上一次,我们实现了对话类,今天就来做一个游戏中必不可少的——人物类。

当然,你完全是可以自己写一个人物类,但是为了方便起见,还是决定把人物类封装到这个引擎里。

为了使这个类更有意义,我还给人物类加了几个特效,在以下讲解中会提到。

以下是本系列文章的目录:

如何制作一款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

如何制作一款HTML5 RPG游戏引擎——第四篇,情景对话

http://blog.csdn.net/yorhomwang/article/details/9076103

该引擎是基于lufylegend开发的,学习时请先了解lufylegend。

官方网站地址:http://lufylegend.com/lufylegend

API地址:http://lufylegend.com/lufylegend/api

一,人物类LCharacter

首先来看LCharacter构造器:

/**
*LCharacter.js
*/
function LCharacter(data,row,col,speed,isFighter){
var s = this;
base(s,LSprite,[]);
s.type = "LCharacter";
if(!speed)speed = 0;
if(isFighter == undefined)isFighter = false;
s.speed = speed;
s.speedIndex = 0;
s.x = 0;
s.y = 0;
s.mode = "";
s.index = 0;
if(isFighter == true){
s.hp = 0;
s.attack = 0;
s.defense = 0;
}
s.effect = null;
s.avatarNum = 0;
s.flickerNum = 0;
s.img = data;
s.row = row;
s.col = col;
s.effectSprite = new LSprite();
s.addChild(s.effectSprite);
s.nameSprite = new LSprite();
s.addChild(s.nameSprite);
var imgData = new LBitmapData(data);
imgData.setProperties(0,0,imgData.image.width/col,imgData.image.height/row);
var list = LGlobal.divideCoordinate(imgData.image.width,imgData.image.height,row,col);
s.imgWidth = imgData.image.width/col;
s.imgHeight = imgData.image.height/row;
s.anime = new LAnimation(s,imgData,list);
s.addEventListener(LEvent.ENTER_FRAME,function(){
if(s.effect != null){
s.showEffect(s,s.effect);
}
});
}

这个类有5个参数,功能如下:

data:人物图片
row:将图片切成多少行,以方便执行动画
col:将图片切成多少列,以方便执行动画
speed:人物动画播放频率相对屏幕刷新频率的倍数
isFighter:是否处于战斗状态

上面的介绍有些含糊,我接着解释一下。首先,data所代表的图片是一个装有每帧动画的图片,比如下面这种图片:

然后我们的参数row和参数col就是用来表示这个图片可以分成几行,几列。比如上图,row就赋值成4,col也赋值成4,这样恰好能将每帧都分割出来。

speed是用来表示播放动画频率的,假设我们在用init初始化游戏时,传入游戏频率为30毫秒,那如果不给这个参数赋值,播放动画的频率就是30毫秒,但是如果你觉得30毫秒播放一帧太快了,想慢一点,便可以用到这个参数。比如说你想让播放频率达到每120毫秒播放一帧,而游戏频率设的是30毫秒,那就可以把这个参数设置为4。假设达到每150毫秒播放一帧,那就可以把这个参数设置为5。但要注意,这个参数赋值必须是正整数。

isFighter这个参数是用来判断是否这个角色是处于战斗状态的。如果是就设为true,不是就设为false,当然你不设定就默认为false。当这个参数为true时,人物类就可以加几个属性,它们用来控制人物的hp,战斗力,防御力等,判断代码如下:

if(isFighter == true){
s.hp = 0;
s.attack = 0;
s.defense = 0;
}

为了给这个类更方便地添加特效,我给它自身创建了一个叫effectLayer的LSprite。用于特效的几个属性还如下几个:

s.effect = null;
s.avatarNum = 0;
s.flickerNum = 0;

接着我创建了一个LAnimation对象,用它来显示人物动画,代码如下:

var imgData = new LBitmapData(data);
imgData.setProperties(0,0,imgData.image.width/col,imgData.image.height/row);
var list = LGlobal.divideCoordinate(imgData.image.width,imgData.image.height,row,col);
s.imgWidth = imgData.image.width/col;
s.imgHeight = imgData.image.height/row;
s.anime = new LAnimation(s,imgData,list);

具体LAnimation使用方法可以去lufylegend官方API中查看。这里就先不多讲了~

为了使特效使用方便,我设计为直接通过调整effect属性来完成。但是effect在实例化前值是null,所以如果不做处理就调整了属性依然是不会显示的。所以我加入了一个时间轴事件,让它不断地判断effect属性,以至于达到一改effect属性就能立刻显示效果。代码如下:

s.addEventListener(LEvent.ENTER_FRAME,function(){
if(s.effect != null){
s.showEffect(s,s.effect);
}
});

关于时间轴,说白了就是一个死循环,只不过是停顿一段时间调用一次,javascript中通常用setInerval来实现,具体方法Google一下或百度一下就OK,我不多解释了。

当然,具体如何显示效果留到下面讲,我们先看其他方法。

由于我们在开发的过程中要用到修改数据的方法,因此我们还得加一个setData方法:

LCharacter.prototype.setData = function(data,row,col,speed,isFighter){
var s = this;
if(!speed)speed = 0;
if(isFighter == undefined)isFighter = false;
s.speed = speed;
s.img = data;
s.row = row;
s.col = col;
if(isFighter == true){
s.hp = 0;
s.attack = 0;
s.defense = 0;
}
var imgData = new LBitmapData(data);
imgData.setProperties(0,0,imgData.image.width/col,imgData.image.height/row);
var list = LGlobal.divideCoordinate(imgData.image.width,imgData.image.height,row,col);
s.imgWidth = imgData.image.width/col;
s.imgHeight = imgData.image.height/row;
s.removeChild(s.anime);
s.anime = new LAnimation(s,imgData,list);
}

参数和构造器的参数是一样的,方法也差不多,大家可以自己看一下。

二,动画操作

上面我们做好了构造器和重设数据方法,并解释了大半天,接下来就要讲讲动画操作了。

动画操作一般有这几种:1,设置动画 2,获取动画信息 3,加入动画监听事件 4,播放动画

还好,这三种方法在lufylegend中都封装得有,我们用起来就很方便了。添加addActionEventListener方法,以达到给动画加入监听事件:

LCharacter.prototype.addActionEventListener = function(type,listener){
var s = this;
s.anime.addEventListener(type,listener);
}

添加setAction方法,以达到设置动画:

LCharacter.prototype.setAction = function(rowIndex,colIndex,mode,isMirror){
var s = this;
s.anime.setAction(rowIndex,colIndex,mode,isMirror);
}

添加getAction方法,以达到获取动画信息:

LCharacter.prototype.getAction = function(){
var s = this;
var returnAction = s.anime.getAction();
return returnAction;
}

添加onframe方法,以达到播放动画:

LCharacter.prototype.onframe = function(){
var s = this;
if(s.speedIndex++ < s.speed)return;
s.speedIndex = 0;
s.anime.onframe();
}

有了这些使用时就方便多了。开发到这里,其实是已经可以显示人物动画了。只用这样写即可:

var backLayer = new LSprite();
addChild(backLayer);
var chara = new LCharacter(imglist["player"],4,4,3);
backLayer.addChild(chara);
backLayer.addEventListener(LEvent.ENTER_FRAME,onframe);
function onframe(){
chara.onframe();
}

三,moveTo方法

为了简化操作,我加入moveTo方法来控制人物移动。

moveTo方法的代码:

LCharacter.prototype.moveTo = function(x,y,timer,type,style,completefunc){
var s = this;
if(!timer)timer = 1;
if(!type)type = Quad.easeIn;
if(!style)style = LMoveStyle.direct; switch(style){
case LMoveStyle.direct:
var vars = {
x:x,
y:y,
ease:type,
onComplete:completefunc
};
LTweenLite.to(s,timer,vars);
break;
case LMoveStyle.horizontal:
LTweenLite.to(s,timer,{
x:x,
ease:type,
onComplete:function(){
LTweenLite.to(s,timer,{
y:y,
ease:type,
onComplete:completefunc
});
}
});
break;
case LMoveStyle.vertical:
LTweenLite.to(s,timer,{
y:y,
ease:type,
onComplete:function(){
LTweenLite.to(s,timer,{
x:x,
ease:type,
onComplete:completefunc
});
}
});
break;
default:
trace("Error: Value of last param is wrong!");
}
}

参数分别为:目标x坐标,目标y坐标,移动时间,缓动类型,移动样式,移动完成后调用的函数

目标x坐标,目标y坐标不用解释。关键是后面几个比较重要。首先,由于这个效果我使用lufylegend的缓动类LTweenLite做的,所以timer就代表LTweenLite参数$duration,type就代表LTweenLite中的ease(缓动函数),LTweenLite的用法很广,可以上官网看看。

我们创建一个JSON对象,叫LMoveStyle,如下:

var LMoveStyle = {
horizontal:"horizontal",
vertical:"vertical",
direct:"direct"
};

style这个参数传得值为LMoveStyle中的成员,就是LMoveStyle.horizontal,LMoveStyle.vertical,LMoveStyle.direct。LMoveStyle.horizontal是先横向移动,再竖向移动;LMoveStyle.vertical则是先竖向移动,再横向移动;LMoveStyle.direct则是直接移到该地点。以后或许还会加更多效果,这里就先做3个。

使用时这么写就行了:

charaObj.moveTo(200,100,10,Quad.easeIn,LMoveStyle.direct,function(){});

四,加入角色名称

以前在lufy博客上看到有人问如何给人物加一个名称,当时看到了就想到了要加这个方法。其实实现起来很简单,代码如下:

LCharacter.prototype.addName = function(name,style){
var s = this;
s.nameSprite.removeAllChild();
if(!name)name = 0;
if(!style)style = [];
if(!style[0])style[0] = 0;
if(!style[1])style[1] = 0;
if(!style[2])style[2] = "black";
if(!style[3])style[3] = "11";
if(!style[4])style[4] = "utf-8";
var nameText = new LTextField();
nameText.text = name;
nameText.x = style[0];
nameText.y = style[1];
nameText.color = style[2];
nameText.size = style[3];
nameText.font = style[4];
s.nameSprite.addChild(nameText);
}

代码很简单,要用的时候直接这么写:

charaObj.addName("yorhom",[0,0,"black",10,"黑体"]);

五,人物特效

1,分身术

分身效果通常是出现在游戏的战斗过程中放大招什么的,实现起来也不是很难,主要也是用到LTweenLite缓动类。

首先我们来看看showEffect方法:

LCharacter.prototype.showEffect = function(s,type){
switch(type){ }
}

这个方法是用时间轴驱动的,因此里面的内容是不断调用的。这个参数很特别,首先是将自身指针传入,然后将效果类型传入。接着在内部判断类型为何,然后根据类型来作出相应的效果。

我们创建一个LSkill对象,它是一个JSON对象,如下:

var LSkill = {
avatar:"LSkillAvatar"
};

avatar音译为阿凡达,分身的意思(据我初步地了解应该是这样)。在这里就代表分身效果。写的时候就只用写:

charaObj.effect = LSkill.avatar;

但具体怎么实现呢,可以看看下面代码:

LCharacter.prototype.showEffect = function(s,type){
switch(type){
case LSkill.avatar:
if(s.avatarNum++ < 3){
var nowImg = s.anime.getAction();
var nowY = nowImg[0];
var nowX = nowImg[1]; var bitmapData = new LBitmapData(s.img,nowX*s.imgWidth,nowY*s.imgHeight,s.imgWidth,s.imgHeight);
var bitmap = new LBitmap(bitmapData);
bitmap.x = 0;
bitmap.y = 0;
LTweenLite.to(bitmap,0.5,{
x:(s.imgWidth)*s.avatarNum,
alpha:0.2,
ease:Quad.easeIn,
onComplete:function(){
LTweenLite.to(bitmap,0.5,{
x:(s.imgWidth)*s.avatarNum,
ease:Quad.easeIn,
});
}
});
s.effectSprite.addChild(bitmap); var bitmapData2 = new LBitmapData(s.img,nowX*s.imgWidth,nowY*s.imgHeight,s.imgWidth,s.imgHeight);
var bitmap2 = new LBitmap(bitmapData2);
bitmap2.x = 0;
bitmap2.y = 0;
LTweenLite.to(bitmap2,0.5,{
x:(s.imgWidth)*s.avatarNum * -1,
alpha:0.2,
ease:Quad.easeIn,
onComplete:function(){
LTweenLite.to(bitmap2,0.5,{
x:(s.imgWidth)*s.avatarNum * -1,
ease:Quad.easeIn,
onComplete:function(){
s.avatarNum = 0;
s.effect = null;
s.effectSprite.removeAllChild();
}
});
}
});
s.effectSprite.addChild(bitmap2);
}
break;
}
}

代码很长,不过逻辑很简单,我们慢慢解释:

首先我们的分身有六个也就是3对,然后我们判断是否达到3对,如果是就不再显示分身。接着我们取出动画的前几帧,作为分身的图片,如下:

var nowImg = s.anime.getAction();
var nowY = nowImg[0];
var nowX = nowImg[1];

然后创建左边分身的LBitmap对象,如下:

var bitmapData = new LBitmapData(s.img,nowX*s.imgWidth,nowY*s.imgHeight,s.imgWidth,s.imgHeight);
var bitmap = new LBitmap(bitmapData);
bitmap.x = 0;
bitmap.y = 0;

bitmap对象的显示区域大小就是人物动画的显示区域大小,图片就是人物本身那张图片。有了这些,就可以将人物的分身和人物本身做得一模一样了,只不过分身是静态的,人物本身是动态的。

接着我们开始将右边的分身缓动操作:

LTweenLite.to(bitmap,0.5,{
x:(s.imgWidth)*s.avatarNum,
alpha:0.2,
ease:Quad.easeIn,
onComplete:function(){
LTweenLite.to(bitmap,0.5,{
x:(s.imgWidth)*s.avatarNum,
ease:Quad.easeIn,
});
}
});
s.effectSprite.addChild(bitmap);

这个缓动是一个特别的缓动,因为它是缓动套缓动,这样做就可以让分身移动的速度达到 慢->快->慢->快 的效果。并切在移动的过程中改变透明度。

右边的分身效果很左边得差不多,就是改一改方向而已。如下:

var bitmapData2 = new LBitmapData(s.img,nowX*s.imgWidth,nowY*s.imgHeight,s.imgWidth,s.imgHeight);
var bitmap2 = new LBitmap(bitmapData2);
bitmap2.x = 0;
bitmap2.y = 0;
LTweenLite.to(bitmap2,0.5,{
x:(s.imgWidth)*s.avatarNum * -1,
alpha:0.2,
ease:Quad.easeIn,
onComplete:function(){
LTweenLite.to(bitmap2,0.5,{
x:(s.imgWidth)*s.avatarNum * -1,
ease:Quad.easeIn,
onComplete:function(){
s.avatarNum = 0;
s.effect = null;
s.effectSprite.removeAllChild();
}
});
}
});
s.effectSprite.addChild(bitmap2);

当右边缓动结束后,就会将effect属性设为null,然后移除所有分身。

为了让大家见证一下分身效果,发两张截图:

2,闪烁

闪烁很简单,直接用缓动调整透明度就行了。如下:

if(s.flickerNum++ < 3){
LTweenLite.to(s,0.3,{
alpha:0.5,
ease:Quad.easeIn,
onComplete:function(){
LTweenLite.to(s,0.5,{
alpha:1,
ease:Quad.easeIn,
onComplete:function(){
s.effect = null;
s.flickerNum = 0;
}
});
}
});
}

同时为LSkill添加一项,完整LSkill代码如下:

var LSkill = {
avatar:"LSkillAvatar",
flicker:"LSkillFlicker"
};

效果如下:

完整showEffect代码如下:

LCharacter.prototype.showEffect = function(s,type){
switch(type){
case LSkill.avatar:
if(s.avatarNum++ < 3){
var nowImg = s.anime.getAction();
var nowY = nowImg[0];
var nowX = nowImg[1]; var bitmapData = new LBitmapData(s.img,nowX*s.imgWidth,nowY*s.imgHeight,s.imgWidth,s.imgHeight);
var bitmap = new LBitmap(bitmapData);
bitmap.x = 0;
bitmap.y = 0;
LTweenLite.to(bitmap,0.5,{
x:(s.imgWidth)*s.avatarNum,
alpha:0.2,
ease:Quad.easeIn,
onComplete:function(){
LTweenLite.to(bitmap,0.5,{
x:(s.imgWidth)*s.avatarNum,
ease:Quad.easeIn,
});
}
});
s.effectSprite.addChild(bitmap); var bitmapData2 = new LBitmapData(s.img,nowX*s.imgWidth,nowY*s.imgHeight,s.imgWidth,s.imgHeight);
var bitmap2 = new LBitmap(bitmapData2);
bitmap2.x = 0;
bitmap2.y = 0;
LTweenLite.to(bitmap2,0.5,{
x:(s.imgWidth)*s.avatarNum * -1,
alpha:0.2,
ease:Quad.easeIn,
onComplete:function(){
LTweenLite.to(bitmap2,0.5,{
x:(s.imgWidth)*s.avatarNum * -1,
ease:Quad.easeIn,
onComplete:function(){
s.avatarNum = 0;
s.effect = null;
s.effectSprite.removeAllChild();
}
});
}
});
s.effectSprite.addChild(bitmap2);
}
break;
case LSkill.flicker:
if(s.flickerNum++ < 3){
LTweenLite.to(s,0.3,{
alpha:0.5,
ease:Quad.easeIn,
onComplete:function(){
LTweenLite.to(s,0.5,{
alpha:1,
ease:Quad.easeIn,
onComplete:function(){
s.effect = null;
s.flickerNum = 0;
}
});
}
});
}
break;
default:
trace("Error: LSkill has no property that named " + "'" + type + "'");
}
}

最后把DEMO呈现给大家,方便大家测试

Demo URL:http://www.cnblogs.com/yorhom/articles/3134031.html

六,源代码

人物类要实现的功能有很多,所以,代码也有些多,如下:

/**
*LCharacter.js
*/
function LCharacter(data,row,col,speed,isFighter){
var s = this;
base(s,LSprite,[]);
s.type = "LCharacter";
if(!speed)speed = 0;
if(isFighter == undefined)isFighter = false;
s.speed = speed;
s.speedIndex = 0;
s.x = 0;
s.y = 0;
s.mode = "";
s.index = 0;
if(isFighter == true){
s.hp = 0;
s.attack = 0;
s.defense = 0;
}
s.effect = null;
s.avatarNum = 0;
s.flickerNum = 0;
s.img = data;
s.row = row;
s.col = col;
s.effectSprite = new LSprite();
s.addChild(s.effectSprite);
s.nameSprite = new LSprite();
s.addChild(s.nameSprite);
var imgData = new LBitmapData(data);
imgData.setProperties(0,0,imgData.image.width/col,imgData.image.height/row);
var list = LGlobal.divideCoordinate(imgData.image.width,imgData.image.height,row,col);
s.imgWidth = imgData.image.width/col;
s.imgHeight = imgData.image.height/row;
s.anime = new LAnimation(s,imgData,list);
s.addEventListener(LEvent.ENTER_FRAME,function(){
if(s.effect != null){
s.showEffect(s,s.effect);
}
});
}
LCharacter.prototype.setData = function(data,row,col,speed,isFighter){
var s = this;
if(!speed)speed = 0;
if(isFighter == undefined)isFighter = false;
s.speed = speed;
s.img = data;
s.row = row;
s.col = col;
if(isFighter == true){
s.hp = 0;
s.attack = 0;
s.defense = 0;
}
var imgData = new LBitmapData(data);
imgData.setProperties(0,0,imgData.image.width/col,imgData.image.height/row);
var list = LGlobal.divideCoordinate(imgData.image.width,imgData.image.height,row,col);
s.imgWidth = imgData.image.width/col;
s.imgHeight = imgData.image.height/row;
s.removeChild(s.anime);
s.anime = new LAnimation(s,imgData,list);
}
LCharacter.prototype.addActionEventListener = function(type,listener){
var s = this;
s.anime.addEventListener(type,listener);
}
LCharacter.prototype.setAction = function(rowIndex,colIndex,mode,isMirror){
var s = this;
s.anime.setAction(rowIndex,colIndex,mode,isMirror);
}
LCharacter.prototype.getAction = function(){
var s = this;
var returnAction = s.anime.getAction();
return returnAction;
}
LCharacter.prototype.onframe = function(){
var s = this;
if(s.speedIndex++ < s.speed)return;
s.speedIndex = 0;
s.anime.onframe();
}
LCharacter.prototype.moveTo = function(x,y,timer,type,style,completefunc){
var s = this;
if(!timer)timer = 1;
if(!type)type = Quad.easeIn;
if(!style)style = LMoveStyle.direct; switch(style){
case LMoveStyle.direct:
var vars = {
x:x,
y:y,
ease:type,
onComplete:completefunc
};
LTweenLite.to(s,timer,vars);
break;
case LMoveStyle.horizontal:
LTweenLite.to(s,timer,{
x:x,
ease:type,
onComplete:function(){
LTweenLite.to(s,timer,{
y:y,
ease:type,
onComplete:completefunc
});
}
});
break;
case LMoveStyle.vertical:
LTweenLite.to(s,timer,{
y:y,
ease:type,
onComplete:function(){
LTweenLite.to(s,timer,{
x:x,
ease:type,
onComplete:completefunc
});
}
});
break;
default:
trace("Error: Value of last param is wrong!");
}
}
LCharacter.prototype.addName = function(name,style){
var s = this;
s.nameSprite.removeAllChild();
if(!name)name = 0;
if(!style)style = [];
if(!style[0])style[0] = 0;
if(!style[1])style[1] = 0;
if(!style[2])style[2] = "black";
if(!style[3])style[3] = "11";
if(!style[4])style[4] = "utf-8";
var nameText = new LTextField();
nameText.text = name;
nameText.x = style[0];
nameText.y = style[1];
nameText.color = style[2];
nameText.size = style[3];
nameText.font = style[4];
s.nameSprite.addChild(nameText);
}
LCharacter.prototype.showEffect = function(s,type){
switch(type){
case LSkill.avatar:
if(s.avatarNum++ < 3){
var nowImg = s.anime.getAction();
var nowY = nowImg[0];
var nowX = nowImg[1]; var bitmapData = new LBitmapData(s.img,nowX*s.imgWidth,nowY*s.imgHeight,s.imgWidth,s.imgHeight);
var bitmap = new LBitmap(bitmapData);
bitmap.x = 0;
bitmap.y = 0;
LTweenLite.to(bitmap,0.5,{
x:(s.imgWidth)*s.avatarNum,
alpha:0.2,
ease:Quad.easeIn,
onComplete:function(){
LTweenLite.to(bitmap,0.5,{
x:(s.imgWidth)*s.avatarNum,
ease:Quad.easeIn,
});
}
});
s.effectSprite.addChild(bitmap); var bitmapData2 = new LBitmapData(s.img,nowX*s.imgWidth,nowY*s.imgHeight,s.imgWidth,s.imgHeight);
var bitmap2 = new LBitmap(bitmapData2);
bitmap2.x = 0;
bitmap2.y = 0;
LTweenLite.to(bitmap2,0.5,{
x:(s.imgWidth)*s.avatarNum * -1,
alpha:0.2,
ease:Quad.easeIn,
onComplete:function(){
LTweenLite.to(bitmap2,0.5,{
x:(s.imgWidth)*s.avatarNum * -1,
ease:Quad.easeIn,
onComplete:function(){
s.avatarNum = 0;
s.effect = null;
s.effectSprite.removeAllChild();
}
});
}
});
s.effectSprite.addChild(bitmap2);
}
break;
case LSkill.flicker:
if(s.flickerNum++ < 3){
LTweenLite.to(s,0.3,{
alpha:0.5,
ease:Quad.easeIn,
onComplete:function(){
LTweenLite.to(s,0.5,{
alpha:1,
ease:Quad.easeIn,
onComplete:function(){
s.effect = null;
s.flickerNum = 0;
}
});
}
});
}
break;
default:
trace("Error: LSkill has no property that named " + "'" + type + "'");
}
}
var LMoveStyle = {
horizontal:"horizontal",
vertical:"vertical",
direct:"direct"
};
var LSkill = {
avatar:"LSkillAvatar",
flicker:"LSkillFlicker"
};

差不多引擎中的功能就这么多了,再看看有没有什么漏掉了。如果没有就可以发布了,敬请期待。

如何制作一款HTML5 RPG游戏引擎——第五篇,人物&人物特效的更多相关文章

  1. 如何制作一款HTML5 RPG游戏引擎——第四篇,情景对话

    今天我们来实现情景对话.这是一个重要的功能,没有它,游戏将变得索然无味.所以我们不得不来完成它. 但是要知道,使用对话可不是一件简单的事,因为它内部的东西很多,比如说人物头像,人物名称,对话内容... ...

  2. 如何制作一款HTML5 RPG游戏引擎——第三篇,利用幕布切换场景

    开言: 在RPG游戏中,如果有地图切换的地方,通常就会使用幕布效果.所谓的幕布其实就是将两个矩形合拢,直到把屏幕遮住,然后再展开直到两个矩形全部移出屏幕. 为了大家做游戏方便,于是我给这个引擎加了这么 ...

  3. 如何制作一款HTML5 RPG游戏引擎——第二篇,烟雨+飞雪效果

    今天我们来实现烟雨+飞雪效果.首先来说,一款经典的RPG游戏难免需要加入天气的变化.那么为了使我们的RPG游戏引擎更完美,我们就只好慢慢地实现它. 本文为该系列文章的第二篇,如果想了解以前的文章可以看 ...

  4. 如何制作一款HTML5 RPG游戏引擎——第一篇,地图类的实现

    一,话说天下大事 前不久看到lufy的博客上,有一位朋友想要一个RPG游戏引擎,出于兴趣准备动手做一做.由于我研究lufylegend有一段时间了,对它有一定的依赖性,因此就准备将这个引擎基于lufy ...

  5. HTML5 RPG游戏引擎 地图实现篇

    一,话说全国年夜事   前没有暂看到lufy的专客上,有一名伴侣念要一个RPG游戏引擎,出于兴趣筹办入手做一做.因为我研讨lufylegend有冶时间了,对它有必然的依赖性,因而便筹办将那个引擎基于 ...

  6. 用Html5结合Qt制作一款本地化EXE游戏-太空大战(Space War)

    本次来说一说如何利用lufylegend.js引擎制作一款html5游戏后将其通过Qt转换成EXE程序.步骤其实非常简单,接下来就一步步地做一下解释和说明. 首先我们来开发一个有点类似于太空大战的游戏 ...

  7. HTML5开源RPG游戏引擎lufylegendRPG 0.1发布

    一,小小开篇   首先不得不先介绍一下这个引擎: lufylegendRPG是lufylegend的拓展引擎,使用它时,需要引入lufylegend.同时您也需要了解lufylegend语法,这样才能 ...

  8. 推荐一些好用的 HTML5 & JavaScript 游戏引擎开发库

    推荐一些好用的 HTML5 & JavaScript 游戏引擎开发库 0. 引言 如果你是一个游戏开发者,并且正在寻找一个可以与 JavaScript 和 HTML5 无缝工作的游戏引擎.那么 ...

  9. 或许您还不知道的八款Android开源游戏引擎

    很多初学Android游戏开发的朋友,往往会显得有些无所适从,他们常常不知道该从何处入手,每当遇到自己无法解决的难题时,又往往会一边羡慕于iPhone下有诸如Cocos2d-iphone之类的免费游戏 ...

随机推荐

  1. Flowplayer-一款免费的WEB视频播放器(转)

    Flowplayer 是一个开源(GPL 3的)WEB视频播放器.您可以将该播放器嵌入您的网页中,如果您是开发人员,您还可以自由定制和配置播放器相关参数以达到您要的播放效果.本文主要介绍Flowpla ...

  2. 微信小程序 - mixins

    mixins 概念 可百度  参考 http://ask.seowhy.com/article/21007 大意和Python中的多重继承, java中的接口类似(java接口只是定义,实现需要子类自 ...

  3. Fastcgi_Finish_Request 提高页面响应速度

    当PHP运行在FastCGI模式时,PHP FPM提供了一个名为fastcgi_finish_request的方法.按照文档上的说法,此方法可以提高请求的处理速度,如果有些处理可以在页面生成完后再进行 ...

  4. HeadFirst Jsp 09 (JSTL)

    JSTL (jsp standard tag library) 标准标记库 JSTL 安装, 注意你的每一个项目都需要一个 JSTL副本, 并把它放在WEB-INF/lib 目录下, 在 Tomcat ...

  5. MapReduce总体架构分析

    转自:http://blog.csdn.net/Androidlushangderen/article/details/41051027 继前段时间分析Redis源码一段时间之后,我即将开始接下来的一 ...

  6. XML 是一种元语言, 可以用它来描述其他语言。

    A.正确 B.错误 解答:B XML(Extensible Markup Language)即可扩展标记语言,它与HTML一样,都是SGML(Standard Generalized Markup L ...

  7. Unity5.X 新版AssetBundle打包控制

    一.什么是AssetBundle 估计很多人只知道Unity的模型之类的东西可以导出成一种叫做AssetBundle的文件,然后打包后可以在Unity程序运行的时候再加载出来用.那么AssetBund ...

  8. pydoc介绍

    Ka-Ping Yee 曾创建了一个相当著名的模块,名叫 pydoc (比较而言: pydoc 可以做到 perldoc 所能做的任何事,并且做得更好.更漂亮:-).对于 Python 2.1 来说, ...

  9. nginx php文件上传的大小配置问题

  10. C#正则表达式操作中使用LINQ

    比如:[程序员][代码]博客园 - 程序员的网上家园,代码改变世界 提取出来的Tag应该是:[程序员].[代码] Regex _regexTag = new Regex(@"^(\[[^\] ...