1. 加密、壓縮js代碼
安裝terser
:
sudo apt-get update
sudo apt-get install npm
sudo npm install terser -g
terser
不僅支持文件輸入,也支持標准輸入。結果會輸出到標准輸出中。
使用方式:
terser xxx.js -c -m
scripts/compress_game_js.sh
#! /bin/bash
JS_PATH=/home/sdz/project/hyld/game/static/js/
JS_PATH_DIST=${JS_PATH}dist/
JS_PATH_SRC=${JS_PATH}src/
find $JS_PATH_SRC -type f -name '*.js' | sort | xargs cat | terser -c -m > ${JS_PATH_DIST}game.js
echo yes | python3 /home/sdz/project/hyld/manage.py collectstatic
2. 清理監聽函數
在AcAPP
關閉之前觸發的事件可以通過如下api
添加:
AcWingOS.api.window.on_close(func);
game/static/js/src/playground/zbase.js
create_uuid() {
let res = "";
for (let i = 0; i < 8; i++) {
let x = parseInt(Math.floor(Math.random() * 10)); // 返回[0, 1)之間的數
res += x;
}
return res;
}
start() {
let outer = this;
let uuid = this.create_uuid();
$(window).resize(`resize.${uuid}`, function () {
outer.resize();
});
// 關閉窗口,關閉上面對應的
if (this.root.AcWingOS) {
this.root.AcWingOS.api.window.on_close(function () {
$(window).off(`resize.${uuid}`);
});
}
}
注意:
- 同一個頁面中,多個
acapp
引入的js
代碼只會加載一次,因此AC_GAME_OBJECTS
等全局變量是同一個頁面、同一個acapp
的所有窗口共用的。 - 各自創建的局部變量是獨立的,比如
new AcGame()
創建出的對象各個窗口是獨立的。
3. 編寫每局游戲的結束界面
game/static/js/src/playground/score_board/zbase.js
class ScoreBoard extends HyldObject {
constructor(playground) {
super();
this.playground = playground;
this.ctx = this.playground.game_map.ctx;
this.state = null; // win: 勝利,lose:失敗
this.win_img = new Image();
this.win_img.src = "https://cdn.acwing.com/media/article/image/2021/12/17/1_8f58341a5e-win.png";
this.lose_img = new Image();
this.lose_img.src = "https://cdn.acwing.com/media/article/image/2021/12/17/1_9254b5f95e-lose.png";
}
start() {
}
add_listening_events() {
let outer = this;
let $canvas = this.playground.game_map.$canvas;
$canvas.on('click', function() {
outer.playground.hide();
outer.playground.root.menu.show();
});
}
win() {
this.state = "win";
let outer = this;
setTimeout(function() {
outer.add_listening_events();
}, 1000);
}
lose() {
this.state = "lose";
let outer = this;
setTimeout(function() {
outer.add_listening_events();
}, 1000);
}
late_update() {
this.render();
}
render() {
let len = this.playground.height / 2;
if (this.state === "win") {
this.ctx.drawImage(this.win_img, this.playground.width / 2 - len / 2, this.playground.height / 2 - len / 2, len, len);
} else if (this.state === "lose") {
this.ctx.drawImage(this.lose_img, this.playground.width / 2 - len / 2, this.playground.height / 2 - len / 2, len, len);
}
}
}
注意:
觸發時機:一定要有this.playground.state ==="fighting"
,需要好好考慮條件
game/static/js/src/playground/palyer/zbase.js
update_win() {
if(this.playground.state ==="fighting" && this.character === "me" && this.playground.players.length === 1){
this.playground.state = "over";
this.playground.score_board.win();
}
}
if (this.character === "me"){
if(this.playground.state === "fighting") {
this.playground.state = "over";
this.playground.score_board.lose();
}
}
playground
需要刪除諸多里面的元素
資源地址:
4. 更新戰績
注意極端情況,考慮到兩個小球互相發子彈,然后一前一后消失,導致房間失效。
async def attack(self, data):
# 可能回出現極端情況
if not self.room_name:
return
players = cache.get(self.room_name)
if not players:
return
for player in players:
if player['uuid'] == data['attackee_uuid']:
player['hp'] -= 25
remain_cnt = 0
for player in players:
if player['hp'] > 0:
remain_cnt += 1
if remain_cnt > 1:
if self.room_name:
cache.set(self.room_name, players, 3600)
else:
def dp_update_player_score(username, score):
player = Player.objects.get(user__username=username)
player.score += score
player.save()
for player in players:
if player['hp'] <= 0:
await database_sync_to_async(dp_update_player_score)(player['username'], -5)
else:
await database_sync_to_async(dp_update_player_score)(player['username'], 10)
await self.channel_layer.group_send(
self.room_name,
{
'type': "group_send_event",
'event': "attack",
'attackee_uuid': data["attackee_uuid"],
'uuid': data['uuid'],
'x': data['x'],
'y': data['y'],
'angle': data['angle'],
'damage': data['damage'],
'ball_uuid': data['ball_uuid'],
}
)
async def blink(self, data):
await self.channel_layer.group_send(
self.room_name,
{
'type': "group_send_event",
'event': "blink",
'uuid': data['uuid'],
'tx': data['tx'],
'ty': data['ty'],
}
)
5. 添加favicon.ico
game/templates/multiends/web.html
{% load static %}
<head>
<link rel="stylesheet" href="https://cdn.acwing.com/static/jquery-ui-dist/jquery-ui.min.css">
<script src="https://cdn.acwing.com/static/jquery/js/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="{% static 'css/game.css' %}">
<link rel="icon" href="https://cdn.acwing.com/media/article/image/2021/12/17/1_be4c11ce5f-acapp.png">
</head>
<body style="margin: 0">
<div id="hyld"></div>
<script type="module">
import {Hyld} from "{% static 'js/dist/game.js' %}";
$(document).ready(function(){
let hyld = new Hyld("hyld");
});
</script>
</body>
資源地址: