RPG Game System with Interfaces and Inheritance
Complete game system demonstrating interfaces, abstract classes, inheritance, and polymorphism
SpacialElement (Base Class)
Base class for all elements that exist in the game world.
- name: Name of the element (protected)
- x: X coordinate on the map (protected)
- y: Y coordinate on the map (protected)
- SpacialElement(String name, int x, int y): Constructor to place element at coordinates
- Implements
Movableinterface - All game elements inherit from this class
Movable (Interface)
Interface for elements that can move in four directions.
- goUp(int speed): Move up by speed units
- goDown(int speed): Move down by speed units
- goRight(int speed): Move right by speed units
- goLeft(int speed): Move left by speed units
Attacker (Interface)
Interface for entities that can attack.
- attack(target): Attack a target entity
DistantAttacker (Interface)
Interface for entities that can attack from a distance.
- distantAttack(target, int): Attack a target from distance with range parameter
Flying (Interface)
Interface for entities that can fly.
- takeOff(): Take off from ground, returns success status
- land(): Land on ground, returns success status
Adopt (Interface)
Interface for entities that can adopt other beings (like packs).
- adopt(candidate MovableBeing): Adopt a movable being into the group, returns success
- revoke(candidate Object): Remove a being from the group, returns success
Being
Living entity with health and resistance.
- maxHealth: Maximum health points (private)
- health: Current health points (protected)
- resistance: Damage resistance (protected)
- Extends
SpacialElement - receiveDamage(int amount): Reduces health by damage minus resistance
- getLuckLevel(): Returns a luck value affecting outcomes
- Base class for all living entities
MovableBeing (Abstract Class)
Abstract base class for all creatures that can move and fight.
- maxSpeed: Maximum movement speed (protected)
- force: Attack strength (protected)
- inAir: Whether the being is currently airborne (protected)
- Extends
Being - Implements
AttackerandMovableinterfaces - canMove(String direction): Checks if movement in direction is possible
- communicate(): Makes sounds or communicates with others
- Cannot be instantiated directly
Humanoid (Abstract Class)
Abstract base class for human-like creatures.
- Extends
MovableBeing - No additional attributes or methods in base form
- Template for warrior, archer, wizard types
- Cannot be instantiated directly
Animal (Abstract Class)
Abstract base class for animal creatures.
- Extends
MovableBeing - getMaxSpeed(): Returns maximum speed (animals tend to be fast)
- Template for dragons, eagles, wolves, etc.
- Cannot be instantiated directly
Pack
Group of creatures that moves and acts together.
- maxSize: Maximum number of members (private)
- name: Name of the pack (public)
- Extends
SpacialElement - Implements
Adopt,Movable, andAttackerinterfaces - Pack(MovableBeing chief): Creates pack with a leader
- isInPack(Object being): Checks if a being is member of this pack
- Contains 1 or more
MovableBeingmembers - Has exactly 1 chief (leader)
- Pack moves as a unit and can attack as a group
Warrior
Melee fighter class.
- Extends
Humanoid - No special attributes beyond inherited ones
- Strong in close combat
Archer
Ranged attacker with bow and arrows.
- range: Maximum attack range (public)
- dexterity: Skill level with ranged weapons (public)
- Extends
Humanoid - Implements
DistantAttackerinterface - Can attack from distance
Dragon
Powerful flying creature with breath weapon.
- power: Attack power multiplier (private)
- range: Distance of breath attack (public)
- Extends
Animal - Implements
FlyingandDistantAttackerinterfaces - Can fly and attack from distance with breath weapon
Eagle
Flying bird of prey.
- vision: Range of sight (public)
- Extends
Animal - Implements
Flyinginterface - High speed and vision, can fly
Wolf
Ground-based pack animal.
- Extends
Animal - No special attributes
- Typically part of a Pack
Tree
Static vegetation obstacle.
- Extends
Being(has health, can be damaged/destroyed) - No movement or attack capabilities
- Blocks movement
Rock
Static terrain obstacle.
- Extends
SpacialElement(not Being - cannot be damaged) - No health or combat properties
- Permanent obstacle
Map
Game world that contains all spatial elements.
- WIDTH: Map width in tiles (static public constant)
- HEIGHT: Map height in tiles (static public constant)
- add(SpacialElement element): Adds element to the map
- Maintains collection of all elements in the game world
Exporter
Utility for saving and loading game state.
- serialize(Object map, String path): Saves map to file
- deserialize(String path): Loads map from file, returns Map object
- filter(Object m): Private method to filter elements before export
Practice Exercise: Implement the RPG Game System
Objective: Implement the complete game system matching the UML diagram precisely.
Requirements:
- Create all 5 interfaces:
Movable,Attacker,DistantAttacker,Flying,Adopt - Create base class
SpacialElementimplementingMovable - Create
BeingextendingSpacialElementwith health system - Create abstract
MovableBeingextendingBeingand implementingAttackerandMovable - Create abstract
HumanoidandAnimalclasses - Implement all concrete classes:
Warrior,Archer,Dragon,Eagle,Wolf,Tree,Rock,Pack - Implement
MapandExporterutility classes - Demonstrate polymorphism with pack mechanics
💡 Click to see suggested implementation
// Movable interface
public interface Movable {
void goUp(int speed);
void goDown(int speed);
void goRight(int speed);
void goLeft(int speed);
}
// Attacker interface
public interface Attacker {
void attack(Object target);
}
// DistantAttacker interface
public interface DistantAttacker {
void distantAttack(Object target, int range);
}
// Flying interface
public interface Flying {
boolean takeOff();
boolean land();
}
// Adopt interface
public interface Adopt {
boolean adopt(MovableBeing candidate);
boolean revoke(Object candidate);
}
// SpacialElement base class
public class SpacialElement implements Movable {
protected String name;
protected int x;
protected int y;
public SpacialElement(String name, int x, int y) {
this.name = name;
this.x = x;
this.y = y;
}
@Override
public void goUp(int speed) {
y -= speed;
}
@Override
public void goDown(int speed) {
y += speed;
}
@Override
public void goRight(int speed) {
x += speed;
}
@Override
public void goLeft(int speed) {
x -= speed;
}
public String getName() { return name; }
public int getX() { return x; }
public int getY() { return y; }
}
// Being class
public class Being extends SpacialElement {
private int maxHealth;
protected int health;
protected double resistance;
public Being(String name, int x, int y, int maxHealth, double resistance) {
super(name, x, y);
this.maxHealth = maxHealth;
this.health = maxHealth;
this.resistance = resistance;
}
public void receiveDamage(int amount) {
int actualDamage = (int) (amount - resistance);
if (actualDamage > 0) {
health -= actualDamage;
if (health < 0) health = 0;
}
System.out.println(name + " received " + actualDamage + " damage. HP: " + health);
}
public int getLuckLevel() {
return (int) (Math.random() * 10); // Random luck 0-9
}
public int getHealth() { return health; }
public boolean isAlive() { return health > 0; }
}
// MovableBeing abstract class
public abstract class MovableBeing extends Being implements Attacker {
protected int maxSpeed;
protected int force;
protected boolean inAir;
public MovableBeing(String name, int x, int y, int health, double resistance, int force) {
super(name, x, y, health, resistance);
this.force = force;
this.maxSpeed = 5;
this.inAir = false;
}
public boolean canMove(String direction) {
return isAlive(); // Can only move if alive
}
public void communicate() {
System.out.println(name + " communicates!");
}
// Abstract attack method - each type implements differently
@Override
public abstract void attack(Object target);
public int getForce() { return force; }
}
// Humanoid abstract class
public abstract class Humanoid extends MovableBeing {
public Humanoid(String name, int x, int y) {
super(name, x, y, 100, 5.0, 15); // Standard humanoid stats
}
}
// Animal abstract class
public abstract class Animal extends MovableBeing {
public Animal(String name, int x, int y, int health, double resistance, int force) {
super(name, x, y, health, resistance, force);
this.maxSpeed = 8; // Animals tend to be faster
}
public int getMaxSpeed() {
return maxSpeed;
}
}
// Warrior class
public class Warrior extends Humanoid {
public Warrior(String name, int x, int y) {
super(name, x, y);
this.force = 20; // Warriors are strong
}
@Override
public void attack(Object target) {
if (target instanceof Being && isAlive()) {
System.out.println(name + " attacks with sword!");
((Being) target).receiveDamage(force);
}
}
}
// Archer class
public class Archer extends Humanoid implements DistantAttacker {
public int range;
public int dexterity;
public Archer(String name, int x, int y) {
super(name, x, y);
this.range = 10;
this.dexterity = 15;
this.force = 12;
}
@Override
public void attack(Object target) {
if (target instanceof Being && isAlive()) {
System.out.println(name + " shoots arrow!");
((Being) target).receiveDamage(force);
}
}
@Override
public void distantAttack(Object target, int distance) {
if (target instanceof Being && isAlive() && distance <= range) {
int damage = force + dexterity / 2;
System.out.println(name + " shoots from distance " + distance + "!");
((Being) target).receiveDamage(damage);
}
}
}
// Dragon class
public class Dragon extends Animal implements Flying, DistantAttacker {
private int power;
public int range;
public Dragon(String name, int x, int y) {
super(name, x, y, 200, 15.0, 30);
this.power = 40;
this.range = 15;
}
@Override
public boolean takeOff() {
if (!inAir) {
inAir = true;
System.out.println(name + " takes off!");
return true;
}
return false;
}
@Override
public boolean land() {
if (inAir) {
inAir = false;
System.out.println(name + " lands!");
return true;
}
return false;
}
@Override
public void attack(Object target) {
if (target instanceof Being && isAlive()) {
System.out.println(name + " breathes fire!");
((Being) target).receiveDamage(power);
}
}
@Override
public void distantAttack(Object target, int distance) {
if (target instanceof Being && isAlive() && distance <= range) {
System.out.println(name + " breathes fire from distance!");
((Being) target).receiveDamage(power + 10);
}
}
}
// Eagle class
public class Eagle extends Animal implements Flying {
public int vision;
public Eagle(String name, int x, int y) {
super(name, x, y, 50, 2.0, 8);
this.vision = 20;
}
@Override
public boolean takeOff() {
if (!inAir) {
inAir = true;
System.out.println(name + " soars into the sky!");
return true;
}
return false;
}
@Override
public boolean land() {
if (inAir) {
inAir = false;
System.out.println(name + " lands gracefully!");
return true;
}
return false;
}
@Override
public void attack(Object target) {
if (target instanceof Being && isAlive()) {
System.out.println(name + " dives and strikes!");
((Being) target).receiveDamage(force);
}
}
}
// Wolf class
public class Wolf extends Animal {
public Wolf(String name, int x, int y) {
super(name, x, y, 80, 3.0, 12);
}
@Override
public void attack(Object target) {
if (target instanceof Being && isAlive()) {
System.out.println(name + " bites!");
((Being) target).receiveDamage(force);
}
}
@Override
public void communicate() {
System.out.println(name + " howls!");
}
}
// Tree class
public class Tree extends Being {
public Tree(String name, int x, int y) {
super(name, x, y, 100, 0.0);
}
@Override
public void goUp(int speed) {
System.out.println("Trees cannot move!");
}
@Override
public void goDown(int speed) {
System.out.println("Trees cannot move!");
}
@Override
public void goRight(int speed) {
System.out.println("Trees cannot move!");
}
@Override
public void goLeft(int speed) {
System.out.println("Trees cannot move!");
}
}
// Rock class
public class Rock extends SpacialElement {
public Rock(String name, int x, int y) {
super(name, x, y);
}
@Override
public void goUp(int speed) {
System.out.println("Rocks cannot move!");
}
@Override
public void goDown(int speed) {
System.out.println("Rocks cannot move!");
}
@Override
public void goRight(int speed) {
System.out.println("Rocks cannot move!");
}
@Override
public void goLeft(int speed) {
System.out.println("Rocks cannot move!");
}
}
// Pack class
import java.util.ArrayList;
import java.util.List;
public class Pack extends SpacialElement implements Adopt, Attacker {
private int maxSize;
public String name;
private MovableBeing chief;
private List<MovableBeing> members;
public Pack(MovableBeing chief) {
super("Pack of " + chief.getName(), chief.getX(), chief.getY());
this.chief = chief;
this.maxSize = 10;
this.members = new ArrayList<>();
this.members.add(chief);
this.name = "Pack";
}
@Override
public boolean adopt(MovableBeing candidate) {
if (members.size() < maxSize && !members.contains(candidate)) {
members.add(candidate);
System.out.println(candidate.getName() + " joined the pack!");
return true;
}
return false;
}
@Override
public boolean revoke(Object candidate) {
if (candidate instanceof MovableBeing && candidate != chief) {
boolean removed = members.remove(candidate);
if (removed) {
System.out.println(((MovableBeing) candidate).getName() + " left the pack!");
}
return removed;
}
return false;
}
public boolean isInPack(Object being) {
return members.contains(being);
}
@Override
public void attack(Object target) {
System.out.println("Pack attacks together!");
for (MovableBeing member : members) {
member.attack(target);
}
}
@Override
public void goUp(int speed) {
super.goUp(speed);
for (MovableBeing member : members) {
member.goUp(speed);
}
}
@Override
public void goDown(int speed) {
super.goDown(speed);
for (MovableBeing member : members) {
member.goDown(speed);
}
}
@Override
public void goRight(int speed) {
super.goRight(speed);
for (MovableBeing member : members) {
member.goRight(speed);
}
}
@Override
public void goLeft(int speed) {
super.goLeft(speed);
for (MovableBeing member : members) {
member.goLeft(speed);
}
}
public MovableBeing getChief() { return chief; }
public List<MovableBeing> getMembers() { return new ArrayList<>(members); }
}
// Map class
import java.util.ArrayList;
import java.util.List;
public class Map {
public static final String WIDTH = "100";
public static final String HEIGHT = "100";
private List<SpacialElement> elements;
public Map() {
this.elements = new ArrayList<>();
}
public void add(SpacialElement element) {
elements.add(element);
System.out.println("Added " + element.getName() + " to map at (" +
element.getX() + ", " + element.getY() + ")");
}
public List<SpacialElement> getElements() {
return new ArrayList<>(elements);
}
}
// Exporter class
import java.io.*;
public class Exporter {
public void serialize(Object map, String path) {
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(path))) {
out.writeObject(filter(map));
System.out.println("Map exported to " + path);
} catch (IOException e) {
System.err.println("Export failed: " + e.getMessage());
}
}
public Object deserialize(String path) {
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(path))) {
Object map = in.readObject();
System.out.println("Map imported from " + path);
return map;
} catch (IOException | ClassNotFoundException e) {
System.err.println("Import failed: " + e.getMessage());
return null;
}
}
private Object filter(Object m) {
// Filter out temporary or invalid elements before export
return m;
}
}
// Game demo
public class RPGGameDemo {
public static void main(String[] args) {
System.out.println("=== RPG Game System Demo ===\n");
// Create map
Map gameMap = new Map();
// Add terrain
gameMap.add(new Tree("Oak", 10, 10));
gameMap.add(new Rock("Boulder", 15, 15));
// Create characters
Warrior warrior = new Warrior("Aragorn", 5, 5);
Archer archer = new Archer("Legolas", 7, 5);
Dragon dragon = new Dragon("Smaug", 50, 50);
Eagle eagle = new Eagle("Gwaihir", 60, 5);
gameMap.add(warrior);
gameMap.add(archer);
gameMap.add(dragon);
gameMap.add(eagle);
// Create wolf pack
Wolf alpha = new Wolf("Alpha", 20, 20);
Wolf beta = new Wolf("Beta", 21, 20);
Wolf gamma = new Wolf("Gamma", 20, 21);
Pack wolfPack = new Pack(alpha);
wolfPack.adopt(beta);
wolfPack.adopt(gamma);
gameMap.add(wolfPack);
System.out.println("\n=== Combat Demo ===");
// Warrior attacks dragon
warrior.attack(dragon);
// Archer uses distant attack
archer.distantAttack(dragon, 8);
// Dragon flies and attacks
dragon.takeOff();
dragon.distantAttack(warrior, 10);
dragon.land();
// Pack attacks together
System.out.println("\nWolf pack attacks:");
wolfPack.attack(warrior);
// Eagle flies
eagle.takeOff();
eagle.attack(gamma);
System.out.println("\n=== Movement Demo ===");
System.out.println("Pack position: (" + wolfPack.getX() + ", " + wolfPack.getY() + ")");
wolfPack.goRight(3);
System.out.println("Pack moved to: (" + wolfPack.getX() + ", " + wolfPack.getY() + ")");
System.out.println("\n=== Pack Info ===");
System.out.println("Pack members: " + wolfPack.getMembers().size());
System.out.println("Pack chief: " + wolfPack.getChief().getName());
}
}
Key Implementation Points:
SpacialElementis the base class for ALL game elementsBeingextendsSpacialElementand adds health/resistanceMovableBeingis abstract and implements bothAttackerand inheritsMovableHumanoidandAnimalare abstract templatesPackextendsSpacialElement(notBeing) and implements 3 interfacesTreeextendsBeing(can be damaged) butRockextendsSpacialElement(indestructible)- Static constants in
Mapare public Strings - Multiple interface implementation shown (Dragon, Archer, Pack)
- Pack contains and moves members together
- Protected members allow subclass access