๐ Episode 1 ยท Beginner ยท No Java Experience Needed
Jump Into Java! Simple Platformer
Build your first real Java game: a player square that runs, jumps with gravity, and lands on platforms. You will learn classes, the game loop, keyboard input and collision, the foundations of every game you will ever make.
๐ถ Ages 11+โฑ๏ธ ~2 Hoursโ Javaโ Free
๐ฆ Variables๐๏ธ Classes๐ Game loopโจ๏ธ Keyboard input๐ Gravity๐งฑ Collision
Get Java installed and an empty project ready with a window that opens.
1Download and install the free JDK (Java Development Kit) from adoptium.net, pick the latest LTS version for your computer.
2Install a free code editor: VS Code (with the "Extension Pack for Java") or IntelliJ IDEA Community both work great.
3Make a new folder for this game and create a file called Main.java inside it.
4Type the starter code below, it opens a game window using Swing, the windowing toolkit built into Java.
5Run it (the โถ button in your editor, or javac Main.java then java Main in a terminal). A dark empty window should appear!
Main.java
import javax.swing.*;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame("My Java Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new GamePanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
๐จโ๐ง
Parent note: Everything used in this series is free and built into Java, no game engine or extra libraries to install. If java -version prints a version number in a terminal, the JDK is installed correctly.
โ๏ธ
Fill in the Blanks
+15 XP
The JDK stands for Java Kit. Our game window is created by the Swing class called .
๐ง
Knowledge Check
+15 XP
What does frame.setVisible(true) do?
ACompiles the Java code
BActually shows the window on screen, without it the window stays hidden
CMakes the window transparent
2
๐
The Game Panel & Game Loop
Create GamePanel with a timer that updates 60 times a second
Locked
๐ฏ
Goal for this step
Build the heart of every game: a panel that redraws itself about 60 times per second.
1Create a new file called GamePanel.java in the same folder.
2It extends JPanel (a drawable surface) and implements ActionListener (so the timer can call it).
3The Timer(16, this) fires an event every 16 ms, roughly 60 frames per second.
4Each tick we will move things in update(), then repaint() asks Swing to call paintComponent() again.
5Run it, you should see the dark blue sky colour filling the window.
GamePanel.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GamePanel extends JPanel implements ActionListener {
Timer timer = new Timer(16, this); // ~60 FPS
public GamePanel() {
setPreferredSize(new Dimension(800, 480));
setBackground(new Color(25, 30, 60)); // night sky
timer.start();
}
public void actionPerformed(ActionEvent e) {
update(); // move everything
repaint(); // then draw everything
}
void update() { /* movement goes here soon */ }
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// drawing goes here soon
}
}
๐ก
update() then repaint() is the classic game loop: move first, draw second. Every game in this series uses this exact pattern.
๐ง
Knowledge Check
+15 XP
Why do we use a Timer that fires every 16 milliseconds?
AIt saves the game every 16 milliseconds
BIt runs our update + repaint code about 60 times per second, creating smooth animation
CIt makes the game harder over time
3
๐
Draw the Player & Move Left/Right
Add player variables, keyboard input and horizontal movement
Locked
๐ฏ
Goal for this step
Get a player square on screen that runs left and right with the arrow keys.
1Add player variables at the top of GamePanel: position, size and speed.
2Implement KeyListener so the panel hears the keyboard, and remember which keys are held down with two booleans.
3In update(), move the player while a key is held.
4In paintComponent(), draw the player as an orange rectangle.
5Add addKeyListener(this); setFocusable(true); in the constructor or keys will be ignored!
GamePanel.java (additions)
int px = 100, py = 380; // player position
int pw = 34, ph = 44; // player size
int speed = 5;
boolean leftHeld, rightHeld;
void update() {
if (leftHeld) px -= speed;
if (rightHeld) px += speed;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(255, 119, 0));
g.fillRect(px, py, pw, ph);
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT) leftHeld = true;
if (e.getKeyCode() == KeyEvent.VK_RIGHT) rightHeld = true;
}
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) {}
โจ๏ธ
Code Challenge
+20 XP
Make the player move with the arrow keys. Fill in the blanks:
GamePanel.java
if (leftHeld) px speed;
if (rightHeld) px speed;
g.fillRect(, py, pw, ph);
๐ก Hint: Moving left means the x position gets smaller. fillRect draws at (x, y).
๐ง
Knowledge Check
+15 XP
Why do we track leftHeld/rightHeld booleans instead of moving inside keyPressed?
ABooleans use less memory
BSo movement is smooth every frame while the key is held, instead of stuttering with key-repeat
CJava does not allow movement inside keyPressed
4
๐
Gravity & Jumping
Add vertical velocity, gravity each frame, and a jump key
Locked
๐ฏ
Goal for this step
Make the player fall with gravity and jump with a satisfying arc when you press Up.
1Add a vertical velocity variable vy and a boolean onGround.
3Jumping is just setting vy to a big negative number, but only when standing on something!
4For now, treat the bottom of the window as the floor so you can test.
5Run it: you should fall, land, and jump with a smooth arc. That arc is real physics!
GamePanel.java (update method)
int vy = 0;
boolean onGround = false;
void update() {
if (leftHeld) px -= speed;
if (rightHeld) px += speed;
vy += 1; // gravity accelerates you down
py += vy; // apply velocity
// temporary floor at the bottom of the window
if (py + ph >= 480) {
py = 480 - ph;
vy = 0;
onGround = true;
}
}
public void keyPressed(KeyEvent e) {
// ... existing arrow keys ...
if (e.getKeyCode() == KeyEvent.VK_UP && onGround) {
vy = -16; // launch upward!
onGround = false;
}
}
๐ก
Bigger gravity (+2) feels heavy and snappy; a stronger jump (-20) floats higher. Play with the numbers until it feels like your game.
โ๏ธ
Fill in the Blanks
+15 XP
Gravity works by adding to the velocity: vy += 1, then adding velocity to the position: py += . To jump we set vy to a number, and we only allow it when is true.
๐ง
Knowledge Check
+15 XP
What would happen if we let the player jump when onGround is false?
ANothing changes
BThe player could jump again in mid-air, infinite flying!
CThe game would crash
5
๐งฑ
Platforms & Collision
Add an array of platforms and land on top of them
Locked
๐ฏ
Goal for this step
Replace the temporary floor with real platforms the player can land on and jump between.
1Java has a perfect class for this: java.awt.Rectangle, it even has an intersects() method for collision!
2Create an array of platform rectangles: a ground piece plus floating ledges.
3After applying vy, check each platform: if the player overlaps one while falling, snap on top of it.
4Draw every platform in green in paintComponent.
5Delete the temporary window-bottom floor from the last step and go platform hopping!
GamePanel.java
Rectangle[] platforms = {
new Rectangle(0, 440, 800, 40), // ground
new Rectangle(150, 340, 140, 16),
new Rectangle(380, 260, 140, 16),
new Rectangle(610, 180, 140, 16)
};
void update() {
// ... movement + gravity from before ...
onGround = false;
Rectangle player = new Rectangle(px, py, pw, ph);
for (Rectangle plat : platforms) {
if (player.intersects(plat) && vy >= 0
&& py + ph - vy <= plat.y) {
py = plat.y - ph; // snap on top
vy = 0;
onGround = true;
}
}
}
// in paintComponent:
// g.setColor(new Color(6, 214, 160));
// for (Rectangle plat : platforms) g.fillRect(plat.x, plat.y, plat.width, plat.height);
โจ๏ธ
Code Challenge
+20 XP
Complete the collision check that lands the player on a platform:
GamePanel.java
if (player.(plat) && vy >= 0) {
py = plat.y - ; // stand on top
vy = ;
onGround = true;
}
๐ก Hint: Rectangle has a built-in overlap method. To stand ON a platform, the player bottom (py + height) must equal the platform top.
๐ง
Knowledge Check
+15 XP
Why do we only land when vy >= 0?
ASo we pass through platforms from below while jumping up, and only land when falling down
BBecause negative numbers crash Java
CTo make the player move faster
6
๐
Coins, Score & Winning
Collect coins on the platforms and show a win screen
Locked
๐ฏ
Goal for this step
Add collectable coins, a score counter, and a WIN screen when you grab them all.
1Store coins in an ArrayList<Rectangle> so we can remove them when collected.
2Place one coin above each floating platform.
3Each frame, if the player intersects a coin: remove it and add 10 to score.
4Draw the score top-left with g.drawString(), and coins as gold squares.
5When the list is empty, draw a giant YOU WIN message. You finished your first Java game!
GamePanel.java
java.util.List<Rectangle> coins = new java.util.ArrayList<>(java.util.List.of(
new Rectangle(205, 300, 18, 18),
new Rectangle(435, 220, 18, 18),
new Rectangle(665, 140, 18, 18)));
int score = 0;
void update() {
// ... previous code ...
coins.removeIf(c -> {
if (new Rectangle(px, py, pw, ph).intersects(c)) { score += 10; return true; }
return false;
});
}
protected void paintComponent(Graphics g) {
// ... player + platforms ...
g.setColor(new Color(255, 209, 102));
for (Rectangle c : coins) g.fillRect(c.x, c.y, c.width, c.height);
g.setColor(Color.WHITE);
g.setFont(new Font("Arial", Font.BOLD, 18));
g.drawString("Score: " + score, 16, 26);
if (coins.isEmpty()) {
g.setFont(new Font("Arial", Font.BOLD, 48));
g.drawString("YOU WIN!", 290, 240);
}
}
๐ก
Want more? Add a falling-off-screen respawn (if (py > 480) px = 100;), more platforms, or a timer to beat. This is YOUR game now.
โ๏ธ
Fill in the Blanks
+15 XP
We use an instead of an array for coins because we need to items while the game runs. The text on screen is drawn with g..
๐ง
Knowledge Check
+15 XP
You finished a platformer with a game loop, gravity, collision and scoring. Which part decides how often everything updates?
ApaintComponent
BThe Swing Timer firing every 16 ms
CThe JFrame
๐๐๐ฎโจ๐
Workshop Complete!
You built a real platformer in pure Java, game loop, gravity, jumping and collision, all coded by you. Episode 2 turns you loose on Brick Breaker!