自己动手打造html5星际迷航的示例代码分享


本文摘自PHP中文网,作者黄舟,侵删。

学习html5的canvas第三天,觉得还没过瘾,转眼就忘,于是趁着有空,准备弄个小游戏来玩!游戏应该需要注意性能,还有一些逻辑需要斟酌,我想还需要用户可修改性,也就是用户配置。好,开始我们简单但有趣的旅程吧――

想先看效果的,先跳转试玩一下吧!

第一步,当然需要一张画布

1

1 <canvas id="canvas" width="300" height="400">你的浏览器不支持Canvas</canvas>

JavaScript的总体结构如下:

1

2

3

4

5

6

7

var定义一些变量

planeMoveTimer飞机移动监听/计时器

attackEnemyTimer发射炮弹计时器

onkeydown监听

onkeyup监听

drawPlane画飞机

drawEnemy画敌人

首先预定义一些变量

1

2

3

4

5

6

7

8

9

10

11

var _keyA = _keyD = _keyW = _keyS = 0,  // 存储按键状态

 

    step = 8,                          // 飞机移动速率

    w = 34, h = 44,                  // 飞机实际大小

    planeX = 133, planeY = 356,      // 飞机目前位置

    planeSrc = "feiji.png",          // 飞机素材位置

    imgW = 177, imgH = 220,          // 飞机源图尺寸

 

    cw = 300, ch = 400,  // 画布大小

    canvas = document.getElementById("canvas"),

    ctx = canvas.getContext("2d");

本游戏只用到一个外部资源,就是那张图片,获取地址请访问本文底部给出的项目GitHub位置链接。跳转

先看画图的两个方法

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

function drawPlane(x, y) {

    var img = new Image();

    img.src = planeSrc;  // 飞机源图地址

    img.onload = function() {

        ctx.drawImage(img, 0, 0, imgW, imgH, planeX, planeY, w, h);

    }

}

function drawEnemy(){

    for(var a=0;a<cw;a+=10) {

        for(var b=0;b<ch-300;b+=10) {

            ctx.beginPath();

            ctx.fillStyle = "orange";

            ctx.strokeStyle = "black";

            ctx.strokeRect(a, b, 10 ,10);

            ctx.fillRect(a, b, 10, 10);

            ctx.closePath();

        }

    }

}

飞机的图片一定要在onload()方法里才能把飞机画出来,目前的敌人还是一堆橙色的不会动的砖头,通过遍历在画布的顶端把它们画出来。

接着,看两个键盘事件:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

window.document.onkeydown = function(evt){

    evt = (evt) ? evt : window.event;

    switch(evt.keyCode) {

        case 65:  // A

            _keyA = 1;

            break;

        case 68:  // D

            _keyD = 1;

            break;

        case 87:  // W

            _keyW = 1;

            break;

        case 83:  // S

            _keyS = 1;

            break;

    }

}

window.document.onkeyup = function(evt){

    evt = (evt) ? evt : window.event;

    switch(evt.keyCode) {

        case 65:  // A

            _keyA = 0;

            break;

        case 68:  // D

            _keyD = 0;

            break;

        case 87:  // W

            _keyW = 0;

            break;

        case 83:  // S

            _keyS = 0;

            break;

    }

}

至于为什么要在两个事件里设置变量_keyA、_keyD、_keyW、_keyS,而不是直接触发画图事件,原因是――同时长按两个键时,无法同时触发事件,先按者只触发一次,只有后按者在按着键的时候才能一直触发事件,简单点来说,如果我想要向左上角移动,同时按下A和W,假设A比W慢了一点点,即时很微小,那么飞机的移动路径是先上移一步然后一直向左移动,这显然不是我想要的,我用4个变量来存储按键的状态,按下键的时候,设置其状态为1,在按键起来的时候,设置其状态为0,然后我们用计时器来不断地读这些键的状态并及时更新飞机的状态。

飞机移动计时器如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

var planeMoveTimer = window.setInterval(function(){

    if(_keyA||_keyD||_keyW||_keyS){

        ctx.clearRect(planeX, planeY, w, h);

        _keyA && (planeX-=step);

        _keyD && (planeX+=step);

        _keyW && (planeY-=step);

        _keyS && (planeY+=step);

        planeX>=0 || (planeX=0);

        planeX<=(cw-w) || (planeX=cw-w);

        planeY>=0 || (planeY=0);

        planeY<=(ch-h) || (planeY=ch-h);

        drawPlane(planeX, planeY);

    }

}, 10);

ctx.clearRect()用来清除原来位置的飞机,为绘制飞机的下一状态做准备,但是有一个很大的问题,它是直接清除整块的,要是游戏有背景,有交叠,那不是要把这些不是飞机的东西也一并清空了?恕我愚昧,暂时不考虑这个问题。

通过判断按键状态,每次移动的步距为预先设置的step,并做好边界处理。

然后是攻击计时器:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

var attackEnemyTimer = window.setInterval(function(){

    var cannonX = planeX+Math.floor(w/2);  // 炮口X轴位置

    var cannonY = planeY;  // 炮口Y轴位置

    var tmpTimer = window.setInterval(function(){  // 每颗炮弹的移动计时器

        ctx.clearRect(cannonX-1, cannonY-3, 2, 3);

        cannonY -= 3;  // 炮弹步距

        if(cannonY<0){

            // 炮弹的贯透效果

            ctx.beginPath();

            ctx.moveTo(cannonX, 100);  // 100为enemy的最低位置

            ctx.strokeStyle = "white";

            ctx.lineWidth = "4";  // 模拟不规则毁坏,暂时尚未没实现

            ctx.lineTo(cannonX, 0);

            ctx.stroke();

            ctx.closePath();

            window.clearInterval(tmpTimer);  // 清除该炮弹的计时器

        }

        ctx.clearRect(cannonX-1, cannonY-3, 2, 3);

        ctx.beginPath();

        ctx.fillStyle="red";

        ctx.fillRect(cannonX-1, cannonY-3, 2, 3);  // 炮弹大小:2X3

        ctx.closePath();

    }, 0);

}, 500);

每0.5s发射一颗炮弹,每颗炮弹又单独设置一个计时器,以便控制,炮弹的移动我也是采用先擦后画的方式,由于炮弹移动也有步距,所谓炮弹贯透效果就是直接画一条颜色跟背景色一样的直线而已。试着修改炮弹步距可以调节炮弹的移动速度,也可以调节炮弹的尺寸。

最后一步了,还差点什么,一开始就要画好敌人和飞机啦!

1

2

1 drawPlane();

2 drawEnemy();

大功告成!还想继续优化增加可玩性的,但实在是没时间弄了,还有很多其他的东西要学,所以这个游戏就先这样啦!是不是很简单!哈哈,?辶税桑?标题太诱惑人,没办法!

以上就是自己动手打造html5星际迷航的示例代码分享的详细内容,更多文章请关注木庄网络博客

相关阅读 >>

基于 HTML5 canvas 的 3d 渲染引擎界面以及吸附等效果的运用

HTML5网页水印sdk的实现方法

HTML5和css3制作一个模态框实例

h5元素/属性/格式化的详细介绍

关于HTML5 canvas旋转动画的2个例子

利用HTML5 从视频中捕获静止图像实例代码

HTML5实践-如何使用css3丰富图片样式的详解(二)

h5实现桌面通知

关于HTML5的知识小结

HTML5 border属性怎么设置?HTML5 table中的border属性介绍

更多相关阅读请进入《HTML5》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...