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.

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.

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.

Improved Sprite System For Games

In my ninth video for the “Building a Game Development Framework” series, I focus on establishing a professional-grade Sprite System. I enhance the framework, moving from loose animation and movement logic into a structured architecture by introducing two primary classes: Decor and Actor.

To better manage a game world, the framework now separates objects based on their behavior:

  • Decor: Represents static elements that do not move or have complex logic, such as a rock or a building. These are lightweight and optimized for objects that just need to be drawn.
  • Actor: Represents dynamic, “living” entities that can move, animate, and react to logic (e.g., players, enemies, or NPCs).

The “Sprite” in this framework acts as the parent container. It ties together the separate components built in previous videos into a single, cohesive unit:

  • Movement: Handles the math of where the object is going (Keyboard, Mouse, or AI).
  • Motion: Manages which animation set to use based on the heading (4-way, 8-way, etc.).
  • Animation: Handles the actual frame-by-frame rendering.

In this video, I demonstrate how to build the Actor class to automate the character’s update loop.

  • Automated Updates: Instead of manually calling movement.update() and motion.update() in your screen’s render method, you now simply call actor.update(). The Actor class internally handles data (delta time) delegation between its movement and motion components.
  • Flexibility: Because the Actor uses the Movement and Motion interfaces, you can swap a player’s controls from “Keyboard” to “Mouse” just by changing one line of code during initialization, without changing how the character is drawn or updated.

I then integrate this with the LibGdx library by updating the Screen class logic, making the game screen significantly less cluttered. Instead of managing individual floats for X and Y or multiple animation timers, the screen simply holds a list of Sprite objects and iterates through them to call update() and draw().

By separating Decor from Actors, you optimize performance (static objects don’t need movement logic) and create a system where complex game entities are built like “Legos.” This modularity makes it easy to add features like pathfinding or new animation types later in development without breaking existing characters.

Note: Since this is part of a series, this video serves as the “bridge” that turns the experimental code from earlier videos into a structured framework ready for actual game projects.

Movement using a mouse

In my eighth installment of the “Building a Game Development Framework” series, I expand on the movement system to include mouse-based interaction and introduce visual translucency for sprites.

I have created a new Movement class that allows characters to move toward a target destination clicked by the user.

  • Goal-Oriented Logic: The class tracks a goalX and goalY. When the user clicks, the system calculates the direction from the Sprite’s current position to the click point and moves the character at a set speed.
  • Overshoot Prevention: To prevent the Sprite from going past the target, the code includes logic to check whether the next move would exceed the goal. If so, it simply sets the character’s position to the exact goal coordinates.
  • Continuous Tracking: If the mouse button is held down, the character will continuously follow the cursor.

To make the movement classes more flexible, the framework now uses a SpriteUpdate interface. This acts as a bridge (using a visitor pattern) that allows the movement logic to “get” and “set” the X and Y coordinates of any object, whether it’s a player character or an NPC, without the movement class needing to know the specific details of that object.

A significant challenge in 2D games is clicking on the screen when the camera has moved or is moving.

  • The Problem: Standard input gives “screen coordinates,” but if your camera has scrolled to the right (or any direction from center), a click at screen position (100, 100) is actually a different coordinate on the game’s screen (game world).
  • The Solution: The ScreenInput class is updated to take the camera’s position into account when returning the location of the mouse click on the world map. It offsets the raw mouse input by the camera’s current X and Y coordinates, ensuring that clicking on a world object always works regardless of where the viewport is positioned.

Additionally, I added a “translucency” property (often called Alpha, or sometimes transparency) to the animation and motion interfaces.

  • Value Range: A float from 0.0 (fully invisible) to 1.0 (fully opaque).
  • Inheritance: Setting the translucency on a Motion object automatically applies it to all underlying animations (4-way, 8-way, etc.).
  • Visual Trick for “Behind Walls”: I demonstrate a clever rendering trick for characters walking behind objects (or through objects). Instead of making the character translucent, you render the character in front of an opaque image and behind another layer, then the front layer is rendered semi-transparent. This creates a professional-looking “X-ray” effect where the character appears to be obscured but still visible.

I also point out a subtle LibGDX “gotcha”: the built-in color constants (like Color.WHITE) are actually mutable objects. If you change the alpha of Color.WHITE for one sprite, it would change it for every other sprite using that constant. To fix this, the framework now creates a new color object every time a color or translucency is set, ensuring visual isolation between sprites

Movement in Games

In this video for “Building a Game Development Framework” series, I focus on integrating LibGDX input handling into my custom 2D framework. The goal is to move away from complex, repeated logic and instead encapsulate movement and input into reusable classes.

First, I handle the coordinate system. A common issue in game development is that mouse input coordinates often start from the top-left, while OpenGL (used by LibGDX) renders from the bottom-left. I created a ScreenInput helper class to:

  • Flip the Y-axis: Automatically subtracts the input Y-position from the screen height so the “game world” Y matches the “input” Y.
  • Delta Movement: Provides methods to get the change in mouse position (DeltaX, DeltaY), which is essential for mechanics like first-person camera rotation or smooth scrolling.

Then I demonstrate the difference between the primary LibGDX input polling methods:

  • isButtonPressed vs. isButtonJustPressed: The former returns true as long as a button is held down (useful for continuous fire), while the latter fires only once per click (useful for menus).
  • Key Input: Similar logic is applied to keyboard keys using Gdx.input.isKeyPressed.
  • Multi-touch: Brief mention of how to handle specific finger indexes for mobile development.
  • Text Input: A quick look at a built-in dialog for simple user text entry.

Then I explain my Movement Interface and its implementations, which decouple “how a character moves” from “how the animation is drawn.”

  • Base Movement & Magnitudes: A base class calculates movement “magnitudes” using sine and cosine. This ensures that when a character moves diagonally, they don’t move faster than they do horizontally or vertically (maintaining a consistent speed).
  • Two-Key Movement: Encapsulates logic for moving along a single axis (e.g., Left/Right or Up/Down) using two specified keys.
  • Four-Key Movement: Handles full 2D movement. It includes a “Multi-key” mode that allows for diagonal movement (8 directions) by checking if two keys (like Up and Right) are pressed simultaneously.

I sum this up by showing how the framework simplifies the code. Instead of writing complex if statements in every character class, a developer only needs about five lines of code to:

  1. Initialize the movement type (e.g., FourKeyMovement).
  2. Update the movement with delta time.
  3. Update the animation’s direction based on the movement’s calculated heading.
  4. Update the character’s X and Y coordinates using the movement’s calculated updates.

This modularity allows for easy swapping of controls—for example, switching a character from keyboard controls to a different input method—without touching the animation logic.

Motion in Games

In my sixth video from the “Building a Game Development Framework” series, I demonstrate how to build a robust Motion System on top of the LibGDX framework. This system is designed to simplify how character animations are managed and triggered based on the movement direction.

The core of this system is the Motion interface. Similar to the Animation class from the earlier videos, the “motion” encapsulates all the possible animations for a character (e.g., walking north, south, east and west) and decides which one to play base on the character’s current heading.

To handle the movement logic, I introduce a Direction class that uses the FastMath utility class for performance. This class contains:

  • Pythagorean Theorem & Angles: It calculates the angle of movement between an origin and destination.
  • Cardinal Directions: It includes methods to snap to a precise degree (0–360) to the nearest 4-way (North, South, East, West) or 8-way cardinal directions.
  • Normalization: A helper method ensures angles always stay within the 0 to 360-degree range.

I developed classes in the framework to be used depending on how complex your character’s visuals are:

  • Single Motion: Displays the same animation regardless of direction (useful for objects like a spinning coin or a single Animation).
  • Two-Way Motion: Switches between two animations, typically for horizontal (left/right) or vertical (up/down) movement.
  • Four-Way & Eight-Way Motion: These implementations map animations to the standard cardinal and inter-cardinal directions. I show how to streamline this by creating constructors that take a single sprite sheet and automatically slice the necessary frames for each direction.

Since the Motion class contains Animations, it supports the Animation’s set color method, making it easy to change the color.

A significant addition, I added, is the LayeredAnimation class. This allows you to stack multiple animations on top of each other. This Animation class allows several Animations to be treated as a single Animation, layering them to produce a single object. The first Animation added is the bottom layer, and subsequent additions are rendered on top. Here I demonstrated with the “Magic Egg”, with a ring and egg underneath it. This allows us to color these two separately.

This modular approach allows game developers to change a character’s “Motion” type (e.g., from 4-way to 8-way) without rewriting their core game logic, making the framework highly flexible for different art styles.

Animated images

In my third video, Rendering animated images in LibGdx, I show how LibGdx has a TextureRegion for splitting the cells of an animation sequence. I demonstrate the Animation class and how setting the PlayMode, you can achieve different looping techniques. There are LOOP, LOOP_PINGPONG, LOOP_RANDOM, LOOP_REVERSED, NORMAL and REVERSED. It is nice to have that in a single class. One feature that I didn’t see, was having it loop a set number of times. I show how to implement that manually, by using the getKeyFrame() and passing in a boolean for continuous looping. You have to manually keep track of the number of loops.

I then move on to the additional parameters to the getKeyFrame() method for resizing, by passing in additional values for the size in pixels you want the image to appear at. Then, I show the rotation, including setting the origin, and show you how the rotation degree affects the resulting image. I then show how the rotation with the counter-clockwise boolean, and how the size (height and width) are flipped in this implementation. I find it odd that with the counter-clockwise rotation, they change the height and width direction from the source image. Not what I would expect from just setting the direction to counter-clockwise.

I finish off this video with a character walking around the screen and what is involved in coding that.

In the fourth video, Creating an Animation Framework for LibGdx, I build a framework around the Animation of images, to simplify the entire process. This is based on the Animation framework I used in my Old Style Game Framework. I start with rending a single image in the StaticAnimation class. I move the values from the method parameters into class attributes, thus removing complexity in just drawing an image on the screen. This also give flexibility to easily change the size and orientation of a single image.

Finally, in my fifth video, Updating the Animation Framework for LibGdx, I build out a BaseAnimation class for storing common attributes and extend it with three classes: LoopAnimation, BounceAnimation, and RandomAnimation. The LoopAnimation handles going through the sequence any number of times, one to many times. Also, handling the “ping-pong” animation, bouncing forward and backward. Again, the changing of the size and rotation are the same methods as in the StaticAnimation. This gives us a familiar framework between different types of animating. Having common ways of changing an animation’s size and rotation makes working with the classes easier. It also removes the multi-parameter method out of sight. As an additional feature, I have the animation loop, or bounce, a set number of times as well.

I will enhance the framework in the sixth video, which will simplify the animation of a character walking.

Animation Effects

Imaging effects in my original Old Style Game Framework was more “involved” to get it to work. I had to make it as an added feature of the Animation class, by creating the ImageFx class. Effects that dealt with color changes; brightening, darkening, changing color, etc, involved more complicated procedures and using a BufferedImageOp object to do the operation. Rotating the image involved using the AffinsTransform class. One thing about this class is that you had to be careful where the “center” of the rotation is; if you move the object and then try to rotate it, you get a different effect than rotating it and then moving.

LibGDX, with the underlying LWJGL framework underneath it, makes much of this trivial. The SpriteBatch’s draw method has arguments for rotating, shrinking and enlarging, cropping and even flipping the image horizontally and/or vertically.

public void draw(TextureRegion region, float x, float y, float originX, float originY, float width, float height, float scaleX, float scaleY, float rotation)

public void draw(Texture texture, float x, float y, float originX, float originY, float width, float height, float scaleX, float scaleY, float rotation, int srcX, int srcY, int srcWidth, int srcHeight, boolean flipX, boolean flipY)

The use of the booleans to flip the image can also be achieved by using the method that takes U and V values and reversing them. I demonstrated this in my second video on still image rendering. Coloring and translucency effects are done by setting the color on the SpriteBatch.

SpriteBatch.setColor(new Color(red, green, blue, translucency or alpha));

In my framework, I integrated this within the BaseAnimation class. Using a framework, takes away all the hard work in making a game.

A step beyond Animation

Animation is key to any 2D Game, but one aspect I didn’t want to overlook was how to make switching between different animations by the direction in which a sprite is moving. To me, this logic is repeated again and again in a 2D Game. You move your character across the screen, then back again. If your character walks (or runs) from left to right across the screen, then he moves back (from right to left), you either have him run backward or change his direction. The variance is in how many directions the character can go. Does the character only move in one direction? Is he able to only move left and right? Can he jump? Does he move in four directions or eight? No matter which kind of game you make, your sprites will move in some direction, likely multiple directions.

I feel that this is another item to be added to the framework. The hard part was to figure out the names of the classes. My first thought was Movement, which is confusing with the sprite actually moving, so I came up with the class name of Motion. What the Motion class does is encapsulate the transitioning of Animations based on the direction in which the Sprite moves. If you remember in my third video, making the Animations switch between directions can get excessive. When the sprite moves from left to right, it uses the Animation for that direction, and when it moves from right to left it uses the Animation for that direction. Since the Motion classes internally use Animation objects, the developer is free to put in any type of Animation class they want, including using the same Animation.

Now, you can have a sprite that has a looping Animation when moving from down to up and a static (non-changing) Animation when moving from up to down. If you decide to change how the sprite will be animated, you just have to change the Animation used in the Motion class. This makes changes easier and gives the flexibility to experiment with different animation sequences.

A Note about the Animation and Motion classes is that they don’t deal with placing the image on the screen. The location where these images are placed must be passed into the draw method. The Motion forwards that location to the Animation class. The Motion class has an additional method for setting the direction, which it will use to determine which Animation class to use for rendering.