Week 6 – Project Management Tool & Our Game Engine

JIRA - Introduction

We use Jira for project management which allows several Scrum-functionalities.

Our sprints last for one week each in order to fit the weekly updates on our blog and the given tasks of the lectures.

Because of initial difficulties, we had some problems using Jira in order to get a fancy burndown-chart. The burndown-chart of week 2 is displayed on the right. Because Jira does not support the public chart-generation, there is no public access to live diagrams available.

Jira Integration in Android Studio (IDE)

GIT integration in Jira

Game Engine - General

When we talk about the "Game Engine" we focus on the inner core of our app which is doing the logical part. This engine provides our objects at the moment without a physical extension. That will change in the next weeks, but the behavior of our main objects like towers and enemies will still be the same. To get an overview of the development just have a look at our class setup:

At the top, you can see some testing classes for JUnit. Actually we only test the logic of the classes Enemy and Tower, because of the artificial intelligence they include.

As we described it in our process we handle two Activities currently, the MainActivity which is the starting page with a menu and the GameActivity where the game is running at.

The 'Game' class creates a simple demo of our game which is helpful for us to see if everything is working as we expect.

Game Engine - "MatchField"

The first part of the engine is the class "MatchField". This class keeps all the enemies and towers and controls them. The main part is about moving the enemies and let the towers shoot them. So every Object needs a different thread to be able to act independently on the map. An example of starting the towers looks like that:

  • As long as there are enemies on the map our towers will be able to fire
  • after one shoot we clear the map by removing dead enemies
  • if there are no enemies left on the map, the towers will be stopped (the map contains all enemies of a wave even if they are not spawned yet)
  • the timer task we used there, also have to observe the fire rate of a tower

This class "MatchField" is, in conclusion, our game controller, so it also knows when the game is over and so on.

Game Engine - Enemy & Tower

The abstract class Enemy contains all basic actions an enemy has to perform. So it contains the logic to move on the given path the ‚MapStructure‘ defines and it also knows about the healthpoints, moving speed and other criteria. The move action can move the enemy one pixel on the given path, the enemy class makes sure that it’s moving in the right direction. But the move action is called by the MatchField to control the speed by scheduling a timer.

More interesting is the artificial intelligence of ower towers. Before a shoot, we need to calculate for every enemy which already spawned on the map the distance to our tower. Then we need to decide if the enemy is in the shooting range. If there are multiple enemies in range we focus on the nearest. In most tower defense games the focus only changes when the enemy is out of range, so towers fire multiple times on one enemy. The logic is not hard to implement but we are not quite sure if we want this behavior or not. So maybe you can give a feedback about which behavior you would expect. Currently, a tower focuses on the nearest enemy and calculates that before every shoot. The distance for all enemies is collected in a map, where we wrote our own util to sort the map by value. So we have the possibility to get the next enemy to the nearest if the first one was shoot at the same time and is already dead… So you see there is lot we had to think about.

Game Engine - "MapStructure"

Another big part is our MapStructure. We need to create a map with lots of fields. Every field has one of the conditions: free, path or tower. So a tower can only be placed on a free field, but then the field is set to tower. A field can also be free again by deleting a tower. But the path can not be changed while the game is running. At the moment we set a fixed path by defining different positions at the beginning, where the fields should be a part of the path. But the map Structure does also include more logic. It is the representation of the map and has methods like getNextFieldForEnemyToMove() and so on.

Creating a random path will be very easy, with the foundation we have here. But in the beginning, we won’t focus on that.

We don’t want to bore you with some more detailed information yet. There is some more stuff like the Bullet class which represents the projectiles a tower can shoot, but enough is enough.

Game Engine - Application

The current result of our game-engine is only textbased in the console. We saw that before in week 4 as a preview, now you know a bit more how it works. The game is already running like intended. So enemies move, towers shoot and also the game stops if all enemies passed the target or died before.

Next step will be to visualize our objects and just to give you a little preview, yes we are already working on that! 🙂

6 Gedanken zu „Week 6 – Project Management Tool & Our Game Engine

  1. Hello guys,

    great to hear about your progress.

    The part about your scrum workflow appears a bit short. But I also know that there isn’t very much to write about and your screenshots speak for themselves. So I assume its OK.

    Thank you for giving an introduction to your game-engine. Now it becomes more clear what you are doing. About your question on which enemy to focus: I would also expect the tower to focus on the nearest enemy, like you already implemented it.
    But I have a question about your implementation. Why did you implement it that way? It looks like you are creating some overhead by doing it this way, because of the extra lists, maps and loops you are using. I would adapt the fire method the following way:

    public boolean fire(List enemies) {
    Optional nearestEnemy = enemies.stream()
    .filter(this::isEnemyInRange)
    .filter(Enemy::isAlive)
    .min(this::compareEnemyDistance);
    if (nearestEnemy.isPresent()) {
    Enemy enemy = nearestEnemy.get();
    enemy.reduceHealthPoints(damage);
    System.out.println(enemy.getLabel() + “ was shot by “ + label + “ and has “ + enemy.getHealthPoints() + “ hp left“);
    return true;
    }
    return false;
    }

    private int compareEnemyDistance(Enemy e1, Enemy e2) {
    return Integer.compare(getDistance(e1.getPositionX(), e1.getPositionY()),
    getDistance(e2.getPositionX(), e2.getPositionY()));
    }

    This is only a suggestion. I suppose this would be more lightweight and performant especially when there are more enemies in the game at a later stage. Also it looks more readable to me, but this can also be a personal preference. As this is your project I don’t want to influence you too much, just show my solution. If you already have some good reasons for doing it the other way, you can ignore this suggestion.

    Keep on working!

    Yours, Marlon
    from SaSEp/Clairvoyance-Team

    1. Hi Marlon,
      we are amazed – thanks a lot for your extensive feedback and suggestion!

      In our team, we already discussed about your solution for the fire-method. I want to demonstrate our considerations:
      Your solution is probably more performant, just like you said.
      At the moment, your code focuses on just one enemy which is nearest to a tower. For the current situation, of course, your solution would work out.
      In the future, there will be towers that support shooting multiple enemies (we did not write something about this feature yet). In this case, your code presumably would not work out anymore because of the focus of just one enemy. Using our (current) solution, we could probably support towers shooting at multiple enemies more easily.
      This is why this part is implemented this way.

      Nonetheless, we will test your solution/way of thinking on performance soon because your idea seems very useful at least at the moment.
      We will keep you up to date in the following blog entries.

      Oh and don’t worry, you don’t influence „too much“. We really appreciate every new idea because it improves the whole game in the end. 🙂

      Kind regards,
      Nicolas

      1. Hi Nicolas,

        if you want to target multiple enemies, you could simply replace the .min() function with .sorted(this::compareEnemyDistance).limit(x). Then you will get a list of targets to fire on or use the forEach()-function of the stream directly to execute the fire-code .

        Yours,
        Marlon

        1. Hey Marlon,

          I tested the two different implementations with some unit tests and with one million enemies in range, yours took about 0.2 seconds while our implementation needed 4.5 seconds. So you were totally right, thanks for the help! The performance won’t make a big difference as we don’t have more than 20 Enemies on the map in one wave, but it is nice to read and in both cases the better implementation.

          Kind regards,
          Fabian

  2. Hello Towerdefense Team,

    it is really cool to see a burndown chart of your sprint up front, also I see that you have managed the Integration into the IDE too.
    It would be cool to see how much time each individual of you have spent on which category though.
    Maybe you have implemented it but not showed it, it would be nice to know that.
    All in all you did very well and you should keep up the good work!

    Sincerely

    Manu & Simon
    Gyrogame Team

    1. Hi Simon,

      thanks for your feedback!
      As far as we know, our project-management-tool Jira sadly does not support any chart-functionality in order to show the time of each team-member spent on certain categories/workflows (even not using external plugins).
      In return, we are able to generate charts which show the whole time of each member spent on all tasks and charts which demonstrate the total amounts of tickets for each category.
      We will keep our search for a suitable chart-plugin on in order to have more possibilities in the future.

      Kind regards,
      Nicolas

Die Kommentarfunktion ist geschlossen.