Heim >Web-Frontend >js-Tutorial >Devlog – Ich erstelle eine Spiel-Engine!

Devlog – Ich erstelle eine Spiel-Engine!

WBOY
WBOYOriginal
2024-09-12 18:15:41690Durchsuche

Devlog - Je créé un moteur de jeu !

Ich erstelle eine Spiel-Engine!

Einführung in dieses großartige Abenteuer

Seit einigen Wochen arbeite ich regelmäßig an einem Projekt, von dem ich glaube, dass es interessant sein könnte, darüber zu sprechen: der Erstellung meiner Videospiel-Engine in JavaScript und HTML5 auf Basis von Canvas.

Sie fragen sich wahrscheinlich, warum Sie sich für HTML5 und JavaScript entschieden haben, um Videospiele zu erstellen? Die Antwort ist weniger cool als die Frage, es ist der Wettbewerb der für meine Schule (Zone01 Normandie) notwendigen Projekte und die Tatsache, dass die Sprachen über alles Notwendige verfügen, um dieses Projekt durchzuführen, die mich dazu veranlasst haben, diese Technologien zu wählen

Aber eigentlich sind das nicht die Sprachen, die ich als Basis gewählt hätte, und ich werde mich nach der Fertigstellung dieses Abenteuers sicherlich auf andere Abenteuer dieser Art mit anderen Sprachen einlassen.

Architektur

Also habe ich mich an die Arbeit gemacht, meine Videospiel-Engine zu entwerfen. Sie wird aus mehreren Klassen bestehen, darunter mindestens zwei Hauptklassen: Die Game-Klasse, die den gesamten Spielbereich verwaltet, und die GameObject-Klasse, mit der Sie die Objekte generieren können unsere Spiele und sorgen dafür, dass sie miteinander interagieren.

Zu diesen Klassen füge ich die CollideBox-Klasse hinzu, mit der ich die Kollisionsboxen aller Objekte verwalten kann.

Die Game-Klasse verfügt über eine GameLoop-Methode, die bei jedem Frame (Bild) des Spiels ausgeführt wird, und eine Draw-Methode, die während jeder Spielschleife aufgerufen wird.

Die GameObject-Klasse verfügt über eine Step-Methode und eine Draw-Methode.
Der erste führt jede Runde der Spielschleife aus und der zweite jedes Mal, wenn die Draw-Methode der GameLoop-Klasse aufgerufen wird.

Damit können Sie theoretisch Spiele erstellen, indem Sie das Engine-Modul in ein Projekt importieren.
Für die Anzeige der Sprites habe ich mich für die Canva-API entschieden, die in HTML5 integriert ist (integriert bedeutet, dass sie standardmäßig mitgeliefert wird)
Dadurch kann ich alle Sprites anzeigen und die Bilder neu schneiden, um Animationen zu erstellen, die für mich äußerst nützlich sein werden!

Nach einigen Tagen bin ich in der Lage, Animationen bei einer bestimmten Geschwindigkeit anzuzeigen und Kollisionen über meine CollideBoxes zu erkennen.
Und viele andere schöne Dinge, die ich Ihnen unten zeigen werde:

Die GameObject-Klasse

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()   {};
}   

Die Spielklasse

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
    }
}

Es gibt sicherlich viele Optimierungen oder andere Fehler, aber alles funktioniert,
"Perfekt!" verrätst du es mir?
Das wäre viel zu einfach.

Die Sorgen

Nachdem ich damit fertig war und begonnen hatte, die Voraussetzungen für die Erstellung eines Spiels mit dieser Engine zu testen, erfuhr ich während eines Gesprächs mit einem Kollegen schreckliche Neuigkeiten.

Ich kann mir vorstellen, dass Sie sich daran erinnern, dass die Technologieentscheidungen getroffen wurden, um den Anforderungen meiner Zone01-Schule zu entsprechen …
Nun ja, die gewählten Sprachen waren zwar gut, aber mir war keine Anleitung bekannt, die das Projekt ernsthaft behindern würde…
Es war uns untersagt, die Canva-Bibliothek zu nutzen!

Zur Erinnerung: Dies ist die Bibliothek, die wir zum Anzeigen unserer Bilder verwenden.

Was kommt als nächstes?

Während ich diesen Text schreibe, beginne ich auch damit, diese Spiel-Engine komplett neu zu gestalten, ohne die Verwendung von Canva.

Dieses Devlog ist fertig und Sie werden den Rest dieser Geschichte bald haben, keine Sorge.
Für den nächsten Devlog werde ich auf jeden Fall ein neues Format ausprobieren.

Ich hoffe, dass dieser Inhalt Ihnen geholfen, Sie unterhalten oder Sie zumindest über einige Themen aufgeklärt hat. Ich wünsche Ihnen einen schönen Feierabend und gute Codierung.

DevLogs 1.1: Die Engine ist fertig, wie funktioniert sie?

Vorher

Vor ein paar Monaten habe ich mit der Entwicklung meiner Videospiel-Engine begonnen, ich habe sie fertiggestellt ... Vor einiger Zeit und mit der Hilfe mehrerer Kollegen von Zone01 ist es uns sogar gelungen, ein von Super Mario Bros. inspiriertes Spiel zu entwickeln, das auf meinem verfügbar ist Itch.io-Seite.

Die Entscheidung über das Format für die Bewerbung für dieses Devlog hat viel Zeit in Anspruch genommen, und ich gebe zu, dass ich die Frist für das Schreiben dieses Devlogs leicht verzögert oder sogar ganz verschoben habe.
Indem ich geduldig die Entschuldigung meiner Unentschlossenheit entgegennehme, nicht an diesem Thema zu arbeiten, befinde ich mich nun zwei Monate nach dem geplanten Veröffentlichungstermin wieder und schreibe auf dem Rastplatz des Busbahnhofs von Rouen, während mein ausgefallener Zug mich dazu zwingt, eine zusätzliche Stunde zu warten.

Ignorieren wir also alle Details der Architektur, denn diese hat sich seit dem ersten Teil meines Devlogs kaum verändert (abgesehen von der Anpassung durch den Verzicht auf Leinwände).
Wir werden daher über das durchgeführte Projekt, die Art und Weise, wie wir als Team gearbeitet haben, und die Probleme sprechen, auf die wir gestoßen sind.
Sehen Sie dies als Feedback zu diesem Projekt und ich hoffe, dass Sie aus diesem Schreiben einige Lehren ziehen können, die Ihnen bei einem Ihrer Projekte helfen werden.

Das Projekt

Das Projekt bestand darin, einen Super Mario Bros. in JavaScript nachzubilden und, zumindest was den Code betrifft, ganz von vorne anzufangen.

Die Spezifikationen waren einfach, wir mussten ein Mario-Spiel mit mehreren Levels haben, eine Möglichkeit, einfach neue zu erstellen.
Außerdem mussten wir eine Anzeigetafel und ein Menü erstellen, um die Optionen anzupassen.

Die Schwierigkeiten dieses Projekts waren:

  • Horizontales Scrollen von Elementen auf dem Bildschirm
  • Optimierung von Elementen, die nicht auf dem Bildschirm vorhanden sind

Scrollen, da alle Elemente im Hintergrund relativ zur Position des Spielers scrollen müssen.
Und durch die Optimierung von Elementen, die nicht auf dem Bildschirm angezeigt werden, werden die Ressourcen reduziert, die zum Ausführen des Spiels ohne Leistungsverlust erforderlich sind.

Nachdem wir diese Schwierigkeiten gelöst haben, haben wir dieses Spiel auf meiner itch.io-Seite veröffentlicht, wo Sie es sogar testen können.

So endet dieser Devlog, jetzt, da ich fertig bin, kann ich über andere Projekte und/oder andere Themen schreiben.

Wenn Sie auch nur ein wenig daran interessiert sind, was ich Ihnen erzähle, können Sie sich meine verschiedenen Projekte (einschließlich der in diesem Devlog) auf Github ansehen.

Einen schönen Rest des Tages!

Das obige ist der detaillierte Inhalt vonDevlog – Ich erstelle eine Spiel-Engine!. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn