首页 >> 大全

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

2023-07-10 大全 34 作者:考证青年

可曾记得小时候玩过的飞行棋游戏,是90后的都有玩过吧,现在重温一下,这是一个可以二到四个人参与的游戏,通过投骰子走棋,一开始靠运气,后面还靠自己选择,谁抢占先机才能赢,还可以和小伙伴们一起玩,狭路相逢勇者胜,可谓趣味多多。

文章目录 测试游戏关于项目

创建小程序

打开电脑上的微信开发工具,如下图所示,新建一个小程序项目

例如,项目名称为-chess,依次选择

开始页面

新建的项目中,系统有自动创建的第一个页面,文件在/pages/index/index.wxml,就在这里添加布局,

考虑到游戏可视情况选择几人玩,要在布局里添加表单组件,让用户选择,

然后点击开始游戏即可,显示结果如下图所示

在对应的index.js逻辑文件里,添加开始游戏按钮点击事件,

在事件方法里写上代码调用系统的API如下,可打开游戏页面:

wx.({ url:"/pages/game/game", ... }) 还需要把用户选择的数据传过去;

游戏页面

接下来,新建一个文件夹game,建一个游戏页面,文件名都是game,

在文件/pages/game/game.wxml中,添加游戏页面的布局,代码如下

<view class="game-panel"><image class="canvas" src="{{bgImg}}" /><view class="float-panel id{{index}} {{index==current ? 'active' : ''}}" wx:for="{{toasts}}" wx:key="index"><view class="title"><text>{{item}}text>view>view><canvas class="canvas" id="canv" type="2d" disable-scroll="true" bindtouchstart="onTouchStart">canvas>
view>
view>
view>

游戏页面上只用了一个画布组件,一个背景图片,一个float-panel类的视图层显示数据,都是层层叠放显示的

游戏逻辑

就在game.js文件里写游戏逻辑,当页面加载渲染完成时,系统会调用其中的方法(),就在这里开始写,先获取组件的数据,

画棋盘

实现画棋盘的逻辑并不复杂的,可以这么做,先用绘制好网格,然后在对应的格子上绘制各种图案就可以,

就像平时用电脑办公的表格制作软件Excel,单元格可以合并的,如下图所示,

画棋盘的代码放在项目里的一个/utils/game-map.js文件中,作为模块来用

需要用模块的时候,用导入一下这个模块文件,看如下代码

import GameMap from '../../utils/game-map.js';Page({/*** 页面的初始数据*/data: {bgImg: '',//显示背景图片isAnimaging: false,//是否在动画中isNewAir: false,//是否再加棋子(派新飞机)toasts: ['x4', 'x4', 'x4', 'x4'],//飞机场显示的信息current: 0,//允许哪个玩家操作,默认第一个玩家(1号)currentColor: 'none',//设置游戏地图底部的控件背景颜色isSelectMode: false,//如果一个玩家派出多个棋子,会进入选择棋子状态isEndGame: false,//是否结束游戏},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {//获取canvas组件的数据wx.createSelectorQuery().select('#canv').fields({size: true,node: true}, res => {//...省略了//这里设置canvas组件的节点和绘制APIthis.canvasData = {canvas: res.node,context: res.node.getContext('2d')};//获取底部控件对象 组件 将用来操作this.ctrlPanel = this.selectComponent('#ctrl-panel');//初始化棋盘this.initChessPanel();//...省略了}).exec()},

从上面代码看出来了,调用方法()就可以绘制游戏地图,来看看怎么实现的呢

//设置初始游戏数据
const initGameData = {bgColor: '#55A3FF',//棋盘背景色preCurrentUid: -1,//上一个玩家id,-1表示没有
};
//用不同的四个颜色分别表示四个玩家的棋子
const initUserList = ['#E60116', '#FFC700', '#0277A8', '#08983F'].map((color, i) => {return {chessColor: color,//棋子颜色isJoin: this.joinUsers.indexOf(i) >= 0,//是否加入};
});
//这里调用模块文件game-map.js的GameMap地图对象,把上面的配置数据传入即可
const map = new GameMap(this.canvasData, initUserList, initGameData);
//调用地图对象的绘制地图上所有格子的方法,格子就是棋子的位置,生成图片数据
let bgImg = map.drawMapGrids();
let current = this.data.current;
//设置好地图数据,将来用到
this.gameData = map.gameData;
//更新显示到页面
this.setData({bgImg,//把地图显示到背景中currentColor: this.gameData.userlist[current].chessColor,gameToast: `${current + 1}号玩家点击投骰子`
});
//省略了...

棋盘上各种颜色都是可以替换的,例如到了晚上,背景就显示漆黑的夜空;

_微信小程序游戏开发教程_微信小程序游戏开发价格

其中是一个游戏地图对象,在模块文件中有实现绘制地图,能给出坐标,

想想生活中用到的地图导航,作用一样的,

其中的是从开始页面传来的数据,表示有哪些玩家加入游戏

把画好的棋盘生成一个图片数据,设置到背景图片组件中显示,

画出来后,效果如下图

画棋子

地图有了,再把所有棋子画出来,

开始玩的时候,棋子都是放在飞机场上的,每个玩家都有四个棋子,

在调用方法()里面继续写,代码如下,

//给地图设置棋子上的图像,就是飞机图片
map.setChessImg('/static/fly.png',()=>{//设置好,就可以绘制棋子了this.redraw();
});

然后调用方法()去绘制所有棋子,代码如下

const { canvas, context: ctx } = this.canvasData;//canvas组件的数据
const { grids, userlist, size, chessImg } = this.gameData;//游戏的数据
const r = size / 2;//棋子半径
const { toasts } = this.data;//显示游戏状态的数据
//因为这是重绘方法 使用前先清空画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
//把参与的玩家的棋子全部画出来
userlist.forEach((user, uid) => {let chesses = [];//记录可以绘制的棋子user.chesses.forEach((chess, i) => {//这里判断一下棋子的状态,如没有隐藏,且棋子有指向棋盘上的坐标,就可以加到记录中if (chess.isHide!=true && chess.gridIndex >= 0) {//...省略了继续判断逻辑}});//绘制棋子的chesses.forEach((chess, i) => {let g = grids[chess.gridIndex];//...省略了//绘制棋子的方法this.drawChessAtLocation(user, g);//判断棋子的数量,这是在同一个坐标上被叠放的棋子if (chess.count > 1) {let p = {//...};//给棋子画上数量标记ctx.fillText('' + chess.count, p.left, p.top);}});//判断这个玩家是否加入游戏if (user.isJoin) {//绘制玩家飞机场上的棋子user.chesses.forEach(chess => {if (chess.gridIndex < 0) {ctx.drawImage(chessImg, chess.left - r, chess.top - r, size, size);}});//更新玩家的信息toasts[uid] = `${uid + 1}号玩家`;} else {toasts[uid] = ``;}
});
//更新显示
this.setData({toasts
})

其中用到了方法(user, g),这是实现在地图上画棋子的,只传入参数用户数据和格子坐标

把所有棋子画出来后, 效果图如下

投骰子

由于绘制投骰子动画会变得复杂,需要写很多代码,不如做一下布局,这样好弄点,省了不少代码吧,

就用控件组件来代替投骰子,控件组件放在棋盘的底部,在文件/pages/game/game.wxml中加上如下布局代码

<view><block wx:if="{{isEndGame}}"><text>{{gameToast}}text>block><block wx:else><ctrl-panel id="ctrl-panel" isGameEnd="{{isGameEnd}}" isDisabled="{{isAnimaging || isSelectMode}}" bindstart="onClickStart" bgColor="{{currentColor}}"><text>{{gameToast}}text>ctrl-panel>block><view>

这个组件ctrl-panel是放在别处的,也是自定义组件,需要的时候可以拿来直接用,用这个来选择操作再好不过了,

看看控件在游戏页面的布局显示效果,如下图

这控件不仅仅是用来投骰子哦,还有一些细节待发现

游戏规则

接下来,写到游戏规则了,实现过程会复杂一些,

再理清一下思路,想想应该怎么做才合适呢,

飞行棋的游戏规则大致是这样的,没有玩过的可以了解一下:

按照飞行棋的游戏规则,实现游戏逻辑,觉得难不难呢,可以分三步实现,能把难度降低,

1. 投骰子

要移动棋子前,先投骰子,这部分靠运气,通过概率分配实现,

_微信小程序游戏开发教程_微信小程序游戏开发价格

投骰子的逻辑在组件ctrl-panel中有实现,代码如下

// 取1~6之间的随机数
let num = Math.floor(Math.random()*6)+1;

可见Math的一些函数有经常用到

投完骰子后,组件ctrl-panel会传来事件,调用一个方法(e),

是写到game.js里面的,代码如下,

const { stepNum } = e.detail;
//这里记录一下步数
this.stepNum = stepNum;
//记录玩家在棋盘中的所有棋子id
let indexes = [];
//...省略了
//定义走下一步的方法
let next = () => {//判断有没有派过新飞机,以及棋子有2个以上,让玩家先选择棋子再走if (this.isNewAir != true && indexes.length > 1) {this.setData({isSelectMode: true,//设置选择棋子状态gameToast: `${current + 1}号玩家选择棋子`});return;}//开始动画 看出棋子移动效果this.startAnimation(false, () => {//动画结束会执行到这里,判断一下是否派过新飞机了,重置一下状态if (this.isNewAir) this.isNewAir = false;});
};
//获取步数后,判断是否是6点,是的话,让用户选择是否再拿一个棋子(派新飞机)
if (stepNum == 6 && this.isNewAir != true && indexes.length > 0) {if (user.chessIndex >= 0) {//...省略了}//下一步next();return;
}
//没有就继续,下一步
next();

2. 移动棋子

获取步数后,就可以移动棋子了,调用的方法(used, ),

需要通过动画实现棋子一步一步走的效果,代码如下

const { current } = this.data;//表示当前的玩家id
const { grids, size, userlist } = this.gameData;//游戏数据
this.gameData.preCurrentUid = current;//记录到上一个
//省略了...
//获取步数
let num = this.stepNum;
//动画结束方法
let end = (index) => {//走完棋子,动画也就结束了,调用此方法处理一下this.endAnimation(chess, index, used, callback);
};
//下一步移动方法
let next = (i) => {//省略了...//棋子位置变了,重新画个棋子this.drawChess(user, d);//如果步数没走完,继续调用下一步方法setTimeout(() => next(i + 1), StepTimeMs);
};
//获取棋子在地图中指定位置上的格子数据
let d = grids[chess.gridIndex];
//判断是否到了自己开始升降的位置,nodes是升降点的地图数据
if (d.nodes && d.nodes[0].grid.cid == current) {//省略了...this.takeGridChess(user, () => {this.enterNextNode(user, chess, d.nodes, num, chess.nodeIndex);});return;
};
//调用带走的棋子方法
this.takeGridChess(user, () => next(1));

调用移动棋子的方法参数used, 分别是是否使用过,动画结束时会回调,

其中方法()就是把正在移动的棋子拿走,然后重新绘制整个棋子,实现动画效果,

方法()就是在进入升降航道路线时才调用的

还有,动画结束需要处理的方法是(, index, used, ),

这实现了棋子到目标格子上做出反应处理的逻辑,代码如下

const { current } = this.data;
const { userlist, grids, size } = this.gameData;
const user = userlist[current];
const chess = user.chesses[user.chessIndex];
const gridIndex = chess.gridIndex;
let end = () => {//...省略了//处理结束,更新一下显示数据this.setData({isAnimaging: false,gameToast: `${uid + 1}号玩家点击投骰子`});//重新绘制所有棋子this.redraw();//需要结束回调时 就回调if (callback instanceof Function) callback();
};
switch (gridIndex) {case 6:case 19://...{//执行到这里,说明是走到可以直线飞行的格子上,调用控件组件让玩家选择要不要直线飞行this.ctrlPanel.showSelectAirAtLineModal(res => {if (!res.confirm) {//没选择直线飞,就继续判断this.isBeatBackChess(gridIndex,current);end();return;}let i = 0;//直线飞行动画const next = () => {//...省略了i++;if(i>10) {//...省略了this.isBeatBackChess(chess.gridIndex, current, gridIndex + 6);end();return;}//...省略了setTimeout(next, 100);//0.1s移动一次};			this.takeGridChess(user, next);});return;}default:{//...省略了//调用判断是否碰到对方的棋子方法this.isBeatBackChess(chess.gridIndex, current);}
}
end();

3. 选择棋子

只有当玩家的飞机场里至少有两个都出发了,才是可以选择棋子的,

在game.js里写,是组件绑定是触摸事件方法(e),选择棋子的代码如下

if (this.data.isEndGame) return;//游戏结束时,不处理操作
const touch = e.touches[0];
const { userlist, grids, size } = this.gameData;
const { current, isSelectMode } = this.data;
// 获取正在操作的玩家数据
let user = userlist[current];
let chessIndex = user.chesses.findIndex((c, i) => {//...省略了
});
//判断是否选择到棋子
if (chessIndex >= 0) {//更新玩家选择的棋子user.chessIndex = chessIndex;//判断是否是选择状态,若是的话,就开始走棋动画if (isSelectMode) {this.startAnimation();}
}

测试游戏

就讲到这里,篇幅有限,上面都有讲了重点的,还有几个方法就不讲了,

可以看看项目源码,直接运行,看到有感觉,里面代码并不多,可以参考学习一下,

最后看一下飞行棋小程序的运行效果图,怎么样,可以吧

若想一起玩的人数不够4个,在开始页面上是可以选择人数的

三缺一,没事儿,让我的小伙伴们能一起玩就对了 关于项目

如果要看项目源码 请点这里看,在资源一栏下可以找到飞行棋的源码,放心下载,感谢支持!

如果是在手机上看会有可能找不到资源一栏,就在电脑浏览器上看,

喜欢的话,点个赞收藏吧,遇到什么不明白的地方请主动留言,作者看到会回复。

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了