900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 【跳棋】跳棋游戏-多人游戏-微信小程序开发流程详解

【跳棋】跳棋游戏-多人游戏-微信小程序开发流程详解

时间:2024-03-21 02:38:13

相关推荐

【跳棋】跳棋游戏-多人游戏-微信小程序开发流程详解

看到跳棋游戏,一个2到6人可一起玩的游戏,于是联想起,自己上小学时候陪同学们玩过的弹珠游戏,是不是跟跳棋游戏很像呢,看了跳棋玩法,有兴趣就研究,这里把跳棋游戏给弄出来了,想知道地图怎么画,对此感兴趣的同学可以研究研究,让家人孩子们一起参与游戏互动吧,珍惜陪伴的幸福时光。

打开微信开发工具,选择小程序,创建一个项目,

例如项目名称为miniprogram_chinese_draughts,然后选择以下,再确定创建

AppID 使用自己的测试号不使用云服务JavaScript - 基础模板

开始页

新建小程序项目后,开发工具会自动生成一些基础模板文件,

在位置/pages/index/index这里,把index.wxml改成开始页面,添加一个选择人数的表单,和按钮,显示如下

跳棋游戏中的是不能有5个人参与的,因为第5个参与者没有对手,不公平吧,

index.js这里修改一下,添加一个方法enterGame(e),点击开始游戏会调用到,代码如下,

enterGame(e){const {count } = e.detail.value;wx.navigateTo({url: '/pages/game/game?args='+count,})}

跳转到游戏页面,同时会传一个参数count表示参与人数

游戏页面

添加一个游戏页面,文件位置在pages/game/game,页面game.wxml里的添加布局,内容如下

<view class="page"><canvas class="canvas" id="canv" type="2d" bindtouchstart="onTouchStart"></canvas><scroll-view class="scroll-view" scroll-y="true"><view class="game-info"><!-- 这里显示游戏状态信息的布局 ---></view></scroll-view></view>

其中canvas画布,是最重要的组件,可用来绘制画面,

另外放置的组件是用于显示每个参与选手(玩家)的游戏状态,

初始化

开始页有传来的参数count,就从游戏页面onLoad(options)加载方法里获取,代码如下

/*** 页面的初始数据*/data: {players:[],//参与的玩家列表currentPlayer:0,//指定哪个玩家下棋},onLoad(options) {let index = 0;//默认的选择//如果从上一页有传来参数,这里改变默认的选择if(options?.args) index = ['2','3','4','6'].indexOf(options.args);//按照选择人数分配玩家let players = [[0,5],[1,2,5],[1,2,3,4],[0,1,2,3,4,5]][index].map(id=>{return {id: parseInt(id),//玩家的idcolor: ChessColors[id],//对应的颜色step: 0,//开始步数rank: 0,//用于记录的排名}});//更新玩家列表显示this.setData({players})},

接下来,从游戏页面的准备完成事件onReady()方法里,

获取一下页面布局中的canvas,然后绑定触摸开始事件,代码如下

onReady() {wx.createSelectorQuery().select('#canv').fields({size:true,node:true},res=>{//...//获取画布数据this.canvasData = {canvas:res.node,//画布canvas元素的节点ctx:res.node.getContext('2d'),//画布canvas的绘制工具};//实例化地图对象const map = new Map(this.canvasData,this.data.players.map(p=>p.id));//绘制地图的异步方法map.drawMap(()=>{//绘制完成了,这里绘制所有参与玩家的棋子map.drawChesses();});this.map = map;//...}).exec()},onTouchStart(e) {//...这里是canvas画布触摸开始的处理方法}

从上面看,其中的Map是指地图模块,

在使用模块前,需要在代码文件头写一行导入模块的代码,也就是引用,代码如下

import {Map, ChessColors } from '../../utils/map.js';

还有ChessColors,是默认分配玩家的棋子颜色集合,若想自定义,可在此修改,

模块文件代码共有240行(包括空格行),看着不多,实现了地图数据和地图绘制方法

游戏背景

在上面的初始化逻辑里,游戏背景已经绘制好了,

地图的绘制方法是drawMap(callback),参数callback是传入的回调方法,绘制完成后会调用,

这里简单说一下它的实现过程,代码如下

drawMap(callback){const {canvas, ctx } = this.canvasData;//定义它们分别是网格,所有棋子,格子大小,格子半径,圆半径const {grids, chesses, gSize, gR, gRp } = this;//初始化值const angle = Math.PI*2;//修改设置ctx.strokeStyle=BorderColor;grids.forEach((g,i)=>{//这个方法是扫描一个格子位置中相邻的一些格子(圆)let gs = this.scanGrids(g);if (gs.length<=0) return;//在这里画上一些格子之间的连接线gs.forEach(g1=>{ctx.beginPath();ctx.moveTo(g.x,g.y);ctx.lineTo(g1.x,g1.y);ctx.stroke();});});ctx.fillStyle=BorderColor;//接下来,画出所有的格子(圆),就是覆盖着画grids.forEach((g,i)=>{//...ctx.beginPath();ctx.arc(g.x,g.y,gRp,0,angle);ctx.fill();ctx.stroke();});//这里就算画好了,导出图像let img = canvas.createImage();img.onload = () => callback(img);img.src = canvas.toDataURL();//网格地图,需要设置到bgImg缓存起来(背景图),将来有用this.bgImg = img;}

由于这里是设置到bgImg缓存中,每次更新就要重新绘制出来,

也可以将绘制的图像设置到背景图中,每次更新就不用重新绘制地图,直接在底层显示,

然后绘制其它的,例如绘制改变位置后的棋子

选手和棋子

绘制不同选手阵营中的棋子,也可以看作是珠子,不同选手代表的棋子和格子颜色不同,

如果棋子的位置改变后,就需要调用地图的方法drawChesses(selectIndex)重新绘制,

显示最新的所有棋子布局,代码如下

drawChesses(selectIndex){const {canvas, ctx } = this.canvasData;const {grids, chesses, gSize, gR, gRp } = this;const angle = Math.PI*2;//每次绘制前,都要清空画布ctx.clearRect(0,0,canvas.width,canvas.height);//将缓存的背景图重新绘制出来ctx.drawImage(this.bgImg, 0, 0);//然后,再去绘制所有的棋子let isSelect=false;chesses.forEach(chess=>{//判断是否有选择,记录一下if(chess.index==selectIndex) isSelect=true;//如果有选择棋子,就在棋子周围画一个圆(代表选择)this.drawChesse(chess,selectIndex);});//这里还要判断,如果没有棋子被选择过,那剩下可能是选择了没有棋子占用的格子if(!isSelect) {this.drawChesse(undefined,selectIndex);}}

从上面看出,传入的参数selectIndex就是指玩家选择的格子索引,

同时也传给了方法drawChesse(chess,selectIndex),另一个参数chess就是指选择的棋子,没有选择就传undefined,这个方法实现了怎样绘制网格中的棋子

讲到这里,游戏页面就算绘制好了,编译运行看效果,

显示出来是下图这样的,一共6个玩家参与的跳棋游戏

游戏逻辑

从画布的触摸开始事件中去处理,就是上面提到的onTouchStart(e)方法,

游戏规则

这里再想一下游戏逻辑,当用户点击棋子,选择自己的棋子后,接下来应该怎样实现呢,

这里了解以下游戏规则,

按照游戏规则,理清一下实现思路:

判断每个玩家的步数,在30步内未走出自己的阵营的,就判出局,不能再继续;走棋,有两个走法:第一个就是只走一步;第二个,就是以旁边的棋子为方向,跳到棋子方向的另一边,可连续跳;步数,走一步算一步,跳一次也算一步,如果是连续跳也算一步,可以修改过来的;将对方阵营所有的棋子空位全部占领就判赢,如果是三人以上的,赢的按排名计算,剩下的判出局;

怎么实现游戏逻辑的呢,实现游戏逻辑是最复杂的地方吧,说来也是,只要理解它的实现过程基本就可以自己尝试了,

选择棋子

第一步,要选择棋子,然后移动棋子,就在它的触摸事件中处理,代码如下

onTouchStart(e) {//...const touch = e.touches[0];//第一个触摸点(位置)const {grids, gRp, chesses } = this.map;//所有玩家,指向当前下棋的玩家const {players, currentPlayer } = this.data;//通过触摸点位置判断,从网格中找出选择的棋子let chess;let grid = grids.find(grid=>{//先从网格位置判断...如果是在这个格子里,再判断是否有棋子在这个格子上...});//没有点到格子的画,就返回不处理了if (grid==undefined) return;//给出当前在下棋的玩家const player = players[currentPlayer];let {selectGridData } = this;//判断之前是否选择过网格(棋子)了,还有就是选择的棋子是当前在下棋的玩家的,如果条件满足了,反之就是不满足if (!(selectGridData?.chess?.id==player.id)) {//不满足以上条件,就重新设置选择数据this.selectGridData = {grid, chess, moveCount:0 };//重新绘制所有棋子this.map.drawChesses(grid.i);//不再继续处理return;}//如果选择到棋子if (chess) {//不是自己的,提示一下if (chess.id!=player.id) {this.showToast(`请${player.id+1}号玩家操作`);return;}//如果是相邻跳过的,又选择下一个棋子,就不是连续跳了if (selectGridData.moveCount>1) {//换下一个玩家this.setNextPlayer();return;}//剩下的,只有选择棋子了吧,直接给它更新显示Object.assign(this.selectGridData, {chess, grid });this.map.drawChesses(grid.i);return;}//获得移动到下一个位置的距离,相对格子的,一个格子算一个单位距离let count = this.map.gotoGrid(selectGridData.grid,grid);if (count>0) {//判断是否只移动1个(走),然后就是上次移动的是否大于1个(跳),满足条件if (!(count==1 && selectGridData.moveCount>count)) {//反之不满足,这里更新选择的棋子位置chess = selectGridData.chess;chess.index = grid.i;//记录移动距离selectGridData.moveCount = count;//棋子步数加1player.step++;//获取玩家在自己阵营内的所有棋子let chesses2 = this.map.getPlayerChessesAtGrids(player.id);//判断这个玩家是否在游戏,还有步数if (player.rank==0 && player.step==MinStep) {//步数大于MinStep限制,还未走出自己阵营,就得通知这个玩家出局了...}//更新显示玩家的状态this.setData({players});}}//若只移动1个(走),就更新绘制棋子,换下一个玩家if (count==1){this.map.drawChesses(grid.i);this.setNextPlayer();return;}//剩下的,就是其它操作了,直接更新显示即可Object.assign(this.selectGridData, {chess, grid });this.map.drawChesses(grid.i);},

看上面,就会注意到,还有一些细节都在地图模块的方法里了,

上面还有个重要的方法setNextPlayer(),是处理换下一个玩家来,切换玩家前还要加个判断,

就是判断玩家输赢,最后若是剩下一个玩家还没赢的话,那么游戏就结束,代码如下

setNextPlayer(){const {players, currentPlayer } = this.data;//定义当前参与的玩家const player = players[currentPlayer];//找出当前玩家的所有棋子let chesses2 = this.map.getPlayerChessesAtGrids(player.id);//计算当前玩家是否全部占领对方的阵营let isWin = chesses2.reduce((current,next,index)=>{//棋子flag属性判断即可...});if (isWin) {let rank=0;//全部占领了,更新排名,不再参与...player.rank = rank+1;//可通过排名和参与人数判断是否到最后了if (player.rank+1 >= players.length) {//这里是最后的了,直接弹出游戏结束...this.showGameOver(`${player.id+1}号玩家赢了,成功占领对方的阵营`);return;}else{//提示一下,然后继续this.showModal(`${player.id+1}号玩家赢了,成功占领对方的阵营`);}}//换下一个玩家let current = (currentPlayer+1)%players.length;//此处省略了...this.setData({currentPlayer: current,players});this.showToast(`请${players[current].id+1}号玩家操作`);},

游戏测试

就讲到这里,跳棋游戏的实现思路大概清晰了吧,

调用的其它方法不对,虽然没有讲,但是,见其名知其意,相信自己可以实现出来的,

来看一下,游戏运行的效果动图如下,这是两个人参与的,测试完感觉没问题,

想看项目源码的,请点此查看,找到资源类别一栏(如果是手机上看可能找不到,就换成电脑浏览器访问),

资源列表里面,找到其中的跳棋游戏项目源码,请放心下载,感谢支持。

游戏启示:对此你有什么启发呢

选好目标,尽快占领,类似五行斗法里的相生相克,在这个游戏规则里,尽可能快速移动,落后就要挨打

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。