代码之家  ›  专栏  ›  技术社区  ›  Philipp Lenssen

计算子弹击中目标所需速度的二维博弈算法?

  •  9
  • Philipp Lenssen  · 技术社区  · 14 年前

    我使用的是JavaScript,有以下sprite变量(以及其他变量): sprite.x,sprite.y,sprite.width,sprite.height,sprite.speedX(即速度),sprite.speedY。。。所以我有对象originSprite,targetSprite和bulletSprite,都有这些类型的值,我需要设置正确的bulletSprite速度值。

    非常感谢!

    5 回复  |  直到 14 年前
        1
  •  3
  •   gnarf    14 年前

    使用 vectors 可以让数学看起来简单一点。 Sylvester .x / .y

    // this is a "constant"  - representing 10px motion per "time unit"
    var bulletSpeed = 10; 
    // calculate the vector from our center to their center
    var enemyVec = vec_sub(targetSprite.getCenter(), originSprite.getCenter());
    // measure the "distance" the bullet will travel
    var dist = vec_mag(enemyVec);
    // adjust for target position based on the amount of "time units" to travel "dist"
    // and the targets speed vector
    enemyVec = vec_add(enemyVec, vec_mul(targetSprite.getSpeed(), dist/bulletSpeed));
    // calculate trajectory of bullet
    var bulletTrajectory = vec_mul(vec_normal(enemyVec), bulletSpeed);
    // assign values
    bulletSprite.speedX = bulletTrajectory.x;  
    bulletSprite.speedY = bulletTrajectory.y;  
    
    // functions used in the above example:
    
    // getCenter and getSpeed return "vectors"
    sprite.prototype.getCenter = function() { 
      return {
        x: this.x+(this.width/2), 
        y: this.y+(this.height/2) 
      }; 
    };
    
    sprite.prototype.getSpeed = function() { 
      return {
        x: this.speedX, 
        y: this.speedY 
      }; 
    };
    
    function vec_mag(vec) { // get the magnitude of the vector
      return Math.sqrt( vec.x * vec.x + vec.y * vec.y); 
     }
    function vec_sub(a,b) { // subtract two vectors
      return { x: a.x-b.x, y: a.y-b.y };
    }
    function vec_add(a,b) { // add two vectors
      return { x: a.x + b.x, y: a.y + b.y };
    }
    function vec_mul(a,c) { // multiply a vector by a scalar
      return { x: a.x * c, y: a.y * c };
    }
    function vec_div(a,c) { // divide == multiply by 1/c
      return vec_mul(a, 1.0/c);
    }
    function vec_normal(a) { // normalize vector
      return vec_div(a, vec_mag(a)); 
    }
    
        2
  •  6
  •   Christian    14 年前

    将目标精灵视为二维房间中的直线,其中:

    A(time) = (sprite.positionX + sprite.speedX * time, sprite.positionX + sprite.speedX * time)
    

    因为子弹的速度是恒定的,所以你也知道:

    bullet.speedX^2 + bullet.speedY^2 = bullet.definedSpeed^2
    

    B(time) = (bullet.positionX + bullet.speedX * time, bullet.positionX + bullet.speedX * time)
    

    你知道这两条线都在某个地方:

    A(time) = B(time)
    

    然后由你用给定的值来解这些方程,并求出最小值 time .

        3
  •  5
  •   Dave Jensen Steve    14 年前

    一些身体上的洞察力

    1)目标为“点目标”

    位置 [时间=t 1 &燃气轮机;t型 0 目标 [时间=t 1 &燃气轮机;t型 ]--(等式1)

    其中位置由运动(也是矢量)方程给出

    对象 [t]=位置 [t] 0 对象 *(t-t) 0 )

    子弹 0 ]+速度X 子弹 *(t-t) )=X个 [t] 0 目标 0 )

    所以我们的碰撞时间

    (t) 碰撞 -t型 0 )=(x) 目标 [t] 0 子弹 [t] ])/(速度x 目标 )--(等式2)

    因为我们需要t>t型 0 ,这意味着有一个截距就足够了>

    目标 [t] ]-x个 [t] ])=符号(速度x 子弹 -SpeedX公司 目标 )--(式3)

    Which tells us the evident fact that if an object is moving faster than the other, and in the same direction, they will eventually collide.

    从等式2可以看出,对于给定的SpeedX 目标 (在其他答案中已经指出)对于t和SpeedX ,所以我认为你们的规格不全。

    I guess (as stated in a commentary I made in another answer) thinking in a "tower defense" kind of game, that your bullets have a limited range.
    因此,您还需要另一个约束:

    目标 [t] -t型 0 ]-位置 子弹 0

    Which still permits infinite solutions, but bounded by an upper value for the Collision time, given by the fact that the target may abandon the range.
    此外,距离由

    距离[v,u]=+Sqrt[(Vx-Ux)^2+(Vx-Vy)^2]

    所以,等式4变成,

    (十) 目标 [t] -t型 ]-X个 子弹 [t] 0 ]) +(Y) 目标 [t] 碰撞 0 ]-是的 0 ]) <子弹射程 2

    [t] ]年 [t] 0

    现在,在等式5中替换目标位置的值:

    (十) ]+速度X *(t-t) 0 )-X个 子弹 [t] 0 +(Y) [t] ]+快速 目标 )-是的 子弹 [t] 0 ]) 2 <子弹射程 --(等式6)

    Dxt0=X 目标 [t] ]-X个 子弹 0 ]

    目标 0 ]-是的 ]

    方程式6变为

    (Dtx0+SpeedX) *(t-t) 0 ) ) +(Dty0+1) 0 )) 2 <子弹射程 2 --(等式7)

    这是一个二次方程,在t-t0中求解。正解会给我们最大的碰撞时间。之后目标将超出射程。

    速度 目标 2 =速度x +迅捷 2

    H=Dtx0*SpeedX +Dty0*快速 目标


    碰撞最大值 =t 2 *速度 目标 -小时 2 ))/速度 2

    So you need to produce the collision BEFORE this time. The sign of the square root should be taken such as the time is greater than t 0

    After you select an appropriate flying time for your bullet from the visual 
    effects point of view, you can calculate the SpeedX and SpeedY for the bullet 
    from  
    

    [t] 0 子弹 [t] ])/(t 碰撞 0

    迅捷 =(Y) 目标 [t] ]-是的 子弹 [t] ])/(t 碰撞 -t型 )+快速 目标

    2)目标和塔是“广泛的对象”

    所以,用(bullettrange+R)代替bullettrange,得到了允许的最大碰撞时间的新方程。

    如果你还想考虑火炮的半径,同样的考虑也适用,给出一个“双扩展范围”

    NewBulletRange=子弹射程+R 目标 塔楼

    无限射程子弹

    在您决定某些特殊项目符号不应具有范围(和检测)限制的情况下,仍然存在屏幕边界约束。但要解决这个问题就有点困难了。如果你需要这种射弹,请留下评论,我会做一些计算。

        4
  •  1
  •   PhiLho    14 年前

    dist = sqrt((xt - xs)^2 + (yt - ys)^2)
    将x和y距离除以上述距离: nx = (xt - xs)/dist; ny = (yt - ys)/dist; (向量归一化)
    将结果乘以一个系数,得到每单位时间的n个像素,即每个方向的速度。它应该在想要的方向上提供一个恒定的速度。

        5
  •  0
  •   MartinStettner    14 年前

    我假设目标会以匀速直线运动。

    speedX speedY

    从项目符号原点和交点之间的距离(以及先前计算的时间)可以计算项目符号的速度。