如何制作一款HTML5 RPG游戏引擎——第四篇,情景对话
今天我们来实现情景对话。这是一个重要的功能,没有它,游戏将变得索然无味。所以我们不得不来完成它。
但是要知道,使用对话可不是一件简单的事,因为它内部的东西很多,比如说人物头像,人物名称,对话内容。。。
因此我们只能通过数组+JSON来将对话信息装起来,然后根据信息作出不同的显示。接下来我便要向大家展示实现方法。
先看本系列文章目录:
如何制作一款HTML5 RPG游戏引擎——第一篇,地图类的实现
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开发的,学习时请先了解lufylegend。
官方网站地址:http://lufylegend.com/lufylegend
API地址:http://lufylegend.com/lufylegend/api
1,实现后的代码
为了向大家展示封装的必要性,所以我们先看实现后的代码:
<!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(){//加入进度条 loadingLayer = new LoadingSample1(); addChild(loadingLayer); //加载图片并显示进度 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();//添加对话内容 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);//设置样式 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行代码就可以实现进行5次对话的效果,先发两张截图,如下:
由此可见,本次封装还是很有作用的。
但是如何实现呢?请看接下来的讲解。
2,LTalk类
LTalk是一个对话类,构造器如下:
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属性是为了设置文字区宽度的,设置后,如果文字过多而超出这个区域就会自动换行。talkIndex指对话编号。faceX,faceY指人物头像位置。nameX,nameY指人物名称的位置;nameColor,nameFont,nameSize分别用来设置名称颜色,字体,尺寸。msgX,msgY,msgColor,msgFont,msgSize同分别代表对话内容的x坐标,y坐标,颜色,字体,尺寸。
设定好刚才的那些属性后,就可以自定义对话样式了。
这个类构造时要传个参数,这个参数是对话内容。是一个数组套JSON的格式,如下:
[{name:"名称",msg:"内容",face:头像图片},{name:"名称",msg:"内容",face:头像图片},{name:"名称",msg:"内容",face:头像图片},{name:"名称",msg:"内容",face:头像图片},{name:"名称",msg:"内容",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!");} }
这个方法有两个参数,第一个是播放序号,第二个参数是输出完成后调用的函数。
首先我们判断一下参数num是不是没定义,如果是就自动设0,然后再判断第二个参数是否定义,如果没有,就设为null。这样做可以确保程序运行无误。接着,我们把控制播放序号的属性talkIndex设为num,然后清空一次,以便不和上次输出的重叠在一起。接着判断talkIndex有没有超出最大值,没有的话就执行输出命令。代码如下:
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的朋友不难理解这些,就是将名称,内容,头像全部加到界面上。显示内容为构造器参数中对应的内容。
wind做好后,大家想让文本逐字显示时只用写一行obj.wind();就行了。
4,更改样式&手动清空对话&重设数据
刚才我们看了控制文字,图片样式的几个属性,有很多,如果一个一个用手改就会很麻烦,而且要写很多行代码,因此我们加几个控制样式的方法,它们分别是:setFaceStyle,setNameStyle,setMsgStyle。运用时只用传入参数就行了。
实现方法如下:
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;} }
值得注意的是,参数是一个JSON对象。格式如下:
/*给msg和name设置样式时传的参数*/ {x:x坐标,y:y坐标,color:文字颜色,size:文字尺寸} /*给face设置样式时传的参数*/ {x:x坐标,y:y坐标}
OK,给对话设定样式就搞定了。
再加一个手动清空对话的方法,这样一来可以方便用户手动清空对话:
LTalk.prototype.clear = function(){var s = this;s.removeAllChild();s.die(); }
最后加一个重设对话数据的函数:
LTalk.prototype.setData = function(content){var s = this;s.content = content; }
5,Debug输出
前面在设计类时,没考虑到大家debug,所以都没加入什么debug输出。这次想到了,就顺便做一下,顺便把以前的也做了一下。今天就只呈现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);} }
调用此方法输出如下:
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(); }
运用时,就只用写这些代码:
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构造时所传的对话内容参数是一个数组套JSON的格式,它要在游戏图片加载完成后再初始化,否则显示不出对话头像。
最后把测试链接给大家:
http://www.cnblogs.com/yorhom/articles/3132075.html
进入后点击黑框开始对话。祝大家测试愉快~
近天就先说到这里,下次我们接着研究。
如何制作一款HTML5 RPG游戏引擎——第四篇,情景对话相关推荐
- 如何制作一款HTML5 RPG游戏引擎——第五篇,人物人物特效
上一次,我们实现了对话类,今天就来做一个游戏中必不可少的--人物类. 当然,你完全是可以自己写一个人物类,但是为了方便起见,还是决定把人物类封装到这个引擎里. 为了使这个类更有意义,我还给人物类加了几 ...
- 如何制作一款HTML5 RPG游戏引擎——第三篇,利用幕布切换场景
开言: 在RPG游戏中,如果有地图切换的地方,通常就会使用幕布效果.所谓的幕布其实就是将两个矩形合拢,直到把屏幕遮住,然后再展开直到两个矩形全部移出屏幕. 为了大家做游戏方便,于是我给这个引擎加了这么 ...
- 如何制作一款HTML5 RPG游戏引擎——第二篇,烟雨+飞雪效果
今天我们来实现烟雨+飞雪效果.首先来说,一款经典的RPG游戏难免需要加入天气的变化.那么为了使我们的RPG游戏引擎更完美,我们就只好慢慢地实现它. 本文为该系列文章的第二篇,如果想了解以前的文章可以看 ...
- 如何制作一款HTML5 RPG游戏引擎——第一篇,地图类的实现
一,话说天下大事 前不久看到lufy的博客上,有一位朋友想要一个RPG游戏引擎,出于兴趣准备动手做一做.由于我研究lufylegend有一段时间了,对它有一定的依赖性,因此就准备将这个引擎基于lufy ...
- 如何实现一个HTML5 RPG游戏引擎——第五章,实现人物和人物特效
上一次,我们实现了对话类,今天就来做一个游戏中不可缺少的--人物类. 当然,你全然是能够自己写一个人物类,可是为了方便起见,还是决定把人物类封装到这个引擎里. 为了使这个类更有意义,我还给人物类加了几 ...
- 如何实现一个HTML5 RPG游戏引擎——第一章,实现地图类
一,话说天下大事 前不久看到lufy的博客上,有一位朋友想要一个RPG游戏引擎,出于兴趣准备动手做一做.因为我研究lufylegend有一段时间了,对它有一定的依赖性,因此就准备将这个引擎基于lufy ...
- HTML5开源RPG游戏引擎lufylegendRPG 0.1发布
一,小小开篇 首先不得不先介绍一下这个引擎: lufylegendRPG是lufylegend的拓展引擎,使用它时,需要引入lufylegend.同时您也需要了解lufylegend语法,这样才能更合 ...
- 用Html5结合Qt制作一款本地化EXE游戏-太空大战(Space War)
本次来说一说如何利用lufylegend.js引擎制作一款html5游戏后将其通过Qt转换成EXE程序.步骤其实非常简单,接下来就一步步地做一下解释和说明. 首先我们来开发一个有点类似于太空大战的游戏 ...
- 不用写代码的Android 2D RPG游戏引擎
菠萝BOSS为一款基于Android系统的2D RPG游戏引擎,具有以下主要特点:(1)无需编写代码,采用纯配置的开发方式,适合不熟悉Android APP开发的个人及小团队,开发者可将精力投入到游戏 ...
最新文章
- python读取access_Python 获取 Access 表字段名!
- 程序员11月书讯 | 硅谷,梦开始的地方
- ​忆阻器会成为“存储墙”的破局者么
- Spring 基于Java配置
- Leetcode题库 728.自除数(C实现)
- php static method,php 类方法用static::hello(); 等同于 $this-hello();吗?
- 获取网页中选中的文字
- BZOJ 2243 染色(树链剖分好题)
- 第七章:react-ui
- json vue 对象转数组_vue.js基于v-for实现批量渲染 Json数组对象列表数据示例
- 二叉树查找最大最小值c语言,用C语言实现二叉排序树查找小于关键字key的最大节点的函数...
- bzoj3007 解救小云公主
- varnish运行机制及管理优化
- C#控件储备——信息提示控件toolTip
- 在计算机中 总线简称,微机中的总线一般分为几等
- pm2开启nuxt项目pm2 start ./node_modules/nuxt/bin/nuxt-start
- Texture ASTC转换ETC
- sh报错segmentation fault
- 更新驱动后重启黑屏且进不了bios时的一个解决办法
- 垂直居中对齐四种样式
热门文章
- Wireshark网络抓包实践
- 无法安装ie8,因为其他程序或更新正在等待重启您的计算机,ie8 因为其他程序或更新正在等待重新启...
- 分站实现php,php城市分站是什么原理
- 硬盘显示容量和实际容量不符合_SSD小讲堂丨实力科普固态硬盘实际容量为何比标称小...
- vue component created没有触发_Vue 全局数据管理-Vuex
- lsqcurvefit拟合结果为复数_非线性拟合怎么转化为线性拟合?
- C/S和B/S两种架构区别与优缺点分析
- WIN下Nginx缓存加速配置方法
- 【弱化版】【P3371 【模板】单源最短路径(弱化版)】-C++
- Asp.Net Core 之 appsettings.json