👬Django框架课—7实现联机对战
password
icon
AI summary
type
status
date
slug
summary
tags
category
Property
Oct 21, 2024 12:11 PM
实现联机对战✨统一长度单位✨地图渲染地图 16:9 等比例缩放地图居中解决地图 resize时,会出现渐变成黑色的情况✨元素渲染玩家 Player火球 Fireball粒子 particle✨增加 “联机对战” 模式✨配置 django_channels安装 channels_redis配置 acapp/asgi.py配置 acapp/settings.py配置 game/routing.py编写 game/consumers启动 django_channels✨建立 WSS 连接路由 routing前端 js✨编写同步函数create-player✨redis 调试语句move-toshoot-fireballattack✨游戏的小优化多人模式下游戏没有开始前,玩家不可以移动技能 CD用图片来渲染技能 CD✨添加一个闪现技能单机部分联机部分
实现联机对战
✨统一长度单位
由于联机对战的时候,每个用户的客户端长宽不一样,在之前完成的游戏界面里,我们会根据当前客户端的大小,进行渲染
但是在联机对战的时候,应当让所有玩家的游戏界面保持同步才可以,所有,就引入了 统一长度单位 的目标
✨地图渲染
地图 16:9 等比例缩放
实现逻辑:根据当前用户的客户端大小,统一渲染成 16:9的游戏界面,且随着用户调整窗口大小,也动态调整
js/src/playground/zbase.js
js/src/playground/game_map/zbase.js
地图居中
直接把 canvas 元素,用相对位置居中即可
css/game.css
解决地图 resize时,会出现渐变成黑色的情况
原由是因为我们的实现逻辑是:每帧会渲染一层半透明的黑色背景,也就造就了一开始会出现灰屏的情况,解决方法很简单,直接 resize完,强制涂一层不透明的黑色即可
js/src/playground/game_map/zbase.js
✨元素渲染
地图随着尺寸等比例放大缩小的同时,地图内的其他元素也应与背景一同等比例放大缩小,因此,我们只需把元素全部设为相对大小即可,用我们先前设置的
playground.scale
值即可玩家 Player
初始化的时候,转为传递
scale
的比例值js/src/playground/zbase.js
js/src/playground/player/zbase.js
火球 Fireball
js/src/playground/skill/fireball/zbase.js
粒子 particle
js/src/playground/particle/zbase.js
✨增加 “联机对战” 模式
为了区分:用户自己,机器人,联机玩家,需要把
is_me
改成字符串,用以表示不同Player
menu/zbase.js
playground/zbase.js
playground/player/zbase.js
✨配置 django_channels
django_channels 就是基于 wss协议的一种实现。
wss 是 web-socket (ws)协议的安全模式,支持 C/S 下的双向通信(HTTP协议只支持单向通信)
安装 channels_redis
配置 acapp/asgi.py
固定写法,内容如下:
配置 acapp/settings.py
在
INSTALLED_APPS
中添加 channels
,添加后如下所示:然后在文件末尾添加:
配置 game/routing.py
这一部分的作用相当于
http
的 urls
内容如下:
编写 game/consumers
这一部分的作用相当于
http
的 views
参考示例:
consumers/multiplayer/index.py
启动 django_channels
在
~/acapp
目录下执行:✨建立 WSS 连接
路由 routing
game/routing.py
前端 js
playground/zbase.js
playground/socket/multiplayer/zbase.js
✨编写同步函数
一共需要完成四个通信:
(通信的逻辑基本都是现在本地完成,然后将结果返回给服务器,服务器再分发给其他客户端,达成同步)
- create-player :在所有玩家的游戏界面,创建一个新加入的玩家
- move-to :在所有玩家的游戏界面,讲一个角色移动到一个位置
- shoot-fireball :在所有玩家的游戏界面,让一个角色发射一个火球
- attack :在所有玩家的游戏界面,让一个角色被攻击
一场游戏里,所有的元素(玩家,火球等)都需要唯一的标识,来方便同步,为此,我们可以直接修改一下游戏引擎,对于每个元素都创建我们需要的唯一标识
playground/ac-game-object/zbase.js
playground/zbase.js
playground/socket/multiplayer/zbase.js
接着,利用通信的方式,使得每个窗口内,逻辑上相同的元素,其
uid
也相同即可原则是:哪个窗口创建的元素,就用他创建时的
uid
作为整个项目运行时的 uid
然后,我们打算用 redis来实现存储每个游戏房间,以及元素,并初始默认设定每个房间上限 3 人
create-player
- 后端
settings.py
consumers/multiplayer/index.py
- 前端
✨redis 调试语句
打开 shell 交互
然后用 py3 交互进行 cache 调试
到目前为止,便可以在不同的窗口渲染同一批玩家了
move-to
- 前端:客户端的通信的发出和接受函数
js/src/playground/
为了让游戏界面中对于要移动的元素做出移动动作,需要对
move_to
函数做出一些修改首先要标识出当前为多人模式,然后模式为多人模式时,每次移动都会触发一次通信
playground/zbase.js
playground/player/zbase.js
- 后端
consumers/multiplayer/index.py
shoot-fireball
- 优化一下火球元素
用一个数组来存一个玩家发射的所有火球,以便于子弹消失时,将他们找出并对应删掉
playground/player/zbase.js
playground/skill/fireball/zbase.js
js/src/playground/socket/multiplayer/zbase.js
- 后端
consumers/multiplayer/index.py
attack
为了只让一个客户端进行攻击命中的判断,因此只有发出方的火球才做碰撞检测
其他客户端对于该火球只有动画效果
又由于碰撞检测是在一台客户端上进行的,因此多端之间可能会存在同步上的延迟
为此的解决方法是:碰撞检测成功时,强制把被击中玩家移动到发起方客户端中的位置,以避免击中延迟上发生的事情
- 前端
playground/skill/fireball/zbase.js
playground/player/zbase.js
js/src/playground/socket/multiplayer/zbase.js
- 后端
consumers/multiplayer/index.py
✨游戏的小优化
多人模式下游戏没有开始前,玩家不可以移动
为此我们先引入一个状态机:
'waiting' -> 'fighting' -> 'over'
来标识当前游戏进行的状态。然后用一个
notice_board
计分板在前端显示出来,实现的逻辑就是:游戏初始时为 waiting
状态,房间内人数满。
3 人时,才会进入 fighting
,角色死亡时为over
且发射火球,移动等行为,当且仅当玩家状态为 fighting
时,才可以做。然后设定火球技能的 cd 为 3 秒,且在游戏进入
fighting
时,先自动进入 cd 状态。这样就实现了初始 3 秒内,任何玩家不可攻击。
js/src/playground/notice_board/zbase.js
js/src/playground/zbase.js
js/src/playground/player/zbase.js
技能 CD
给火球技能设置 3s 的 cd,实现逻辑很简单,设定一个 cool_time
变量,每次渲染的时候减去上次渲染的时间间隔
然后 cool_time 为 0 时,技能才可以成功释放
另外修改冷却时间,只用修改自己的即可
js/src/playground/player/zbase.js
用图片来渲染技能 CD
js/src/playground/player/zbase.js
✨添加一个闪现技能
单机部分
js/src/playground/player/zbase.js
联机部分
js/src/playground/socket/multiplayer/zbase.js
consumers/multiplayer/index.py
大功告成 =w=
上一篇
初见Rust:编程界的原神
下一篇
ML实践(Pytorch篇)
Loading...