Skip to content

Latest commit

 

History

300 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TheDebugThugs - Escape Game

Implementation and Design Choices


1. Project Overview

TheDebugThugs is a 2D escape game built using the libGDX framework. The game challenges players to navigate through a university campus, collect items, avoid obstacles and enemies, and ultimately escape within a time limit.

Key Statistics

  • Framework: libGDX (Java-based game development framework)
  • Language: Java 17
  • Build System: Gradle
  • Architecture: Multi-module project (core, lwjgl3, headless)
  • Code Quality: JaCoCo for test coverage, Checkstyle for code standards

2. Architecture & Project Structure

2.1 Multi-Module Architecture

The project follows a modular design with three key modules:

Team10Assessment2-Self-test/
├── core/          # Core game logic (platform-independent)
├── lwjgl3/        # Desktop launcher (LWJGL3 backend)
└── headless/      # Headless testing environment

Important

Design Choice: This separation allows the game logic to remain platform-independent while enabling headless testing without graphics initialization, crucial for CI/CD pipelines.

2.2 Core Game Classes (25 Components)

Main Systems:

  • Main.java - Application entry point with dual viewport system
  • FirstScreen.java - Main gameplay screen (549 lines)
  • Player.java - Player controller with state machine

Game Entities:

  • Enemy, Duck, Exam, LongBoi, DuoAuth, WetFloor (various events/obstacles)
  • Key, EnergyDrink, Coin, HelperCharacter (collectibles)
  • Bus, BusStop (transportation system)

Supporting Systems:

  • AchievementManager.java - Achievement tracking with singleton pattern
  • Pathfinding.java - A* pathfinding algorithm
  • Collision.java - Collision detection system

UI Screens:

  • MenuScreen, WinScreen, LoseScreen, SettingsScreen, LeaderBoardScreen, Tutorial

3. Key Implementation Details

3.1 Dual Viewport System

Implementation (Main.java):

// World camera - for game world rendering
worldCamera = new OrthographicCamera();
worldViewport = new FitViewport(800, 600, worldCamera);

// UI camera - for HUD/menu rendering
uiCamera = new OrthographicCamera();
uiViewport = new FitViewport(1280, 720, uiCamera);

Tip

Design Rationale: Separating world and UI rendering allows independent scaling. The world can zoom (0.6x default) while UI remains crisp and pixel-perfect. This prevents UI distortion during camera movements.

3.2 Player State Machine & Animation System

State Management (Player.java):

public enum State {
    WALK,      // Walking down
    WALK_L,    // Walking left
    WALK_R,    // Walking right  
    WALK_UP,   // Walking up
    FALL       // Falling animation (triggered by events)
}

Animation Frame Trimmer (FirstScreen.java):

public static Animation<TextureRegion> frameTrimmer(TextureRegion[] array, int empty) {
    TextureRegion[] arrayOut = new TextureRegion[array.length - empty];
    for (int i = 0; i < (array.length - empty); i++) {
        arrayOut[i] = array[i];
    }
    return new Animation<>(0.05f, arrayOut);
}

Note

Design Choice: The frame trimmer removes empty frames from sprite sheets, optimizing memory and preventing unnecessary frame rendering. This keeps animations smooth at 0.05s per frame.

3.3 Game Loop Architecture

The game follows a clean render pattern with separation of concerns (FirstScreen.java):

@Override
public void render(float delta) {
    logic(delta);      // Update game state
    renderWorld();     // Render world objects
    renderUI(delta);   // Render UI overlay
}

Logic Phase (~76 lines):

  • Pause/unpause handling
  • Player input processing
  • Enemy AI updates
  • Event system updates
  • Score decay calculation
  • Win/lose condition checks

World Rendering Phase:

  • Camera positioning (follows player)
  • Tiled map rendering
  • Sprite batch rendering in proper z-order

UI Rendering Phase:

  • HUD elements (timer, score, events)
  • Achievement popups
  • Pause menu overlay

3.4 Collision Detection System

Tile-based Collision (Collision.java):

The system uses corner-point collision detection - checking the four corners of the player's bounding box against the tilemap:

public static boolean collisionCheck(Player p) {
    // Check all 4 corners of player rectangle
    if (isCellBlocked(p.playerX, p.playerY)) return true;
    if (isCellBlocked(p.playerX + p.playerWidth, p.playerY)) return true;
    if (isCellBlocked(p.playerX, p.playerY + p.playerHeight)) return true;
    if (isCellBlocked(p.playerX + p.playerWidth, p.playerY + p.playerHeight)) return true;
    return false;
}

Important

Design Choice: Corner-point collision provides pixel-perfect collision while remaining computationally efficient. Only 4 tile lookups per movement frame.


4. Advanced Design Patterns

4.1 Singleton Pattern - Achievement Manager

Implementation (AchievementManager.java):

private static AchievementManager instance;

public static AchievementManager get() {
    if (instance == null) {
        instance = new AchievementManager();
    }
    return instance;
}

Achievements Tracked:

  • ESCAPED, ENCOUTERED_DEAN, FOUND_KEY, UNLOCKED_DOOR
  • ENERGISED, FLAWLESS_RUN, TELEPORTED, DUO_AUTHENTICATED
  • WATCH_YOUR_STEP, QUACK, DUCK_OF_RESETTING, HELPER_FOUND

Persistence: Uses libGDX Preferences API for persistent storage across game sessions.

Pop-up System:

  • Queue-based achievement notifications
  • Fade-in/fade-out animations (2s display, 0.5s fade)
  • Non-blocking UI updates

Tip

Design Rationale: Singleton ensures consistent achievement state across all game screens. The queue prevents notification spam when multiple achievements unlock simultaneously.

4.2 A* Pathfinding Algorithm

Implementation (Pathfinding.java):

The enemy AI uses A pathfinding* with the following features:

Key Components:

  1. Node-based graph - Each tile is a node with g, h, and f costs
  2. Octile distance heuristic - Accounts for diagonal movement
  3. Priority queue - Efficiently selects lowest f-cost nodes
  4. Path reconstruction - Backtracks from goal to start via parent links
  5. Path pruning - Removes redundant waypoints near start position
private float heuristic(int ax, int ay, int bx, int by) {
    float dx = Math.abs(ax - bx);
    float dy = Math.abs(ay - by);
    float min = Math.min(dx, dy);
    float max = Math.max(dx, dy);
    return 1.41421356f * min + (max - min);  // Octile distance
}

Diagonal Movement Handling:

if (d[0] != 0 && d[1] != 0) {
    // Diagonal movement - check corners aren't blocked
    if (!isWalkable(current.x + d[0], current.y) || 
        !isWalkable(current.x, current.y + d[1])) {
        continue; // Prevent corner-cutting
    }
}

Performance Optimization:

  • Repath interval: 0.5s (reduces CPU usage)
  • Path pruning: Removes waypoints within half-tile radius of enemy
  • Early termination: Stops when goal is reached

Note

Design Choice: A* provides optimal pathfinding while octile distance heuristic ensures realistic diagonal movement. The repath interval balances responsiveness with performance.

4.3 Event System Architecture

Three Event Categories tracked on player:

public int goodEvent = 0;    // Beneficial events (energy drink, coin)
public int badEvent = 0;     // Negative events (enemy, exam, duck)
public int hiddenEvent = 0;  // Secret events (bus teleportation)

Event Types:

Event Type Effect Duration
Enemy Bad -30s time, +1 counter 2s cooldown
DuoAuth Bad 10s freeze, achievement One-time
WetFloor Bad 5s freeze One-time
Exam Bad Patrol movement, time penalty N/A
Duck Bad Random position reset One-time
EnergyDrink Good +25% speed boost Permanent
Coin Good +50 score N/A
HelperCharacter Good +20s time N/A
Bus Hidden Random teleport Unlimited

Freeze Event Pattern (DuoAuth example):

if (duoAuth.active) {
    return;  // Skip all player input processing
}

Important

Design Rationale: The event counter system supports achievement tracking (e.g., "FLAWLESS_RUN" requires badEvent == 0) and provides gameplay statistics for player feedback.


5. Innovative Game Features

5.1 Transportation System (Bus)

Design:

  • Single bus entity at fixed location (608, 512)
  • 10 bus stops (A-J) scattered across map
  • Random teleportation to any stop on interaction

Implementation (Player.java):

private void teleportToRandomStop(java.util.List<BusStop> busStops) {
    int index = MathUtils.random(0, busStops.size() - 1);
    BusStop targetStop = busStops.get(index);
    
    playerX = targetStop.bounds.x;
    playerY = targetStop.bounds.y;
    
    lastBusMessage = "You took a bus to " + targetStop.name;
    needsBusMessage = true;
    busMessageTimer = 0f;
    
    hiddenEvent += 1;
    AchievementManager.get().unlock("TELEPORTED");
}

UX Polish:

  • Context-sensitive message: "Press 'E' to ride the bus"
  • Notification displays destination for 3 seconds
  • Unlocks "TELEPORTED" achievement on first use

Tip

Design Rationale: The bus provides strategic depth - players can use it to quickly navigate the large map or escape enemies, but the random destination adds risk/reward decision-making.

5.2 Dynamic Score System

Score Calculation:

public float maxScore = 500f;
public float playerScore = maxScore;

// In render loop:
float decayRate = maxScore / 300f;  // 500/300 = ~1.67 points/second
playerScore -= decayRate * delta;

Score Modifiers:

  • Base: 500 points
  • Time decay: Linear decay to 0 over 5 minutes
  • Bonus: +50 from coin collection
  • Penalty: Time lost from events indirectly reduces score

Note

Design Choice: Linear score decay incentivizes fast completion while bonus collectibles reward exploration. The system creates tension between speed and thoroughness.

5.3 Testability Features

Headless Testing Support (FirstScreen.java):

public void initLogic(Player player, Key key, EnergyDrink energyDrink, 
                     Bus bus, java.util.List<BusStop> busStops, 
                     DuoAuth duoAuth, WetFloor wetFloor, 
                     float enemyX, float enemyY) {
    // Initialize game objects without graphics/audio
    // Enables unit testing of game logic
}

Test Mode Constructors:

// Enemy.java - test constructor
public Enemy(float x, float y) {
    this.testMode = true;
    // Skip texture/pathfinding initialization
}

Important

Design Rationale: Separating logic initialization from graphics/audio enables comprehensive unit testing without LibGDX graphics context. This supports CI/CD with headless test runners.


6. Technical Design Decisions

6.1 Resource Management

Texture Loading Strategy:

  • All textures loaded in show() method
  • Proper disposal in dispose() method (60+ lines)
  • Animation textures separated from sprite textures

Example (FirstScreen.java):

@Override
public void dispose() {
    if (renderer != null) renderer.dispose();
    if (map != null) map.dispose();
    if (keyTexture != null) keyTexture.dispose();
    // ... 50+ more resource disposals
}

Warning

Critical Choice: LibGDX requires manual memory management. Failing to dispose textures causes memory leaks. The comprehensive disposal pattern prevents crashes in long play sessions.

6.2 Tiled Map Integration

Map Layers:

map = new TmxMapLoader().load("maps/maze_map.tmx");
MapLayer wallsLayer = map.getLayers().get("Walls");
MapLayer doorsLayer = map.getLayers().get("Doors");
collisionLayer = (TiledMapTileLayer) wallsLayer;
doorLayer = (TiledMapTileLayer) doorsLayer;

Benefits:

  • Visual level design using Tiled Map Editor
  • Non-programmers can create levels
  • Collision data embedded in map
  • Easy iteration without code changes

6.3 Player Input System

Input Handling:

  • WASD and Arrow Keys for movement
  • E for interaction (doors, bus)
  • ESC for pause menu
  • C for debug win (testing shortcut)

Input Processor Swapping:

if (paused)
    Gdx.input.setInputProcessor(pauseStage);  // UI handles input
else
    Gdx.input.setInputProcessor(null);        // Game handles input

Tip

Design Rationale: Swapping input processors cleanly separates game input from UI input, preventing movement during pause menu interaction.

6.4 Camera System

Camera Following:

game.worldCamera.position.set(
    playerChar.playerX + playerChar.playerWidth / 2f,
    playerChar.playerY + playerChar.playerHeight / 2f, 
    0
);

Zoom Level: 0.6x (shows more of the world while maintaining visibility)

Note

Design Choice: Centered camera follows player smoothly. The 0.6x zoom provides strategic view of surroundings, important for spotting enemies and planning routes.


7. Code Quality & Testing

7.1 Testing Infrastructure

Test Organization:

  • Core module: core/src/test/ - 5 test classes
  • Headless module: headless/src/test/ - 13+ test classes

Test Categories:

  1. Unit Tests: Individual component testing (Player, Collision, Key, Door)
  2. Integration Tests: Multi-component interactions (BusStop, DuoAuth, Enemy)
  3. Headless Tests: Full game logic without graphics
  4. Asset Tests: Verify all game assets load correctly

Coverage Reporting:

jacoco {
    toolVersion = "0.8.10"
}

jacocoTestReport {
    reports {
        html.required = true
        xml.required = true
        csv.required = false
    }
}

7.2 Code Standards

Checkstyle Integration:

checkstyle {
    toolVersion = '10.12.0'
    configFile = rootProject.file("${rootDir}/config/checkstyle/checkstyle.xml")
    ignoreFailures = true
}

Enforced Standards:

  • Consistent naming conventions
  • Javadoc comments for public methods
  • Proper indentation and formatting
  • Maximum line length constraints

8. Performance Optimizations

8.1 Rendering Optimizations

SpriteBatch Pattern:

game.batch.begin();
// All sprite drawing here
game.batch.end();

Tip

Batching all sprite draws between single begin/end calls minimizes GPU state changes, crucial for 60 FPS performance.

8.2 AI Optimizations

Enemy Pathfinding:

  • Repath interval: 0.5s (not every frame)
  • Path pruning eliminates unnecessary waypoints
  • Early goal detection terminates search

Cost Analysis:

  • Pathfinding: ~0.5-2ms per repath (depends on distance)
  • 2 repaths/second = negligible CPU impact

8.3 Animation Optimizations

Frame Timing:

if (playerChar.isMoving)
    stateTime += delta * animSpeed;  // Only advance when moving
else
    stateTime = 0f;  // Reset to idle frame

This prevents unnecessary GPU texture swaps when player is stationary.


9. Challenges & Solutions

Challenge 1: Door Interaction State Management

Problem: Detecting when player is near door and has key.

Solution: Static door state flags in Player class:

public static boolean doorInfront = false;
public static boolean open = false;

Collision detection sets these flags, player input reads them.

Challenge 2: Multiple Event System Coordination

Problem: Events (DuoAuth, WetFloor, Enemy) need to coordinate without interfering.

Solution: Individual active flags and update loops:

if (duoAuth.active) return;  // Skip input processing
if (wetFloor.active) return; // Skip input processing
// Normal movement here

Challenge 3: Test Without Graphics Context

Problem: LibGDX rendering requires OpenGL context, unavailable in CI/CD.

Solution:

  1. Headless backend (no graphics initialization)
  2. Test-specific constructors for entities
  3. initLogic() method to set up game state for testing

10. Key Takeaways for Presentation

Technical Highlights

Modular Architecture - Clean separation enables testing and future platform expansion
Dual Viewport System - Professional rendering with independent world/UI cameras
A Pathfinding* - Sophisticated AI with optimal path calculation
Singleton Achievement System - Persistent player progression across sessions
Comprehensive Testing - Headless testing enables CI/CD integration
Resource Management - Proper disposal prevents memory leaks
Event-Driven Design - Flexible event system supports diverse gameplay mechanics

Design Priorities

  1. Testability First - Every component designed with testing in mind
  2. Performance - Optimizations at every layer (batching, pathfinding intervals, frame skipping)
  3. Maintainability - Clear separation of concerns, consistent patterns
  4. Player Experience - Smooth animations, responsive controls, clear feedback
  5. Code Quality - Checkstyle enforcement, comprehensive Javadoc, code reviews

11. Future Improvements (Optional Discussion Points)

Potential Enhancements:

  • Entity Component System (ECS) - Refactor entities to component-based architecture for flexibility
  • Level Editor - In-game level designer using Tiled integration
  • Multiplayer - Add networked co-op using Kryonet
  • Mobile Port - Android/iOS modules (architecture already supports it)
  • Procedural Generation - Randomized map layouts for replayability
  • Save System - Checkpoint system using LibGDX Preferences
  • Sound Effects - Currently only background music, add SFX for events

12. Conclusion

TheDebugThugs demonstrates professional game development practices with a focus on:

  • Clean architecture with separation of concerns
  • Advanced algorithms (A*, state machines, event systems)
  • Comprehensive testing infrastructure
  • Performance-conscious implementation
  • Extensible design for future features

The project showcases both technical depth (pathfinding, dual viewports, resource management) and creative design (unique bus teleportation, multi-layered event system, achievement progression).


Appendix: Quick Reference

Key Files by Function

Function Primary File LOC
Main Game Loop FirstScreen.java 549
Player Control Player.java 248
Enemy AI Enemy.java 181
Pathfinding Pathfinding.java 198
Achievements AchievementManager.java 216
Collision Collision.java ~145

Design Patterns Used

  • Singleton: AchievementManager
  • State Machine: Player animation states
  • Observer: Achievement unlock notifications
  • Template Method: Screen lifecycle (show/render/dispose)
  • Strategy: Different event behaviors (DuoAuth, WetFloor, Duck)

Technologies & Tools

  • libGDX: 1.12.x (game framework)
  • Java: 17
  • Gradle: Build automation
  • JUnit 5: Testing framework
  • JaCoCo: Code coverage
  • Checkstyle: Code quality
  • Tiled: Map editor

End of Presentation Guide

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages