Need nice way to create parabolic trajectory

Started by
10 comments, last by meteors 16 years, 9 months ago
Hi all, I have made basic parabolic paths (by subtracting from a pre-set Y-amount), but I am looking for something more elaborate. I'm using this to create a trajectory for a mortar/projectile. I would really like a function which takes three parameters: the launching position(Vector), the landing position(Vector), and the angle of arc (float). Anyone have a function like this sitting on their hard drive? I also wouldn't mind finding a Class which does this and offers more features; this is something I do fairly often and would love more flexibility. I am happy to answer any questions if it helps to convey what I'm looking for. Thanks in advance!! Regards, -joshua joshua >>at<< spaceweather.com
Advertisement
You could take a look at my two responses here for a couple of trajectory equations and functions, you could also do it iteratively (as you seem to be currently) as was also suggested there.

Unfortunately neither method I presented uses the angle of the arc, although im sure you could use the angle to calculate an initial speed/direction vector, but you did say you were interested in alternatives [smile]

Good luck
Hey DMatter,

That's a helpful thread, but of course it's not exactly what I'm looking for. I really want a function with this signature:

Vector3 calculateTrajectory(Vector3 orgin, Vector3 destination, double arc);


Any ideas :-)



Thanks!!!!! Best,
-joshua
R = horizontal difference of points
H = altitude difference to target
A = arc angle from ground
G = gravity constant
S = initial speed of the projectile

t = R / cos(A)

solve for S:
H = G * t * t / 2 + sin(A) * S * t

S = (H - G * t * t / 2) / (sin(A) * t)


Now that you have S, just make a new vector in the direction of the target, at the arc angle with magnitude of S.

I just did this now, there may be errors. But this should get you started.
Quote:Original post by meteors
Hey DMatter,

That's a helpful thread, but of course it's not exactly what I'm looking for. I really want a function with this signature:

Vector3 calculateTrajectory(Vector3 orgin, Vector3 destination, double arc);

I'm afraid that's not well-defined. If 'arc' defines the angle at the origin, then the (function) parameter set will uniquely define a parabola. To determine a point on the trajectory you'd also need to pass an input (mathematical) parameter, most likely time-from-launch or current-angle-from-some-give-point.

But yes, the best way to proceed would be to solve the quadratic equations of motion to describe the parabola as an appropriate polynomial, then evaluate it using the passed parameter.

Think carefully about exactly what inputs will be available and what form you want the output to be in, then report back.

Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Hi Admiral,

Argh...math...

Do you not know of any library which makes this sort of thing easy?



Cheers!
-joshua
Quote:Original post by meteors
Do you not know of any library which makes this sort of thing easy?

The mathematics isn't too tricky. I'm sure there are a few of us who'd be happy to walk you through the calculation and corresponding code. But first we need to know exactly what you're trying to achieve, 'cause it's not clear at the moment.

Take a step back and describe your goal (rather than your method) and we'll see how we can help.

Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Here's a way to do that's alot simpler since I cheated a bit with the equations:
""" turretGrav.py     Side view of turrent gun    Jaime Moreno    4/13/07    """    import pygame, mathpygame.init()class Label(pygame.sprite.Sprite):    """ Label Class (simplest version)         Properties:            font: any pygame font object            text: text to display            center: desired position of label center (x, y)    """    def __init__(self):        pygame.sprite.Sprite.__init__(self)        self.font = pygame.font.SysFont("None", 30)        self.text = ""        self.center = (320, 240)                    def update(self):        self.image = self.font.render(self.text, 1, (0, 0, 0))        self.rect = self.image.get_rect()        self.rect.center = self.centerclass Turret(pygame.sprite.Sprite):    def __init__(self, shell):        self.shell = shell        pygame.sprite.Sprite.__init__(self)        self.imageMaster = pygame.image.load("turret.gif")        self.imageMaster = self.imageMaster.convert()        self.imageMaster = pygame.transform.scale2x(self.imageMaster)        self.rect = self.imageMaster.get_rect()        self.rect.center = (100, 300)        self.turnRate = 10        self.dir = 0        self.charge = 5            def update(self):        self.checkKeys()        self.rotate()        def checkKeys(self):        keys = pygame.key.get_pressed()        if keys[pygame.K_LEFT]:            self.dir += self.turnRate            if self.dir > 360:                self.dir = self.turnRate        if keys[pygame.K_RIGHT]:            self.dir -= self.turnRate            if self.dir < 0:                self.dir = 360 - self.turnRate        if keys[pygame.K_UP]:            self.charge += 1            if self.charge > 20:                self.charge = 20        if keys[pygame.K_DOWN]:            self.charge -= 1            if self.charge < 0:                self.charge = 0                    if keys[pygame.K_SPACE]:            self.shell.x = self.rect.centerx            self.shell.y = self.rect.centery            self.shell.speed = self.charge            self.shell.dir = self.dir            self.shell.calcVector()        def rotate(self):        oldCenter = self.rect.center        self.image = pygame.transform.rotate(self.imageMaster, self.dir)        self.rect = self.image.get_rect()        self.rect.center = oldCenterclass Shell(pygame.sprite.Sprite):    def __init__(self, screen, background): # add background to draw path        pygame.sprite.Sprite.__init__(self)        self.screen = screen        self.background = background                self.image = pygame.Surface((10, 10))        self.image.fill((0xff, 0xff, 0xff))        self.image.set_colorkey((0xff, 0xff, 0xff))        pygame.draw.circle(self.image, (0, 0, 0), (5, 5), 5)        self.image = pygame.transform.scale(self.image, (5, 5))        self.rect = self.image.get_rect()        self.rect.center = (-100, -100)        self.gravity = .5 # modify gravity as needed        self.speed = 0        self.dir =0        self.dx = 0        self.dy = 0        self.reset()            def update(self):        # self.calcVector()        # since we commented out calcVector() need to add self.dx,dy above!        self.calcPos()        self.checkBounds()        self.rect.center = (self.x, self.y)       def calcVector(self):        radians = self.dir * math.pi / 180                self.dx = self.speed * math.cos(radians)        self.dy = self.speed * math.sin(radians)        self.dy *= -1        # clear the background each time we fire so old paths don't show up        #self.background.fill((0x00,0xcc,0x00))        def calcPos(self):        # compensate for gravity                       self.dy += self.gravity        # draw shell path        # get old position for drawing        oldx = self.x        oldy = self.y        self.x += self.dx        self.y += self.dy        pygame.draw.line(self.background, (0,0,0), (oldx, oldy),(self.x,self.y))                def checkBounds(self):        screen = self.screen        if self.x > screen.get_width():            self.reset()        if self.x < 0:            self.reset()        if self.y > screen.get_height():            self.reset()        if self.y < 0:            self.reset()        def reset(self):        """ move off stage and stop"""        self.x = -100        self.y = -100        self.speed = 0def main():    screen = pygame.display.set_mode((640, 480))    pygame.display.set_caption ("Firing a Shell")        background = pygame.Surface(screen.get_size())    background.fill((0x00, 0xCC, 0x00))    screen.blit(background, (0, 0))        shell = Shell(screen, background)    turret = Turret(shell)    lblOutput = Label()    lblOutput.center = (100, 20)        allSprites = pygame.sprite.Group(shell, turret, lblOutput)        clock = pygame.time.Clock()    keepGoing = True    while keepGoing:        clock.tick(30)        for event in pygame.event.get():            if event.type == pygame.QUIT:                keepGoing = False                #update label        lblOutput.text = "dir: %d  speed %d" % (turret.dir, turret.charge)        # blit background for drawings        screen.blit(background, (0,0))                #allSprites.clear(screen, background)        allSprites.update()        allSprites.draw(screen)        pygame.display.flip()if __name__ == "__main__":    main()

[size="2"]Don't talk about writing games, don't write design docs, don't spend your time on web boards. Sit in your house write 20 games when you complete them you will either want to do it the rest of your life or not * Andre Lamothe
TheAdmiral,

Later today (when I have free time), I will explain in detail what I want to do. I really appreciate your offer to help :-)


Best,
-joshua
Alright. Consider the following. You have a generic parabola which would be expressed as

y(x) = Ax^2 + Bx + C

You also have two points, and initial point (x0, y0) and a final point (x1, y1). This gives us two equations:

y0 = A(x0)^2+B(x0)+C
y1 = A(x1)^2+B(x1)+C

But with 3 unknowns (A,B,C) we don't have a solution yet. But we also have an initial angle theta. This corresponds to a slope of tan(theta). We can evaluate the slope of the parabola by taking a derivative so:

y'(x) = 2A*x+B

y' is our slope which we know at the initial point x=x0 so a third equation is

tan(theta) = 2*A*(x0)+B

This gives three equations:

tan(theta) = 2*A*(x0)+B
y0 = A(x0)^2+B(x0)+C
y1 = A(x1)^2+B(x1)+C

Which can be solved in the usual ways for A, B, and C.

At this point we have the equation we need for the parabola based off the initial point, final point and initial slope.

This topic is closed to new replies.

Advertisement