開言:
在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();}}
這次講解就到這裡,下一次我們就來實現必不可少的對話類,不容錯過哦!!!
謝謝大家閱讀本文。支援就是最大的鼓勵。
----------------------------------------------------------------
歡迎大家轉載我的文章。
轉載請註明:轉自Yorhom's Game Box
http://blog.csdn.net/yorhomwang
歡迎繼續關注我的部落格