当前位置: 首页 > news >正文

深圳快速网站制作服免费php网站空间

深圳快速网站制作服,免费php网站空间,wordpress搭建知识库,网站建设五合一笔记内容转载自 AcWing 的 Django 框架课讲义#xff0c;课程链接#xff1a;AcWing Django 框架课。 CONTENTS 1. 编写移动同步函数move_to2. 编写攻击同步函数shoot_fireball3. 编写击中判定同步函数attack4. 优化改进 1. 编写移动同步函数move_to 与上一章中的 create_pl…笔记内容转载自 AcWing 的 Django 框架课讲义课程链接AcWing Django 框架课。 CONTENTS 1. 编写移动同步函数move_to2. 编写攻击同步函数shoot_fireball3. 编写击中判定同步函数attack4. 优化改进 1. 编写移动同步函数move_to 与上一章中的 create_player 同步函数相似移动函数的同步也需要在前端实现 send_move_to 和 receive_move_to 函数。我们修改 MultiPlayerSocket 类在目录 ~/djangoapp/game/static/js/src/playground/socket/multiplayer 中 class MultiPlayerSocket {constructor(playground) {this.playground playground;// 直接将网站链接复制过来将https改成wss如果没有配置https那就改成ws然后最后加上wss的路由this.ws new WebSocket(wss://app4007.acapp.acwing.com.cn/wss/multiplayer/);this.start();}start() {this.receive();}receive() {let outer this;this.ws.onmessage function(e) {let data JSON.parse(e.data); // 将字符串变回JSONlet uuid data.uuid;if (uuid outer.uuid) return false; // 如果是给自己发送消息就直接过滤掉let event data.event;if (event create_player) { // create_player路由outer.receive_create_player(uuid, data.username, data.avatar);} else if (event move_to) { // move_to路由outer.receive_move_to(uuid, data.tx, data.ty);}};}send_create_player(username, avatar) {...}receive_create_player(uuid, username, avatar) {...}// 根据uuid找到对应的Playerget_player(uuid) {let players this.playground.players;for (let i 0; i players.length; i) {let player players[i];if (player.uuid uuid)return player;}return null;}send_move_to(tx, ty) {let outer this;this.ws.send(JSON.stringify({event: move_to,uuid: outer.uuid,tx: tx,ty: ty,}));}receive_move_to(uuid, tx, ty) {let player this.get_player(uuid);if (player) { // 确保玩家存在再调用move_to函数player.move_to(tx, ty);}} }然后修改一下后端通信代码~/djangoapp/game/consumers/multiplayer 目录中的 index.py 文件 from channels.generic.websocket import AsyncWebsocketConsumer import json from django.conf import settings from django.core.cache import cacheclass MultiPlayer(AsyncWebsocketConsumer):async def connect(self):...async def disconnect(self, close_code):...async def create_player(self, data): # async表示异步函数...async def group_send_event(self, data): # 组内的每个连接接收到消息后直接发给前端即可await self.send(text_datajson.dumps(data))async def move_to(self, data): # 与create_player函数相似await self.channel_layer.group_send(self.room_name,{type: group_send_event,event: move_to,uuid: data[uuid],tx: data[tx],ty: data[ty],})async def receive(self, text_data):data json.loads(text_data)print(data)event data[event]if event create_player: # 做一个路由await self.create_player(data)elif event move_to: # move_to的路由await self.move_to(data)最后我们还需要调用函数首先我们需要在 AcGamePlayground 类中记录下游戏模式 mode class AcGamePlayground {...// 显示playground界面show(mode) {...this.mode mode; // 需要将模式记录下来之后玩家在不同的模式中需要调用不同的函数this.resize(); // 界面打开后需要resize一次需要将game_map也resize...}... }然后在 Player 类中进行修改当为多人模式时需要广播发送 move_to 信号 class Player extends AcGameObject {...add_listening_events() {let outer this;this.playground.game_map.$canvas.on(contextmenu, function() {return false;}); // 取消右键的菜单功能this.playground.game_map.$canvas.mousedown(function(e) {const rect outer.ctx.canvas.getBoundingClientRect();if (e.which 3) { // 1表示左键2表示滚轮3表示右键let tx (e.clientX - rect.left) / outer.playground.scale;let ty (e.clientY - rect.top) / outer.playground.scale;outer.move_to(tx, ty); // e.clientX/Y为鼠标点击坐标if (outer.playground.mode multi mode) {outer.playground.mps.send_move_to(tx, ty);}} else if (e.which 1) {...}});...}... }现在即可实现多名玩家的同步移动。当 A 窗口中的玩家移动时首先该窗口Player 类的监听函数会控制该玩家自身进行移动接着判定为多人模式因此再调用 MultiPlayerSocket 类中的 send_move_to 函数向服务器发送信息通过 WebSocket 向服务器发送一个事件接着服务器端~/djangoapp/game/consumers/multiplayer/index.py 文件中的 receive 函数会接收到信息发现事件 event 为 move_to就会调用 move_to 函数该函数会向这个房间中的其他所有玩家群发消息每个窗口都会在前端MultiPlayerSocket 类中的 receive 函数接收到信息通过事件路由到 receive_move_to 函数该函数就会通过 uuid 调用每名玩家的 move_to 函数。 2. 编写攻击同步函数shoot_fireball 由于发射的火球是会消失的因此需要先将每名玩家发射的火球存下来此外我们实现一个根据火球的 uuid 删除火球的函数在 Player 类中进行修改 class Player extends AcGameObject {constructor(playground, x, y, radius, color, speed, character, username, avatar) {...this.fire_balls []; // 存下玩家发射的火球...}...// 向(tx, ty)位置发射火球shoot_fireball(tx, ty) {let x this.x, y this.y;let radius 0.01;let theta Math.atan2(ty - this.y, tx - this.x);let vx Math.cos(theta), vy Math.sin(theta);let color orange;let speed 0.5;let move_length 0.8;let fire_ball new FireBall(this.playground, this, x, y, radius, vx, vy, color, speed, move_length, 0.01);this.fire_balls.push(fire_ball);return fire_ball; // 返回fire_ball是为了获取自己创建这个火球的uuid}destroy_fireball(uuid) { // 删除火球for (let i 0; i this.fire_balls.length; i) {let fire_ball this.fire_balls[i];if (fire_ball.uuid uuid) {fire_ball.destroy();break;}}}... }由于火球在 Player 中存了一份因此我们在删除火球前需要将它从 Player 的 fire_balls 中删掉。且由于 FireBall 类中的 update 函数过于臃肿可以先将其分成 update_move 以及 update_attack我们修改 FireBall 类 class FireBall extends AcGameObject {// 火球需要标记是哪个玩家发射的且射出后的速度方向与大小是固定的射程为move_lengthconstructor(playground, player, x, y, radius, vx, vy, color, speed, move_length, damage) {...}start() {}update_move() {let true_move Math.min(this.move_length, this.speed * this.timedelta / 1000);this.x this.vx * true_move;this.y this.vy * true_move;this.move_length - true_move;}update_attack() { // 攻击碰撞检测for (let i 0; i this.playground.players.length; i) {let player this.playground.players[i];if (player ! this.player this.is_collision(player)) {this.attack(player); // this攻击player}}}update() {if (this.move_length this.eps) {this.destroy();return false;}this.update_move();this.update_attack();this.render();}get_dist(x1, y1, x2, y2) {...}is_collision(player) {...}attack(player) {...}render() {...}on_destroy() {let fire_balls this.player.fire_balls;for (let i 0; i fire_balls.length; i) {if (fire_balls[i] this) {fire_balls.splice(i, 1);break;}}} }然后我们在 MultiPlayerSocket 类中实现 send_shoot_fireball 和 receive_shoot_fireball 函数 class MultiPlayerSocket {...receive() {let outer this;this.ws.onmessage function(e) {let data JSON.parse(e.data); // 将字符串变回JSONlet uuid data.uuid;if (uuid outer.uuid) return false; // 如果是给自己发送消息就直接过滤掉let event data.event;if (event create_player) { // create_player路由outer.receive_create_player(uuid, data.username, data.avatar);} else if (event move_to) { // move_to路由outer.receive_move_to(uuid, data.tx, data.ty);} else if (event shoot_fireball) { // shoot_fireball路由outer.receive_shoot_fireball(uuid, data.tx, data.ty, data.fireball_uuid);}};}...send_shoot_fireball(tx, ty, fireball_uuid) {let outer this;this.ws.send(JSON.stringify({event: shoot_fireball,uuid: outer.uuid,tx: tx,ty: ty,fireball_uuid: fireball_uuid,}));}receive_shoot_fireball(uuid, tx, ty, fireball_uuid) {let player this.get_player(uuid);if (player) {let fire_ball player.shoot_fireball(tx, ty);fire_ball.uuid fireball_uuid; // 所有窗口同一个火球的uuid需要统一}} }现在我们需要实现后端函数 import json from channels.generic.websocket import AsyncWebsocketConsumer from django.conf import settings from django.core.cache import cacheclass MultiPlayer(AsyncWebsocketConsumer):...async def shoot_fireball(self, data):await self.channel_layer.group_send(self.room_name,{type: group_send_event,event: shoot_fireball,uuid: data[uuid],tx: data[tx],ty: data[ty],fireball_uuid: data[fireball_uuid],})async def receive(self, text_data):data json.loads(text_data)print(data)event data[event]if event create_player: # 做一个路由await self.create_player(data)elif event move_to: # move_to的路由await self.move_to(data)elif event shoot_fireball: # shoot_fireball的路由await self.shoot_fireball(data)最后是在 Player 类中调用函数 class Player extends AcGameObject {constructor(playground, x, y, radius, color, speed, character, username, avatar) {...}start() {...}add_listening_events() {let outer this;this.playground.game_map.$canvas.on(contextmenu, function() {return false;}); // 取消右键的菜单功能this.playground.game_map.$canvas.mousedown(function(e) {const rect outer.ctx.canvas.getBoundingClientRect();if (e.which 3) { // 1表示左键2表示滚轮3表示右键...} else if (e.which 1) {let tx (e.clientX - rect.left) / outer.playground.scale;let ty (e.clientY - rect.top) / outer.playground.scale;if (outer.cur_skill fireball) {let fire_ball outer.shoot_fireball(tx, ty);if (outer.playground.mode multi mode) {outer.playground.mps.send_shoot_fireball(tx, ty, fire_ball.uuid);}}outer.cur_skill null; // 释放完一次技能后还原}});$(window).keydown(function(e) {if (e.which 81) { // Q键outer.cur_skill fireball;return false;}});}// 计算两点之间的欧几里得距离get_dist(x1, y1, x2, y2) {...}// 向(tx, ty)位置发射火球shoot_fireball(tx, ty) {...}destroy_fireball(uuid) { // 删除火球...}move_to(tx, ty) {...}is_attacked(theta, damage) { // 被攻击到...}// 更新移动update_move() {...}update() {...}render() {...}on_destroy() {for (let i 0; i this.playground.players.length; i) {if (this.playground.players[i] this) {this.playground.players.splice(i, 1);break;}}} }3. 编写击中判定同步函数attack 我们需要统一攻击这个动作由一个窗口来唯一判断是否击中若击中则广播给其他窗口因此窗口中看到其他玩家发射的火球仅为动画不应该有击中判定。我们先在 FireBall 类中进行修改 class FireBall extends AcGameObject {...update() {if (this.move_length this.eps) {this.destroy();return false;}this.update_move();if (this.player.character ! enemy) { // 在敌人的窗口中不进行攻击检测this.update_attack();}this.render();}... }每名玩家还需要有一个函数 receive_attack 表示接收到被攻击的信息 class Player extends AcGameObject {...destroy_fireball(uuid) { // 删除火球for (let i 0; i this.fire_balls.length; i) {let fire_ball this.fire_balls[i];if (fire_ball.uuid uuid) {fire_ball.destroy();break;}}}...is_attacked(theta, damage) { // 被攻击到// 创建粒子效果for (let i 0; i 10 Math.random() * 5; i) {let x this.x, y this.y;let radius this.radius * Math.random() * 0.2;let theta Math.PI * 2 * Math.random();let vx Math.cos(theta), vy Math.sin(theta);let color this.color;let speed this.speed * 10;let move_length this.radius * Math.random() * 10;new Particle(this.playground, x, y, radius, vx, vy, color, speed, move_length);}this.radius - damage;this.speed * 1.08; // 血量越少移动越快if (this.radius this.eps) { // 半径小于eps认为已死this.destroy();return false;}this.damage_vx Math.cos(theta);this.damage_vy Math.sin(theta);this.damage_speed damage * 90;}receive_attack(x, y, theta, damage, fireball_uuid, attacker) { // 接收被攻击到的消息attacker.destroy_fireball(fireball_uuid);this.x x;this.y y;this.is_attacked(theta, damage);}... }我们假设发射火球的玩家为 attacker被击中的玩家为 attackee被击中者的位置也是由攻击者的窗口决定的且火球在击中其他玩家后在其他玩家的窗口也应该消失因此还需要传火球的 uuid。我们在 MultiPlayerSocket 类中实现 send_attack 与 receive_attack 函数 class MultiPlayerSocket {...receive() {let outer this;this.ws.onmessage function(e) {let data JSON.parse(e.data); // 将字符串变回JSONlet uuid data.uuid;if (uuid outer.uuid) return false; // 如果是给自己发送消息就直接过滤掉let event data.event;if (event create_player) { // create_player路由outer.receive_create_player(uuid, data.username, data.avatar);} else if (event move_to) { // move_to路由outer.receive_move_to(uuid, data.tx, data.ty);} else if (event shoot_fireball) { // shoot_fireball路由outer.receive_shoot_fireball(uuid, data.tx, data.ty, data.fireball_uuid);} else if (event attack) { // attack路由outer.receive_attack(uuid, data.attackee_uuid, data.x, data.y, data.theta, data.damage, data.fireball_uuid);}};}...send_attack(attackee_uuid, x, y, theta, damage, fireball_uuid) {let outer this;this.ws.send(JSON.stringify({event: attack,uuid: outer.uuid,attackee_uuid: attackee_uuid,x: x,y: y,theta: theta,damage: damage,fireball_uuid: fireball_uuid,}));}receive_attack(uuid, attackee_uuid, x, y, theta, damage, fireball_uuid) {let attacker this.get_player(uuid);let attackee this.get_player(attackee_uuid);if (attacker attackee) { // 如果攻击者和被攻击者都还存在就判定攻击attackee.receive_attack(x, y, theta, damage, fireball_uuid, attacker);}} }然后实现后端函数如下 import json from channels.generic.websocket import AsyncWebsocketConsumer from django.conf import settings from django.core.cache import cacheclass MultiPlayer(AsyncWebsocketConsumer):...async def attack(self, data):await self.channel_layer.group_send(self.room_name,{type: group_send_event,event: attack,uuid: data[uuid],attackee_uuid: data[attackee_uuid],x: data[x],y: data[y],theta: data[theta],damage: data[damage],fireball_uuid: data[fireball_uuid],})async def receive(self, text_data):data json.loads(text_data)print(data)event data[event]if event create_player: # 做一个路由await self.create_player(data)elif event move_to: # move_to的路由await self.move_to(data)elif event shoot_fireball: # shoot_fireball的路由await self.shoot_fireball(data)elif event attack: # attack的路由await self.attack(data)最后需要在火球 FireBall 类中调用攻击判定的同步函数 class FireBall extends AcGameObject {// 火球需要标记是哪个玩家发射的且射出后的速度方向与大小是固定的射程为move_lengthconstructor(playground, player, x, y, radius, vx, vy, color, speed, move_length, damage) {...}start() {}update_move() {...}update_attack() { // 攻击碰撞检测for (let i 0; i this.playground.players.length; i) {let player this.playground.players[i];if (player ! this.player this.is_collision(player)) {this.attack(player); // this攻击player}}}update() {if (this.move_length this.eps) {this.destroy();return false;}this.update_move();if (this.player.character ! enemy) { // 在敌人的窗口中不进行攻击检测this.update_attack();}this.render();}get_dist(x1, y1, x2, y2) {...}is_collision(player) {let distance this.get_dist(this.x, this.y, player.x, player.y);if (distance this.radius player.radius)return true;return false;}attack(player) {let theta Math.atan2(player.y - this.y, player.x - this.x);player.is_attacked(theta, this.damage);if (this.playground.mode multi mode) {this.playground.mps.send_attack(player.uuid, player.x, player.y, theta, this.damage, this.uuid);}this.destroy();}render() {...}on_destroy() {...} }4. 优化改进 我们限制在房间人数还没到3个时玩家不能移动需要在 AcGamePlayground 类中添加一个状态机 state一共有三种状态waiting、fighting、over且每个窗口的状态是独立的提示板会在之后进行实现 class AcGamePlayground {...// 显示playground界面show(mode) {...this.mode mode; // 需要将模式记录下来之后玩家在不同的模式中需要调用不同的函数this.state waiting; // waiting - fighting - overthis.notice_board new NoticeBoard(this); // 提示板this.player_count 0; // 玩家人数this.resize(); // 界面打开后需要resize一次需要将game_map也resize...}... }接下来我们实现一个提示板显示当前房间有多少名玩家在等待在 ~/djangoapp/game/static/js/src/playground 目录下新建 notice_board 目录然后进入该目录创建 zbase.js 文件如下 class NoticeBoard extends AcGameObject {constructor(playground) {super();this.playground playground;this.ctx this.playground.game_map.ctx;this.text 已就绪: 0人;}start() {}write(text) { // 更新this.text的信息this.text text;}update() {this.render();}render() { // Canvas渲染文本this.ctx.font 20px serif;this.ctx.fillStyle white;this.ctx.textAlign center;this.ctx.fillText(this.text, this.playground.width / 2, 20);} }每次有玩家创建时就将 player_count 的数量加一在 Player 类中进行修改 class Player extends AcGameObject {...start() {this.playground.player_count;this.playground.notice_board.write(已就绪: this.playground.player_count 人);if (this.playground.player_count 3) {this.playground.state fighting;this.playground.notice_board.write(Fighting);}...}... }
http://www.huolong8.cn/news/304841/

相关文章:

  • 网站建设中服务器的搭建方式怎么制作安卓app
  • 百度网站提交网站背景图片素材 唯美
  • 关于网站建设的网站如何做网站模版
  • 关于旅游网站建设的方案企业网站优化服务
  • 阿里云网站建设教程视频有没有类似一起做网店的网站
  • 很大气的网站 营销周口微网站制作
  • 山东省建设工程协会网站广州网站建设团队
  • 聚划算网站建设分析诸暨市建设局网站
  • 北京网站优化和推广网站栏目设计模板
  • easyui 网站开发实现软文代理平台
  • 哪个做网站平台好wordpress 主题翻译
  • 网站建设公司行业wordpress如何自己写页面
  • 做外贸大一点的网站西安建筑工程有限公司
  • 环境设计网站推荐如何获取网站开发语言
  • 网站建立的关键技术建网站的程序免费
  • 做单网站跨境电商的行业现状
  • 合肥网站建设求职简历百度95099怎么转人工
  • HTML网站页面建设外贸网站源码php
  • 网站建设最便宜多少钱做代金券的网站
  • 河北工程招标信息网官网seo优化网络公司排名
  • 安阳网站建设哪家好跨境电商网站如何做推广方案
  • 常州网站建设方案策划企业管理软件价格
  • 找人做彩票网站有哪些暗网网站有那些
  • 网站建设发布教程上海企业服务云下载
  • 如何做网站展示商品站长工具收录
  • 龙华住房与建设局网站在国内可以做国外的网站吗
  • 实验教学网站建设策划方案做网站翻页怎么做
  • 统计局网站建设河南做网站公司汉狮
  • 毕业设计团购网站建设网站建设网站建设公司
  • 网站 app设计开发建设手机代理ip免费网址