Recreate the 1972 legend: two paddles, one ball, first to 7. Then teach the right paddle to play by itself, your first game AI, plus proper game states (menu, playing, game over).
๐ถ Ages 11+โฑ๏ธ ~1.5 Hoursโ Javaโ Free
๐ Two paddles๐ค Simple AI๐ฏ Serve & rally๐ข Score to win๐ฌ Game statesโ๏ธ Balancing
When the ball exits the LEFT side, player scores a point. The match ends when a score reaches .
๐ง
Knowledge Check
+15 XP
Why serve toward the player who just lost the point?
AIt punishes the loser
BIt is fair, the scorer should not immediately receive an easy attack
CThe ball must alternate sides by law
4
๐ค
Computer Opponent
An AI paddle that tracks the ball, imperfectly
Locked
๐ฏ
Goal for this step
Replace player 2 with a computer that chases the ball but can be beaten.
1Add boolean vsComputer = true;, when on, ignore Up/Down and let the AI drive p2Y.
2Dead-simple AI: if the paddle centre is above the ball centre, move down; if below, move up.
3A perfect AI is unbeatable and boring. Give it a reaction dead-zone: only react when the gap is bigger than 12 pixels.
4And a speed limit: the AI paddle moves 5 while you move 6, you can outpace it with clever angles.
5Playtest: can you beat it 7-3? Tune deadZone and aiSpeed until it is a fair fight.
GamePanel.java
boolean vsComputer = true;
int aiSpeed = 5, deadZone = 12;
void update() {
// ...
if (vsComputer) {
int padCentre = p2Y + 45;
int ballCentre = by + bs/2;
if (padCentre < ballCentre - deadZone) p2Y += aiSpeed;
if (padCentre > ballCentre + deadZone) p2Y -= aiSpeed;
} else {
if (upHeld) p2Y -= 6;
if (downHeld) p2Y += 6;
}
}
๐ก
This tiny "chase with flaws" pattern is genuinely how a LOT of game AI works: perfect logic, deliberately weakened until it is fun.
โจ๏ธ
Code Challenge
+20 XP
Complete the AI chase logic:
GamePanel.java
if (padCentre < ballCentre - deadZone) p2Y aiSpeed;
if (padCentre > ballCentre + deadZone) p2Y aiSpeed;
๐ก Hint: If the paddle centre is ABOVE the ball (smaller y), the paddle must move DOWN (y grows).
๐ง
Knowledge Check
+15 XP
Why give the AI a dead-zone and a speed limit?
ATo save CPU power
BA flawless AI cannot be beaten, deliberate weakness is what makes it fun
CSwing timers require it
5
๐ฌ
Game States & Menu
MENU โ PLAYING โ GAME_OVER with clean switching
Locked
๐ฏ
Goal for this step
Add a title screen and restart flow using a proper state variable.
1One variable runs the show: String state = "MENU"; (or an enum if you are feeling fancy).
2update(): only move things when state equals "PLAYING".
3paintComponent(): draw the court always; draw the menu text over it in MENU; the winner banner in GAME_OVER.
4Keys: in MENU press 1 for vs-computer or 2 for two-player; in GAME_OVER press R to reset scores and return to MENU.
5This MENU/PLAYING/GAME_OVER pattern is in literally every game you will ever write. Learn it here, reuse it forever.
GamePanel.java
String state = "MENU";
void update() {
if (!state.equals("PLAYING")) return;
// ... all game code ...
if (score1 == 7 || score2 == 7) state = "GAME_OVER";
}
public void keyPressed(KeyEvent e) {
if (state.equals("MENU")) {
if (e.getKeyChar() == '1') { vsComputer = true; state = "PLAYING"; }
if (e.getKeyChar() == '2') { vsComputer = false; state = "PLAYING"; }
} else if (state.equals("GAME_OVER") && e.getKeyChar() == 'r') {
score1 = 0; score2 = 0; serve(1);
state = "MENU";
}
// ... held-key booleans ...
}
โ๏ธ
Fill in the Blanks
+15 XP
Our three states are MENU, and GAME_OVER. Gameplay code only runs when state equals , and pressing after a match returns to the menu.
๐ง
Knowledge Check
+15 XP
What is the advantage of one state variable over lots of booleans like inMenu, isPlaying, hasEnded?
AStrings are faster than booleans
BThe game can only ever be in ONE state, impossible to be in the menu and playing at once
CIt uses less disk space
6
โจ
Juice & Final Polish
Screen flash on score, sound beeps and tuning
Locked
๐ฏ
Goal for this step
Add the little touches that make Pong feel alive, then ship it.
1Score flash: set int flash = 12; when someone scores; while flash > 0, decrement it and paint the background slightly brighter.
2Beep! Java can make the classic blip with Toolkit.getDefaultToolkit().beep(); on every paddle hit.
3Show FIRST TO 7 and control hints on the menu screen so nobody has to guess.
4Final balance pass: rally speed-up (+1 per hit) vs paddle speed (6) vs AI (5). Adjust until matches last 2-3 minutes.
5Show a friend. Best-of-three. Defend your title. ๐
GamePanel.java
int flash = 0;
// when a point is scored:
// score2++; serve(-1); flash = 12;
void update() {
// ...
if (flash > 0) flash--;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (flash > 0) {
g.setColor(new Color(255, 255, 255, 40));
g.fillRect(0, 0, 800, 500);
}
// ... everything else ...
}
๐ก
Game developers call this juice, flashes, shakes, beeps. It costs a few lines and doubles how good a game feels.
โจ๏ธ
Code Challenge
+20 XP
Make the score flash fade out over time:
GamePanel.java
// when scoring:
flash = ;
// each frame:
if (flash > 0) flash;
๐ก Hint: Set the counter to its full value, then count down by one per frame.
๐ง
Knowledge Check
+15 XP
You built Pong with AI and game states. Which pattern from this episode appears in almost every commercial game?
AThe dashed centre line
BThe MENU โ PLAYING โ GAME_OVER state machine
CThe beep sound
๐๐๐ฎโจ๐
Workshop Complete!
Two paddles, an AI opponent and real game states, Pong looks simple but you just used every core game-dev pattern. Next: the three-part RPG Quest finale!