📄 daserstespieldeu.html
字号:
Also, zweite Idee: Man akzeptiert alle Koordinaten als Treffer, die um einen gewissen Betrag kleiner bzw. größer sind als die Koordinaten des Balles. Dies muss natürlich für die x und die y - Koordinate gleichermaßen zutreffen (&& - Abfrage). Auf diese Weise testet man, ob der Klick des Spielers in einem Quadrat um den Ball (bei Radius 10 z. B. mit Kantenlänge 20) erfolgt ist. Diese Idee hatte ich bei meinem ersten Versuch dieses Spiel umzusetzen implementiert, mit leider nur mäßigem Erfolg. Das Ganze hat mal funktioniert, mal wieder nicht, obwohl der Ball richtig getroffen wurde. Der Grund dafür ist mir immernoch schleierhaft. <br> <br>
Nun denn, die dritte Idee: Aus der Schule dürfte den meisten noch der Begriff eines Vektors geläufig sein. Wir haben es hier nun zwei Vektoren zu tun, die bei einem Schuss entstehen: Einem Schussvektor (x_maus, y_maus) des Mausklicks und einem Positionsvektor des Balles (x_ball, y_ball). Wenn wir nun die Länge des Verbindungsvektors dieser beiden Vektoren bestimmen und dieser kleiner als der Radius des Balles ist, so haben wir den Ball getroffen. <br>
Zunächst berechnen wir also den Verbindungsvektor indem wir die Koordinaten des einen Vektors von denen des Anderen abziehen:</p>
<ul><i>
// Bestimmen des Verbindungsvektors<br>
double x = maus_x - pos_x;<br>
double y = maus_y - pos_y;<br>
</i></ul>
<p align="justify">Nun können wir mit Hilfe des Skalarproduktes bzw. Pythagoras (c = Wurzel aus a² + b²) die Länge dieses Verbindungsvektors bestimmen:</p>
<ul><i>
// Berechnen der Distanz<br>
double distance = Math.sqrt ((x*x) + (y*y));<br>
</i></ul>
<p align="justify">Als letzten Schritt testen wir, ob die Länge dieses Vektors kleiner ist als ein gewisser Betrag, bis zu dem wir den Ball noch als getroffen ansehen. Ich habe für diese Zahl 15 gewählt obwohl der Ball nur einen Radius von 10 hat. Aber nachdem ich einige Werte getestet habe, erschien mir dieser Wert als der am besten taugliche.</p>
<ul><i>
// Wenn Distanz kleiner als 15 gilt Ball als getroffen<br>
if (distance < 15)<br>
{<ul>
player.addScore (20);<br>
return true;<br>
</ul>
}<br>
else return false;<br>
</i></ul>
<p align="justify">Damit können wir den Ball abschießen, wenn wir auf bzw. kurz daneben schießen. Die Rückgabewerte ergeben sich aus der oben beschriebenen Struktur und Zusammenarbeit der Methoden.</p>
<h3>Das Spielerobjekt: Punkte zählen und Leben verlieren</h3>
<p align="justify">Um dies zu verwirklichen haben wir die Player - Klasse mit den Methoden looseLife() und addScore (int plus) ausgestattet. Immer wenn ein Ball das Spielfeld verlässt, ruft er player.looseLife() in der Methode isOut() auf. Dadurch verliert der Spieler ein Leben. Trifft der Spieler den Ball (ober beschrieben), so ruft die Methode userHit() player.addScore (10* Math.abs(x_speed) + 10) auf und zählt somit je nach Geschwindikeit des Balles Punkte zu denen des Spielers hinzu. Umso schneller ein Ball fliegt, umso mehr Punkte kann man durch einen Abschuss somit erreichen. Die Methoden addScore und looseLife sind dabei wirklich denkbar einfach. <br>
Einziger Knackpunkt: Man muss sehen, dass das Player - Objekt in der Klasse Main geschaffen wird. Die Refferenz auf das Spieler - Objekt muss also im Konstruktor oder in der Methode (userHit() bzw. isOut()) die Methoden des Objektes verwendet, an die Klasse Ball übergeben worden sein! <br>
Dies ist eine wichtige Technik, denn es kommt häufig vor, dass mehrere Klassen Zugriff auf ein und das selbe Objekt benötigen. Man initialisiert das Objekt dann einfach z. B. in der Klasse Main (die ich gerne verwende um alle Objekte des Spiels zu verwalten) und übergibt die Refferenz von dort aus an alle anderen Objekte, die die Refferenz benötigen.</p>
<h3>Mauszeiger verändern: Das Fadenkreuz</h3>
<p align="justify">Natürlich passt zu unserem Spiel ein Fadenkreuz als Mauszeiger viel besser, als ein normaler Zeiger. Um uns einen Fadenkreuzmauszeiger zu beschaffen, müssen wir unserer Main - Klasse lediglich drei Codezeilen hinzufügen: Zunächst eine Instanzvariable der Klasse Cursor:</p>
<ul><i>
// Fadenkreuzmauszeiger<br>
Cursor c; // Variable für Cursor<br>
</i></ul>
<p align="justify">In die Init - Methode fügen wir dann folgende Zeilen ein:</p>
<ul><i>
// Mauszeiger wird zu Fadenkreuz<br>
c = new Cursor (Cursor.CROSSHAIR_CURSOR);<br>
this.setCursor (c);<br>
</i></ul>
<p align="justify">Weitere Klassenvariablen der Klasse Cursor und somit weitere Mauscursor, können in der API nachgelesen werden.</p>
<h3>Spielzustände: Das Spiel erst nach einem Doppelklick starten und beenden, wenn der Spieler seine Leben verbraucht hat</h3>
<p align="justify">Bis auf eine kleine Kleinigkeit ist unser Spiel nun fertig: Es ist für den Spieler sehr unangenehm, wenn das Spiel schon losgeht, bevor er sich überhaupt die Anleitung durchgelesen hat. Wir wollen das Spiel daher erst dann starten, wenn er einen Doppelklick in das Appletfenster ausgeführt hat. Das hat nicht nur den Vorteil, dass der Spieler den Startpunkt des Spieles selbst bestimmen kann, sondern wenn man in seinem Spiel Tastaturereignisse verwendet, dann kann man den Tastaturfocus für das Applet (wird durch Klick auf das Applet erreicht) auf diese Weise sicherstellen. Des weiteren soll das Spiel natürlich dann beendet sein, wenn der Spieler alle seine Leben verspielt hat.</p>
<p align="justify">Zunächst fügen wir also in die Klasse Main eine boolsche Instanzvariable mit Namen isStoped ein. Ist sie true, so ist das Spiel gestoppt, ist sie false, so läuft das Spiel.
Nun fügen wir in unseren Thread (run - Methode) eine Abfrage ein, die die Methoden zur Bewegung des Balles nur dann aufruft, wenn der Spieler mehr als 0 Leben hat und gleichzeitig isStoped false ist. repaint() wird weiterhin immer nach dem Starten des Threads aufgerufen. </p>
<i><ul>
// Endlosschleife der run - Methode<br>
while (true)<br>
{<ul>
if (player.getLives() >= 0 && !isStoped)<br>
{<ul>
redball.move();<br>
blueball.move();<br>
</ul>
}<br><br>
...<br>
</ul>}
</ul></i>
<p align="justify">Im nächsten Schritt wollen wir in der paint() - Methode eine weitere Abfrage einfügen. Sie soll, solange der Spieler noch Leben hat, die Bälle sowie die Angabe über Leben und Punkte zeichen. Ist das Spiel gestoppt, so zeichnet sie zudem die Information, dass das Spiel mit einem Doppelklick gestartet werden kann, auf den Bildschirm. Hat der Spieler keine Leben mehr, so wertet die paint() - Methode seine Punktezahl aus, schreibt eine Bewertung der Ergebnisse auf den Bildschirm, sowie weitere Informationen auf den Bildschirm und gewährleistet, dass das Spiel nach
einem weiteren Doppelklick des Spielers wieder gestartet wird. Die paint() - Methode gestalltet sich also folgendermaßen: </p>
<ul><i>
// paint() - Methode<br>
public void paint (Graphics g)<br>
{<ul>
// Spieler hat noch Leben<br>
if (player.getLives() >= 0)<br>
{<ul>
// Alle nötigen Anweisungen zum Zeichnen von Ball, Punktestand...<br><br>
...<br><br>
// Wenn das Spiel zusätzlich noch gestoppt ist<br>
if (isStoped)<br>
{<ul>
// Information: "Spiel startet auf Doppelklick" zeichen<br>
</ul>}
</ul>}<br>
// Spieler hat keine Leben mehr<br>
else if (player.getLiver() < 0)<br>
{<ul>
// Bewertung der Punkte, Game over zeichnen, isStoped true setzen<br>
// Details bitte im SourceCode nachlesen
</ul>}
</ul>}
</i></ul>
<p align="justify">Nun ist es fast geschafft! Im Moment haben wir aber noch keine Kontrolle darüber, wann wir das Spiel starten, da wir in die MouseDown - Methode noch keine Befehle eingefügt haben, die das Umschalten von dem gestoppten Spielzustand in das laufende Spiel erlauben. Um dies zu erreichen müssen wir die mouseDown() - Methode folgendermaßen verändern:</p>
<ul><i>
// Auffangen der Mausereignisse<br>
public void mouseDown (Event e, int x, int y)<br>
{<ul>
// Behandlung von Mausereignissen, während das Spiel läuft<br>
if (!isStoped)<br>
{<ul>
// Test ob roter Ball getroffen wurde<br>
if (redball.userHit (x, y))<br>
{<ul>
// Abspielen der Audiodatei<br>
hitnoise.play();<br><br>
// Ball zu Startwert zurücksetzten<br>
redball.ballWasHit ();<br>
</ul>}<br>
// Test ob blauer Ball getroffen wurde<br>
if (blueball.userHit (x, y))<br>
{<ul>
// Abspielen der Audiodatei<br>
hitnoise.play();<br><br>
// Ball zu Startwert zurücksetzten<br>
blueball.ballWasHit ();<br>
</ul>}<br>
else<br>
{<ul>
// Abspielen des normalen Schussgeräusches<br>
shotnoise.play();<br>
</ul>}
</ul>}<br>
// Gestopptes Spiel bei Doppelklick starten<br>
else if (isStoped && e.clickCount == 2)<br>
{<ul>
// Alle wichtigen Werte zurücksetzen<br>
isStoped = false;<br>
init ();<br>
</ul>}<br><br>
return true;<br>
</ul>}
</i></ul>
<h3>Geschafft!!</h3>
<p align="justify">So, nun habt ihr es hinter euch und wenn ihr auch die Teile, die ich nicht so ausführlich besprochen habe, verstanden habt, dann steht eurem ersten Spiel ja nichts mehr im Wege.
Die nächsten Kapitel werden sich noch mit einigen weiterführenden Problemen und Lösungen befassen, die ich in meinen bisher programmierten Spielen verwendet bzw. irgendwo mal gesehen habe. <br> Ansonsten entlasse ich euch hiermit "in die Freiheit", in der Dank der Mächtigkeit und Flexibilität von Java beinahe alles möglich ist, wünsche euch viel Spaß und Erfolg bei der Entwicklung eurer eigenen Spiele, hoffe, dass ich euch in diesem Tutorial ein wenig weiterhelfen konnte und wenn ihr eure ersten Spiele geschrieben, Wünsche, Anregungen, Beschwerden, eigene Tutorials zu bestimmten Themen... oder ein Problem habt, dann schreibt bzw. schickt mir doch einfach eine Mail bzw. euer Spiel...! <br>
Zuguterletzt könnt ihr euch, wie immer den SourceCode runterladen und das Spiel ausprobieren.</p>
<p><a href="SourceCodes/ErstesSpiel/DasersteSpiel.zip">SourceCode download (*.zip - Datei)</a><br>
<a href="Applets/ErstesSpiel/ErstesSpiel.html">Applet ansehen</a>
<h4>Nächstes Kapitel</h4>
<a href="PongKIDeu.html">Künstliche Intelligenz für einen Pong Klon</a>
<!-- InstanceEndEditable -->
</div>
</td>
</tr>
<tr>
<td colspan="11" style="background-color:#990000" align="center">
<table width="100%" style="padding:0"><tr>
<td width="88" bgcolor="#993300"><div align="center" style="font-size:10px; color: #FFFFFF;"> <a href="#top"> to top </a></div></td>
<td><div align="center" style="font-size:10px; color: #FFFFFF;">
<a href="mailto:javacooperation@gmx.de">Fabian Birzele</a>, 2001-2004.<br>
web-design: <a href="http://www.freehand.str.ru/">Vadim Murzagalin</a>, 2004.
</div></td>
<td width="88">
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</body>
<!-- InstanceEnd --></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -