Spieleentwicklung mit JavaScript - Dynamische Spielfelder
(Unterschied zwischen Versionen)
(→Zeichnen des Spielfelds) |
|||
(Der Versionsvergleich bezieht 1 dazwischenliegende Version mit ein.) | |||
Zeile 17: | Zeile 17: | ||
<meta http-equiv="content-type" content="text/html;charset=UTF-8"> | <meta http-equiv="content-type" content="text/html;charset=UTF-8"> | ||
<title>Sample</title> | <title>Sample</title> | ||
- | + | <script type="text/javascript"> | |
- | <script type="text/javascript"> | + | var canvas; |
- | + | var context; | |
- | + | var tiles = new Array(); | |
- | + | var level = new Array( | |
- | + | new Array( 0,4,0,0,0,0,0,0 ), | |
- | + | new Array( 2,1,1,1,1,1,1,2 ), | |
- | + | new Array( 2,0,3,0,0,0,0,2 ), | |
- | + | new Array( 2,0,3,0,0,0,0,2 ), | |
- | + | new Array( 2,0,3,2,1,1,1,2 ), | |
- | + | new Array( 2,4,3,2,0,0,0,4 ), | |
- | + | new Array( 1,1,1,2,1,0,1,1 ), | |
- | + | new Array( 4,0,0,2,0,0,4,0 ) | |
- | + | ); | |
- | + | ||
- | + | function init() | |
- | + | { | |
- | + | canvas = document.getElementById("board"); | |
- | + | context = canvas.getContext("2d"); | |
- | + | var tileset = document.getElementById("tileset"); | |
- | + | context.drawImage( tileset, 0, 0 ); | |
- | + | for( var i = 0; i < 5; i++ ) | |
- | + | { | |
- | + | tiles[i] = context.getImageData( i * 30, 0, 30, 30 ); | |
+ | } | ||
+ | |||
+ | drawPlayfield( level ); | ||
} | } | ||
- | |||
- | |||
- | |||
- | + | function drawPlayfield( level ) | |
- | + | ||
- | + | ||
{ | { | ||
- | for( | + | for( y = 0; y < 8; y++ ) |
{ | { | ||
- | context.putImageData( tiles[level[y][x]], x * 30, y * 30 ); | + | for( x = 0; x < 8; x++ ) |
+ | { | ||
+ | context.putImageData( tiles[level[y][x]], x * 30, y * 30 ); | ||
+ | } | ||
} | } | ||
} | } | ||
- | + | </script> | |
- | </script> | + | </head> |
<body onLoad="init();"> | <body onLoad="init();"> | ||
<canvas id="board" width="240" height="240" style="border:1px black solid">Dieser Browser ist nicht geeignet.</canvas> | <canvas id="board" width="240" height="240" style="border:1px black solid">Dieser Browser ist nicht geeignet.</canvas> | ||
Zeile 73: | Zeile 73: | ||
# Im Feld Filter security.fileuri.strict_origin_policy eingeben | # Im Feld Filter security.fileuri.strict_origin_policy eingeben | ||
# Die Einstellung mit einem Doppelklick von true auf false ändern | # Die Einstellung mit einem Doppelklick von true auf false ändern | ||
- | |||
== Vorbereiten des Tilesets == | == Vorbereiten des Tilesets == | ||
Zeile 156: | Zeile 155: | ||
* [[Spieleentwicklung mit JavaScript - Einleitung]] | * [[Spieleentwicklung mit JavaScript - Einleitung]] | ||
* Zurück zu [[Spieleentwicklung mit JavaScript - Spielfeld]] | * Zurück zu [[Spieleentwicklung mit JavaScript - Spielfeld]] | ||
- | * Weiter zu [[Spieleentwicklung mit JavaScript - | + | * Weiter zu [[Spieleentwicklung mit JavaScript - Scrollende Spielfelder]] |
Aktuelle Version vom 07:33, 2. Sep. 2010
Inhaltsverzeichnis |
Dynamische Spielfelder
Viele Spielfelder in Computer setzen sich aus einzelnen Elementen zusammen, die insgesamt das Spielfeld ergeben. Diese einzelnen Teile können unterschiedliche Funktionen und Attribute innehaben wie zum Beispiel "Dieses Feld kann vom Spieler betreten werden" oder "Wer auf dieses Feld kommt, wird weggebeamt".
Um ein solches Spielfeld erzeugen zu können, werden zuerst die Einzelteile benötigt, aus denen es sich zusammensetzt. Das sind sogenannte Tilesets, die alle einzelnen Elemente in einer Grafik zusammenfassen.
Zum Testen bitte dieses Bild abspeichern und in einem Unterordner des Ordners ablegen, in dem sich das Script befindet. Der Name des Ordners ist 'img'.
Dieses Bild enthält 5 Teilstücke, die als Hintergrund für ein Jump'n'Run Spiel dienen können.
Sourcecode
<html> <head> <meta http-equiv="content-type" content="text/html;charset=UTF-8"> <title>Sample</title> <script type="text/javascript"> var canvas; var context; var tiles = new Array(); var level = new Array( new Array( 0,4,0,0,0,0,0,0 ), new Array( 2,1,1,1,1,1,1,2 ), new Array( 2,0,3,0,0,0,0,2 ), new Array( 2,0,3,0,0,0,0,2 ), new Array( 2,0,3,2,1,1,1,2 ), new Array( 2,4,3,2,0,0,0,4 ), new Array( 1,1,1,2,1,0,1,1 ), new Array( 4,0,0,2,0,0,4,0 ) ); function init() { canvas = document.getElementById("board"); context = canvas.getContext("2d"); var tileset = document.getElementById("tileset"); context.drawImage( tileset, 0, 0 ); for( var i = 0; i < 5; i++ ) { tiles[i] = context.getImageData( i * 30, 0, 30, 30 ); } drawPlayfield( level ); } function drawPlayfield( level ) { for( y = 0; y < 8; y++ ) { for( x = 0; x < 8; x++ ) { context.putImageData( tiles[level[y][x]], x * 30, y * 30 ); } } } </script> </head> <body onLoad="init();"> <canvas id="board" width="240" height="240" style="border:1px black solid">Dieser Browser ist nicht geeignet.</canvas> <img id="tileset" src="img/tileset.png" style="visibility:hidden;"> </body> </html>
WICHTIGER HINWEIS
Wird die Seite lokal getestet, muss der Link auf das Bild eine lokale URI sein und im Browser müssen die Einstellungen geändert werden. Dazu sind folgende Schritte notwendig:
- Neues Tab öffnen und in der Adress-Zeile "about:config" eingeben
- Im Feld Filter security.fileuri.strict_origin_policy eingeben
- Die Einstellung mit einem Doppelklick von true auf false ändern
Vorbereiten des Tilesets
Zuerst wird das TileSet als HTML-Element geladen. In der Funktion init() greifen wir darauf zu und kopieren es in den Canvas, um es in die einzelnen Teile zerlegen zu können. Mit der Canvas-Methode GetImageData ist es möglich, einen Bildausschnitt zu kopieren, den wir dann später beliebig oft wieder einfügen können.
Die einzelnen Tiles sind 30x30 Pixel groß und es sind insgesamt 5 Teile. Folgender Code-Abschnitt erledigt diese Aufgabe:
var tileset = document.getElementById("tileset"); context.drawImage( tileset, 0, 0 ); for( var i = 0; i < 5; i++ ) { tiles[i] = context.getImageData( i * 30, 0, 30, 30 ); }
Im Anschluss befinden sich die einzelnen Tiles im tiles-Array. Die einzelnen Tiles haben einen Index von 0 bis 4.
Definition des Spielfelds
Das Spielfeld wird jetzt einfach nur noch durch die Nummern der Tiles beschrieben, die verwendet werden sollen. Also eine Reihe von Zahlen von 0 bis 4. Diese werden in einem zweidimensionalen Array abgelegt, die der Anordnung der Felder auf dem Spielfeld entspricht.
Als Beispiel definieren wir ein Level, dass genau in das dafür vorgesehene Canvas passt - also mit 8x8 Feldern:
var level = new Array( new Array( 0,4,0,0,0,0,0,0 ), new Array( 2,1,1,1,1,1,1,2 ), new Array( 2,0,3,0,0,0,0,2 ), new Array( 2,0,3,0,0,0,0,2 ), new Array( 2,0,3,2,1,1,1,2 ), new Array( 2,4,3,2,0,0,0,4 ), new Array( 1,1,1,2,1,0,1,1 ), new Array( 4,0,0,2,0,0,4,0 ) );
Zeichnen des Spielfelds
Nun muss ledigleich eine Funktion erstellt werden, die diese Teilchen gemäß der Leveldefinition aneinander reiht. das ist relativ einfach:
function drawPlayfield( level ) { for( y = 0; y < 8; y++ ) { for( x = 0; x < 8; x++ ) { context.putImageData( tiles[level[y][x]], x * 30, y * 30 ); } } }
Mit einer verschachtelten Schleife werden alle einzelnen Felder durchlaufen, die Information aus der Levelbeschreibung gelesen und das entsprechende Tile an der richtigen Position angezeigt.
Beachtenswert ist dieser Ausdruck:
tiles[level[y][x]]
- tiles[] verweist auf das Array mit den 5 Teilchen, die für die Darstellung verwendet werden. Der Index muss also ein Wert zwischen 0 und 4 sein.
- level[y] liefert die Zeile zurück, die wiederum ein Array darstellt und deshalb mit einem weiteren Index-Operator versehen wird:
- level[y][x] liefert also aus der Zeile y das Element x zurück. Da wir in der Tabelle nichts anderes eingegeben haben, können nur
Werte zwischen 0 und 4 zurückgeliefert werden. Ein anderer Wert kleiner 0 oder größer 4 würde also Probleme und Fehlermeldungen verursachen. Wenn die Daten aus anderen Quellen kommen, wäre hier eine Sicherheitsüberprüfung angebracht. Damit kann sichergestellt werden, dass keine ungültigen Werte eingeschleust werden können.
function drawPlayfield( level ) { for( y = 0; y < 8; y++ ) { for( x = 0; x < 8; x++ ) { var tile = tiles[level[y][x]]; if( tile >= 0 && tile <= 4 ) { context.putImageData( tile, x * 30, y * 30 ); } } } }
Das Ergebnis sollte genau so aussehen: