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 
}

 

 

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

 

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

 

源码下载>>