You can save this as GreenLanternGame.java and compile it with the J2ME Wireless Toolkit.
// GreenLanternGame.java // A story-driven action game for 320x240 screens // Controls: Left/Right = Move, Fire = Shoot, Up = Fly Up (in flight segments)import javax.microedition.lcdui.; import javax.microedition.midlet.; import java.util.Random;
public class GreenLanternGame extends MIDlet implements CommandListener, Runnable { private Display display; private GameCanvas canvas; private Command exitCommand; private Command backCommand; private boolean running; private Thread gameThread; private int gameState; // 0=menu, 1=level1, 2=level2, 3=level3, 4=cutscene, 5=gameOver, 6=victory private int cutsceneStep; private long cutsceneTimer; green lantern java game 320x240 upd
// Game objects private int playerX, playerY; private int[] enemiesX, enemiesY; private boolean[] enemiesAlive; private int[] bulletsX, bulletsY; private boolean[] bulletsActive; private int score; private int lives; private int energy; // Green Lantern ring energy private int levelProgress; private Random rand; private String storyText; // Flight segment variables private boolean flightMode; private int obstacleX; private int scrollY; public GreenLanternGame() display = Display.getDisplay(this); canvas = new GameCanvas(); exitCommand = new Command("Exit", Command.EXIT, 1); backCommand = new Command("Back", Command.BACK, 1); canvas.addCommand(exitCommand); canvas.setCommandListener(this); rand = new Random(); gameState = 0; // menu enemiesX = new int[10]; enemiesY = new int[10]; enemiesAlive = new boolean[10]; bulletsX = new int[10]; bulletsY = new int[10]; bulletsActive = new boolean[10]; score = 0; lives = 3; energy = 100; flightMode = false; public void startApp() display.setCurrent(canvas); running = true; gameThread = new Thread(this); gameThread.start(); public void pauseApp() {} public void destroyApp(boolean unconditional) running = false; public void commandAction(Command c, Displayable d) if (c == exitCommand) destroyApp(true); notifyDestroyed(); else if (c == backCommand && gameState == 5) gameState = 0; // back to menu resetGame(); private void resetGame() score = 0; lives = 3; energy = 100; levelProgress = 0; flightMode = false; gameState = 0; private void startLevel(int level) playerX = 140; playerY = 200; flightMode = false; levelProgress = 0; energy = 100; // Initialize enemies for (int i = 0; i < 10; i++) enemiesX[i] = 20 + rand.nextInt(280); enemiesY[i] = -50 - (i * 50); enemiesAlive[i] = true; // Clear bullets for (int i = 0; i < 10; i++) bulletsActive[i] = false; if (level == 2) storyText = "Sinestro's fear constructs attack!"; flightMode = true; scrollY = 0; obstacleX = rand.nextInt(280); else if (level == 3) storyText = "Parallax rises. Willpower is your only weapon."; public void run() { while (running) { try updateGame(); canvas.repaint(); Thread.sleep(50); // ~20 FPS catch (Exception e) {} } } private void updateGame() int keyState = canvas.getKeyStates(); if (gameState == 0) // Menu state - story-driven menu if (keyState != 0) gameState = 4; // start cutscene cutsceneStep = 0; cutsceneTimer = System.currentTimeMillis(); storyText = "In brightest day, in blackest night..."; return; if (gameState == 4) // Cutscene if (System.currentTimeMillis() - cutsceneTimer > 3000) cutsceneStep++; cutsceneTimer = System.currentTimeMillis(); switch(cutsceneStep) case 1: storyText = "No evil shall escape my sight!"; break; case 2: storyText = "Let those who worship evil's might..."; break; case 3: storyText = "Beware my power... GREEN LANTERN'S LIGHT!"; break; case 4: gameState = 1; startLevel(1); break; return; if (gameState == 5) // Game Over return; if (gameState == 6) // Victory if (keyState != 0) gameState = 0; resetGame(); return; // --- GAMEPLAY UPDATE --- if (flightMode) // Flight segment (Level 2) scrollY += 8; if (scrollY > 240) scrollY = 0; obstacleX = rand.nextInt(280); // Move player in flight mode if ((keyState & LEFT_PRESSED) != 0) playerX -= 6; if ((keyState & RIGHT_PRESSED) != 0) playerX += 6; if ((keyState & UP_PRESSED) != 0) playerY -= 5; if ((keyState & DOWN_PRESSED) != 0) playerY += 5; // Boundaries if (playerX < 10) playerX = 10; if (playerX > 310) playerX = 310; if (playerY < 20) playerY = 20; if (playerY > 230) playerY = 230; // Collision with obstacle if (Math.abs(playerX - obstacleX) < 20 && scrollY > 200) energy -= 20; if (energy <= 0) lives--; if (lives <= 0) gameState = 5; else startLevel(2); obstacleX = rand.nextInt(280); scrollY = 0; // Level progress levelProgress++; if (levelProgress > 200) gameState = 3; // go to level 3 startLevel(3); flightMode = false; else // Ground combat levels (1 and 3) // Player movement if ((keyState & LEFT_PRESSED) != 0) playerX -= 5; if ((keyState & RIGHT_PRESSED) != 0) playerX += 5; if (playerX < 10) playerX = 10; if (playerX > 310) playerX = 310; // Shooting if ((keyState & FIRE_PRESSED) != 0) for (int i = 0; i < 10; i++) if (!bulletsActive[i]) bulletsActive[i] = true; bulletsX[i] = playerX; bulletsY[i] = playerY - 10; break; // Update bullets for (int i = 0; i < 10; i++) if (bulletsActive[i]) bulletsY[i] -= 8; if (bulletsY[i] < 0) bulletsActive[i] = false; // Check collision for (int j = 0; j < 10; j++) if (enemiesAlive[j] && Math.abs(bulletsX[i] - enemiesX[j]) < 15 && Math.abs(bulletsY[i] - enemiesY[j]) < 15) enemiesAlive[j] = false; bulletsActive[i] = false; score += 10; levelProgress++; // Update enemies for (int i = 0; i < 10; i++) if (enemiesAlive[i]) enemiesY[i] += 3; if (enemiesY[i] > 240) enemiesY[i] = -20; enemiesX[i] = 20 + rand.nextInt(280); // Enemy hits player if (Math.abs(playerX - enemiesX[i]) < 20 && Math.abs(playerY - enemiesY[i]) < 20) energy -= 15; enemiesAlive[i] = false; if (energy <= 0) lives--; if (lives <= 0) gameState = 5; else startLevel(gameState); enemiesY[i] = -20; // Level progression if (levelProgress >= 20) if (gameState == 1) gameState = 2; startLevel(2); else if (gameState == 3) gameState = 6; // Victory // Regenerate energy slowly if (energy < 100 && !flightMode) energy++; class GameCanvas extends Canvas private Font titleFont = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_LARGE); private Font textFont = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN, Font.SIZE_SMALL); public void paint(Graphics g) // Black background g.setColor(0, 0, 0); g.fillRect(0, 0, getWidth(), getHeight()); if (gameState == 0) // Menu Screen g.setColor(0, 255, 0); g.setFont(titleFont); g.drawString("GREEN LANTERN", 160, 40, Graphics.HCENTER); g.setColor(100, 255, 100); g.setFont(textFont); g.drawString("Press any key", 160, 120, Graphics.HCENTER); g.drawString("Defeat Sinestro", 160, 150, Graphics.HCENTER); g.drawString("Protect Oa", 160, 180, Graphics.HCENTER); // Green Lantern symbol g.setColor(0, 180, 0); g.fillArc(130, 80, 60, 60, 0, 360); g.setColor(0, 0, 0); g.fillArc(140, 90, 40, 40, 0, 360); else if (gameState == 4) // Cutscene g.setColor(0, 255, 0); g.setFont(titleFont); g.drawString("STORY", 160, 30, Graphics.HCENTER); g.setFont(textFont); g.drawString(storyText, 160, 100, Graphics.HCENTER); g.drawString("You are Hal Jordan", 160, 140, Graphics.HCENTER); g.drawString("Last hope of the Corps", 160, 170, Graphics.HCENTER); else if (gameState == 5) // Game Over g.setColor(255, 0, 0); g.setFont(titleFont); g.drawString("GAME OVER", 160, 80, Graphics.HCENTER); g.setColor(200, 200, 200); g.setFont(textFont); g.drawString("Score: " + score, 160, 140, Graphics.HCENTER); g.drawString("Press Back to Menu", 160, 200, Graphics.HCENTER); else if (gameState == 6) // Victory g.setColor(0, 255, 0); g.setFont(titleFont); g.drawString("VICTORY!", 160, 60, Graphics.HCENTER); g.setFont(textFont); g.drawString("You have mastered", 160, 110, Graphics.HCENTER); g.drawString("the willpower!", 160, 135, Graphics.HCENTER); g.drawString("Oa is saved.", 160, 160, Graphics.HCENTER); g.drawString("Press any key", 160, 210, Graphics.HCENTER); else // Gameplay Screen // Draw UI g.setColor(0, 255, 0); g.drawString("Score: " + score, 5, 5, Graphics.LEFT); g.drawString("Lives: " + lives, 5, 20, Graphics.LEFT); g.drawString("Energy: " + energy, 5, 35, Graphics.LEFT); // Energy bar g.setColor(50, 50, 50); g.fillRect(80, 35, 100, 8); g.setColor(0, 255, 0); g.fillRect(80, 35, energy, 8); // Draw story hint if (gameState == 1) g.drawString("Earth Invasion", 200, 5, Graphics.LEFT); else if (gameState == 2) g.drawString("Flight: Avoid fear!", 200, 5, Graphics.LEFT); else if (gameState == 3) g.drawString("Parallax Boss", 200, 5, Graphics.LEFT); if (flightMode) // Flight mode graphics g.setColor(0, 100, 0); g.fillRect(0, 0, 320, 240); // Starfield for (int i = 0; i < 50; i++) g.setColor(255, 255, 255); g.drawLine(i * 7, (scrollY + i * 10) % 240, i * 7, (scrollY + i * 10) % 240); // Obstacle (fear construct) g.setColor(100, 0, 100); g.fillRect(obstacleX, scrollY, 25, 25); g.setColor(200, 0, 200); g.drawString("FEAR", obstacleX + 2, scrollY + 8, Graphics.LEFT); // Player - Green Lantern g.setColor(0, 255, 0); g.fillArc(playerX - 10, playerY - 10, 20, 20, 0, 360); g.setColor(0, 180, 0); g.fillArc(playerX - 6, playerY - 6, 12, 12, 0, 360); else // Ground combat // Draw ground g.setColor(30, 30, 30); g.fillRect(0, 210, 320, 30); // Draw enemies (Sinestro Corps) for (int i = 0; i < 10; i++) if (enemiesAlive[i]) g.setColor(100, 0, 255); g.fillRect(enemiesX[i] - 8, enemiesY[i] - 8, 16, 16); g.setColor(200, 100, 255); g.drawString("S", enemiesX[i] - 3, enemiesY[i] - 5, Graphics.LEFT); // Draw bullets for (int i = 0; i < 10; i++) if (bulletsActive[i]) g.setColor(0, 255, 0); g.fillRect(bulletsX[i] - 2, bulletsY[i] - 4, 4, 8); // Draw player - Green Lantern g.setColor(0, 255, 0); g.fillArc(playerX - 12, playerY - 12, 24, 24, 0, 360); g.setColor(0, 200, 0); g.fillArc(playerX - 6, playerY - 6, 12, 12, 0, 360); // Ring glow effect g.setColor(0, 255, 0, true); for (int i = 0; i < 3; i++) g.drawArc(playerX - 15 - i, playerY - 15 - i, 30 + i * 2, 30 + i * 2, 0, 360); // Story text during gameplay if (storyText != null && gameState < 4) g.setColor(0, 0, 0); g.fillRect(10, 200, 300, 30); g.setColor(0, 255, 0); g.drawString(storyText, 160, 210, Graphics.HCENTER);
}
Not all Java games are created equal. Most older Java games were designed for small screens like 128x160 or 176x220. The 320x240 resolution (common on Nokia N-series, Sony Ericsson K800i, and Samsung D900) offers a widescreen-like experience with better visibility of constructs, enemies, and environmental hazards.
The “UPD” (Updated) tag in your search refers to community-patched versions that fix: You can save this as GreenLanternGame
Without the UPD version, you risk downloading a stretched or letterboxed game that is nearly unplayable.
Story:
Hal Jordan (player) patrols Sector 2814. Sinestro Corps attacks Coast City. Use the power ring to create constructs (giant fist, shield, minigun, bubble) to destroy enemies and protect civilians. Why the “320x240 UPD” Version Matters Not all
Core loop:
Control scheme (320x240 keypad):
Image (320x240 x 2 bytes = 150 KB)int[] arrays (faster than Image objects)Vector or Hashtable – use fixed-size arraysString concatenation in game loop – use StringBuffer