Game-Apps für Smartphones und Tablets |
|
Bern University oh Teacher Education |
Raketenschub (Massenausstoss pro Sekunde) kann mit der Volumentaste gesteuert werden: Ziel: Landung mit einer möglichst kleinen Geschwindigkeit. Ist die Geschwindigkeit grösser als 10 m/s kracht das Raumschiff in den Mond. |
![]() |
|
Programmcode:
// LunarLander.java package app.lunarlander; import android.graphics.*; import ch.aplu.android.*; import ch.aplu.util.HiResTimer; import ch.aplu.util.*; public class LunarLander extends GameGrid { public LunarLander() { super("moon", false, true, windowZoom(300)); setScreenOrientation(PORTRAIT); } public void main() { int screenWidth = getNbHorzCells(); int screenHeight = getNbVertCells(); setSimulationPeriod(50); Lander lander = new Lander(screenWidth, screenHeight); addNavigationListener(lander); addActor(lander, new Location(2 * screenWidth / 3, screenWidth / 7)); doRun(); } } class Lander extends Actor implements GGNavigationListener { private int screenWidth; private int screenHeight; private int imageWidth; private int imageHeight; private final double yTouchdown = 350; private final double xmax = 300; 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("landerdebris"); private Actor thrust = new Actor("thrust", 9); private boolean isLanded = false; private HiResTimer timer = new HiResTimer(); private final int xLeft = 10; private GGTextField status; private Location statusLoc; private GGTextField title; private Location titleLoc; private GGTextField fuelIndicator; private Location fuelIndicatorLoc; private GGTextField thrustIndicator; private Location thrustIndicatorLoc; private Location[] resultLocs = new Location[6]; private GGTextField[] results = new GGTextField[resultLocs.length]; private String[] fuelLevel = new String[12]; public Lander(int screenWidth, int screenHeight) { super("lander"); imageWidth = screenWidth; imageHeight = 4 * imageWidth / 3; this.screenWidth = screenWidth; this.screenHeight = screenHeight; init(); } // User coordinates 0..xmax -> screen ulx...screen urx private int toPixel(double user) { return (int)(screenWidth / xmax * user); } private double toUser(int pixel) { return xmax / screenWidth * pixel; } private void init() { statusLoc = new Location(xLeft, screenHeight - 10); status = new GGTextField("", statusLoc, false); status.show(); titleLoc = new Location(10, 27); title = new GGTextField("LunarLander (www.aplu.ch). Thrust: Volume+-", titleLoc, false); title.setFontSize(20); title.show(); fuelIndicatorLoc = new Location(xLeft, imageHeight / 2 - 40); fuelIndicator = new GGTextField("Fuel level: 11", fuelIndicatorLoc, false); fuelIndicator.setTextColor(Color.YELLOW); fuelIndicator.setFontSize(30); fuelIndicator.show(); thrustIndicatorLoc = new Location(xLeft, imageHeight / 2 - 10); thrustIndicator = new GGTextField("Fuel level: 11", thrustIndicatorLoc, false); thrustIndicator.setTextColor(Color.YELLOW); thrustIndicator.setFontSize(30); thrustIndicator.show(); for (int i = 0; i < results.length; i++) { resultLocs[i] = new Location(xLeft, imageHeight / 2 + 20 + 20 * i); results[i] = new GGTextField("", resultLocs[i], false); results[i].show(); } for (int i = 0; i < fuelLevel.length; i++) fuelLevel[i] = "fuel" + i; } public void reset() { GameGrid gg = gameGrid; setDirection(Location.SOUTH); x = toUser(getLocationStart().x); y = toUser(getLocationStart().y); L.i("xStart = " + x); L.i("yStart = " + y); v = 0; a = amax; fuel = startFuel; 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.getBg().clear(Color.BLACK); for (int i = 0; i < results.length; i++) results[i].setText(""); timer.start(); showFuelLevel(11); showThrustLevel(0); } public void act() { GameGrid gg = gameGrid; double vdisp = (int)(100 * v) / 100.0; double h = yTouchdown - y; String s = String.format("h=%4.1f m v=%4.2f m/s", h, v); if (getNbCycles() % 10 == 0) status.setText(s); double dt = 2 * gg.getSimulationPeriod() / 1000.0; // Time scaled: * 2 v = v + a * dt; y = y + v * dt; setLocation(new Location(toPixel(x), toPixel(y))); thrust.setLocation(new Location(toPixel(x), toPixel(y) + (int)(27 * gg.getZoomFactor()))); fuel = fuel - z * fuelFactor; if (fuel < 0) fuel = 0; for (int i = 2; i <= 10; i++) { if (fuel <= (i - 1) * 100.0 && fuel > (i - 2) * 100.0) { if (fuel > 50) showFuelLevel(i); } } if (fuel <= 50 && fuel > 0) showFuelLevel(1); if (fuel == 0) { showFuelLevel(0); z = 0; a = amax; showThrustLevel(0); } if (h <= 0 && !isLanded) { status.setText("Touchdown!"); if (v > 10.0) { debris.setLocation(new Location(getLocation().x, getLocation().y + 30)); debris.show(); hide(); results[0].setText("Crashed!"); results[1].setText("Speed: " + vdisp + "m/s"); } else { long time = timer.getTime(); results[0].setText("Successfully landed!"); results[1].setText("Speed: " + vdisp + "m/s"); results[2].setText("Time used: " + time / 1000000 + "s"); results[3].setText("Remaining fuel: " + (int)fuel + "kg"); } results[4].setText("Play: 'Back' button"); results[5].setText("Quit: 'Home' button"); setActEnabled(false); z = 0; showThrustLevel(0); isLanded = true; } } public void navigationEvent(GGNavigationEvent event) { if (!gameGrid.isRunning()) return; if (event == GGNavigationEvent.BACK_DOWN && isLanded) { reset(); gameGrid.doRun(); return; } if (fuel == 0) return; double da = 0.4; switch (event) { case VOLUME_INCREASE_REPEAT: if (z < 8) { a -= da; z++; } break; case VOLUME_DECREASE_REPEAT: if (z > 0) { a += da; z -= 1; } else a = amax; break; } showThrustLevel(z); } private void showFuelLevel(int i) { fuelIndicator.setText("Fuel level: " + i); } private void showThrustLevel(int z) { thrust.show(z); thrustIndicator.setText("Thrust: " + z); } } |