How junior frontend in a software development company can have fun - DO OK

Creating a JavaScript game can be fun!

When I got a job as a frontend developer in DO OK, I never thought that I’d create a game. Of course, I expected to learn a lot about React, Javascript or teamwork, but how could I know that a bit of free time and a crazy idea would be transformed into DOOKTOPUS?



In this article I’ll focus on some of the challenges I encountered when I was building the game, and how I solved them (if at all). I’m assuming the readers have at least a basic understanding of the concepts behind building simple games, which are well covered in game development glossary.

Origin story

Inspiration for game
Inspiration for game

Just look at this image. These octopus mascots are an inspiration and a decoration of everything in our front dev room. When one of our teammates mentioned making our own game, it was clear who would be the main character! The suggestion about a game turned into a real project when our team leader said that it is a great idea.

Choosing the right Javascript / HTML5 framework


I decided to write the game in JavaScript as an HTML 5 game. I was thinking about vanilla JS, but I decided to use a framework to make things easier. My choice was Phaser, a popular framework for making HTML 5 games. It provides handy API with a lot of examples, however, not everything was straightforward. I used Phaser CE which is a fork of Phaser v2. When I started my work, Phaser 3 docs weren’t yet available, but right now they are up and you should definitely look at Phaser 3 if you want to try this. So while I wasn’t on the newest version, the upside was that there were lots of examples online which still used Phaser v2 API, making my life much easier. I wanted to have the ability to use ES6 classes and modules, but I didn’t have any knowledge about best practices in structuring a Phaser game. The issue was that all tutorials and samples I could find were written as a single file using ES5 style. My remedy was a repository called phaser-es6-webpack. The added bonus of using this repo was having the ability to easily build a mobile app version using Apache Cordova.

 

First look at the Phaser code and collisions


The main pattern of Phaser code is simple. One of the main concepts is state. You can think of it as an autonomous view, e.g. loading screen, menu, actual game scene, game over screen. The state has several built-in methods, such as init for taking things from other states or for loading resources, create for adding sprites on the screen, update which fires with every frame and checks for various conditions, for example, collisions.

In examples below this refers to a chosen state object. It has access to various Phaser manager objects like Phaser.Loader.


To use assets, you first have to load them:

this.load.image('key_for_img', 'path/to/img');
this.load.spritesheet('key_for_spritesheet', 'path/to/sprite', frame_width, frame_height);

Once the asses are loaded, you can add them to a particular state object and place them in a chosen location:

this.add.sprite(x_pos, y_pos, 'key');
this.add.button(x_pos, y_pos, 'key', click_func);
this.add.text(x_pos, y_pos, 'Text', {font_properties});

Adding collisions is easy thanks to built-in physics engine. To enable it:

this.physic.enable(ARR_OF_SPRITES_TO_APPLY_PHYSICS_TO, Phaser.Physics.ARCADE); // ARCADE is one of the available physics types ```

Once the sprites have their physics behaviour enabled, you can define collisions: In the create method defines the overall parameters of the collision behaviour:

sprites.body.collideWorldBounds = true; // makes the sprite collide with the edge of window
sprites.body.bounce.set(1); // makes the sprite bounce on collision

In the update method actually check for the collision and optionally call a method which drives extra effects during the collision:

this.physics.arcade.collision(sprite1, sprite2, optional_func)
My idea of collisions between octopus and water.
My idea of collisions between octopus and water.


This is where I ran into a problem. The idea of the game is that the octopus needs water to survive, so I need a way to model collisions with the surface of the water. Water is a sprite which can have collisions enabled, but they only work from the outside, not the inside! I thought that Phaser must have a helper to provide this feature. I was wrong. After a few hours of research, I gave up and invented a simple workaround. I built an invisible sprite which is placed just above the surface of the water and changes its position together with the changes in the water level. It may not be as elegant as an internal collision mechanism, but it works

Another challenge with collisions had to with overlaying sprites. The standard function for collision checking doesn’t work if one sprite overlays another. In my case, I was changing the position of an invisible sprite manually which would sometimes cause the octopus to boldly leave the water world.

One option to solve this was to use an existing moveToXY function which is directly connected to physics, which makes the sprites’ positions predictable for the engine. However, moveToXY has some limitations and so I opted for another solution. I replaced collision with overlap , and when overlap with the invisible obstacle is detected, I push out the octopus sprite back into the water with the function passed to overlap .
Overall, dealing with collisions was not trivial but quite satisfying.

 

Working with music and pixel art


Taking a break from code, let’s talk about the sprites which I worked on. I chose pixel art because I’m bad at drawing. I find working with pixels on a small area much easier than digital painting, especially with using a mouse. Generally, the process was enjoyable, but it also took a long time. I used Photoshop, but there are good free online tools like piskel or pixilart. For Photoshop or Gimp users who want to go into pixel art, I have three tips: use pencil instead of a brush, set interpolation on the nearest neighbour, and if you want less work, start from the smallest possible canvas size.

I searched through FreeMusicArchive for some annoying 8-bit music to use as a soundtrack. Simple sound effects were made by me using an online tool called BeepBox, which was super fun. I said we were taking a break from code? Unfortunately, music poses a new problem. As I mentioned earlier, Phaser uses the state as a core concept. Question is, what if you want to keep playing the same music across multiple states without restarting? Theoretically, nothing needs to be done, because when you add music using audio = this.add.audio('soundtrack'); audio.play();, the music will not stop playing after switching between states. However, opening the menu caused the music to begin again, so two soundtracks were playing simultaneously. The solution was to assign the audio object to a class variable so that I could check if it already exists.

 

The gameplay is the biggest challenge

 

The most important aspect turned out to be overall gameplay quality, specifically keeping the players of various skill level engaged. I didn’t make any detailed plans for the game, I just dived into code with only one the idea of water falling down and the player scoring by clicking the octopus. Initially, the time of a single playthrough was fairly monotone with the water level always decreasing and not much the player could do about it.

I began rewarding accurate players by raising the water level every few successful hits, but it had relatively little effect on the player score. Eventually, I developed a combo system which rewards accuracy of a good player to a much greater extent, making achieving a high score possible for a diligent gamer :).

Thanks to the development of DOOKTOPUS, I came up with many new ideas for games using even just the same elements, which could be much more engaging to players. For example, I could create a sharky version which depends on killing sharks (like in Fruit Ninja that want to eat our dear octopus. Who knows, maybe one day?

 

An unresolved issue


Despite the game working well, there is one unresolved bug accompanying me almost from the very beginning of my work. Sometimes, there is a small gap visible between the waves and the main water (these are two separate sprites). Depending on the project’s stage, this situation was more or less pronounced.

What is this?
What is this?


To this day I wasn’t able to identify the root cause.

Initially I though this could be a number rounding issue, which turned out to be significant but didn’t fully resolve the issue. Searching the web, I found a lot of forum posts suggesting that I change the render mode on the canvas. I did try changing the rendering mode and… it looked much worse. I had to keep looking.

Another suggestion I found mentioned that when you want to tile sprites, they should have repeated pixels at the sprite edge to help with what I believe is a rendering artifact of the engine. It seemed to work for a while, the gap seemed to appear less frequently and was less pronounced.

The final work around I considered was to join the sprites into a single image, but I think there should be a better solution. If you have any idea how to fix it, please share that in a comment!

Summary


To summarize my experience, I can say that it wasn’t all that hard to create a game from scratch without prior game dev experience. The learning path is easy, especially with frameworks like Phaser, because of all the features already available as well as a big community sharing lots of code. It helps in understanding how specific elements of game work. Now I can create plain JavaScript game, which was out of my reach before.

I now realize that it would have helped to have planned as much as possible before implementation, especially when it comes to the overall gameplay. It’s the key aspect of the game design, and the ideas behind it may be hard to come up with and hard to implement.

However, not having strict plans also let me learn a lot along the way and improvising.

I’m glad I wrote DOOKTOPUS. Even though it may not be the most interesting game around, I’m proud of it. I got plenty of positive feedback from other developers at DO OK, which was really encouraging. I think that everyone should try to create a game, it can be a welcome change from daily work.

If you have any questions or suggestions, feel free to leave a comment. You will also find a few relevant links below.

Wave the uncertainty and get opportunities with Value-Focused Workshop
When the clock struck midnight on January 1, 2020, most of us optimistically looked ahe...
12.10.2020, min read
Dmitrij Żatuchin
Read more
What is business analysis?
07.10.2020, min read
Dmitrij Żatuchin
Read more
Cookies

Our website has cookies. more info