Html5小游戏之【是男人就忍30秒】

好久没写过小游戏了,最近抽时间写了一个,看了一些高人写的游戏,无限感慨呀。。。也从中学到了不少东西。

我不会写什么大的游戏,因为需要很多时间与精力,而且自认水平有限,个人喜欢写些小游戏。

这次的游戏是【是男人就忍30秒】,游戏玩法很简单,就是用键盘控制飞机,飞来飞去,躲开子弹,看你能撑多久。

本来是打算写一个教程来一步步说明的,但后来想了想,还是算了,免得误人子弟,在源码上加些注释就可以。

 

没有测试过IE9,因为没有IE9。。。鄙人还是用XP的。。。所以还是请用谷歌或者FF或者Safari吧。

 

刚刚修复了在FF下不能使用的问题,因为没给canvas设置tabindex属性,它就不能触发keydown事件,以及设置canvas为focus,现在可以了。。。 

 

游戏预览如下:

请使用chrome,safari,ff

 

此游戏用了四个js文件。

1。canvas.js,简单了封装了一些需要用到的画图方法,相信一看就懂了。。。

 

 1 //画布类
 2 var Canvas = {
 3     //画布的2d对象
 4     cxt : null,
 5     //初始化画布
 6     init : function(id){
 7         this.cxt = (typeof id=='string'?document.getElementById(id):id).getContext('2d');
 8     },
 9     //清除画布
10     clear : function(x,y){
11         this.cxt.clearRect(0,0,x,y);
12     },
13     //画图
14     drawImg : function(obj){
15         this.cxt.drawImage(obj.img,obj.x,obj.y);
16     },
17     //画文字
18     drawText : function(string,x,y,color){
19         
20         this.cxt.fillStyle = color;
21         this.cxt.font = 'bold 14px sans-serif';
22         this.cxt.fillText(string,x,y);
23     },
24     //加载图片
25     //imgs:图片对象的数组
26     //callback:回调函数
27     //context:上下文对象
28     loadImgs : function(imgs,callback,context){
29     
30         var success_count = 0;
31         
32         var addCount = function(){
33             success_count += 1;
34             
35             if(success_count == l)callback && callback.call(context);
36         }
37         
38         for(var i=0,l=imgs.length;i<l;i++){
39             imgs[i].onload = addCount;
40         }
41         
42     }
43 }

 

 

2。fly.js,飞机类,采用在计时器中移动,而非一般的键盘按一下就移动一格,这样做,控制得更流畅,而且,可以支持打斜飞。

 

 1 var Fly = function(img,x,y){
 2     //飞机的图片
 3     this.img = img;
 4     //飞机的坐标
 5     this.x = x;
 6     this.y = y;
 7     //飞机的移动方向值
 8     this.moveDir = {
 9         left:false,
10         right:false,
11         up:false,
12         down:false
13     };
14     //移动的速度
15     this.movesp = 2;
16 }
17 Fly.prototype = {
18     //键盘码对应移动方向
19     keyCode2Dir : {
20         37:'left',
21         38:'up',
22         39:'right',
23         40:'down'
24     },
25     //键盘按下事件
26     //keyCode:键盘码
27     keyDown : function(keyCode){
28         //修改对应的移动值
29         this.moveDir[this.keyCode2Dir[keyCode]]=true;
30     },
31     //键盘释放事件
32     //keyCode:键盘码
33     keyUp : function(keyCode){
34         //修改对应的移动值
35         this.moveDir[this.keyCode2Dir[keyCode]]=false;
36     },
37     //判断是否在移动中
38     checkMove : function(){
39         if(this.moveDir.left || this.moveDir.right || this.moveDir.up || this.moveDir.down)return true;
40         return false;    
41     },
42     //移动
43     //gameInfo:游戏背景信息
44     move : function(gameInfo){
45         
46         var This = this;
47         //根据方向来移动
48         if(This.moveDir.left)This.x -= This.movesp;
49         if(This.moveDir.right)This.x += This.movesp;
50         if(This.moveDir.up)This.y -= This.movesp;
51         if(This.moveDir.down)This.y += This.movesp;
52         //边界值检测
53         if(This.x <0)This.x=0;
54         else if(This.x >gameInfo.width-This.img.width)This.x = gameInfo.width-This.img.width;
55         if(This.y <0)This.y=0;
56         else if(This.y >gameInfo.height-This.img.height)This.y = gameInfo.height-This.img.height;
57     }
58 
59 }

 

 

3。bullet.js,子弹类,子弹的飞,我承认,确实做得很简单,希望大家自己改进这个算法。。。

 

 1 var Bullet = function(img){
 2     //子弹的图片
 3     this.img = img;
 4     //X坐标
 5     this.x = 0;
 6     //Y坐标
 7     this.y = 0;
 8     //子弹要飞的x与y的速度
 9     this.arc = {};
10     //移动的帧数
11     this.moveFps = 20;
12     //帧数延迟
13     this.moveFpsLazy = 0;
14     //初始化
15     this.init();
16 }
17 Bullet.prototype = {
18     //方向数组
19     arrDir : ['left','right','up','down'],
20     //初始化
21     init : function(){
22         //最小位置
23         var min = 5,
24             //最大位置
25             max = 395,
26             //随机位置
27             rnd = Math.floor(Math.random()*370+10),
28             //移动方向
29             dir = this.arrDir[Math.floor(Math.random()*4)];
30         
31         //设置子弹的初始位置与将要飞的方向与速度    
32         switch(dir){
33             case 'left':{
34                 this.x = max;
35                 this.y = rnd;
36                 if(this.y>=max/2)this.arc = {x:-5,y:-2};
37                 else this.arc={x:-5,y:2};
38                 break;
39             }
40             case 'right':{
41                 this.x = min;
42                 this.y = rnd;
43                 if(this.y>=max/2)this.arc = {x:5,y:-2};
44                 else this.arc={x:5,y:2};
45                 break;
46             }
47             case 'up':{
48                 this.y = max;
49                 this.x = rnd;
50                 if(this.x>=max/2)this.arc = {x:-3,y:-5};
51                 else this.arc={x:3,y:-5};
52                 break;
53             }
54             case 'down':{
55                 this.y = min;
56                 this.x = rnd;
57                 if(this.x>=max/2)this.arc = {x:-3,y:5};
58                 else this.arc={x:3,y:5};
59                 break;
60             }
61         }
62     },
63     //更新子弹数据
64     //gameInfo:游戏背景信息
65     updata : function(gameInfo){
66         //延迟+10
67         this.moveFpsLazy += 10;
68         //判断延迟是否等于移动帧数
69         if(this.moveFpsLazy == this.moveFps){
70             //移动
71             this.x += this.arc.x;
72             this.y += this.arc.y;
73             //边界值检测
74             if(this.x <0 || this.x > gameInfo.width || this.y <0 || this.y > gameInfo.height){
75                 this.callback();
76                 return false;
77             }
78             //清0
79             this.moveFpsLazy = 0;
80         }
81     },
82     //检测是否撞到飞机
83     //fly:飞机对象
84     checkCrashFly : function(fly){
85         //获取子弹与飞机的圆心坐标
86         var bx = this.x+this.img.width/2,by = this.y+this.img.height/2,
87             fx = fly.x+fly.img.width/2,fy = fly.y+fly.img.height/2;
88         //判断圆心距
89         if(Math.sqrt(Math.pow(bx-fx,2)+Math.pow(by-fy,2)) < (fly.img.width/2+this.img.width/2)){
90             return true;
91         }
92         return false;
93     },
94     //回调函数
95     callback : function(){}
96 
97 }

 

 

4。Game.js,游戏控制类,主要控制游戏的逻辑

 

  1 var Game = {
  2     //游戏背景数据,主要是宽与高
  3     gameInfo :{width:0,height:0},
  4     //飞机对象
  5     fly : null,
  6     //子弹对象数组
  7     bullets : [],
  8     //子弹图片
  9     bulletImg : null,
 10     //子弹产生的延迟
 11     bulletLazyFps : 0,
 12     //绘画处理计时器ID
 13     processId : 0,
 14     //分数
 15     score : 0,
 16     //是否开始
 17     isStart : false,
 18     //显示开始信息
 19     showStart : function(){
 20         
 21         var This = this;
 22         //画开始字
 23         Canvas.drawText("Press Enter to Start!",120,200,'white');
 24         //绑定事件
 25         document.body.onkeydown = function(e){This.keyDown(e);};
 26         document.body.onkeyup = function(e){This.keyUp(e);};
 27     },
 28     //游戏初始化
 29     init : function(){
 30         //设置游戏背景信息
 31         var gameBg = document.getElementById('js_canvas');
 32         this.gameInfo.width = gameBg.offsetWidth;
 33         this.gameInfo.height = gameBg.offsetHeight;
 34         //初始化画布
 35         gameBg.focus();Canvas.init(gameBg);
 36         //设置飞机图片与子弹图片
 37         var flyImg = new Image();
 38         var bulletImg = new Image();
 39         flyImg.src = "img/fly.gif";
 40         bulletImg.src = "img/bullet.gif";
 41         //加载图片,成功后,回调显示开始信息
 42         Canvas.loadImgs([flyImg,bulletImg],this.showStart,this);
 43         //设置飞机对象
 44         this.fly = new Fly(flyImg,200,200);
 45         //设置Game子弹图片
 46         this.bulletImg = bulletImg;
 47     },
 48     //生成子弹
 49     createBullets : function(){
 50         
 51         var This = this;
 52         //判断延时是否200
 53         if(this.bulletLazyFps == 200){
 54             //创建子弹,添加到数组中
 55             var bullet = new Bullet(this.bulletImg);
 56             bullet.callback = function(){
 57                 This.removeBullet(this);
 58             }
 59             
 60             this.bullets.push(bullet);
 61             this.bulletLazyFps = 0;
 62         }
 63         else{
 64             this.bulletLazyFps += 10;
 65         }
 66     },
 67     //开始
 68     start : function(){
 69         
 70         var This = this;
 71         //重置数据
 72         this.reset();
 73         //设置开始
 74         this.isStart = true;
 75         //开始绘画
 76         this.process();
 77         
 78     },
 79     //重置数据
 80     reset : function(){
 81         
 82         this.score = 0;
 83         this.bullets = [];
 84     },
 85     //结束
 86     end : function(){
 87         
 88         this.isStart = false;
 89         
 90         clearInterval(this.processId);
 91         
 92         this.showStart();
 93     },
 94     //绘画函数
 95     process : function(){
 96         
 97         var This = this;
 98         //绘画计时器
 99         this.processId = setInterval(function(){
100             
101             if(!This.isStart)return;
102             //清除画布
103             Canvas.clear(This.gameInfo.width,This.gameInfo.height);
104             //判断飞机是否移动
105             if(This.fly.checkMove())This.fly.move(This.gameInfo);
106             //画飞机
107             Canvas.drawImg(This.fly);
108             //生产子弹
109             This.createBullets();
110             //画出所有子弹
111             for(var i=0,l=This.bullets.length;i<l;i++){
112                 
113                 var bullet = This.bullets[i];
114                 
115                 if(!bullet)continue;
116                 //更新子弹信息
117                 bullet.updata(This.gameInfo);
118                 //画子弹
119                 Canvas.drawImg(bullet);
120                 //检测是否撞到飞机
121                 if(bullet.checkCrashFly(This.fly)){
122                     This.end();
123                 }
124             }
125             //画分数
126             Canvas.drawText(Math.floor(This.score/1000)+"秒",20,20,'white');
127             This.score += 10;
128         },10);
129     },
130     //键盘按下事件
131     keyDown : function(e){
132         
133         var This =this;
134         //游戏还没开始,而且按了回车
135         if(e.keyCode == 13 && !this.isStart){
136             e.preventDefault();
137             //开始
138             this.start();
139         }
140         //游戏开始而且按了方向键
141         if(e.keyCode >= 37 && e.keyCode <= 40 && this.isStart){
142             e.preventDefault();
143             
144             This.fly.keyDown(e.keyCode);
145         }
146     },
147     //键盘释放事件
148     keyUp : function(e){
149         
150         var This = this;
151         //释放了方向键
152         if(e.keyCode >= 37 && e.keyCode <= 40){
153             e.preventDefault();
154             
155             This.fly.keyUp(e.keyCode);
156         }
157     },
158     //移除子弹
159     removeBullet : function(item){
160         
161         for(var i=0,l=this.bullets.length;i<l;i++){
162             
163             if(this.bullets[i] == item){
164                 this.bullets.splice(i,1);
165                 return true;
166             }
167         }
168     }
169 
170 }

 

 

突然发觉自己写的那些,为啥会那么卡了。。。因为,我以前都是计时器分开来写,后来才发现,要放在同一个计时器去做动画。。。

 

希望大家喜欢,有啥不好的,欢迎指出。。。

 

源码下载>>

posted @ 2011-01-17 18:25  Floyd  阅读(5783)  评论(31编辑  收藏  举报