原生js+canvas实现类贪吃蛇的小游戏

写在前面

这是一个类贪吃蛇的小游戏,因为最近又翻到了canvas,想着写一些东西来巩固下,刚好就看到博主写的demo,不过我在其基础上进行了一定的规则限制,下面附上链接:博主原文

设计初衷

此次这个游戏加入了
1、积分规则,
2、碰壁死亡规则,
3、调用requestAnimationFrame方法实现循环。
游戏的截图效果如下:
使用键盘的方向键来控制游戏人物的移动
死亡效果截图如下:
死亡截图

设计步骤

1、在HTML文档中创建canvas的节点,以便DOM操作。

代码如下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>使用canvas和js来实现一个小游戏</title>
        <script type="text/javascript" src = "canvas.js"></script>
    </head>
    <body>
        <canvas id = "drawing" width = "512" height = "480" style="border: 1px solid lightblue;">
        </canvas>
    </body> 
</html>

2、获取对canvas元素以及canvas上下文的引用。

var drawing = document.getElementById("drawing");
var context = drawing.getContext("2d");

3、将游戏人物、怪物、背景图加载进去

因为图片是异步加载的,所以我使用了onload加载函数,并且设置了标记量,以免图片加载的过程中出现错误,显示不了画布上。

//在画布上获取对背景的引用
    var bgReady = false;  //布尔值用于确保何时可以正确的引用图片
    var bgImage = new Image();
    bgImage.onload = function () //图片的加载是异步加载
    {
        bgReady = true;
    };
    bgImage.src = "image/bg.png";
    //在画布上获取对英雄的引用
    var heroReady = false;
    var heroImage = new Image();
    heroImage.onload = function ()
    {
        heroReady = true;
    };
    heroImage.src = "image/hero.png";
    //在画布上获取对怪兽的引用
    var monsterReady = false;
    var monsterImage = new Image();
    monsterImage.onload = function ()
    {
        monsterReady = true;
    };
    monsterImage.src = "image/monster.png";

4、定义游戏对象,定义分数变量

在这个游戏里面,怪物是静止不动且随机出现的,当键盘上控制人物移动时,需要一个速度,即:speed,创建对象来保存他们的变量。

//定义游戏对象(英雄和怪兽的画布座标)
    var hero = {
        speed : 256,
        x : 0,
        y : 0
    };
    var monster = {
        x : 0,
        y : 0
    };
    var score = 0;

5、当游戏失败后重置网页或得分后怪物的位置随机出现

在这个函数中使用了随机数来确保怪物位置出现的随机性,确保了游戏的可玩性。

var reset = function ()
    {
        if(over == true)
        {
            hero.x = drawing.width/2;
            hero.y = drawing.height/2;
            over = false;
        }
        monster.x = 32 + Math.floor((Math.random() * (drawing.width - 64)));
        monster.y = 32 + Math.floor((Math.random() * (drawing.height - 64)));
    };

6、采用键盘事件的监听,保持稍后存储用户输入

这个部分我们旨在用addEventListener()方法、采用“keydown”、“keyup”来对键盘设置事件的监听,以此来获取用户键盘的输入。addEventListener()方法接受三个参数,即:
1)event,必选,注意: 不要使用 “on” 前缀。 例如,使用 “click” ,而不是使用 “onclick”。
2)必选。指定要事件触发时执行的函数, 当事件对象会作为第一个参数传入函数。 事件对象的类型取决于特定的事件。
3) 可选。布尔值,指定事件是否在捕获或冒泡阶段执行。

var keyDown = {};
    addEventListener("keydown", function(e){
        keyDown[e.keyCode] = true;
    },false);

    addEventListener("keyup", function(e){
        delete keyDown[e.keyCode];
    },false);

7、游戏的更新

在这部分的函数中,前四个if语句说明了,当四个方向键被按下的时候,游戏人物会朝着相应的方向移动;第五个if语句用来判断怪兽和游戏人物是否相撞,相撞的话则得一分,因为游戏人物和怪兽都是32 * 32 像素的,所以判断语句才这么写的。

//Dom操作实现英雄和怪兽碰撞加分
    var update = function (modifier)
    {
        if(38 in keyDown)
        {
            hero.y -= hero.speed * modifier;
        }
        if (40 in keyDown) 
        { 
            hero.y += hero.speed * modifier;
        }
        if (37 in keyDown) 
        { 
            hero.x -= hero.speed * modifier;
        }
        if (39 in keyDown) 
        { 
            hero.x += hero.speed * modifier;
        }

        if(
            hero.x <= (monster.x + 32) && 
            hero.y <= (monster.y + 32)  && 
            monster.x <= (hero.x + 32)  && 
            monster.y <= (hero.y + 32)  
          )
        {
            score = score + 1;
            reset();
        }
    };

8、绘制图像

在这个部分中,我们就用到了之前的标志量,使得可以确保图片在加载时候可以正常的显示在画布中,因为图片是异步加载的;并且将得分情况写在了左上角。

//绘制图像(英雄、怪兽、背景、分数)
    var render = function ()
    {
        if(bgReady)
        {
             context.drawImage(bgImage,0,0);
        }
        if(heroReady)
        {
            context.drawImage(heroImage,hero.x,hero.y);
        }
        if(monsterReady)
        {
            context.drawImage(monsterImage,monster.x,monster.y);
        }
        context.fillStyle = "#fff";
        context.font = "24px Helvetica";
        context.textAlign = "left";
        context.textBaseline = "top";
        context.fillText("你的得分: " + score, 32,32);
    };

9、设置当英雄碰撞到画布上的边界时,游戏结束或者重置游戏

var over = false;
    var gameOver = function ()
    {
        if(
            hero.x <= 0 ||
            hero.x >= drawing.width ||
            hero.y <= 0 ||
            hero.y >=drawing.height
          )
        {
            over = true;
            score = 0;
            alert("很遗憾,你不小心结束了比赛!");
            reset();
        }
    };

Tips

1、图片的加载方式是异步,必须使用onload加载函数才能够正确的显示
2、我们获取canvas是通过getElementById获取的,其所返回对象的宽和高就是我们所要获取的canvas的宽和高。
3、在设置游戏结束函数时,over必须是提前声明的,且在reset中要有判断over布尔值的语句。

如果大家获取源码的话,请点击这里:游戏源码地址

如果有什么问题还要深究的话,欢迎大家提问。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章