开言:
在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坐标,然后再来画。计算方法非常easy,就是用屏幕宽度减去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();
- }
- }
这次解说就到这里,下一次我们就来实现不可缺少的对话类,不容错过哦!!!
谢谢大家阅读本文。支持就是最大的鼓舞。
----------------------------------------------------------------
欢迎大家转载我的文章。
转载请注明:转自Yorhom's Game Box
http://blog.csdn.net/yorhomwang
欢迎继续关注我的博客