- Overview
- Features
- Game Mechanics
- Controls
- Installation & Running
- Project Structure
- Architecture
- Class Documentation
- Game States
- Combat System
- Enemy AI
- Level System
- Development Notes
HFS (Horizontal Fighting System) is a 2D side-scrolling platformer game built with Java Swing. The game features a player character that can move, jump, and attack enemies in a tile-based level. Enemies patrol the level and will chase and attack the player when detected.
- Type: 2D Side-Scrolling Platformer
- Style: Action/Combat Platformer
- Engine: Java Swing with custom game loop
- ✅ Player Movement: Smooth horizontal movement with jumping mechanics
- ✅ Combat System: Player and enemy attack mechanics with hitboxes
- ✅ Health System: Player and enemy health with visual health bar
- ✅ Enemy AI: Intelligent enemies that patrol, detect, chase, and attack the player
- ✅ Level System: Tile-based level rendering with collision detection
- ✅ Death System: Player death animation and Game Over screen
- ✅ Replay System: Reset and replay functionality
- ✅ Menu System: Main menu with play, options, and quit
- ✅ Pause System: In-game pause menu with replay option
- ✅ Animation System: Sprite-based animations for player and enemies
- Animated player sprites (9 states: Standing, Running, Jumping, Falling, Ground, Hit, Attack, etc.)
- Animated enemy sprites (5 states: Idle, Running, Attack, Hit, Dead)
- Health bar UI with current/max health display
- Game Over screen with fade effect
- Background clouds with parallax scrolling
- Tile-based level rendering
- Horizontal Movement: Left (A) and Right (D) keys
- Jumping: Space bar or Right Mouse Button
- Gravity: Applied when player is in air
- Collision Detection: Wall and floor collision using tile-based system
- Attack: Left Mouse Button or Left Click
- Attack Range: 40 pixels in front of player
- Attack Damage: 10 damage per hit
- Attack Animation: 3-frame attack animation
- Max Health: 100 HP
- Damage: 5 damage per enemy attack
- Invincibility: 60 frames (1 second) after taking damage
- Death: When health reaches 0, plays death animation (GROUND state)
- Patrolling: Default state - moves back and forth
- Chasing: When player is within vision range (200 pixels)
- Attacking: When player is within attack range (30 pixels)
- Hit: Brief stun state after taking damage
- Dead: Death animation plays, enemy stops moving
- Max Health: 50 HP
- Attack Damage: 5 damage per attack
- Vision Range: 200 pixels
- Attack Range: 30 pixels
- Attack Cooldown: 90 frames (1.5 seconds)
- Movement Speed: 1.0 * SCALE
- Tile Size: 32x32 pixels (scaled)
- Level Data: Loaded from image file (
level_one_data_long.png) - Collision: Tile value 11 = air, all other values = solid
- Enemy Spawning: Enemies placed based on green channel values in level image
- Camera Follow: Follows player with left/right borders
- Level Offset: Scrolls level based on player position
- Boundaries: Prevents scrolling beyond level edges
| Key | Action |
|---|---|
| A | Move Left |
| D | Move Right |
| Space | Jump |
| ESC | Pause/Unpause Game |
| Enter | Start Game (from menu) |
| Button | Action |
|---|---|
| Left Click | Attack |
| Right Click | Jump (alternative) |
| Mouse Movement | Navigate menus, adjust volume slider |
- Mouse Over: Highlights menu buttons
- Left Click: Selects menu option
- Enter Key: Starts game from main menu
- Java JDK 8 or higher
- IDE (IntelliJ IDEA, Eclipse, or VS Code) recommended
-
Clone or Download Project
# If using git git clone <repository-url> cd HFS
-
Project Structure
HFS/ ├── src/ │ ├── main/ # Main game classes │ ├── Entities/ # Player and Enemy classes │ ├── State/ # Game states (Menu, Playing) │ ├── UI/ # UI components │ ├── Function/ # Utility classes │ ├── GameLevels/ # Level management │ └── Inputes_of_game/ # Input handlers ├── Resource/ # Game assets (images) └── README.md -
Resource Files Required Ensure all images are in the
Resource/folder:p2.png- Player sprite sheetenemy_1.png- Enemy sprite sheetlevel_one_data_long.png- Level data imageoutside_sprites.png- Level tilesmenu_background.png- Menu panelmenu_bg.jpg- Menu backgroundpause_menu.png- Pause menubutton_atlas.png- Button spritessound_button.png- Sound buttonurm_buttons.png- URM buttonsvolume_buttons.png- Volume sliderplaying_bg_img.png- Game backgroundbig_clouds.png- Large cloudssmall_clouds.png- Small clouds
-
Running the Game
# Compile (if needed) javac -d out src/**/*.java # Run java -cp out main.Main
Or run directly from your IDE:
- Open project in IDE
- Run
src/main/Main.java
- Game Scale: 1.0 (can be adjusted in
game.java) - Target FPS: 120
- Target UPS: 120
- Game Resolution: 832x448 pixels (26x14 tiles)
src/
├── main/
│ ├── Main.java # Entry point
│ ├── game.java # Main game loop and state management
│ ├── game_panel.java # Swing panel for rendering
│ └── window_of_game.java # JFrame window setup
│
├── Entities/
│ ├── Entity.java # Base entity class
│ ├── Player.java # Player character
│ ├── Enemy.java # Base enemy class
│ ├── Enemy1.java # Crab enemy implementation
│ └── EnemyMangerclass.java # Enemy manager
│
├── State/
│ ├── State.java # Base state class
│ ├── Methods.java # State interface
│ ├── GameState.java # Game state enum
│ ├── MENU.java # Main menu state
│ └── Playing.java # Gameplay state
│
├── UI/
│ ├── MenuButton.java # Menu button component
│ ├── Pause.java # Pause menu
│ ├── PauseButton.java # Base pause button
│ ├── Sound_Button.java # Sound toggle button
│ ├── URMButtons.java # URM (Unpause/Replay/Menu) buttons
│ └── VloumeButton.java # Volume slider
│
├── Function/
│ ├── LoadSave.java # Asset loading utilities
│ ├── StaticMethodsforMovement.java # Collision and movement helpers
│ └── features.java # Game constants and configurations
│
├── GameLevels/
│ ├── Level.java # Level data structure
│ └── LevelManager.java # Level rendering and management
│
└── Inputes_of_game/
├── keyboard_input.java # Keyboard input handler
└── mouse_input.java # Mouse input handler
The game uses a fixed timestep game loop running in a separate thread:
// Update loop: 120 UPS (Updates Per Second)
if (deltaUpdate >= 1) {
UpdateGame();
deltaUpdate--;
}
// Render loop: 120 FPS (Frames Per Second)
if (deltaFrame >= 1) {
Game_panel.repaint();
deltaFrame--;
}The game uses a state pattern for managing different game screens:
- MENU: Main menu screen
- PLAYING: Active gameplay
- OPTIONS: Options menu (placeholder)
- QUIT: Exit game
States implement the Methods interface which defines:
update()- Update game logicdraw(Graphics)- Render graphics- Input handlers (mouse/keyboard)
All game entities inherit from Entity base class:
- Entity: Base class with position, hitbox, and rendering
- Player: Extends Entity, adds movement, combat, health
- Enemy: Extends Entity, adds AI, combat, health
- Enemy1: Specific enemy implementation (Crab)
Main game class managing the game loop and state switching.
Key Methods:
run()- Main game loop threadUpdateGame()- Updates current game stateRenderGraphicsGame(Graphics)- Renders current state
Player character with movement, combat, and health systems.
Key Methods:
UpdatePlayer()- Updates player statetakeDamage(int)- Applies damage to playergetAttackHitbox()- Returns attack collision boxreset()- Resets player for replayisAlive()- Checks if player is aliveisDead()- Checks if player is dead
Key Properties:
currentHealth- Current health (0-100)maxHealth- Maximum health (100)isDead- Death state flagattacking- Attack state flag
Base enemy class with AI, combat, and health systems.
Key Methods:
loadLevelData(int[][])- Loads level collision datasetPlayer(Player)- Sets player reference for AIcanSeePlayer()- Checks if player is in vision rangecanAttackPlayer()- Checks if player is in attack rangetakeDamage(int)- Applies damage to enemygetAttackHitbox()- Returns attack collision box
Key Properties:
visionRange- Detection range (200 pixels)attackRange- Attack range (30 pixels)currentHealth- Current health (0-50)isDead- Death state flag
Crab enemy implementation with patrolling and chasing AI.
Key Methods:
update()- Updates enemy state and AIupdatePosition()- Handles movement and AI decisionsupdateCombat()- Updates combat cooldowns
Manages all enemies in the game.
Key Methods:
update()- Updates all enemiesdraw(Graphics, int)- Renders all enemiescheckPlayerAttack(Rectangle2D.Float)- Checks player attackscheckEnemyAttacks(Player)- Checks enemy attacks on playerresetEnemies()- Resets all enemies for replay
Main gameplay state managing player, enemies, and level.
Key Methods:
update()- Updates game statedraw(Graphics)- Renders gamecheckCombat()- Handles combat collisionsresetGame()- Resets game for replaydrawHealthBar(Graphics)- Renders health bardrawGameOver(Graphics)- Renders game over screen
Utility class for loading game assets.
Key Methods:
GetAtlas(String)- Loads image from resourcesGetLevelData()- Loads level collision datagetEnemyCrab()- Creates enemies from level data
Static utility methods for collision detection.
Key Methods:
CanMove(float, float, float, float, int[][])- Checks if entity can moveIsSolid(float, float, int[][])- Checks if position is solidOnFloor(Rectangle2D.Float, int[][])- Checks if entity is on floorPositionNextToWall(Rectangle2D.Float, float)- Calculates wall collision positionCheckUnderEnvironmentorAbove(Rectangle2D.Float, float)- Calculates floor/ceiling collision
Main menu screen with three buttons:
- Play - Starts new game (resets game state)
- Options - Opens options menu (placeholder)
- Quit - Exits game
Active gameplay state with:
- Player movement and combat
- Enemy AI and combat
- Level rendering
- Health bar
- Pause menu (ESC key)
- Game Over screen (when player dies)
MENU → PLAYING (Play button)
PLAYING → MENU (Game Over or Menu button in pause)
PLAYING → PLAYING (Pause/Unpause with ESC)
Attack Trigger:
- Left Mouse Button pressed
Attack Hitbox:
- Width: 40 pixels
- Height: Player height
- Position: Extends in front of player (left or right based on facing direction)
Attack Damage:
- 10 damage per hit
Attack Animation:
- 3 frames
- Plays once per attack
Attack Trigger:
- Player within 30 pixels
- Attack cooldown expired (90 frames)
Attack Hitbox:
- Width: 30 pixels
- Height: Enemy height
- Position: Extends in front of enemy (based on facing direction)
Attack Damage:
- 5 damage per hit
Attack Animation:
- 7 frames
- Plays during attack state
Combat is checked every frame in Playing.checkCombat():
- Check player attack hitbox against all enemies
- Check all enemy attack hitboxes against player
- Apply damage if hitboxes intersect
- Respect invincibility cooldowns
- Moves back and forth
- Changes direction on wall collision or cliff edge
- Checks floor ahead before moving
- Player within 200 pixels (vision range)
- Faces player direction
- Moves toward player
- Still respects floor and wall collisions
- Player within 30 pixels (attack range)
- Enters ATTACK state
- Attack cooldown prevents spam
- Returns to chasing after attack
- Brief stun state
- Plays HIT animation (4 frames)
- Returns to previous state after cooldown
- Health reaches 0
- Plays DEAD animation (5 frames)
- Stops at last frame
- No movement or attacks
Update Loop:
1. Check if dead → Stop all actions
2. Check if can see player → Enter chase mode
3. Check if can attack player → Enter attack mode
4. Otherwise → Continue patrolling
Levels are defined using image files where:
- Red Channel: Tile type (0-47 = tile sprite index, 11 = air)
- Green Channel: Enemy spawn points (value = ENEMY_1 constant)
- Blue Channel: (Unused)
- Load level image (
level_one_data_long.png) - Extract red channel for tile data
- Extract green channel for enemy positions
- Create collision map from tile data
- Spawn enemies at marked positions
- Tiles are rendered from sprite sheet (
outside_sprites.png) - 48 different tile sprites (4 rows × 12 columns)
- Each tile is 32×32 pixels
- Level scrolls based on camera position
- Tile value 11 = Air (passable)
- All other values = Solid (collision)
- Collision checked at 4 corners of entity hitbox
- Floor detection checks 1 pixel below entity
- Package naming: lowercase (e.g.,
Entities,State) - Class naming: PascalCase (e.g.,
Player,Enemy1) - Method naming: camelCase (e.g.,
UpdatePlayer(),takeDamage()) - Constants: UPPER_SNAKE_CASE (e.g.,
MAX_HEALTH,TILE_SIZE)
- Game loop runs at 120 FPS/UPS
- Double buffering for smooth rendering
- Efficient collision detection using tile-based system
- Enemy updates only when in active area
- Fixed game resolution (832×448)
- Single level (no level progression)
- No save system
- Options menu not implemented
- Sound system placeholder (buttons exist but no audio)
- Multiple levels
- Save/Load system
- Sound effects and music
- More enemy types
- Power-ups and collectibles
- Score system
- Difficulty levels
Game won't start:
- Check that all resource files are in
Resource/folder - Verify Java version (JDK 8+)
- Check console for error messages
Player falls through floor:
- Verify level data image is loaded correctly
- Check collision detection in
StaticMethodsforMovement
Enemies not spawning:
- Check green channel values in level image
- Verify
ENEMY_1constant matches level data
Controls not working:
- Ensure game panel has focus (click on game window)
- Check input handlers are properly attached