Ein Frosch soll fröhlich durch das Spiel springen und sich vom Boden abstoßen,
wenn immer er die Chance dazu hat.
Dieser Frosch soll durch das Spiel springen
In der Scene FroggyJump kann der Spieler ein
Objekt der Klasse Frog steuern. Zusätzlich geben Objekte der Klasse Platform
halt.
Damit ergibt sich das Codegerüst für das Spiel:
Der Frosch kann sich bewegen, knallt aber unangenehmerweise noch gegen die Decke
Ein paar Erklärungen zum Codegerüst für FroggyJump:
Physikalische Eigenschaften
Wie im Physics-Tutorial beschrieben, werden die physikalischen Eigenschaften der
Spielobjekte und ihrer Umgebung bestimmt:
Platformen sind statische Objekte: Sie ignorieren Schwerkraft und können
nicht durch andere Objekte verschoben werden (egal mit wie viel Kraft der
Frosch auf sie fällt).
Der Frosch ist ein dynamisches Objekt: Er lässt sich von der Schwerkraft
beeinflussen und wird von den statischen Platformen aufgehalten.
In der Scene FroggyJump existiert eine Schwerkraft von 10 m/s^2. Sie wird
mit setGravity(Vector) gesetzt.
Bewegung des Frosches
Die Bewegung des Frosches wird in jedem Frame kontrolliert. Wie im Game Loop
Tutorial beschrieben, wird hierzu das Interface FrameUpdateListener genutzt.
In jedem Frame wird die Bewegung des Frosches in dreierlei hinsicht kontrolliert:
Teil A: Blickrichtung des Frosches: Das Bild des Frosches wird gespiegelt,
falls er sich nach links bewegt.
Teil B: Horizontale Bewegung des Frosches: Jeden Frame, in dem der Spieler den
Frosch (per Tastendruck) nach links oder rechts steuern möchte, wird eine
Bewegungskraft auf den Frosch angewendet. Wird der Frosch in die Gegenrichtung
seiner aktuellen Bewegung gesteuert, wird seine horizontale Geschwindigkeit
zuvor auf 0 gesetzt, um ein langsames Abbremsen zu verhindern. Das ermöglicht
schnelle Reaktion auf Nutzereingabe und ein besseres Spielgefühl. Zusätzlich
wird seine Geschwindigkeit auf die Konstante MAX_SPEED begrenzt.
Teil C: Springe, wenn möglich: Mit der Funktion isGrounded() bietet die
Engine einen einfachen Test, um sicherzustellen, dass der Frosch Boden unter
den Füßen hat. Wenn dies gegeben ist, wird ein Sprungimpuls auf den Frosch
angewandt. Zuvor wird die vertikale Komponente seiner Geschwindigkeit auf 0
festgesetzt - das garantiert, dass der Frosch jedes mal die selbe Sprunghöhe
erreicht.
Die Kamera folgt dem Frosch
Der Frosch soll stets sichtbar bleiben. Hierzu werden zwei Funktionen der
Engine-Kamera genutzt:
Der Frosch wird mit Camera.setFocus(Actor) in den Mittelpunkt der Kamera
gesetzt. Sie folgt dem Frosch.
Gleichzeitig soll der Frosch nicht exakt im Mittelpunkt des Bildschirms sein:
Weil das Spielziel ist, sich nach oben zu bewegen, braucht der Spieler mehr
Blick nach oben als nach unten. Mit Camera.setOffset(Vector) wird die
Kamera nach oben verschoben.
Durch Platformen Springen: Kollisionen kontrollieren
Das Interface CollisionListener wurde bereits in
seiner grundlegenden Form im Nutzereingabe-Tutorial benutzt.
CollisionListener kann mehr als nur melden, wenn zwei
Actor-Objekte sich überschneiden. Um das FroggyJump-Spiel zu implementieren,
nutzen wir weitere Features.
Unser Frosch soll fähig sein, von unten „durch die Platform hindurch“ zu
springen. Von oben fallend soll er natürlich auf der Platform stehen bleiben.
Um diesen Effekt zu erzeugen, müssen Kollisionen zwischen Frosch und Platform
unterschiedlich behandelt werden:
Kollidiert der Frosch von unten, so soll die Kollision ignoriert werden.
Er prallt so nicht von der Decke ab und kann weiter nach oben Springen.
Kollidiert der Frosch von oben, so soll die Kollision normal aufgelöst werden,
sodass er nicht durch den Boden fällt.
Hierzu stellt das CollisionEvent-Objekt in der onCollision-Methode Funktionen bereit.
importpi.Camera;importpi.Controller;importpi.Random;importpi.Scene;importpi.graphics.geom.Vector;publicclassFroggyJumpextendsScene{privateFrogfrog;privatefinaldoublePLATFORM_HEIGHT=0.5;publicFroggyJump(){info().title("Spiel „Froggy Jump“").help("Tastenkürzel: a bewegt den Frosch nach links, d bewegt den Frosch nach rechts.");frog=newFrog();add(frog);gravity(Vector.DOWN.multiply(10));Cameracamera=camera();camera.focus(frog);camera.offset(newVector(0,4));makeLevel(40);makePlatforms(10);}privatevoidmakePlatforms(intheightLevel){for(inti=0;i<heightLevel;i++){Platformplatform=newPlatform(5,PLATFORM_HEIGHT);platform.anchor(0,i*4);add(platform);}}privatevoidmakeLevel(intheightLevel){for(inti=0;i<heightLevel;i++){intnumPlatforms=Random.range(2)+1;for(intj=0;j<numPlatforms;j++){Platformplatform=newPlatform(6/numPlatforms,PLATFORM_HEIGHT);platform.anchor(numPlatforms*(j+1)*i*Random.range(),i*4);add(platform);}if(i>3){for(intj=0;j<Random.range(3);j++){SpikeBall.setupSpikeBall(Random.range()*(4+j)*i,Random.range()*4+0.5+5*i,layer());}}}}publicstaticvoidmain(String[]args){Controller.instantMode(false);Controller.start(newFroggyJump(),400,600);}}
importjava.awt.event.KeyEvent;importpi.Controller;importpi.Scene;importpi.Text;importpi.event.KeyStrokeListener;classDeathScreenextendsSceneimplementsKeyStrokeListener{publicDeathScreen(){Textmessage=newText("You Died. Press any button to try again");message.height(.6);message.center(camera().focus());add(message);}@OverridepublicvoidonKeyDown(KeyEvente){Controller.transitionToScene(newFroggyJump());}}
importjava.awt.event.KeyEvent;importpi.Controller;importpi.Image;importpi.event.FrameUpdateListener;importpi.graphics.geom.Vector;classFrogextendsImageimplementsFrameUpdateListener{privatebooleancanJump=true;privatestaticdoubleMAX_SPEED=4;publicFrog(){super("froggy/Frog.png");pixelPerMeter(25);makeDynamic();rotationLocked(true);}publicvoidjumpEnabled(booleanjumpEnabled){canJump=jumpEnabled;}publicvoidkill(){Controller.transitionToScene(newDeathScreen());}@OverridepublicvoidonFrameUpdate(doublepastTime){Vectorvelocity=this.velocity();// A: Die Blickrichtung des Frosches steuernif(velocity.x()<0){flippedHorizontally(true);}else{flippedHorizontally(false);}// B: Horizontale Bewegung steuernif(Controller.isKeyPressed(KeyEvent.VK_A)){if(velocity.x()>0){velocity(newVector(0,velocity.y()));}applyForce(Vector.LEFT.multiply(600));}elseif(Controller.isKeyPressed(KeyEvent.VK_D)){if(velocity.x()<0){velocity(newVector(0,velocity.y()));}applyForce(Vector.RIGHT.multiply(600));}if(Math.abs(velocity.x())>MAX_SPEED){velocity(newVector(MAX_SPEED*Math.signum(velocity.x()),velocity.y()));}// C: Wenn möglich den Frosch springen lassenif(isGrounded()&&velocity.y()<=0&&canJump){velocity(newVector(velocity.x(),0));applyImpulse(Vector.UP.multiply(180));}}}