赞 | 65 |
VIP | 231 |
好人卡 | 2 |
积分 | 19 |
经验 | 35171 |
最后登录 | 2024-9-15 |
在线时间 | 1554 小时 |
Lv3.寻梦者
- 梦石
- 0
- 星屑
- 1912
- 在线时间
- 1554 小时
- 注册时间
- 2013-4-13
- 帖子
- 917
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
本帖最后由 沉滞的剑 于 2019-8-19 22:42 编辑
逐渐进入一些表层的部分
于是以后会陆陆续续加入一点练手的部分
希望大家能够觉得有所帮助
====================
第七章 标题什么的以后就不起了, 都多大了, 还中二
继续讲Window相关的东西
Window还是个很底层的类, Window_Base对这个类继续填充功能
Window只是定义了一些属性和基本的生命周期
实际上它并不具备显示的效果
比如它定义了窗口皮肤, 但又没有直接加载皮肤的方法
所以一般我们写Window类的时候不会继承Window
那我们先来看看Window_Base
- Window_Base.prototype = Object.create(Window.prototype);
- Window_Base.prototype.constructor = Window_Base;
- Window_Base.prototype.initialize = function(x, y, width, height) {
- Window.prototype.initialize.call(this);
- this.loadWindowskin(); // 加载窗口皮肤
- this.move(x, y, width, height); // 设定窗口位置和大小
- this.updatePadding(); // 初始化内边距
- this.updateBackOpacity(); // 初始化可见度
- this.updateTone(); // 初始化色调
- this.createContents(); // 重绘内容
- this._opening = false; // 设置窗口正在打开的状态为false
- this._closing = false; // 设置窗口正在关闭的状态为false
- this._dimmerSprite = null; // 遮挡背景色
- };
复制代码
Window_Base提供了一些列简单到复杂的属性计算
比如contentsWidth, contentsHeight, fittingHeight等
窗口是遵循Box模型
所以内容的宽高都要减去两个padding的宽高
- Window_Base.prototype.contentsWidth = function() {
- return this.width - this.standardPadding() * 2;
- };
- Window_Base.prototype.contentsHeight = function() {
- return this.height - this.standardPadding() * 2;
- };
复制代码
fittingHeight则是文字高度计算, 不过Window_Base并没有定义一个文字区域, 所以这个方法是给其子类使用的
- Window_Base.prototype.fittingHeight = function(numLines) {
- return numLines * this.lineHeight() + this.standardPadding() * 2;
- };
复制代码
当然还有不知道为啥还保留着远古气息的通过点阵图取色的骚操作
看下Window.png右下角那个区域你们就懂了...
- Window_Base.prototype.textColor = function(n) {
- var px = 96 + (n % 8) * 12 + 6;
- var py = 144 + Math.floor(n / 8) * 12 + 6;
- return this.windowskin.getPixel(px, py);
- };
复制代码
还有一些reset字体, 字体大小, 颜色, 边距, 色调, 背景透明度等等重置为常量的方法我就不再赘述了
createContents()就是重绘内容, 之前的内容会被清空
- Window_Base.prototype.createContents = function() {
- this.contents = new Bitmap(this.contentsWidth(), this.contentsHeight());
- this.resetFontSettings();
- };
复制代码
剩下就是关于开启关闭窗口的动画相关的了
先看看周期函数update
- Window_Base.prototype.update = function() {
- Window.prototype.update.call(this);
- this.updateTone(); // 更新色调
- this.updateOpen(); // 更新打开动画
- this.updateClose(); // 更新关闭动画
- this.updateBackgroundDimmer(); // 遮挡背景色
- };
复制代码 '
窗口打开动画的程度通过this.openness来判断0~255
打开状态由this._opening 和 this._closing判断
- Window_Base.prototype.updateOpen = function() {
- if (this._opening) {
- this.openness += 32;
- if (this.isOpen()) {
- this._opening = false;
- }
- }
- };
- Window_Base.prototype.updateClose = function() {
- if (this._closing) {
- this.openness -= 32;
- if (this.isClosed()) {
- this._closing = false;
- }
- }
- };
复制代码
如果在关闭中已经是0了, 则不再关闭
如果在打开中已经是255了则不再打开
我们看一下open和close方法, 也很简单粗暴:
- Window_Base.prototype.open = function() {
- if (!this.isOpen()) {
- this._opening = true;
- }
- this._closing = false;
- };
- Window_Base.prototype.close = function() {
- if (!this.isClosed()) {
- this._closing = true;
- }
- this._opening = false;
- };
复制代码
- Window_Base.prototype.isOpening = function() {
- return this._opening;
- };
- Window_Base.prototype.isClosing = function() {
- return this._closing;
- };
- /**
- * Returns true if the window is completely open (openness == 255).
- *
- * @method isOpen
- */
- Window.prototype.isOpen = function() {
- return this._openness >= 255;
- };
- // 这两个方法是继承于Window方法的
- /**
- * Returns true if the window is completely closed (openness == 0).
- *
- * @method isClosed
- */
- Window.prototype.isClosed = function() {
- return this._openness <= 0;
- };
复制代码
还有几个状态是不需要动画效果的, 所以只有是或者不是两个状态- Window_Base.prototype.show = function() {
- this.visible = true;
- };
- Window_Base.prototype.hide = function() {
- this.visible = false;
- };
- Window_Base.prototype.activate = function() {
- this.active = true;
- };
- Window_Base.prototype.deactivate = function() {
- this.active = false;
- };
复制代码
好了, 现在我们的内容虽然有了, 不过是个空白的
Window_Base提供了几个方法让我们对它进绘制
因为绘制方法实在是太多了, 我就不详解了
而且里面还有很多繁琐的计算, 比如绘制矩形文字区域drawTextEx
就需要计算各种转义符, 计算高度等, 以后还是会用到的, 到时候再说
给大家感受一下, 基本上能画的标准图形在这里都有了
- drawTextEx
- drawText
- drawIcon
- drawFace
- drawCharacter
- drawGauge // 应该是血条之类的计量柱
- drawActorCharacter
- drawActorFace
- drawActorName
- drawActorClass
- drawActorNickname
- drawActorLevel
- drawActorIcons
- drawCurrentAndMax // 数值显示 比如hp/MaxHp
- drawActorHp
- drawActorMp
- drawActorTp
- drawActorSimpleStatus
- drawItemName
- drawCurrencyValue
复制代码 还有几个零散的方法:
canvasToLocalX/Y是转换canvas的绝对坐标到本地坐标
reserveFaceImages()是将所有队伍头像反转显示
- Window_Base.prototype.canvasToLocalX = function(x) {
- var node = this;
- while (node) {
- x -= node.x;
- node = node.parent;
- }
- return x;
- };
- Window_Base.prototype.canvasToLocalY = function(y) {
- var node = this;
- while (node) {
- y -= node.y;
- node = node.parent;
- }
- return y;
- };
- Window_Base.prototype.reserveFaceImages = function() {
- $gameParty.members().forEach(function(actor) {
- ImageManager.reserveFace(actor.faceName());
- }, this);
- };
复制代码
===================
练手时间:
我们来自己定义一个从Window_Base派生的窗口吧假设我们想要弄一个200*200大小的窗口
- class Window_Test extends Window_Base {
- constructor(x, y) {
- super(x, y, 200, 200)
- }
- }
复制代码
嗯 我们采取ES5的class写法, 而不是官方Object.create, 都9012了好么!
我们想要一开始的就重绘这个窗口, 显示一段文字
那我们就创建一个refresh方法并在构造器里调用它- class Window_Test extends Window_Base {
- constructor(x, y) {
- super(x, y, 200, 200)
- this.refresh = () => {
- this.drawText('Hello World', 0, 0, 200)
- }
- this.refresh()
- }
- }
复制代码
我们先了解一下drawText, 这个其实是一个Bitmap对象的方法
- Window_Base.prototype.drawText = function(text, x, y, maxWidth, align) {
- this.contents.drawText(text, x, y, maxWidth, this.lineHeight(), align);
- };
- Bitmap.prototype.drawText = function(text, x, y, maxWidth, lineHeight, align) {
- // Note: Firefox has a bug with textBaseline: Bug 737852
- // So we use 'alphabetic' here.
- if (text !== undefined) {
- var tx = x;
- var ty = y + lineHeight - (lineHeight - this.fontSize * 0.7) / 2;
- var context = this._context;
- var alpha = context.globalAlpha;
- maxWidth = maxWidth || 0xffffffff;
- if (align === 'center') {
- tx += maxWidth / 2;
- }
- if (align === 'right') {
- tx += maxWidth;
- }
- context.save();
- context.font = this._makeFontNameText();
- context.textAlign = align;
- context.textBaseline = 'alphabetic';
- context.globalAlpha = 1;
- this._drawTextOutline(text, tx, ty, maxWidth);
- context.globalAlpha = alpha;
- this._drawTextBody(text, tx, ty, maxWidth);
- context.restore();
- this._setDirty();
- }
- };
复制代码
可以看出我们可以选择位置, 最大宽度, 和对齐方式, 对齐方式'right' 和 'center'还有个默认的左对齐
这里就用默认的左对齐就好了
我把成员方法的定义写在了构造函数里
原因是nw版本不支持在class里直接写箭头函数...怨念
进入游戏, 打开F12控制台
我们把类的定义执行一遍, 再输入
- const myWin = new Window_Test()
- SceneManager._scene.addWindow(myWin)
复制代码 一个带有文字的对话框就出现了
不过让我们再进一步, 我们希望这个窗口在加载的时候要有一个打开动画
- class Window_Test extends Window_Base {
- constructor(x, y) {
- super(x, y, 200, 200)
- this.openness = 0
- this.open()
- this.refresh = () => {
- this.drawText('Hello World', 0, 0, 200)
- }
- this.refresh()
- }
- }
复制代码
这样一个创建时播放打开动画的窗口就创造完了
但是这些只是一个窗口最基本的展示能力, 为了有更多的交互行为
还会有更高级的Window类拓展了Window_Base的功能
我们很快就会讲到更多的Window类, 下次再见~
|
评分
-
查看全部评分
|