Hi guys!
I’ve made a little avoid’em’up-game for this years Java4k. It runs smooth on some computers, but when I test it on one some “older” computers the animation is a bit jerky and I run into some irritating stuttering :(.
I have these problems on an older Linux laptop (in Firefox), and an older Windows 7 box (in Internet Explorer). However, when I run Chrome on these computers the game runs fine ???.
I’ve made some Java2D games before, but I have not experience rendering issues then. For example, my entry for last years Java4K runs just fine.
I’ve done everything I can think of (even desperate things): testing with different timing approaches, busy timing looping, non-busy timing looping, reducing painting operations, removing object allocations, reducing floating number operations, removing code, and so on… but nothing seems to solve this. Obviously I’m optimizing the wrong things, and I have a hard time to find the real issue.
This is starting to drive me crazy. What am I doing wrong? Do you have any suggestions?
I’m attaching the source code for the project. It’s not very many lines of code, but since it’s a Java4K-project the readability may not be the best. Just ask me if you need any specific details or info.
If someone wants to help me I would be very happy and grateful.
Help me JavaGaming, you are my only hope!
/*
* Legend of the package delivering hero
* Copyright (C) 2012 Jens Stääf
*
* Legend of the package delivering hero is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import java.applet.Applet;
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.util.Random;
public class G extends Applet implements Runnable {
// SIZE
static final int WINDOW_WIDTH = 320;
static final int WINDOW_HEIGHT = 480;
static final int MAP_WIDTH = 20;
static final int MAP_HEIGHT = 30;
// DIRECTION
static final int UP = 0;
static final int DOWN = 1;
static final int LEFT = 2;
static final int RIGHT = 3;
// BOOLEAN
static final int NO = 0;
static final int YES = 1;
static final int PLAYER_SPEED = 220;
static final int STAR_SPEED = 1;
static final int SUN_SPEED = 1;
static final int MAX_NUMBER_OF_ENEMIES = 50;
// ENEMY TYPES
static final int POWERUP_BOMB = -3;
static final int POWERUP_SCORE = -2;
static final int POWERUP_HEALTH = -1;
static final int ENEMY_STRAIGHT = 0;
static final int ENEMY_BOUNCING = 1;
static final int ENEMY_HOMING = 2;
static final int ENEMY_TERMINATOR = 3;
static final int ENEMY_NARROWER = 4;
static final int ENEMY_CONFUSER = 5;
static final int ENEMY_BLACKHOLE = 6;
// ENEMY SPEED
static final int ENEMY_SPEED_Y = 3;
static final int ENEMY_SPEED_X = 2;
// BUTTONS
static int KEY_LEFT;
static int KEY_RIGHT;
static int KEY_UP;
static int KEY_DOWN;
static int KEY_SPACE;
// STATES
static final int STATE_TITLE = 0;
static final int STATE_START = 1;
static final int STATE_BREIFING = 2;
static final int STATE_LEVELCOMPLETED = 3;
static final int STATE_RUNNING = 4;
static final int STATE_GAMEOVER = 5;
// SCORE LIMITS, USED FOR CALCULATING ADAPTIVE DIFFICULTY
static final int SCORE_LIMIT_1 = 300;
static final int SCORE_LIMIT_2 = 500;
// PLANETS
static final String[] planets = { "Mercury", "Venus", "Earth", "Mars",
"Jupiter", "Saturn", "Uranus" };
// PARTICLES
static final int MAX_NUMBER_OF_PARTICLES = 50;
static final int NUMBER_OF_PARTICLES_IN_EXPLOSION = 20;
static final int NUMBER_OF_PARTICLES_IN_SMALL_EXPLOSION = 5;
public void start() {
this.enableEvents(AWTEvent.KEY_EVENT_MASK);
new Thread(this).start();
}
public void run() {
setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
BufferedImage screen = new BufferedImage(WINDOW_WIDTH, WINDOW_HEIGHT,
BufferedImage.TYPE_INT_RGB);
Graphics g = screen.getGraphics();
Graphics appletGraphics = getGraphics();
Random random = new Random();
// Variable for looping
int i = 0;
int a = 0;
int b = 0;
// Tile sizes
int TILE_SIZE = 16;
int TILE_SIZE_QUARTER = 4;
// Set up player
int playerX = 160;
int playerY = 440;
int playerVelocityX = 0;
int playerVelocityY = 0;
int[] playerXPoints = new int[3];
int[] playerYPoints = new int[3];
int score = -10;
int health = 5;
// Level
int scoreLimit = 30;
int level = 0;
// Timings
int timeBeforePlanet = 0;
int currentPlanetIndex = 0;
int flickerCounter = 0;
int powerupTimer = 1200;
// Ship status effects
int confused = 0;
int narrowTimer = 0;
int isHit = 0;
int isPower = 0;
// Enemy animation
int animationCounter = 0;
int animationFactor = 0;
int animationEnlarge = NO;
int blackHoleinPlace = NO;
// Set up enemies
int[] enemyX = new int[MAX_NUMBER_OF_ENEMIES];
int[] enemyY = new int[MAX_NUMBER_OF_ENEMIES];
int[] enemyDirection = new int[MAX_NUMBER_OF_ENEMIES];
int[] enemyType = new int[MAX_NUMBER_OF_ENEMIES];
int numberOfEnemies = 10;
int terminatorTimer = 0;
enemyY[0] = 800;
// Set up particles
int[] particleX = new int[MAX_NUMBER_OF_PARTICLES];
int[] particleY = new int[MAX_NUMBER_OF_PARTICLES];
int[] particleVelocityX = new int[MAX_NUMBER_OF_PARTICLES];
int[] particleVelocityY = new int[MAX_NUMBER_OF_PARTICLES];
int[] particleLife = new int[MAX_NUMBER_OF_PARTICLES];
int starsX = -100;
int starsY = 0;
int sunX = 100;
int sunY = -200;
// Game state
int state = STATE_TITLE;
// Create star image
BufferedImage starImage = new BufferedImage(WINDOW_WIDTH + 200,
WINDOW_HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics starGfx = starImage.getGraphics();
for (i = 0; i < 200; i++) {
a = random.nextInt(200);
starGfx.setColor(new Color(250 - a, 250 - a, 250 - a));
starGfx.fillOval(random.nextInt(WINDOW_WIDTH + 200),
random.nextInt(WINDOW_HEIGHT), 2, 2);
}
BufferedImage sunImage = new BufferedImage(WINDOW_WIDTH, WINDOW_HEIGHT,
BufferedImage.TYPE_INT_ARGB);
Graphics sunGfx = sunImage.getGraphics();
i = random.nextInt(3);
for (a = 0; a < 150; a++) {
sunGfx.setColor(new Color(a, 0, a / 2));
for (b = 0; b < a; b += 1) {
sunGfx.fillOval(
random.nextInt(200 - a) - random.nextInt(200 - a) + 100,
random.nextInt(200 - a) - random.nextInt(200 - a) + 150,
3, 3);
}
}
// Game loop.
long nextFrameStartTime = System.nanoTime();
while (true) {
// Start the game
if (state == STATE_START) {
// Set up the score limit
scoreLimit = 20;
// Reset the level
score = -10;
level = 0;
// Set up enemies
numberOfEnemies = 1;
terminatorTimer = 0;
// Reset planet times
timeBeforePlanet = 0;
// Remove the black hole
blackHoleinPlace = NO;
// Now run the game!
state = STATE_BREIFING;
}
// Set up enemies
if (state == STATE_RUNNING) {
for (i = 0; i < numberOfEnemies; i += 1) {
if (enemyY[i] > WINDOW_HEIGHT) {
enemyY[i] = -random.nextInt(WINDOW_HEIGHT);
enemyX[i] = random.nextInt(WINDOW_WIDTH);
if (score > SCORE_LIMIT_2 && level > 0) {
enemyType[i] = random.nextInt(10) - 3;
} else if (score > SCORE_LIMIT_1) {
enemyType[i] = random.nextInt(7) - 3;
} else {
enemyType[i] = random.nextInt(6) - 3;
}
if (enemyType[i] <= POWERUP_HEALTH) {
if (powerupTimer == 0) {
powerupTimer = 1200;
} else {
enemyType[i] = ENEMY_STRAIGHT;
}
}
if (enemyType[i] == ENEMY_BLACKHOLE) {
enemyX[i] = 160;
}
// Make sure there's only one terminator at once.
// Start the terminator timer.
if (enemyType[i] >= ENEMY_TERMINATOR) {
if (terminatorTimer == 0) {
terminatorTimer = 3000;
} else {
enemyType[i] = ENEMY_STRAIGHT;
}
}
score += 10;
// Create new enemies
if (score >= scoreLimit) {
if (numberOfEnemies < MAX_NUMBER_OF_ENEMIES - 1) {
numberOfEnemies += 1;
scoreLimit *= 3;
enemyY[numberOfEnemies - 1] = 800;
}
}
}
// Check collision with player
if (playerX <= (enemyX[i] + TILE_SIZE)
&& enemyX[i] <= (playerX + TILE_SIZE)
&& playerY <= (enemyY[i] + TILE_SIZE)
&& enemyY[i] <= (playerY + TILE_SIZE)) {
score -= 10;
if (enemyType[i] >= ENEMY_TERMINATOR) {
terminatorTimer = 0;
}
if (enemyType[i] == ENEMY_CONFUSER) {
confused = 400;
} else if (enemyType[i] == ENEMY_NARROWER) {
narrowTimer = 400;
} else if (enemyType[i] == POWERUP_HEALTH) {
health = 5;
} else if (enemyType[i] == POWERUP_SCORE) {
score += 500;
} else if (enemyType[i] == POWERUP_BOMB) {
for (b = 0; b < numberOfEnemies; b += 1) {
enemyY[b] = -(random.nextInt(350) + 350);
}
blackHoleinPlace = NO;
} else {
health -= 1;
}
enemyY[i] = 800;
a = 0;
// Set up the explosion
for (b = 0; b < MAX_NUMBER_OF_PARTICLES - 1; b += 1) {
// Check if the particle is free
if (particleLife[b] == 0) {
particleX[b] = playerX;
particleY[b] = playerY;
particleVelocityX[b] = random.nextInt(180) - 90;
particleVelocityY[b] = random.nextInt(180) - 90;
particleLife[b] = 100;
a += 1;
if (a == NUMBER_OF_PARTICLES_IN_EXPLOSION) {
break;
}
}
}
// If the player has no health, then it's game over
if (health <= 0) {
state = STATE_GAMEOVER;
confused = 0;
narrowTimer = 0;
isHit = 0;
isPower = 0;
scoreLimit = 30;
currentPlanetIndex = 0;
playerVelocityX = 0;
playerVelocityY = 0;
score += 10; // This is a quick fix
} else {
if (enemyType[i] <= POWERUP_HEALTH) {
isPower = 25;
} else {
isHit = 25;
}
}
}
}
}
flickerCounter -= 2;
if (flickerCounter <= 0) {
flickerCounter = 100;
}
if (state == STATE_RUNNING) {
// If there is a terminator, decrease the terminator timer.
if (terminatorTimer > 0) {
terminatorTimer -= 1;
}
if (powerupTimer > 0) {
powerupTimer -= 1;
}
if (isHit > 0) {
isHit -= 1;
}
if (isPower > 0) {
isPower -= 1;
}
if (confused > 0) {
confused -= 1;
}
if (narrowTimer > 0) {
narrowTimer -= 1;
if (TILE_SIZE < 32) {
TILE_SIZE += 1;
TILE_SIZE_QUARTER = TILE_SIZE / 4;
}
} else {
if (TILE_SIZE > 16) {
TILE_SIZE -= 1;
TILE_SIZE_QUARTER = TILE_SIZE / 4;
}
}
// Time to complete the level
if (timeBeforePlanet > 0) {
timeBeforePlanet -= 1;
// The level is completed
if (timeBeforePlanet == 0) {
state = STATE_LEVELCOMPLETED;
if (numberOfEnemies < MAX_NUMBER_OF_ENEMIES - 1) {
numberOfEnemies += 1;
enemyY[numberOfEnemies - 1] = 800;
}
playerVelocityX = 0;
playerVelocityY = -(PLAYER_SPEED * 2);
}
}
}
do {
if (state == STATE_RUNNING) {
// Detect keys
if ((KEY_LEFT == YES && confused == 0)
|| (KEY_RIGHT == YES && confused > 0)) {
playerVelocityX = -PLAYER_SPEED;
} else if ((KEY_RIGHT == YES && confused == 0)
|| (KEY_LEFT == YES && confused > 0)) {
playerVelocityX = PLAYER_SPEED;
}
if ((KEY_DOWN == YES && confused == 0)
|| (KEY_UP == YES && confused > 0)) {
playerVelocityY = PLAYER_SPEED;
} else if ((KEY_UP == YES && confused == 0)
|| (KEY_DOWN == YES && confused > 0)) {
playerVelocityY = -PLAYER_SPEED;
}
}
if (KEY_SPACE == YES) {
if (state == STATE_TITLE || state == STATE_GAMEOVER) {
state = STATE_START;
} else if (state == STATE_BREIFING) {
// Start a new level
state = STATE_RUNNING;
// Set up player
playerX = 160;
playerY = 385;
playerVelocityX = 0;
playerVelocityY = 0;
health = 5;
// Set up enemies
enemyX = new int[MAX_NUMBER_OF_ENEMIES];
enemyY = new int[MAX_NUMBER_OF_ENEMIES];
enemyDirection = new int[MAX_NUMBER_OF_ENEMIES];
enemyType = new int[MAX_NUMBER_OF_ENEMIES];
enemyY[0] = 800;
confused = 0;
narrowTimer = 0;
isHit = 0;
isPower = 0;
blackHoleinPlace = NO;
timeBeforePlanet = 3000 + (level * 500);
sunY = -300;
}
KEY_SPACE = NO;
}
if (state == STATE_RUNNING) {
// Reduce player velocity
if (playerVelocityX > 0) {
playerVelocityX -= 10;
} else if (playerVelocityX < 0) {
playerVelocityX += 10;
}
if (playerVelocityY > 0) {
playerVelocityY -= 10;
} else if (playerVelocityY < 0) {
playerVelocityY += 10;
}
// Black hole!
if (blackHoleinPlace == YES) {
if (playerX < 160) {
if (playerVelocityX < 220) {
playerVelocityX += 16;
}
} else if (playerVelocityX > -220) {
playerVelocityX -= 16;
}
if (playerY < 240) {
playerVelocityY += 11;
} else {
playerVelocityY -= 11;
}
}
}
if ((playerVelocityX < 0 && playerX >= 16)
|| (playerVelocityX > 0 && playerX <= 302)) {
playerX += (playerVelocityX / 50);
} else {
playerVelocityX = 0;
}
if ((playerVelocityY < 0 && playerY >= 10)
|| (playerVelocityY > 0 && playerY <= 460)
|| state == STATE_LEVELCOMPLETED) {
playerY += (playerVelocityY / 50);
} else {
playerVelocityY = 0;
}
if (state == STATE_LEVELCOMPLETED && playerY < -200) {
confused = 0;
level += 1;
currentPlanetIndex = random.nextInt(6);
confused = 0;
narrowTimer = 0;
isHit = 0;
isPower = 0;
state = STATE_BREIFING;
}
// Move stars
starsY += STAR_SPEED;
starsX -= (playerVelocityX / 100);
sunX -= (playerVelocityX / 100);
sunY += SUN_SPEED;
if (starsY == WINDOW_HEIGHT) {
starsY = 0;
}
if (sunY > WINDOW_HEIGHT) {
sunY = -300;
sunX = random.nextInt(WINDOW_WIDTH);
}
// Update particles
for (i = 0; i < MAX_NUMBER_OF_PARTICLES - 1; i += 1) {
if (particleLife[i] > 0) {
particleLife[i] -= 1;
particleX[i] += particleVelocityX[i] / 10;
particleY[i] += particleVelocityY[i] / 10;
if (particleVelocityY[i] > 0) {
particleVelocityY[i] -= 1 / 2;
} else if (particleVelocityY[i] < 0) {
particleVelocityY[i] += 1 / 2;
}
if (particleVelocityX[i] > 0) {
particleVelocityX[i] -= 1 / 2;
} else if (particleVelocityX[i] < 0) {
particleVelocityX[i] += 1 / 2;
}
// If the particle is outside the screen, then set it as
// inactive
if ((particleX[i] > WINDOW_HEIGHT || particleX[i] < 0)
&& (particleY[i] > WINDOW_HEIGHT || particleY[i] < 0)) {
particleLife[i] = 0;
}
}
}
// Move enemies
if (state == STATE_RUNNING) {
for (i = 0; i < numberOfEnemies; i += 1) {
enemyX[i] -= (playerVelocityX / 100);
// Straight moving enemies and powerups
if (enemyType[i] == ENEMY_STRAIGHT
|| enemyType[i] <= POWERUP_HEALTH) {
enemyY[i] += ENEMY_SPEED_Y;
}
// Bouncing enemies
else if (enemyType[i] == ENEMY_BOUNCING) {
if (enemyDirection[i] == LEFT) {
enemyX[i] -= ENEMY_SPEED_Y;
if (enemyX[i] <= 0) {
enemyDirection[i] = RIGHT;
}
} else {
enemyX[i] += ENEMY_SPEED_Y;
if (enemyX[i] >= 290) {
enemyDirection[i] = LEFT;
}
}
enemyY[i] += ENEMY_SPEED_X;
}
// Homing enemies
else if (enemyType[i] == ENEMY_HOMING) {
enemyY[i] += ENEMY_SPEED_Y;
if (playerX < enemyX[i]) {
enemyX[i] -= 2.;
} else if (playerX > enemyX[i]) {
enemyX[i] += 2;
}
}
else if (enemyType[i] == ENEMY_BLACKHOLE) {
if (terminatorTimer > 0) {
if (enemyY[i] < 240) {
enemyY[i] += 1;
} else {
blackHoleinPlace = YES;
}
if (enemyX[i] < 160) {
enemyX[i] += 1;
} else if (enemyX[i] > 160) {
enemyX[i] -= 1;
}
} else {
enemyY[i] += ENEMY_SPEED_Y;
blackHoleinPlace = NO;
}
}
// Terminator, confuser- and narrower-enemies
else {
if (playerX < enemyX[i]) {
enemyX[i] -= 1;
} else if (playerX > enemyX[i]) {
enemyX[i] += 1;
}
if (terminatorTimer > 0) {
if (playerY < enemyY[i]) {
enemyY[i] -= 1;
} else if (playerY > enemyY[i]) {
enemyY[i] += 1;
}
} else {
enemyY[i] += ENEMY_SPEED_Y;
}
}
}
}
// Enemy animation
animationCounter += 1;
if (animationCounter == 10) {
if (animationEnlarge == YES) {
animationFactor += 1;
if (animationFactor >= TILE_SIZE_QUARTER) {
animationEnlarge = NO;
}
} else {
animationFactor -= 1;
if (animationFactor <= -TILE_SIZE_QUARTER) {
animationEnlarge = YES;
}
}
animationCounter = 0;
}
nextFrameStartTime += 16666667;
} while (nextFrameStartTime < System.nanoTime());
// Update the player position arrays, so we can draw the spaceship
a = playerVelocityX / 60;
playerXPoints[0] = playerX + a;
playerXPoints[1] = playerX - (TILE_SIZE_QUARTER * 2 + a);
playerXPoints[2] = (playerX + TILE_SIZE_QUARTER * 2 - a);
playerYPoints[0] = playerY;
playerYPoints[2] = playerY + TILE_SIZE;
playerYPoints[1] = (playerYPoints[2] - a);
g.setColor(Color.BLACK);
g.fillRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
// Draw stars
if (!((confused > 0 || narrowTimer > 0) && flickerCounter > 50)) {
g.drawImage(starImage, starsX, starsY, null);
g.drawImage(starImage, starsX, starsY - WINDOW_HEIGHT, null);
}
g.drawImage(sunImage, sunX, sunY, null);
// Draw stuff
if (isHit > 0) {
g.setColor(Color.RED);
g.fillRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
} else if (isPower > 0) {
g.setColor(Color.GREEN);
g.fillRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
} else if (confused > 0 && flickerCounter > 50) {
g.setColor(Color.YELLOW);
g.fillRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
} else if (narrowTimer > 0 && flickerCounter > 50) {
g.setColor(Color.PINK);
g.fillRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
}
g.setColor(Color.WHITE);
// Draw particles
for (i = 0; i < MAX_NUMBER_OF_PARTICLES - 1; i += 1) {
if (particleLife[i] > 0) {
a = 55 + (particleLife[i] * 2);
g.setColor(new Color(a, a, a));
g.fillOval(particleX[i], particleY[i], TILE_SIZE_QUARTER,
TILE_SIZE_QUARTER);
}
}
// Draw on state running
if (state == STATE_RUNNING || state == STATE_LEVELCOMPLETED) {
// Draw player
g.setColor(Color.GREEN);
g.fillPolygon(playerXPoints, playerYPoints, 3);
// Draw enemies
for (i = 0; i < numberOfEnemies; i += 1) {
if (enemyType[i] == ENEMY_STRAIGHT) {
g.setColor(Color.MAGENTA);
}
else if (enemyType[i] == ENEMY_BOUNCING) {
g.setColor(Color.CYAN);
}
else if (enemyType[i] == ENEMY_HOMING) {
g.setColor(Color.RED);
}
else if (enemyType[i] == ENEMY_TERMINATOR) {
g.setColor(Color.DARK_GRAY);
}
else if (enemyType[i] == ENEMY_CONFUSER) {
g.setColor(Color.YELLOW);
}
else if (enemyType[i] == ENEMY_NARROWER) {
g.setColor(Color.PINK);
}
else if (enemyType[i] <= POWERUP_HEALTH) {
g.setColor(Color.GREEN);
if (enemyType[i] == POWERUP_HEALTH) {
g.drawString("HEALTH", enemyX[i]
- (TILE_SIZE_QUARTER * 3), enemyY[i]
+ (TILE_SIZE * 2));
} else if (enemyType[i] == POWERUP_SCORE) {
g.drawString("POINTS", enemyX[i]
- (TILE_SIZE_QUARTER * 3), enemyY[i]
+ (TILE_SIZE * 2));
} else if (enemyType[i] == POWERUP_BOMB) {
g.drawString("BOMB!!", enemyX[i]
- (TILE_SIZE_QUARTER * 3), enemyY[i]
+ (TILE_SIZE * 2));
}
}
if (enemyType[i] == ENEMY_BLACKHOLE) {
g.setColor(Color.BLACK);
g.fillOval(enemyX[i], enemyY[i], TILE_SIZE
+ animationFactor, TILE_SIZE + animationFactor);
g.setColor(Color.WHITE);
g.drawOval(enemyX[i], enemyY[i], TILE_SIZE
+ animationFactor, TILE_SIZE + animationFactor);
} else {
g.fillOval(enemyX[i], enemyY[i], TILE_SIZE
+ animationFactor, TILE_SIZE + animationFactor);
}
}
}
if (state == STATE_RUNNING || state == STATE_LEVELCOMPLETED
|| state == STATE_GAMEOVER) {
// Draw texts
if ((confused > 0 || narrowTimer > 0) && flickerCounter > 50) {
g.setColor(Color.BLACK);
} else {
g.setColor(Color.WHITE);
}
if (state != STATE_GAMEOVER && timeBeforePlanet != 0
&& (timeBeforePlanet / 100) <= 1 && flickerCounter > 50) {
g.drawString("Going in for landing on "
+ planets[currentPlanetIndex] + ".", 60, 200);
}
g.drawString("Score: " + score, 10, 419);
g.drawString("Health:", 10, 437);
for (i = 0; i < health; i += 1) {
g.fillOval(60 + (12 * i), 428, 8, 8);
}
g.drawString("Pkgs delivered: " + level, 10, 455);
g.drawString("Distance to " + planets[currentPlanetIndex]
+ ": " + (timeBeforePlanet / 100), 10, 473);
}
else if (state == STATE_BREIFING) {
g.setColor(Color.WHITE);
if (level == 0) {
g.drawString("Hi package delivering hero!", 45, 120);
g.drawString("You need to deliver a very secret", 45, 150);
} else {
g.drawString("Well done! The package is now safe.", 45, 120);
g.drawString("Now you need to deliver another secret", 45,
150);
}
if (flickerCounter > 50) {
g.drawString("Press space to start mission.", 45, 250);
}
g.drawString("package to our base on "
+ planets[currentPlanetIndex] + ".", 45, 170);
}
// Draw on state title
else if (state == STATE_TITLE) {
g.drawString("Legend of the package delivering hero", 45, 200);
if (flickerCounter > 50) {
g.drawString("Press space to start", 100, 250);
}
}
// Draw on state game over
if (state == STATE_GAMEOVER) {
g.setColor(Color.WHITE);
g.drawString("GAME OVER", 127, 210);
if (flickerCounter > 50) {
g.drawString("Press space to restart.", 100, 250);
}
}
// Draw the entire results on the screen.
appletGraphics.drawImage(screen, 0, 0, null);
// Burn off extra cycles
long remaining = nextFrameStartTime - System.nanoTime();
if (remaining > 0) {
try {
Thread.sleep(remaining / 1000000);
} catch (Exception e) {
}
}
}
}
/**
* Check for key events
*/
public void processKeyEvent(KeyEvent e) {
int keyCode = e.getKeyCode();
if (e.getID() == KeyEvent.KEY_PRESSED) {
if (keyCode == KeyEvent.VK_LEFT) {
KEY_LEFT = YES;
} else if (keyCode == KeyEvent.VK_RIGHT) {
KEY_RIGHT = YES;
} else if (keyCode == KeyEvent.VK_UP) {
KEY_UP = YES;
} else if (keyCode == KeyEvent.VK_DOWN) {
KEY_DOWN = YES;
} else if (keyCode == KeyEvent.VK_SPACE) {
KEY_SPACE = YES;
}
} else if (e.getID() == KeyEvent.KEY_RELEASED) {
if (keyCode == KeyEvent.VK_LEFT) {
KEY_LEFT = NO;
} else if (keyCode == KeyEvent.VK_RIGHT) {
KEY_RIGHT = NO;
} else if (keyCode == KeyEvent.VK_UP) {
KEY_UP = NO;
} else if (keyCode == KeyEvent.VK_DOWN) {
KEY_DOWN = NO;
}
}
}
}