GameGrid: Game programming with Java

Research project PHBern  
HomePrintJava-Online

Moon landing

This program simulates a real moon landing. The speed, the acceleration and the amount of fuel left is recalculated continuously. There is only a limited amout of fuel.

The landing speed is controlled with the cursor keys:
UP: uses more fuel - breaks
DOWN: uses less fuel - accelerates

 

Aim: Landing with almost no speed. If the speed is over 10 m/s, the Lunarlander crashes.

Run this example

Edit this example in the Online-Editor

Download the program code (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);
  }
}