Test Driven Development is Pretty Cool

A couple of years ago I stumbled over one of the best articles about test-driven development I ever read. Even the title is crispy I mean Stepping Through the Looking Glass: Test-Driven Game Development how cool sounds that? Noel did a decent job to explain the mantra write a test, see it fail, write code, see it proceed, refactor test, refactor code. There are 3 parts and they are worth reading it. And you will not believe but those articles are over ten years old and still relevant still fresh, still entertaining.

My first step was to figure out how to write tests before I write the code. I quickly realized it is not about write all tests upfront but write a test for a small functionality. Still, I had quite some trouble to figure out what kind of functionality I should test next. I learned some tricks to be very efficient with that. And how important it is that the tests fail first because only then you know that it will fail, if somebody breaks your code.

Another topic is the fixture. It took me some time to wrap my head around that fixture thing but it was one of the biggest beneficial ideas I’ve ever heard. A fixture or I also call it sometimes "The Story" of a set of tests helps you to organize your tests code and keep them understandable. Fixtures are part of the refactoring, which I do after I have two or three tests in place. Fixtures are much better for the understanding than helper code. Helpers look nice at first glance but can be a pain to understand what you exactly test in the long run. Helper code is often a sign that you should improve your interface with this functionality or just reorganize the test code around a fixture instead.
I also sometimes have a base fixture to have a higher level story which I can inherit. I don’t write tests for that fixture, else they will be executed for all inherited test class, that makes no sense. The base fixture reduces the copy past of code into different fixtures, which most often lead to helper methods and classes.

There are so many lessons I learned doing software test-driven. Code that is developed test-driven does look significantly different than code which is not tested or tested after the implementation. TDD helps you to keep a class simple, understandable, and testable. It’s just a pain to test complicated methods and classes, you automatically want to keep that simple. And you use your implemented code right away, you don’t need to fire up the application to see if your code does what you expect, no browser involved no server start, just the test. Test-driven tests are fast and give you instant feedback if your changes lately do interfere with something you didn’t expect.

I love this topic also in the game development world tests are a useful tool, especially when you do not work alone on a game. I will write some more articles about this topic.

ECS Pattern: Follow Entity

When I write games I have always something following something else. The camera follows a hero. Light follows ghost. Goody follows the space ship. Weapon follows the player. And so on and so on. This is a very common pattern in games.
In the object-oriented world, I would probably have a reference to the object which is "attached" to me, like the gun or lamp or whatever it is. In an entity component system I go the other way around, the attached item does have a link to the entity it has to follow. Once you have your system which makes it happen, that every item entity with a link to another entity will follow that other entity you will be able to let nearly everything follow anything else with literally one line of additional code, well most often.

Lemings

Precondition

You already know what an entity component system is if not this article EntityComponent System is Crazy Cool migth give you a clue. I do all my examples in Java, but it should easily be adaptable to whatever own language you have. Also, the ECS might differ, I use Zay-ES, but as well you can probably easily make the link to your implementation of an ECS.

Position of Your Leming

The objects which lead and those which follow need a position component to store the location and the orientation of the entity. This component is set on every frame to make the thing move around. And yes it is always a new instance, no reuse. And java seems to be smart and efficient enough not to have any issue with very short-living objects. Components do have intentionally no setter methods!

public class Position implements EntityComponent {

    private final Vec3d location;
    private final Quatd facing;

    public Position(Vec3d loc, Quatd quat) {
        this.location = loc;
        this.facing = quat;
    }

    public Vec3d getLocation() {
        return location;
    }

    public Quatd getFacing() {
        return facing;
    }

    @Override
    public String toString() {
        return "Position[location=" + location + ", facing=" + facing + "]";
    }
}

Link to Another Leming

Now the object which shall follow another object needs a follow component

public class Follow implements EntityComponent {

    private final EntityId parent;

    public Follow(EntityId parent) {
        this.parent = parent;
    }

    public EntityId getParent() {
        return parent;
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + "[parent=" + parent + "]";
    }
}

I just store the entity id I want to follow and that’s it.

I Follow You

Now we need a follow system which handles the linked entities. I will have to take care of all entities with a position and a model component and all entities with a position, link, and model component. I will call them leaders and followers.
The followers will be iterated and checked if they have a link to one of the leaders.

Set It Up

For this, I only need the entity data and two Zay-ES containers, one to hold the follers and one to hold the leaders.

public class FollowSystem extends BaseAppState {

    static Logger LOG = LoggerFactory.getLogger(FollowSystem.class);
    private EntityData ed;
    private FollowerContainer followerContainer;
    private LeaderContainer leaderContainer;

    @Override
    protected void initialize(Application app) {
        ed = main.getStateManager().getState(EntityDataState.class).getEntityData();
    }

    @Override
    protected void cleanup(Application app) {
    }

Start/Stop It

When we enable this system we instantiate and start the follower and leader container.

    @Override
    protected void onEnable() {
        followerContainer = new FollowerContainer(ed);
        followerContainer.start();
        leaderContainer = new LeaderContainer(ed);
        leaderContainer.start();
    }

    @Override
    protected void onDisable() {
        followerContainer.stop();
        followerContainer = null;
        leaderContainer.stop();
        leaderContainer = null;

Every Frame

On every frame, I update the follower and leader container to get all added, updated, and removed followers and leaders. To update all follower’s positions I simply loop over the followers, see if their leader does exist in the leader container, get the leader position, and store this position in the follower’s position.

    @Override
    public void update(float tpf) {
        followerContainer.update();
        leaderContainer.update();

        followerContainer.stream().forEach(follower -> {
            LeaderData leader = leaderContainer.getObject(follower.leader);
                        if (leader != null) {
                ed.setComponent(follower.id, new Position(leader.location));
            }
                });
    }

Leaders

The leader’s container keeps track of all the entities which do have a model and a position component, the code is very simple and straight forward.

    class LeaderData {
        Vec3d location;
    }

    class LeaderContainer extends EntityContainer<LeaderData> {
        LeaderContainer(EntityData ed) {
            super(ed, ModelType.class, Position.class);
        }

        Stream<LeaderData> stream() {
            return Arrays.stream(getArray());
        }

        @Override
        protected LeaderData addObject(Entity entity) {
            LeaderData result = new LeaderData();
            updateObject(result, entity);
            return result;
        }

        @Override
        protected void updateObject(LeaderData data, Entity entity) {
            SpawnPosition position = entity.get(Position.class);
            data.location = position.getLocation();
        }

        @Override
        protected void removeObject(LeaderData data, Entity entity) {
        }
    }

Followers

The container is even simpler, we are only interested in entities which do have a follow component and store our entity id and the leader’s entity id.

    class FollowerData {
        EntityId id;
        EntityId leader;
    }

    class FollowerContainer extends EntityContainer<FollowerData> {

        FollowerContainer(EntityData ed) {
            super(ed, Follow.class);
        }

        Stream<FollowerData> stream() {
            return Arrays.stream(getArray());
        }

        @Override
        protected FollowerData addObject(Entity entity) {
            FollowerData result = new FollowerData();
            result.id = entity.getId();
            result.leader = entity.get(Follow.class).getParent();
            return result;
        }

        @Override
        protected void updateObject(FollowerData t, Entity entity) {
        }

        @Override
        protected void removeObject(FollowerData t, Entity entity) {
        }
    }
}

Finally

You can extend this with an offset as at the moment the follower and the leader will have the same position, which might not be wished as you probably want to have the lamp, weapon, or tool in front of your character and not on the very same position. As well you could implement a smoothing when following something.

Thanks for reading. If you have questions, suggestions, or an oppinions leave a comment below.

ECS Pattern: Decay

This blog post is based on Entity Component System are Crazy Cool.
There are so many things in-game that have a lifetime. Bullets, effects, debris, blood, vanishing tiles in a can’t stop running-game, and many more things which have a lifetime.
In the past, I would have done it separately depending on which situation something hast to vanish. With the entity component system you can solve all of them with one component and one system. The decay component and decay system.

I use jMonkeyEngine with Zay-ES written in Java.

Component

Bullets, debris, blood are represented by entities with a certain set of components in our game world. A bullet entity for example has a model component, a position component, and a damage component. For the decay system, we need a decay component we can attach to those entities to make them disappear after a while. Instead of detecting where the bullet is, you simply remove the bullet after a while if it didn’t hit something. No need to detect where the bullet is right now, just remove it after let’s say a second.

public class Decay implements EntityComponent {

    public long timeout;

    public Decay(long timeoutMs) {
        this.timeout = timeoutMs;
    }

    public long getTimeoutMs() {
        return timeout;
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + "[" + timeout + " ms" + "]";
    }
}

On creation, you define the timeout for the decay component. The timeout in ms does define how long the entity shall live.

System

The decay system does the calculation if the entity’s lifetime has been reached. It doesn’t matter if it is a bullet, an effect, debris, or even the space station. And that is the shiny beauty of an entity component system. You can give something a lifetime in your game at any time. You can decide to add a lifetime to something even very late in the development process. You can decide this a day before you launch the game as it is simply a one-liner by adding a decay component to that entity. No refactoring or code moving involved at all.

Skeleton

Let’s start with a very basic system and set up everything we need, like the entity data and the decay container.

public class DecaySystem extends BaseAppState {

    private EntityData ed;
    private DecayContainer decayContainer;

    public DecaySystem() {
    }

    @Override
    protected void initialize(Application app) {
        Main main = (Main) app;
        ed = main.getStateManager().getState(EntityDataState.class).getEntityData();
    }

    @Override
    protected void cleanup(Application app) {
    }

    @Override
    protected void onEnable() {
        decayContainer = new DecayContainer();
        decayContainer.start();
    }

    @Override
    protected void onDisable() {
        decayContainer.stop();
        decayContainer = null;
    }

    @Override
    public void update(float tpf) {
            decayContainer.update();
        }

    private class DecayData {
    }

    private class DecayContainer extends EntityContainer<DecayData> {

        DecayContainer() {
            super(ed, Decay.class);
        }

        Stream<DecayData> stream() {
            return Arrays.stream(getArray());
        }

        @Override
        protected DecayData addObject(Entity entity) {
            DecayData data = new DecayData();
            return data;
        }

        @Override
        protected void updateObject(DecayData data, Entity entity) {
        }

        @Override
        protected void removeObject(DecayData data, Entity entity) {
        }
    }
}

It does nothing yet. We will now fill in the needed code. Which is not really a lot. Very simple.

Decay Entity Container

Let’s begin with the Zay-ES entity container to get all the added, removed, and updated entities with a decay component attached. In the addObject() method we create our local decay data to handle the timeout. I almost always have a local data representation with some additional logic. We store the entity id and the timeout in milliseconds. That’s it.
You can add as well logic for the updateObject() method to be able to update the decay of an entity during your gameplay, think of a plant that got some water or fertilizer or tool which got repaired.

    private class DecayContainer extends EntityContainer<DecayData> {

        DecayContainer() {
            super(ed, Decay.class);
        }

        Stream<DecayData> stream() {
            return Arrays.stream(getArray());
        }

        @Override
        protected DecayData addObject(Entity entity) {
            long timeoutMs = entity.get(Decay.class).getTimeoutMs;
            DecayData data = new DecayData(entity.getId(), timeoutMs);
            return data;
        }

        @Override
        protected void updateObject(DecayData data, Entity entity) {
                }

        @Override
        protected void removeObject(DecayData data, Entity entity) {
        }
    }

Local Decay Data

The local decay data class handles the timeout. We store the start time and the timeout and with getPercent() method we return the decay as a value 0 (no decay) and 1 (fully decayed). Very simple logic.

    private class DecayData {

        EntityId id;
        private long start;
        public long timeout;

        DecayData(EntityId eId, long timoutMs) {
            this.id = entity.getId();
            this.start = System.nanoTime();
            this.timeout = timeoutMs * 1000000;
        }

        double getPercent() {
            long time = System.nanoTime();
            return (double) (time - start) / timeout;
        }
    }

Update

And finally, in the update method, we loop over all decay data and remove those which are fully decayed.

    @Override
    public void update(float tpf) {
        decayContainer.update();
        decayContainer.stream().forEach(e -> {
            if (e.getPercent() >= 1.0) {
                    ed.removeEntity(e.id);
            }
        });
    }

Additionally

You can implement as well visualization systems to make the decay of a thing like a plant or a tool visible and give feedback to the player.

The End

That’s it. Thanks for reading. If you have suggestions or questions just write a comment below.

Game Feeling

I read and watched a lot about game feeling beyond many I liked these best

Game feeling is how you experience your interaction within a game. Does jumping feel good? Does the gun have a powerful feeling when using it? Is it satisfying when you destroy or kill something? Does it have a snappy control? Was it exciting to solve that puzzle?

The 30 Tricks of Jan Willem Nijman

I made my self a list of the 30 tricks to make a game feel good by Jan Willem Nijam:

  1. Basic Animations & Sounds: Makes the walking, jumping, pick up things, and shooting more fun.
  2. Lower Enemy HP: It’s more fun.
  3. Higher Rate of Fire: It’s a video game about shooting so put more bullets in there.
  4. More Enemies: Because of trick 2. you need more enemies to shoot.
  5. Bigger Bullets: Don’t use realistically sized bullets as it looks so silly, make them big.
  6. Muzzle Flash: Just make the first bullet frame a circle.
  7. Faster Bullets: Slow bullets are lame, make it faster.
  8. Less Accuracy: If your gun is not too accurate it looks more realistic and is more fun.
  9. Impact Effects: Let the player know he hit something, don’t just remove the bullets.
  10. Hit Animation: Let the player know that he damaged the enemies.
  11. Enemy Knockback: But knockback force if you hit enemies.
  12. Permanence: Don’t remove dead bodies, it helps you remember if you come back in a room with a huge pile of dead bodies in it.
  13. Camera Lerp: Smoother cameras make the character feel more in-motion.
  14. Camera Position: Your your camera to focus on important things in your video game.
  15. Screen Shake: This is an important rule add screen shake on explosions it looks so much more powerful than without.
  16. Player recoil: Shooting feels much more powerful with recoil on the player and you can use it to avoid that player do not shoot all the time as it has a drawback.
  17. Sleep: If you set a deadly hit sleep for 100 or 200 ms, it puts more meaning in that action, brawl games do that a lot.
  18. Gun Delay: Make the character and its props look like they have weight/momentum when moving.
  19. Gun Kick: Add recoil to things that would have it.
  20. Strafing: If you shoot and change the direction the shooting will be still in the same direction until you stop shooting to turn around the gun.
  21. More Permanence: Put ejecting shells in your game and make them permanent, it also helps to remember that you were in that room and that you did shoot a lot.
  22. More Bass: Add bass to your shooting and explosions they get much more meaning and power.
  23. Super Machinegun: Try ridiculous variations on how shooting performs, maybe three bullets a time, go crazy.
  24. Random Explosions: That is a funny one but it puts more action in your game if you put some random explosions to your game when you shoot enemies, don’t overdo it.
  25. More Enemies: You tuned up your gameplay so that you got the feeling you have not enough to shoot at.
  26. Even Higher Rate of Fire: Because it is more fun to shoot
  27. Even Higher Rate of Camera Kick: Make your camera kick in the direction of the action/shooting.
  28. Bigger Explosions: Seriously, who doesn’t like explosions.
  29. Even More Permanence: Put some dust after your gigantic explosions and let it fade slowly.
  30. Meaning: Let your player win or loos.

My Personal Addition

I have some more points for this list.

  1. Flashlight: Add a short bright light flash on explosions it feels more realistic and more boom, it looks good even without sound.
  2. Add more light: Attach light on rockets, it makes it more vivid.
  3. Hitpoints: Visualize hitpoints instantly on the location of the hit.
  4. Add a camera kickback: When you fire a gun add kickback to the camera, it looks more fun.

Entity Component System Is the Coolest Thing I Ever Met

Entity component system or short ECS is one of the coolest, brightest, and most beautiful paradigm in programming I have ever met. It is data-driven and different from object-oriented programming most people know nowadays. It is mainly used in game development. The entity component system approach brought me back the feeling of the old days hacking games on a zx81 with a 4kbyte ram extension.

The "All Fucked Up" game relays heavily on entity component system and makes it super cool to develop.

But What is ECS

Looking at the name we can identify three parts.

  • Entity
  • Component
  • System

Entity

An entity is just an identifier. Nothing more than that. In my case a number.

Component

An entity can have one or many components. A Component is just data, like the position or the model name or health. It has no functionality like walk, spell or any other activity. It might have getters. I use getters.

System

The System subscribes for entities with certain components and implements what should happen with added, updated or removed entities.

Basically, you subscribe for entities with a certain set of components, and in the update loop of your system, you get all the added, updated, and removed entities.

So let’s say you are interested in all entities which do have a position and a model component. Let’s further assume that there are already entities "1" and "2" with a position and a model component. In the current frame you add entity "3", update the position of entity "2" and remove entity "1". In the update loop, you get entity "3" as added, entity "2" as updated, and entity "1" as removed. Your system does now load and display the new entity "3" to the given position, move the entity "2" to the new position and removes entity "1" from the screen.

Note: The system in this example only sees the entities with a position and a model. If you remove either the position or the model from an entity, this entity will appear as removed in this example.

Let’s deep dive

I love code examples. My click experience was to use ECS for displaying the objects on the screen and move them around. I will provide some real code in a simplified form and explain the parts.

jMonkeyEngine and Zay-ES

I use jMonkeyEngine with Zay-ES written in Java. You might use another game engine and even another language, but that doesn’t really matter, as I’m sure you guys are all smart enough to make the link to your game engine as they don’t differ that much.

The System

First of all, I use app states as my Systems provided by the jMonkeEngine. All app states update method are called every frame in the order they are registered. This might look different for your game engine and maybe you even have to introduce a construct like this.

This app states here is the System to display the models on the screen.

public class ModelViewState extends BaseAppState {
    private Node modelRoot;
    private Main main;
    private EntityData ed;
    private ModelContainer modelContainer;

    @Override
    protected void initialize(Application app) {
        ...
    }

    @Override
    protected void onEnable() {
        ...
    }

    @Override
    protected void onDisable() {
            ...
        }

    @Override
    public void update(float tpf) {
            ...
        }

    private class ModelContainer extends EntityContainer<ModelData> {
        ...
    }
}

Lets add some flesh to this skeleton…

Initialization

In the initialization method I set up the model root, a pointer to the main app, and the entity data. The entity data is in my case an own app state, I like to organize the stuff in-app states, makes it clearer and the code gets less cluttered.

    @Override
    protected void initialize(Application app) {
        modelRoot = new Node();
        main = (Main) app;
        ed = main.getStateManager().getState(EntityDataState.class).getEntityData();
    }

Enable

The application state features an enable method, that might be different for your game engine. I use this to let the models appear by adding my model root node. It’s not really relevant but helps to understand the software a bit better. So no magic.

What is relevant is the model container we instantiate and start, this is an ECS container. The model container is described in all details further down.

    @Override
    protected void onEnable() {
        main.getRootNode().attachChild(modelRoot);
        modelContainer = new ModelContainer(ed);
        modelContainer.start();
    }

Disable

The application state also features a disable method. I use this to remove all the models by simply remove the model root from its parent. Very handy. It’s as well not really relevant to explain the ECS architecture.

The ECS model container is stopped and destroyed as well.

    @Override
    protected void onDisable() {
        modelContainer.stop();
        modelContainer = null;
        modelRoot.removeFromParent();
    }

Update

In the update method, we update the started model container. For this example this is it, nothing else is needed for the update loop. For more advanced stuff you need to iterate over all entities and for example calculate collision detection or other logic you may need to make entities interact with each other.

    @Override
    public void update(float tpf) {
        modelContainer.update();
    }

ECS Model Container

The ECS container from Zay-ES makes it really simple to handle added, removed and update entities on every update() call.

Data Class

I always define a data class, in this case, it is very simple and holds just the loaded spatial. That’s it.

   private class ModelData {
         Spatial model;
     }

The ECS Container

The ECS container does subscribe for all entities which have a ModelType and a Position component. This is now the important stuff. We are interested in entities that have a model and a position component.

    private class ModelContainer extends EntityContainer<ModelData> {

        public ModelContainer(EntityData ed) {
            super(ed, ModelType.class, Position.class);
        }

Add Entities

The addObject method is called for all new entities which do have a ModelType and a Position component. For every entity, I create a model data object and fill in the loaded model. Only the model name must be stored in the component and not the spatial itself. This leads to very decoupled software, you can even have another system that also is interested in the model and the position but does for example display it in a minimap. To store the spatial in the component would be an anti-pattern. I also call the updateObject method to place the added model. Of course to make it visible we have to attach the model to the model root.

        @Override
        protected ModelData addObject(Entity entity) {
                    modelData = new ModelData();
                    String modelName = entity.get(ModelType.class).getModelName();
                    modelData.model = main.getAssetManager().loadModel(model);
                    updateObject(modelData, entity);
                    modelRoot.attachChild(modelData.model);
                    return modelData;
                }

Update Entities

The updateObject method is called if either the ModelType or the Position of an entity has changed. In this example, I’m only interested in the position changes. A position holds the new location and the new rotation. So if your controller stated wants to move your hero around, it simply updates the position component of the hero entity.


        @Override
        protected void updateObject(ModelData modelData, Entity entity) {
                    Position position = entity.get(Position.class);
                    modelData.model.setLocalLocation(position.getLocation());
                    modelData.model.setLocalRotation(position.getFacing());
        }

Remove Entities

Finally, we have the removeObject method, which is simply plain to remove the models, because either the Position and/or the ModelType component was removed by another system, for example, your dead system.


        @Override
        protected void removeObject(ModelData modelData, Entity entity) {
                    modelData.removeFromParent();
        }
    }

Place Models and Move it

The code we have so fare wants entities with ModelType and Position components, so we need to place that. For this, I have a level app state which places the initial stuff including my hero. The initial stuff is done in the app state enable method, where I load the level or build up the level, that depends. Ok real quick

public class ModelViewState extends BaseAppState {
    private Main main;
    private EntityData ed;
    private EntityId myHero;
    ...

    @Override
    protected void onEnable() {
            myHero = ed.createEntity();
        ed.setComponents(myHero, new ModelType("MyFancyModel.j3o"), new Position(new Vector3f(0, 0, 0)));
    }

    @Override
    public void update(float tpf) {
        ed.setComponent(myHero, newPosition(newVector3f(tpf, 0, 0)));
    }
        ...
}

Yes that simple, this moves the object to the right in my case with a speed of 1 unit per second. And java is pretty good with very short-living objects and never was an issue for me. I have up to 2500 or more frames per second if I do not run it in sync mode. And even with a lot, and I mean a lot of entities (up to 10’000 objects) it is not an issue…
And right the position component is a new instance everytime you change it, java seems to be smart and efficient enought to handle short living objects.

The wow moment

Just to displaying and moving the stuff around wasn’t really my wow moment, it was just the now-I-understand moment. It’s even like why should I use ECS for this? What is the benefit? The real wow moment was the decay system for me. It is a pattern you probably have in every game.

What is a decay system exactly? The decay system is interested in all entities with the Decay component, which basically says how long this entity shall live. Very handy to clean stuff up like bullets, which are probably very short living in almost all games. And you have tons of them and as well different kinds of them. But as well any entity which is dying or has to be removed after a while. You even can display the decay state with another system that is also interested in the decay component. The only thing you have to do is to attach the Decay component to the entity which should vanish after a while. No inheritance, no direct component linking, just attach the Decay component.

You can also think of a health system to give something health and it doesn’t matter if that is a dog, a tree, a house, a stone, or your hero. And you can add it anytime. Maybe you started with stones without health, but then your game designer shows up and wants that the stones have health and the hero can destruct them with a tool. No big deal it is a one-line addition by just adding Health component to the stone entity and it has health. If you have already a health visual system in place the health of the stones will be displayed like any other thing with health. And that’s really cool.

If you made it this far

Put your questions and suggestions in the comments below. Thanks for reading.

Player control

I recently worked on my jumping abilities. In the beginning, I only could do double jumps. Whenever the player hits the ground he gots one extra jump which can be pretty handy and looks fun. But to jump from walls was very shaky and sometimes you had the extra jump and sometimes you didn’t because you jumped too late and used up that extra jump instead of a wall jump.

Again behavior tree

As with the weapons, it started pretty simple and straight forward by just program the player control. But for the double jump, I already had a counter in place which had to be updated and consumed. Motivated by the early success modeling weapons with a behavior tree implementation I start over the character control implementation with a behavior tree.
First I had to split my stuff into tasks to be able to model the walking and jumping behavior of the player with the libgdx-ai behavior tree

The main goals were walking, jumping, double jumps, and wall jumps. The wall jump was especially tricky.

Move

The moving part is simple, we just apply force on the character, limit the speed to max speed and turn the character in the proper direction. The character model implementation has an update loop where it detects/measures the speed to do the walk animation properly. We apply also force to the player midair to give the player more control.

One improvement would be to let the character look in the direction he is shooting in that case he would just move forth and back but would not change the shoot direction. This is especially for fully automatic weapons.

Double jump

The double jump was just something I saw in so many games and wanted it for mine as well.

As long you jump in the same direction as you walk, I only stop midair the vertical movement to give more control else it feels very wobbly. But the horizontal movement is untouched.

In case the player also changes the direction hitting the jump button mid-air I stop completely horizontal and vertical this makes the jumps more controllable and fun. You can do all the impossible jumps you ever dreamt of.

Wall jump

If the player pushes the jump button sticking to the wall or is close enough and has no ground underneath it he gets pushed away from the wall. Actually, the push from the wall is away and slightly upward, the character also changes its direction. If you hold the movement towards the wall the jumps out and moves back to the wall and the player doesn’t change its direction. The wall jumps are unlimited. This keeps the gameplay pretty fast. The stickiness to the wall is not very strong and you have to move fast.

As soon the player jumps on a wall the vertical movement goes to a full stop. This makes the wall jumps nice and responsive. I tried it without and it feels very fluffy.

The push from the wall should make it possible to jump up a corridor with just pressing the jump button all the time without any midair movements.

Shooting

The shooting part is pretty simple, it just triggers the gun. Maybe set a marker that the trigger is pulled so the player doesn’t change direction while shooting, see moving chapter above.

Dashing

I’m not yet sure if I and how I want to model dashing. It’s already pretty fast. And it should do something. Maybe dodge bullets or distract enemies. This is working in progress.

Keep on testing

I do a lot of testing these days. And with the behavior tree approach, I can easily change the behavior of the controls. The downside of changing the control behavior also often means that I have to rework the levels, just think of a slightly higher jump or slightly less high jump, a tiny bit less speed, new abilities like dashing. So what’s easy still has a rat tail of other implications.

But it is fun as hell.

Conclusion

The jump topic is very tricky and needs by fare more testing until I can say this is it.




Behavior Trees for Weapons

If it comes down to behavior trees many developers think of AI, robotics, or NPCs. I started to use behavior trees to make my stupid soldier NPCs patrol and shoot. They are still very stupid and sometimes shoot each other. I realized that I can use behavior trees for more than just my NPCs.

For example for my weapons. It’s actually so much fun to design and model weapons, not only from the visual representation but also in how it behaves and how it feels to use it.

Note that…

this blog article doesn’t want to explain behavior trees in all lengths and depths. There are many blogs and articles available which do a great job explaining behavior trees. Furthermore, you will probably also need to read the documentation for your behavior tree implementation at hand.

Here a small selection of links:

It starts always simple

When I first introduced my weapons to my platformer "All Fucked Up", I did it the classical way by simply programing them. It started simple with a weapon which eject a shell, launch a bullet, place a flash light and make a boom sound. Even when I modeled a submachine gun it was simple. I thougt well how messy can that possible go. And then a double barrel shot gun came along the way and everything started to get messy.

After two shots the shotgun should eject two shells, not imediately but with a small delay. As well I wanted to limit the rounds per minute. I managed to do this and ended up with the following code:

   public void shoot(double tpf, Vec3d location, Quatd orientation) {
        time += tpf;
        if (pull) {
            if (cartridge > 0 && time > 0.25) {
                cartridge -= 1;
                time = 0;
                launchProjectile(orientation, location);
                if (cartridge <= 0) {
                    eject = true;
                    ejectTime = 0;
                }
            }
            if (time > 2.5) {
                cartridge = 2;
            }
        }
        if (eject && ejectTime < 0.6) {
            ejectTime += tpf;
        } else if (eject) {
            eject = false;
            ejectShell(orientation, location);
        }
    }

It doesn’t look too bad to be honest, if you carefully read it you will get your head around it. But you probably also see the problem with this approach. Just think of extending it with a limited amount of ammo you collected. A force-reload, where you want to reload the weapon even if you didn’t shoot all ammo. It was no fun to try to extend it.

There must be an alternative to this messy code, which is hard to maintain, extend, or adapt. I tried to refactor it in breaking it down to smaller and simpler pieces. The main problem remained, it was still hard to extend or adapt.*

The weapons do have behavior and why not use a behavior tree implementation as a way out. It was one of the best decision I made for this game.

A very short story about behavior trees

I use the behavior tree implementation from libgdx-ai.
We have tasks, sequences, selectors, and parallels. In this article, I don’t need parallels.

I just describe very short what the single parts do.

Task

A task can either fail, succeed or stay running. A task in the state running, will be reentered on the next execution of the behavior tree.

Sequence

A sequence is a special task that runs each of its child tasks in turn. It will fail immediately when one of its children fails. As long as its children succeed, it will keep going. If it runs out of children, it will succeed.

Selector

A selector is a special task that runs each of its child tasks in turn. It will succeed when one of its children succeed. As long as its children are failing, it will keep on trying the next child. If it runs out of children completely, it will fail.

Ok then let us use this behavior tree

On the top level of the behavior tree we have a sequence with two tasks, the first one will reload the gun if needed and if possible, the second task will shoot if the trigger is pulled and there is at least one round chambered.

Let’s look at how we model the "need reload" task. Probably not the best naming. The reload task consist of a selector with two child tasks. The first task checks if the ammo count of the gun is bigger than zero. The second task does a delayed reload of the gun and fails if the player does not have any shotgun rounds left else it succeeds. The check if it really can reload is done in the reload task.

Shooting is basically a sequence of tasks. First, we check if the trigger is pulled and fail if not. If the trigger is pulled we launch the projectiles, this task does always succeed. After that, we wait until the trigger gets released to have a controlled shooting. After we release the trigger we check if there is still life ammo chambered and fail if so. In the case there is no life ammo anymore we wait a fraction of a second and eject two shells and succeed.

As you can see the shoot task also returns with fail or succeed this is important and has to be considered if you want to proceed after the shooting task with an additional task whatever this might be…

And here the complete behavior tree

Looks cool. The code of this behavior tree looks like this

        this.bb = new WeaponBlackboard(main, this);

        Sequence<WeaponBlackboard> reloading = new Sequence<>();
        reloading.addChild(new Wait(1.4f));
        reloading.addChild(new Reload());

        Selector<WeaponBlackboard> needReload = new Selector<>();
        needReload.addChild(new AmmoCount());
        needReload.addChild(reloading);

        Sequence<WeaponBlackboard> shoot = new Sequence<>();
        shoot.addChild(new DetectPullTrigger());
        shoot.addChild(new LaunchProjectile());
        shoot.addChild(new WaitUntilSuccess<>(new Invert(new DetectPullTrigger())));
        shoot.addChild(new Invert<>(new AmmoCount()));
        shoot.addChild(new Wait<>(0.6f));
        shoot.addChild(new EjectShell());

        Sequence<WeaponBlackboard> gun = new Sequence<>();
        gun.addChild(needReload);
        gun.addChild(shoot);

        this.bh = new BehaviorTree<>(gun, bb);

And in the update loop you call something like

bh.next()

It is so much easier to change the behavior or to adapt it. And a new weapon is done literally in no time. Even if I don’t use a graphical editor. It’s so much fun to model weapons with this approach.

Tasks and reusable code

Because we have capsulated the stuff into tasks, we can reuse these tasks for new weapons. Like DetectPullTrigger(), LaunchProjectile(), AmmoCount() and EjectShell(). And also very generic tasks and decorators like Wait(seconds), WaitUnitlSucceed(task), AlwaysSucceed(task) and Invert(task).

For our own tasks, we can handover a weapon blackboard where we keep together everything we need. The weapon itself implements an interface with the basic actions, like launch bullets, eject shells and reloading as this is very weapon specific.

So let’s conclude

The main message of this blog article is not the solution for the double-barrel shotgun. The main message is that you can use behavior trees beyond NPC AI. Whatever has a behavior can be modeled with a behavior tree even if it is not too obvious in the beginning. If you have a graphical behavior tree editor your game designers can model that part of the game directly and have instant feedback if their ideas work out or not.

I also model my controller and the level switching logic with a behavior tree approach. These parts are much easier to adapt and to extend now. It’s also very handy as you simply can try out all your weird ideas without a lot of coding. What makes it really really fun.

The end

That’s it, I hope you enjoyed it.