我正在玩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;
}
答案 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中的移动存储为数字,否则子弹不会最终到达应有的位置。