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

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

WBOY
發布: 2024-09-12 18:15:41
原創
556 人瀏覽過

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 頁面。

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

Fis donc de tous les détails de l'architecture, celle ci n'ayant que peu changer (hormis l'adaptation en évitant l'utilisation des canvas) depuis la première partie de mon devlog.
Nous allons donc parler du projet réalisé, de la manière dont nous avons travaillé en équipe et des problèmes que nous avons rencontré.
Voyez cela comme un retour d'expérience sur ce projet, et j'espère que vous parviendrai à tirer de cette rédaction quelques enseignements qui vous aiderons sur un de vos projet.

Le projet

Le projet était de recréer un Super Mario Bros en JavaScript et en partant de zéro, tout du moins pour ce qui est du code.

Le cahier des charges était simple, nous devions avoir un jeu mario avec plusieurs niveau, une manière d'en créer de nouveaux simplement.
Aussi nous devions créer un tableau des scores et un menu afin de régler les options.

Les difficultés de ce projet étaient :

  • Le défilement horizontal des éléments à l'écran
  • L'optimisation des éléments n'étants pas présent à l'écran

Le défilement car il requiert que tous les éléments défile en arrière plan relativement à la position du joueur.
Et l'optimisation des éléments qui ne sont pas affiché à l'écran permet de réduire les ressources nécessaires à faire fonctionner le jeu sans perte de performance.

Après avoir résolus ces difficultés nous avons publié ce jeu sur ma page itch.io sur laquelle même vous pouvez aller le tester.

Voila comment se termine ce devlog, maintenant terminé je vais pouvoir écrire sur d'autres projets et/ou d'autres sujets.

Si tu es même un petit peu intéressé par ce que je te raconte, tu peux aller voir mes différents projets (Dont ceux de ce devlog) sur github.

Bonne fin de journée!

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

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