XT Knowledge Base
Hauptseite | Über | Hilfe | FAQ | Spezialseiten | Anmelden

Druckversion | Impressum | Datenschutz | Aktuelle Version

Spieleentwicklung mit JavaScript - Die PlayField-Klasse

Version vom 09:47, 3. Sep. 2010 bei Monettenom (Diskussion | Beiträge)

Inhaltsverzeichnis

Die PlayField-Klasse

Inzwischen ist das JavaScript-Programm ein bißchen unübersichtlich geworden. Funktionen mischen sich mit Variablen und Eventhandlern. Bevor wir dieses Chaos erweitern, sollten wir erst ein bißchen aufräumen. Es bietet sich an, die Funktionen, die zur Darstellung des Spielfelds notwendig sind zusammenzufassen.

Exkurs: Klassen in JavaScript

Hier kommt die "objektorientierte Programmierung" (kurz OOP) ins Spiel, die es ermöglicht, zusammengehörende Daten und Funktionen sinnvoll zu strukturieren. JavaScript ist zwar keine objektorientierte Sprache, sie bietet aber ein paar Sprachkonstrukte, die es ermöglichen, einige Ansätze der Objektorientierung umzusetzen.

Ein Beispiel:

function Position( x, y )
{
  this.x = x;
  this.y = y;
}
        
Position.prototype.getX = function()
{
  return this.x;
}
        
Position.prototype.getY = function()
{
  return this.y;
}

Position.prototype.setXY = function( x, y )
{
  this.x = x;
  this.y = y;
}

var pos = new Position( 10, 20 );
alert( "x: " + pos.getX() + ", y: " + pos.getY() );
pos.setXY( 99, 100 );
alert( "x: " + pos.getX() + ", y: " + pos.getY() );

Die Klassendeklaration sieht aus wie eine ganz normale Funktion. Innerhalb dieser Funktion können Member-Variablen definiert und gleichzeitig initialisiert werden. Die Klassendeklaration dient somit auch gleichzeitig als Konstruktor. Ein Konstruktor einer Klasse ist eine Funktion, die direkt beim Erstellen aufgerufen wird und das Objekt "konstruiert", d.h. alle Member-Variablen initialisiert und andere Initialisierungen durchführt, so dass das Objekt benutzt werden kann.

In diesem Fall erhält die Klasse im Konstruktor x und y, die in den Membervariablen gespeichert werden.

Für die Definition der Methoden gibt es drei unterschiedliche Varianten. Ich empfehle die oben verwendete, da sie am übersichtlichsten ist. Die Alternativen wären, die Methoden direkt im Konstruktor zu definieren oder sie im JSN-Format anzugeben, was ich nur für sehr kleine Klassen empfehle.

Vorüberlegungen

Nun muss entschieden werden, welche Informationen in die PlayField-Klasse aufgenommen werden sollen:

  1. Die Referenzen auf die HTML-Elemente, die für die Darstellung des Spielfelds notwendig sind
  2. Alle Variablen, die dynamisch berechnet werden
  3. Die Tiles, die zum Zeichnen benötigt werden
  4. Die aktuelle Position des sichtbaren Bereichs

Außerdem wird die drawPlayField-Funktion in die Klasse aufgenommen.

Die Eventhandler und Steuerung wird nicht in die PlayField-Klasse integriert, da sich die Art der Steuerung von Spiel zu Spiel unterscheiden kann. Daher beschränken wir uns bei der Klasse auf die reine Darstellung behalten uns vor, für die Steuerung eigene Klassen zu erstellen, die man dann beliebig mit der PlayField-Klasse kombinieren kann.

Alle statischen Informationen wie die Anzahl der Tiles im Tileset und die Leveldefinition wird im Konstruktor übergeben.

Der PlayField-Konstruktor

  function PlayField( playfield_id, tileset_id, tile_count_x, tile_count_y, level )
  {
    this.canvas = document.getElementById( playfield_id );
    this.context = this.canvas.getContext("2d");
    var imgTileSet = document.getElementById( tileset_id );
    this.tiles = new Array();
    this.context.drawImage( imgTileSet, 0, 0 );
    this.level = level;

    this.display_pixel_width = this.canvas.width;
    this.display_pixel_height = this.canvas.height;
    this.tile_pixel_width = imgTileSet.width / tile_count_x;
    this.tile_pixel_height = imgTileSet.height / tile_count_y;
    this.display_tile_width = Math.ceil( this.display_pixel_width / this.tile_pixel_width )+1;
    this.display_tile_height = Math.ceil( this.display_pixel_height / this.tile_pixel_height )+1;
    this.map_tile_width = level[0].length;
    this.map_tile_height = level.length;
    this.map_pixel_width = this.map_tile_width * this.tile_pixel_width;
    this.map_pixel_height = this.map_tile_height * this.tile_pixel_height;
    
    this.posx = 0;
    this.posy = 0;
    
    for( var y = 0; y < tile_count_y; y++ )
    {
      for( var x = 0; x < tile_count_x; x++ )
      {
        var i = y * tile_count_x + x;
        var imgData = this.context.getImageData( 
          x * this.tile_pixel_width, 
          y * this.tile_pixel_height, 
          this.tile_pixel_width, 
          this.tile_pixel_height 
        );
        this.tiles[i] = document.getElementById("tile"+i);
        this.tiles[i].width = this.tile_pixel_width;
        this.tiles[i].height = this.tile_pixel_height;
        this.tiles[i].getContext("2d").putImageData( imgData, 0, 0 );
      }
    }
  }

Der für das PlayField relevatnte Code aus der Init()-Funktion wurde nun in den Konstruktor übertragen. Alle Variablen-Zugriffe müssen nun mit this.<variable> angegeben werden.

Der Konstruktor erhält nun folgende Parameter:


Finden

Blättern
Hauptseite
XT Knowledge Base-Portal
Aktuelle Ereignisse
Letzte Änderungen
Zufällige Seite
Konfiguration
Hilfe
Ändern
Quelltext betrachten
Bearbeitungshilfe
Seitenoptionen
Diskussion
Neuer Abschnitt
Druckversion
Seitendaten
Versionen
Links auf diese Seite
Änderungen an verlinkten Seiten
Meine Seiten
Anmelden
Spezialseiten
Neue Seiten
Dateiliste
Statistik
Mehr …