2025年贪吃蛇-单机游戏-微信小程序项目开发流程详解

贪吃蛇-单机游戏-微信小程序项目开发流程详解还记得小时候玩过的经典贪食蛇小游戏吗 游戏规则简单 对新手来说很容易入门编程 在这里 TA 远方来讲一下实现过程 详解过程按照实现思路来 请仔细往下看 阅读此文章需要满足的以下条件 会使用微信开发工具 或者 HBuilderX 开发工具

大家好,我是讯享网,很高兴认识大家。

还记得小时候玩过的经典贪食蛇小游戏吗,游戏规则简单,对新手来说很容易入门编程,在这里,TA远方来讲一下实现过程,详解过程按照实现思路来,请仔细往下看

💡 阅读此文章需要满足的以下条件

  • 会使用微信开发工具,或者HBuilderX开发工具
  • 属性Javascript编程语言
  • 熟悉使用Canvas组件
  • 这里TA远方使用的是微信开发工具,新建项目的时候,选择小程序,使用Javascript语言,选择空模板,最后点击完成,
    若有项目源码,直接选择小程序再打开项目就即可
  1. 接下来,在项目中的路径pages/index/index.wxml文件里,写一下布局,用层叠布局方式,需要放置三个Canvas组件,分别是下层canvA中间层canvB上层canvC,上层的加上一些写属性,如下图
<view class="page"> <view class="canvas-box"> <canvas class="canvas" canvas-id="canvA" id="canvA"></canvas> <canvas class="canvas" canvas-id="canvB" id="canvB"></canvas> <canvas class="canvas" canvas-id="canvC" id="canvC" :disable-scroll="true" bindtouchstart="onTouchStart" bindtouchmove="onTouchMove" bindtouchend="onTouchEnd" bindtouchcancel="onTouchEnd"></canvas> </view> </view> 

讯享网
  1. 接着在对应的index.js文件里写下代码,获取布局中的那三个Canvas组件,做好初始化,代码如下
讯享网App({ 
    data: { 
    canvas: { 
   /*包括画布的相关数据*/}, //... }, onLoad(){ 
    wx.createSelectorQuery().select('#canvA').fields({ 
    size: true }, res => { 
    const canvA = wx.createCanvasContext('canvA'); const canvB = wx.createCanvasContext('canvB'); const canvC = wx.createCanvasContext('canvC'); //初始画布的相关数据 this.data.canvas = { 
    width: res.width, height: res.height, canvA, canvB, canvC }; this.canvA_drawBg(); this.canvC_drawSnake(); this.canvB_drawFood(); this.redraw(this.data.canvas); }).exec(); }, //...绘制地图...背景图...还有障碍物(现在把它叫做墙壁) canvA_drawBg(){ 
    //... }, //...绘制蛇自身 canvC_drawSnake(){ 
    //... }, //...绘制食物... canvB_drawFood(){ 
    //... }, //...重绘...实现游戏刷新的逻辑 redraw(canvas){ 
    //... }, }) 
  1. 接下来,用下层canvA组件的来实现绘制,应该绘制什么呢,是游戏地图,效果如下图所示,绘制网格
    在这里插入图片描述
    讯享网

  2. 那么如何绘制游戏地图呢,用火眼金睛观察一下,游戏中的小蛇每移动一步的位置和距离都在变化,用网格来表示最合适不过了,绘制过程很简单,看下方法canvA_drawBg的实现,代码如下
App({ 
    data: { 
    canvas: { 
   /*包括画布的相关数据*/}, config: { 
    gridSize: 10,//网格大小 drawGrid: false,//绘制网格 wellCount: 5,//墙壁数量 }, //... } / * 绘制地图...背景图...还有障碍物(现在把它叫做墙壁) */ canvA_drawBg(){ 
    const { 
    width, height, canvA } = this.data.canvas;//画布宽高 const { 
    gridSize:g, drawGrid, wellCount } = this.data.config;//关于游戏的配置 //g是网格大小, wellCount障碍物数量 //此处省略...初始化处理 this.data.canvas.w = w;//网格宽 this.data.canvas.h = h;//网格高 this.data.canvas.l = l;//left 左边距 this.data.canvas.t = t;//top 顶边距 this.data.canvas.ln = ln;//x grid count 横向 X坐标网格数 this.data.canvas.tn = tn;//y grid count 纵向 y坐标网格数 //绘制背景色 canvA.fillRect(0,0,width,height); //所有坐标集合,包括制障碍物的 const coordinaties = []; for(let i=0; i<ln; i++){ 
    //是否绘制网格,纵向绘制 if (drawGrid) { 
    //... } //是否绘制障碍物,判断数量大于0即可 if (wellCount>0) { 
    //... } } //是否绘制网格,横向绘制 if (drawGrid) { 
    for(let i=0; i<tn; i++){ 
    //... } } else { 
    //...如果不绘制网格,就绘制边框 } if(coordinaties.length>0) { 
    //... do{ 
    //绘制障碍物... }while(this.data.wall.length<wellCount);//绘制障碍物的数量判断 //... } canvA.draw(); }, }) 
  1. 接下来,绘制蛇自身,在网格中的位置,方法canvC_drawSnake的实现代码如下
讯享网const MoveDire = { 
    u: 'up', d: 'down', l: 'left', r: 'right', }; const Colors = { 
    bgColor: '#A4D1FC', fillColor: '#365DC0', }; App({ 
    data: { 
    canvas: { 
   /*包括画布的相关数据*/}, config: { 
    gridSize: 10,//网格大小 snakeMinLength: 1,//初始蛇身长度 }, snakeDire: MoveDire.u,//移动方向,默认向上移 //... } / * 绘制蛇自身 * @param isReset 是否重置蛇身长 */ canvC_drawSnake(isReset){ 
    const { 
    gridSize:g, snakeMinLength } = this.data.config;//关于游戏的配置 const { 
    w, h, canvC, l, t, ln, tn } = this.data.canvas; const { 
    snakeDire } = this.data; if (isReset || this.data.snake.length<=0) { 
    this.data.snake = [this.createCoordinate(parseInt(ln/2), parseInt(tn/2), snakeDire)]; for(let i=1; i<snakeMinLength; i++){ 
    this.addSnakeLength(); } } canvC.setFillStyle(Colors.fillColor); this.snake.forEach(f => { 
    canvC.fillRect(f.x,f.y,g,g); }); canvC.draw(); }, //...创建坐标信息,传入坐标系a和b createCoordinate(a,b){ 
    //... } //...加长蛇身 addSnakeLength(){ 
    //... } }) 
  1. 接着,绘制食物,用一个位置来表示,方法canvB_drawFood的实现代码如下
App({ 
    data: { 
    canvas: { 
   /*包括画布的相关数据*/}, config: { 
    gridSize: 10,//网格大小 }, food: null,//食物坐标 //... }, / * 绘制食物 * @param isNew 是否用新的 */ canvB_drawFood(isNew){ 
    const { 
    gridSize:g } = this.data.config; const { 
    canvB } = this.data.canvas; let f = this.data.food; if (isNew || f==null) { 
    f = this.createRandomFood(); this.data.food = f; } canvB.setFillStyle(Colors.fillColor); canvB.fillRect(f.x,f.y,g,g); canvB.draw(); }, //...获取新的食物,食物放置位置随机 createRandomFood(){ 
    //... } }) 
  1. 最后,实现重绘的逻辑方法redraw,刷新游戏视图,代码如下
讯享网const App = getApp(); const Util = App.getUtil(); App({ 
    data: { 
    canvas: { 
   /*包括画布的相关数据*/}, config: { 
    speed: 5,//初始移动速度 1~5 }, food: null,//食物坐标 timer: null,//定时器 //... }, / * 实现重绘的逻辑,刷新游戏 * @param canvas 画布信息 */ redraw(canvas){ 
    const { 
    speed } = this.data.config; const maxSpeed = 200;//记录最大值 const moveSpeed = Math.max(maxSpeed*Math.abs(speed-1) - this.data.snake.length*100, maxSpeed);//下一次刷新等待时长越短,移动速度越大 //定时器 this.data.timer = setTimeout(() => { 
    const { 
    food } = this.data; //判断是否显示食物,实现闪烁效果 if (food) { 
    let timeout = Date.now()-food.t; if (timeout>1000*30) { 
    //如果超过30s,则食物过期,应重新出现 this.canvB_drawFood(true); } else if (food.show) { 
    // food.t = Date.now(); food.show = false; this.canvB_drawFood();//绘制 } else if (!food.show) { 
    food.show = true; this.data.canvas.canvB.draw();//不绘制 } else { 
    } } //移动蛇身,返回判断是否继续游戏 let confirmGame = this.moveCoordinaties(); if (confirmGame) { 
    this.canvC_drawSnake(); //使用window下的方法,如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销 requestAnimationFrame(this.redraw); return; } //游戏结束了 this.endGame(true); //显示对话框 Util.alert('游戏结束!确认要重新开始吗?', res => { 
    if (!res.confirm) return; wx.reLaunch({ 
    url:'/pages/index/index' }) }); }, moveSpeed); }, //...绘制蛇身 canvC_drawSnake(){ 
    //... }, //...移动蛇身,处理蛇身新坐标,新的位置 moveCoordinaties(){ 
    //...蛇头移动后 //...判断是否吃到食物,碰到自己 //...判断是否碰到墙(障碍物) //...最后移动没问题的话,返回true, 否则返回false return true; }, //...对游戏结束的处理,关闭定时器 endGame(isEnd){ 
    //... }, onUnload(){ 
    this.endGame(); } }) 
  1. 对了,还有,游戏的交互逻辑,就用触摸操作手势,实现代码如下
import Gesture from './../../utils/gesture.js'; App({ 
    data: { 
    gestures: { 
   },//定义触摸操作的数据 snakeDire: MoveDire.u,//当前的移动方向 }, onTouchStart(event){ 
    this.data.gestures.a = event.touches[0];//触摸开始点 }, onTouchMove(event){ 
    this.data.gestures.b = event.touches[0];//最后一个触摸点 }, //触摸结束 onTouchEnd(){ 
    const { 
    snakeDire: dire } = this.data; //Gesture是引入来的,封装了手势操作的处理 const Ges = Gesture.G; //获取手势操作方法getG const g = Gesture.getG(this.data.gestures); switch(g){ 
    case Ges.left: //向左划 //判断,若是相反方向就无效,以下同理 if (dire!=MoveDire.r) { 
    this.snakeDire = MoveDire.l; } break; case Ges.up: //向上划 if (dire!=MoveDire.d) { 
    this.snakeDire = MoveDire.u; } break; case Ges.right: //向右划 if (dire!=MoveDire.l) { 
    this.snakeDire = MoveDire.r; } break; case Ges.down: //向下划 if (dire!=MoveDire.u) { 
    this.snakeDire = MoveDire.d; } break; case Ges.click: //只是点击 default: this.pauseGame(); } this.data.gestures = { 
   }; }, //...暂停,或继续游戏 pauseGame(){ 
    //... } }) 

💡 小提示
关于Gesture触摸手势操作的详解文章请点击此处查看

  1. 就写到这里,其它的细节不重要,在这里就不讲,重要是实现思路清晰,最后,项目中小程序编译运行没问题的话,结果如下图,一个动态图,这样看着比较直观
    在这里插入图片描述

如需要看微信小程序项目源码的,还有类似uniapp项目源码也有,
请点击【项目源码】前往找到再下载(如果是在手机浏览器上看的话,可能会找不到下载项,请用PC端浏览器上查看即可 ),
若觉得此文章有帮助,请点赞再走不迟~,谢谢!
在这里插入图片描述

小讯
上一篇 2025-03-11 23:14
下一篇 2025-03-21 20:19

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/44993.html