Learning and Applying Mathematics using Computing

First In Line

In our last post we added a laser to our spaceship that shot asteroids. It was a very powerful laser, because it would shoot absolutely everything in its path, effectively shooting through all the asteroids in one go. Often in a game, you don’t want this: you want to shoot only the first thing that the laser hits. We can implement this by continuing our maths from last post.

Our last post finished with this quadratic equation:

(\text{dirX}^2 + \text{dirY}^2) \times \text{scalar}^2 + ((2\times\text{distX}\times\text{dirX}) + (2\times\text{distY}\times\text{dirY}))\times\text{scalar} + \text{distX}^2 + \text{distY}^2 - \text{radius}^2 = 0

The variable of interest there was \text{scalar}, which is, in effect, a distance along the line. We have a direction vector for the laser (the pink arrow below), and to make up the line for the laser, we effectively lay an infinite amount of these arrows end-to-end, like in the diagram below. The \text{scalar} variable keeps track of how many of these pink arrows we are from the origin of the line (the centre of the spaceship):

So if we actually finish calculating the value for \text{scalar} where each asteroid is hit by the line, then the asteroid that we hit with the lowest associated positive \text{scalar} value is the first one along the line of the laser (in this diagram, 1.7):

Note that we don’t want to allow negative \text{scalar} values, because then we would shoot asteroids that were behind the ship! So, back to our maths equation — we saw last post that a quadratic can be rearranged to:

x = \displaystyle\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}

Where, for us:

x = \text{scalar}
a = \text{dirX}^2 + \text{dirY}^2
b = (2\times\text{distX}\times\text{dirX}) + (2\times\text{distY}\times\text{dirY})
c = \text{distX}^2 + \text{distY}^2 - \text{radius}^2

The quadratic equation gives two solutions: this will be the value of scalar where the line enters the circle, and a second solution for the value of scalar where the line exits the circle (think about it: an infinite straight line can’t enter a circle without leaving it again). We don’t need to worry about which is which, we are just interested in the lowest scalar value that we find, as that will be the nearest one. All this comes out in the code that we need:

        Asteroid nearest = null;
        double nearestScalar = 1000; //huge value
        for (Asteroid asteroid : (List<Asteroid>)getWorld().getObjects(Asteroid.class))
            double distX = getX() - asteroid.getX();
            double distY = getY() - asteroid.getY();
            double a = dirX * dirX + dirY * dirY;
            double b = 2 * distX * dirX + 2 * distY * dirY;
            double c = distX * distX + distY * distY - asteroid.getRadius() * asteroid.getRadius();
            if (b * b - 4 * a * c >= 0)
                double scalarA = (-b + Math.sqrt(b * b - 4 * a * c)) / (2*a);
                double scalarB = (-b - Math.sqrt(b * b - 4 * a * c)) / (2*a);
                if (scalarA >= 0 && scalarA < nearestScalar)
                    nearestScalar = scalarA;
                    nearest = asteroid;
                if (scalarB >= 0 && scalarB < nearestScalar)
                    nearestScalar = scalarB;
                    nearest = asteroid;
        if (nearest != null)
            if (nearest.hit(30))

So there it is — the quadratic formula actually implemented and used in code. You can have a play with the scenario (and download the full source) on the Greenfoot site.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s