Full LibGDX Game Tutorial – Ashley & Steering Behaviors

Sharing is caring!

Full LibGDX Game Tutorial – Ashley & Steering Behaviors

Welcome to part 17 of our Full LibGDX Game Tutorial. This part will focus on linking Ashley, Box2D and Gdx-Ai together to allow entities to use steering behaviors. If you haven’t seen the earlier parts of this tutorial I advise you to start at Full LibGDX Game Tutorial – Project setup as this tutorial continues from these earlier parts. For those of you who have come from part 16, you can continue on.

In this part we will add the Gdx-Ai extension using gradle so it is included in our project. We will then add a few components for a new enemy type that will move towards the player using the Gdx-Ai steering behaviors.

Adding Gdx-Ai to your project

We have to add the Gdx-Ai extension to our project as we never added it when we created our project. We can do that by using gradle. Since we already have the repository “https://oss.sonatype.org/content/repositories/snapshots/” defined in our project all we need to do is add the Gdx-Ai dependency in our core project. I believe we also need it in our android dependency as well. Simply open your build.gradle file in the box2dtut project and add “com.badlogicgames.gdx:gdx-ai:1.8.0” to the file and save.

We then have to refresh our dependencies. We can do that in eclipse by right clicking on each project and going to Gradle(STS) > Refresh All. This will refresh the project and you will be prompted with a build message once completed and should look something similar to this:

Plugging our steering behaviors into Ashley

We can now add a new component for our steering behavior, let’s call it SteeringComponent so it’s job easily understood. The SteeringComponent will contain all the data for steering an entity. It will also have some methods that it gets from the Steerable interface so doesn’t fall into the Ashley ECS system very well as a component should only contain data. The benefits of being able to use prebuilt AI behaviors is more important to me than keeping the ECS system pure. So our component looks like this:

Here we have basically just implemented the steerable interface, added some behavior enums and linked the steering to our Box2D body. The update method is what we need to call in our system to update the steering. Since we added a new component we need to add a new component mapper to our Mapper class. We simply add:

And we’re done so let’s move into our system.

steering behaviors part-17

Building our Steering Behavior system

Our steering system is very simple as all it needs to do is update each entities SteeringComponent and update the Gdx-Ai timepiece. The timepiece is essentially a timer solely for the AI which allows pausing AI by not updating the timepiece. So our SteeringSystem looks like this:

Steering Behaviors

Gdx-Ai comes with a range of different behaviors and each one has its own set of properties that can be changed. Usually, this is done for each different type of enemy e.g. one type of enemy will have a big wander area whereas a different enemy will have a small area. Since we only have 1 enemy that will wander we will reuse the same wander settings again and again. To save us from adding code in different places for the same steering behavior we will add a static class that defines the different behaviors we will need.

Here we have added a wander behavior so we can have our enemies wander when there is no player close. We also have a seek and flee behavior that allows us to make an enemy run to or run away from another steering entity. Finally, we have the arrive behavior, which allows us to seek out a target and slow down when we get close.

A new Enemy for our new Steering Behaviors

We need to make a new enemy so we have something to attach our new steering behaviors to. We will create a new enemy that will float around randomly and then when it is close enough, move towards the player and if the player gets too close then the enemy will flee. So let’s make the enemy:

We have our method for creating a new enemy. We need to add it now to our level generation so it is generated as the level is generated and added to our world. While testing this out I noticed the player would sometimes die at the start of the level due to the enemies spawning in the same place or very close to the player. This isn’t good so the level generation has been updated to account for this as well as a few changes to generally improve the level generation. So, still in the levelFactory update the level generation code to:

I believe you can now test out a level and there will be enemies floating about for you to avoid. They will only wander about at the moment because we haven’t updated our enemy system to change their behaviors based on the distance to the player.

Switching Steering Behaviors based on player proximity

Our enemySystem should now be updated to include the code to change the behavior of our cloud enemies only. To do that we need to have to update our enemyComponent to:

This will allow us to check which enemy type we are processing and allow us to apply steering behaviors to only the cloud enemies. It will also allow us later to enable our enemies to shoot. We now have our enemyComponent updated we need to update our enemySystem to:

Here we have added some checks to check the distance of the player from the current entity. We have a set of if statements which we use to change the behavior of the enemy for each distance. We also have a check in those if statements to check that the state isn’t already in that state as we don’t want to overwrite a wander state with a wander state or the enemy would only ever do the first step of the wander state and would just move in a single direction.

Allowing Our Enemies to shoot

We already added some variables for the enemy component to allows us to shoot, Now all we need is a way for them to shoot. To allow them to do this we will update our enemySystem again:

Here we check that the enemy is in the arrive state (a state where we know the enemy has the player in their sights) Then we check if the timer has elapsed enough time to allow the enemy to shoot. Similar to the player shooting code. Next, we use a new DFUtil called aimTo. I added this as its a common set of code in many games and the code is:

Now when the enemy shoots, it kills itself which, let’s face it, isn’t very good. We need a way for the bullets to know which entity type they’re from so that we can ignore collisions from its own side. We need to update our bullet component to this:

We have added an enum that will identify what type of entity shot this bullet. Now we need to update the collisionSystem so it can change what happens depending on the type of bullet:

What we have done is made a check to see who fired the bullet. if it’s from a friendly team member or from themselves it is ignored. If it isn’t then it sets the entity to dead as usual.

[embedyt] https://www.youtube.com/watch?v=iaFIVhAMMvs[/embedyt]

In this part we have added 2 steering behaviors; wander and seek. We also have a new enemy which can shoot at the user. From this part onwards I will be adding the code to github with a branch for each part. This part is available from https://github.com/dfour/box2dtut/tree/part17 .


← Particle Effects Contents Coming Soon →


Sharing is caring!

4 Replies to “Full LibGDX Game Tutorial – Ashley & Steering Behaviors”

  1. Very good game development covering all aspects of creating a game using Box2D in libGDX for people new to programming. Worth reading who wants to make their first game.

    Learn Level Design with Blender and Unity 3D

  2. Hello!
    You are doing a magnificent job!
    It really helped me understand many core concepts.
    Could you please create a tutorial on Behavior Trees?
    I looked all over the net there aren’t any step by step tutorials.
    I have been looking at the tests created in the official documentation but its hard to piece together.

  3. hola
    colo me salen las texturas de las llamas

  4. Years later, but thanks for all the content. i found this all very helpful.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.