我正在参加掘金社区游戏创意投稿大赛个人赛,详情请看:游戏创意投稿大赛。
阴阳五行转是一款结合阴阳五行原理实现的一款对弈小游戏。
游戏体验地址:阴阳五行转。
创意思路
起初的想法来源五行相生相克之理,以五行为棋子,有生克之变。
以太极阴阳为棋盘,圆环八个棋子对应八卦。
对弈时,每轮下子可棋盘顺时旋转一个45°,使其一直存在变化之中。
一步一步走太慢了,又设置了多步走,和加入中心点棋位,使其可以直接到对面棋位,同时可以随机变化。
总之围绕五行生克变化,同时棋位变化。哈哈,还有点意思,但就是还有点费脑。
要是棋逢对手,发现好像也能难决胜负。的确,长远的看好,好似一切都在轮回之中。
玩法说明
进入页面看下游戏规则
⬇
点击开始游戏
⬇
取个帅气的名字加入
⬇
点击去准备等待其他玩家邀请 或者 直接邀请已准备玩家
⬇
去玩吧开始游戏
游戏规则
-
棋盘有 9 个下子位置
-
双方各执五子,分别为:金,木,水,火,土
-
双方轮流下子,每轮下完后棋盘会自动顺时针旋转45°
-
棋盘内,棋子每一轮操作可顺时针拖动或者转换棋子:
-
· 棋子可顺时针拖动前方连续任意空白位置,若前方有子与其相克则会被吃掉,否则不能前进。
-
· 双击棋子会变化成相生的棋子,而中心棋子会随机变化
-
当棋子走到太极两眼相连位置时可以进入中心或对面位置
-
博弈后,当一方没有棋子时,棋多者胜。
额,人机模式还没有(没写过), 若没其他人玩只能自己左右手互博了(隐私模式 [ InPrivate 窗口] 打开另一个窗口,避免localStorage保存重名)
玩过几局大概就知道五行相生相克了
五行相生相克图
技术实现
想好了,撸起袖子就是干。
遇到了第一个技术选型的问题。
想到的就是各个游戏引擎,cocos, egret, laya, unity等。
结合实际发现我只是了解并不熟悉(第一次写)
还是用我熟悉的js+html+css写吧,简单,纯粹。
虽然用canvas绘图比操作DOM会更节省性能,但这个游戏也不复杂,先现实再说。
想到最近world游戏很火,我想就参考了大致的布局。
于是整体页面框架有了,但游戏的核心逻辑还得自己写
主要的功能模块:棋盘布局,棋子放置,对弈通信等
首先是实现棋盘布局,通过三角函数sin,cos可以确定8个棋子的位置布局
// 棋子位置信息
function pieceItemStyle(piece: Piece, index: number) {
const halfCheckBoardSize = checkerboard.height / 2;
const halfPieceSize = checkerboard.pieceHeight / -2;
const pieceItemRadian = ((index - 2) * 2 * Math.PI) / count.value;
return {
top:
halfCheckBoardSize +
halfCheckBoardSize * Math.sin(pieceItemRadian) +
"px",
left:
halfCheckBoardSize +
halfCheckBoardSize * Math.cos(pieceItemRadian) +
"px",
transform: `translate(${halfPieceSize}px, ${halfPieceSize}px) rotate(${
(360 / count.value) * index
}deg)`,
};
}
再然后就是要确定被选中棋子可放置的位置的逻辑。
这里涉及五行生克,多步走的位置,以及过中心棋位的逻辑
watchEffect(() => {
if (draging.piece && draging.piece.name) {
if (draging.piece.isPlay) {
if (draging.piece.isCenter) {
connectCenterIndexs.value.forEach((index) => {
indexCanMoveHandler(index);
});
} else {
// 遍历圆环棋位是否下子
for (
let i = selectedIndex.value + 1, last = selectedIndex.value + pieces.value.length;
i < last;
i++
) {
let index = i % pieces.value.length;
indexCanMoveHandler(index);
let piece = pieces.value[index];
if (piece.name) {
break;
}
}
// 判断是否过圆心下子,如果是,则可以移动到中心,或者对面
if (connectCenterIndexs.value.includes(selectedIndex.value)) {
if (
!centerPiece.value.name ||
(centerPiece.value.name &&
isRivalCamp(draging.piece, centerPiece.value) &&
isRestriction(draging.piece, centerPiece.value))
) {
centerPiece.value.canMove = true;
}
if (!centerPiece.value.name) {
let oppositeIndex = getOppositeIndex(selectedIndex.value);
indexCanMoveHandler(oppositeIndex);
}
}
}
} else {
// 第一次上子,不可下到中心位置
pieces.value.forEach((piece, index) => {
if (!piece.name) {
canMoveIndexs.value.push(index);
piece.canMove = true;
}
});
}
} else {
// 未选择,则取消
canMoveIndexs.value = [];
centerPiece.value.canMove = false;
pieces.value.forEach((piece, index) => {
piece.canMove = false;
});
}
});
最后对弈通信,这里通过websocket进行对应的通信,用到了socket.io库
// 对弈数据交换逻辑
async exchange() {
const { ctx, app, service, logger } = this
const nsp = app.io.of('/wuxing')
const socket = ctx.socket
const currentId = ctx.socket.id
let startTime = 0
// 获取客户端传来的数据包
let message = ctx.args[0] || {}
if (typeof message === 'string') {
message = JSON.parse(message)
}
const { target, payload } = message.target
switch (message.action) {
case ExchangeEvent.PLAYER_STATE:
// 更新玩家状态
if(payload.state) {
let stateData = { state: payload.state }
const updatePlayerInfo = await service.wuxing.player.updatePlayerInfo(currentId, stateData)
}
// 更新玩家列表
const players = await service.wuxing.player.getPlayerList()
const msg = ctx.helper.parseMsg(ExchangeEvent.PLAYER_LIST, {players}, { target })
nsp.to(hall).emit('exchange', JSON.stringify(msg)) // 往大厅房间,发送信息
}
break
case ExchangeEvent.JOIN:
// 加入游戏
break;
case ExchangeEvent.START:
// 开始游戏
break;
// 其他游戏状态交互操作
....
需要提前了解socket.io中定义命名空间,房间,socket之间的关系
深入理解 Socket.io 中的 Room 与 Namespace
比如一进来,所有人都会加大厅的房间,用于同步玩家的状态,同时显示玩家列表,而进入游戏则创建一个单独的房间用游戏双方的游戏通信。 类似于聊天室的群聊和私聊的区别
另外,由于我这边后端用的是egg.js框架,线上环境会开启多个进程,sticky 模式,
对应socket.io Using multiple nodes | Socket.IO
技术栈
前端:vite, vue3, vueuse
后端:egg.js, socket.io, redis
优化点
人机模式(没写过🤯)
排行榜(未加入用户系统)
参考
总结
好想法是很难得的。
我这个小游戏也是在老祖宗阴阳五行的理论下,做的微微创新而已。
技术实现并不难,但布局样式费了不少时间,交互逻辑清晰很重要。有想法就去实现。
最后,欢迎各位路过客官瞧一瞧,看一看
欢迎体验吐槽
游戏体验地址:阴阳五行转。