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

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

    [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

    欢迎继续关注我的博客

  • 相关阅读:
    68
    56
    Django manager 命令笔记
    Django 执行 manage 命令方式
    Django 连接 Mysql (8.0.16) 失败
    Python django 安装 mysqlclient 失败
    H.264 SODB RBSP EBSP的区别
    FFmpeg—— Bitstream Filters 作用
    MySQL 远程连接问题 (Windows Server)
    MySQL 笔记
  • 原文地址:https://www.cnblogs.com/mfryf/p/3138678.html
Copyright © 2011-2022 走看看