preface

Recently, I came up with the idea of implementing a tower defense game using Canvas technology, in which the gameplay is mainly about monsters being born from the starting point, and before they reach the end point, players can use gold coins to place/upgrade items to stop or defeat monsters. When the monster enters the item’s attack range, the item’s muzzle is pointed in the monster’s direction and bullets are fired in that direction.


I. Example screenshot


2. Functional analysis

Before we can implement this bullet tracking algorithm, we need to understand a few things.

  1. Does the speed of bullets vary depending on how far monsters are from items?
  2. How does the bullet have to move?
  3. How do I get the direction of the bullet?

Well, after putting forward these three questions, we can carefully think about the answers to these three questions.

So, the first question.

Does the speed of bullets vary depending on how far monsters are from items?

The question is actually quite simple.

Let’s think carefully, in the life around us can see the tower defense game, is there a bullet from the near to the far is a second to the game?

Apparently, very few, or very few.

Then there is the second question.

How does the bullet have to move?

Here we can look at the example diagram above (also sketched below).

From the picture we can see that the monster is in the upper left corner of the item.

That is, the monster’s X and Y values are less than the item’s X and Y values.

Since the initial position of the bullet is the center point of the prop, when our bullet wants to move toward the upper left corner, the bullet can move toward the upper left corner by adding negative values of x and y.

And the same thing happens when x is equal to 0, when y is equal to negative 1, when y is equal to negative 1, when y is equal to 0, when y is equal to negative 1, when y is equal to 0, when y is equal to negative 1, when y is equal to negative 1, when y is equal to negative 1, when y is equal to negative 1, when y is equal to negative 1, when y is equal to negative 1, when y is equal to negative 1, when y is equal to negative 1, If y is 1, we’re going to move down to the right and x is equal to 1, if y is negative 1, we’re going to move up to the right and x is equal to negative 1, and y is equal to 1, we’re going to move down to the left

Finally, let’s think about the third problem, which is the most important and difficult problem.

How do I get the direction of the bullet?

We know that the x and y velocities of the bullet affect the direction of the bullet.

Maybe a smart friend would think that we would compare the x and y coordinates of monsters and items and figure out whether x or y should be 1, -1 or 0.

It’s true, but it’s also not true.

Because what happens if we just take 1, minus 1, 0?

In that case, the bullet would only travel at 0 degrees, 45 degrees, 90 degrees, 135 degrees.

Obviously, these are not the only fixed angles between monsters and items.

So we can use some mathematical theorem at this point.


Pythagorean Theorem

Let’s take a look at this picture.

In this picture, the positions of monsters and items clearly form a right triangle.

In mathematics, you can use the Pythagorean theorem to figure out the hypotenuse of a right triangle.

namely

But if you think about it and you’re confused, why do we do the hypotenuse? Does the hypotenuse help with the Angle of the bullet? Let’s not hurry here, but we’ll see why later on.

In the figure above, we can know that a value is the absolute difference between the monster and the prop’s Y-axis, and B value is the absolute difference between the monster and the prop’s X-axis.

So let’s assume that x of the monster is 10 and y is 10.

Item x is 30, y is 20.

So we can get the side of the bevel

let x1 = 10,
    x2 = 30, 
    y1 = 10,
    y2 = 20,
    c = Math.sqrt(Math.pow(Math.abs(x1 - x2), 2) + Math.pow(Math.abs(y1 - y2),2));/ / 22.360679774997898
Copy the code

Now that we have the bevel edge, we can declare a value, which is the speed of the bullet, to ensure that the bullet’s speed does not change whether it is close to the monster or not.

const speed = 5;
Copy the code

Here we declare the bullet speed variable and assign it a value of 5. This means that the bullet moves 5 pixels per frame.

We then divide our beveled edge by the bullet’s velocity to get how many frames later the bullet reaches the end of the beveled edge.

let hy = c / speed;/ / 4.47213595499958
Copy the code

Here we can see that after frame 4.47213595499958 our bullet will reach the end of the hypotenuse.

In other words, we just need to subtract the absolute difference between x and Y of the monster and item to get the x and Y movement distance of the bullet in each frame.

(In this case, we need to take inverse, otherwise the bullet will only move in the opposite direction)

let x = -((x1 - x2) / hy),
    y = -((y1 - y2) / hy);
Copy the code

Finally, the whole algorithm is as follows.

const speed = 5;

function get_move_speed(m, t) {
    let m_x = m.x + m.speed.x,
        m_y = m.y + m.speed.y,
        abs_x = Math.abs(t.x - m_x),
        abs_y = Math.abs(t.y - m_y),
        hy = Math.sqrt(Math.pow(abs_x, 2) + Math.pow(abs_y, 2)) / speed,
        x = -((t.x - m_x) / hy),
        y = -((t.y - m_y) / hy);
        
        // Note that the coordinates of the M object and the T object are the center points of the monster and item
        
   return {x,y}
}
Copy the code

PS: In the end, it’s a bit of a prediction, because monsters move, and if you don’t, it’s easy for the monster to leave after the bullet moves to its original position. To avoid being seen as clickbait, this method should only be called every few frames if you want the bullet to follow the monster.

Finally, if you think this article is helpful to you, please click a “like” to support it!

(Next issue or next issue update how to implement this tower defense game ~).