Objektorientiertes JavaScript Spiel

Dieses kleine Spiel soll mit einfachen Mittel zeigen das man auch in JavaScript gutlesbaren, objektorientierten Code schreiben kann.

Als Unterstützung verwende ich die jQuery Bibilothekt um mir das arbeiten mit dem DOM und das Positionieren zu erleichtern.

Für das ganze Spiel werden nur 4 Objekte benötigt, wobei eines nur ein Containerobjekt für Tastencode-Zuweisungen ist. Ich habe für alle Objekte eine eigene Datei erstellt um eine gute Lesbarkeit zu erreichen. Immer wenn die Datei ein JavaScript-Objekt repräsentiert schreibe ich den Dateiname groß.

Unser Startpunkt ist die Datei Game.js. Als Erstes wird für jedes Element mit der Klasse „.game“ eine Game-Objekt erzeugt, dadurch werden auch die im Konstruktor definierten Variablen zugewiesen und Methoden ausgeführt. Ich initialisiere einen KeyListener um auf Tastatureingaben zu reagieren. In der Datei „util.js“ ist das Containerobjekt mit den Tastencode-Zuweisungen.

In der Methode „run()“ wird das Spiel gestartet. Mit der setInerval Funktion des Window-Objekts erreichen wir eine dauerhafte Ausführung unseres Spiels. In jedem Durchlauf können wir die Hindernisse bewegen, Kollision zwischen Spieler und Gegenständen feststellen und gegeben Falls darauf reagieren.

Im Konstuktor des Game-Objektes wird außerdem für jedes Hinderniss und den Spieler jeweils Objekte erstellt. Diese sind dem Game-Objekt bekannt um in der „run()“
Methode mit ihnen zu arbeiten.

$(document).ready(function () {

    $('.game').each(function () {
        new Game($(this));
    });

});

function Game($game) {
    this.$board = $game.find('.board');
    this.speed = 10;
    this.pause = false;
    this.gameOver = false;
    this.player = new Player(this.$board);
    this.$text = $game.find(".text");
    this.barriers = this.initBarrier();
    this.initKeyListener();
    this.run();
}

Game.prototype.run = function () {
    var game = this;
    var $player = game.player.$player;

    window.setInterval(function () {

        if (game.gameOver || game.pause) {
            return;
        }

        $.each(game.barriers, function (i) {

            this.move();

            if ($player.collidesWith(this.$barrier).length) {
                game.gameOver = true;
                game.$text.text("GAME OVER!");
            }

            if ($player.offset().top > (game.$board.height() + $player.height())) {
                game.pause = true;
                game.$text.text("WIN!");
            }

        });

    }, game.speed);
};

Game.prototype.initKeyListener = function () {
    var game = this;
    $(window).bind('keydown', function (e) {
        switch (e.keyCode) {

            // Reset
        case Keys.ESC:
            game.player.reset();
            game.pause = false;
            game.gameOver = false;
            game.$text.text("");
            break;

            // Pause
        case Keys.SPACE:
            game.pause = !game.pause;
            break;

            // Spieler zurücksetzen
        case Keys.POS1:
            if (!game.pause && !game.gameOver) game.player.reset();
            break;

        case Keys.LEFT:
            if (!game.pause && !game.gameOver) game.player.moveLeft();
            break;

        case Keys.UP:
            if (!game.pause && !game.gameOver) game.player.moveUp();
            break;

        case Keys.RIGHT:
            if (!game.pause && !game.gameOver) game.player.moveRight();
            break;

        case Keys.DOWN:
            if (!game.pause && !game.gameOver) game.player.moveDown();
            break;

        default:
            break;
        }
    });
};

Game.prototype.initBarrier = function () {
    var $board = this.$board;
    var barriers = [];
    $board.find('.barrier').each(function () {
        barriers.push(new Barrier($board, $(this)));
    });
    return barriers;
};

Das Player-Objekt wird lediglich vom KeyListener angesprochen. Je nach Tastatureingabe wird das enthaltene HTML bzw. jQuery Objekt bewegt.

function Player($board) {
    var p = this;
    p.speed = 5;
    p.$board = $board;
    p.$player = p.$board.find('.player:eq(0)');
}

Player.prototype.reset = function () {
    this.$player.css("margin", "0");
};

Player.prototype.moveUp = function () {
    var p = this;
    if (p.$player.offset().top > p.$board.offset().top) {
        p.$player.css("margin-top", "-=" + p.speed + "px");
    }
};

Player.prototype.moveDown = function () {
    var p = this;
    if (p.$player.offset().top < (p.$board.height() + p.$player.height())) {
        p.$player.css("margin-top", "+=" + p.speed + "px");
    }
};

Player.prototype.moveLeft = function () {
    var p = this;
    if (p.$player.offset().left > p.$board.offset().left) {
        p.$player.css("margin-left", "-=" + p.speed + "px");
    }
};

Player.prototype.moveRight = function () {
    var p = this;
    if (p.$player.offset().left - p.speed < p.$board.width()) {
        p.$player.css("margin-left", "+=" + p.speed + "px");
    }
};

Die „move()“ Methode des Barrier Objektes wird in jedem Durchlauf der „run()“ Methode aufgerufen, dadurch bewegt es sich automatisch und wird so „animiert“.

function Barrier($board, $barrier) {
    var b = this;
    b.$board = $board;
    b.$barrier = $barrier;
    b.moveLeft = false;
    b.sign = "+";
    b.range = 1;
}

Barrier.prototype.move = function () {
    var b = this;

    // Move left
    if (b.nachLinks || (b.$barrier.offset().left + b.$board.position().left >= b.$board.width())) {
        b.sign = "-";
        b.nachLinks = true;
    }

    // Move right
    if (b.$barrier.offset().left <= b.$board.offset().left) {
        b.sign = "+";
        b.nachLinks = false;
    }

    b.$barrier.css("margin-left", b.sign + "=" + b.range + "px");

};

Hier könnt ihr meine Sourcen Downloaden um sie euch genauer anzusehen und vielleicht selber noch ein bisschen damit rum zu spielen.

Download