Drucken

Kollisionen im Gitter


Interaktion zwischen den Spielfiguren spielt bei der Game-Programmierung eine wichtige Rolle. In JGameGrid sind Kollisionen auf zwei Arten implementiert:

Das zweite Vorgehen wird im Abschnitt Figuren-Kollisionen erklärt.

Bei den Kollisionen im Gitter gibt die Methode getActorsAt() alle Actors, die sich in einer bestimmten Zelle befinden, in einer ArrayList zurück. Man kann diese Liste für einen bestimmten Actor-Typ einschränken, indem man dessen Klassennamen angibt. Befindet sich in einer Zelle nur ein oder kein Actor, kann man die Methode getOneActorAt() verwenden, welche die Actor-Referenz oder null zurückgibt.

Beispiel 1: Actors eliminieren: Pacman isst Pillen

Zu Beginn werden 10 Objekte der Klasse Pill mit der Methode getRandomEmptyLocation() an zufällig gewählte freie Positionen im Gitter gesetzt. Der Pacman bewegt sich durch das Gitter und isst die Algen. Mit der Methode getOneActorAt(getLocation(), Pill.class) kann überprüft werden, ob sich an der aktuellen Position eine Pille befindet. Wenn ja, lässt man ihn mit actor.hide() verschwinden.

Anstelle der Methode hide() kann auch actor.removeSelf() verwendet werden. Dabei wird der Actor endgültig vernichtet und kann mit reset() nicht mehr zurückgeholt werden.

 

Beispiel im Online-Editor bearbeiten

App installieren auf Smartphone oder Tablet

QR-Code

Sources downloaden (AndroidEx10.zip). Auf Tablet mit Longpress.

 

// AndroidEx10.java

package app.ex10;

import ch.aplu.android.*;

public class AndroidEx10 extends GameGrid 
{
  public AndroidEx10()
  {
    super(8, 8, 0, RED);
  }

  public void main()
  {
    addActor(new Pacman(), new Location(0, 0));
    for (int = 0; i < 10; i++)
      addActor(new Pill(), getRandomEmptyLocation());
    doRun();
  }
}

class Pacman extends Actor
{
  public Pacman()
  {
    super("pacman"2);
  }

  public void act()
  {
    show(0);
    if (isMoveValid())
       move();
    if (getX() == 7)
    {
      turn(90);
      setHorzMirror(true);
    }
    if (getX() == 0)
    {
      turn(270);
      setHorzMirror(false);
    }
    tryToEat();
  }

  private void tryToEat()
  {
    Actor actor = gameGrid.getOneActorAt(getLocation(), Pill.class);
    if (actor != null)
    {
      show(1);
      actor.hide();
    }
  }
}

class Pill extends Actor
{

  public Pill()
  {
    super("pill");
  }
}

Erklärungen zum Programmcode:
tryToEat() Testet, ob sich an der aktuellen Position eine Pille befindet und eliminiert sie. Dabei wird der Pacman mit offenem Mund dargestellt
getOneActorAt(getLocation(), Pillclass) Gibt einen Actor oder null zurück
if (actor != null) Diese Bedingung trifft zu, wenn die Zelle mit einer Pille belegt ist
actor.hide() actor wird unsichtbar, bleibt aber im Gitter und kann mit reset() wieder aktiviert werden
actor.removeSelf() Kann anstelle hide() verwendet werden. Der Actor wird aus dem Gitter eliminiert.

 

 

Beispiel 2: Ausweichen. Nemo muss dem bewegten Crab ausweichen.

Nemo schwimmt horizontal hin und her, der Crab taucht an zufälligen x-Koordinaten auf und bewegt sich vertikal hin und her. Damit mehrere Kollisionen zu beobachten sind, bleibt der Crab jeweils während 5 Simulationsperioden auf der y-Koordinate von Nemo stehen. Bei einer Kollision dreht der Fisch um und schwimmt in die entgegengesetzte Richtung.

Es wird mit
getOneActorAt(getNextMoveLocation(), Crab.class)
überprüft, ob sich an der nächsten Position, an die sich der Fisch bewegen will, ein Crab befindet. Es ist wichtig, dass sich zuerst der Crab bewegt und erst nachher der Fisch testet, ob er sich bewegen darf. Daher muss das act() des Crabs vor dem act() des Fisches ausgeführt werden. Die Reihenfolge des Aufrufs der act-Methoden ist standardmässig so eingestellt, dass später hinzugefügte Actors ihr act() vor den anderen ausführen. Daher muss addActor() mit dem Crab nachher aufgerufen werden (die act-Reihenfolge kann mit setActOrder() umgestellt werden).

 

Beispiel im Online-Editor bearbeiten

App installieren auf Smartphone oder Tablet

QR-Code

Sources downloaden (AndroidEx11.zip)

 

// AndroidEx11.java

package app.ex11;

import ch.aplu.android.*;

public class AndroidEx11 extends GameGrid
{
  public AndroidEx11()
  {
    super(8, 8, 40, RED, "reef"false);
  }

  public void main()
  {
    Crab crab = new Crab();
    addActor(crab, new Location(4, 6));
    addActor(new Fish(), new Location(0, 3));
    crab.setDirection(Location.NORTH);
    doRun();
  }
}

class Fish extends Actor
{
  public Fish()
  {
    super("nemo");
  }

  public void act()
  {
    Actor actor = gameGrid.getOneActorAt(getNextMoveLocation(), Crab.class);
    if (actor != null)
    {
      turn(180);
      setHorzMirror(!isHorzMirror());
    }
    move();
    if (isNearBorder())
    {
      turn(180);
      setHorzMirror(!isHorzMirror());
    }
  }
}

class Crab extends Actor
{
  public Crab()
  {
    super("crab");
  }

  public void act()
  {
    if (getY() == || getY() == 7)
      turn(180);
    move();
  }
}

Erklärungen zum Programmcode:
getOneActorAt(nextMoveLocation, Crab.class) Wenn sich an der nächsten Position ein Objekt der Klasse Crab befindet, gibt diese Methode einen Actor zurück, sonst null