Spielprogrammierung mit Java
HomeAufgabenDruckenJava-Online

Moonlander

Das Programm simuliert eine Mondlandung. Die Geschwindigkeit, Beschleunigung und die verbliebene Treibstoffmenge wird laufend berechnet. Es steht nur eine beschränkte Menge Treibstoff zur Verfügung.

Die Landegeschwindigkeit kann mit den Cursortasten gesteuert werden:
UP: mehr Treibstoff - bremsen
DOWN: weniger Treibstoff

 

Ziel: Landung mit einer möglichst kleinen Geschwindigkeit. Ist die Geschwindigkeit grösser als 10 m/s kracht das Raumschiff in den Mond.

Programmcode downloaden: LunarLander.zip

 

 
Programmcode
// LunarLander.java

import ch.aplu.jgamegrid.*;
import ch.aplu.util.*;
import java.awt.*;
import java.awt.event.KeyEvent;

public class LunarLander extends GameGrid
{
  public LunarLander()
  {
    super(600, 600, 1, null"sprites/moon.gif"false);
    setSimulationPeriod(50);
    Lander lander = new Lander();
    addActor(lander, new Location(330, 100));
    addKeyListener(lander);
    setTitle("Moon Lander. Use cursor up/down to increase/decrease thrust");
    show();
    delay(3000);
    doRun();
  }

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

// Lander.java

class Lander extends Actor implements GGKeyListener
{
  private final double startFuel = 1000;  // Amount of fuel at start
  private final double fuelFactor = 0.5; // Fuel consumtion per simulation period and thrust level
  private final double amax = 1.6; // Free acceleration on moon
  private double x;  // Position in east direction
  private double y;  // Position in downward direction
  private double v;  // Speed in downward direction
  private double a;  // Accelleration in downward direction
  private int z; // Thrust level
  private double fuel; // Remaining fuel
  private Actor debris = new Actor("sprites/landerdebris.gif");
  private Actor thrust = new Actor("sprites/thrust.gif"9);
  private boolean isLanded = false;
  private HiResTimer timer = new HiResTimer();
  private SoundPlayer player = new SoundPlayer(this"wav/jet.wav");
  private boolean fuelExpired;
  //private boolean[] isPlayed = new boolean[12];

  public Lander()
  {
    super("sprites/lander.gif");
  }

  public void reset()
  {
    GameGrid gg = gameGrid;
    setDirection(Location.SOUTH);
    x = getLocationStart().x;
    = getLocationStart().y;
    = 0;
    a = amax;
    fuel = startFuel;
    fuelExpired = false;
    show();
    setActEnabled(true);
    if (debris.gameGrid == null)  // not yet added to GameGrid
      gg.addActor(debris, new Location());
    debris.hide();
    if (thrust.gameGrid == null) // not yet added to GameGrid
      gg.addActor(thrust, new Location());
    thrust.hide();
    isLanded = false;
    gg.setBgColor(java.awt.Color.black);
    timer.start();
    player.setVolume(0);
    player.playLoop();
  //  for (int i = 0; i < 12; i++)
  //    isPlayed[i] = false;
  }

  public void act()
  {
    GameGrid gg = gameGrid;
    double vdisp = (int)(100 * v/ 100.0;
    double = 490 - y;
    String s;
    if (fuelExpired)
      s = String.format("h = %10.2f m     v = %10.2f m/s    a = %10.2f m/s^2    fuel = %10.0f kg (expired)"h, v, a, fuel);
    else
      = String.format("h = %10.2f m     v = %10.2f m/s    a = %10.2f m/s^2    fuel = %10.0f kg"h, v, a, fuel);
    gg.setTitle(s);
    double dt = * gg.getSimulationPeriod() / 1000.0;  // Time scaled: * 2
    = + * dt;
    y = + * dt;
    setLocation(new Location((int)x, (int)y));
    thrust.setLocation(new Location((int)x, (int)+ 57));
    fuel = fuel - * fuelFactor;
   
    if (fuel <= 0)
    {
      fuel = 0;
      z = 0;
      a = amax;
      setThrust(0);
      player.setVolume(0);
      fuelExpired = true;
    }

    if (getLocation().> 490 && !isLanded)
    {
      gg.setTitle("Touchdown!");
      if (v > 10.0)
      {
        debris.setLocation(new Location(getLocation().x, getLocation().+ 30));
        debris.show();
        hide();
        gg.getBg().drawText("Sorry! Crashed with speed: " + vdisp + " m/s"new Point(20, 300));
        gg.playSound(thisGGSound.EXPLODE);
      }
      else
      {
        long time = timer.getTime();
        gg.getBg().drawText("Congratulation! Landed with speed: " + vdisp + " m/s"new Point(20, 300));
        gg.getBg().drawText("Time used: " + time / 1000000 + " s"new Point(20, 350));
        gg.getBg().drawText("Remaining fuel: " + (int)fuel + " kg"new Point(20, 400));
        gg.playSound(thisGGSound.FADE);
      }
      player.stop();
      gg.getBg().drawText("Press any key..."new Point(20, 450));
      setActEnabled(false);
      z = 0;
      setThrust(0);
      isLanded = true;
    }
  }

  public boolean keyPressed(KeyEvent evt)
  {
    if (!gameGrid.isRunning())
      return true;

    if (isLanded)
    {
      reset();
      gameGrid.doRun();
      return true;
    }

    double da = 0.4;
    switch (evt.getKeyCode())
    {
      case KeyEvent.VK_UP:
        a -= da;
        z += 1;
        break;
      case KeyEvent.VK_DOWN:
        a += da;
        z -= 1;
        if (a > amax)
        {
          a = amax;
          z = 0;
        }
        break;
    }
    if (a == amax)
    {
      setThrust(0);
      player.setVolume(0);
    }
    else
    {
      player.setVolume((int)(-100 * a+ 820);
      setThrust(z);
    }
    return true;  // Consume
  }

  public boolean keyReleased(KeyEvent evt)
  {
    return true;
  }

  private void setThrust(int i)
  {
    if (i < 0)
      i = 0;
    if (i > 8)
      i = 8;
    thrust.show(i);
  }
}