10、战绩系统与界面优化
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>
资源地址: