2d game : fire at a moving target by predicting intersection of projectile and unit

后端 未结 11 794
庸人自扰
庸人自扰 2020-11-28 22:26

Okay, this all takes place in a nice and simple 2D world... :)

Suppose I have a static object A at position Apos, and a linearly moving object B at Bpos with bVeloci

11条回答
  •  忘掉有多难
    2020-11-28 22:54

    Jeffrey Hantin has a nice solution for this problem, though his derivation is overly complicated. Here's a cleaner way of deriving it with some of the resultant code at the bottom.

    I'll be using x.y to represent vector dot product, and if a vector quantity is squared, it means I am dotting it with itself.

    origpos = initial position of shooter
    origvel = initial velocity of shooter
    
    targpos = initial position of target
    targvel = initial velocity of target
    
    projvel = velocity of the projectile relative to the origin (cause ur shooting from there)
    speed   = the magnitude of projvel
    t       = time
    

    We know that the position of the projectile and target with respect to t time can be described with some equations.

    curprojpos(t) = origpos + t*origvel + t*projvel
    curtargpos(t) = targpos + t*targvel
    

    We want these to be equal to each other at some point (the point of intersection), so let's set them equal to each other and solve for the free variable, projvel.

    origpos + t*origvel + t*projvel = targpos + t*targvel
        turns into ->
    projvel = (targpos - origpos)/t + targvel - origvel
    

    Let's forget about the notion of origin and target position/velocity. Instead, let's work in relative terms since motion of one thing is relative to another. In this case, what we now have is relpos = targetpos - originpos and relvel = targetvel - originvel

    projvel = relpos/t + relvel
    

    We don't know what projvel is, but we do know that we want projvel.projvel to be equal to speed^2, so we'll square both sides and we get

    projvel^2 = (relpos/t + relvel)^2
        expands into ->
    speed^2 = relvel.relvel + 2*relpos.relvel/t + relpos.relpos/t^2
    

    We can now see that the only free variable is time, t, and then we'll use t to solve for projvel. We'll solve for t with the quadratic formula. First separate it out into a, b and c, then solve for the roots.

    Before solving, though, remember that we want the best solution where t is smallest, but we need to make sure that t is not negative (you can't hit something in the past)

    a  = relvel.relvel - speed^2
    b  = 2*relpos.relvel
    c  = relpos.relpos
    
    h  = -b/(2*a)
    k2  = h*h - c/a
    
    if k2 < 0, then there are no roots and there is no solution
    if k2 = 0, then there is one root at h
        if 0 < h then t = h
        else, no solution
    if k2 > 0, then there are two roots at h - k and h + k, we also know r0 is less than r1.
        k  = sqrt(k2)
        r0 = h - k
        r1 = h + k
        we have the roots, we must now solve for the smallest positive one
        if 0

    Now, if we have a t value, we can plug t back into the original equation and solve for the projvel

     projvel = relpos/t + relvel
    

    Now, to the shoot the projectile, the resultant global position and velocity for the projectile is

    globalpos = origpos
    globalvel = origvel + projvel
    

    And you're done!

    My implementation of my solution in Lua, where vec*vec represents vector dot product:

    local function lineartrajectory(origpos,origvel,speed,targpos,targvel)
        local relpos=targpos-origpos
        local relvel=targvel-origvel
        local a=relvel*relvel-speed*speed
        local b=2*relpos*relvel
        local c=relpos*relpos
        if a*a<1e-32 then--code translation for a==0
            if b*b<1e-32 then
                return false,"no solution"
            else
                local h=-c/b
                if 0

提交回复
热议问题