GameMaps and Layers

In the seventeenth video of the “Building a Game Development Framework” series, I implement a sophisticated Layering System and a new architectural concept called Game Maps. These updates provide 3D-like depth in a 2D game, enabling objects to be rendered on top of one another and moved across different visual planes.

I go from managing sprites directly in the Screen class to using a GameMap.

  • Centralized Logic: SimpleScreen is moved into the BaseScreen, and the logic for storing and updating sprites is delegated to the GameMap.
  • Custom Iterators: To handle complex updates (like removing an object from one layer and adding it to another in the same frame), the creator implements a custom Iterator. This prevents “Concurrent Modification Exceptions” when the game tries to update the list of objects while it is still drawing them.

Entities now possess a layer property (an integer), allowing the framework to sort them from back to front.

  • Rendering Order: The GameMap renders objects starting from layer 0 upward. Objects in higher layers are naturally drawn on top of those in lower layers.
  • Collision by Layer: To optimize performance and enable complex interactions, collision detection is updated to only check objects that are currently in the same layer.

Building on the previous “Mouse Drag” system, I add the ability to physically “lift” an object to a higher layer when it is grabbed.

  • Vertical Transitions: When a user clicks a chip (like in Checkers), the movement class automatically increments its layer. This visually pulls the piece “up” toward the camera.
  • Reversion on Collision: If a user tries to “drop” a piece into a lower layer where another object already exists, the framework detects the collision, reverses the layer change, and prevents the drop.

With multiple layers and overlapping sprites, a major technical hurdle is ensuring that a single click doesn’t trigger multiple objects simultaneously.

  • The Lock System: The creator introduces an InputLocks object. When an actor is grabbed, it “locks” the mouse input to itself. Even if the user drags that actor over another one, the second actor ignores all input because it doesn’t hold the lock.
  • Two-Step Clearing: Unlocking is handled as a two-step process to ensure that a “release” click doesn’t accidentally trigger a different object on the frame immediately following the drop.

I show these features using red and black checker chips on a board:

  • Stacking: Pieces can now be moved over one another without colliding if they are at different heights (layers).
  • Layer Toggling: When a piece is clicked, it visually pops to the top layer. When released, it settles back down into the base layer.
  • Drop Logic: You can successfully drag a piece over another, but you cannot “drop” it unless the square underneath is empty.

By the end of this video, the framework supports complex 2D depth, allowing for board games, top-down RPGs with multi-level environments, or UI systems with overlapping windows.

The Gdx2DGameFramework can be found here on github.

Building a Simple Game with the Framework

I my thirteenth video of the “Building a Game Development Framework” series, I change things up by using the framework to build a functional Shoot ‘Em Up (Shmup) style game. This project shows how to use the framework in a game development scenario. It focuses on using the framework’s features, such as input handling, movement scripting, and collision detection.

First I update the framework to the latest versions.

  • LibGDX 1.12.1: I updated the framework to the latest version of LibGDX.
  • LWJGL3 Transition: With newer LibGDX versions, the backend transitions from LWJGL2 to LWJGL3. This requires updating the DesktopLauncher configuration to use Lwjgl3ApplicationConfiguration, which changes how window titles, icons, and dimensions are set.

Implementing the Game

I build the player character using the Actor class:

  • Movement Constraints: First, I override the update method to prevent the ship from moving off-screen. The Movement checks the X-coordinate and “clamps” it so the ship stops just before hitting the window edges.
  • Audio Integration: A laser sound effect (created in ChipTone) is triggered whenever the player presses the Space key.

To handle many objects on screen (like hundreds of lasers or falling obstacles), I create the Actor Factory class with Object Pooling:

  • The Problem: Creating a new “Laser” object every time the player fires is memory-intensive and can cause lag.
  • The Solution (Pooling): The factory maintains a Queue of pre-created actors. When a laser is needed, it’s pulled from the queue and “reset.” When it leaves the screen, it’s added back to the queue for reuse instead of being deleted.

The game needs a way to spawn enemies or obstacles over time. I made these updates to accomplish that:

  • Updatable Interface: A new interface is added for logic that needs to run every frame but doesn’t have a visual sprite (like a “spawner” or “game manager”).
  • Randomized Spawning: The ObstacleFactory implements Updatable. Every 1 second, it picks a random X-coordinate and spawns a falling block at the top of the screen.

The collision logic between lasers and obstacles utilizes the movement scripts built in the previous video:

  • Hit Logic: When a laser hits an obstacle, it doesn’t just disappear. The obstacle’s movement script transitions to an Easing Action, causing it to slow down and changing its color to red (simulating being “destroyed”) before eventually being removed and returned to the pool.
  • Collision Filtering: To prevent “ghost” collisions, the obstacle’s contains method is overridden to return false once it has been destroyed, allowing other lasers to pass through it while it’s in its death animation.

By the end of the video, the user has a playable demo where they can move a ship, fire lasers, and destroy falling obstacles with smooth transitions and efficient memory management.

The Gdx2DGameFramework can be found here on github.

Scripting Movement

In my twelfth video of the “Building a Game Development Framework” series, I introduce a Scripted Movement System. This allows developers to define a sequence of automated actions for Non-Player Characters (NPCs) or cinematic events without writing manual update logic for every frame.

Before diving into scripting, I made a few essential adjustments to the core framework:

  • Window Resizing: Desktop window sizes are now correctly handled via LibGDX configurations and the resize method, ensuring the game’s internal coordinate system matches the actual window dimensions.
  • Safe Sprite Removal: To avoid “Concurrent Modification Exceptions” (crashes when deleting a sprite while the game is still drawing or updating it), the framework now uses a “To Be Added” list and a removed flag. Sprites are only physically added or removed from the main list between render cycles.
  • Clean Interfaces: Redundant methods were removed from the Movement interface, delegating all positional updates to the SpriteUpdate class.

The scripting system is built around two main components:

  • ScriptMovement: The “brain” that holds a list of actions and executes them one by one. Once an action reports it is “done,” the script automatically transitions to the next one in the list.
  • ScriptAction: The base class for specific behaviors (waiting, moving, turning). It includes logic for Gradual Direction Changes, allowing actors to make smooth arcs rather than “snapping” to a new heading.

I detail several specialized actions that can be chained together:

  • Wait Action: Pauses the actor for a set duration. You can also specify a direction for the actor to face while waiting.
  • Time Movement Action: Moves the actor in a specific direction at a set speed for a fixed amount of time.
  • Change Speed Action: Gradually accelerates or decelerates the actor over time.
  • Destination Action: Moves the actor to a specific (X, Y) coordinate. It uses the Pythagorean theorem to calculate the distance and ensures the actor stops exactly on the target.
  • Easing Action: Provides advanced acceleration/deceleration curves (Linear, Quadratic, Cubic, etc.). This allows for “juicy” movement where an actor starts slow and “eases in” to a high speed.
  • Go-To Action: A logic-based action that jumps to a previous step in the script, allowing for infinite loops or repeating patterns.

I then demonstrate how to combine these actions to create a complex patrol path:

  1. Ease In: The character starts from a standstill and slowly speeds up.
  2. Move to Destination: The character hits a series of four (X, Y) coordinates to walk in a square.
  3. Go-To: After the fourth corner, a GoToAction sends the script back to the second step, creating a permanent walking loop.

This scripting system significantly reduces the complexity of AI behavior, allowing developers to “choreograph” NPCs using a simple list of commands.

The Gdx2DGameFramework can be found here on github.

Handling Collisions in Video Games

In my eleventh video of the “Building a Game Development Framework” series, I implement Collision Detection and update the Screen Management system. This update allows game objects to interact with each other physically and simplifies how developers add entities to their game world.

I make the foundation of the collision system the BoundingBox class.

  • AABB (Axis-Aligned Bounding Box): The framework uses simple rectangle-to-rectangle intersection checks. It verifies if the X or Y edges of one sprite fall within the span of another.
  • Insets and Offsets: A major improvement I made is adding Insets. Often, a sprite’s image (for example, 64×64 pixels) is much larger than the actual character (e.g., a person is thin, but the image is a square). With Insets this allows you to shrink the physical “hitbox” independently of the visual image so collisions will feel more realistic.

I setup the framework to categorizes collisions based on whether an object is an “Actor” or “Decor”. Since Decors do not move, they don’t check if they collide with another sprite. Actors, which move, do check if they collide with another sprite.

  • Impact Flag: Not all objects need to check for collisions. The doesImpact() method allows the system to skip checks for static background objects (Decor) that don’t move, saving processing power.
  • Reversion Logic: When a collision is detected, the framework “reverts” the character’s movement. In the basic implementation, it simply moves the character back to their previous non-colliding position.
  • Sliding Physics: In more advanced movement (like in 4-key or mouse movement), the framework checks horizontal and vertical collisions separately. If you walk diagonally into a wall, the X-movement might be blocked, but the system allows the Y-movement to continue, creating a “sliding” effect against the wall.

I also introduce the SimpleScreen, which automates the rendering loop:

  • The Sprite List: Instead of manually updating every character, the screen maintains a list of all Sprites.
  • Automated Loop: The renderChild method automatically iterates through the list, calls update(), performs detectCollision(), and then calls draw() for every entity.
  • Separation of Concerns: New abstract methods addActor() and addDecor() provide a clean way for developers to populate their game world during the show() phase.

To make the world feel more alive, I introduce a Random Sound class:

  • Footstep Variance: Instead of a single repetitive sound, this class holds a list of similar sounds (e.g., four different footstep recordings). Every time an animation triggers a sound, it randomly picks one from the list to create a more natural, less “robotic” audio experience.

I conclude with a demonstration of an Actor (the player) navigating around our “Soda Machine” Decor objects. I show how the player is physically blocked by the machines and how the “sliding” logic feels smoother than a hard stop.

This set of features transforms the framework from a simple animation player into a functional game engine where objects have physical presence and sound.

The Gdx2DGameFramework can be found here on github.

Sound and Music with LibGDX

In my tenth video of the “Building a Game Development Framework” series, I focus on integrating audio capabilities into the LibGDX framework. I cover the distinction between sound effects and music, how to manage their lifecycles, and how to trigger them within an animation system.

The LibGDX framework distinguishes between two types of audio objects based on how they are handled in memory:

  • Sound: Intended for short clips (typically < 10 seconds), such as explosions or footsteps. These are completely loaded into RAM.
  • Music: Intended for longer tracks, like background music or ambient loops. These are streamed from the storage device to save memory.

I demonstrate the primary methods for controlling both types of audio:

  • Playback: Simple .play(), .pause(), .resume(), and .stop() methods. Note that Music does not have a dedicated “resume” method; calling play() on a paused track automatically resumes it from where it left off.
  • Volume & Pitch: Volume is set as a float from 0.0 to 1.0. Pitch (available only for Sound) speeds up or slows down the audio to change its tone—useful for varied sound effects like different-pitched “hellos”.
  • Panning: Moves audio between the left and right speakers (values from -1.0 to 1.0). This only works on mono audio files.
  • Positioning: Specifically for Music, you can jump to a specific second in a track using setDevicePosition().

Because audio objects consume system resources, they must be “disposed” when no longer needed.

  • Automatic Disposal: I have updated the BaseScreen with maps for both Sound and Music objects. When a screen is closed, the framework automatically iterates through these maps and disposes of every audio file to prevent memory leaks.

Then I update my framework to have “Sound-Aware” animations. By adding a Sound field to the BaseAnimation class, animations can now trigger audio automatically:

  • Static/Block Animations: Play a sound once when they first appear on the screen.
  • Loop Animations: Play a sound at the start of every loop cycle (e.g., a footstep sound every time a walk cycle reaches the first frame).
  • Bounce Animations: Trigger sounds at both the beginning and the “apex” (last frame) of the animation, making it ideal for things like bouncing balls or swinging pendulums.
  • Random Animations: Use a counter to ensure a sound plays every time the animation completes a full set of frames, even though the frames themselves are randomized.

I then recommend two browser-based tools for generating 8-bit/16-bit sound effects for game development:

  • SFXR: A classic generator for “retro” sounds.
  • ChipTone: A more modern, user-friendly version of SFXR for creating explosions, jumps, and other game effects.

The Gdx2DGameFramework can be found here on github.