• 如何实现一个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

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

    [javascript] view plaincopy
     
    1. var curtain = new LCurtainSample3();  
    2. addChild(curtain);  


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

    因为有非常多种幕布效果,因此我仅仅为大家实现常常使用的3种作为sample,大家能够借鉴一下,写出更美观的幕布。

    1,LCurtainSample1

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

    看看构造器中的代码:

    [javascript] view plaincopy
     
    1. function LCurtainSample1(speed,onClosing,onComplete){  
    2.     var s = this;  
    3.     base(s,LSprite,[]);  
    4.     if(!speed)speed = LStage.width/100;  
    5.     if(!onClosing){  
    6.         s.onClosing = function(){};  
    7.     }else{  
    8.         s.onClosing = onClosing;  
    9.     }     
    10.     if(!onComplete){  
    11.         s.onComplete = function(){};  
    12.     }else{  
    13.         s.onComplete = onComplete;  
    14.     }  
    15.     s.mode = "close";  
    16.     s.width1 = 0;  
    17.     s.width2 = 0;  
    18.     s.isDoClosing = false;  
    19.     s.speed = speed;  
    20.     s.addEventListener(LEvent.ENTER_FRAME,s.onshow);  
    21. }  

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

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

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

    onshow中的完整代码:

    [javascript] view plaincopy
     
    1. LCurtainSample1.prototype.onshow = function(s){  
    2.     s.graphics.clear();  
    3.     s.graphics.drawRect(1,"black",[0,0,s.width1,LStage.height],true,"black");  
    4.     s.graphics.drawRect(1,"black",[LStage.width-s.width2,0,s.width2,LStage.height],true,"black");  
    5.     if(s.width1 >= LStage.width/2){  
    6.         s.mode = "open";  
    7.         if(s.isDoClosing == false){  
    8.             s.onClosing();  
    9.             s.isDoClosing = true;  
    10.         }  
    11.     }  
    12.     if(s.mode == "close"){  
    13.         s.width1 += s.speed;  
    14.         s.width2 += s.speed;  
    15.     }else if(s.mode == "open"){  
    16.         s.width1 -= s.speed;  
    17.         s.width2 -= s.speed;  
    18.         if(s.width1 < 0){  
    19.             s.mode = "stop";  
    20.         }  
    21.     }else if(s.mode == "stop"){  
    22.         s.graphics.clear();  
    23.         s.removeEventListener(LEvent.ENTER_FRAME,s.onshow);  
    24.         s.onComplete();  
    25.     }  
    26. }  

    首先我们将我们的画图区清空,然后画一个高为画布的高度,宽为width1的矩型。因为它是从x坐标为0,y坐标为0的地方画起,所以不须要不论什么处理。

    接着用相同的办法画出高为画布的高度,宽为width2的矩形。可是因为是在屏幕最右边開始画,所以我们就得计算出它的x坐标,然后再来画。计算方法非常easy,就是用屏幕宽度减去width2的长度就能够得到画笔起始的x坐标。

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

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

    尽管单独看有点丑,可是假设放在游戏中还是非常不错的

    2,LCurtainSample2

    LCurtainSample2和LCurtainSample1几乎相同,仅仅是一个是横着的,一个竖着的。

    直接上代码:

    [javascript] view plaincopy
     
    1. /** 
    2. *LCurtainSample2.js 
    3. */  
    4. function LCurtainSample2(speed,onClosing,onComplete){  
    5.     var s = this;  
    6.     base(s,LSprite,[]);  
    7.     if(!speed)speed = LStage.height/100;  
    8.     if(!onClosing){  
    9.         s.onClosing = function(){};  
    10.     }else{  
    11.         s.onClosing = onClosing;  
    12.     }     
    13.     if(!onComplete){  
    14.         s.onComplete = function(){};  
    15.     }else{  
    16.         s.onComplete = onComplete;  
    17.     }  
    18.     s.mode = "close";  
    19.     s.height1 = 0;  
    20.     s.height2 = 0;  
    21.     s.isDoClosing = false;  
    22.     s.speed = speed;  
    23.     s.addEventListener(LEvent.ENTER_FRAME,s.onshow);  
    24. }  
    25. LCurtainSample2.prototype.onshow = function(s){  
    26.     s.graphics.clear();  
    27.     s.graphics.drawRect(1,"black",[0,0,LStage.width,s.height1],true,"black");  
    28.     s.graphics.drawRect(1,"black",[0,LStage.height-s.height2,LStage.width,s.height2],true,"black");  
    29.     if(s.height1 >= LStage.height/2){  
    30.         s.mode = "open";  
    31.         if(s.isDoClosing == false){  
    32.             s.onClosing();  
    33.             s.isDoClosing = true;  
    34.         }  
    35.     }  
    36.     if(s.mode == "close"){  
    37.         s.height1 += s.speed;  
    38.         s.height2 += s.speed;  
    39.     }else if(s.mode == "open"){  
    40.         s.height1 -= s.speed;  
    41.         s.height2 -= s.speed;  
    42.         if(s.height1 < 0){  
    43.             s.mode = "stop";  
    44.         }  
    45.     }else if(s.mode == "stop"){  
    46.         s.graphics.clear();  
    47.         s.removeEventListener(LEvent.ENTER_FRAME,s.onshow);  
    48.         s.onComplete();  
    49.     }  
    50. }  

    效果例如以下:

    3,LCurtainSample3

    LCurtainSample3是LCurtainSample1和LCurtainSample2的结合体,效果就是一起合拢展开。实现方法几乎相同,大家能够看看:

    [javascript] view plaincopy
     
    1. /** 
    2. *LCurtainSample3.js 
    3. */  
    4. function LCurtainSample3(speed,onClosing,onComplete){  
    5.     var s = this;  
    6.     base(s,LSprite,[]);  
    7.     if(!speed)speed = LStage.width/100;  
    8.     if(!onClosing){  
    9.         s.onClosing = function(){};  
    10.     }else{  
    11.         s.onClosing = onClosing;  
    12.     }     
    13.     if(!onComplete){  
    14.         s.onComplete = function(){};  
    15.     }else{  
    16.         s.onComplete = onComplete;  
    17.     }  
    18.     s.mode = "close";  
    19.     s.height1 = 0;  
    20.     s.height2 = 0;  
    21.     s.width1 = 0;  
    22.     s.width2 = 0;  
    23.     s.isDoClosing = false;  
    24.     s.speed = speed;  
    25.     s.addEventListener(LEvent.ENTER_FRAME,s.onshow);  
    26. }  
    27. LCurtainSample3.prototype.onshow = function(s){  
    28.     s.graphics.clear();  
    29.     s.graphics.drawRect(1,"black",[0,0,LStage.width,s.height1],true,"black");  
    30.     s.graphics.drawRect(1,"black",[0,LStage.height-s.height2,LStage.width,s.height2],true,"black");  
    31.     s.graphics.drawRect(1,"black",[0,0,s.width1,LStage.height],true,"black");  
    32.     s.graphics.drawRect(1,"black",[LStage.width-s.width2,0,s.width2,LStage.height],true,"black");  
    33.     if(s.height1 >= LStage.height/2 ){  
    34.         s.mode = "open";  
    35.         if(s.isDoClosing == false){  
    36.             s.onClosing();  
    37.             s.isDoClosing = true;  
    38.         }  
    39.     }  
    40.     if(s.mode == "close"){  
    41.         s.height1 += s.speed;  
    42.         s.height2 += s.speed;  
    43.         s.width1 += s.speed;  
    44.         s.width2 += s.speed;  
    45.     }else if(s.mode == "open"){  
    46.         s.height1 -= s.speed;  
    47.         s.height2 -= s.speed;  
    48.         s.width1 -= s.speed;  
    49.         s.width2 -= s.speed;  
    50.         if(s.height1 < 0){  
    51.             s.mode = "stop";  
    52.         }  
    53.     }else if(s.mode == "stop"){  
    54.         s.graphics.clear();  
    55.         s.removeEventListener(LEvent.ENTER_FRAME,s.onshow);  
    56.         s.onComplete();  
    57.     }  
    58. }  

    效果例如以下:

    4,切换场景

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

    首先我们找几张图片:

    另一张

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

    [javascript] view plaincopy
     
    1. <!DOCTYPE html>  
    2. <html lang="en">  
    3.     <head>  
    4.     <meta charset="utf-8" />  
    5.     <title>Curtain幕布</title>  
    6.     <script type="text/javascript" src="./js/lufylegend-1.7.6.min.js"></script>  
    7.     <script type="text/javascript" src="./js/lufylegendrpg-1.0.0.js"></script>   
    8.     <script>  
    9.     init(30,"legend",600,400,main);  
    10.     var backindex = 1;  
    11.     var loadlist = [  
    12.         {name:"back1",path:"./back1.jpg"},  
    13.         {name:"back2",path:"./back2.jpg"}  
    14.     ];  
    15.     var datalist = [];  
    16.     LRPGStage.setShortcuts(true);  
    17.     LGlobal.setDebug(true);  
    18.     var backLayer;  
    19.     var loadingLayer;  
    20.     function main(){  
    21.         LEvent.addEventListener(LGlobal.window,LKeyboardEvent.KEY_DOWN,onkeydown);  
    22.         loadingLayer = new LoadingSample1();   
    23.         addChild(loadingLayer);   
    24.         LLoadManage.load(   
    25.             loadlist,   
    26.             function(progress){   
    27.                 loadingLayer.setProgress(progress);   
    28.             },   
    29.             gameInit   
    30.         );   
    31.     }  
    32.     function gameInit(result){  
    33.         datalist = result;  
    34.         backLayer = new LSprite();  
    35.         addChild(backLayer);  
    36.         addImg();  
    37.     }  
    38.     function addImg(){  
    39.         backLayer.removeAllChild();  
    40.         var bitmapdata = new LBitmapData(datalist["back"+backindex]);  
    41.         var bitmap = new LBitmap(bitmapdata);  
    42.         backLayer.addChild(bitmap);  
    43.     }  
    44.     function onkeydown(){  
    45.         var curtain = new LCurtainSample3(20,function(){  
    46.             if(backindex == 1){  
    47.                 backindex = 2;  
    48.             }else if(backindex == 2){  
    49.                 backindex = 1;  
    50.             }  
    51.             addImg();  
    52.         },function(){  
    53.             trace("已经切换为back"+backindex);  
    54.         });  
    55.         addChild(curtain);  
    56.     }  
    57.     </script>  
    58.     </head>  
    59.     <body>  
    60.             <div id="legend"></div>  
    61.     </body>  
    62. </html>  

    截图例如以下:

    合拢时



    展开完成后

    嘻嘻~不错吧

    5,源码

    本次开发代码尽管比較多,但都有些相似,放在以下,大家能够拿下去測试:

    [javascript] view plaincopy
     
    1. /** 
    2. *LCurtainSample1.js 
    3. */  
    4. function LCurtainSample1(speed,onClosing,onComplete){  
    5.     var s = this;  
    6.     base(s,LSprite,[]);  
    7.     if(!speed)speed = LStage.width/100;  
    8.     if(!onClosing){  
    9.         s.onClosing = function(){};  
    10.     }else{  
    11.         s.onClosing = onClosing;  
    12.     }     
    13.     if(!onComplete){  
    14.         s.onComplete = function(){};  
    15.     }else{  
    16.         s.onComplete = onComplete;  
    17.     }  
    18.     s.mode = "close";  
    19.     s.width1 = 0;  
    20.     s.width2 = 0;  
    21.     s.isDoClosing = false;  
    22.     s.speed = speed;  
    23.     s.addEventListener(LEvent.ENTER_FRAME,s.onshow);  
    24. }  
    25. LCurtainSample1.prototype.onshow = function(s){  
    26.     s.graphics.clear();  
    27.     s.graphics.drawRect(1,"black",[0,0,s.width1,LStage.height],true,"black");  
    28.     s.graphics.drawRect(1,"black",[LStage.width-s.width2,0,s.width2,LStage.height],true,"black");  
    29.     if(s.width1 >= LStage.width/2){  
    30.         s.mode = "open";  
    31.         if(s.isDoClosing == false){  
    32.             s.onClosing();  
    33.             s.isDoClosing = true;  
    34.         }  
    35.     }  
    36.     if(s.mode == "close"){  
    37.         s.width1 += s.speed;  
    38.         s.width2 += s.speed;  
    39.     }else if(s.mode == "open"){  
    40.         s.width1 -= s.speed;  
    41.         s.width2 -= s.speed;  
    42.         if(s.width1 < 0){  
    43.             s.mode = "stop";  
    44.         }  
    45.     }else if(s.mode == "stop"){  
    46.         s.graphics.clear();  
    47.         s.removeEventListener(LEvent.ENTER_FRAME,s.onshow);  
    48.         s.onComplete();  
    49.     }  
    50. }  
    51. /** 
    52. *LCurtainSample2.js 
    53. */  
    54. function LCurtainSample2(speed,onClosing,onComplete){  
    55.     var s = this;  
    56.     base(s,LSprite,[]);  
    57.     if(!speed)speed = LStage.height/100;  
    58.     if(!onClosing){  
    59.         s.onClosing = function(){};  
    60.     }else{  
    61.         s.onClosing = onClosing;  
    62.     }     
    63.     if(!onComplete){  
    64.         s.onComplete = function(){};  
    65.     }else{  
    66.         s.onComplete = onComplete;  
    67.     }  
    68.     s.mode = "close";  
    69.     s.height1 = 0;  
    70.     s.height2 = 0;  
    71.     s.isDoClosing = false;  
    72.     s.speed = speed;  
    73.     s.addEventListener(LEvent.ENTER_FRAME,s.onshow);  
    74. }  
    75. LCurtainSample2.prototype.onshow = function(s){  
    76.     s.graphics.clear();  
    77.     s.graphics.drawRect(1,"black",[0,0,LStage.width,s.height1],true,"black");  
    78.     s.graphics.drawRect(1,"black",[0,LStage.height-s.height2,LStage.width,s.height2],true,"black");  
    79.     if(s.height1 >= LStage.height/2){  
    80.         s.mode = "open";  
    81.         if(s.isDoClosing == false){  
    82.             s.onClosing();  
    83.             s.isDoClosing = true;  
    84.         }  
    85.     }  
    86.     if(s.mode == "close"){  
    87.         s.height1 += s.speed;  
    88.         s.height2 += s.speed;  
    89.     }else if(s.mode == "open"){  
    90.         s.height1 -= s.speed;  
    91.         s.height2 -= s.speed;  
    92.         if(s.height1 < 0){  
    93.             s.mode = "stop";  
    94.         }  
    95.     }else if(s.mode == "stop"){  
    96.         s.graphics.clear();  
    97.         s.removeEventListener(LEvent.ENTER_FRAME,s.onshow);  
    98.         s.onComplete();  
    99.     }  
    100. }  
    101. /** 
    102. *LCurtainSample3.js 
    103. */  
    104. function LCurtainSample3(speed,onClosing,onComplete){  
    105.     var s = this;  
    106.     base(s,LSprite,[]);  
    107.     if(!speed)speed = LStage.width/100;  
    108.     if(!onClosing){  
    109.         s.onClosing = function(){};  
    110.     }else{  
    111.         s.onClosing = onClosing;  
    112.     }     
    113.     if(!onComplete){  
    114.         s.onComplete = function(){};  
    115.     }else{  
    116.         s.onComplete = onComplete;  
    117.     }  
    118.     s.mode = "close";  
    119.     s.height1 = 0;  
    120.     s.height2 = 0;  
    121.     s.width1 = 0;  
    122.     s.width2 = 0;  
    123.     s.isDoClosing = false;  
    124.     s.speed = speed;  
    125.     s.addEventListener(LEvent.ENTER_FRAME,s.onshow);  
    126. }  
    127. LCurtainSample3.prototype.onshow = function(s){  
    128.     s.graphics.clear();  
    129.     s.graphics.drawRect(1,"black",[0,0,LStage.width,s.height1],true,"black");  
    130.     s.graphics.drawRect(1,"black",[0,LStage.height-s.height2,LStage.width,s.height2],true,"black");  
    131.     s.graphics.drawRect(1,"black",[0,0,s.width1,LStage.height],true,"black");  
    132.     s.graphics.drawRect(1,"black",[LStage.width-s.width2,0,s.width2,LStage.height],true,"black");  
    133.     if(s.height1 >= LStage.height/2 ){  
    134.         s.mode = "open";  
    135.         if(s.isDoClosing == false){  
    136.             s.onClosing();  
    137.             s.isDoClosing = true;  
    138.         }  
    139.     }  
    140.     if(s.mode == "close"){  
    141.         s.height1 += s.speed;  
    142.         s.height2 += s.speed;  
    143.         s.width1 += s.speed;  
    144.         s.width2 += s.speed;  
    145.     }else if(s.mode == "open"){  
    146.         s.height1 -= s.speed;  
    147.         s.height2 -= s.speed;  
    148.         s.width1 -= s.speed;  
    149.         s.width2 -= s.speed;  
    150.         if(s.height1 < 0){  
    151.             s.mode = "stop";  
    152.         }  
    153.     }else if(s.mode == "stop"){  
    154.         s.graphics.clear();  
    155.         s.removeEventListener(LEvent.ENTER_FRAME,s.onshow);  
    156.         s.onComplete();  
    157.     }  
    158. }  


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

    谢谢大家阅读本文。支持就是最大的鼓舞。

    ----------------------------------------------------------------

    欢迎大家转载我的文章。

    转载请注明:转自Yorhom's Game Box

    http://blog.csdn.net/yorhomwang

    欢迎继续关注我的博客

  • 相关阅读:
    etcd 部署、备份与恢复
    centos7 mysql 5.7.24 源码编译
    生产中两块网卡bond
    shell 免密批量执行脚本
    MegaCli 清除与添加raid5
    centos7 mongodb4.0.2 复制集主从部署
    centos6.6 部署 cacti 并采集交换机流量
    shell 批量远程主机执行命令
    拯救系统文件只读模式
    下推自动机(PDA)在程序设计中的应用
  • 原文地址:https://www.cnblogs.com/mfryf/p/3138678.html
Copyright © 2020-2023  润新知