• HTML5 游戏开发实战 | 贪吃蛇


    在该游戏中,玩家操纵一条贪吃的蛇在长方形场地里行走,贪吃蛇按玩家所按的方向键折行,蛇头吃到食物(豆)后,分数加10分,蛇身会变长,如果贪吃蛇碰上墙壁或者自身的话,游戏就结束了(当然也可能是减去一条生命)。

    贪吃蛇游戏的运行界面如上图所示。

    01、贪吃蛇游戏设计的思路

    把游戏画面看成40×30的方格。食物(豆)和组成蛇的块均在屏幕上占据一个方格。游戏设计中主要用到的4个类如下。

    Farm类:主要用来显示场地,随机生成食物,初始化一条蛇。

    Food类:抽象了食物(豆)的属性和动作。

    Snake类:抽象了贪吃蛇的属性和动作,调用Block类来组成蛇,并处理键盘输入事件和蛇的移动。

    Block类:表示组成蛇的块(实心圆)。一条蛇可以看成由许多“块”(或称节)拼凑而成,块是蛇身上最小的单位。

    02、贪吃蛇游戏设计的步骤

    游戏页面index.html

    1. html>
    2. <html lang = "en">
    3. < head >
    4. <meta charset ="UTF - 8"
    5. < title>小游戏之贪吃蛇title>
    6. < style>
    7. # canvas{border: 3px solid red;style>
    8. head>
    9. < body>
    10. <canvas id='canvas'width=800'height =00'>canvas><div id="textmsg">分数div>

    设计脚本

    1. 食物(豆)类(Food)设计

    在此游戏中,首先会在场地的特定位置出现一个豆,豆要不断被蛇吃掉,当豆被吃掉后,原豆消失,又在新的位置出现新的豆。这些豆都是由豆(Food)类创建的对象。

    foodInit()函数用于在屏幕上显示一个豆(实心圆),设计方法是直接在场地(canvas)上画一个实心圆。

    equal()函数用于判断是否与蛇身“块”node重合,也就是蛇吃到食物。

    1. //食物类
    2. function Food(x,y,w) {
    3. var t= this;
    4. t.x=x;
    5. t.y=y;
    6. t.w=w;//食物
    7. //X坐标
    8. //Y坐标
    9. //大小
    10. t.foodInit = function() [
    11. //画一个实心圆
    12. ctx.beginPath();
    13. ctx.arc(x+w/2,y+w/2,w/2,0,360,false);ctx.fillStyle="red";
    14. //填充颜色,默认是黑色
    15. //画实心圆
    16. ctx.fill();
    17. ctx.closePath();
    18. //判断是否重合
    19. t.equal = function(node)
    20. if(this.x == node.x && this.y== node.y) return true;else(
    21. return false;
    22. }
    23. }
    24. }

     

    2. 块类(Block)

    在贪吃蛇游戏中,块用来构成蛇,在蛇出现时,要把构成蛇的块一个个地输出(显示),在蛇消失时,要把块消除掉,显示和消除哪一个块都要由位置决定,并且由于蛇是由多个块构成的,每个块要填到snakes数组中。

    1. //蛇块类
    2. function Block(x,Y,w)(
    3. var t = this;
    4. t.x= x;
    5. t.y=y;
    6. t.w= w;
    7. //画一个蛇块
    8. t.drawBlock = function()
    9. ctx.beginPath();
    10. ctx.arc(x+w/2,y+w/2,w/2,0,360,false);
    11. //填充颜色,默认是黑色
    12. ctx.fillStyle="blue";
    13. ctx.fill();
    14. //画实心圆
    15. //清除蛇块
    16. t.clear = function()!
    17. ctx.fillStvle=white';
    18. ctx.strokeStyle = white';
    19. ctx.fillRect(x,Y,w,w);
    20. ctx.strokeRect(x,Y, w,w);
    21. //判断是否重合
    22. t.equal = function(node)
    23. if(this.x== node.x && this.y== node.y){return true;
    24. else
    25. return false;
    26. }
    27. }

     

    3. 蛇类(Snake)设计

    现在到了最难的步骤,就是处理蛇,一条完整的贪吃蛇是由一块一块组成的。snakes数组用于存放组成蛇的所有块;其中保存的第一个元素是蛇的头部,最后一个元素是蛇的尾巴。当蛇运动的时候,它头部增加一块而尾部减少一块。如果它吃到了豆,头部增加一块而尾部不减少。也就是说,蛇是从头部开始长的。蛇运行过程中要不断地改变方向;如果蛇头碰到了它自身,蛇就要死亡,即程序结束。

    首先,画一条蛇并移动它。

    1. //蛇类
    2. function Snake(x,y len,speed) {
    3. var t = this;
    4. t.x=x;
    5. t.y=y;
    6. t.dir='R';
    7. t.len = len;
    8. //dir 方向,R'向右
    9. var nx = x;ny =y;
    10. //初始蛇最初 len(5)块,并启动定时
    11. t.init = function()
    12. for(var i=0;i< len; i++){
    13. var tempBlock = new Block(nx,ny,gridWidth);tempBlock.drawBlock();nx-= gridWidth;
    14. snakes.push(tempBlock);
    15. snake interval = setInterval(t.move,speed);//定时移动蛇
    16. }

     然后,识别键盘事件,修改移动方向dir,初始移动dir方向为'R'(向右)。

    1. //取得键盘方向
    2. document.onkevdown = function(e)
    3. var code = e.keyCode;
    4. t.odir = t.dir;
    5. switch(code)
    6. case 37:
    7. t.dir='L';
    8. break;case 38:
    9. t.dir='u';break;
    10. case 39:
    11. t.dir='R';break;case 40 :
    12. t.dir='D';
    13. //向左键
    14. //向上键
    15. //向右键
    16. //向下键
    17. break;
    18. }
    19. }

     

    以下主要是让蛇动的move()函数。主要是根据原来蛇头snakes[0]的位置和移动方向确定新的蛇头位置,绘制新的蛇头,并清除原来的蛇尾即达到移动效果。

    在蛇移动时,判断蛇头是否和食物相撞,是否碰撞到了场地的壁以及是否与自己相撞。

    1. //移动蛇
    2. t.move = function()
    3. var newHead;
    4. //是否碰撞到了场地的壁
    5. if(snakes0].x+ snakes0].w >= canvas.width snakes0].x- snakes0].w<0snakes[0].y- snakes[0].w < 0 snakes[0].y + snakes[0].w > canvas.height)(gameover();
    6. else{//根据原来蛇头 snakes[0]的位置和移动方向确定新的蛇头位置
    7. if(t.dir=='R'){newHead= new Block(snakes[0].x + gridWidth,snakes[0].y,gridWidth);) else if (t.dir =='L')(
    8. newHead = new Block(snakes[0].x- gridWidth,snakes[0].y,gridWidth);else if (t.dir==D') !
    9. newHead = new Block(snakes[0].x,snakes[0].y + gridWidth,gridWidth);else if (t.dir==u') !
    10. newHead= new Block(snakes[0].x,snakes[0].y- gridwidth,gridWidth)
    11. //禁止反向跑
    12. if(newHead.x == snakes[1].x && newHead.y == snakes[1].y)t.dir = t.odir;return;
    13. //画新的蛇头newHead.drawBlock();//追加到数组中(长度会自动加)snakes.unshift(newHead);//清除原来尾部snakes[snakes.length - 17.clear();//并从数组中移除(长度会自动减)snakes.pop()
    14. //清除(蛇尾)块
    15. /判断食物是否和蛇头相撞
    16. for(var i=0;i< foods.length; i++)if(foods[ i].equal( snakes[0]))
    17. //给蛇增加长度
    18. t.growth();
    19. score= score +10:
    20. textmsq.innerHTML = score +“分”
    21. t.len = t.len + 1;
    22. //蛇生长方法
    23. //增加 10 分
    24. //显示分数
    25. clearInterval(snake interval);
    26. //速度加快snake interval = setInterval(t.move,speed);
    27. speed = speed < 20 ? speed : speed -10;
    28. //判断是否与自己相撞
    29. for(var i=1;i< snakes.length; i++)if(snakesil.equal(snakes[0T)) gameover();
    30. )//move()函数结束

    用于实现蛇生长growth()函数的具体功能是当蛇吃到一个豆后,蛇就要在它的尾巴上增加一块即蛇增长。设计思路是找到蛇尾snakes[snakes.length-1],根据蛇尾与蛇的倒数第2块snakes[snakes.length-2]的位置关系,计算出蛇尾新增一块的位置。

     

    1. //给蛇增加长度(在尾巴加)
    2. t.growth = function()
    3. var tail1 = snakes[ snakes.length - 1];
    4. var tai12 = snakes[snakes.ength - 2];
    5. var addBlock;
    6. if(tai11.x== tai12.x)
    7. {
    8. if(tail1.y>= tail2.y)
    9. }
    10. addBlock =new Block(tail1.x,tail1.y + gridWidth,gridWidth);
    11. else
    12. addBlock =new Block(tail1.x,tail1.y-gridWidth,gridWidth);
    13. else
    14. if(tai11.x>= tail2.x)
    15. addBlock =new Block(tail1.x + gridWidth,tail1.y,gridWidth);
    16. else
    17. addBlock =new Block(tail1.x-gridWidth,tail1.y,gridWidth);
    18. //数组加入尾部
    19. snakes.push(addBlock);addBlock.drawBlock();
    20. console.log(snakes.length);
    21. )//growth()函数
    22. * snake 类结束 */

     

    4. 场地类(Farm)设计

    为游戏的主场地,豆要在此范围内出现,蛇要在此范围内运行,显示场地内的所有对象、场地边框、豆和蛇。

    1. //场地类,生成一个画布和豆、蛇
    2. function Farm()
    3. var t = this;
    4. ctx.fillStyle ='white';
    5. ctx.fillRect(0,0,canvas.width,canvas.height);foods =l;//有环莲浮墩甘伴榜机郧扒唉癌挨膊鞍皑傲卑唉扮诚成一个食物t.addfood = function()var x= parseInt(canvas.width / gridWidth * Math.random()) * gridWidth;var y=parseInt(canvas.height / gridWidth * Math.random()) * gridWidth;var food = new Eood(x,y,gridWidth);food把椽斌新foodInit();
    6. //重新初始化豆数组,不要把前一次游戏的数组元素遗留
    7. foods.push(food);
    8. //重新初始化蛇身(块)数组,不要把前一次游戏的数组元素遗留snakes =;//更新速度 500 毫秒(即移动速度)
    9. t.snake= new Snake(100,100,5,500); //初始 5 节长度,位置(100,100)处//*彼啊画钻班等滁癌报蛇t.snake.init();
    10. }

     

    5. 主程序

    在游戏开始后,要首先初始化场地Farm类,显示场地内的所有对象,场地边框、豆和蛇。同时要2秒随机产生一个新豆并显示。

    1. var canvas = document.getElementById("canvas”)
    2. var ctx = canvas.getContext( 2d');
    3. var gridWidth = 20;
    4. var score = 0;
    5. var foods = new Array(),snakes = new Array();//开始游戏
    6. function gameStart(
    7. var farm = new Farm();
    8. //放豆和蛇的数组
    9. //2 秒产生一个豆
    10. food interval = setInterval(farm.addfood,2000);
    11. gameStart();
    12. //结束
    13. function gameover()var judge = confirm("游戏结束,是否重新开始”);score =0;
    14. textmsg.innerHTML = score +“分clearInterval(snake interval);
    15. //清除产生蛇移动定时
    16. //清除产生新豆定时
    17. clearInterval(food interval);
    18. if(!judge){
    19. //选择不重新开始
    20. return false;
    21. gameStart();
    22. }

    至此,贪吃蛇游戏编写完成。 

  • 相关阅读:
    esp32 idf 添加的compones找不到头文件
    数据的存储--Redis缓存存储
    HTML5入门(1)——HTML基础
    MySQL的主从复制与读写分离详解
    MCDF--lab02
    ESP8266-Arduino编程实例-LM75温度传感器驱动
    HSF概述
    注意 Laravel 清除缓存 php artisan cache:clear 的一个坑
    Hadoop_HDFS笔记2(HDFS的API操作,HDFS的读写流程(面试重点))
    K8s Ingress Controller部署指南:轻松实现服务外部访问
  • 原文地址:https://blog.csdn.net/qq_41640218/article/details/131455944