如何制作一款HTML5 RPG游戏引擎——第四篇,情景对话
今天我們來實(shí)現(xiàn)情景對話。這是一個重要的功能,沒有它,游戲?qū)⒆兊盟魅粺o味。所以我們不得不來完成它。
但是要知道,使用對話可不是一件簡單的事,因?yàn)樗鼉?nèi)部的東西很多,比如說人物頭像,人物名稱,對話內(nèi)容。。。
因此我們只能通過數(shù)組+JSON來將對話信息裝起來,然后根據(jù)信息作出不同的顯示。接下來我便要向大家展示實(shí)現(xiàn)方法。
?
先看本系列文章目錄:
如何制作一款HTML5?RPG游戲引擎——第一篇,地圖類的實(shí)現(xiàn)
http://blog.csdn.net/yorhomwang/article/details/8892305
如何制作一款HTML5 RPG游戲引擎——第二篇,煙雨+飛雪效果
http://blog.csdn.net/yorhomwang/article/details/8915020
如何制作一款HTML5 RPG游戲引擎——第三篇,利用幕布切換場景
http://blog.csdn.net/yorhomwang/article/details/9042571
?
?
該引擎是基于lufylegend開發(fā)的,學(xué)習(xí)時請先了解lufylegend。
官方網(wǎng)站地址:http://lufylegend.com/lufylegend
API地址:http://lufylegend.com/lufylegend/api
?
1,實(shí)現(xiàn)后的代碼
為了向大家展示封裝的必要性,所以我們先看實(shí)現(xiàn)后的代碼:
<!DOCTYPE html> <html lang="en"><head><meta charset="utf-8" /><title>LTalk</title><script type="text/javascript" src="../lufylegend-1.7.6.min.js"></script><script type="text/javascript" src="../lufylegendrpg-1.0.0.js"></script> <script>init(30,"legend",480,320,main);LRPGStage.setShortcuts(true);LGlobal.setDebug(true);var backLayer,loadingLayer,talkLayer;var talk;var talkContent;var talkNum = 0;var loadData = [{name:"yorhom_face",path:"./yorhom.jpg"},{name:"lufy_face",path:"./lufy.jpg"}];var imglist = [];function main(){//加入進(jìn)度條 loadingLayer = new LoadingSample1(); addChild(loadingLayer); //加載圖片并顯示進(jìn)度 LLoadManage.load(loadData,function(progress){loadingLayer.setProgress(progress);},gameInit); }function gameInit(result){removeChild(loadingLayer);imglist = result;//初始化層 backLayer = new LSprite();addChild(backLayer);talkLayer = new LSprite();backLayer.addChild(talkLayer);//加入操作按鈕 addEvent();//添加對話內(nèi)容 talkContent = [{name:"[Yorhom]",msg:"你好,lufy",face:imglist["yorhom_face"]},{name:"[lufy]",msg:"你好,yorhom",face:imglist["lufy_face"]},{name:"[Yorhom]",msg:"lufylegend最新版本是哪個版本啊?",face:imglist["yorhom_face"]},{name:"[lufy]",msg:"……你不知道自己看嗎?",face:imglist["lufy_face"]},{name:"[Yorhom]",msg:"……說得也是",face:imglist["yorhom_face"]},];//加入對話 talkLayer.graphics.drawRect(5,"black",[20,15,400,130],true,"black");talkLayer.alpha = 0.8;talk = new LTalk(talkContent);talkLayer.addChild(talk);talkLayer.addEventListener(LMouseEvent.MOUSE_DOWN,say);//設(shè)置樣式 talk.setNameStyle({x:160,y:40,color:"white",size:12});talk.setMsgStyle({x:160,y:70,color:"white",size:10});talk.setFaceStyle({x:30,y:30});talk.textWidth = 260;}function addEvent(){LEvent.addEventListener(LGlobal.window,LKeyboardEvent.KEY_UP,say);}function say(){if(talkNum < talkContent.length){//輸出對話 talk.wind(talkNum,function(){talkNum++;});}}</script></head><body><div id="legend"></div></body> </html>這78行代碼就可以實(shí)現(xiàn)進(jìn)行5次對話的效果,先發(fā)兩張截圖,如下:
?
由此可見,本次封裝還是很有作用的。
但是如何實(shí)現(xiàn)呢?請看接下來的講解。
2,LTalk類
LTalk是一個對話類,構(gòu)造器如下:
function LTalk(content){var s = this;base(s,LSprite,[]);if(!content){s.content = [];}else{s.content = content;}s.x = 0;s.y = 0;s.textWidth = LStage.width;s.talkIndex = 0;s.faceX = 0;s.faceY = 0;s.nameX = 0;s.nameY = 0;s.nameColor = "black";s.nameFont = "宋體";s.nameSize = "15";s.msgX = 0;s.msgY = 0;s.msgColor = "black";s.msgFont = "宋體";s.msgSize = "15"; }其中,textWidth屬性是為了設(shè)置文字區(qū)寬度的,設(shè)置后,如果文字過多而超出這個區(qū)域就會自動換行。talkIndex指對話編號。faceX,faceY指人物頭像位置。nameX,nameY指人物名稱的位置;nameColor,nameFont,nameSize分別用來設(shè)置名稱顏色,字體,尺寸。msgX,msgY,msgColor,msgFont,msgSize同分別代表對話內(nèi)容的x坐標(biāo),y坐標(biāo),顏色,字體,尺寸。
設(shè)定好剛才的那些屬性后,就可以自定義對話樣式了。
這個類構(gòu)造時要傳個參數(shù),這個參數(shù)是對話內(nèi)容。是一個數(shù)組套JSON的格式,如下:
[{name:"名稱",msg:"內(nèi)容",face:頭像圖片},{name:"名稱",msg:"內(nèi)容",face:頭像圖片},{name:"名稱",msg:"內(nèi)容",face:頭像圖片},{name:"名稱",msg:"內(nèi)容",face:頭像圖片},{name:"名稱",msg:"內(nèi)容",face:頭像圖片}, ];每往這個列表里加一條,就會多一段對話。
3,wind方法
接下來看看wind方法:
LTalk.prototype.wind = function(num,completeFunc){var s = this;if(!num || num == null)num = 0;if(!completeFunc)completeFunc = null;s.talkIndex = num;s.removeAllChild();if(s.talkIndex < s.content.length){var talkObject = s.content[s.talkIndex];var faceBitmapdata = new LBitmapData(talkObject.face);var faceBitmap = new LBitmap(faceBitmapdata);faceBitmap.x = s.faceX;faceBitmap.y = s.faceY;s.addChild(faceBitmap);var name = new LTextField();name.x = s.nameX;name.y = s.nameY;name.size = s.nameSize;name.color = s.nameColor;name.font = s.nameFont;name.text = talkObject.name;name.width = s.textWidth;name.setWordWrap(true,name.getHeight()+5);s.addChild(name);var msg = new LTextField();msg.x = s.msgX;msg.y = s.msgY;msg.size = s.msgSize;msg.color = s.msgColor;msg.font = s.msgFont;msg.text = talkObject.msg;msg.width = s.textWidth;msg.setWordWrap(true,msg.getHeight()+7);msg.wind(completeFunc);s.addChild(msg);}else{trace("Error: Param exceeds the size of the content!");} }這個方法有兩個參數(shù),第一個是播放序號,第二個參數(shù)是輸出完成后調(diào)用的函數(shù)。
?
首先我們判斷一下參數(shù)num是不是沒定義,如果是就自動設(shè)0,然后再判斷第二個參數(shù)是否定義,如果沒有,就設(shè)為null。這樣做可以確保程序運(yùn)行無誤。接著,我們把控制播放序號的屬性talkIndex設(shè)為num,然后清空一次,以便不和上次輸出的重疊在一起。接著判斷talkIndex有沒有超出最大值,沒有的話就執(zhí)行輸出命令。代碼如下:
var talkObject = s.content[s.talkIndex]; var faceBitmapdata = new LBitmapData(talkObject.face); var faceBitmap = new LBitmap(faceBitmapdata); faceBitmap.x = s.faceX; faceBitmap.y = s.faceY; s.addChild(faceBitmap); var name = new LTextField(); name.x = s.nameX; name.y = s.nameY; name.size = s.nameSize; name.color = s.nameColor; name.font = s.nameFont; name.text = talkObject.name; name.width = s.textWidth; name.setWordWrap(true,name.getHeight()+5); s.addChild(name); var msg = new LTextField(); msg.x = s.msgX; msg.y = s.msgY; msg.size = s.msgSize; msg.color = s.msgColor; msg.font = s.msgFont; msg.text = talkObject.msg; msg.width = s.textWidth; msg.setWordWrap(true,msg.getHeight()+7); msg.wind(completeFunc); s.addChild(msg);熟悉lufylegend的朋友不難理解這些,就是將名稱,內(nèi)容,頭像全部加到界面上。顯示內(nèi)容為構(gòu)造器參數(shù)中對應(yīng)的內(nèi)容。
wind做好后,大家想讓文本逐字顯示時只用寫一行obj.wind();就行了。
?
4,更改樣式&手動清空對話&重設(shè)數(shù)據(jù)
剛才我們看了控制文字,圖片樣式的幾個屬性,有很多,如果一個一個用手改就會很麻煩,而且要寫很多行代碼,因此我們加幾個控制樣式的方法,它們分別是:setFaceStyle,setNameStyle,setMsgStyle。運(yùn)用時只用傳入?yún)?shù)就行了。
實(shí)現(xiàn)方法如下:
LTalk.prototype.setFaceStyle = function(styleData){var s = this;if(!styleData.x){s.faceX = 0;}else{s.faceX = styleData.x;}if(!styleData.y){s.faceY = 0;}else{s.faceY = styleData.y;} } LTalk.prototype.setNameStyle = function(styleData){var s = this;if(!styleData.x){s.nameX = 0;}else{s.nameX = styleData.x;}if(!styleData.y){s.nameY = 0;}else{s.nameY = styleData.y;}if(!styleData.color){s.nameColor = "black";}else{s.nameColor = styleData.color;}if(!styleData.font){s.nameFont = "宋體";}else{s.nameFont = styleData.font;}if(!styleData.size){s.nameSize = "15";}else{s.nameSize = styleData.size;} } LTalk.prototype.setMsgStyle = function(styleData){var s = this;if(!styleData.x){s.msgX = 0;}else{s.msgX = styleData.x;}if(!styleData.y){s.msgY = 0;}else{s.msgY = styleData.y;}if(!styleData.color){s.msgColor = "black";}else{s.msgColor = styleData.color;}if(!styleData.font){s.msgFont = "宋體";}else{s.msgFont = styleData.font;}if(!styleData.size){s.msgSize = "15";}else{s.msgSize = styleData.size;} }值得注意的是,參數(shù)是一個JSON對象。格式如下:
/*給msg和name設(shè)置樣式時傳的參數(shù)*/ {x:x坐標(biāo),y:y坐標(biāo),color:文字顏色,size:文字尺寸} /*給face設(shè)置樣式時傳的參數(shù)*/ {x:x坐標(biāo),y:y坐標(biāo)}OK,給對話設(shè)定樣式就搞定了。
?
再加一個手動清空對話的方法,這樣一來可以方便用戶手動清空對話:
LTalk.prototype.clear = function(){var s = this;s.removeAllChild();s.die(); }最后加一個重設(shè)對話數(shù)據(jù)的函數(shù):
LTalk.prototype.setData = function(content){var s = this;s.content = content; }5,Debug輸出
前面在設(shè)計類時,沒考慮到大家debug,所以都沒加入什么debug輸出。這次想到了,就順便做一下,順便把以前的也做了一下。今天就只呈現(xiàn)LTalk中的Debug輸出,代碼如下:
LTalk.prototype.showData = function(){var s = this;for(var key in s.content){trace("----------No."+key+"----------");trace("Name: " + s.content[key].name);trace("Msg: " + s.content[key].msg);trace("Face: " + s.content[key].face);} }調(diào)用此方法輸出如下:
6,源代碼
源代碼不多,大家可以拿下去測試一下:
/** *LTalk.js */ function LTalk(content){var s = this;base(s,LSprite,[]);if(!content){s.content = [];}else{s.content = content;}s.x = 0;s.y = 0;s.textWidth = LStage.width;s.talkIndex = 0;s.faceX = 0;s.faceY = 0;s.nameX = 0;s.nameY = 0;s.nameColor = "black";s.nameFont = "宋體";s.nameSize = "15";s.msgX = 0;s.msgY = 0;s.msgColor = "black";s.msgFont = "宋體";s.msgSize = "15"; } LTalk.prototype.setData = function(content){var s = this;s.content = content; } LTalk.prototype.showData = function(){var s = this;for(var key in s.content){trace("----------No."+key+"----------");trace("Name: " + s.content[key].name);trace("Msg: " + s.content[key].msg);trace("Face: " + s.content[key].face);} } LTalk.prototype.setFaceStyle = function(styleData){var s = this;if(!styleData.x){s.faceX = 0;}else{s.faceX = styleData.x;}if(!styleData.y){s.faceY = 0;}else{s.faceY = styleData.y;} } LTalk.prototype.setNameStyle = function(styleData){var s = this;if(!styleData.x){s.nameX = 0;}else{s.nameX = styleData.x;}if(!styleData.y){s.nameY = 0;}else{s.nameY = styleData.y;}if(!styleData.color){s.nameColor = "black";}else{s.nameColor = styleData.color;}if(!styleData.font){s.nameFont = "宋體";}else{s.nameFont = styleData.font;}if(!styleData.size){s.nameSize = "15";}else{s.nameSize = styleData.size;} } LTalk.prototype.setMsgStyle = function(styleData){var s = this;if(!styleData.x){s.msgX = 0;}else{s.msgX = styleData.x;}if(!styleData.y){s.msgY = 0;}else{s.msgY = styleData.y;}if(!styleData.color){s.msgColor = "black";}else{s.msgColor = styleData.color;}if(!styleData.font){s.msgFont = "宋體";}else{s.msgFont = styleData.font;}if(!styleData.size){s.msgSize = "15";}else{s.msgSize = styleData.size;} } LTalk.prototype.wind = function(num,completeFunc){var s = this;if(!num || num == null)num = 0;if(!completeFunc)completeFunc = null;s.talkIndex = num;s.removeAllChild();if(s.talkIndex < s.content.length){var talkObject = s.content[s.talkIndex];var faceBitmapdata = new LBitmapData(talkObject.face);var faceBitmap = new LBitmap(faceBitmapdata);faceBitmap.x = s.faceX;faceBitmap.y = s.faceY;s.addChild(faceBitmap);var name = new LTextField();name.x = s.nameX;name.y = s.nameY;name.size = s.nameSize;name.color = s.nameColor;name.font = s.nameFont;name.text = talkObject.name;name.width = s.textWidth;name.setWordWrap(true,name.getHeight()+5);s.addChild(name);var msg = new LTextField();msg.x = s.msgX;msg.y = s.msgY;msg.size = s.msgSize;msg.color = s.msgColor;msg.font = s.msgFont;msg.text = talkObject.msg;msg.width = s.textWidth;msg.setWordWrap(true,msg.getHeight()+7);msg.wind(completeFunc);s.addChild(msg);}else{trace("Error: Param exceeds the size of the content!");} } LTalk.prototype.clear = function(){var s = this;s.removeAllChild();s.die(); }運(yùn)用時,就只用寫這些代碼:
var talkContent = [{name:"[Yorhom]",msg:"你好,lufy",face:imglist["yorhom_face"]},{name:"[lufy]",msg:"你好,yorhom",face:imglist["lufy_face"]},{name:"[Yorhom]",msg:"lufylegend最新版本是哪個版本啊?",face:imglist["yorhom_face"]},{name:"[lufy]",msg:"……你不知道自己看嗎?",face:imglist["lufy_face"]},{name:"[Yorhom]",msg:"……說得也是",face:imglist["yorhom_face"]}, ]; var talk = new LTalk(talkContent); addChild(talk); talk.wind();順便提示一下,LTalk構(gòu)造時所傳的對話內(nèi)容參數(shù)是一個數(shù)組套JSON的格式,它要在游戲圖片加載完成后再初始化,否則顯示不出對話頭像。
?
最后把測試鏈接給大家:
http://www.cnblogs.com/yorhom/articles/3132075.html
進(jìn)入后點(diǎn)擊黑框開始對話。祝大家測試愉快~
近天就先說到這里,下次我們接著研究。
總結(jié)
以上是生活随笔為你收集整理的如何制作一款HTML5 RPG游戏引擎——第四篇,情景对话的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 跨界创立PayPal、特斯拉、Space
- 下一篇: centos ruby通过rvm更新版本