HTML5小游戏【是男人就下一百层】UI美化版
之前写的小游戏,要么就比较简单,要么就是比较难看,或者人物本身是不会动的。
结合了其它人的经验,研究了一下精灵运动,就写一个简单的小游戏来试一下。
介绍一下几个主要的类
:
- Frame:帧的定义,主要描述动画的一帧
- Animation:动画的定义,主要描述一个连贯的动画,由多个帧组成
- Sprite:精灵的定义,主要描述一个完整的实体,由多个动画组成
- TimeProcess:时间管理,由
requestAnimationFrame
完成 - Person:一个完整人定义,就是主人公--
男人
- BlockBase:块的基类,下降中的障碍物基类,包含一些基本的参数与方法
- NormalBlock:普通块,继承于
BlockBase
,最基础的块 - MissBlock,LeftBlock...等:其它特殊功能的块
- BlockFactory:块工厂,生产块的类
- Main:游戏主入口
游戏的文件结构
:
- wfn.js:基础文件,包含动画定义,公共方法(都是比较简单的)
- person.js:人物的定义
- block.js:各种障碍物块的定义
- main.js:游戏主逻辑入口文件,处理主要逻辑
游戏的文件结构
:
TimeProcess:主要用于统一处理定时器的事件,确保全局只有一个计时器
1 //定义贞管理类,兼容 2 var requestAnimationFrame = window.requestAnimationFrame 3 || window.mozRequestAnimationFrame 4 || window.webkitRequestAnimationFrame 5 || function(cb){setTimeout(cb,1000/60)}; 6 7 var TimeProcess = function(){ 8 9 this.list = []; 10 this.isStart = false; 11 } 12 TimeProcess.prototype = { 13 14 add : function(cb,param,context){ 15 16 this.list.push({cb:cb,param:param,context:context}); 17 }, 18 start : function(){ 19 20 this.isStart = true; 21 22 var self = this; 23 24 requestAnimationFrame(function(){ 25 26 var item = null, 27 p = []; 28 29 for(var i=0;i<self.list.length;i++){ 30 31 item = self.list[i]; 32 33 item.cb.apply(item.context,item.param); 34 } 35 36 if(self.isStart)requestAnimationFrame(arguments.callee); 37 }); 38 }, 39 stop : function(){ 40 41 this.isStart = false; 42 } 43 }
Frame:帧的定义,就类似flash中的帧
1 //帧的定义 2 /** 3 @param x int 帧在雪碧图中的起始x坐标 4 @param y int 帧在雪碧图中的起始y坐标 5 @param w int 帧在雪碧图中的宽 6 @param y int 帧在雪碧图中的高 7 @param dw int 帧实际的宽 8 @param dh int 帧实际的高 9 */ 10 var Frame = function(x,y,w,h,dw,dh){ 11 12 this.x = x; 13 this.y = y; 14 this.w = w; 15 this.h = h; 16 this.dw = dw; 17 this.dh = dh; 18 }
Animation:动画的定义,一个动作需要多个连贯的帧才能完成
1 //一个动画得定义 2 var Animation = function(param) { 3 4 this.startX = param.startX || 0; 5 this.startY = param.startY || 0; 6 this.fs = param.fs || 1; 7 this.sw = param.sw || 0; 8 this.sh = param.sh || 0; 9 this.width = param.width || param.sw; 10 this.height = param.height || param.sh; 11 this.dir = param.dir || "right"; 12 this.loop = !!param.loop; 13 //this.fps = param.fps || 30; 14 15 //this.lazy = 1000 / this.fps; 16 //this.last = 0; 17 18 this.ls = []; 19 //当前帧 20 this.current = null; 21 //当前帧得索引 22 this.index = -1; 23 24 this.init(); 25 } 26 Animation.prototype = { 27 init : function(){ 28 29 for(var i=0;i<this.fs;i++){ 30 31 var x = this.startX + (this.dir=="right"?i*this.sw:0); 32 var y = this.startY + (this.dir=="down"?i*this.sh:0); 33 34 var frame = new Frame(x,y,this.sw,this.sh,this.width,this.height); 35 36 this.ls.push(frame); 37 } 38 39 this.index = 0; 40 this.current = this.ls[0]; 41 }, 42 //下一帧 43 next : function() { 44 45 if(this.index + 1 >= this.ls.length){ 46 47 if(this.loop){ 48 49 this.current = this.ls[0]; 50 this.index = 0; 51 } 52 } 53 else{ 54 55 this.index += 1; 56 57 this.current = this.ls[this.index]; 58 } 59 }, 60 //重置为第一帧 61 reset : function(){ 62 63 this.current = this.ls[0]; 64 this.index = 0; 65 }, 66 size : function(){ 67 68 return {w:this.width,h:this.height}; 69 } 70 }
Sprite:精灵的定义,一个完整的个体,是需要多个动画,例如向左,向右等
1 //一个精灵的定义 2 /** 3 @param objParam object 动画的json对象 {"left":[frame1,frame2],"right":[frame1,frame2]} 4 @param def string 默认动画索引 5 @param img object 精灵得雪碧图 6 @param cxt object canvas对象 7 @param x int 精灵的起始位置x 8 @param y int 精灵的起始位置y 9 */ 10 var Sprite = function(img,cxt,fps,param){ 11 12 this.animations = {}; 13 this.img = img; 14 this.cxt = cxt; 15 this.x = param.x || 0; 16 this.y = param.y || 0; 17 this.fps = fps; 18 19 this.xspeed = param.xspeed || 0; 20 this.yspeed = param.yspeed || 0; 21 22 this.yaspeed = param.yaspeed || 0; 23 24 this.lazy = 1000 / this.fps; 25 this.last = 0; 26 27 this.moveLazy = 33; 28 this.moveLast = 0; 29 30 //当前动画 31 this.index = null; 32 33 this.key = ""; 34 } 35 Sprite.prototype = { 36 add : function(key,animation){ 37 38 this.animations[key] = animation; 39 40 if(!this.index){ 41 this.index = animation; 42 this.key = key; 43 } 44 }, 45 //修改当前动画 46 change : function(key){ 47 48 if(key == this.key)return false; 49 50 var index = this.animations[key]; 51 52 if(!index)return false; 53 54 this.index = index; 55 this.okey = this.key; 56 this.key = key; 57 this.index.reset(); 58 }, 59 //绘画出当前帧 60 draw : function(){ 61 62 if(!this.index || !this.img)return false; 63 64 var frame = this.index.current; 65 66 this.cxt.drawImage(this.img,frame.x,frame.y,frame.w,frame.h,this.x,this.y,frame.dw,frame.dh); 67 }, 68 //更新精灵 69 update : function(){ 70 71 var t = new Date().getTime(); 72 73 var diff = t - this.last; 74 75 var moveDiff = t - this.moveLast; 76 77 if(this.last == 0){ 78 diff = this.lazy; 79 moveDiff = this.moveLazy; 80 } 81 82 if(diff >= this.lazy){ 83 84 this.index.next(); 85 86 this.last = t; 87 } 88 89 if(moveDiff >= this.moveLazy){ 90 91 if(this.yaspeed)this.yspeed += this.yaspeed; 92 93 if(this.xspeed)this.x += this.xspeed; 94 if(this.yspeed)this.y += this.yspeed; 95 96 this.moveLast = t; 97 } 98 }, 99 //移动 100 move : function(x,y){ 101 102 this.x = x; 103 this.y = y; 104 }, 105 setXSpeed : function(xs){ 106 107 this.xspeed = xs; 108 }, 109 setYSpeed : function(ys,yas){ 110 111 this.yspeed = ys; 112 this.yaspeed = yas || 0; 113 }, 114 //获取当前精灵得大小 115 size : function(){ 116 117 var frame = this.index.current; 118 119 return {w:frame.dw,h:frame.dh,x:this.x,y:this.y,r:this.x+frame.dw,b:this.y+frame.dh}; 120 } 121 }
下面是游戏试玩:
键盘左右控制移动,界面上的按钮是给iphone触屏用,图片全面兼容iphone4的retina,可以直接放在phonegap中使用!
完整源码猛击:下载
PS:bug这种玩意,是肯定会有的了。。。大家就见谅吧。。