Player movement, gravity and jumping, real platform collision with java.awt.Rectangle, collectable coins, a score and a win screen , one runnable file. Save it as Main.javaMain.java, run javac Main.java && java Mainjavac Main.java && java Main, and play. Stuck on a step? Compare your file against this.
// Complete Java platformer. Both classes are in one file so it runs with:
// javac Main.java then java Main
// In the workshop you put GamePanel in its own GamePanel.java, which works too.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
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);
}
}
class GamePanel extends JPanel implements ActionListener, KeyListener {
Timer timer = new Timer(16, this); // ~60 FPS
int px = 100, py = 380; // player position
int pw = 34, ph = 44; // player size
int speed = 5, vy = 0;
boolean leftHeld, rightHeld, onGround;
boolean won = false;
int score = 0;
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)
};
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)));
public GamePanel() {
setPreferredSize(new Dimension(800, 480));
setBackground(new Color(25, 30, 60));
addKeyListener(this);
setFocusable(true);
timer.start();
}
public void actionPerformed(ActionEvent e) {
update();
repaint();
}
void update() {
if (won) return;
if (leftHeld) px -= speed;
if (rightHeld) px += speed;
if (px < 0) px = 0;
if (px + pw > 800) px = 800 - pw;
vy += 1; // gravity
py += vy;
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;
}
}
coins.removeIf(c -> {
if (new Rectangle(px, py, pw, ph).intersects(c)) { score += 10; return true; }
return false;
});
if (coins.isEmpty()) won = true;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(6, 214, 160));
for (Rectangle plat : platforms) g.fillRect(plat.x, plat.y, plat.width, plat.height);
g.setColor(new Color(255, 209, 102));
for (Rectangle c : coins) g.fillRect(c.x, c.y, c.width, c.height);
g.setColor(new Color(255, 119, 0));
g.fillRect(px, py, pw, ph);
g.setColor(Color.WHITE);
g.setFont(new Font("Arial", Font.BOLD, 18));
g.drawString("Score: " + score, 16, 26);
if (won) {
g.setFont(new Font("Arial", Font.BOLD, 56));
g.drawString("YOU WIN!", 250, 250);
}
}
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_UP && onGround) {
vy = -16;
onGround = false;
}
}
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 platformer. Both classes are in one file so it runs with:
// javac Main.java then java Main
// In the workshop you put GamePanel in its own GamePanel.java, which works too.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
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);
}
}
class GamePanel extends JPanel implements ActionListener, KeyListener {
Timer timer = new Timer(16, this); // ~60 FPS
int px = 100, py = 380; // player position
int pw = 34, ph = 44; // player size
int speed = 5, vy = 0;
boolean leftHeld, rightHeld, onGround;
boolean won = false;
int score = 0;
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)
};
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)));
public GamePanel() {
setPreferredSize(new Dimension(800, 480));
setBackground(new Color(25, 30, 60));
addKeyListener(this);
setFocusable(true);
timer.start();
}
public void actionPerformed(ActionEvent e) {
update();
repaint();
}
void update() {
if (won) return;
if (leftHeld) px -= speed;
if (rightHeld) px += speed;
if (px < 0) px = 0;
if (px + pw > 800) px = 800 - pw;
vy += 1; // gravity
py += vy;
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;
}
}
coins.removeIf(c -> {
if (new Rectangle(px, py, pw, ph).intersects(c)) { score += 10; return true; }
return false;
});
if (coins.isEmpty()) won = true;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(6, 214, 160));
for (Rectangle plat : platforms) g.fillRect(plat.x, plat.y, plat.width, plat.height);
g.setColor(new Color(255, 209, 102));
for (Rectangle c : coins) g.fillRect(c.x, c.y, c.width, c.height);
g.setColor(new Color(255, 119, 0));
g.fillRect(px, py, pw, ph);
g.setColor(Color.WHITE);
g.setFont(new Font("Arial", Font.BOLD, 18));
g.drawString("Score: " + score, 16, 26);
if (won) {
g.setFont(new Font("Arial", Font.BOLD, 56));
g.drawString("YOU WIN!", 250, 250);
}
}
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_UP && onGround) {
vy = -16;
onGround = false;
}
}
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) {}
}