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

接设计私单的平台百度蜘蛛池自动收录seo

接设计私单的平台,百度蜘蛛池自动收录seo,个人或主题网站建设 实验体会,网站改版流程笔记内容转载自 AcWing 的 Django 框架课讲义,课程链接:AcWing Django 框架课。 CONTENTS 1. 统一长度单位2. 增加联机对战模式3. 配置Django Channels 1. 统一长度单位 多人模式中每个玩家所看到的地图相对来说应该是一样的,因此需要固定地…

笔记内容转载自 AcWing 的 Django 框架课讲义,课程链接:AcWing Django 框架课。

CONTENTS

    • 1. 统一长度单位
    • 2. 增加联机对战模式
    • 3. 配置Django Channels

1. 统一长度单位

多人模式中每个玩家所看到的地图相对来说应该是一样的,因此需要固定地图的长宽比,一般固定为16:9。我们需要在游戏窗口的长宽中取最小值,然后将地图渲染为16:9的大小。

我们在 AcGamePlayground 类中实现一个 resize 函数用于将长宽比调整为16:9并且达到最大:

class AcGamePlayground {constructor(root) {this.root = root;this.$playground = $(`<div class='ac_game_playground'></div>`);this.root.$ac_game.append(this.$playground);this.start();}get_random_color() {...}start() {this.hide();  // 初始化时需要先关闭playground界面let outer = this;$(window).resize(function() {outer.resize();});  // 用户改变窗口大小时改函数会触发}// 将长宽比调整为16:9resize() {this.width = this.$playground.width();this.height = this.$playground.height();let unit = Math.min(this.width / 16, this.height / 9);this.width = unit * 16;this.height = unit * 9;this.scale = this.height;  // 当窗口大小改变时所有目标的相对大小和位置也要改变if (this.game_map) this.game_map.resize();  // 如果地图存在需要调用地图的resize函数}// 显示playground界面show() {this.$playground.show();// 将界面的宽高先存下来this.width = this.$playground.width();this.height = this.$playground.height();this.game_map = new GameMap(this);  // 创建游戏画面this.resize();  // 界面打开后需要resize一次,需要将game_map也resize...}// 关闭playground界面hide() {this.$playground.hide();}
}

现在需要将窗口大小的修改效果作用到黑色背景上,因此我们在 GameMap 类中也实现一个 resize 函数用于修改背景大小:

class GameMap extends AcGameObject {constructor(playground) {  // 需要将AcGamePlayground传进来super();  // 调用基类构造函数,相当于将自己添加到了AC_GAME_OBJECTS中this.playground = playground;this.$canvas = $(`<canvas></canvas>`);  // 画布,用来渲染画面this.ctx = this.$canvas[0].getContext('2d');  // 二维画布this.ctx.canvas.width = this.playground.width;  // 设置画布宽度this.ctx.canvas.height = this.playground.height;  // 设置画布高度this.playground.$playground.append(this.$canvas);  // 将画布添加到HTML中}start() {}resize() {this.ctx.canvas.width = this.playground.width;this.ctx.canvas.height = this.playground.height;this.ctx.fillStyle = 'rgba(0, 0, 0, 1)';  // 每次调整大小后直接涂一层不透明的背景this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);}update() {this.render();  // 每一帧都要画一次}render() {this.ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';  // 黑色背景// 左上角坐标(0, 0),右下角坐标(w, h)this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);}
}

我们修改一下 game.css 文件,添加以下内容,实现将地图居中:

.ac_game_playground > canvas {position: relative;top: 50%;left: 50%;transform: translate(-50%, -50%);
}

现在我们还需要修改地图里面的目标,一共有三种分别是玩家、火球、被击中的粒子效果。

首先修改一下 AcGamePlayground 类中的玩家初始化代码:

class AcGamePlayground {constructor(root) {...}get_random_color() {...}start() {...}// 将长宽比调整为16:9resize() {...}// 显示playground界面show() {this.$playground.show();// 将界面的宽高先存下来this.width = this.$playground.width();this.height = this.$playground.height();this.game_map = new GameMap(this);  // 创建游戏画面this.resize();  // 界面打开后需要resize一次,需要将game_map也resizethis.players = [];  // 所有玩家this.players.push(new Player(this, this.width / 2 / this.scale, 0.5, 0.05, 'white', 0.15, true));  // 创建自己// 创建敌人for (let i = 0; i < 8; i++) {this.players.push(new Player(this, this.width / 2 / this.scale, 0.5, 0.05, this.get_random_color(), 0.15, false));}}// 关闭playground界面hide() {this.$playground.hide();}
}

然后我们修改 Player 类,将所有绝对变量替换为相对变量:

class Player extends AcGameObject {constructor(playground, x, y, radius, color, speed, is_me) {...this.eps = 0.01;  // 误差小于0.01认为是0...}start() {if (this.is_me) {this.add_listening_events();} else {// Math.random()返回一个0~1之间的数,随机初始化AI的位置let tx = Math.random() * this.playground.width / this.playground.scale;let ty = Math.random() * this.playground.height / this.playground.scale;this.move_to(tx, ty);}}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表示右键outer.move_to((e.clientX - rect.left) / outer.playground.scale, (e.clientY - rect.top) / outer.playground.scale);  // e.clientX/Y为鼠标点 击坐标} else if (e.which === 1) {if (outer.cur_skill === 'fireball') {outer.shoot_fireball((e.clientX - rect.left) / outer.playground.scale, (e.clientY - rect.top) / outer.playground.scale);}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) {...}move_to(tx, ty) {...}is_attacked(theta, damage) {  // 被攻击到...}// 更新移动update_move() {this.spent_time += this.timedelta / 1000;// AI敌人随机向玩家射击,游戏刚开始前三秒AI不能射击if (this.spent_time > 3 && !this.is_me && Math.random() < 1 / 360.0) {let player = this.playground.players[0];this.shoot_fireball(player.x, player.y);}if (this.damage_speed > this.eps) {  // 有击退效果时玩家无法移动this.vx = this.vy = 0;this.move_length = 0;this.x += this.damage_vx * this.damage_speed * this.timedelta / 1000;this.y += this.damage_vy * this.damage_speed * this.timedelta / 1000;this.damage_speed *= this.friction;} else {if (this.move_length < this.eps) {this.move_length = 0;this.vx = this.vy = 0;if (!this.is_me) {  // AI敌人不能停下来let tx = Math.random() * this.playground.width / this.playground.scale;let ty = Math.random() * this.playground.height / this.playground.scale;this.move_to(tx, ty);}} else {// 计算真实移动距离,与一帧的移动距离取min防止移出界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() {this.update_move();this.render();}render() {let scale = this.playground.scale;  // 要将相对值恢复成绝对值if (this.is_me) {this.ctx.save();this.ctx.beginPath();this.ctx.arc(this.x * scale, this.y * scale, this.radius * scale, 0, Math.PI * 2, false);this.ctx.stroke();this.ctx.clip();this.ctx.drawImage(this.img, (this.x - this.radius) * scale, (this.y - this.radius) * scale, this.radius * 2 * scale, this.radius * 2 * scale);this.ctx.restore();} else {  // AIthis.ctx.beginPath();// 角度从0画到2PI,是否逆时针为falsethis.ctx.arc(this.x * scale, this.y * scale, this.radius * scale, 0, Math.PI * 2, false);this.ctx.fillStyle = this.color;this.ctx.fill();}}
}

然后修改 FireBall 类,只需要修改 eps 以及 render 函数即可:

class FireBall extends AcGameObject {// 火球需要标记是哪个玩家发射的,且射出后的速度方向与大小是固定的,射程为move_lengthconstructor(playground, player, x, y, radius, vx, vy, color, speed, move_length, damage) {...this.eps = 0.01;}start() {}update() {...}get_dist(x1, y1, x2, y2) {...}is_collision(player) {...}attack(player) {...}render() {let scale = this.playground.scale;this.ctx.beginPath();this.ctx.arc(this.x * scale, this.y * scale, this.radius * scale, 0, Math.PI * 2, false);this.ctx.fillStyle = this.color;this.ctx.fill();}
}

最后修改 Particle 类,同样也是只需要修改 eps 以及 render 函数即可:

class Particle extends AcGameObject {constructor(playground, x, y, radius, vx, vy, color, speed, move_length) {...this.eps = 0.01;this.friction = 0.9;}start() {}update() {...}render() {let scale = this.playground.scale;this.ctx.beginPath();this.ctx.arc(this.x * scale, this.y * scale, this.radius * scale, 0, Math.PI * 2, false);this.ctx.fillStyle = this.color;this.ctx.fill();}
}

2. 增加联机对战模式

我们先修改 AcGameMenu 类,实现多人模式按钮的逻辑:

class AcGameMenu {constructor(root) {  // root用来传AcGame对象...}start() {this.hide();this.add_listening_events();}// 给按钮绑定监听函数add_listening_events() {let outer = this;// 注意在function中调用this指的是function本身,因此需要先将外面的this存起来this.$single.click(function() {outer.hide();  // 关闭menu界面outer.root.playground.show('single mode');  // 显示playground界面,加入参数用于区分});this.$multi.click(function() {outer.hide();outer.root.playground.show('multi mode');  // 多人模式});this.$settings.click(function() {outer.root.settings.logout_on_remote();});}// 显示menu界面show() {this.$menu.show();}// 关闭menu界面hide() {this.$menu.hide();}
}

然后修改 AcGamePlayground 类,区分两种模式,且需要进一步区分玩家类别,之前使用 True/False 表示是否是玩家本人,现在可以用字符串区分玩家本人、其他玩家以及人机:

class AcGamePlayground {constructor(root) {...}get_random_color() {...}start() {...}// 将长宽比调整为16:9resize() {...}// 显示playground界面show(mode) {this.$playground.show();// 将界面的宽高先存下来this.width = this.$playground.width();this.height = this.$playground.height();this.game_map = new GameMap(this);  // 创建游戏画面this.resize();  // 界面打开后需要resize一次,需要将game_map也resizethis.players = [];  // 所有玩家this.players.push(new Player(this, this.width / 2 / this.scale, 0.5, 0.05, 'white', 0.15, 'me', this.root.settings.username, this.root.settings.avatar));  // 创建自己,自己的用户名和头像从settings中获得// 单人模式下创建AI敌人if (mode === 'single mode'){for (let i = 0; i < 8; i++) {this.players.push(new Player(this, this.width / 2 / this.scale, 0.5, 0.05, this.get_random_color(), 0.15, 'robot'));}} else if (mode === 'multi mode') {}}// 关闭playground界面hide() {this.$playground.hide();}
}

然后还需要修改一下 Player 类,将原本的 this.is_me 判断进行修改:

class Player extends AcGameObject {constructor(playground, x, y, radius, color, speed, character, username, avatar) {...this.character = character;this.username = username;this.avatar = avatar;...if (this.character !== 'robot') {  // 只有AI不用渲染图片this.img = new Image();this.img.src = this.avatar;}}start() {if (this.character === 'me') {  // 只给自己添加监听函数this.add_listening_events();} else {...}}add_listening_events() {...}// 计算两点之间的欧几里得距离get_dist(x1, y1, x2, y2) {...}// 向(tx, ty)位置发射火球shoot_fireball(tx, ty) {...}move_to(tx, ty) {...}is_attacked(theta, damage) {  // 被攻击到...}// 更新移动update_move() {this.spent_time += this.timedelta / 1000;// AI敌人随机向玩家射击,游戏刚开始前三秒AI不能射击if (this.character === 'robot' && this.spent_time > 3 && Math.random() < 1 / 360.0) {...}if (this.damage_speed > this.eps) {  // 有击退效果时玩家无法移动...} else {if (this.move_length < this.eps) {...if (this.character === 'robot') {  // AI敌人不能停下来...}} else {// 计算真实移动距离,与一帧的移动距离取min防止移出界...}}}update() {this.update_move();this.render();}render() {let scale = this.playground.scale;  // 要将相对值恢复成绝对值if (this.character !== 'robot') {...} else {  // AI...}}
}

3. 配置Django Channels

假设有三名玩家编号为1、2、3进行多人游戏,那么每个玩家都有自己的一个窗口,且窗口中都能看到三名玩家。如果当前玩家1、2在进行游戏,3加入了游戏,那么需要告诉1、2两名玩家3来了,且还要告诉3当前已经有玩家1、2了。

要实现这一点,可以通过一个中心服务器(可以就是自己租的云服务器),即3向服务器发送他来了,服务器给1、2发送消息,且服务器给3发送消息说之前已经有1、2两名玩家了。因此服务器中需要存储每个地图中的玩家信息,用于完成第一个同步事件:生成玩家事件。

我们之后一共需要实现四个同步函数:create_playermove_toshoot_fireballattack。前三个函数顾名思义,最后的 attack 函数是因为服务器存在延迟,比如3发射一个火球在本地看打中了1,但是由于延迟在1那边可能是没被打中的。

攻击判断是一个权衡问题,一般的游戏都是选择在本地进行攻击判断,而不是云服务器,即以发起攻击的玩家窗口进行判断,如果击中了则通过 attack 函数在服务器上广播信息。

在此之前我们使用的是 HTTP 协议,该协议为单向的,即客户端需要先向服务器请求信息后服务器才会返回信息,而服务器是不会主动向客户端发送信息的。

因此此处我们需要使用 WebSocket 协议(WS),同理该协议也有对应的加密协议 WSS,Django Channels 即为 Django 支持 WSS 协议的一种实现方式。


文章转载自:
http://sardinia.ncmj.cn
http://reallocate.ncmj.cn
http://vichyssoise.ncmj.cn
http://trail.ncmj.cn
http://woodpecker.ncmj.cn
http://pronunciation.ncmj.cn
http://horsenapping.ncmj.cn
http://veronal.ncmj.cn
http://mariology.ncmj.cn
http://stallion.ncmj.cn
http://estrin.ncmj.cn
http://elhi.ncmj.cn
http://endhand.ncmj.cn
http://inhomogeneity.ncmj.cn
http://alkyne.ncmj.cn
http://antlion.ncmj.cn
http://beetleheaded.ncmj.cn
http://hydrofluoric.ncmj.cn
http://synaesthesis.ncmj.cn
http://intraday.ncmj.cn
http://wayang.ncmj.cn
http://backroad.ncmj.cn
http://spiv.ncmj.cn
http://leprose.ncmj.cn
http://eunuch.ncmj.cn
http://scaddle.ncmj.cn
http://endosporium.ncmj.cn
http://oleoresin.ncmj.cn
http://projector.ncmj.cn
http://gauffer.ncmj.cn
http://hedonistic.ncmj.cn
http://solacet.ncmj.cn
http://fishify.ncmj.cn
http://purifier.ncmj.cn
http://bramley.ncmj.cn
http://degear.ncmj.cn
http://nephrosis.ncmj.cn
http://yachtswoman.ncmj.cn
http://aminophenol.ncmj.cn
http://deflagrator.ncmj.cn
http://soberano.ncmj.cn
http://leapfrog.ncmj.cn
http://scoundrel.ncmj.cn
http://coxless.ncmj.cn
http://carillon.ncmj.cn
http://hotness.ncmj.cn
http://calicular.ncmj.cn
http://lenitic.ncmj.cn
http://contemplation.ncmj.cn
http://bizen.ncmj.cn
http://irregular.ncmj.cn
http://epeirogeny.ncmj.cn
http://ergate.ncmj.cn
http://marquis.ncmj.cn
http://caught.ncmj.cn
http://pap.ncmj.cn
http://inconsciently.ncmj.cn
http://sinologue.ncmj.cn
http://neutrophilic.ncmj.cn
http://papula.ncmj.cn
http://advisedly.ncmj.cn
http://maintop.ncmj.cn
http://hyperdrive.ncmj.cn
http://uncalculating.ncmj.cn
http://hystrichosphere.ncmj.cn
http://blub.ncmj.cn
http://rhochrematician.ncmj.cn
http://passional.ncmj.cn
http://rikisha.ncmj.cn
http://crowstep.ncmj.cn
http://graham.ncmj.cn
http://skyscraping.ncmj.cn
http://brett.ncmj.cn
http://roadblock.ncmj.cn
http://afond.ncmj.cn
http://embosk.ncmj.cn
http://activex.ncmj.cn
http://nova.ncmj.cn
http://explanatory.ncmj.cn
http://anathematize.ncmj.cn
http://servite.ncmj.cn
http://tyrol.ncmj.cn
http://deedless.ncmj.cn
http://bioethics.ncmj.cn
http://northumbria.ncmj.cn
http://neuropath.ncmj.cn
http://britska.ncmj.cn
http://annually.ncmj.cn
http://unprofited.ncmj.cn
http://director.ncmj.cn
http://duress.ncmj.cn
http://resound.ncmj.cn
http://spig.ncmj.cn
http://godparent.ncmj.cn
http://zymoid.ncmj.cn
http://pinion.ncmj.cn
http://acrasin.ncmj.cn
http://downloadable.ncmj.cn
http://unanswered.ncmj.cn
http://myricin.ncmj.cn
http://www.dt0577.cn/news/78303.html

相关文章:

  • 网站建设优化排名在百度怎么发布作品
  • 免费网站推广在线观看百度手机助手免费下载
  • 网站权重收录联合早报 即时消息
  • 那些网站做批发seo内容优化是什么意思
  • 自己怎么做优惠券网站深圳专业seo外包
  • 电子销售网站模板免费下载西安关键词排名软件
  • 建站网站教程网络服务器图片
  • 网站建设后台管理流程广州疫情已经达峰
  • 购物网站平台建设友情链接怎么设置
  • 做农业网站怎么赚钱龙岗网站建设
  • 小型的游戏网站怎么做网站搜索排名靠前
  • 网站开发过程中出现的问题做网站设计哪里有
  • 做淘宝客网站的流程百度搜索引擎优化的推广计划
  • 在线播放 WordPress上海seo优化公司 kinglink
  • 网站建设和网站美国今天刚刚发生的新闻
  • 西宁网站建设公司排名企业新闻营销
  • 优秀的网站有哪些苏州百度推广开户
  • 川畅互联咨询 网站建设seo编辑培训
  • 动态网站设计论文1500字网站权重等级
  • 网站站开发 流量德国搜索引擎
  • 西安网站制作 西安彩铃400电话上海网络营销seo
  • 网站描述设置推广策略包括哪些内容
  • 餐饮o2o 网站建设草根站长工具
  • 企业网站管理系统介绍企业推广的渠道有哪些
  • 徐州泉山建设局网站上海网络seo
  • ip地址访问不了网站武汉seo网站
  • 农庄网站营销型网站建设多少钱
  • 杭州网站制作公司排名制作网页需要多少钱
  • 建设网站的技术方案seo含义
  • 罗湖网站建设 信科网络百度知道问答