首頁 > web前端 > js教程 > 主體

開發日誌 - 我正在創建一個遊戲引擎!

PHPz
發布: 2024-09-12 18:15:38
原創
283 人瀏覽過

Devlog - Je créé un moteur de jeu !

我正在創建一個遊戲引擎!

這場偉大的冒險簡介

幾週以來,我一直在定期從事一個我認為可能很有趣的項目,即基於 canvas 使用 JavaScript 和 HTML5 創建我的視頻遊戲引擎。

您可能想知道為什麼選擇 HTML5 和 JavaScript 來創建視訊遊戲?答案沒有問題那麼酷,是我的學校(Zone01 Normandie)所需的項目的競爭,以及語言擁有執行該項目所需的一切的事實,促使我選擇了這些技術

但實際上這些並不是我會選擇作為基礎的語言,在完成這個任務後我一定會用不同的語言開始其他類似的冒險。

建築學

所以我開始設計我的電玩引擎,它將由幾個類別組成,包括至少兩個主要類別:Game 類別將管理整個遊戲區域,而GameObject 類別允許您生成物件我們的遊戲並讓它們互相互動。

對於這些類,我將添加 CollideBox 類,它將允許我管理所有物件的碰撞框。

Game 類別有一個 GameLoop 方法,將在遊戲的每個畫面(圖片)執行,還有一個 Draw 方法,將在每個遊戲循環期間呼叫。

對於GameObject類,它有一個Step方法和一個Draw方法。
第一個執行每輪遊戲循環,第二個每次呼叫 GameLoop 類別的 Draw 方法時執行。

理論上,您可以透過將引擎模組匯入到專案中來創建遊戲。
為了顯示精靈,我選擇使用 HTML5 內建的canva API(內建意味著它預設附帶)
它將允許我顯示所有精靈並重新剪切圖像以創建對我來說非常有用的動畫!

幾天后,我能夠以給定的速度顯示動畫,並透過我的 CollideBox 偵測碰撞。
還有很多其他好東西,我會讓你在下面看到:

GameObject 類別

class GameObject{
    constructor(game) { // Initialize the GameObject
        this.x = 0
        this.y = 0 
        this.sprite_img = {file: undefined, col: 1, row: 1, fw: 1, fh: 1, step: 0, anim_speed: 0, scale: 1}
        this.loaded = false
        this.game = game
        this.kill = false
        this.collision = new CollideBox()

        game.gObjects.push(this)

    };
    setSprite(img_path, row=1, col=1, speed=12, scale=1) {
        var img = new Image();
        img.onload = () => {
            console.log("image loaded")
            this.sprite_img = {file: img, col: col, row: row, fw: img.width / col, fh: img.height / row, step: 0, anim_speed: speed, scale: scale}
            this.onSpriteLoaded()
        };
        img.src = img_path


    }
    onSpriteLoaded() {}
    draw(context, frame) { // Draw function of game object
        if (this.sprite_img.file != undefined) {


            let column = this.sprite_img.step % this.sprite_img.col;
            let row = Math.floor(this.sprite_img.step / this.sprite_img.col);

           // context.clearRect(this.x, this.y, this.sprite_img.fw, this.sprite_img.fh);
            context.drawImage(
                this.sprite_img.file,
                this.sprite_img.fw * column,
                this.sprite_img.fh * row,
                this.sprite_img.fw,
                this.sprite_img.fh,
                this.x,
                this.y,
                this.sprite_img.fw * this.sprite_img.scale,
                this.sprite_img.fh * this.sprite_img.scale
            );

            if (frame % Math.floor(60 / this.sprite_img.anim_speed) === 0) {
                // Mise à jour de step seulement à 12 fps
                if (this.sprite_img.step < this.sprite_img.row * this.sprite_img.col - 1) {
                    this.sprite_img.step += 1;
                } else {
                    this.sprite_img.step = 0;
                }
            }
        }
    }
    distance_to(pos) {
        return Math.sqrt((pos.x - this.x) ** 2 + (pos.y - this.y) ** 2)
    }

    collide_with(box) {
        if (box instanceof GameObject) {
            box = box.collision
        }
        return (
            this.collision.x < box.x + box.w &&
            this.collision.x + this.collision.w > box.x &&
            this.collision.y < box.y + box.h &&
            this.collision.y + this.collision.h > box.y
          )
    }
    onStep()   {};
}   
登入後複製

遊戲類

class Game {
    constructor(width = 1400, height = 700) {
        this.gObjects = [];
        this.toLoad = [];
        this.timers = [];
        this.layers = [];
        this.canvas = document.getElementsByTagName("canvas")[0]

        this.canvas.width = width
        this.canvas.height = height
        this.context =  this.canvas.getContext("2d")
        this.context.globalCompositeOperation = 'source-over';
        this.inputs = {};
        this.mouse = {x: 0, y: 0}
        document.addEventListener('keydown', (e) => {
            this.inputs[e.key] = true;
        }, false);
        document.addEventListener('keyup', (e) => {
            this.inputs[e.key] = false;
        }, false);
        document.addEventListener('mousemove', (e) => {
            this.mouse.x = e.x;
            this.mouse.y = e.y;
        })
        document.addEventListener('mouseevent', (e) => {
            switch (e.button) {

            }
        })

    }
    draw(frame) {
        this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
        console.log( this.canvas.width, this.canvas.heigh)
        for(let i = 0; i < this.gObjects.length; i ++) {
            this.gObjects[i].draw(this.context, frame)
        }

    }
    gLoop() {
        let fps = Math.floor(1000 / 60)
        console.log(fps)
        let clock = 0
        setInterval(() => {
            clock += 1
            for(let i = 0; i < this.gObjects.length; i ++) {

                if (this.gObjects[i] != undefined) {
                    if (this.gObjects[i].kill) {
                        this.gObjects.splice(i, 1);
                        continue;
                    }
                    this.gObjects[i].onStep();
                }


            }
            this.draw(Math.floor(clock))
               // context.l();

           //     console.log(clock)

           if (fps <= clock) {
            clock = 0
           } 

        }, fps)
    }
    keyboard_check(key) {
        return this.inputs[key] == true
    }
}
登入後複製

當然有很多最佳化或其他錯誤,但一切都正常,
「完美的!」你能告訴我嗎?
那就太簡單了。

憂慮

完成此任務並開始嘗試使用此引擎創建遊戲後,我在與同事的談話中得知了一些可怕的消息。

我想您還記得所做的技術選擇是為了符合我的 Zone01 學校的要求......
確實,選擇的語言很好,但我不知道有一條指令會嚴重阻礙該項目......
我們被禁止使用 Canva 函式庫!

提醒一下,這是我們用來顯示圖像的函式庫。

接下來是什麼?

當我寫這篇文章時,我也開始完全重新設計這個遊戲引擎,而不使用canva。

本開發日誌已經完成,您很快就會看到這個故事的其餘部分,別擔心。
對於下一個開發日誌,我一定會嘗試新的格式。

希望這些內容對您有所幫助,給您帶來樂趣,或至少在一些主題上對您進行了教育。祝您一天愉快,程式設計愉快。

DevLogs 1.1:引擎完成了,它是如何運作的?

之前

幾個月前,我開始創建我的電玩引擎,我完成了它......不久前,在Zone01 的幾位同事的幫助下,我們甚至成功地創建了一款受《超級瑪利歐兄弟》啟發的遊戲,可以在我的網站上找到Itch.io 頁面。

決定申請這個開發日誌的格式花了很多時間,我承認我稍微推遲了甚至完全推遲了寫這篇文章的截止日期。
透過耐心地以我猶豫不決為藉口不從事這個主題,我現在發現自己在計劃發布日期兩個月後在魯昂汽車站的休息區寫作,而取消的火車迫使我多等一個小時。

因此,让我们忽略架构的所有细节,自我的开发日志的第一部分以来,这个架构的变化很小(除了通过避免使用画布进行的调整之外)。
因此,我们将讨论所进行的项目、我们作为团队的工作方式以及我们遇到的问题。
将此视为对该项目的反馈,我希望您能够从本文中吸取一些教训,这将对您的项目之一有所帮助。

项目

该项目是用 JavaScript 重新创建一个超级马里奥兄弟,并从头开始,至少在代码方面是这样。

规格很简单,我们必须有一个具有多个级别的马里奥游戏,这是一种简单地创建新级别的方法。
此外,我们还必须创建一个记分板和一个菜单来调整选项。

这个项目的难点是:

  • 屏幕上元素的水平滚动
  • 优化屏幕上不存在的元素

滚动,因为它要求所有元素在背景中相对于玩家的位置滚动。
优化屏幕上未显示的元素有助于减少运行游戏所需的资源,而不会损失性能。

解决了这些困难后,我们在我的 itch.io 页面上发布了这个游戏,您甚至可以去测试它。

本开发日志就这样结束了,现在完成了,我将能够撰写有关其他项目和/或其他主题的文章。

如果你对我告诉你的内容有一点兴趣,你可以在 github 上查看我的不同项目(包括本开发日志中的项目)。

祝你今天休息愉快!

以上是開發日誌 - 我正在創建一個遊戲引擎!的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!