Spielprogrammierung mit Java
HomeAufgabenDruckenJava-Online

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: Fisch frisst Algen

Zu Beginn werden 10 Algen der Klasse Alga mit der Methode getRandomEmptyLocation() an zufällig gewählte freie Positionen im Gitter gesetzt. Der Fisch schwimmt durch das Gitter und frisst die Algen. Mit der Methode getOneActorAt(getLocation(), Alga.class) kann überprüft werden, ob sich an der aktuellen Position eine Alge Alga 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üclgeholt werden.


 

 
// JGameEx12.java

import ch.aplu.jgamegrid.*;
import java.awt.Color;

public class JGameEx12 extends GameGrid
{
  public JGameEx12()
  {
    super(10, 10, 60, Color.red, "sprites/reef.gif");
    addActor(new EatingFish(), new Location(0, 0));
    for (int = 0; i < 10; i++)
      addActor(new Alga(), getRandomEmptyLocation());
    show();
  }
  
  public static void main(String[] args)
  {
    new JGameEx12();
  }
}

// --------------------- class EatingFish ---------------------
class EatingFish extends Actor
{
  public EatingFish()
  {
    super("sprites/fish.gif"2);
  }

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

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

// --------------------- class Alga ---------------------------
class Alga extends Actor
{

  public Alga()
  {
    super("sprites/alga.gif");
  }
}

Erklärungen zum Programmcode:
tryToEat() Testet, ob sich an der aktuellen Position eine Alge befindet und eliminiert sie. Dabei wird der Fish mit offenem Mund dargestellt
getOneActorAt(getLocation(), Alga.class) Gibt eine Algen-Referenz oder null zurück
if (actor != null) Diese Bedingung trifft zu, wenn die Zelle mit einer Alge 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.

Programmcode für lokale Bearbeitung Downloaden: JGameEx12.zip

 

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).

 

 

// JGameEx14.java

import ch.aplu.jgamegrid.*;
import java.awt.Color;

public class JGameEx14 extends GameGrid
{
  public JGameEx14()
  {
    super(10, 10, 60, Color.red, "sprites/reef.gif");
    addActor(new Fish(), new Location(1, 4));
    addActor(new Crab(), new Location(5, 7));
    show();
  }

  public static void main(String[] args)
  {
    new JGameEx14();
  }
}

// ----------------------- class Fish ---------------------------------------

class Fish extends Actor
{
  public Fish()
  {
    super("sprites/sNemo.gif");
  }

  public void act()
  {

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

  public void reset()
  {
    setHorzMirror(false);
  }
}

// ---------------------- class Crab ------------------------------------------

class Crab extends Actor
{
  public Crab()
  {
    super("sprites/crab.gif");
  }

  public void act()
  {
    if (getY() == && getNbCycles() % != 0)
       return;
    move();
    if (getY() == 2)
      turn(180);
    if (getY() == 7)
    {
      turn(180);
      setX((int)(5 * Math.random()) + 3);
    }
  }

  public void reset()
  {
    setDirection(Location.NORTH);
  }
}

Erklärungen zum Programmcode:
Actor actor = 
getOneActorAt(nextMoveLocation, Crab.class)
Wenn sich an der nächsten Position ein Objekt der Klasse Crab befindet, ist actor nicht null und der Fisch muss umkehren
if (getY() == 4 && getNbCycles() % 5 != 0)
return
Befindet sich der Crab bei y = 4 , so wird zusätzlich geprüft, ob die Anzahl Perioden ein Fünferzahl ist. Wenn nicht wird act() verlassen
setX((int)(5 * Math.random()) + 3) Die x-Koordinate wird zufällig auf eine Zahl zwischen 3 und 7 gesetzt

Programmcode für lokale Bearbeitung Downloaden: JGameEx14.zip