Iteration 1 – Production Diary

Monday 4th:

I had planned to set up the GitHub repo, start on the UI elements, and create a basic start screen.

To start creating the UI elements, I made a button class that I can use anytime I need to generate a button. I did this because the game will have a pause/play button, and a menu that the player will use for summoning towers. By have a pre-made button class, I can simplify how much code I need to do in the future. I had hoped to have a few more UI assets completed today, but I didn’t get round to it. I plan to catch up on the asset creation later in the week.

For the start screen, I placed a button in the centre (missing its asset) that the player can touch and it will load up the first level. I would like to possibly add an options menu in the future, but I’m unsure at the moment.

I started on a basic tower selection menu, that will pop-up over the game screen to allow the player to select and upgrade their towers. The menu currently doesn’t do anything, but it’s there.

Tuesday 5th:

Today in the morning I had planned to work on the monster base class, the altar that the player will protect and start on an example level. In the afternoon I wanted to make the unit summoning menu functional, and start on my collision detection system.

Instead, I spent the day in bed, feeling sorry for myself with a nasty cold and headache 🙁

Wednesday 6th:

Originally, I wanted to work on the path following system today, and create the maths functions for upgrading and purchasing towers. However, the majority of today was a repeat of yesterday, spent in bed, trying to recover.

In the evening, I had started to feel better, so I decided to attempt to catch up on some of the work that I had been unable to complete.

The main task that I got done today was creating a class for creating an Altar object. The main goal of the game is to protect your Altar, so it was important to get this object into the game in way that will allow me to summon a new one each scene without having to duplicate code.

When the player’s remaining health goes below a set threshold, I want the altar’s frame to change. I didn’t realise that I could use the simple setTexture method to change the frame of the sprite until after I had created single frame animations for the Altar’s different frames. In the future I would know to use setTexture instead, but as I had already written code to use animations, I left it as it was.

I also created the lose state for the game, by creating the take_damage function for the altar. To stop the game when the player’s health goes negative, I disable input and pause the scene’s physics. I started on the tower’s (monster’s) base class, creating a few properties that I feel may come in useful later such as health, attack_speed and level.

For the cost functions, I referred to my old maths notes from A level to find a suitable curve that would be fairly simple to graph. I used Desmos a graphing web app the adjust the curves until they were just right. On paper I rearranged the equations so that they had y on one side and could be used to return a value when needed.

My upgrade function is: 

Even though the graph has an asymtope at x = 10, it is still fit for purpose as I don’t want the player to be able to upgrade past level 10.

My cost function is: 

By using this function, I can continue to increase the cost of purchasing a troop without imposing a limit on the number of a particular type the player can have.

Thursday 7th:

My plan for today had been to create win/game over states, and start on an enemy attack system. Due to the fact that I was behind on other tasks, I was unable to begin work on these particular problems.

I glued together the images for the tentacle’s spritesheet using a tool by Leshy Labs that allows you to create a spritesheet just by uploading the individual frame images.

To create a path for the enemies follow, I looked at a Phaser tutorial that allows you to use interpolation to create smooth paths for your sprites to follow. It uses two arrays of values – one for x, one for y – that I want to read in from a Tiled tile map in the future. Currently, I am using placeholder arrays for testing, as I pass these arrays to the level base class from the instance of a level.

I also started work on the enemy base class, putting in a basic attack function, and attempting to create the update function to allow the enemy to move. I couldn’t test this yet as the game didn’t have a start button, but it wasn’t throwing any errors due to improper syntax, so I left it as it was and moved on to a different code task.

In the past, I had created a cooldown function for enemy attacks where the game would compare the current time to the time of last attack. I looked over my previous code to help in creating a cooldown function for the towers, so that they couldn’t spam attacks. I wanted to do this so that the enemies could pass through a few towers attack areas, forcing the player to spread their towers out across the path to the altar.

Monday 11th:

During the Game Design Document planning phase, I only created planning for the first week of development time. This was to allow me flexibility going into the second week in case of tasks that were incomplete, or bugs that may have popped up during the first week.

The key tasks that I had left to do at the beginning of this week were:

  • Complete a start screen
  • Spawn in enemies when the player hits start at set intervals or in waves
  • Work on unit placement mechanics
  • Put individual sprite frames into spritesheets
  • Add in a start/pause/play button
  • Collision filtering/detection
  • Add in currency the player can spend

I spent a good section of today planning out in what order tasks would need to be completed, to make sure that I could properly test each new section of code for bugs without having to rely on something else being completed first.

Wednesday 13th:

Today I focused my time on working on the start/pause/play button, as well as the tower summoning mechanic. I briefly started working on the base class for the first type of monster I wanted to implement – a tentacle that has a slam attack.

I started on the summoning system by looking at some of my past work to see how I had implemented touch controls in the past. I started out using the method from the Matter Game, however I found that it wasn’t working quite as I needed. It was suitable for swipe input, but I wanted a drag system instead. I decided to fix this another day, to allow myself to continue to work on other components.

To implement my pause/play button, I created a new PausePlayButton class. I couldn’t extend my previous button class as I used a sprite sheet for my new class, whereas the other class uses an image instead. I decided to use a state constant to check whether the game was paused, playing, or stopped. This was so that on my update loop, I could ensure that the correct frame of the sprite sheet was displaying based on what state the game was in. This will also help in the future once I make the button interactive.

Thursday 14th:

Today was a check-in day at uni, so I wanted to use that opportunity to get some help with a couple of errors that had been troubling me over the past week.

I fixed a simple problem where my tentacle class was unable to inherit from my monster base class by simply changing the order in which they were loaded in the index file.

I created a SpawnerButton class that inherits from the Button class to use for confirming if the player is happy with where they have placed their unit.

Since I want to read in my enemy paths from a tilemap, I created two functions to read in the tilemap data, and convert the information from the objects layer into the arrays needed for the path creation functions.

During the university session today, I spoke to James about a way in which I could prevent specific objects from colliding with one another. For example, I wanted to be able to display a monster over the top of the summoning menu background, whereas they were colliding with each other and the monster was being pushed off of the menu area. He explained that I could set the background to static to prevent it from moving and set it to a sensor to prevent it from colliding with other objects.

The next task that I moved onto was changing the controls over. Built into Phaser was a drag input function, that allowed me to update the position of the sprite as the player moves it. Furthermore, there was a dragend function so I could have the confirm button pop-up whenever the player stopped dragging the sprite around.

                    this.input.on("dragstart", function (pointer) {
                        this.menu_background.setActive(false);        
                        this.menu_background.setVisible(false);
                    }, this);
                    this.input.on("drag", function (pointer, object, drag_x, drag_y) {
                        object.x = drag_x;
                        object.y = drag_y;
                    });

Saturday 16th:

For today, I updated my pause/play spritesheet, as there were white corners on all of the images. I also created a basic, plain, place holder tilesheet as well as a level that I could use for testing and debugging. I also changed the dimensions of the game canvas by 4 pixels. Originally, I had matched it to the Google Pixel’s dimensions however, I needed the screen dimensions to be a multiple of 32. Unfortunately, I wasted a lot of time over a mistake that I made importing the tileset into Tiled. Instead of setting the spacing of the tileset to 1px, I set the margin to 1px. Since I didn’t notice this problem immediately, I spent a while trying to diagnose the issue in another way, hence I didn’t get much more done today.

Sunday 17th:

As today was my last day of development time, I focussed on making sure that the game was playable all the way through to ensure that my testing tomorrow will go as smoothly as possible. A small change that I made was to move where I loaded in the animations from the altar class into the level loader, since I had more than one sprite with animations to load now. I also moved the spawner timer for the enemies from the Level_1 class into the level base class so that it can be access from new levels in the future. I fleshed out the game over state, properly pausing the scene. Before, I wasn’t pausing the physics correctly, as I hadn’t used the Matter specific way of freezing it.

Another problem I fixed was the enemies weren’t quite following their path correctly, this was due to the fact that when loading in the path, I was incrementing up to the number of items in the passed arrays, rather than iterating for each pixel in the width of the screen. Next, I implemented the enemies attacking the altar and being removed from the enemy array. I needed to add a new level property that tracked how many enemies had been spawned in. This was so that I could remove enemies from the array without infinitely spawning enemies in.

My main time sink today was creating a collision detection system. In Matter physics, you cannot determine which objects have collided with one another using functions built into Phaser, you can only detect that two objects have collided with one another. Initially, before I noticed that I couldn’t tell what was colliding, I looped through every enemy setting up collisions with all the tentacles. However, after realising that this wouldn’t work, I changed my approach. To figure out how I could tell what was colliding, I put in console logs for information on the two bodies that were colliding. I quickly realised that the only information that the event tracked was about the bodies themselves, not the objects that they belonged to.

In order to determine what was colliding, I created two for loops – one for all the monsters and one for all the enemies. Initially, I loop through the monsters and check if one of the bodies matches the body of a monster’s attack radius. If more than one tentacle is detected, then the event is exited. If no tentacles were detected, then the event also exits. I repeat this process but with the enemies. If there is a tentacle and an enemy colliding, then the tentacle attacks, else the event is exited. I found the keyword “instanceof” very helpful, as it allowed me to determine if my variables for storing the tentacle and the enemy had already been filled, enabling me to exit the event earlier if two tentacles or two enemies were colliding.

        this.matter.world.on("collisionstart", function (event, bodyA, bodyB) {
            var tentacle = {};
            var enemy = {};
            for (var i = 0; i < this.tentacles.length; i++) {
                if (bodyA.id === this.tentacles[i].hit_box.id) {
                    if (tentacle instanceof TentacleClass) {
                        break;
                    } else {
                        tentacle = this.tentacles[i];
                        break;
                    }
                } else if (bodyB.id === this.tentacles[i].hit_box.id) {
                    if (tentacle instanceof TentacleClass) {
                        break;
                    } else {
                        tentacle = this.tentacles[i];
                        break;
                    }
                }
            };

When this system was complete, I was very pleased with the outcome. However, it does occassionally freeze up the game when a new object is spawned and a collision event trigger within the same frame. This is something I will need to aim to fix in iteration 2.

Monday 18th:

Today I fixed a few last minute issues from the night before just to tidy up my code and make the game better for testing. The main task I completed was showing the cost of summoning a monster to the player so that they were better aware of if they were currently able to summon an extra monster or not.