Everlast

Role: Programmer, Game Designer


Tool: LibGDX, Tiled


Team: Redpact, Team of 7


Timeline: 1 semester


Completion Date: May 18, 2024

Role: Programmer, Game Designer


Tool: LibGDX, Tiled


Team: Redpact, Team of 7


Timeline: 1 semester


Completion Date: May 18, 2024

Role: Programmer, Game Designer


Tool: LibGDX, Tiled


Team: Redpact, Team of 7


Timeline: 1 semester


Completion Date: May 18, 2024

Play ->

Play ->

Play ->

GAME DESIGN

GAME DESIGN

GAME DESIGN

design pillars

design pillars

design pillars

Fast-Paced Strategy

Fast-Paced Strategy

Fast-Paced Strategy

Center the gameplay on dynamic mechanics that demand quick, strategic decision-making.

Center the gameplay on dynamic mechanics that demand quick, strategic decision-making.

Center the gameplay on dynamic mechanics that demand quick, strategic decision-making.

Narrative-Driven

Narrative-Driven

Narrative-Driven

Tie progression and rewards to immersive environments and a compelling narrative, guiding players through diverse, challenging levels.

Tie progression and rewards to immersive environments and a compelling narrative, guiding players through diverse, challenging levels.

Tie progression and rewards to immersive environments and a compelling narrative, guiding players through diverse, challenging levels.

Replayability

Replayability

Replayability

Design levels to encourage replays, allowing players to discover varied paths and experiment with alternative tactics for greater enjoyment.

Design levels to encourage replays, allowing players to discover varied paths and experiment with alternative tactics for greater enjoyment.

Design levels to encourage replays, allowing players to discover varied paths and experiment with alternative tactics for greater enjoyment.

mechanics

mechanics

mechanics

PROGRAMMING

PROGRAMMING

PROGRAMMING

software Architecture

software Architecture

software Architecture

The game’s codebase is structured using the MVC architecture, ensuring a clear separation of responsibilities to enhance readability and maintainability. At the top of this structure is the Root section, which serves as the entry point for the LibGDX program. This centralizes setup and initialization, keeping these processes in one place rather than distributing them across multiple components.

The controller layer is the most complex part of the architecture. It is divided into game modes, including MenuMode, LoadingMode, and GameMode, each serving specific purposes. MenuMode and LoadingMode operate with minimal components, managing menus, loading screens, and level tracking using GameCanvas. GameMode, in contrast, handles the core gameplay mechanics, such as collision detection and resolution, audio, input handling, and the management of player and enemy AI. Specialized controllers are used for many game features, further organizing this layer.

The models represent the state and data of in-game objects. These models are subcomponents of a central Level model responsible for generating entire game levels. Inheritance is used extensively, with abstract classes defining shared behaviors for objects like characters and tiles. Concrete classes then store detailed information for specific elements such as players, enemies, and destructible tiles.

Below is a screenshot of the dependency diagram that illustrates the game’s architecture:

The game’s codebase is structured using the MVC architecture, ensuring a clear separation of responsibilities to enhance readability and maintainability. At the top of this structure is the Root section, which serves as the entry point for the LibGDX program. This centralizes setup and initialization, keeping these processes in one place rather than distributing them across multiple components.

The controller layer is the most complex part of the architecture. It is divided into game modes, including MenuMode, LoadingMode, and GameMode, each serving specific purposes. MenuMode and LoadingMode operate with minimal components, managing menus, loading screens, and level tracking using GameCanvas. GameMode, in contrast, handles the core gameplay mechanics, such as collision detection and resolution, audio, input handling, and the management of player and enemy AI. Specialized controllers are used for many game features, further organizing this layer.

The models represent the state and data of in-game objects. These models are subcomponents of a central Level model responsible for generating entire game levels. Inheritance is used extensively, with abstract classes defining shared behaviors for objects like characters and tiles. Concrete classes then store detailed information for specific elements such as players, enemies, and destructible tiles.

Below is a screenshot of the dependency diagram that illustrates the game’s architecture:

The game’s codebase is structured using the MVC architecture, ensuring a clear separation of responsibilities to enhance readability and maintainability. At the top of this structure is the Root section, which serves as the entry point for the LibGDX program. This centralizes setup and initialization, keeping these processes in one place rather than distributing them across multiple components.

The controller layer is the most complex part of the architecture. It is divided into game modes, including MenuMode, LoadingMode, and GameMode, each serving specific purposes. MenuMode and LoadingMode operate with minimal components, managing menus, loading screens, and level tracking using GameCanvas. GameMode, in contrast, handles the core gameplay mechanics, such as collision detection and resolution, audio, input handling, and the management of player and enemy AI. Specialized controllers are used for many game features, further organizing this layer.

The models represent the state and data of in-game objects. These models are subcomponents of a central Level model responsible for generating entire game levels. Inheritance is used extensively, with abstract classes defining shared behaviors for objects like characters and tiles. Concrete classes then store detailed information for specific elements such as players, enemies, and destructible tiles.

Below is a screenshot of the dependency diagram that illustrates the game’s architecture:

Level Parsing and Generation

Level Parsing and Generation

Level Parsing and Generation

The method parses a JSON representation of the level to instantiate and place interactable objects like players, enemies, and waypoints. It iterates through each object in the layer, extracting attributes such as position, rotation, and type, and invokes specific creation methods (e.g., createPlayer(), createEnemy()) to add them to the LevelModel. Additional properties, such as enemy ID, type, and labels, customize object behavior. This modular approach simplifies level updates and allows seamless addition of new object types without modifying core code.

Below is a code snippet illustrating map generation using a Tiled JSON file for characters and destructible tiles:

The method parses a JSON representation of the level to instantiate and place interactable objects like players, enemies, and waypoints. It iterates through each object in the layer, extracting attributes such as position, rotation, and type, and invokes specific creation methods (e.g., createPlayer(), createEnemy()) to add them to the LevelModel. Additional properties, such as enemy ID, type, and labels, customize object behavior. This modular approach simplifies level updates and allows seamless addition of new object types without modifying core code.

Below is a code snippet illustrating map generation using a Tiled JSON file for characters and destructible tiles:

The method parses a JSON representation of the level to instantiate and place interactable objects like players, enemies, and waypoints. It iterates through each object in the layer, extracting attributes such as position, rotation, and type, and invokes specific creation methods (e.g., createPlayer(), createEnemy()) to add them to the LevelModel. Additional properties, such as enemy ID, type, and labels, customize object behavior. This modular approach simplifies level updates and allows seamless addition of new object types without modifying core code.

Below is a code snippet illustrating map generation using a Tiled JSON file for characters and destructible tiles:

private void initializeCharacterLayer(LevelModel level, JsonValue layer, AssetDirectory directory){
        int x,y,rotation;
        int id;
        String enemyType;
        int base = 0;
        String type;
        String label;
        JsonValue objects = layer.get("objects").child();
        while (objects != null){
            x = objects.getInt("x");
            y = objects.getInt("y");
            rotation = objects.getInt("rotation");
            JsonValue properties = objects.get("properties").child();
            type = properties.getString("value");
            switch (type){
                case "player":
                    x+= 140;
                   level.createPlayer(x,(height*64-y),rotation,directory);
                    break;
                case "enemy":
                    properties = properties.next();
                    x+= 75;
                    id = properties.getInt("value");
                    properties = properties.next();
                    enemyType = properties.getString("value");
                    //System.out.println(id);
                    level.createEnemy(x,height*64-y,rotation,directory,enemyType, new int[] {(int)Math.floor((double) x /64), height - (int)Math.floor((double) y /64)}, id);
                    break;
                case "waypoint":
                    properties = properties.next();
                    id = properties.getInt("value");
                    properties = properties.next();
                    int pointNumber = properties.getInt("value");
                    x += 32;
                    //System.out.println(id);
                    level.addWaypoint(x,height*64 - y,id,pointNumber);
                    break;
                case "bouncy":
                    properties = properties.next();
                    id = properties.getInt("value");
                    properties = properties.next();
                    label = properties.getString("value");
                    level.createBouncy(x,(height*64-y),rotation,directory, id, label, -base);
                    break;
                case "breakable":
                    properties = properties.next();
                    id = properties.getInt("value");
                    properties = properties.next();
                    label = properties.getString("value");
                    level.createBreakable(x,(height*64-y),rotation,directory, id, label, -base);
                    break;
                case "goal":
                    properties = properties.next();
                    label = properties.getString("value");
                    level.createGoal(x,(height*64-y),rotation,directory, label, -base);
                    break;


            }
            objects = objects.next();
        }
    }
private void initializeCharacterLayer(LevelModel level, JsonValue layer, AssetDirectory directory){
    int x,y,rotation;
    int id;
    String enemyType;
    int base = 0;
    String type;
    String label;
    JsonValue objects = layer.get("objects").child();
    while (objects != null){
        x = objects.getInt("x");
        y = objects.getInt("y");
        rotation = objects.getInt("rotation");
        JsonValue properties = objects.get("properties").child();
        type = properties.getString("value");
        switch (type){
            case "player":
                x+= 140;
                level.createPlayer(x,(height*64-y),rotation,directory);
                break;
            case "enemy":
                properties = properties.next();
                x+= 75;
                id = properties.getInt("value");
                properties = properties.next();
                enemyType = properties.getString("value");
                //System.out.println(id);
                level.createEnemy(x,height*64-y,rotation,directory,enemyType, new int[] {(int)Math.floor((double) x /64), height - (int)Math.floor((double) y /64)}, id);
                break;
            case "waypoint":
                properties = properties.next();
                id = properties.getInt("value");
                properties = properties.next();
                int pointNumber = properties.getInt("value");
                x += 32;
                //System.out.println(id);
                level.addWaypoint(x,height*64 - y,id,pointNumber);
                break;
            case "bouncy":
                properties = properties.next();
                id = properties.getInt("value");
                properties = properties.next();
                label = properties.getString("value");
                level.createBouncy(x,(height*64-y),rotation,directory, id, label, -base);
                break;
            case "breakable":
                properties = properties.next();
                id = properties.getInt("value");
                properties = properties.next();
                label = properties.getString("value");
                level.createBreakable(x,(height*64-y),rotation,directory, id, label, -base);
                break;
            case "goal":
                properties = properties.next();
                label = properties.getString("value");
                level.createGoal(x,(height*64-y),rotation,directory, label, -base);
                break;


        }
        objects = objects.next();
    }
}

Copyright © 2024, Andy Pang. All rights reserved.

Copyright © 2024, Andy Pang. All rights reserved.

Copyright © 2024, Andy Pang. All rights reserved.