HellWorm game. Development history

Good day! I would like to talk about my experience in creating a mobile game on Unity called HellWorm. From the name you can understand that the game is about a worm. We crawl, eat coins, do not crash into obstacles. It would seem to be a clone of the classic game on which most of us grew up. But, in fact, the parallel with the snake ends there.


The game, however, positions itself as an endless runner in which there is a constant forward movement, without the ability to turn off the vertical route. And the worm itself, with all this, can wriggle as it pleases (yes, yes, and even crawl through itself). As a result, I would like to focus on the difficulties that I experienced trying to realize the movement of such a straightforward character.

Management is quite simple and is described by only one phrase:
“Where you click, it crawls there.”


The first implementation of the motion algorithm is clearly demonstrated in the diagram below.


The essence of the movement is this: with speed n the length of the first segment (head) increases and the length of the last (tail) decreases with the same speed, and at the moment of pressing the screen a new segment is created. The connection goes along the center lines of the rectangles. And at the joints, to smooth the cuts, circles are placed with a radius equal to the width of the segment. However, this method, unfortunately, did not fit, because the visual style of the game does not imply the use of rounded corners. I had to reinvent the wheel further, so please read the following implementation.


Docking occurs not along the central lines, but along the corners of the segments: on the left or on the right, where the side is selected depending on which side of the line AB lies the new point P.

(Bx - Ax) * (Py - Ay) - (By - Ay) * (Px - Ax), if the expression> 0 then the point P lies on the left side.

How to find the coordinate of the docking point, I will not paint, because there is nothing special about this, simple geometry. I’d better tell you more about the approach itself.

I want to immediately stipulate that in this case the maximum angle between the segments should be no more than 90 degrees, otherwise, as you might guess, the corners will come out. Therefore, during steep (> 90 degrees) turns, a transition segment is added.


When a player clicks on the screen, the angle that the worm should rotate is remembered and as soon as the head segment reaches the allowable length, a new segment is created at the specified angle, provided that it is no more than 90 degrees, otherwise a transition segment is created, and when it reaches a predetermined length, then a final turn occurs. This strategy allows you to avoid chaotic distortions with a very quick tap on the screen, and also makes the movement more natural. I would like to note that there are no visual delays in control at all.

The experiments ended and the development of the game continued: various types of obstacles, level generation, a store with skins, a bonus coin mode when selecting a shard, color change of the environment depending on the path traveled, etc. were added. During this time, the look was decently “blurred” and I simply did not notice a misfire in my algorithm for moving the worm. Namely, small jerks when changing the direction of movement. As it turned out, the thing is the connection of segments at extreme points.


When creating a new segment in this way, it is not possible to connect the centers of the sides of the segments (red and blue dots in the figure). And since the head of the worm is always tied to the center point of the first segment (and the tail is tied to the center of the edge of the latter), a jerk occurs when turning, and the larger the angle of the turn, the more noticeable the jerk. Of course, at the final stages of development it is very annoying to encounter this, because you need to redo the entire algorithm. But the desire to finish the project polished and without jambs prevailed. It was decided to return to the first implementation of the algorithm, because to calculate with respect to a broken solid line around which the body is built is much simpler and more logical. It remains to solve the problem with the joints of the rectangles, namely, how to fill them.


After a little reflection, the idea came to extend the segments towards each other to eliminate the gap.


The solution turned out to be quite working, and, surprisingly, the first time it worked. The math steps are as follows:

  • determine in which direction the new segment is looking relative to the previous one (to the left or to the right)
  • find the corner points B, C and the points at the other end of the segments B ', C'
  • we find the intersection point A of the lines BB 'and CC':

    Ax = ((Bx * B'y - By * B'x) * (Cx - C'x) - (Bx - B'x) * (Cx * C'y - Cy * C'x)) / (( Bx - B'x) * (Cy - C'y) - (By - B'y) * (Cx - C'x))

    Ay = ((Bx * B'y - By * B'x) * (Cy - C'y) - (By - B'y) * (Cx * C'y - Cy * C'x)) / ((Bx - B'x) * (Cy - C'y) - (By - B 'y) * (Cx - C'x))

  • we extend the segments by the lengths of the segments BA and CA, respectively

In general, on this development of the algorithm for the movement of the worm was successfully completed. Separately, I would like to note that this algorithm can be used to create a worm or a snake with rounded (realistic) edges during bending. To do this, it is enough to set the maximum pivot angle of about 10-15 degrees, and also reduce the allowable segment length for the pivot. The result is shown below:


In addition, I would like to tell a couple of words about the generation of the surrounding world. All objects are saved in sprite sheets in black and white. Frames are painted in white that change color during the game, because changing the color of the Sprite Renderer all white areas become exactly the selected color.


(side walls with added Polygon Collider 2D, and background image)

The same technique is used for game obstacles and the main character.


In the screenshot with obstacles, you can see blue and yellow rhombuses, these are places where coins (yellow) or shard (blue) can appear. They are empty gameobject with the selected icon.


I chose this approach, firstly, to simplify the task of adding coins / skulls to the scene (not to bother with random generation), and secondly, so that they appear in places interesting for gameplay. And, since there are about 70 different tunnels, rocks and passages in the game, the predetermined places are not so noticeable for the player.

I’ll tell you a few words about the worm, namely its head. The player has the opportunity to change it (like other parts of the bodies), and, including the color of the skin and eyes.


It was not obvious to me how to implement this. Therefore, the resulting solution, perhaps not the most competent, but working.


There is a prefab of the worm_head head, which contains all the head + n heads, consisting of head objects (white head sprite) and eyes (eye sprite located on top of the head, which is also white). By default, all head + n objects are invisible. During the start of the game, the number of the installed head is checked to make the object head + n visible. Along with this, the color scheme chosen by the player is applied: the main color is set for the sprite of the head, body, tail, and additional colors are set for the eyes and spikes.

head.GetComponent().color = headColor;
eyes.GetComponent().color = eyesColor;

In my opinion, I talked about the most interesting and not obvious moments of development, but if anyone has questions, I will be glad to answer them!

Thanks for attention. You can play the game on Google Play.

PS There is no publisher in the game, we are trying to get started on our own.

Also popular now: