10、戰績系統與界面優化


源碼地址https://gitee.com/pxlsdz/hyld

演示地址http://121.199.59.80/hyld/

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需要刪除諸多里面的元素

資源地址:

  1. 獲勝圖標
  2. 失敗圖標

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>

資源地址:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM