本文基于lufylegend游戏引擎,所以以下内容全部和此有关,
lufylegend引擎的下载地址: http://www.lufylegend.com/lufylegend
既然是使用引擎,首先就要配置引擎的开发环境,lufylegend的使用极其方便,只需将lufylegend-x.x.x.min.js文件引入即可,默认将legend文件夹放入当前文件路径中,如下方所示,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>LTileMap</title>
<script type="text/javascript" src="lufylegend.js-lufylegend-1.9.7/lufylegend-1.9.7.min.js"></script>
此时即可开始使用lufylegend开始我们的游戏之旅
一、初始化引擎
加载引擎后,就需要对环境初始化,lufylegend的初始化需要使用引擎中提供的函数init(30,"legend",500,400,main);
第一个参数为刷新频率,也就是多久对屏幕刷新一次
第二个参数为需要初始化的html中的div的id,这也是lufylegend的优点之一
第三个参数为窗口的长
第四个参数为窗口的宽
第五个参数为初始化时调用的函数
二、游戏的图层
既然是游戏,那么图层就必不可少,对于本次游戏来说会分成地图层,也就是载入地图的层次,人物层,也就是载入人物的图层,金币层,也就是载入掉落的金币的图层,游戏结束层,也就是游戏结束时所调用的图层,时间层,也就是载入倒数计时的图层,分数层,查看分数的图层,游戏结束图层,也就是游戏结束时调用的图层
总的来说本次游戏开发会分成地图层,人物图层,金币层,时间层,分数层,游戏结束层这6个图层,所以就需要先定义这6个图层,定义的代码如下
var backLayer,maplayer ,timelayer,playerlayer,moneylayer,pointlayer,gameoverLayer;
定义好之后就需要在main函数中于初始化过程中将图层全部载入,另外需要注意的是图层的顺序,地图层要在最下面,否则会遮住其他图层,而导致其他图层出现显示不出的情况,在lufylegend中是根据图层加入的顺序来决定谁在最下方,也就是先加入的就是最下面的图层,之后以此类推,所以init函数就需要这样定义
function gameinit(result){//移除loading
removeChild(loadingLayer);
//初始化分数
point=0;
imglist=result
//加入backlayer背景层
backLayer = new LSprite();
addChild(backLayer);
//加入地图层
maplayer= new LSprite();
backLayer.addChild(maplayer);
//加入timelayer时间层
timelayer= new LTime(1);
timelayer.x=340;
timelayer.y=0;
backLayer.addChild(timelayer);
//加入人物层
playerlayer= new LSprite();
backLayer.addChild(playerlayer);
//加入金币层
moneylayer= new LSprite();
backLayer.addChild(moneylayer);
//加入分数层
pointLayer= new LSprite();
backLayer.addChild(pointLayer);
//加入游戏结束层
gameoverLayer = new LSprite();
backLayer.addChild(gameoverLayer);
//初始化游戏
gamestart();
}
其中LSprite为lufylegend所提供的精灵类,此类可以实现载入图片,以及绘制各种图形,具体的参数可以参考API:http://lufylegend.com/api/zh_CN/out/index.html,而LTime则是由自己实现的LTime类作用是为了实现倒计时的运算和显示,具体的函数如下:
function LTime(min){
var s=this;
base(s,LSprite,[]);
s.x=1;
s.y=1;
s.time=min;
leftTime=s.time*60*1000;
time=new LTextField();
time.x=25;
time.y=10
time.size=15;
time.color="#ffD700";
s.onshow();
//s.onframe();
}
LTime为此类的构造函数,可以很清楚地看出此类继承自LSprite类,因此也具有精灵类的所有特性,在此基础上添加了一个用以显示倒计时的文字区域,x,y为文字起始位置的坐标,需要注意的是这里的x,y并不是针对整个游戏的坐标系来说的,而是针对所在类来看,如下图:
构造函数之后就是倒计时的实现了,大致上的实现是用类似UNIX时间戳的形式,需要注意的只有lefttime需要减去的值,正常情况下直接减去真实时间即可,但这样就和游戏的刷新率有冲突,会导致时间的跳动,所以在这里需要按照游戏的刷新率来减去时间,也就是说我们需要减去的时间为游戏的刷新率即init函数中的第一个参数,这样才能在每一次刷新时显示正确且连贯的时间
LTime.prototype.onframe=function(){
//var s=this;
minutes=Math.floor(leftTime/1000/60);
second=Math.floor(leftTime/1000-60*minutes);
millsecond=Math.floor(leftTime-60*minutes*1000-1000*second);
mill=Math.floor(millsecond/10);
if(second<10){
second="0"+second;
}
if(mill<10){
mill="0"+mill;
}
time.text="Time:"+minutes+":"+second+":"+mill;
if(leftTime>0){
leftTime -= 1000*60/(1000*60/30);
}else{
return false;
}
}
在这之后就可以得到一个漂亮的倒计时显示了
三,绘制游戏
只是载入图层而不向图层中添加东西,获得的只会是一个空白的画面,所以在载入所需的图片和插入图层后就需要绘制游戏的画面,也就是需要向各个精灵类中添加载入的图片和绘制图形,下面就是绘制函数gamestart。
//开始绘制游戏界面
function gamestart(result){
//加入地图
var bitmapData=new LBitmapData(imglist['map']);
var bitmap=new LBitmap(bitmapData);
maplayer.addChild(bitmap);
//加入人物图片
anima=new LCharcter(imglist['cr']);
playerlayer.addChild(anima);
//timelayer.addChild(time);
//加入记分牌
pointtext=new LTextField();
pointtext.x=0;
pointtext.y=360;
pointtext.size=15;
pointtext.color="#ffD700";
pointLayer.addChild(pointtext);
//加入动画和按键事件监听
backLayer.addEventListener(LEvent.ENTER_FRAME,onframe);
LEvent.addEventListener(LGlobal.window, LKeyboardEvent.KEY_DOWN,move);
LEvent.addEventListener(LGlobal.window, LKeyboardEvent.KEY_UP,stop);
}
在这里要说的是LCharcter类,这个类是自己实现的类,是为了实现人物的载入和移动,下面是主要函数的介绍,首先可以看出此类依然继承自LSprite类,接下来需要关注的就是lufylegend引擎提供的Lanimation类,这个类的主要作用是讲类似下图的图片依次载入,从而实现动画效果,在这里在入的图片就是8方向的人物行走图,通过动画类就可以实现人物的行走效果了,关于此类的应用也可以直接参照引擎的API
function LCharcter(imgdata){
var s=this;
base(s,LSprite,[]);
s.x=200;
s.y=100;
s.imgdata=imgdata;
var list=LGlobal.divideCoordinate(640,728,8,8);
bitmapData=new LBitmapData(s.imgdata);
s.width=bitmapData.width/8;
s.height=bitmapData.height/8;
player= new LAnimation(s,bitmapData,list);
player.setAction(0,1,1,false);
s.addChild(player);
}
下为移动内的实现,需要注意的仅是在第一次按下方向键时才设置帧序列的位置,否则会不断设置序列,导致人物无法正确表现跑步动画,所以在这里使用了4个计数器,来记录按键次数,避免在第二次按下时仍然设置序列位置
LCharcter.prototype.move=function(moveto){
//仅设置一次action避免重复设置导致图形不断重置
var s=this;
if(moveto==40){
if(down==0){
player.setAction(0,1,1,false);
down++;
}
if(s.y<400-bitmapData.height){
s.y=s.y+speed;
}
}else if(moveto==39){
if(left==0){
player.setAction(2,1,1,false);
left++;
}
if(s.x<500-bitmapData.width){
s.x=s.x+speed;
}
}else if(moveto==38){
if(up==0){
player.setAction(3,1,1,false);
up++;
}
if(s.y>0){
s.y=s.y-speed;
}
}else if(moveto==37){
if(right==0){
player.setAction(1,1,1,false);
right++;
}
if(s.x>0){
s.x=s.x-speed;
}
}
s.addEventListener(LEvent.ENTER_FRAME,s.onmove);
}
之后需要注意的就是碰撞检测的函数,函数目的就是为了检测是否与金币碰撞,从而计分的目的,在这里我仅使用了最简单的碰撞检测,也就是长方形的交错检测,长方形检测仅需要判断一下,两个长方形是否有交叠即可,交叠一般可以用4种情况来判断,在上方,在左方,在右方,在下方,下面有4个图可以表示这4中情况的碰撞
上面的图片显示的均是未碰撞的条件,所以反过来说也就是除了上述条件以外全都是发生了碰撞,所以碰撞函数的写法就可以确定了
LCharcter.prototype.CheckContact=function(money){
var s=this;
//money在右侧
if((s.x>money.x)&&(money.x+money.width<s.x)){
return false;
//money在左侧
}else if((s.x<money.x)&&(s.x+s.width<money.x)){
return false;
//money在下测
}else if((s.y<money.y)&&(s.y+s.height<money.y)){
return false;
//money在上测
}else if((s.y>money.y)&&(money.y+money.height<s.y)){
return false;
}else{
money.mode="die";
return true;
}
}
到这里基本需要使用的函数定义和画面的组成就介绍完毕了,下面需要考虑的就是游戏的运行
四,游戏的运行
游戏的运行需要基于刷新率来运行,也就是通过这个刷新率来实现游戏的动画效果,所以需要编写基于屏幕刷新事件而运行的函数,因为是基于事件运行的函数,所以就需要添加对屏幕刷新事件的监视器,添加方法:backLayer.addEventListener(LEvent.ENTER_FRAME,onframe);第一个参数为事件名,第二个参数是在事件发生时所调用的函数名,在这里的函数为onframe,可以看出在onframe函数中,需要对几个参数进行刷新,一个是分数,一个是倒计时的刷新,一个是对金币位置和数量的刷新,和对金币精灵死亡后将其移出画面,总共需要做这4个操作,所以onframe函数就需要这样写
function onframe(){
//刷新分数
pointtext.text="得分:"+point;
if(startflag==true){
var result=timelayer.onframe();
//刷新金币
addmoney();
if(result==false){
playerlayer.die();
//backLayer.die();
gameover();
}
for(i=0;i<moneylayer.childList.length;i++){
//让金币动起来
moneylayer.childList[i].run();
if(anima.CheckContact(moneylayer.childList[i])==true){
point++;
}
if(moneylayer.childList[i].mode == "die"){ //当金币移出屏幕或是与人物碰撞时……
//移除该成员
moneylayer.removeChild(moneylayer.childList[i]);
totalmoney++;
}
}
}
}
这样一个简单的游戏就编写出来了,附上游戏画面:
源码地址:http://pan.baidu.com/s/1eQ6cbVO