中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

如何做網(wǎng)站對(duì)比網(wǎng)站優(yōu)化排名網(wǎng)站

如何做網(wǎng)站對(duì)比,網(wǎng)站優(yōu)化排名網(wǎng)站,不規(guī)則網(wǎng)站模板,專門(mén)做反季的網(wǎng)站筆記內(nèi)容轉(zhuǎn)載自 AcWing 的 Django 框架課講義,課程鏈接:AcWing Django 框架課。 CONTENTS 1. 實(shí)現(xiàn)聊天系統(tǒng)前端界面2. 實(shí)現(xiàn)后端同步函數(shù) 1. 實(shí)現(xiàn)聊天系統(tǒng)前端界面 聊天系統(tǒng)整體可以分為兩部分:輸入框與歷史記錄。 我們需要先修改一下之前代…

筆記內(nèi)容轉(zhuǎn)載自 AcWing 的 Django 框架課講義,課程鏈接:AcWing Django 框架課。

CONTENTS

    • 1. 實(shí)現(xiàn)聊天系統(tǒng)前端界面
    • 2. 實(shí)現(xiàn)后端同步函數(shù)

1. 實(shí)現(xiàn)聊天系統(tǒng)前端界面

聊天系統(tǒng)整體可以分為兩部分:輸入框與歷史記錄。

我們需要先修改一下之前代碼中的一個(gè)小 BUG,當(dāng)在一個(gè)窗口中按 Q 時(shí),另一個(gè)窗口中點(diǎn)擊鼠標(biāo)左鍵也能攻擊,因?yàn)榘聪掳存I的事件被所有窗口都捕捉到了,這是不合理的。

我們之前監(jiān)聽(tīng)的對(duì)象是 window,每個(gè)地圖是一個(gè) canvas 元素,因此我們可以綁定到 canvas 對(duì)象上。由于不是所有對(duì)象都能添加綁定事件的,因此我們還需要對(duì) canvas 做一個(gè)修改,首先在 GameMap 類中修改一下 canvas 對(duì)象:

class GameMap extends AcGameObject {constructor(playground) {  // 需要將AcGamePlayground傳進(jìn)來(lái)super();  // 調(diào)用基類構(gòu)造函數(shù),相當(dāng)于將自己添加到了AC_GAME_OBJECTS中this.playground = playground;this.$canvas = $(`<canvas tabindex=0></canvas>`);  // 畫(huà)布,用來(lái)渲染畫(huà)面,tabindex=0表示能夠監(jiān)聽(tīng)事件...}start() {this.$canvas.focus();  // 聚焦后才能監(jiān)聽(tīng)事件}...
}

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;}});}...
}

聊天的前端界面需要?jiǎng)?chuàng)建一個(gè)新的文件,我們?cè)?~/djangoapp/game/static/js/src/playground 目錄下創(chuàng)建一個(gè) chat_field 目錄,并進(jìn)入該目錄創(chuàng)建 zbase.js 文件:

class ChatField {constructor(playground) {this.playground = playground;this.func_id = null;  // 在每次打開(kāi)輸入框時(shí)需要將之前歷史記錄框的計(jì)時(shí)函數(shù)刪掉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) {  // 輸入框也需要監(jiān)聽(tīng)ESC事件if (e.which === 27) {outer.hide_input();return false;}});}show_history() {let outer = this;this.$history.fadeIn();  // 慢慢顯示出來(lái)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();  // 打開(kāi)輸入框順帶打開(kāi)歷史記錄this.$input.focus();  // 聚焦一下才能輸入}hide_input() {this.$input.hide();this.playground.game_map.$canvas.focus();  // 關(guān)閉輸入框后要重新聚焦回Canvas上}
}

然后在 AcGamePlayground 類中創(chuàng)建出來(lái):

class AcGamePlayground {...// 顯示playground界面show(mode) {...// 單人模式下創(chuàng)建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;  // 用每名玩家的唯一編號(hào)區(qū)分不同的窗口this.chat_field = new ChatField(this);  // 聊天區(qū)this.mps.ws.onopen = function() {outer.mps.send_create_player(outer.root.settings.username, outer.root.settings.avatar);};}}...
}

現(xiàn)在在 Player 類中即可監(jiān)聽(tīng)事件:

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') {  // 還沒(méi)滿人允許使用聊天功能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;}});}...
}

然后我們還需要實(shí)現(xiàn)一下聊天區(qū)的 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 {  /* 滾動(dòng)條 */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;
}

現(xiàn)在我們實(shí)現(xiàn)在歷史記錄區(qū)域里添加新消息的功能:

class ChatField {constructor(playground) {...}start() {this.add_listening_events();}add_listening_events() {let outer = this;this.$input.keydown(function(e) {  // 輸入框也需要監(jiān)聽(tīng)ESC事件if (e.which === 27) {outer.hide_input();return false;} else if (e.which === 13) {  // 按Enter鍵時(shí)發(fā)送消息let username = outer.playground.root.settings.username;let text = outer.$input.val();outer.hide_input();  // 發(fā)送完消息后關(guān)閉輸入框if (text) {  // 信息不為空才渲染出來(lái)outer.$input.val('');  // 將輸入框清空outer.add_message(username, text);}return false;}});}render_message(message) {  // 渲染消息return $(`<div>${message}</div>`);}add_message(username, text) {  // 向歷史記錄區(qū)里添加消息let message = `[${username}] ${text}`;this.$history.append(this.render_message(message));this.show_history();  // 每次發(fā)新消息時(shí)都顯示一下歷史記錄this.$history.scrollTop(this.$history[0].scrollHeight);  // 將滾動(dòng)條移動(dòng)到最底部}...
}

2. 實(shí)現(xiàn)后端同步函數(shù)

我們先在 WebSocket 前端實(shí)現(xiàn)發(fā)送和接收消息的函數(shù):

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;  // 如果是給自己發(fā)送消息就直接過(guò)濾掉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);}
}

然后實(shí)現(xiàn)后端代碼:

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':  # 做一個(gè)路由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 類中調(diào)用一下發(fā)送消息的函數(shù)即可:

class ChatField {...add_listening_events() {let outer = this;this.$input.keydown(function(e) {  // 輸入框也需要監(jiān)聽(tīng)ESC事件if (e.which === 27) {outer.hide_input();return false;} else if (e.which === 13) {  // 按Enter鍵時(shí)發(fā)送消息let username = outer.playground.root.settings.username;let text = outer.$input.val();outer.hide_input();  // 發(fā)送完消息后關(guān)閉輸入框if (text) {  // 信息不為空才渲染出來(lái)outer.$input.val('');  // 將輸入框清空outer.add_message(username, text);outer.playground.mps.send_message(username, text);  // 給其他玩家的窗口發(fā)送消息}return false;}});}...
}
http://www.risenshineclean.com/news/29161.html

相關(guān)文章:

  • 網(wǎng)站建設(shè)實(shí)戰(zhàn)視頻教程桂林網(wǎng)站設(shè)計(jì)制作
  • 報(bào)考建設(shè)八大員官方網(wǎng)站seo推廣軟件哪個(gè)好
  • wordpress 文章列表只顯示標(biāo)題外貿(mào)seo
  • 哪個(gè)網(wǎng)站做任務(wù)能賺錢(qián)我要看今日頭條
  • 廈門(mén)廣告公司有哪些aso優(yōu)化的主要內(nèi)容為
  • wordpress修改谷歌外貿(mào)seo公司
  • 做美團(tuán)網(wǎng)這種網(wǎng)站賺錢(qián)嗎亞馬遜關(guān)鍵詞搜索器
  • 英語(yǔ)網(wǎng)站建設(shè)如何制作一個(gè)公司網(wǎng)站
  • 上海網(wǎng)站建設(shè)平臺(tái)站霸網(wǎng)絡(luò)seo學(xué)習(xí)網(wǎng)站
  • 做網(wǎng)站有一個(gè)火箭回頂部網(wǎng)站優(yōu)化關(guān)鍵詞公司
  • 做cpa的博客網(wǎng)站類型博客網(wǎng)
  • 優(yōu)惠券推廣網(wǎng)站怎么做seo怎么搞
  • nas網(wǎng)站怎么做網(wǎng)站時(shí)事新聞最新2022
  • 順德樂(lè)從有做阿里巴巴的網(wǎng)站嗎sem競(jìng)價(jià)專員是干什么的
  • 做網(wǎng)站視頻圖片加載不出來(lái)企業(yè)網(wǎng)站模板下載
  • 情感視頻素材網(wǎng)站劉連康seo培訓(xùn)哪家強(qiáng)
  • 網(wǎng)站建設(shè)和網(wǎng)站推廣可以同一家做嗎網(wǎng)站優(yōu)化排名金蘋(píng)果系統(tǒng)
  • 企業(yè)網(wǎng)站建設(shè)英文超級(jí)外鏈
  • 手機(jī)網(wǎng)站哪家好西安百度推廣優(yōu)化
  • 網(wǎng)站開(kāi)發(fā) 英文文章百度收錄快的發(fā)帖平臺(tái)
  • 福州網(wǎng)頁(yè)鄭州seo排名優(yōu)化公司
  • 汕頭網(wǎng)站建設(shè)制作公司衡陽(yáng)seo快速排名
  • 分類信息網(wǎng)站成都搭建如何搭建一個(gè)網(wǎng)站平臺(tái)
  • 做網(wǎng)站的點(diǎn)子站長(zhǎng)之家ppt素材
  • 同程網(wǎng)站建設(shè)分析朝陽(yáng)網(wǎng)站建設(shè)公司
  • 深圳住建委網(wǎng)站智謀網(wǎng)站優(yōu)化公司
  • html5門(mén)戶網(wǎng)站模板百度人工客服電話多少
  • 鄭州做網(wǎng)站九零后排名點(diǎn)擊工具
  • 網(wǎng)站開(kāi)發(fā)程序員 工資百度云怎么找資源
  • 貴陽(yáng)網(wǎng)站建設(shè)多少錢(qián)?影視后期培訓(xùn)機(jī)構(gòu)全國(guó)排名