1

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

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

我没有注意到任何真正的问题,但我无法想象这是在 Flash 游戏中处理子弹的最佳方式。我想一旦屏幕上有多个敌方玩家并且有大量子弹飞来飞去(尤其是当我在自动武器中编码时),事情可能会停止。

我在这里想念什么?我并不是真正的游戏开发者,所以我所做的大部分事情都是当场“编造”出来的,但我无法弄清楚如何在 Flash 中有效地处理子弹。

编辑:根据要求,这是“我的”布雷森汉姆代码。我用引号说“我的”,因为我基本上是从互联网上的某个地方撕下来的。我对算法的更改基本上涉及底部的行。最初的实现会找到从玩家角色到目标的路径,除了每隔一段时间(我浪费了一点时间试图弄清楚但从未到达任何地方)它会生成从目标到目标的路径播放器。为了“修复”这个问题,我最终只检查了路径数组中的第一个 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

4 回答 4

1

您可以在这里发布您的(布雷森汉姆的)代码实现吗?如果我的实现速度更快,我想进行基准测试:D ...

奇怪的事情——我确实做了一个基准测试,将我的实现与 AS3.0 的原生Graphics.drawLine()进行了比较……它的速度快了 5 到 10 倍。它甚至是抗锯齿的,但我想耶稣诞生在这里做的事情。

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

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

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

于 2010-11-08T18:39:25.447 回答
1

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

不断增加每帧发射的对象数量,直到您看到每秒不可接受的帧数。

您还应该查看 GameDev.Stackexchange.com,因为那里有很多人更有资格回答 Game Dev 问题。

于 2010-11-08T22:33:53.093 回答
0

不管你做什么,舞台上太多的演员都会降低表演。我个人会尝试将符号实例创建为movieClips,并沿路径移动它们,当它们与目标接触时将其删除。(这样做还可以进行碰撞检测,如果目标可以移开,这将很重要。如果检测到碰撞,子弹可以播放其“爆炸”场景等)

于 2010-11-08T17:13:57.703 回答
0

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

于 2010-11-08T20:13:40.510 回答