zoukankan      html  css  js  c++  java
  • 如何制作一款HTML5 RPG游戏引擎——第三篇,利用幕布切换场景

    开言:

    在RPG游戏中,如果有地图切换的地方,通常就会使用幕布效果。所谓的幕布其实就是将两个矩形合拢,直到把屏幕遮住,然后再展开直到两个矩形全部移出屏幕。

    为了大家做游戏方便,于是我给这个引擎加了这么一个类。

    本系列文章目录:

    如何制作一款HTML5 RPG游戏引擎——第一篇,地图类的实现

    http://blog.csdn.net/yorhomwang/article/details/8892305

    如何制作一款HTML5 RPG游戏引擎——第二篇,烟雨+飞雪效果

    http://blog.csdn.net/yorhomwang/article/details/8915020

    该引擎是基于lufylegend开发的,学习时请先了解lufylegend。

    官方网站地址:http://lufylegend.com/lufylegend

    API地址:http://lufylegend.com/lufylegend/api

    今天我们先看实现后的代码:

    var curtain = new LCurtainSample3();
    addChild(curtain);

    就两行,已经达到最简单了。那么接下来就来看看是如何实现它的。

    由于有很多种幕布效果,因此我只为大家实现常用的3种作为sample,大家可以借鉴一下,写出更美观的幕布。

    1,LCurtainSample1

    这个是一个基础幕布,效果是左右合拢。

    看看构造器中的代码:

    function LCurtainSample1(speed,onClosing,onComplete){
        var s = this;
        base(s,LSprite,[]);
        if(!speed)speed = LStage.width/100;
        if(!onClosing){
            s.onClosing = function(){};
        }else{
            s.onClosing = onClosing;
        }    
        if(!onComplete){
            s.onComplete = function(){};
        }else{
            s.onComplete = onComplete;
        }
        s.mode = "close";
        s.width1 = 0;
        s.width2 = 0;
        s.isDoClosing = false;
        s.speed = speed;
        s.addEventListener(LEvent.ENTER_FRAME,s.onshow);
    }

    这个类是继承自LSprite类,有三个参数,分别是:幕布合拢/展开的速度,幕布合拢后调用此函数,幕布展开后调用此函数。

    mode 属性顾名思义,它是用来表示接下来的工作的。当为close时说明要合拢。
    我们在其中定义两个属性:width1,width2,它们分别表示两块幕布显示的宽度,通过调节宽度来实现合拢。另外定义了isDoClosing来判断是否已经合拢。用speed来保存幕布移动速度,方便以后使用。

    然后我们给自身加一个时间轴事件,在时间轴事件中调用onshow方法绘画幕布。

    onshow中的完整代码:

    LCurtainSample1.prototype.onshow = function(s){
        s.graphics.clear();
        s.graphics.drawRect(1,"black",[0,0,s.width1,LStage.height],true,"black");
        s.graphics.drawRect(1,"black",[LStage.width-s.width2,0,s.width2,LStage.height],true,"black");
        if(s.width1 >= LStage.width/2){
            s.mode = "open";
            if(s.isDoClosing == false){
                s.onClosing();
                s.isDoClosing = true;
            }
        }
        if(s.mode == "close"){
            s.width1 += s.speed;
            s.width2 += s.speed;
        }else if(s.mode == "open"){
            s.width1 -= s.speed;
            s.width2 -= s.speed;
            if(s.width1 < 0){
                s.mode = "stop";
            }
        }else if(s.mode == "stop"){
            s.graphics.clear();
            s.removeEventListener(LEvent.ENTER_FRAME,s.onshow);
            s.onComplete();
        }
    }

    首先我们将我们的绘图区清空,然后画一个高为画布的高度,宽为width1的矩型。由于它是从x坐标为0,y坐标为0的地方画起,所以不需要任何处理。

    接着用同样的办法画出高为画布的高度,宽为width2的矩形。但是由于是在屏幕最右边开始画,所以我们就得计算出它的x坐标,然后再来画。计算方法很简单,就是用屏幕宽度减去width2的长度就可以得到画笔起始的x坐标。

    接着我们判断第一块幕布是否已经到达中点,如果是,就将mode设为"open",表示接下来要open,判断isDoClosing是否为false,是则设为true,并且调用合拢时调用的函数。

    接下来我们为了使幕布增长或缩短,我用到了判断mode的值的方法来实现。当为close时,就将宽度变大,当为open时就变小。如果移动完毕就将mode设置为stop,然后接着判断如果为stop就清屏,然后移除时间轴事件,达到停止的效果。效果如下:

    虽然单独看有点丑,但是如果放在游戏中还是很不错的

    2,LCurtainSample2

    LCurtainSample2和LCurtainSample1差不多,只是一个是横着的,一个竖着的。

    直接上代码:

    /**
    *LCurtainSample2.js
    */
    function LCurtainSample2(speed,onClosing,onComplete){
        var s = this;
        base(s,LSprite,[]);
        if(!speed)speed = LStage.height/100;
        if(!onClosing){
            s.onClosing = function(){};
        }else{
            s.onClosing = onClosing;
        }    
        if(!onComplete){
            s.onComplete = function(){};
        }else{
            s.onComplete = onComplete;
        }
        s.mode = "close";
        s.height1 = 0;
        s.height2 = 0;
        s.isDoClosing = false;
        s.speed = speed;
        s.addEventListener(LEvent.ENTER_FRAME,s.onshow);
    }
    LCurtainSample2.prototype.onshow = function(s){
        s.graphics.clear();
        s.graphics.drawRect(1,"black",[0,0,LStage.width,s.height1],true,"black");
        s.graphics.drawRect(1,"black",[0,LStage.height-s.height2,LStage.width,s.height2],true,"black");
        if(s.height1 >= LStage.height/2){
            s.mode = "open";
            if(s.isDoClosing == false){
                s.onClosing();
                s.isDoClosing = true;
            }
        }
        if(s.mode == "close"){
            s.height1 += s.speed;
            s.height2 += s.speed;
        }else if(s.mode == "open"){
            s.height1 -= s.speed;
            s.height2 -= s.speed;
            if(s.height1 < 0){
                s.mode = "stop";
            }
        }else if(s.mode == "stop"){
            s.graphics.clear();
            s.removeEventListener(LEvent.ENTER_FRAME,s.onshow);
            s.onComplete();
        }
    }

    效果如下:

    3,LCurtainSample3

    LCurtainSample3是LCurtainSample1和LCurtainSample2的结合体,效果就是一起合拢展开。实现方法差不多,大家可以看看:

    /**
    *LCurtainSample3.js
    */
    function LCurtainSample3(speed,onClosing,onComplete){
        var s = this;
        base(s,LSprite,[]);
        if(!speed)speed = LStage.width/100;
        if(!onClosing){
            s.onClosing = function(){};
        }else{
            s.onClosing = onClosing;
        }    
        if(!onComplete){
            s.onComplete = function(){};
        }else{
            s.onComplete = onComplete;
        }
        s.mode = "close";
        s.height1 = 0;
        s.height2 = 0;
        s.width1 = 0;
        s.width2 = 0;
        s.isDoClosing = false;
        s.speed = speed;
        s.addEventListener(LEvent.ENTER_FRAME,s.onshow);
    }
    LCurtainSample3.prototype.onshow = function(s){
        s.graphics.clear();
        s.graphics.drawRect(1,"black",[0,0,LStage.width,s.height1],true,"black");
        s.graphics.drawRect(1,"black",[0,LStage.height-s.height2,LStage.width,s.height2],true,"black");
        s.graphics.drawRect(1,"black",[0,0,s.width1,LStage.height],true,"black");
        s.graphics.drawRect(1,"black",[LStage.width-s.width2,0,s.width2,LStage.height],true,"black");
        if(s.height1 >= LStage.height/2 ){
            s.mode = "open";
            if(s.isDoClosing == false){
                s.onClosing();
                s.isDoClosing = true;
            }
        }
        if(s.mode == "close"){
            s.height1 += s.speed;
            s.height2 += s.speed;
            s.width1 += s.speed;
            s.width2 += s.speed;
        }else if(s.mode == "open"){
            s.height1 -= s.speed;
            s.height2 -= s.speed;
            s.width1 -= s.speed;
            s.width2 -= s.speed;
            if(s.height1 < 0){
                s.mode = "stop";
            }
        }else if(s.mode == "stop"){
            s.graphics.clear();
            s.removeEventListener(LEvent.ENTER_FRAME,s.onshow);
            s.onComplete();
        }
    }

    效果如下:

    4,切换场景

    上面我们实现了幕布类,接下来就要实战一下了。

    首先我们找几张图片:

    还有一张

    接着就用到了我们的幕布类实现切换场景,代码如下:

    <!DOCTYPE html>
    <html lang="en">
        <head>
        <meta charset="utf-8" />
        <title>Curtain幕布</title>
        <script type="text/javascript" src="./js/lufylegend-1.7.6.min.js"></script>
        <script type="text/javascript" src="./js/lufylegendrpg-1.0.0.js"></script> 
        <script>
        init(30,"legend",600,400,main);
        var backindex = 1;
        var loadlist = [
            {name:"back1",path:"./back1.jpg"},
            {name:"back2",path:"./back2.jpg"}
        ];
        var datalist = [];
        LRPGStage.setShortcuts(true);
        LGlobal.setDebug(true);
        var backLayer;
        var loadingLayer;
        function main(){
            LEvent.addEventListener(LGlobal.window,LKeyboardEvent.KEY_DOWN,onkeydown);
            loadingLayer = new LoadingSample1(); 
            addChild(loadingLayer); 
            LLoadManage.load( 
                loadlist, 
                function(progress){ 
                    loadingLayer.setProgress(progress); 
                }, 
                gameInit 
            ); 
        }
        function gameInit(result){
            datalist = result;
            backLayer = new LSprite();
            addChild(backLayer);
            addImg();
        }
        function addImg(){
            backLayer.removeAllChild();
            var bitmapdata = new LBitmapData(datalist["back"+backindex]);
            var bitmap = new LBitmap(bitmapdata);
            backLayer.addChild(bitmap);
        }
        function onkeydown(){
            var curtain = new LCurtainSample3(20,function(){
                if(backindex == 1){
                    backindex = 2;
                }else if(backindex == 2){
                    backindex = 1;
                }
                addImg();
            },function(){
                trace("已经切换为back"+backindex);
            });
            addChild(curtain);
        }
        </script>
        </head>
        <body>
                <div id="legend"></div>
        </body>
    </html>

    截图如下:

    合拢时



    展开完成后

    嘻嘻~不错吧

    5,源代码

    本次开发代码虽然比较多,但都有些类似,放在下面,大家可以拿下去测试:

    /**
    *LCurtainSample1.js
    */
    function LCurtainSample1(speed,onClosing,onComplete){
        var s = this;
        base(s,LSprite,[]);
        if(!speed)speed = LStage.width/100;
        if(!onClosing){
            s.onClosing = function(){};
        }else{
            s.onClosing = onClosing;
        }    
        if(!onComplete){
            s.onComplete = function(){};
        }else{
            s.onComplete = onComplete;
        }
        s.mode = "close";
        s.width1 = 0;
        s.width2 = 0;
        s.isDoClosing = false;
        s.speed = speed;
        s.addEventListener(LEvent.ENTER_FRAME,s.onshow);
    }
    LCurtainSample1.prototype.onshow = function(s){
        s.graphics.clear();
        s.graphics.drawRect(1,"black",[0,0,s.width1,LStage.height],true,"black");
        s.graphics.drawRect(1,"black",[LStage.width-s.width2,0,s.width2,LStage.height],true,"black");
        if(s.width1 >= LStage.width/2){
            s.mode = "open";
            if(s.isDoClosing == false){
                s.onClosing();
                s.isDoClosing = true;
            }
        }
        if(s.mode == "close"){
            s.width1 += s.speed;
            s.width2 += s.speed;
        }else if(s.mode == "open"){
            s.width1 -= s.speed;
            s.width2 -= s.speed;
            if(s.width1 < 0){
                s.mode = "stop";
            }
        }else if(s.mode == "stop"){
            s.graphics.clear();
            s.removeEventListener(LEvent.ENTER_FRAME,s.onshow);
            s.onComplete();
        }
    }
    /**
    *LCurtainSample2.js
    */
    function LCurtainSample2(speed,onClosing,onComplete){
        var s = this;
        base(s,LSprite,[]);
        if(!speed)speed = LStage.height/100;
        if(!onClosing){
            s.onClosing = function(){};
        }else{
            s.onClosing = onClosing;
        }    
        if(!onComplete){
            s.onComplete = function(){};
        }else{
            s.onComplete = onComplete;
        }
        s.mode = "close";
        s.height1 = 0;
        s.height2 = 0;
        s.isDoClosing = false;
        s.speed = speed;
        s.addEventListener(LEvent.ENTER_FRAME,s.onshow);
    }
    LCurtainSample2.prototype.onshow = function(s){
        s.graphics.clear();
        s.graphics.drawRect(1,"black",[0,0,LStage.width,s.height1],true,"black");
        s.graphics.drawRect(1,"black",[0,LStage.height-s.height2,LStage.width,s.height2],true,"black");
        if(s.height1 >= LStage.height/2){
            s.mode = "open";
            if(s.isDoClosing == false){
                s.onClosing();
                s.isDoClosing = true;
            }
        }
        if(s.mode == "close"){
            s.height1 += s.speed;
            s.height2 += s.speed;
        }else if(s.mode == "open"){
            s.height1 -= s.speed;
            s.height2 -= s.speed;
            if(s.height1 < 0){
                s.mode = "stop";
            }
        }else if(s.mode == "stop"){
            s.graphics.clear();
            s.removeEventListener(LEvent.ENTER_FRAME,s.onshow);
            s.onComplete();
        }
    }
    /**
    *LCurtainSample3.js
    */
    function LCurtainSample3(speed,onClosing,onComplete){
        var s = this;
        base(s,LSprite,[]);
        if(!speed)speed = LStage.width/100;
        if(!onClosing){
            s.onClosing = function(){};
        }else{
            s.onClosing = onClosing;
        }    
        if(!onComplete){
            s.onComplete = function(){};
        }else{
            s.onComplete = onComplete;
        }
        s.mode = "close";
        s.height1 = 0;
        s.height2 = 0;
        s.width1 = 0;
        s.width2 = 0;
        s.isDoClosing = false;
        s.speed = speed;
        s.addEventListener(LEvent.ENTER_FRAME,s.onshow);
    }
    LCurtainSample3.prototype.onshow = function(s){
        s.graphics.clear();
        s.graphics.drawRect(1,"black",[0,0,LStage.width,s.height1],true,"black");
        s.graphics.drawRect(1,"black",[0,LStage.height-s.height2,LStage.width,s.height2],true,"black");
        s.graphics.drawRect(1,"black",[0,0,s.width1,LStage.height],true,"black");
        s.graphics.drawRect(1,"black",[LStage.width-s.width2,0,s.width2,LStage.height],true,"black");
        if(s.height1 >= LStage.height/2 ){
            s.mode = "open";
            if(s.isDoClosing == false){
                s.onClosing();
                s.isDoClosing = true;
            }
        }
        if(s.mode == "close"){
            s.height1 += s.speed;
            s.height2 += s.speed;
            s.width1 += s.speed;
            s.width2 += s.speed;
        }else if(s.mode == "open"){
            s.height1 -= s.speed;
            s.height2 -= s.speed;
            s.width1 -= s.speed;
            s.width2 -= s.speed;
            if(s.height1 < 0){
                s.mode = "stop";
            }
        }else if(s.mode == "stop"){
            s.graphics.clear();
            s.removeEventListener(LEvent.ENTER_FRAME,s.onshow);
            s.onComplete();
        }
    }

    这次讲解就到这里,下一次我们就来实现必不可少的对话类,不容错过哦!!!

  • 相关阅读:
    学习MongoDB(Troubleshoot Replica Sets) 集群排除故障
    MyBatis 相同事物查询缓存问题
    Spring事物源码
    Spring Session Redis
    Tomcat配置多个域名绑定到不同项目
    Shiro相关文章资料
    一网打尽:Java 程序员必须了解的计算机底层知识!
    Chrome 80 调教篇
    谭浩强《C++程序设计》
    HTTP/HTTPS协议
  • 原文地址:https://www.cnblogs.com/jiangxiaobo/p/6004992.html
Copyright © 2011-2022 走看看