โ˜• My First Java Game ยท Episode 3 of 7 ยท See All Episodes
๐Ÿ‘พ Episode 3 ยท Improver ยท Builds on Episodes 1-2

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.

๐Ÿ‘ถ Ages 11+ โฑ๏ธ ~2 Hours โ˜• Java โœ“ Free
๐Ÿš€ Player ship ๐Ÿ”ซ Shooting ๐Ÿ“‹ ArrayLists ๐Ÿ‘พ Enemy waves ๐Ÿงน Object cleanup ๐Ÿ“ˆ Difficulty ramp
โญ
0 XP
Level 1
๐Ÿ”ฅ0
Your Progress 0 / 6 steps
1
๐Ÿš€
Setup & the Player Ship
New project, then a ship that strafes along the bottom
Active
๐ŸŽฏ
Goal for this step

Set up the project and get your ship sliding along the bottom of space.

  • 1New folder SpaceShooter, same Main.java + GamePanel.java template (600ร—640 window, near-black background).
  • 2Ship variables: shipX centred, width 40, sitting at y = 580.
  • 3Arrow keys strafe left/right, clamped to the screen, you have done this twice now, so it should feel easy!
  • 4Draw the ship as a triangle using fillPolygon, three points: nose and two wing tips.
  • 5Sprinkle some stars: draw 40 small white dots at random-but-fixed positions.
GamePanel.java
    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);
    }
โœ๏ธ
Fill in the Blanks
+15 XP
fillPolygon draws a shape from arrays of points, our ship triangle uses points. The ship is clamped with Math.max and Math. just like the Breakout paddle.
๐Ÿง 
Knowledge Check
+15 XP
The xs array starts with shipX + shipW/2. What point of the ship is that?
AThe left wing tip
BThe nose, horizontally centred on the ship
CThe engine
2
๐Ÿ”ซ
Firing Lasers
An ArrayList of bullets that fly up the screen
Locked
๐ŸŽฏ
Goal for this step

Press Space to fire lasers that travel up and disappear off screen.

  • 1Bullets come and go constantly, so an array will not do, use ArrayList<Rectangle> bullets.
  • 2On Space keyPressed: add a new Rectangle at the ship nose (width 4, height 12).
  • 3In update(), move every bullet up 9 pixels per frame.
  • 4Remove bullets that leave the top with removeIf, never let dead objects pile up, or the game slowly chokes!
  • 5Draw them as bright yellow slivers.
GamePanel.java
    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);
๐Ÿ’ก
removeIf with a lambda is the tidy modern way to delete from a list while looping, no crashes, no leftover objects eating memory.
โŒจ๏ธ
Code Challenge
+20 XP
Make the lasers fly and clean themselves up:
GamePanel.java
for (Rectangle b : bullets) b.y  9;
bullets.(b -> b.y + b.height < );
๐Ÿ’ก Hint: Up the screen means y gets smaller. The cleanup method takes a condition; off-screen means fully above y = 0.
๐Ÿง 
Knowledge Check
+15 XP
Why must off-screen bullets be removed from the list?
AThey could hit aliens from behind
BOtherwise the list grows forever and the game gradually slows down
CJava limits lists to 100 items
3
๐Ÿ‘พ
The Alien Wave
Spawn a marching grid of invaders
Locked
๐ŸŽฏ
Goal for this step

Fill the sky with aliens that march side-to-side and step down like Space Invaders.

  • 1Aliens also live in an ArrayList<Rectangle>, spawn a 6ร—4 grid of 36ร—26 aliens in the constructor.
  • 2One shared direction: int alienDir = 1;, every frame each alien moves alienDir * 2 horizontally.
  • 3If ANY alien touches a side wall, flip alienDir and move the whole wave DOWN 14 pixels.
  • 4Do the wall check first with a flag, then apply movement, otherwise half the wave turns and half does not!
  • 5Draw them in classic green.
GamePanel.java
    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;
    }
โœ๏ธ
Fill in the Blanks
+15 XP
The whole wave shares one direction variable called . When any alien touches a wall we flip it and every alien steps by 14 pixels.
๐Ÿง 
Knowledge Check
+15 XP
Why check the wall with a flag BEFORE moving the aliens?
AIt is faster
BSo the entire wave turns together on the same frame instead of splitting apart
CJava evaluates loops backwards
4
๐Ÿ’ฅ
Blasting Aliens
Bullet-alien collision with double removal and score
Locked
๐ŸŽฏ
Goal for this step

Lasers destroy aliens on contact, with score, and both objects removed cleanly.

  • 1Loop bullets with an Iterator, and for each bullet loop the aliens.
  • 2On intersect: remove the alien, remove the bullet, score += 20, and stop checking that bullet (it is gone!).
  • 3Removing from a list you are looping is the classic beginner crash, the Iterator pattern below is the safe way.
  • 4Draw the score top-left, same as always.
GamePanel.java (update)
    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 you see ConcurrentModificationException, you removed from a list inside a for-each loop. Always use the iteratorโ€™s own remove() like above.
โŒจ๏ธ
Code Challenge
+20 XP
Complete the safe double-removal when a laser hits an alien:
GamePanel.java
if (b.intersects(a)) {
    ai.();
    bi.();
    score += 20;
    ;
}
๐Ÿ’ก Hint: Both iterators have a removal method, and we must stop checking a bullet that no longer exists.
๐Ÿง 
Knowledge Check
+15 XP
What does the break after a hit prevent?
AThe alien respawning
BOne bullet destroying several aliens in the same frame after it was already removed
CThe score going negative
5
๐Ÿ“ˆ
Waves & Rising Difficulty
New waves spawn faster and march quicker
Locked
๐ŸŽฏ
Goal for this step

When a wave is cleared, spawn the next one, faster and worth more.

  • 1Add int wave = 1; and move the grid-spawning code into a method spawnWave().
  • 2In update(): if aliens.isEmpty(), wave++, spawnWave().
  • 3Make speed scale with the wave: aliens move alienDir * (1 + wave) pixels.
  • 4Score per kill can scale too: score += 20 * wave;.
  • 5Show Wave: 3 next to the score, players love seeing how far they got.
GamePanel.java
    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);
    }
๐Ÿ’ก
Pulling repeated code into a method like spawnWave() is called refactoring, the moment you need something twice, make it a method.
โœ๏ธ
Fill in the Blanks
+15 XP
When the list is empty we increase and call (). Alien speed scales as alienDir * (1 + ).
๐Ÿง 
Knowledge Check
+15 XP
Why put the grid-spawn code in its own method?
AMethods run faster than loose code
BWe need it at the start AND after every cleared wave, write once, call twice
CpaintComponent cannot contain loops
6
โ˜ ๏ธ
Game Over & Polish
Invasion line, game-over screen and final balance
Locked
๐ŸŽฏ
Goal for this step

Lose when aliens reach your ship line, show a proper end screen, and tune the fun.

  • 1Add boolean gameOver = false;. If any alienโ€™s bottom passes y = 560, the invasion succeeded: gameOver = true.
  • 2Also end the game if an alien rectangle intersects the shipโ€™s bounding box.
  • 3When gameOver: freeze update() with an early return and draw GAME OVER + score + wave reached.
  • 4Balance pass: bullet speed vs alien speed vs fire rate. Try limiting shots: only fire if bullets.size() < 3, suddenly aiming matters!
  • 5Optional flourish: give aliens a chance to drop bombs, a second ArrayList moving down. You already know every technique needed. That is the point. ๐Ÿš€
GamePanel.java
    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);
    }
โŒจ๏ธ
Code Challenge
+20 XP
Limit the player to 3 lasers on screen at once:
GamePanel.java
if (e.getKeyCode() == KeyEvent.VK_SPACE
        && bullets.() < )
    bullets.add(new Rectangle(shipX + shipW/2 - 2, 578, 4, 12));
๐Ÿ’ก Hint: Lists report how many items they hold with a method; we allow firing only under the limit.
๐Ÿง 
Knowledge Check
+15 XP
Limiting bullets to 3 on screen makes the gameโ€ฆ
AEasier, because bullets are stronger
BMore skilful, you must aim instead of holding down fire
CSlower to render
๐ŸŽ‰๐Ÿ†๐ŸŽฎโœจ๐ŸŽ‰
Workshop Complete!
Bullets, waves, spawning, cleanup, you now think in lists of objects, which is how real games are built. Episode 4: the game that started it all, Pong.
0
Total XP
1
Level
0
Best Streak
0%
Accuracy
โ–ถ Episode 4: Pong Classic โ†’
โญ View My Progress & Certificates

This workshop was free and took many hours to build. If it helped you learn something new, consider supporting the project.

☕ Support on Ko-fi