RPG Maker MV 踩坑九 场景和窗口问题

RPG Maker MV 踩坑九 场景和窗口问题

启言

RPG Maker MV中使用的语言是JavaScript作为脚本语言,在HTML中的Canvas画布上进行绘制图像及交互行为
在游戏中能够感知到的最大的容器是场景,往下就是各种用于菜单操作的窗口,再往下可以看做是容器的精灵,之后在精灵中添加位图然后绘制出来。

场景

场景是游戏中的环境、建筑、机械、道具等。游戏场景通常可以理解为根据企划的要求还原出游戏中的建筑物、树木、天空、道路等可用元素(包含武器道具与NPC等)。
在RPG Maker MV的游戏中可以看到的装着窗口的容器就是场景,地图主菜单状态装备交易标题等等,这些都是一个个的场景,场景中有人物移动、有效果变化,有窗口等等。
可以说游戏中的所有看得到的,听得到的一切元素构成了场景;只不过现在我们说的场景只是装着构成场景的各元素的一个盒子。

窗口

在游戏中窗口就是可被绘制出来的一个矩形区域,这个区域有着背景边框,及内容,内容中有些是直接进行显示的,有些是可进行交互的。
WindowLayer 包含游戏的窗口层,简单解释就是游戏中各个窗口基本都是放在这里面的。

场景和窗口问题

通过之前各篇的内容,可以看到我在开发的代码中有些时候窗口并不是放在窗口层中的,而是直接放在场景中的,这是为什么呢?
窗口在窗口层中时会发现这样的一个怪象,窗口和窗口之间互相遮挡时会显示场景中的背景信息,而将精灵放入其中时会发现所有的精灵都在最顶层,即覆盖遮挡了所有的窗口,这也是之前绘制做战斗物品、法术窗口时出现的问题;由于代码功底较少,现在调试着代码比较麻烦,但也可以推测出是窗口层进行渲染时进行的操作。

WindowLayer.prototype.renderCanvas = function(renderer) {
    if (!this.visible || !this.renderable) {
        return;
    }
    if (!this._tempCanvas) {
        this._tempCanvas = document.createElement('canvas');
    }
    this._tempCanvas.width = Graphics.width;
    this._tempCanvas.height = Graphics.height;
    var realCanvasContext = renderer.context;
    var context = this._tempCanvas.getContext('2d');
    context.save();
    context.clearRect(0, 0, Graphics.width, Graphics.height);
    context.beginPath();
    context.rect(this.x, this.y, this.width, this.height);
    context.closePath();
    context.clip();
    renderer.context = context;
    for (var i = 0; i < this.children.length; i++) {
        var child = this.children[i];
        if (child._isWindow && child.visible && child.openness > 0) {
            this._canvasClearWindowRect(renderer, child);
            context.save();
            child.renderCanvas(renderer);
            context.restore();
        }
    }
    context.restore();
    renderer.context = realCanvasContext;
    renderer.context.setTransform(1, 0, 0, 1, 0, 0);
    renderer.context.globalCompositeOperation = 'source-over';
    renderer.context.globalAlpha = 1;
    renderer.context.drawImage(this._tempCanvas, 0, 0);
    for (var j = 0; j < this.children.length; j++) {
        if (!this.children[j]._isWindow) {
            this.children[j].renderCanvas(renderer);
        }
    }
};
WindowLayer.prototype.renderWebGL = function(renderer) {
    if (!this.visible || !this.renderable) {
        return;
    }
    if (this.children.length==0) {
        return;
    }
    renderer.flush();
    this.filterArea.copy(this);
    renderer.filterManager.pushFilter(this, this.filters);
    renderer.currentRenderer.start();
    var shift = new PIXI.Point();
    var rt = renderer._activeRenderTarget;
    var projectionMatrix = rt.projectionMatrix;
    shift.x = Math.round((projectionMatrix.tx + 1) / 2 * rt.sourceFrame.width);
    shift.y = Math.round((projectionMatrix.ty + 1) / 2 * rt.sourceFrame.height);
    for (var i = 0; i < this.children.length; i++) {
        var child = this.children[i];
        if (child._isWindow && child.visible && child.openness > 0) {
            this._maskWindow(child, shift);
            renderer.maskManager.pushScissorMask(this, this._windowMask);
            renderer.clear();
            renderer.maskManager.popScissorMask();
            renderer.currentRenderer.start();
            child.renderWebGL(renderer);
            renderer.currentRenderer.flush();
        }
    }
    renderer.flush();
    renderer.filterManager.popFilter();
    renderer.maskManager.popScissorMask();
    for (var j = 0; j < this.children.length; j++) {
        if (!this.children[j]._isWindow) {
            this.children[j].renderWebGL(renderer);
        }
    }
};

通过该渲染代码渲染了窗口层,后期看能否详细解读下。
场景中直接加入窗口就发现不会出现这样的情况,个人看法是场景的渲染将直接放入的窗口当成了类似图片一样的渲染,这样的重叠遮挡就不会暴露后面的背景了。
在这里插入图片描述
其实这用的话,之前遇到的指令问题也可以迎刃而解了!!!
不过场景与场景之前的问题也是一个头疼的问题,比如返回上一个场景,并显示之前打开的窗口,就发现了问题了!所以需要场景管理器来从中间进行协调管理。

战斗场景

战斗的场景刚进入时会出现敌人出现的消息弹窗,这和原来的游戏方式不搭配,毕竟刚进去时弹出合理,但从其他的场景返回战斗场景时就显得非常突兀了,这时的解决办法是在战斗管理器中开始战斗时注释掉对应的方法调用,但又会出现一个问题,默认的调用使用时会默认显示战斗的角色信息,及窗口,这样就是非常大的BUG,现在找到方法处理了后,又出现了一个战斗操作及人物状态的显示太慢,又是得优化的地方!!!
从其他场景返回战斗场景时可能人物的数据和敌人的数据会发生重置(还没有做到这里),这也是后面得处理的问题。

  • 28
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
【实例教程1】怎样编写一个插件? 1. 插件的注释与定义参数 2. 读取插件参数 3. 插件指令的实现 【实例教程2】制作一个启动画面 1. 从哪里开始? 2. 创建启动画面的场景类 【实例教程3】玩转菜单初级篇 1. 给各个菜单界面添加背景 2. 让背景滚动起来 3. 在主菜单界面增加自定义菜单:改名 4. 在主菜单界面移除菜单命令 5. 在主菜单界面增加一个自定义窗口 【实例教程4】玩转标题画面 1. 美化游戏标题 2. 让背景动起来 3. 自定义标题菜单 4. 美化菜单 【实例教程5】制作小游戏:坦克大战(上) 1. 游戏结构及流程介绍 2. 相关素材资源的下载和使用 3. 基础知识:音效的播放 4. 基础知识:精灵表的切帧 5. 基础知识:使用MV中的动画 6. Scene_TankWarTitle类解析 7. Sprite_Bullet类解析 8. Sprite_Explode类解析 9. Sprite_Tank类解析 10. Sprite_Enemy类解析 11. Scene_TankWar类解析 12. Scene_TankWarGameOver类解析 【实例教程6】存档的加密解密与保护 1. 找出MV存档和读档的方式 2. 制作MV存档的修改器 3. 如何保护存档? 4. 制作一个存档保护插件 【实例教程7】制作一个传送插件 1. 传送插件的主要功能 2. 将自定义数据保存到存档中 3. meta数据的使用 4. 使用地图备注登记传送点 5. 在插件中解析并记录传送点 6. 使用地图备注登记多个传送点并在插件中记录 7. 制作传送点选取窗口显示传送点数据 8. 将物品或技能标记为传送物品、传送技能 9. 显示传送动画实现传送功能 10. 禁止使用传送道具或传送技能 11. 实现插件命令
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值