之前写的小游戏,要么就比较简单,要么就是比较难看,或者人物本身是不会动的。
结合了其它人的经验,研究了一下精灵运动,就写一个简单的小游戏来试一下。
介绍一下几个主要的类
:
- Frame:帧的定义,主要描述动画的一帧
- Animation:动画的定义,主要描述一个连贯的动画,由多个帧组成
- Sprite:精灵的定义,主要描述一个完整的实体,由多个动画组成
- TimeProcess:时间管理,由
requestAnimationFrame
完成 - Person:一个完整人定义,就是主人公--
男人
- BlockBase:块的基类,下降中的障碍物基类,包含一些基本的参数与方法
- NormalBlock:普通块,继承于
BlockBase
,最基础的块 - MissBlock,LeftBlock...等:其它特殊功能的块
- BlockFactory:块工厂,生产块的类
- Main:游戏主入口
游戏的文件结构
:
- wfn.js:基础文件,包含动画定义,公共方法(都是比较简单的)
- person.js:人物的定义
- block.js:各种障碍物块的定义
- main.js:游戏主逻辑入口文件,处理主要逻辑
游戏的文件结构
:
TimeProcess:主要用于统一处理定时器的事件,确保全局只有一个计时器
//定义贞管理类,兼容
var requestAnimationFrame = window.requestAnimationFrame
|| window.mozRequestAnimationFrame
|| window.webkitRequestAnimationFrame
|| function(cb){setTimeout(cb,1000/60)}; var TimeProcess = function(){ this.list = [];
this.isStart = false;
}
TimeProcess.prototype = { add : function(cb,param,context){ this.list.push({cb:cb,param:param,context:context});
},
start : function(){ this.isStart = true; var self = this; requestAnimationFrame(function(){ var item = null,
p = []; for(var i=0;i<self.list.length;i++){ item = self.list[i]; item.cb.apply(item.context,item.param);
} if(self.isStart)requestAnimationFrame(arguments.callee);
});
},
stop : function(){ this.isStart = false;
}
}
Frame:帧的定义,就类似flash中的帧
//帧的定义
/**
@param x int 帧在雪碧图中的起始x坐标
@param y int 帧在雪碧图中的起始y坐标
@param w int 帧在雪碧图中的宽
@param y int 帧在雪碧图中的高
@param dw int 帧实际的宽
@param dh int 帧实际的高
*/
var Frame = function(x,y,w,h,dw,dh){ this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.dw = dw;
this.dh = dh;
}
Animation:动画的定义,一个动作需要多个连贯的帧才能完成
//一个动画得定义
var Animation = function(param) { this.startX = param.startX || 0;
this.startY = param.startY || 0;
this.fs = param.fs || 1;
this.sw = param.sw || 0;
this.sh = param.sh || 0;
this.width = param.width || param.sw;
this.height = param.height || param.sh;
this.dir = param.dir || "right";
this.loop = !!param.loop;
//this.fps = param.fps || 30; //this.lazy = 1000 / this.fps;
//this.last = 0; this.ls = [];
//当前帧
this.current = null;
//当前帧得索引
this.index = -1; this.init();
}
Animation.prototype = {
init : function(){ for(var i=0;i<this.fs;i++){ var x = this.startX + (this.dir=="right"?i*this.sw:0);
var y = this.startY + (this.dir=="down"?i*this.sh:0); var frame = new Frame(x,y,this.sw,this.sh,this.width,this.height); this.ls.push(frame);
} this.index = 0;
this.current = this.ls[0];
},
//下一帧
next : function() { if(this.index + 1 >= this.ls.length){ if(this.loop){ this.current = this.ls[0];
this.index = 0;
}
}
else{ this.index += 1; this.current = this.ls[this.index];
}
},
//重置为第一帧
reset : function(){ this.current = this.ls[0];
this.index = 0;
},
size : function(){ return {w:this.width,h:this.height};
}
}
Sprite:精灵的定义,一个完整的个体,是需要多个动画,例如向左,向右等
//一个精灵的定义
/**
@param objParam object 动画的json对象 {"left":[frame1,frame2],"right":[frame1,frame2]}
@param def string 默认动画索引
@param img object 精灵得雪碧图
@param cxt object canvas对象
@param x int 精灵的起始位置x
@param y int 精灵的起始位置y
*/
var Sprite = function(img,cxt,fps,param){ this.animations = {};
this.img = img;
this.cxt = cxt;
this.x = param.x || 0;
this.y = param.y || 0;
this.fps = fps; this.xspeed = param.xspeed || 0;
this.yspeed = param.yspeed || 0; this.yaspeed = param.yaspeed || 0; this.lazy = 1000 / this.fps;
this.last = 0; this.moveLazy = 33;
this.moveLast = 0; //当前动画
this.index = null; this.key = "";
}
Sprite.prototype = {
add : function(key,animation){ this.animations[key] = animation; if(!this.index){
this.index = animation;
this.key = key;
}
},
//修改当前动画
change : function(key){ if(key == this.key)return false; var index = this.animations[key]; if(!index)return false; this.index = index;
this.okey = this.key;
this.key = key;
this.index.reset();
},
//绘画出当前帧
draw : function(){ if(!this.index || !this.img)return false; var frame = this.index.current; this.cxt.drawImage(this.img,frame.x,frame.y,frame.w,frame.h,this.x,this.y,frame.dw,frame.dh);
},
//更新精灵
update : function(){ var t = new Date().getTime(); var diff = t - this.last; var moveDiff = t - this.moveLast; if(this.last == 0){
diff = this.lazy;
moveDiff = this.moveLazy;
} if(diff >= this.lazy){ this.index.next(); this.last = t;
} if(moveDiff >= this.moveLazy){ if(this.yaspeed)this.yspeed += this.yaspeed; if(this.xspeed)this.x += this.xspeed;
if(this.yspeed)this.y += this.yspeed; this.moveLast = t;
}
},
//移动
move : function(x,y){ this.x = x;
this.y = y;
},
setXSpeed : function(xs){ this.xspeed = xs;
},
setYSpeed : function(ys,yas){ this.yspeed = ys;
this.yaspeed = yas || 0;
},
//获取当前精灵得大小
size : function(){ var frame = this.index.current; return {w:frame.dw,h:frame.dh,x:this.x,y:this.y,r:this.x+frame.dw,b:this.y+frame.dh};
}
}
下面是游戏试玩:
键盘左右控制移动,界面上的按钮是给iphone触屏用,图片全面兼容iphone4的retina,可以直接放在phonegap中使用!
完整源码猛击:下载
PS:bug这种玩意,是肯定会有的了。。。大家就见谅吧。。