创建像 Skribbl.io 这样的实时多人游戏是一项令人兴奋的挑战,它结合了 Web 开发的各个方面。在这篇文章中,我将讨论我在构建实时克隆时的实现和思考,以及如何处理基于回合和计时器系统的游戏
如果您想查看该项目的源代码,您可以在 Github 上找到它
技术堆栈
在深入了解细节之前,我们先简要了解一下该项目所使用的技术堆栈:
- Node.js:用于后端服务器。
- Socket.IO:用于实时通信。
- Redis:用于高效的数据处理。
- Vite:使用 React 进行快速开发。
- TypeScript:用于前端和后端的类型安全。
- React:用于构建用户界面。
- Docker:用于容器化应用程序。
设置后端
后端由 Node.js 和 Socket.IO 提供支持,非常适合处理实时交互。以下是主要组件的快速概述:
1. 用于实时通信的WebSockets
Socket.IO 允许服务器和客户端之间的无缝通信。我们用它来处理玩家加入房间、开始游戏、发送绘图数据等事件。
2. 房间系统
每个游戏都在一个唯一的房间中托管,由房间 ID 标识。玩家使用此 ID 加入房间并与同一房间中的其他人互动。该系统还处理玩家连接和断开连接。
但是这里我们有一个问题,如果服务器崩溃了,我们如何确保我们的服务器保留游戏中的数据
这里我们使用一个速度快的数据库,并且也是与服务器分开的主体
Redis 是此类用例的绝佳选择。它是一个内存数据库,速度很快,可以在不同的服务器上单独运行
我们稍后会在帖子中详细讨论这一点。
3. 事件处理
服务器监听并发出各种事件:
-
客户端事件:连接、断开连接、joinRoom、leaveRoom、startGame、draw、guess、changeSettings、wordSelect
-
服务器事件:joinedRoom、playerJoined、playerLeft、gameStarted、gameEnded、drawData、guessed、turnEnded、chooseWord、wordChosen、settingsChanged、guessFail
开发前端
对于前端,我使用了 React 和 TypeScript 以及 Vite,以获得流畅的开发体验。
1. 构建用户界面
用户界面包括用于绘图、猜测和管理游戏设置的组件。 React 基于组件的架构可以轻松创建动态且响应式的 UI。
2. 处理游戏状态
前端管理游戏状态,包括玩家得分、当前回合和绘图数据。 TypeScript 确保数据结构定义明确且无错误。
3. 实时更新
使用Socket.IO,前端根据服务器事件实时更新。例如,当玩家抽奖时,抽奖数据会发送给房间内的所有客户端。
游戏状态管理
有效的游戏状态管理对于确保 Skribbl.io 这样的实时多人游戏的流畅和愉快的体验至关重要。以下详细介绍了如何管理游戏状态的各个方面:
玩家加入和离开
管理玩家加入和离开房间涉及几个关键步骤:
-
加入:
-
事件发送:当玩家想要加入房间时,他们会向服务器发送带有房间 ID 的 joinRoom 事件。
-
验证:服务器验证房间ID并检查房间是否存在。
-
添加玩家:如果有效,则将玩家添加到房间的玩家列表中。然后,服务器更新游戏状态并向房间中的所有客户端发出playerJoined 事件,通知他们新玩家的到来。
-
UI 更新:在前端,新玩家的存在会反映在房间的玩家列表中,确保每个人都能看到最新的玩家名单。
-
离开:
-
事件发射:当玩家决定离开时,他们会向服务器发送一个leaveRoom事件。
-
玩家移除:服务器将玩家从房间的玩家列表中移除,并相应更新游戏状态。
-
通知:服务器向所有剩余的客户端发出一个playerLeft事件,通知他们玩家已经离开房间。
-
UI 更新:前端通过从玩家列表中删除玩家并在必要时调整任何正在进行的游戏机制来反映此更改。
选词
选择一个单词并管理轮到谁选择涉及多种机制:
-
当前玩家回合:
-
轮次管理:服务器维护轮到谁选择单词的记录。这是由游戏状态管理的,其中包括指示当前玩家 ID 的属性。
-
单词选择提示:轮到玩家选择单词时,他们会从服务器收到一个chooseWord事件,提示他们选择一个单词。
-
防止单词泄露:
-
回合限制访问:所选单词不会立即广播给其他玩家。相反,它仅在轮到抽屉时才共享,以防止任何不公平的优势。
-
事件发射:一旦抽屉选择了单词,服务器就会向所有玩家发出一个 wordChosen 事件。此事件包括一个通知,表明该单词已被选择并准备好猜测。
-
单词选择通知:
-
广播:wordChosen 事件包括一个已选择单词的通知,该通知会发送给房间中的所有玩家。
-
前端处理:在客户端,玩家进行更新以指示绘图阶段已经开始,他们现在可以开始猜测。
处理单词选择的超时
处理当前玩家可能延迟单词选择的情况:
-
自动分配:
-
超时机制:服务器实现了一个计时器,该计时器在轮到玩家选择单词时启动。如果玩家没有在规定时间内选择单词,则会触发超时事件。
-
单词分配:服务器自动从预定义列表中选择一个单词并将其分配给玩家。这可以确保游戏继续进行,不会出现不必要的延迟。
-
通知:然后发出一个 wordChosen 事件,通知所有玩家单词已被分配并且绘图阶段即将开始。
绘图数据处理
处理绘图数据对于维持玩家之间的同步至关重要:
-
实时绘图:
-
绘图事件:玩家使用绘图事件将绘图数据发送到服务器。该数据包括画笔颜色、半径和绘制点的坐标。
-
广播:服务器接收此数据并使用drawData事件将其广播到房间中的所有客户端。这确保了每个玩家的画布都实时更新为最新的绘图信息。
处理玩家猜测事件
管理玩家的猜测涉及处理和验证每个猜测:
-
猜测提交:
-
事件处理:当玩家进行猜测时,他们会向服务器发送一个带有猜测词的猜测事件。
-
验证:服务器处理猜测,并根据正确的单词进行检查。如果猜测正确,服务器会更新游戏状态和玩家得分。
-
播出结果:
-
猜测结果:服务器向所有玩家发出猜测事件,指示猜测是否正确。
-
UI 更新:在前端,结果向所有玩家显示,显示谁猜对了并更新游戏进度。
绘画和猜测的超时
管理时间限制是保持游戏吸引力的关键:
-
抽奖时间结束:
-
时间管理:每轮都有规定的抽奖时间限制。服务器会跟踪这个时间,并在时间到期时触发turnEnded事件。
-
过渡:此事件标志着抽奖阶段的结束,游戏过渡到猜测阶段或下一轮。
-
所有玩家都猜到了:
-
猜测完成:如果所有玩家在时间耗尽之前猜出单词,服务器会提前触发turnEnded事件。
-
游戏流程:此事件会向所有客户端更新猜测阶段已完成并将游戏过渡到下一个阶段或回合。
这种管理游戏状态的方法可确保所有玩家获得流畅、互动且公平的体验,从而增强游戏的整体乐趣。
结论
构建 Skribbl.io 克隆涉及实时通信、游戏状态管理和用户交互的复杂相互作用。通过这个项目,我们探索了游戏开发的各个方面,从处理玩家连接和单词选择到管理绘图数据和玩家猜测。
要点
-
实时通信:利用 Socket.IO 实现无缝和交互式游戏,确保所有玩家保持同步。
-
状态管理:有效处理游戏状态(例如玩家加入、单词选择和绘图数据)对于流畅的用户体验至关重要。实施超时和自动分配可确保游戏顺利进行。
-
用户体验:保持引人入胜且响应迅速的界面可以提高玩家满意度。对绘画和猜测等动作的清晰反馈,加上及时的更新,可以让玩家了解情况并投入到游戏中。
下一步
如果您有灵感进一步推进这个项目,请考虑:
-
添加新功能:实施额外的游戏模式、自定义或增强功能,使游戏更加动态。
-
优化性能:探索提高性能的方法,例如优化绘图数据传输或减少延迟。
-
增强 UI/UX:根据玩家反馈完善用户界面和体验,让游戏更有趣。
这个项目是一次令人兴奋的实时游戏开发之旅,结合了各种技术和技巧来创造有趣且引人入胜的多人游戏体验。我希望本文能够为游戏状态管理提供宝贵的见解,并激励您在游戏开发领域进行更多探索。
请随时在下面的评论中分享您对此项目的想法、问题或改进。快乐编码!
以上是构建 Skribbl.io 克隆:从概念到完成的详细内容。更多信息请关注PHP中文网其他相关文章!