1
\$\begingroup\$

I am doing a clone of the classic arcade game missile command, i am curious about how to implement the trajectories of the missiles. I have a solution that looks pretty similar to the original game, but it have some problems that i don't know how to avoid.

Here is the relevant code i have right know:

missiles_attack = []

class Missile(object):

    def __init__(self, pos_src, pos_dst, color, speed):

        # direction of the missile
        direction = (pos_dst - pos_src).normalize()

        # total distance that missile must travel to reach his target
        self.__distance = pos_dst.distance_to(pos_src)

        # the current distance traveled
        self.__distance_traveled = 0

        # how many the head should move each frame
        self.__step = speed * direction

        # the length of a step
        self.__step_length = self.__step.length()

        self.pos_head = Vector2(pos_src)
        self.points = [(self.pos_head.x, self.pos_head.y)]

        self.color = color

    def update(self):
        self.__distance_traveled += self.__step_length
        if self.__distance_traveled < self.__distance:
            self.pos_head += self.__step
            self.points.append((self.pos_head.x, self.pos_head.y))
        else:
            self.destroy()

    def destroy(self):
        missiles_attack.remove(self)

def draw_missiles():
    for missile in missiles_attack:
        pygame.draw.lines(screen, missile.color, False, missile.points, 2)

def update_missiles():
    for missile in missiles_attack:
        missile.update()

So when i want to create a missile, i pass the src and dst position of the missile and then add it to the list of attack missiles, both the draw_missiles and update_missiles functions are called for each frame inside the game loop.

The idea behind the trajectory is to work out a new point in the line defined by the src and dst position each frame, i have three problems with this approach:

problem 1

I don't know how to draw the missile heads, in the video you can see that the heads are like a white pixel, i tried to take the last two points of the missile.points list and draw a new line with those points to represent the head, the problem is that the line length changes when the speed of the missile changes so it not works.

problem 2

Seems silly to store all the points of the trajectory in a list, seems like is too much waste of memory, i can't think in another more efficient solution with the same 'graphical results'.

problem 3

Another thing i tried is instead of use the pygame.draw.lines function use the pygame.draw.line one, the draw_missiles function will be something like this:

def draw_missiles():
    for missile in missiles_attack:
        pygame.draw.line(
          screen, 
          missile.color,
          (missile.pos_src.x, missile.pos_src.y),
          (missile.pos_head.x, missile.pos_head.y),
          2 
        )

Well, now i don't have to store all the points, which is a good thing i think, the problem is that when the line is draw, the results are different than the 'points approach', seems like the line algorithm that pygame uses under the hood not draws the same pixels for a line going from the point A to the point B, that for a line going from the point A to the point C, where C is a point in the line between A and B.

So how i can deal with this problems, what is the most reasonable approach to implement this kind of behavior?

\$\endgroup\$
1
\$\begingroup\$

So a few things here. Whats most evident to me is that you seem to be looking at the problem in terms of lines. I know missile command has a lot of these and pygame offers ways to draw them in a few ways but if you can abstract the moving point ( missile ) from how it is visualised ( lines ) then it may be easier.

And so taking the above into account and your problem 3. Calculate a start position and direction for a missile, and then give it a lifespan. So given it can travel at a certain speed you can figure out a kind of 'explode timer' So it will go in a direction for so long and then explode. Every gameloop you update this and calculate a new missile position. So there are no lines here. Just a new position every game frame. so the missile is a simple object. Direction, speed and lifespan. Fire and forget :)

And so now you come to visualising the position. With missile command I seem to remember a line is drawn from current missile position to the base it was fired from. And so you can just do that every game loop. Draw a line from missile current pos to the base. This is the render part ( or visualisation ). Its separate from the update

Visualising the head is the same ( problem 1 ) . Take the current position of the missile and just draw a square. Forget how far it has traveled, the head will always be the same size no matter how fast it moves.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Have you tried using the speed as an offset for the position of the missile head? Consider this image, which uses Pythagoras Theorem:

enter image description here

enter image description here

Esentially, you would track the delta(distance moved) and use that to find your hypotenuse(speed). You can then use the speed as an offset for the missle head.

Here is an example of the formula:

        /// <summary>
        /// https://en.wikipedia.org/wiki/Pythagorean_theorem
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static float Pythagorean(float a, float b)
        {
            return (float)Math.Sqrt((a * a) + (b * b));
        }
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.