📄 platformgamebasicsdeu.html
字号:
</ul>
}<br>
</ul></i>
<p align="justify">Der letzte der vier Zustände ist der Zustand <b>falling</b>. Hier ist hauptsächlich zu beachten, dass wenn der Spieler auf einer neuen Platform landet, falling also auf false gesetzt wird, dass in diesem Fall ein Sprung beendet ist (jump_lock und jumping also auf false gesetzt werden müssen). Eine weitere Sache ist, dass es vorkommen kann, dass der Spieler nicht direkt auf der Oberfläche der Platform zum stehen kommt, sondern gewissermaßen in ihr. Daher muss man nach Stoppen eines Falls die Spielerfigur auf die Oberfläche des Levelelementes bewegen. Ansonsten ist noch zu beachten, dass der Spieler nicht gleichzeitig fallen und springen kann, dies wird aber an anderer Stelle (in der playerMove() - Methode) nochmals sicher gestellt.</p>
<i><ul>
// Methode um den Wert von falling zu setzen<br>
public void playerFall(boolean value)<br>
{<br>
<ul>
// Die Fallbewegung soll gestoppt werden<br>
if(!value)<br>
{<br>
<ul>
// ist der Spieler gesprungen und landet auf einer Platform<br>
// müssen die Werte von jumping und jump_lock zurückgesetzt werden<br>
if(jump_lock)<br>
{<br>
<ul>jump_lock = false;<br>
jumping = false;</ul>
}<br><br>
// die Position des Spielers muss gegebenenfalls korrigiert werden,<br>
// damit er sich immer genau auf der Oberfläche eines Levelelementes<br> // befindet. Ist dies der Fallist die untere Position des Spielers<br>
// ohne Rest durch die Höhe einesLevelelementes teilbar, die y -<br>
// Positionen des Spielers werden also verändert<br>
while(y_pos_down%C_Jump.level_element_height != 0)<br>
{<br>
<ul>y_pos_down --;<br>
y_pos_up--;</ul>
}<br>
</ul>
}<br><br>
// Wert für falling setzten<br>
falling = value;<br>
</ul>
}<br>
</ul></i>
<h4>Bewegung und Animation des Spielers</h4>
<p align="justify">Nachdem wir jetzt wissen, wie die einzelnen Bewegungszustände des Spielers manipuliert werden werden wir einen kurzen Blick auf die konkrete Umsetzung der Flag - Werte in Bewegung und Animation werfen. Dies geschieht in der Methode playerMove(), deren Sourcecode ich nun etwas genauer unter die Lupe nehmen werde, zuvor muss ich allerdings noch einige kleine Variablen erklären:</p>
<ul>
<li><p align="justify"><b>step_counter</b> und <b>picture_counter</b>: Diese Variablen sind ausschließlich zur Animiation des Player - Objektes nötig. Immer nach 15 "Schritten" soll sich das Bild, das an Stelle des Spielers angezeigt wird ändern, d.h. der picture_counter, der angibt, welches Bild des Spieler in der paint - Methode gezeichnet werden soll, wird geändert.</p></li>
<li><p align="justify"><b>jump_counter</b>: Dieser Counter bestimmt, wie weit der Spieler springen kann. Hat dieser Counter einen Maximalwert erreicht, wird der Wert der Variablen jumping auf false gesetzt. Weitere Erläuterungen finden sich im Code</p></li>
</ul>
<i><ul>
// Diese Methode bewegt den Spieler bezüglich der gesetzten Werte der Bewegungs - Flags<br>
public void playerMove()<br>
{<br>
<ul>
// Der Spieler soll nach links laufen<br>
if(walking_left)<br>
{<br>
<ul>
// Verändern der x - Positionen des Spielers<br>
x_pos_left -= walk_x_speed;<br>
x_pos_right -= walk_x_speed;<br><br>
// ändern der Gameposition (wichtig für Scrolling)<br>
game_x_position -= walk_x_speed;<br><br>
// nach jeweils 15 "Schritten" das Bild ändern<br>
if (step_counter%15 == 0)<br>
{<br>
<ul>
// Wert des Picture Counters ändern<br>
picture_counter ++;<br><br>
// wenn der Counter den Wert zwei hat, auf 0 zurücksetzen<br>
if(picture_counter == 2)<br>
{<br>
<ul>picture_counter = 0;</ul>
}<br><br>
// step_counter zurücksetzen<br>
step_counter = 1;<br>
</ul>
}<br>
// ansonsten den step_counter erhöhen und das aktuelle Bild beibehalten<br>
else<br>
{<br>
<ul>step_counter ++;</ul>
}<br><br>
// Spieler blickt nach links (nur wichtig für die Animation)<br>
look_left = true;<br>
</ul>
}<br>
// Spieler soll nach rechts laufen<br>
else if(walking_right)<br>
{<br>
<ul>... Äquivalente Anweisungen wie bei walking_left, nur eben nach rechts...</ul>
}<br><br>
// Spieler soll springen<br>
if(jumping)<br>
{<br>
<ul>
// Diese Variable dient dazu, zu verhindern, dass der Spieler springen<br>
// kann, wenn er schon springt<br>
jump_lock = true;<br><br>
// Stelle sicher, dass der Wert von falling false ist. Denn von der<br>
// Kollisionskontrolle wird dieser Wert auch bei einem Sprung auf<br>
// true gesetzt<br>
falling = false;<br><br>
// Hat der Sprungcounter noch nicht den Maximalwert von 30 erreicht<br>
if(jump_counter < 30)<br>
{<br>
<ul>
// in diesem Fall springt der Spieler mit einer Geschwindigkeit von // 2 nach oben. <br>
y_pos_up -= jump_y_speed;<br>
y_pos_down -= jump_y_speed;<br>
jump_counter ++;
</ul>
}<br>
// Ist der Sprungcounter größer als 30 aber kleiner als 40, springe mit<br>
// kleinerer Geschwindigkeit<br>
else if (jump_counter < 40)<br>
{<br>
<ul>
y_pos_up -= jump_y_speed2;<br>
y_pos_down -= jump_y_speed2;<br>
jump_counter++;
</ul>
}<br>
// ist der Sprungcounter größer als 40, kann der Spieler nicht mehr<br>
// springen, er wird also nicht weiter nach oben bewegt, jumping ist<br> // false<br>
else<br>
{<br>
<ul>jumping = false;</ul>
}<br>
</ul>
}<br><br>
// Fällt der Spieler wird er nach unten bewegt<br>
if(falling)<br>
{<br>
<ul>
y_pos_up += fall_y_speed;<br>
y_pos_down += fall_y_speed;
</ul>
}<br>
</ul>
}<br>
</ul></i>
<p align="justify">Ich hoffe, dass ich euch nun die wichtigsten Eigenschaften und Methoden der Klasse Player näher bringen konnte, Scrollen und Zeichnen des Spielers sollte inzwischen kein Problem mehr darstellen. Allerdings müsst ihr euch, denke ich, trotzdem nochmal den Sourcecode genauer ansehen, da es sich doch um eine etwas komplexere Klasse handelt. Also auf zu einer noch komplexeren Klasse, der Klasse <b>Level</b></p>
<h3><a name="PlatformGameLevelObjekt">Struktur und Funktionen der Klasse <i>Level</i></a></h3>
<p align="justify">In dem folgenden Abschnitt wollen wir uns detailierter mit der Klasse <b>Level</b> und den dazugehörigen Klassen <b>LevelOne</b> und <b>LevelElement</b> beschäftigen. Zunächst werden wir uns mit der "Designsprache" eines Levels in unserem Spiel und der Übersetzung dieser Definition in die interne Datenstruktur des Levels beschäfitigen. Im wesentlichen handelt es sich hier um Ideen, die ich schon im Kapitel über den Leveleditor vorgestellt habe. Anschließend wollen wir uns die Kollisionskontrolle zwischen Spieler und Levelelementen ansehen. Auf die Methoden zum Scrolling und Zeichnen des Levels werde ich nicht eingehen.</p>
<h4>Designsprache und interne Datenrepräsentation eines Levels</h4>
<p align="justify">Ein wichtiges Ziel des Klassendesigns war es, das Design von neuen Leveln möglichst einfach zu gestallten. Aus diesem Grund werden neue Level zunächst in einer eigenen kleinen "Designsprache" geschrieben und anschließend mittels eines Parsers in die eigentliche interne Datenstruktur des Levels übersetzt. Ein Level besteht in der "Designsprache" dabei aus 25 Strings und damit 25 untereinanderliegender Zeilen. Diese Strings können eine beliebige Länge haben, müssen jedoch gleich lang sein. Die verschiedenen Levelelemente werden in diesen Strings durch festgelegte Buchstaben beschrieben. Der Parser in der Klasse Level (Methode initializeLevel()) muss nun in der Lage sein diese Stringrepräsentation in eine sinnvolle interne Repräsentation zu übersetzen wobei diese interne Repräsentation im Wesentlichen aus einem zweidimensionalen Array besteht, das Instanzen der Klasse LevelElement bzw. ihrer Kinder sowie einen null - Pointer an Stellen, an denen sich kein Levelelement befindet, hält. Wer noch Probleme mit dieser Idee hat, sollte sich jetzt nochmal das Kapitel über den <a href="LeveleditorDeu.html">Leveleditor für arraybasierte Spiele</a> ansehen, da ist das Ganze nochmal genauer erklärt. Wir wollen uns jetzt kurz den Sourcecode ansehen und anschließend noch die Kollisionskontrolle zwischen Player und Levelelementen besprechen.</p>
<p align="justify">Die Definition eines Levels findet sich in der von der Klasse Level abgeleiteten Klasse <b>LevelOne</b>. Diese Klasse LevelOne dient dazu, alle levelspezifischen Dinge zu definieren (Hintergrundfarben, das Level selbst...), während die von der Klasse Level vererbten Methoden und Eigenschaften das Level funktionsfähig machen.
Werfen wir zunächst einen Blick auf die Leveldefinitionssprache: </p>
<code>
/**<br>
Legende:<br>
":": Repräsentiert eine Stelle im Level wo kein Levelelement erzeugt werden soll<br>
"g": Repräsentiert eine Grundelement<br>
*/<br><br>
// Stringdefinitionen des Levels<br>
// Zeilen 1 - 10 fehlen, da sie keine Definitionen enthalten, also nur aus ":" bestehen<br>
public static final String row11 = "::::::::::::::::::::::::::::::::::::::::g::";<br>
public static final String row12 = ":::::::::::::::::::::::::::::::::::::::::::";<br>
public static final String row13 = ":::::::::::::::::::::::::::::::::::::::::::";<br>
public static final String row14 = "::::::::::::::::::::::::::::::::::::g::::::";<br>
public static final String row15 = ":::::::::::::::::::::::::::::::::::::::::::";<br>
public static final String row16 = ":::::::::::::::::::::::::::::::::::::::::::";<br>
public static final String row17 = "::::::::::::gggg::::::::::::::::g::::::::::";<br>
public static final String row18 = ":::::::::::::::::::::::::::::::::::::::::::";<br>
public static final String row19 = ":::::::::::::::::::::::gggg::::::::::::::::";<br>
public static final String row20 = ":::::::::::::::::::::::::::::::::::::::::::";<br>
public static final String row21 = "::::::gggg:::::::::::::::::::::::::::::::::";<br>
public static final String row22 = ":::::::::::::::::::::::::::::::::::::::::::";<br>
public static final String row23 = ":::::::::::::::::::::::::::::::::::::::::::";<br>
public static final String row24 = ":::::::::::::::::::::::::::::::::::::::::::";<br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -