对子弹路径进行编程的最佳方法是什么?

时间:2010-11-08 17:04:02

标签: flash actionscript-3 flashdevelop

我正在玩ActionScript 3并尝试为视频游戏(自上而下的动作/射击游戏)构建一个非常简单的原型,并意识到处理子弹比我原先想象的更具挑战性。

为了在角色和目标之间获得相当不错的子弹“飞行”,我最终使用了高度修改版本的Bresenham's Line Algorithm来确定子弹的飞行路径,然后仅绘制一个在我的应用程序的绘制框架阶段,在“飞行路径”上的适当位置使用微小的flash.geom.Rectangle对象。

我没有注意到任何真正的问题,但我无法想象这是在Flash游戏中处理子弹的最佳方式。我想,一旦屏幕上有多个敌人玩家和许多子弹飞来飞去(特别是一旦我用自动武器编码),事情就会停滞不前。

我在这里缺少什么?我不是一个真正的游戏开发者,所以我正在做的大部分事情我只是在当场“制作”,但我无法弄清楚如何在Flash中有效地处理子弹。

编辑:根据要求,这是“我的”Bresenham代码。我在引号中说“我的”,因为我基本上从互联网上的某个地方撕掉了它。我对算法的更改主要涉及底部的行。原始实现将找到从玩家角色到目标的路径,除了每隔一段时间(我浪费了一点时间试图弄清楚但从未到达任何地方)它将生成从目标到目标的路径播放器。为了“修复”这个问题,我最终只检查路径数组中的第一个X / Y值,如果这些值与我的玩家角色的X / Y值不匹配,则反转数组。

public function bresenham(fromX:int, fromY:int, toX:int, toY:int, value:int):Array
{
    // store the character's location
    var orig_x:int = fromX;
    var orig_y:int = fromY;

    var error:int;
    var bullet_path:Array = new Array;

    var dx:int = toX - fromX;
    var dy:int = toY - fromY;
    var yi:int = 1;
    if ( dx < dy ) {
        // swap end points
        fromX ^= toX; toX ^= fromX; fromX ^= toX;
        fromY ^= toY; toY ^= fromY; fromY ^= toY;
    }

    if ( dx < 0 ) {
        dx = -dx;
        yi = -yi;
    }
    if ( dy < 0 ) {
        dy = -dy;
        yi = -yi;
    }
    if ( dy > dx ) {
        error = -( dy >> 1 );
        for ( ; toY < fromY; toY++ ) {
            bullet_path.push( { 'x' : toX, 'y': toY } );
            error += dx;
            if ( error > 0 ) {
                toX   += yi;
                error -= dy;
            }
        }
    } else {
        error = -(dx >> 1);
        for ( ; fromX < toX; fromX++ ) {
            bullet_path.push( { 'x' : fromX, 'y': fromY } );
            error += dy;
            if ( error > 0 ) {
                fromY += yi;
                error -= dx;
            }
        }
    }
    // reverse the bullet path if it was generated from target to player.
    if ( bullet_path[0].x != orig_x && bullet_path[0].y != orig_y ) {
        return bullet_path.reverse();
    }
    return bullet_path;
}

4 个答案:

答案 0 :(得分:1)

你能在这里发布你的(Bresenham)代码的实现吗?如果我的实施更快,我想做一个基准测试:D ...

奇怪的是 - 我做了一个基准测试,将我的实现与AS3.0的原生 Graphics.drawLine()进行比较...它的速度快了5到10倍。它甚至可以消除锯齿,但我想这里的诞生就是这样。

但无论如何 - 只要子弹......让我们说MISSILES(子弹,火箭,激光......)这里不是任何缓慢移动的东西,大看起来也应该看起来不错(不仅仅是线条),使用当不需要动画时, MovieClip ,甚至更好的精灵。其他地方都使用 Graphics.drawLine()

此外,对于使用线条进行命中测试,并找到绘制线条的点(不是 Sprites ),您将拥有该子弹的范围(如果是无限的,请使用类似< em> Stage.width ,或 Stage.height ,如果它更大),它仍然可以击中。然后你也会有它的角度。如果它沿X轴或Y轴,则很容易得到线的点。对于不同的,使用 Point.polar(范围,角度) [liveDocs],您可以向其中添加该项目符号的原始位置。

点击测试将使用 Point.interpolate() [liveDocs]完成。点1将是原始位置/起点,第二个点是您从 Point.polar()获得的点。最后,最后一个参数必须是从开始的距离(此处不需要 Math.atan2() - 只需将每个帧的子弹速度增加此值)除以起点和终点之间的距离(再一次,没有 Math.atan2() - 只是“范围”。这个 Point.interpolate()会给你一个点,你最终将使用每个可能的目标对于子弹(要么循环遍历所有,要么为了表现,检查X和Y距离是否小于或等于它们的宽度和高度) - target.hitTestPoint(interX,interY,true) { {3}}

答案 1 :(得分:1)

在您尝试找到更快的方法之前,请先查看您的代码是否是瓶颈。

继续增加每帧触发的对象数,直到每秒看到不可接受的帧数为止。

你也应该查看GameDev.Stackexchange.com,因为很多人都有资格回答Game Dev问题。

答案 2 :(得分:0)

无论你做什么,舞台上的演员太多都会降低演奏效果。我个人会尝试将符号实例创建为movieClip并沿路径移动它们,当它们与目标接触时删除它们。 (这样做也可以让你进行碰撞检测,如果目标可以移开,这将是非常重要的。如果检测到碰撞,子弹可以发挥其“爆炸”场景等。)

答案 3 :(得分:0)

确定子弹应在每个框架中移动一次的距离并让它离开。如果每个项目符号知道它应该在每帧的x和y属性上移动多远,则不需要再次计算它,子弹将直接飞行。如果你每次子弹移动时都使用Bresenham的线算法,那么你正在做很多工作。只要确保x和y中的移动存储为数字,否则子弹不会最终到达应有的位置。