Drucken

Figuren verfolgen


Beispiel 1: Ein Hai verfolgt Nemo

Nemo schwimmt horizontal hin und her. Der Hai verfolgt den Nemo. Er bewegt sich von Zelle zu 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.

Beispiel im Online-Editor bearbeiten

App installieren auf Smartphone oder Tablet

QR-Code

Sources downloaden (AndroidEx12.zip)

 

// AndroidEx12.java

package app.ex12;

import ch.aplu.android.*;

public class AndroidEx12 extends GameGrid 
{
  public AndroidEx12()
  {
    super(8, 8, cellZoom(62), GRAY, "reef",false);
  }

  public void main()
  {
    Fish nemo = new Fish();
    addActor(nemo, new Location(0, 1));
    Shark shark = new Shark(nemo);
    addActor(shark, new Location(7, 7));
    doRun();
  }
}

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

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

class Shark extends Actor
{
  private Fish nemo;

  public Shark(Fish nemo)
  {
    super(true"shark");
    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();
  }
}

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.

Beispiel im Online-Editor bearbeiten

App installieren auf Smartphone oder Tablet

QR-Code

Sources downloaden (AndroidEx13.zip)

 

// AndroidEx13.java

package app.ex13;

import ch.aplu.android.*;
import android.graphics.Point;

public class AndroidEx13 extends GameGrid
{
  public AndroidEx13()
  {
    super(10, 10, 0, RED, true);
  }

  public void main()
  {
    Target target = new Target();
    addActor(target, new Location(5, 5));
    Ball ball = new Ball(target);
    addActor(ball, new Location(0, 0));
    doRun();
  }
}

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

  public Ball(Target target)
  {
    super("playstone");
    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 Target---------------------------
class Target extends Actor
{
  public Target()
  {
    super(true"ball");
  }
}


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