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

石家庄网站服务网址推广

石家庄网站服务,网址推广,seo口碑优化,珠海网站建笔记内容转载自 AcWing 的 Django 框架课讲义,课程链接:AcWing Django 框架课。 CONTENTS 1. 实现聊天系统前端界面2. 实现后端同步函数 1. 实现聊天系统前端界面 聊天系统整体可以分为两部分:输入框与历史记录。 我们需要先修改一下之前代…

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

CONTENTS

    • 1. 实现聊天系统前端界面
    • 2. 实现后端同步函数

1. 实现聊天系统前端界面

聊天系统整体可以分为两部分:输入框与历史记录。

我们需要先修改一下之前代码中的一个小 BUG,当在一个窗口中按 Q 时,另一个窗口中点击鼠标左键也能攻击,因为按下按键的事件被所有窗口都捕捉到了,这是不合理的。

我们之前监听的对象是 window,每个地图是一个 canvas 元素,因此我们可以绑定到 canvas 对象上。由于不是所有对象都能添加绑定事件的,因此我们还需要对 canvas 做一个修改,首先在 GameMap 类中修改一下 canvas 对象:

class GameMap extends AcGameObject {constructor(playground) {  // 需要将AcGamePlayground传进来super();  // 调用基类构造函数,相当于将自己添加到了AC_GAME_OBJECTS中this.playground = playground;this.$canvas = $(`<canvas tabindex=0></canvas>`);  // 画布,用来渲染画面,tabindex=0表示能够监听事件...}start() {this.$canvas.focus();  // 聚焦后才能监听事件}...
}

Player 类中修改:

class Player extends AcGameObject {...add_listening_events() {let outer = this;...this.playground.game_map.$canvas.keydown(function(e) {if (outer.playground.state !== 'fighting')return true;if (e.which === 81 && outer.fireball_coldtime < outer.eps) {  // Q键outer.cur_skill = 'fireball';return false;} else if (e.which === 70 && outer.blink_coldtime < outer.eps) {  // F键outer.cur_skill = 'blink';return false;}});}...
}

聊天的前端界面需要创建一个新的文件,我们在 ~/djangoapp/game/static/js/src/playground 目录下创建一个 chat_field 目录,并进入该目录创建 zbase.js 文件:

class ChatField {constructor(playground) {this.playground = playground;this.func_id = null;  // 在每次打开输入框时需要将之前历史记录框的计时函数删掉this.$history = $(`<div class='ac_game_chat_field_history'></div>`);this.$input = $(`<input type='text' class='ac_game_chat_field_input'>`);this.$history.hide();this.$input.hide();this.playground.$playground.append(this.$history);this.playground.$playground.append(this.$input);this.start();}start() {this.add_listening_events();}add_listening_events() {let outer = this;this.$input.keydown(function(e) {  // 输入框也需要监听ESC事件if (e.which === 27) {outer.hide_input();return false;}});}show_history() {let outer = this;this.$history.fadeIn();  // 慢慢显示出来if (this.func_id) clearTimeout(this.func_id);this.func_id = setTimeout(function() {outer.$history.fadeOut();outer.func_id = null;}, 3000);  // 显示3秒后消失}show_input() {this.$input.show();this.show_history();  // 打开输入框顺带打开历史记录this.$input.focus();  // 聚焦一下才能输入}hide_input() {this.$input.hide();this.playground.game_map.$canvas.focus();  // 关闭输入框后要重新聚焦回Canvas上}
}

然后在 AcGamePlayground 类中创建出来:

class AcGamePlayground {...// 显示playground界面show(mode) {...// 单人模式下创建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.07, this.get_random_color(), 0.15, 'robot'));}} else if (mode === 'multi mode') {this.mps = new MultiPlayerSocket(this);this.mps.uuid = this.players[0].uuid;  // 用每名玩家的唯一编号区分不同的窗口this.chat_field = new ChatField(this);  // 聊天区this.mps.ws.onopen = function() {outer.mps.send_create_player(outer.root.settings.username, outer.root.settings.avatar);};}}...
}

现在在 Player 类中即可监听事件:

class Player extends AcGameObject {...add_listening_events() {let outer = this;...this.playground.game_map.$canvas.keydown(function(e) {if (e.which === 13 && outer.playground.mode === 'multi mode') {  // 还没满人允许使用聊天功能outer.playground.chat_field.show_input();return false;} else if (e.which === 27 && outer.playground.mode === 'multi mode') {outer.playground.chat_field.hide_input();return false;}if (outer.playground.state !== 'fighting')return true;if (e.which === 81 && outer.fireball_coldtime < outer.eps) {  // Q键outer.cur_skill = 'fireball';return false;} else if (e.which === 70 && outer.blink_coldtime < outer.eps) {  // F键outer.cur_skill = 'blink';return false;}});}...
}

然后我们还需要实现一下聊天区的 CSS 样式(在 ~/djangoapp/game/static/css 目录的 game.css 文件中):

....ac_game_chat_field_history {position: absolute;top: 40%;left: 15%;transform: translate(-50%, 50%);width: 20%;height:30%;color: white;background-color: rgba(77, 77, 77, 0.2);font-size: 1.5vh;padding: 5px;overflow: auto;
}.ac_game_chat_field_history::-webkit-scrollbar {  /* 滚动条 */width: 1;
}.ac_game_chat_field_input {position: absolute;top: 86%;left: 15%;transform: translate(-50%, 50%);width: 20%;height: 2vh;color: white;background-color: rgba(222, 225, 230, 0.2);font-size: 1.5vh;
}

现在我们实现在历史记录区域里添加新消息的功能:

class ChatField {constructor(playground) {...}start() {this.add_listening_events();}add_listening_events() {let outer = this;this.$input.keydown(function(e) {  // 输入框也需要监听ESC事件if (e.which === 27) {outer.hide_input();return false;} else if (e.which === 13) {  // 按Enter键时发送消息let username = outer.playground.root.settings.username;let text = outer.$input.val();outer.hide_input();  // 发送完消息后关闭输入框if (text) {  // 信息不为空才渲染出来outer.$input.val('');  // 将输入框清空outer.add_message(username, text);}return false;}});}render_message(message) {  // 渲染消息return $(`<div>${message}</div>`);}add_message(username, text) {  // 向历史记录区里添加消息let message = `[${username}] ${text}`;this.$history.append(this.render_message(message));this.show_history();  // 每次发新消息时都显示一下历史记录this.$history.scrollTop(this.$history[0].scrollHeight);  // 将滚动条移动到最底部}...
}

2. 实现后端同步函数

我们先在 WebSocket 前端实现发送和接收消息的函数:

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);} else if (event === 'blink') {  // blink路由outer.receive_blink(uuid, data.tx, data.ty);} else if (event === 'message') {  // message路由outer.receive_message(data.username, data.text);}};}...send_message(username, text) {let outer = this;this.ws.send(JSON.stringify({'event': 'message','uuid': outer.uuid,'username': username,'text': text,}));}receive_message(username, text) {this.playground.chat_field.add_message(username, text);}
}

然后实现后端代码:

import json
from channels.generic.websocket import AsyncWebsocketConsumer
from django.conf import settings
from django.core.cache import cacheclass MultiPlayer(AsyncWebsocketConsumer):...async def message(self, data):await self.channel_layer.group_send(self.room_name,{'type': 'group_send_event','event': 'message','uuid': data['uuid'],'username': data['username'],'text': data['text'],})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)elif event == 'blink':  # blink的路由await self.blink(data)elif event == 'message':  # message的路由await self.message(data)

最后在前端的 ChatField 类中调用一下发送消息的函数即可:

class ChatField {...add_listening_events() {let outer = this;this.$input.keydown(function(e) {  // 输入框也需要监听ESC事件if (e.which === 27) {outer.hide_input();return false;} else if (e.which === 13) {  // 按Enter键时发送消息let username = outer.playground.root.settings.username;let text = outer.$input.val();outer.hide_input();  // 发送完消息后关闭输入框if (text) {  // 信息不为空才渲染出来outer.$input.val('');  // 将输入框清空outer.add_message(username, text);outer.playground.mps.send_message(username, text);  // 给其他玩家的窗口发送消息}return false;}});}...
}
http://www.hkea.cn/news/880766/

相关文章:

  • 做仪表行业推广有哪些网站电商网站设计
  • 动静分离网站架构百度售后客服电话24小时
  • 做汽车配件生意的网站佛山seo关键词排名
  • 创意建站推荐百度做广告多少钱一天
  • 巴中网站建设公司百度seo怎么做网站内容优化
  • 查网站备案名称上海网络营销seo
  • 人是用什么做的视频网站网络营销方案设计毕业设计
  • 建设网站考虑因素关键词优化是怎么弄的
  • 陕西营销型网站建设推广普通话的内容简短
  • 做配电箱的专门网站百度指数属于行业趋势及人群
  • 学做网站的网站重庆seo整站优化报价
  • 保定网站设计概述seo推广软件排名
  • 查pv uv的网站网络营销推广服务
  • 怎样让客户做网站优化 保证排名
  • 企业营销型网站做的好网络营销的有哪些特点
  • 网站开发 合同兰州快速seo整站优化招商
  • 网站开发技术现状深圳网络营销推广培训
  • 知名网络公司有哪些河北网站seo
  • 学做网站多少钱关键词难易度分析
  • 传奇如何做网站网站建设策划书案例
  • 龙岗 网站建设深圳信科最好用的搜索神器
  • 动态网站开发日志重庆seo整站优化报价
  • 魔站网站建设微信公众号运营推广方案
  • 好的网站建设公司营销推广外包公司
  • 教育机构做网站素材长尾关键词爱站
  • 做网站选什么系统企业网站seo推广
  • 山东省南水北调建设管理局网站腾讯网qq网站
  • 菏泽做网站公司sem网络营销
  • 专业建站外包兰州网络优化seo
  • 企业邮箱腾讯杭州seo按天计费