ECS Pattern: Damage System

Writing games is often about dealing with health and damage. With entity component system this is fun to do. Furthermore you can give any entity health or damage any time, it is literally only adding the health or damage or both component to that entity.

Bullets And Characters

To handle health and damage we need health, damage, position, and shape components for the involved entities. A bullet usually does have a damage component besides a position and its shape. A character usually does have a health component besides a position and its shape. The damage system handles these entities and calculates the new damage and health of the involved entities. I usually remove the damage entity a soon it hits something, but if you think of a spell or an ax this is not necessarily true. For a bullet, you might add a very short decay component to let the bullet have a physical impact on the body it hits (read here about the decay pattern) before it vanishes.

A Monkey And Doctor Zaius

For this example I use jMonkeyEngine and Zay-ES. Zay-ES features EntityContainer with an update method which takes care of all created, updated and deleted entity and it provides an array of all entities which are currently in the set (not removed). This makes the code super easy. If your ECS system doesn’t have then you probably have to do a bit more leg work.

Components

I shortly introduce the components we will need. The components are pure data without methods that operate on this data which is very different from the OO programming paradigm.

Health

We just store the amount of health in this component. Furthermore, we define -1 as immortal (for concrete walls for example).

public class Health implements EntityComponent {
    static public int IMMORTAL = -1;
    private Integer health;
    public Health(Integer health) {
        this.health = health;
    }
    public Integer getHealth() {
        return health;
    }
}

Damage

We store the amount of damage in this component, that’s it.

public class Damage implements EntityComponent {
    private final int damage;
    public Damage(int damage) {
        this.damage = damage;
    }
    public int getDamage() {
        return damage;
    }
}

Position

And the position component holds the current 3D location (read my first ECS post how to move objects around).

public class Position implements EntityComponent {
    private final Vec3d location;
    public Position(Vec3d loc) {
        this.location = loc;
    }
    public Vec3d getLocation() {
        return location;
    }
}

Shape

And then finally the shape. To make our life simple we just have sphere objects with a radius.

public class SphereShape implements EntityComponent {
    private double radius;
    public SphereShape(double radius) {
        this.radius = radius;
    }
    public double getRadius() {
        return radius;
    }
}

Damage Entity Set

In the damage system we keep two sets of entities. The first set called the DamageContainer handles all entities with a position, shape and damage component.

    private class DamageData {

        EntityId entityId;
        AABB aabb;
        Vec3d location;
        int amount;
    }

    private class DamageContainer extends EntityContainer<DamageData> {

        DamageContainer(EntityData ed) {
            super(ed, Damage.class, Position.class, SphereShape.class);
        }

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

        @Override
        protected DamageData addObject(Entity entity) {
            DamageData result = new DamageData();
            result.entityId = entity.getId();
            result.amount = entity.get(Damage.class).getDamage();
            updateObject(result, entity);
            return result;
        }

        @Override
        protected void updateObject(DamageData data, Entity entity) {
            SphereShape sphereShape = entity.get(SphereShape.class);
            data.location = entity.get(Position.class).getLocation();
            Vector2 center = new Vector2(data.location.x, data.location.y);
            data.aabb = new AABB(center, sphereShape.getRadius());
        }

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

The data we want is the entity id (to be able to get rid of), the location, amount of damage, and an AABB object for simple collision calculation.

Health Entity Set

On the other hand, we have the health set we call it HealthContainer and it goes like this

    private class HealthData {

        EntityId entityId;
        AABB aabb;
        int amount;
    }

    private class HealthContainer extends EntityContainer<HealthData> {

        HealthContainer(EntityData ed) {
            super(ed, Health.class, Position.class, RectangleShape.class);
        }

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

        @Override
        protected HealthData addObject(Entity entity) {
            HealthData result = new HealthData();
            result.entityId = entity.getId();
            result.amount = entity.get(Health.class).getHealth();
            updateObject(result, entity);
            return result;
        }

        @Override
        protected void updateObject(HealthData data, Entity entity) {
            SphereShape sphereShape = entity.get(SphereShape.class);
            data.location = entity.get(Position.class).getLocation();
            Vector2 center = new Vector2(data.location.x, data.location.y);
            data.aabb = new AABB(center, sphereShape.getRadius());
        }

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

The data we want is the same as for the DamageContainer, the entity id (to be able to get rid of it as well), the location, amount of health and an AABB object for simple collision calculation.

The Update Loop

In the update loop we now update the HealthContainer and the DamageContainer and then we loop over all health entities and inside that we loop over all damage entities and calculate the new Health and Damage component. In our case, we remove the Damage component from the entities on collision and only calculate the new Health component.

   @Override
    public void update(float tpf) {
        healthConatiner.update();
        damageContainer.update();

        healthConatiner.stream().forEach(h -> {
            damageContainer.stream()
                    .filter(d -> !d.parentId.equals(h.entityId))
                    .filter(d -> d.aabb.overlaps(h.aabb))
                    .forEach(d -> {
                        handleHealthAndDamage(h, d);
                    });
        });
    }

Calculus

Let’s look into how we handle health and damage. First we check if the health entity is immortal like a concrete wall and skip the calculation. If the health entity is not immortal we calculate the new health and remove the health entity if the health is equal or below zero. In the end we remove the damage entity as it is used up on collision.

    private void handleHealthAndDamage(HealthData health, DamageData damage) {
        if (health.amount != Health.IMMORTAL) {
            health.amount = health.amount - damage.amount;
            if (health.amount > 0) {
                ed.setComponent(health.entityId, new Health(health.amount));
            } else {
                ed.removeEntity(health.entityId);
            }
        }
        ed.removeEntity(damage.entityId);
    }

Benefit

If your game designer has the famous idea at the last minute possible that your weapons should also be able to destroy the furniture you will not spend hours or days making this happen as you simply can add health to these furniture entities and you are done. Because the code is already in place which handles these entities on collision. This is the actual beauty of the entity component system.

I’m Reading

I’m currently reading the self-published Data Oriented Design from Richard Fabian to get me a deeper insight how to design games with entity component system or as the book title says data-oriented design. A very interesting and cool topic so much different from what I learned with OO approaches. Data-oriented design not only improves the execution time but also your developing performance. Counts especially for games with its short update cycle and the game data which is changing constantly.

The End

You can extend and tweak this example as you like. Go wild.

In case you have questions or suggestions, let me know in the comments below.

History Back and Forth

Whenever you write a level editor or maybe a turn-based game (like chess) it would be of great help having undo and redo functionality at hand.

Based on the Game Programming Patterns book from Robert Nystrom I did like to implement an undo/redo history class. The design pattern is based on the Design Patterns book of the gang of four.

Side Note

I use this programming pattern for my test-driven development workshop, I do occasionally. If you are interested in that, just let me know in the comments below.

Implementation

Introduction

A command can be anything from move one square to shoot, cast a spell, and more. The command must encapsulate everything needed to execute and to undo his action. Every command is an own instance. The commands then get stored in a history object which I will show you in this blog post.

Command Interface

The whole thing starts with a command interface which looks like this

package mygame;

public interface Command {
    public void execute();
    public void undo();
}

The only thing you need in command is execute and undo. With that, you can even make a redo. Really?

History Execute, Undo, and Redo

I’ll show you the idea of the history implementation.

package myexample;

public History {
    public void execute(Command command) {}
    public void undo() {}
    public void redo() {}
}

To make the whole thing work you need to encapsulate everything needed to execute the command in your command object, which is of great importance.

For the implementation of the history class, I used LinkedList as it was the simplest way I found for this. Of course, you can implement as well some ring buffer structure using plain arrays, but I did not have the nerve for this.

Ok, let’s start with the basics. First of all, we need to execute the command like this

public void execute(Command command) {
    command.execute();
}

That wasn’t too hard, but to be able to undo it, we need to hold that command instance in a data structure, a linked list in my case.

    private LinkedList<Command> commands;
    public History(int size) throws InstantiationException {
        commands = new LinkedList<>();
    }

    public void execute(Command command) {
        commands.add(command);
        command.execute();
    }

    public void undo() {
        commands.removeLast().undo();
    }

Oh, wait what if I undo when the list is empty? Yes, it fails, so we need some guards to protect it.

    public void undo() {
        if (!commands.isEmpty()) {
            commands.removeLast().undo();
        }
    }

Improvments

That looks not that bad and it works already. But let’s improve it a little more. For example, does this implementation not limit the number of commands in our history, so let’s introduce a size.

    private int size;

    public History(int size) throws InstantiationException {
        if (size == 0) {
            throw new InstantiationException("0 is not a valid history size");
        }
        this.size = size;
        commands = new LinkedList<>();
    }

And now we have to improve the execute method with this size information, by dropping the first command f we hit the capacity of our history.

    public void execute(Command command) {
        if (commands.size() >= size) {
            commands.removeFirst();
        }
        commands.add(command);
        command.execute();
    }

Redo

A redo would be cool and it turns out to be very simple. We need a second linked list for book-keeping.

    private LinkedList<Command> redoCommands;
    public History(int size) throws InstantiationException {
        // ...
        redoCommands = new LinkedList<>();
    }

Then we have to store all undoed commands in that redoCommands list.

    public void undo() {
        if (!commands.isEmpty()) {
            Command command = commands.removeLast();
            redoCommands.add(command);
            command.undo();
        }
    }

Now we are prepared for the redo method

    public void redo() {
        if (!redoCommands.isEmpty()) {
            execute(redoCommands.removeLast());
        }
    }

One small problem we have to solve, what if we did undo 2 times and then call execute and after that call redo? Yeah, it will end up in redo commands which actually should be cleared. So let’s clear the redo command list on execute. This is not that easy as the redo itself calls execute to have the command book-keeping for free. The easiest way is to have an internal execute which is called by execute and redo and only execute clears the redo commands list.

    public void execute(Command command) {
        redoCommands.clear();
        internalExecute(command);
    }

    public void redo() {
        if (!redoCommands.isEmpty()) {
            internalExecute(redoCommands.removeLast());
        }
    }

    private void internalExecute(Command command) {
        if (commands.size() >= size) {
            commands.removeFirst();
        }
        commands.add(command);
        command.execute();
    }

Copy & Paste Code

And to make it a simple copy&past task to take this into your project here the things you need

package myexample;

import java.util.LinkedList;

public class History {

    private LinkedList<Command> commands;
    private LinkedList<Command> redoCommands;
    private int size;

    public History(int size) throws InstantiationException {
        if (size == 0) {
            throw new InstantiationException("0 is not a valid history size");
        }
        this.size = size;
        commands = new LinkedList<>();
        redoCommands = new LinkedList<>();
    }

    public void execute(Command command) {
        redoCommands.clear();
        internalExecute(redoCommands.removeLast());
    }

    public void redo() {
        if (!redoCommands.isEmpty()) {
            internalExecute(redoCommands.removeLast());
        }
    }

    public void internalExecute(Command command) {
        if (commands.size() >= size) {
            commands.removeFirst();
        }
        commands.add(command);
        command.execute();
    }

    public void undo() {
        if (!commands.isEmpty()) {
            Command command = commands.removeLast();
            redoCommands.add(command);
            command.undo();
        }
    }
}

That’s it, folks.

Related Books

This design pattern is based on these two books, I have both ot them, I like the game programming patterns better than the original but the orignal is almost a must have a for any programmer.

Game Programming Patterns

I recently read Game Programming Patterns from Robert Nystrom one of the best books about programming I’ve ever read.


I get commissions for purchases made through the following link


I read the entire book from beginning to end in one go, I couldn’t stop. Normally I use programming books to fall asleep, the design pattern book of the gang of four doesn’t make any exception.

The book Game Programming Pattern from Robert Nystrom on the other hand is one of those very rare books which keeps me awake even late in the night. It is crispy, fun and it explains you the design patterns in a fresh and understandable way. It is also helpfull if you are not a game programmer as it explains the design patterns from the gang of four from a different perspective than you know from your daily work.

The author starts always simple without a pattern until he ends up in a dead end and solve the problem by applying graduadly the corresponding pattern which makes it so easy to understand the patterns in all his depts. It’s a very practical approach and even the samples are in C++ they can be easily adapted to any other language.

One of my favorit one is the command pattern with history functionality. Very use full for level construction tools.

If you are interested in design patterns and don’t like the original one, give this one a try.

Test Driven Development Integration Test

Beside unit tests, it is a good idea to have some integration tests. An integration test only makes sure that the new feature is in place. An integration test does not ponder on edge cases. It’s crucial to keep an integration test as simple as possible.

Make the Greeter App Modular

The greeter app from the Test Driven Development is not very modular and hence it is not possible to write integration tests for the new greeter app. In fact, in the first TDD blog post we only could write a system test to check if reading from the keyboard is working.

For the integration test, we need a ReadAndGreet module where we read from a scanner and return the greeting text. Let’s transform the greeter app from the second test driven development post

class Hello {
    void main() {
        Scanner input = new Scanner(System.in);
        String name = input.next();
        System.out.println("Hello " + name);
    }
}

to

public class ReadAndGreet {
    private Scanner scanner;

    public ReadAndGreet(Scanner scanner) {
        this.scanner = scanner;
    }

    public getGreeting() {
        return "Hello " + scanner.next());
    }
}

and

class Hello {
    void main() {
        Scanner input = new Scanner(System.in);
        readAndGreet = new ReadAndGreet(input);
        System.out.println(readAndGreet.getGreeting());
    }
}

Write a Failing Integration Test

And now we can write a simple failing integration test for the not yet integrated Greeter feature, which says "Good morning", "Good afternoon" or "Good evening" depending on the day time.

public class ReadAndGreetIntegrationTest {
    @Mock
    Scanner scanner;

    @Test
    void shouldGreetTomWithGoodMorning() {
        when(scanner.next).thenReturn("Tom");
        ReadAndGreet readAndGreet = new ReadAndGreet(scanner);
        assertEquals("Good morning Tom", readAndGreet.getGreeting())
    }
}

Perfect works… but wait, what if the test runs in the afternoon? It will fail and we don’t want to test the edge cases. So we need to relax the test a bit, we are only interested in "Good" and "Tom" and omit the in-between "morning", "afternoon" and "evening".

public class ReadAndGreetIntegrationTest {
    @Mock
    Scanner scanner;

    @Test
    void shouldGreetTomWithGoodMorning() {
        when(scanner.next).thenReturn("Tom");
        ReadAndGreet readAndGreet = new ReadAndGreet(scanner);
        assertThat(readAndGreet.getGreeting(), MatchesPattern("^Good .* Tom$", ))
    }
}

Now we have a failing and relaxed integration test because we don’t have our Greeter in place yet. That is the next step

public class ReadAndGreet {
    private Scanner scanner;
    private Greeter greeter;

    public ReadAndGreet(Scanner scanner) {
        this.scanner = scanner;
        this.greeter = new Greeter();
    }

    public getGreeting() {
        return greeter.sayHelloTo(scanner.next());
    }
}

And the integration test is happy. You have now a test in place that will act as an alarm if somebody accidentally removes the Greeter from your code. Or if somebody replaces the Greeter with the old "Hello" greeter functionality. Furthermore writing tests forces you to make your code modular which leads to more reusable code, think of a different scanner than the standard input. So again testing helps you in the microarchitecture and favors simple code over complex code.
If you have questions or improvements or any other kind of suggestions let me know in the comments below.

If you are interested in an online or onside workshop for test driven development write me an email artificials_ch@gmx.ch

Test Driven Development Fixtures

We all tend to write helper classes for testing, which clutters the test code and makes it harder to understand. A test should be like a story that you simply can read from top-down. I like test story better than fixture and I will use story and fixture interchangeable.

Why a Story Is More Powerful Than a Helper

If you have helpers you have code somewhere else, most often at the end of the test or even in another class where you hold all these helper utilities. If I read a test and I see method calls I tend to think that this is the code I test, but it is not. Helper utilities are also a sign that you probably need these utils also in your code and you should have tests for these utilities. As well helpers break the flow of your test story, it is like a reference to another story which you also should read before you can go on with this story. How awkward would that be in a book? Well, it is awkward as well in tests.
Unfortunately, this is hard to teach and to make visible why helper utilities are not a good thing.
When I write a test, I start with one single test and pack everything in that test I need, like calling methods, filling in entities, whatever is needed. Then I write a second test and do the same and after the third test, I put all the similarities into the setup method which is called before every test. And this holds the story. In Java JUnit5 it is the @BeforeEach annotation.

Let’s Jump Into The First Story

We base this blog article on the Test Driven Development Mantra. If not done yet read that first as it will give you a better understanding of the test refactoring we are going to make now.

We have two tests from that article (and maybe you did the exercise and wrote the next test with for "good afternoon")

  @Mock
    private DateTime dateTime

@Test
    void shouldSayGoodMorningToTom() {
        when(dateTime.getHourOfDay()).thenReturn(6);
        assertEquals("Good morning Tom", sayHelloTo("Tom", new DateTime()));
    }

   @Test
    void shouldSayGoodMorningToJerry() {
        when(dateTime.getHourOfDay().thenReturn(6);
        assertEquals("Good morning Jerry", sayHelloTo("Jerry", new DateTime()));
    }

The similarities are very obvious here and you can make a good morning fixture out of it like this

public class GoodMorningTest {
    @Mock
    DateTime dateTime;

    @BeforeEach
    void setUp() {
        when(dateTime.getHourOfDay().thenReturn(6);
    }

@Test
    void shouldSayGoodMorningToTom() {
        assertEquals("Good morning Tom", sayHelloTo("Tom", new DateTime()));
    }

   @Test
    void shouldSayGoodMorningToJerry() {
        assertEquals("Good morning Jerry", sayHelloTo("Jerry", new DateTime()));
    }
}

That’s it. You can read it top-down without any distractions. You have all together which makes tests very easy to read. Avoid helpers at all cost, it asks for troubles and confused programmers. And I’m well aware that this here is a very simple example, but honestly, most often it is not much more complicated than this here, test driven development favors simplicity.

Let me know if you have suggestions or questions in the comments below.

If you are interested in an online or onside workshop for test driven development write me an email artificials_ch@gmx.ch

Test Driven Development Mantra

This is the mantra

  • Think of a piece of code you want to add
  • Write a test which fails because that piece of code is not in place
  • Write that piece of code to make the failing test succeed
  • Refactor the code
  • Refactor the test

and you do that over and over again. Why did I not start with writing a test which fails? Because if you think for the next test without having code in your mind it’s incredible hard to figure out especially in the begining. This first step is a help and that works surprisingly well for me and for the people I taught test driven development with my workshops. It also keeps the steps as small as possible and in my opinion, that’s key if you want to test all the aspects of your new class.
And I do refactor the test as well and organize that around stories mostly referred to as fixtures. I will write about fixtures in one of the next blog posts about test driven development.

Simple App

Let’s carry on with the greeter app from the last blog post

Gretter.java

public class Greeter {
    public String sayHelloTo(String name) {
        return "Hello " + name;
    }
}

Hello.java

class Hello {
    void main() {
        Scanner input = new Scanner(System.in);
        String name = input.next();
        System.out.println(new Greeter().sayHelloTo(name));
    }
}

On the last meeting with the customer, we agreed that our greeting app must greet different depending on the daytime. Or more precisely our greeting app must say "Good morning" after 12 am, "Good afternoon" after 12 am and "Good evening" after 6 pm.

Practice

I will guide you to know how to write the needed code test driven step by step.

First Failing Test

What could be the next line of code we want to write? The easiest way ist to have an additional method in the Greeter class like this

public String sayHelloTo(String name, DateTime time) {
    return null;
}

We don’t write this, it’s just that we think of it. That is the first step. But wait… how does the failing test look like if that code is not even in place? Well it doesn’t compile and that is the failing test and it looks like

public class GreeterTest {

    @Test
    void shouldSayGoodMorningToTom() {
        sayHelloTo("Tom", new DateTime());
    }
}

Make the Test Happy

To make it compile we simply add the piece of code we thought about above and it compiles and even works.

Skip Refactor The Code and The Test

In this case, we don’t need to refactor the code or the test as there is nothing to improve so far. We skip these two steps in the mantra consciously.

Next Piece Of Code

The next piece of code is probably something like this

    public String sayHelloTo(String name, DateTime time) {
        return "Good morning " + name;
    }

but… resist writing the code!

Let’s Think of The Next Test

What could be the next test which fails? Exactly we add now an assertion for this. And here it goes

    @Mock
    private DateTime dateTime
    @Test
    void shouldSayGoodMorningToTom() {
        when(dateTime.getHourOfDay()).thenReturn(6);
        assertEquals("Good morning Tom", sayHelloTo("Tom", new DateTime()));
    }

I made already all the proper assumptions to say good morning and mocked the DateTime to return 6 in the morning if getHourOfDay is called.

And it will fail because our code just returns null.

Make The Second Test Happy Too

This is now really important and it is the only way to test all edge and aspects of your application in a test driven way. What do you think is the minimal code you need to make the app say "Good morning Tom"? What if I say just return exactly that? I mean literally this static string?

    public String sayHelloTo(String name, DateTime time) {
        return "Good morning Tom";
    }

I give you some time to digest… and while digesting run the test to see it is green. I mean it! Hit the damn button and run it.

And yes I know it is not our initial piece of code we thought of, but that is ok because that only helps us to find the next failing test. It’s a help and actually optional if you can do that without, I can not.

What Next?

The first thing we want to go rid of is this super static string. I guess that is your inner urge. Well then let’s think of a less static string, like this

    public String sayHelloTo(String name, DateTime time) {
        return "Good morning " + name;
    }

But… don’t write this code, just think of this code, because we need first a failing test!

Let it Fail Again

But how can we make the test fail? We simply write a new test with a different name, boom!

    @Test
    void shouldSayGoodMorningToJerry() {
        when(dateTime.getHourOfDay().thenReturn(6);
        assertEquals("Good morning Jerry", sayHelloTo("Jerry", new DateTime()));
    }

Isn’t that amazing? So simple to think of the next failing test if you keep thinking of a small portion of code.

That’s It For Now

What are the next steps for daytime addition to making the app say "Good afternoon Tom" if the getHourDay() method returns 14?

Write in the comment about how you would do that. What is the code you think of and what is the test which fails because that piece of code is not yet there? And finally what is the code to make the test happy.

If you are interested in an online or onside workshop for test driven development write me an email artificials_ch@gmx.ch

Test Driven Development Get Started

The start is always the hard part. Most often we face existing code where we have to add some new functionality. In always all cases there are little to no unit tests, but ugly and complicated looking integration or system tests which sometimes fail because of timing, network, or database issues. If you have already had a huge pile of unit tests in place, then you can stop reading. For the rest of us, proceed.

The Greeting App

Let’s dive into a simple example to illustrate how to get out of the mess. We have a very simple say hello app

class Hello {
    void main() {
        Scanner input = new Scanner(System.in);
        String name = input.next();
        System.out.println("Hello " + name);
    }
}

Just something which says hello. Simple. Can you test that? Well yes, you can start it and see if it says "Hello Tom" if you enter "Tom". Maybe there is a shell script based system test which tests that the app says hello to everyone. So whenever you improved your code you would have to start the system tests afterward. Nothing wrong with that. But it is slow to start the Java app and depending on what else you need, like a database or a REST call, you would also have to maintain the surrounding stuff with test data. Network and database add more failure points to the tests. The network could be down, the database could be in a funny state because your workmate did change something for his new feature and deleted all your test users. So system tests tend to be a fragile. I use system tests as well, but as simple as possible and as few as possible.

Refactor It to Make It Testable

To be able to test that with unit tests we have to refactor this class and put the greeting part into a class. Like this

public class Greeter {
    public String sayHelloTo(String name) {
        return "Hello " + name;
    }
}

And the main class would then just call this Greeter to say hello.

class Hello {
    void main() {
        Scanner input = new Scanner(System.in);
        String name = input.next();
        System.out.println(new Greeter().sayHelloTo(name));
    }
}

So you extracted the functionality into a class that you can test. That’s the way to go to have unit tests. This also helps you on a micro level to organize your code in a reusable way.

Unit Test

And the unit test for the Greeter would look like this

public class GretterTest {
    @Test
    void shouldGreetTom() {
        assertEquals("Hello Tom", new Gretter().sayHelloTo("Tom"));
    }

void shouldGreetJerry() {
        assertEquals("Hello Jerry", new Gretter().sayHelloTo("Jerry"));
    }
}

Yes, I have two tests. If I do that test driven I would start with a null to make the first test fail, then I would write a fixed string to greet Tom and then I would add the Jerry test to replace the fixed string. But more on that in the next blog post.

System Test

So now we are on a level where we can write unit tests for this greeting software. We will have one simple system test in place as well, just to see if it says something with Tom in it. We are only interested in the keyboard input is proper. Could look like this

#!/bin/bash
java -jar greetingApp.jar < Tom | grep "Tom"
exit $?

If the keyboard input does not work it will fail as the grep would return something different than 0. Why didn’t I just write this system test you might ask? Because it is just a matter of time when your customer wants that different. They might want the software to be aware of the time and greet you with "Good morning Tom", "Good afternoon Tom", "Good evening Tom" stead just "Hello Tom". So I only test the input of "Tom" that’s it, the edge cases I try to do on the lowest level possible and not on the highest level. It keeps your tests stable and very very fast.

The End

For now, I already prepared the next blog post where I introduce you to the test driven development mantra. Follow me on twitter @ia97lies and on @artificials_ch. Leave a comment below.

If you are interested in an online or onside workshop for test driven development write me an email artificials_ch@gmx.ch

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.