โ˜• My First Java Game ยท Episode 5 of 7 ยท See All Episodes
๐Ÿ—ก๏ธ Episode 5 ยท Big Project ยท RPG Part 1 of 3

RPG Quest
Part 1: The Hero

The three-part finale begins! Design your hero with real class design, stats, inventory, levelling, and build a tile-map world to walk around. This part is all about the architecture that makes big games possible.

๐Ÿ‘ถ Ages 11+ โฑ๏ธ ~2 Hours โ˜• Java โœ“ Free
๐Ÿ—๏ธ Class design ๐Ÿ“Š Stats & levelling ๐ŸŽ’ Inventory ๐Ÿ—บ๏ธ Tile maps ๐Ÿšถ Grid movement ๐Ÿงฑ Wall collision
โญ
0 XP
Level 1
๐Ÿ”ฅ0
Your Progress 0 / 6 steps
1
๐Ÿ—๏ธ
Design Before Code
Plan the classes: Hero, Item, GamePanel, on paper first
Active
๐ŸŽฏ
Goal for this step

Sketch the architecture so the next three workshops slot together perfectly.

  • 1Big games die without a plan. Ours: Hero (stats + inventory), Item (things you carry), GamePanel (world + loop), and later Monster and Battle.
  • 2Each class has ONE job. Hero knows nothing about drawing; GamePanel knows nothing about damage maths. This is called separation of concerns.
  • 3Create the project folder RpgQuest with Main.java + GamePanel.java (700ร—560 window, the usual template).
  • 4Create two empty files ready for the next steps: Hero.java and Item.java.
  • 5Seriously, grab paper and draw three boxes with arrows before continuing. Two minutes now saves hours later.
๐Ÿ’ก
Professional studios draw this exact diagram (a class diagram) before writing any code on a new game.
โœ๏ธ
Fill in the Blanks
+15 XP
Giving each class ONE clear job is called separation of . Our hero data lives in .java, while drawing and the game loop live in GamePanel.java.
๐Ÿง 
Knowledge Check
+15 XP
Why should the Hero class NOT contain drawing code?
ADrawing is too slow for heroes
BOne job per class, Hero manages stats/inventory, GamePanel draws. Each can change without breaking the other
CJava forbids Graphics outside panels
2
๐Ÿฆธ
The Hero Class
Name, HP, attack, gold, XP, with constructor and methods
Locked
๐ŸŽฏ
Goal for this step

Write a Hero class holding all the character data, plus safe methods to change it.

  • 1Fields: name, maxHp, hp, attack, gold, xp, level, all private (data protection!).
  • 2A constructor sets the starting values from the name you pass in.
  • 3Methods instead of raw field access: takeDamage(int) clamps HP at 0; heal(int) clamps at maxHp; isAlive() returns hp > 0.
  • 4This is encapsulation, the Hero controls its own rules, so HP can never go negative by accident.
Hero.java
public class Hero {
    private String name;
    private int maxHp = 30, hp = 30;
    private int attack = 5;
    private int gold = 0, xp = 0, level = 1;

    public Hero(String name) { this.name = name; }

    public void takeDamage(int amount) {
        hp = Math.max(0, hp - amount);
    }
    public void heal(int amount) {
        hp = Math.min(maxHp, hp + amount);
    }
    public boolean isAlive() { return hp > 0; }

    public int getHp() { return hp; }
    public int getMaxHp() { return maxHp; }
    public int getAttack() { return attack; }
    public String getName() { return name; }
}
โŒจ๏ธ
Code Challenge
+20 XP
Write the two clamped methods that protect the heroโ€™s HP:
Hero.java
public void takeDamage(int amount) {
    hp = Math.(0, hp - amount);
}
public void heal(int amount) {
    hp = Math.(maxHp, hp + amount);
}
๐Ÿ’ก Hint: Damage must never push HP below zero; healing must never push it above maxHp.
๐Ÿง 
Knowledge Check
+15 XP
The fields are private and changed only through methods. What does this prevent?
AOther classes setting hp = -50 or gold = 999999 directly, bypassing the game rules
BThe hero being drawn twice
CSlow compilation
3
๐ŸŽ’
Items & Inventory
An Item class and the heroโ€™s ArrayList of loot
Locked
๐ŸŽฏ
Goal for this step

Create items (potions, keys, swords) and let the hero carry and use them.

  • 1Item is small: a name, a type ("potion", "key", "weapon") and a power number.
  • 2Hero gains List<Item> inventory = new ArrayList<>(); plus pickUp(Item) and useItem(String name).
  • 3useItem finds the first item with that name: a potion heals by its power and is removed; a weapon adds its power to attack and is removed.
  • 4Test in main(): create a hero, damage them 20, pick up a Potion(12), use it, print HP, should read 22/30.
Item.java + Hero.java
public class Item {
    String name, type;
    int power;
    public Item(String name, String type, int power) {
        this.name = name; this.type = type; this.power = power;
    }
}

// inside Hero:
private java.util.List<Item> inventory = new java.util.ArrayList<>();

public void pickUp(Item item) { inventory.add(item); }

public boolean useItem(String itemName) {
    for (Item it : inventory) {
        if (it.name.equals(itemName)) {
            if (it.type.equals("potion")) heal(it.power);
            if (it.type.equals("weapon")) attack += it.power;
            inventory.remove(it);
            return true;
        }
    }
    return false;   // did not have one
}
โœ๏ธ
Fill in the Blanks
+15 XP
The inventory is a List of objects. Using a potion calls the heroโ€™s method and then s the item from the list.
๐Ÿง 
Knowledge Check
+15 XP
Why does useItem return a boolean?
AAll Java methods must return something
BSo the caller knows whether the hero actually had that item, no potion, no heal
CBooleans are needed for ArrayLists
4
๐Ÿ—บ๏ธ
The Tile-Map World
Draw a world from a 2D int array: grass, walls, water
Locked
๐ŸŽฏ
Goal for this step

Build a visible world out of tiles, the same technique as Zelda and Pokรฉmon.

  • 1The world is an int[][] map, each number is a tile type: 0 grass, 1 wall, 2 water, 3 chest.
  • 2Our map is 14 rows ร— 17 columns of 40-pixel tiles (making 680ร—560).
  • 3Write the map by hand as a literal array, you are drawing a level with numbers!
  • 4paintComponent: nested loop, pick a colour per tile type, fillRect each 40ร—40 square.
  • 5Design your own layout, put walls around the edge, a lake, and a chest room.
GamePanel.java
    int TILE = 40;
    int[][] map = {
        {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
        {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,1},
        {1,0,1,1,0,0,0,2,2,2,0,0,1,1,0,0,1},
        {1,0,1,0,0,0,0,2,2,2,0,0,0,1,0,0,1},
        {1,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1},
        {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
        // ... build yours 14 rows tall!
    };

    // paintComponent:
    for (int r = 0; r < map.length; r++)
        for (int c = 0; c < map[0].length; c++) {
            switch (map[r][c]) {
                case 0 -> g.setColor(new Color(52, 120, 62));
                case 1 -> g.setColor(new Color(90, 90, 100));
                case 2 -> g.setColor(new Color(50, 90, 180));
                case 3 -> g.setColor(new Color(212, 175, 55));
            }
            g.fillRect(c*TILE, r*TILE, TILE, TILE);
        }
โŒจ๏ธ
Code Challenge
+20 XP
Convert a tileโ€™s row/column into pixels on screen:
GamePanel.java
g.fillRect(*TILE, *TILE, TILE, TILE);
๐Ÿ’ก Hint: Columns run across (x direction); rows run down (y direction).
๐Ÿง 
Knowledge Check
+15 XP
In a tile map, what does map[3][7] == 2 mean?
AThere are 2 tiles at that spot
BThe tile at row 3, column 7 is water (type 2)
CThe map is 3ร—7 tiles
5
๐Ÿšถ
Walking the World
Grid movement that respects walls and water
Locked
๐ŸŽฏ
Goal for this step

Move the hero tile-by-tile with arrow keys, blocked by walls and water.

  • 1The heroโ€™s position is now a grid position: heroRow, heroCol, not pixels!
  • 2On keyPressed (not held, RPGs step once per press), work out the target tile.
  • 3Only move if the target tile is walkable: type 0 or 3. Walls (1) and water (2) block you.
  • 4Draw the hero as a red square at heroCol*TILE, heroRow*TILE, slightly smaller than the tile so the grass peeks out.
  • 5Walk around your world. Blocked by your own lake? That is level design working!
GamePanel.java
    int heroRow = 1, heroCol = 1;
    Hero hero = new Hero("Aria");

    boolean walkable(int r, int c) {
        if (r < 0 || r >= map.length || c < 0 || c >= map[0].length)
            return false;
        return map[r][c] == 0 || map[r][c] == 3;
    }

    public void keyPressed(KeyEvent e) {
        int r = heroRow, c = heroCol;
        if (e.getKeyCode() == KeyEvent.VK_UP)    r--;
        if (e.getKeyCode() == KeyEvent.VK_DOWN)  r++;
        if (e.getKeyCode() == KeyEvent.VK_LEFT)  c--;
        if (e.getKeyCode() == KeyEvent.VK_RIGHT) c++;
        if (walkable(r, c)) { heroRow = r; heroCol = c; }
        repaint();
    }
โœ๏ธ
Fill in the Blanks
+15 XP
RPG movement is stored as a grid position: heroRow and . Before stepping we check (r, c), which returns false for walls and .
๐Ÿง 
Knowledge Check
+15 XP
Why check r < 0 || r >= map.length first in walkable()?
ATo make water solid
BReading outside the array bounds crashes Java, check the edges before reading the tile
CTo speed up walking
6
๐Ÿ’ฐ
Chests, HUD & Saving the Hero
Open chests for loot and show hero stats on screen
Locked
๐ŸŽฏ
Goal for this step

Loot chests into your inventory and display a proper RPG HUD.

  • 1Standing on a chest tile (3): give the hero loot, hero.pickUp(new Item("Potion","potion",12)); gold += 25;, then turn the tile to grass (0) so it cannot be looted twice.
  • 2Draw the HUD in a dark strip: name, HP bar (red background, green foreground scaled by hp/maxHp), gold and inventory count.
  • 3An HP bar beats an HP number, players read bars instantly.
  • 4Congratulations, Part 1 complete! You have a hero, a world, and loot. Part 2 fills the world with monsters and turn-based combat.
GamePanel.java
    // after a successful move:
    if (map[heroRow][heroCol] == 3) {
        hero.pickUp(new Item("Potion", "potion", 12));
        map[heroRow][heroCol] = 0;    // chest opened
    }

    // HUD in paintComponent:
    g.setColor(new Color(0, 0, 0, 170));
    g.fillRect(0, 0, 700, 34);
    g.setColor(Color.RED);
    g.fillRect(90, 10, 120, 14);
    g.setColor(new Color(6, 214, 160));
    g.fillRect(90, 10, 120 * hero.getHp() / hero.getMaxHp(), 14);
    g.setColor(Color.WHITE);
    g.drawString(hero.getName(), 12, 22);
โŒจ๏ธ
Code Challenge
+20 XP
Scale the HP bar to the heroโ€™s current health:
GamePanel.java
g.fillRect(90, 10, 120 * hero.() / hero.(), 14);
๐Ÿ’ก Hint: Full width 120 times current HP divided by maximum HP. The fields are private, use the getter methods.
๐Ÿง 
Knowledge Check
+15 XP
After looting, we set the chest tile to 0. What bug does this prevent?
AThe hero drowning
BStanding on the chest again and looting infinite potions
CThe map failing to draw
๐ŸŽ‰๐Ÿ†๐ŸŽฎโœจ๐ŸŽ‰
Workshop Complete!
A hero with stats, an inventory, and a world with walls, the skeleton of every RPG ever made. Part 2 adds monsters and combat!
0
Total XP
1
Level
0
Best Streak
0%
Accuracy
โ–ถ Part 2: Monsters & Combat โ†’
โญ 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