### Dog Behavior Tree Example (gdx-ai) Source: https://github.com/libgdx/gdx-ai/wiki/Behavior-Trees An example behavior tree for a dog, demonstrating the use of aliases, selectors, parallel tasks, sequences, and fully qualified task names. It includes comments explaining different parts of the tree. ```plaintext # # Dog tree # # Alias definitions import bark:"com.badlogic.gdx.ai.tests.btree.dog.BarkTask" import care:"com.badlogic.gdx.ai.tests.btree.dog.CareTask" import mark:"com.badlogic.gdx.ai.tests.btree.dog.MarkTask" import walk:"com.badlogic.gdx.ai.tests.btree.dog.WalkTask" # Tree definition (note that root is optional) root selector parallel care urgentProb:0.8 alwaysFail com.badlogic.gdx.ai.tests.btree.dog.RestTask # fully qualified task sequence bark times:"uniform,1,3" # the type of attribute times is an IntegerDistribution walk com.badlogic.gdx.ai.tests.btree.dog.BarkTask # fully qualified task mark ``` -------------------------------- ### Find Path Using Indexed A* Algorithm in Java Source: https://context7.com/libgdx/gdx-ai/llms.txt This Java code snippet demonstrates how to implement and use the Indexed A* pathfinding algorithm. It includes a `GridGraph` class representing a 2D grid with connections and a `PathfindingExample` class that utilizes `IndexedAStarPathFinder` with a Manhattan distance heuristic to find a path between a start and goal node. The output indicates whether a path was found and lists the nodes in the path. ```java import com.badlogic.gdx.ai.pfa.Connection; import com.badlogic.gdx.ai.pfa.DefaultConnection; import com.badlogic.gdx.ai.pfa.DefaultGraphPath; import com.badlogic.gdx.ai.pfa.GraphPath; import com.badlogic.gdx.ai.pfa.Heuristic; import com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder; import com.badlogic.gdx.ai.pfa.indexed.IndexedGraph; import com.badlogic.gdx.utils.Array; // Graph node class GridNode { int x, y; int index; public GridNode(int x, int y, int index) { this.x = x; this.y = y; this.index = index; } } // Graph implementation class GridGraph implements IndexedGraph { private Array nodes; private Array>> connections; public GridGraph(int width, int height) { nodes = new Array<>(); connections = new Array<>(); // Create grid nodes for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { nodes.add(new GridNode(x, y, y * width + x)); connections.add(new Array<>()); } } // Create connections (4-directional) for (GridNode node : nodes) { if (node.x > 0) addConnection(node, getNode(node.x - 1, node.y), width); if (node.x < width - 1) addConnection(node, getNode(node.x + 1, node.y), width); if (node.y > 0) addConnection(node, getNode(node.x, node.y - 1), width); if (node.y < height - 1) addConnection(node, getNode(node.x, node.y + 1), width); } } private void addConnection(GridNode from, GridNode to, int width) { connections.get(from.index).add(new DefaultConnection<>(from, to)); } private GridNode getNode(int x, int y) { for (GridNode node : nodes) { if (node.x == x && node.y == y) return node; } return null; } @Override public Array> getConnections(GridNode fromNode) { return connections.get(fromNode.index); } @Override public int getIndex(GridNode node) { return node.index; } @Override public int getNodeCount() { return nodes.size; } } // Usage public class PathfindingExample { public void findPath() { GridGraph graph = new GridGraph(10, 10); // Create heuristic (Manhattan distance) Heuristic heuristic = new Heuristic() { @Override public float estimate(GridNode node, GridNode endNode) { return Math.abs(node.x - endNode.x) + Math.abs(node.y - endNode.y); } }; // Create pathfinder IndexedAStarPathFinder pathfinder = new IndexedAStarPathFinder<>(graph); // Find path from (0,0) to (9,9) GridNode start = new GridNode(0, 0, 0); GridNode goal = new GridNode(9, 9, 99); GraphPath path = new DefaultGraphPath<>(); boolean found = pathfinder.searchNodePath(start, goal, heuristic, path); if (found) { System.out.println("Path found with " + path.getCount() + " nodes:"); for (int i = 0; i < path.getCount(); i++) { GridNode node = path.get(i); System.out.println(" -> (" + node.x + ", " + node.y + ")"); } } else { System.out.println("No path found!"); } } } ``` -------------------------------- ### Create Finite State Machine with Callbacks and Messages (Java) Source: https://context7.com/libgdx/gdx-ai/llms.txt This Java code demonstrates the creation of a Finite State Machine for an 'Agent' entity using LibGDX's gdx-ai library. It defines states like IDLE, PATROL, and FLEE, each with enter, update, exit, and message handling callbacks. The example shows how to initialize the state machine, update its state, change states based on conditions, handle incoming messages for state transitions, and revert to previous states. ```java import com.badlogic.gdx.ai.fsm.DefaultStateMachine; import com.badlogic.gdx.ai.fsm.State; import com.badlogic.gdx.ai.fsm.StateMachine; import com.badlogic.gdx.ai.msg.Telegram; // Entity owning the state machine class Agent { String name; int health = 100; public Agent(String name) { this.name = name; } } // Define states enum AgentState implements State { IDLE { @Override public void enter(Agent entity) { System.out.println(entity.name + " entering IDLE state"); } @Override public void update(Agent entity) { System.out.println(entity.name + " is idle..."); } @Override public void exit(Agent entity) { System.out.println(entity.name + " exiting IDLE state"); } @Override public boolean onMessage(Agent entity, Telegram telegram) { if (telegram.message == 1) { // Attack message entity.health -= 20; return true; } return false; } }, PATROL { @Override public void enter(Agent entity) { System.out.println(entity.name + " starting patrol"); } @Override public void update(Agent entity) { System.out.println(entity.name + " is patrolling..."); if (entity.health < 50) { entity.stateMachine.changeState(FLEE); } } @Override public void exit(Agent entity) { System.out.println(entity.name + " ending patrol"); } @Override public boolean onMessage(Agent entity, Telegram telegram) { return false; } }, FLEE { @Override public void enter(Agent entity) { System.out.println(entity.name + " fleeing! Health: " + entity.health); } @Override public void update(Agent entity) { System.out.println(entity.name + " is running away!"); } @Override public void exit(Agent entity) { System.out.println(entity.name + " stopped fleeing"); } @Override public boolean onMessage(Agent entity, Telegram telegram) { return false; } } } // Extend Agent to include state machine class Agent { String name; int health = 100; StateMachine stateMachine; public Agent(String name) { this.name = name; this.stateMachine = new DefaultStateMachine<>(this, AgentState.IDLE); } } // Usage public class StateMachineExample { public void runStateMachine() { Agent agent = new Agent("Guard"); // Initial state agent.stateMachine.update(); // Output: "Guard is idle..." // Change state agent.stateMachine.changeState(AgentState.PATROL); // Output: "Guard exiting IDLE state" // "Guard starting patrol" agent.stateMachine.update(); // Output: "Guard is patrolling..." // Damage agent to trigger state change agent.health = 30; agent.stateMachine.update(); // Output: "Guard is patrolling..." // "Guard ending patrol" // "Guard fleeing! Health: 30" // Revert to previous state agent.stateMachine.revertToPreviousState(); // Output: "Guard stopped fleeing" // "Guard starting patrol" } } ``` -------------------------------- ### TelegramProvider's provideMessageInfo Method (Java) Source: https://github.com/libgdx/gdx-ai/wiki/Message-Handling This code illustrates the `provideMessageInfo` method within a TelegramProvider. This method is invoked when a new Telegraph starts listening to a message type. It returns immediate information for the message, or null if no extra information should be dispatched. ```java Object provideMessageInfo (int msg, Telegraph receiver); // Returning null means no Telegram will be dispatched by the TelegramProvider. ``` -------------------------------- ### Maven Repository Configuration for gdx-ai Source: https://github.com/libgdx/gdx-ai/wiki/Setting-up-your-Development-Environment Configures the Maven repository in your pom.xml to fetch gdx-ai releases. Ensure the URL matches whether you need stable releases or snapshot builds. ```xml sonatype Sonatype https://oss.sonatype.org/content/repositories/releases ``` -------------------------------- ### Gradle Repository Configuration for gdx-ai Source: https://github.com/libgdx/gdx-ai/wiki/Setting-up-your-Development-Environment Configures the Gradle repositories in your build.gradle file to include locations for gdx-ai releases and snapshots. This allows Gradle to download the library. ```groovy repositories { maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } maven { url "https://oss.sonatype.org/content/repositories/releases/" } } ``` -------------------------------- ### Initialize GdxAI Core Services in Java Source: https://context7.com/libgdx/gdx-ai/llms.txt Initializes and configures the core services of the gdxAI framework using a service locator pattern. It retrieves default implementations for Timepiece, Logger, and FileSystem, or allows setting custom ones. The Timepiece needs to be updated each frame. ```java import com.badlogic.gdx.ai.GdxAI; import com.badlogic.gdx.ai.Timepiece; import com.badlogic.gdx.ai.Logger; import com.badlogic.gdx.ai.FileSystem; public class AIGameManager { private Timepiece timepiece; private Logger logger; public void initialize() { // Get default services (automatically configured) timepiece = GdxAI.getTimepiece(); logger = GdxAI.getLogger(); FileSystem fileSystem = GdxAI.getFileSystem(); // Or set custom implementations GdxAI.setTimepiece(new CustomTimepiece()); GdxAI.setLogger(new CustomLogger()); logger.info("AI", "gdxAI initialized successfully"); } public void update(float deltaTime) { // Update timepiece each frame for delayed messages and time-based AI timepiece.update(deltaTime); } } ``` -------------------------------- ### Maven Dependency Configuration for gdx-ai Source: https://github.com/libgdx/gdx-ai/wiki/Setting-up-your-Development-Environment Adds the gdx-ai library as a dependency in your pom.xml. Specify the desired version for your project. This is for official releases. ```xml com.badlogicgames.gdx gdx-ai 1.8.1 ``` -------------------------------- ### Gradle Dependency Configuration for gdx-ai Source: https://github.com/libgdx/gdx-ai/wiki/Setting-up-your-Development-Environment Adds the gdx-ai library as a dependency in your build.gradle file. This line should be placed within the 'dependencies' block. ```groovy dependencies { classpath "com.badlogicgames.gdx:gdx-ai:1.8.1" } ``` -------------------------------- ### LibGDX Project Dependencies for gdx-ai (Gradle) Source: https://github.com/libgdx/gdx-ai/wiki/Setting-up-your-Development-Environment Adds gdx-ai as a compile dependency for different modules (core, android, html) within a LibGDX project using Gradle. Note the ':sources' for the HTML module. ```groovy project(":core") { dependencies { compile "com.badlogicgames.gdx:gdx-ai:1.8.1" } } project(":android") { dependencies { compile "com.badlogicgames.gdx:gdx-ai:1.8.1" } } project(":html") { dependencies { compile "com.badlogicgames.gdx:gdx-ai:1.8.1:sources" } } ``` -------------------------------- ### GWT Module Inheritance for gdx-ai Source: https://github.com/libgdx/gdx-ai/wiki/Setting-up-your-Development-Environment Includes the gdx-ai GWT module in your GdxDefinition.gwt.xml and GdxDefinitionSuperdev.gwt.xml files. This is necessary for GWT compilation. ```xml ``` -------------------------------- ### Java: Send and Receive Game Messages with MessageDispatcher Source: https://context7.com/libgdx/gdx-ai/llms.txt Demonstrates setting up a MessageDispatcher, defining message codes, creating game entities that implement the Telegraph interface, registering listeners, and sending immediate and delayed messages. It also shows how to update the dispatcher in a game loop to process scheduled messages. Dependencies include com.badlogic.gdx.ai.msg.*. ```java import com.badlogic.gdx.ai.msg.MessageDispatcher; import com.badlogic.gdx.ai.msg.Telegram; import com.badlogic.gdx.ai.msg.Telegraph; import com.badlogic.gdx.ai.GdxAI; // Message codes class Messages { public static final int ATTACK = 1; public static final int DEFEND = 2; public static final int HEAL = 3; } // Entity that can receive messages class GameEntity implements Telegraph { String name; int health = 100; public GameEntity(String name) { this.name = name; } @Override public boolean handleMessage(Telegram msg) { switch (msg.message) { case Messages.ATTACK: int damage = (Integer) msg.extraInfo; health -= damage; System.out.println(name + " received " + damage + " damage. Health: " + health); return true; case Messages.HEAL: int healAmount = (Integer) msg.extraInfo; health += healAmount; System.out.println(name + " healed " + healAmount + ". Health: " + health); return true; case Messages.DEFEND: System.out.println(name + " is defending!"); return true; default: return false; } } } // Usage public class MessageExample { public void setupMessaging() { MessageDispatcher dispatcher = new MessageDispatcher(); GameEntity player = new GameEntity("Player"); GameEntity enemy = new GameEntity("Enemy"); // Register listeners for broadcast messages dispatcher.addListener(player, Messages.HEAL); dispatcher.addListener(enemy, Messages.ATTACK); // Send immediate message to specific receiver dispatcher.dispatchMessage(player, enemy, Messages.ATTACK, 25); // Output: "Enemy received 25 damage. Health: 75" // Send delayed message (1.5 seconds delay) dispatcher.dispatchMessage(1.5f, enemy, player, Messages.ATTACK, 30); // Broadcast message to all registered listeners dispatcher.dispatchMessage(Messages.HEAL, 20); // Output: "Player healed 20. Health: 100" // In game loop, update dispatcher to handle delayed messages GdxAI.getTimepiece().update(0.016f); // Update time dispatcher.update(); // Process delayed messages // After 1.5 seconds of updates... for (int i = 0; i < 94; i++) { GdxAI.getTimepiece().update(0.016f); dispatcher.update(); } // Output: "Player received 30 damage. Health: 70" } } ``` -------------------------------- ### Create and Execute Behavior Tree in Java Source: https://context7.com/libgdx/gdx-ai/llms.txt Demonstrates creating and executing a behavior tree for AI decision-making. It defines a custom blackboard, leaf tasks (CheckHealthTask, FleeTask, AttackTask), and builds a hierarchical tree structure using Sequence and Selector nodes. The tree is executed using the step() method. ```java import com.badlogic.gdx.ai.btree.BehaviorTree; import com.badlogic.gdx.ai.btree.LeafTask; import com.badlogic.gdx.ai.btree.branch.Selector; import com.badlogic.gdx.ai.btree.branch.Sequence; import com.badlogic.gdx.math.Vector2; // Blackboard object class EnemyBlackboard { float health; boolean enemyVisible; Vector2 enemyPosition; } // Custom leaf tasks class CheckHealthTask extends LeafTask { @Override public void run() { if (getObject().health < 30) { success(); } else { fail(); } } @Override protected LeafTask copyTo(LeafTask task) { return task; } } class FleeTask extends LeafTask { @Override public void run() { System.out.println("Fleeing from danger!"); success(); } @Override protected LeafTask copyTo(LeafTask task) { return task; } } class AttackTask extends LeafTask { @Override public void run() { System.out.println("Attacking enemy at: " + getObject().enemyPosition); success(); } @Override protected LeafTask copyTo(LeafTask task) { return task; } } // Usage public class BehaviorTreeExample { public void createEnemyAI() { EnemyBlackboard blackboard = new EnemyBlackboard(); blackboard.health = 25; blackboard.enemyVisible = true; blackboard.enemyPosition = new Vector2(100, 200); // Build tree: If low health, flee. Otherwise, attack if enemy visible. Selector root = new Selector<>(); Sequence fleeSequence = new Sequence<>(); fleeSequence.addChild(new CheckHealthTask()); fleeSequence.addChild(new FleeTask()); root.addChild(fleeSequence); root.addChild(new AttackTask()); BehaviorTree tree = new BehaviorTree<>(root, blackboard); // Execute tree each frame tree.step(); // Output: "Fleeing from danger!" // Update blackboard and re-execute blackboard.health = 100; tree.step(); // Output: "Attacking enemy at: (100.0, 200.0)" } } ```