Defend Earth!
Space Shooter
Pilot a ship, fire lasers and blast waves of descending aliens. You will level up with ArrayLists of bullets and enemies, spawning, object cleanup and difficulty that ramps up over time.
Pilot a ship, fire lasers and blast waves of descending aliens. You will level up with ArrayLists of bullets and enemies, spawning, object cleanup and difficulty that ramps up over time.
Set up the project and get your ship sliding along the bottom of space.
int shipX = 280, shipW = 40;
boolean leftHeld, rightHeld;
void update() {
if (leftHeld) shipX -= 6;
if (rightHeld) shipX += 6;
shipX = Math.max(0, Math.min(600 - shipW, shipX));
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(77, 217, 224));
int[] xs = { shipX + shipW/2, shipX, shipX + shipW };
int[] ys = { 580, 620, 620 };
g.fillPolygon(xs, ys, 3);
} int shipX = 280, shipW = 40;
boolean leftHeld, rightHeld;
void update() {
if (leftHeld) shipX -= 6;
if (rightHeld) shipX += 6;
shipX = Math.max(0, Math.min(600 - shipW, shipX));
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(77, 217, 224));
int[] xs = { shipX + shipW/2, shipX, shipX + shipW };
int[] ys = { 580, 620, 620 };
g.fillPolygon(xs, ys, 3);
}
Press Space to fire lasers that travel up and disappear off screen.
java.util.List<Rectangle> bullets = new java.util.ArrayList<>();
public void keyPressed(KeyEvent e) {
// ... arrows ...
if (e.getKeyCode() == KeyEvent.VK_SPACE)
bullets.add(new Rectangle(shipX + shipW/2 - 2, 578, 4, 12));
}
void update() {
// ... ship movement ...
for (Rectangle b : bullets) b.y -= 9;
bullets.removeIf(b -> b.y + b.height < 0);
}
// paintComponent:
// g.setColor(new Color(250, 204, 21));
// for (Rectangle b : bullets) g.fillRect(b.x, b.y, b.width, b.height); java.util.List<Rectangle> bullets = new java.util.ArrayList<>();
public void keyPressed(KeyEvent e) {
// ... arrows ...
if (e.getKeyCode() == KeyEvent.VK_SPACE)
bullets.add(new Rectangle(shipX + shipW/2 - 2, 578, 4, 12));
}
void update() {
// ... ship movement ...
for (Rectangle b : bullets) b.y -= 9;
bullets.removeIf(b -> b.y + b.height < 0);
}
// paintComponent:
// g.setColor(new Color(250, 204, 21));
// for (Rectangle b : bullets) g.fillRect(b.x, b.y, b.width, b.height);
for (Rectangle b : bullets) b.y for (Rectangle b : bullets) b.y 9; bullets. 9; bullets.(b -> b.y + b.height < (b -> b.y + b.height < ););
Fill the sky with aliens that march side-to-side and step down like Space Invaders.
java.util.List<Rectangle> aliens = new java.util.ArrayList<>();
int alienDir = 1;
// constructor:
for (int r = 0; r < 4; r++)
for (int c = 0; c < 6; c++)
aliens.add(new Rectangle(60 + c*80, 60 + r*52, 36, 26));
void update() {
boolean hitWall = false;
for (Rectangle a : aliens)
if (a.x + alienDir*2 < 0 || a.x + a.width + alienDir*2 > 600)
hitWall = true;
if (hitWall) {
alienDir = -alienDir;
for (Rectangle a : aliens) a.y += 14;
}
for (Rectangle a : aliens) a.x += alienDir * 2;
} java.util.List<Rectangle> aliens = new java.util.ArrayList<>();
int alienDir = 1;
// constructor:
for (int r = 0; r < 4; r++)
for (int c = 0; c < 6; c++)
aliens.add(new Rectangle(60 + c*80, 60 + r*52, 36, 26));
void update() {
boolean hitWall = false;
for (Rectangle a : aliens)
if (a.x + alienDir*2 < 0 || a.x + a.width + alienDir*2 > 600)
hitWall = true;
if (hitWall) {
alienDir = -alienDir;
for (Rectangle a : aliens) a.y += 14;
}
for (Rectangle a : aliens) a.x += alienDir * 2;
}
Lasers destroy aliens on contact, with score, and both objects removed cleanly.
int score = 0;
var bi = bullets.iterator();
while (bi.hasNext()) {
Rectangle b = bi.next();
var ai = aliens.iterator();
while (ai.hasNext()) {
Rectangle a = ai.next();
if (b.intersects(a)) {
ai.remove(); // alien destroyed
bi.remove(); // bullet used up
score += 20;
break; // this bullet is gone
}
}
} int score = 0;
var bi = bullets.iterator();
while (bi.hasNext()) {
Rectangle b = bi.next();
var ai = aliens.iterator();
while (ai.hasNext()) {
Rectangle a = ai.next();
if (b.intersects(a)) {
ai.remove(); // alien destroyed
bi.remove(); // bullet used up
score += 20;
break; // this bullet is gone
}
}
}
if (b.intersects(a)) {
ai.if (b.intersects(a)) {
ai.();
bi.();
bi.();
score += 20;
();
score += 20;
;
};
}
When a wave is cleared, spawn the next one, faster and worth more.
int wave = 1;
void spawnWave() {
for (int r = 0; r < 4; r++)
for (int c = 0; c < 6; c++)
aliens.add(new Rectangle(60 + c*80, 60 + r*52, 36, 26));
}
void update() {
// ... everything so far ...
if (aliens.isEmpty()) {
wave++;
spawnWave();
}
for (Rectangle a : aliens) a.x += alienDir * (1 + wave);
} int wave = 1;
void spawnWave() {
for (int r = 0; r < 4; r++)
for (int c = 0; c < 6; c++)
aliens.add(new Rectangle(60 + c*80, 60 + r*52, 36, 26));
}
void update() {
// ... everything so far ...
if (aliens.isEmpty()) {
wave++;
spawnWave();
}
for (Rectangle a : aliens) a.x += alienDir * (1 + wave);
}
Lose when aliens reach your ship line, show a proper end screen, and tune the fun.
boolean gameOver = false;
void update() {
if (gameOver) return;
// ... everything ...
for (Rectangle a : aliens)
if (a.y + a.height > 560) gameOver = true;
}
// paintComponent:
if (gameOver) {
g.setColor(Color.WHITE);
g.setFont(new Font("Arial", Font.BOLD, 44));
g.drawString("GAME OVER", 160, 300);
g.setFont(new Font("Arial", Font.BOLD, 20));
g.drawString("Score: " + score + " Wave: " + wave, 200, 340);
} boolean gameOver = false;
void update() {
if (gameOver) return;
// ... everything ...
for (Rectangle a : aliens)
if (a.y + a.height > 560) gameOver = true;
}
// paintComponent:
if (gameOver) {
g.setColor(Color.WHITE);
g.setFont(new Font("Arial", Font.BOLD, 44));
g.drawString("GAME OVER", 160, 300);
g.setFont(new Font("Arial", Font.BOLD, 20));
g.drawString("Score: " + score + " Wave: " + wave, 200, 340);
}
if (e.getKeyCode() == KeyEvent.VK_SPACE
&& bullets.if (e.getKeyCode() == KeyEvent.VK_SPACE
&& bullets.() < () < )
bullets.add(new Rectangle(shipX + shipW/2 - 2, 578, 4, 12));)
bullets.add(new Rectangle(shipX + shipW/2 - 2, 578, 4, 12));
A triangle ship, Space-to-fire lasers in an ArrayList, a marching Space-Invaders alien wave that steps down at the walls, bullet-vs-alien collisions with scoring, plus win and lose states , one runnable file. Save as Main.javaMain.java, run javac Main.java && java Mainjavac Main.java && java Main, and play. Stuck? Compare your file against this.
// Complete Java Space Shooter. Run with: javac Main.java then java Main
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame("Defend Earth");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new GamePanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class GamePanel extends JPanel implements ActionListener, KeyListener {
Timer timer = new Timer(16, this);
int shipX = 280, shipW = 40;
boolean leftHeld, rightHeld;
int alienDir = 1, score = 0;
String state = "PLAY"; // PLAY / WIN / LOSE
List<Rectangle> bullets = new ArrayList<>();
List<Rectangle> aliens = new ArrayList<>();
public GamePanel() {
setPreferredSize(new Dimension(600, 650));
setBackground(new Color(10, 12, 26));
addKeyListener(this);
setFocusable(true);
spawnAliens();
timer.start();
}
void spawnAliens() {
aliens.clear();
for (int r = 0; r < 4; r++)
for (int c = 0; c < 6; c++)
aliens.add(new Rectangle(60 + c*80, 60 + r*52, 36, 26));
}
void reset() {
shipX = 280; score = 0; alienDir = 1; state = "PLAY";
bullets.clear(); spawnAliens();
}
public void actionPerformed(ActionEvent e) { update(); repaint(); }
void update() {
if (!state.equals("PLAY")) return;
if (leftHeld) shipX -= 6;
if (rightHeld) shipX += 6;
shipX = Math.max(0, Math.min(600 - shipW, shipX));
for (Rectangle b : bullets) b.y -= 9;
bullets.removeIf(b -> b.y + b.height < 0);
// march the wave, step down and reverse at a wall
boolean hitWall = false;
for (Rectangle a : aliens)
if (a.x + alienDir*2 < 0 || a.x + a.width + alienDir*2 > 600) hitWall = true;
if (hitWall) {
alienDir = -alienDir;
for (Rectangle a : aliens) a.y += 14;
} else {
for (Rectangle a : aliens) a.x += alienDir * 2;
}
// bullets vs aliens
for (int i = aliens.size() - 1; i >= 0; i--) {
Rectangle a = aliens.get(i);
for (int j = bullets.size() - 1; j >= 0; j--) {
if (a.intersects(bullets.get(j))) {
aliens.remove(i);
bullets.remove(j);
score += 10;
break;
}
}
}
// lose if the wave reaches the ship line, win when cleared
for (Rectangle a : aliens)
if (a.y + a.height >= 580) state = "LOSE";
if (aliens.isEmpty()) state = "WIN";
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(163, 88, 245));
for (Rectangle a : aliens) g.fillRect(a.x, a.y, a.width, a.height);
g.setColor(new Color(250, 204, 21));
for (Rectangle b : bullets) g.fillRect(b.x, b.y, b.width, b.height);
g.setColor(new Color(77, 217, 224));
int[] xs = { shipX + shipW/2, shipX, shipX + shipW };
int[] ys = { 580, 620, 620 };
g.fillPolygon(xs, ys, 3);
g.setColor(Color.WHITE);
g.setFont(new Font("Arial", Font.BOLD, 18));
g.drawString("Score: " + score, 16, 26);
if (!state.equals("PLAY")) {
g.setFont(new Font("Arial", Font.BOLD, 44));
g.drawString(state.equals("WIN") ? "EARTH SAVED!" : "GAME OVER", 130, 320);
g.setFont(new Font("Arial", Font.PLAIN, 18));
g.drawString("Press R to play again", 210, 360);
}
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT) leftHeld = true;
if (e.getKeyCode() == KeyEvent.VK_RIGHT) rightHeld = true;
if (e.getKeyCode() == KeyEvent.VK_SPACE && state.equals("PLAY"))
bullets.add(new Rectangle(shipX + shipW/2 - 2, 578, 4, 12));
if (e.getKeyCode() == KeyEvent.VK_R && !state.equals("PLAY")) reset();
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT) leftHeld = false;
if (e.getKeyCode() == KeyEvent.VK_RIGHT) rightHeld = false;
}
public void keyTyped(KeyEvent e) {}
}// Complete Java Space Shooter. Run with: javac Main.java then java Main
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame("Defend Earth");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new GamePanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class GamePanel extends JPanel implements ActionListener, KeyListener {
Timer timer = new Timer(16, this);
int shipX = 280, shipW = 40;
boolean leftHeld, rightHeld;
int alienDir = 1, score = 0;
String state = "PLAY"; // PLAY / WIN / LOSE
List<Rectangle> bullets = new ArrayList<>();
List<Rectangle> aliens = new ArrayList<>();
public GamePanel() {
setPreferredSize(new Dimension(600, 650));
setBackground(new Color(10, 12, 26));
addKeyListener(this);
setFocusable(true);
spawnAliens();
timer.start();
}
void spawnAliens() {
aliens.clear();
for (int r = 0; r < 4; r++)
for (int c = 0; c < 6; c++)
aliens.add(new Rectangle(60 + c*80, 60 + r*52, 36, 26));
}
void reset() {
shipX = 280; score = 0; alienDir = 1; state = "PLAY";
bullets.clear(); spawnAliens();
}
public void actionPerformed(ActionEvent e) { update(); repaint(); }
void update() {
if (!state.equals("PLAY")) return;
if (leftHeld) shipX -= 6;
if (rightHeld) shipX += 6;
shipX = Math.max(0, Math.min(600 - shipW, shipX));
for (Rectangle b : bullets) b.y -= 9;
bullets.removeIf(b -> b.y + b.height < 0);
// march the wave, step down and reverse at a wall
boolean hitWall = false;
for (Rectangle a : aliens)
if (a.x + alienDir*2 < 0 || a.x + a.width + alienDir*2 > 600) hitWall = true;
if (hitWall) {
alienDir = -alienDir;
for (Rectangle a : aliens) a.y += 14;
} else {
for (Rectangle a : aliens) a.x += alienDir * 2;
}
// bullets vs aliens
for (int i = aliens.size() - 1; i >= 0; i--) {
Rectangle a = aliens.get(i);
for (int j = bullets.size() - 1; j >= 0; j--) {
if (a.intersects(bullets.get(j))) {
aliens.remove(i);
bullets.remove(j);
score += 10;
break;
}
}
}
// lose if the wave reaches the ship line, win when cleared
for (Rectangle a : aliens)
if (a.y + a.height >= 580) state = "LOSE";
if (aliens.isEmpty()) state = "WIN";
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(163, 88, 245));
for (Rectangle a : aliens) g.fillRect(a.x, a.y, a.width, a.height);
g.setColor(new Color(250, 204, 21));
for (Rectangle b : bullets) g.fillRect(b.x, b.y, b.width, b.height);
g.setColor(new Color(77, 217, 224));
int[] xs = { shipX + shipW/2, shipX, shipX + shipW };
int[] ys = { 580, 620, 620 };
g.fillPolygon(xs, ys, 3);
g.setColor(Color.WHITE);
g.setFont(new Font("Arial", Font.BOLD, 18));
g.drawString("Score: " + score, 16, 26);
if (!state.equals("PLAY")) {
g.setFont(new Font("Arial", Font.BOLD, 44));
g.drawString(state.equals("WIN") ? "EARTH SAVED!" : "GAME OVER", 130, 320);
g.setFont(new Font("Arial", Font.PLAIN, 18));
g.drawString("Press R to play again", 210, 360);
}
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT) leftHeld = true;
if (e.getKeyCode() == KeyEvent.VK_RIGHT) rightHeld = true;
if (e.getKeyCode() == KeyEvent.VK_SPACE && state.equals("PLAY"))
bullets.add(new Rectangle(shipX + shipW/2 - 2, 578, 4, 12));
if (e.getKeyCode() == KeyEvent.VK_R && !state.equals("PLAY")) reset();
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT) leftHeld = false;
if (e.getKeyCode() == KeyEvent.VK_RIGHT) rightHeld = false;
}
public void keyTyped(KeyEvent e) {}
}