Spielprogrammierung mit Java
HomeAufgabenDruckenJava-Online

 

Figuren verfolgen


Beispiel 1: Ein Hai verfolgt Nemo

Nemo schwimmt horizontal hin und her. Der Hai verfolgt den Nemo. Er bewegt sich von Zelle zur Zelle jeweils in Richtung der aktuellen Position von Nemo. Dabei kann er bei jedem Schritt eine der 8 möglichen benachbarten Zellen wählen. Die für die Verfolgung optimale Richtung wird mit der Methode
getCompassDirectionTo(nemo.getLocation()) bestimmt. Als Parameter erhält diese Methode die Position des verfolgten Objekts. Bereits bei der Erzeugung des Actors shark wird das Verfolgte Objekt als Parameter new Shark(nemo) übergeben.
Damit der Hai den Nemo nicht sofort packt, lassen wir den Hai nur jeden fünften Simulationszyklus bewegen.

 

 

// JGameEx15.java

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

public class JGameEx15 extends GameGrid
{
  public JGameEx15()
  {
    super(10, 10, 60, Color.red, "sprites/reef.gif");
    Fish nemo = new Fish();
    addActor(nemo, new Location(0, 1));
    Shark shark = new Shark(nemo);
    addActor(shark, new Location(7, 9));
    show();
  }

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

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

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

// ---------------------- class Shark ------------------------------------------
class Shark extends Actor
{
  private Fish nemo;

  public Shark(Fish nemo)
  {
    super(true"sprites/shark.gif");
    this.nemo = nemo;
  }

  public void act()
  {
    if (nbCycles % == && !nemo.isRemoved())
    {
      setDirection(getLocation().getCompassDirectionTo(nemo.getLocation()));
      move();
    }
    Actor aNemo = gameGrid.getOneActorAt(getLocation(), Fish.class);
    if (aNemo != null)
      aNemo.removeSelf();
  }
}

Programmcode für lokale Bearbeitung downloaden: JGameEx15.zip

Erklärungen zum Programmcode:
Shark shark = new Shark(nemo) Damit der Hai weiss, wen er verfolgen soll, erhält er den Parameter nemo
if (nbCycles % 5 == 0 && !nemo.isRemoved()) Der Hai bewegt sich nur jeden 5. Simulationszyklus und nur so lange der Nemo da ist
getCompassDirectionTo(nemo.getLocation())) Mit nemo.getLocation() erhalten wir die aktuelle Position von Nemo. mit getCompassDirectionTo() wird die Richtung zum Nemo gewählt
setDirection(getLocation().getCompassDirectionTo(nemo.getLocation())) Es wird Richtung von der aktuellen Position des Haifisches nichts aktuellen Position des Nemo gewählt

 

Beispiel 2: Direkte Verfolgung. Der weisse Ball folgt dem roten Ball

Im Unterschied zum vorhergehenden Beispiel bewegt sich der weisse Ball (Ball) auf dem direkten Weg zum roten Ball (Target); d.h. nicht von Zelle zu Zelle, sondern kontinuierlich. Nachdem der Ball die Position des Targets erreicht hat, verschwindet der rote Ball und erscheint auf einer neuen, zufällig gewählten Position. Die beginnt die Verfolgung erneut.

Die Position des weissen Balls wird punktweise wie folgt berechnet: Zu Beginn jeder Verfolgung wird die Differenz der x-Koordinaten dx und die Differenz der y-Koordinaten dy berechnet. Damit sich der Ball bei grossen Distanzen gleich schnell wie bei kleinen Distanzen bewegt, "normieren" wir die Speed-Komponenten, in dem wir dx und dy durch die Entfernung der beiden Bälle dividieren. Der Speedfaktor kann beliebig angepasst werden. Die neue Koordinaten x und y erhalten wir, in dem wir jeweils zu der aktuellen x bzw. y- Koordinate vx bzw. vy addieren.

 

// JGameEx16.java

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

public class JGameEx16 extends GameGrid
{
  public JGameEx16()
  {
    super(10, 10, 60, Color.red);
    Target target = new Target();
    addActor(target, new Location(5, 5));
    Ball ball = new Ball(target);
    addActor(ball, new Location(0, 0));
    show();
  }

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

class Ball extends Actor
{
  private Target target;
  private double vx, vy, x, y;
  private final double speedFactor = 10;

  public Ball(Target target)
  {
    super("sprites/playStone_0.png");
    this.target = target;
  }

  public void act()
  {
    moveBall();
    tryToTouch();
  }

  public void moveBall()
  {
    x += vx;
    y += vy;
    setPixelLocation(new Point((int)x, (int)y));
  }

  private void tryToTouch()
  {
    if (target.getLocation().equals(getLocation()))
    {
      target.setLocation(gameGrid.getRandomEmptyLocation());
      setSpeed();
    }
  }

  private void setSpeed()
  {
    Point targetPosition = target.getPixelLocation();
    int dx = targetPosition.x - getPixelLocation().x;
    int dy = targetPosition.y - getPixelLocation().y;
    double norm = Math.sqrt(dx * dx + dy *dy);
    vx = speedFactor * dx / norm;
    vy = speedFactor * dy / norm;
  }

  public void reset()
  {
    x = getPixelLocation().x;
    = getPixelLocation().y;
    setSpeed();
  }
}

// --------------------- class Ball ---------------------------
class Target extends Actor
{
  public Target()
  {
    super(true"sprites/ball.gif");
  }
}

Programmcode für lokale Bearbeitung downloaden: JGameEx16.zip

Erklärungen zum Programmcode:
int dx = targetPos.x - getPixelLocation().x
int dy = targetPos.y - getPixelLocation().y   
Berechnung der Differenz der x-Koordinaten der beiden Bälle
Berechnung der Differenz der y-Koordinaten der beiden Bälle
norm = Math.sqrt(dx * dx + dy *dy); Die Entfernung der beiden Bälle zu Beginn der Verfolgung
vx = speedFactor * dx / norm;
vy = speedFactor * dy / norm;
Berechnet die speed Komponenten
x += vx;
y += vy;
Berechnet die neuen Koordinaten
setPixelLocation(new Point((int)x, (int)y)) Setzt den weissen Ball an die genaue Position, die durch die beiden berechneten Pixelkoordinaten gegeben ist
if (ball.getLocation().equals(getLocation())) Gibt true zurück, wenn sich die beiden Bälle in der gleichen Zelle befinden