AS3阻止角色穿过墙壁

时间:2011-10-09 14:50:03

标签: actionscript-3 flash hittest

我想停止影片剪辑移动到墙壁(另一个影片剪辑)时。 以下示例有效,但在碰撞后,movieclip'阻止'向左移动所有动作...... 我的问题是,这是一个好方法,为什么它不能很好地运作?

这段代码会有问题,但我正在学习。 现在使用leftArrow键的示例;

用于检查钥匙的变量,是否撞击墙壁以及是否正在移动:

var leftArrow:Boolean;
var speed:int = 10;
var hitting:Boolean;
var ismoving:Boolean;

键/移动和检测碰撞的事件侦听器:

stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
stage.addEventListener(Event.ENTER_FRAME, walking);
stage.addEventListener(Event.ENTER_FRAME, detectHit);

检测碰撞功能:

function detectHit(e:Event) :void
{
   if(char.hitTestObject(bounds))
   {
       hitting = true;
   }
}

左箭头键的功能:

function keyPressed(event:KeyboardEvent):void
{

    if (event.keyCode == Keyboard.LEFT)
    {
       leftArrow = true;
    }

}

function keyReleased(event:KeyboardEvent):void 
{

    if (event.keyCode == Keyboard.LEFT) 
    {
        leftArrow = false;
    }

}

它不工作的原因可能在这里,但我不明白为什么不:

function walking(event:Event):void {
    if (rightArrow) {
        char.x += speed;    
    }

    if (leftArrow && ! hitting) {
        char.x -= speed;
    }
    else
    {
        ismoving = false
    }

3 个答案:

答案 0 :(得分:4)

if (leftArrow && ! hitting)
如果char为false,

hitting将移动。当char.hitTestObject(bounds)为真时,您将hitting设置为true。您没有在任何地方再次将hitting设置为false。这就是为什么一旦左墙被击中它就会永久停止左移。您需要找出合适的条件将hitting再次设置为false。

detectHit中添加else分支可以解决问题。

function detectHit(e:Event):void {
   if(char.hitTestObject(bounds))
   {
       hitting = true;
   } else { 
       hitting = false;    // add this
   }
}

答案 1 :(得分:1)

尽管Taskinoor的方法应该有效,但我建议采用另一种方法来进行测试。

由于您可能正在创建游戏(角色和边界),因此您将拥有多个绑定。在这种情况下,我强烈建议使用bitmap-hittesting。这样,您可以在一个动画片段中创建所有边界并测试命中。

我将通过使用迷宫的例子来解释这一点。迷宫将成为一个动画片段中的一些行,随机放在一起。如果您使用的是HitTestObject并且没有击中其中一条线,但是您的角色位于movieclip上,则即使您没有撞墙,hitTestObject也会返回true。通过使用bitmapHitTesting,您可以克服这个问题(BitmapHitTest考虑了透明像素,而hitTestObject没有)。

下面你可以找到一个如何进行bitmapHitTesting的例子。如果不改变形状,则在此函数中创建位图不是必需的。在这种情况下,我建议将bitmapdata的代码放在added_to_stage方法中。

private var _previousX:int;
private var _previousY:int;
private var _bmpd:BitmapData ;
private var _physicalBitmapData:BitmapData;

private function walkAround(e:Event):void
{
    var _xTo:int = //Calculate x-to-position;
    var _yTo:int = //Calculate y-to-position;

    //If your character doesn't change shape, you don't have to recalculate this bitmapData over and over. 
    //I suggest placing it in a ADDED_TO_STAGE-Event in that case.
    _bmpd = new BitmapData(char.width, char.height, true, 0);
    _bmpd.draw(char);   

    //If your bounds are static, you don't have to recalculate this bitmapData over and over. 
    //I suggest placing it in a ADDED_TO_STAGE-Event in that case.
    _physicalBitmapData = new BitmapData(bounds.width, bounds.height, true, 0);
    _bmpd.draw(bounds);

    //The below line is the actual hittest
    if(_physicalBitmapData.hitTest(new Point(0, 0), 255, _bmpd, new Point(char.x, char.y), 255))
    {
        char.x = _previousX;
        char.y = _previousY;
    }
    else
    {           
        char.x = _xTo;
        char.y = _yTo;
    }

    _previousX = char.x;
    _previousY = char.y;
}

答案 2 :(得分:1)

看看我的提示,

function loop(Event)
{    
    if(isHit==false)
    {
       if(isRight==true){head_mc.x+=1}
       if(isLeft==true){head_mc.x-=1}
       if(isUp==true){head_mc.y-=1}
       if(isDown==true){head_mc.y+=1}
    }

    if(head_mc.hitTestObject(build_mc))
    {
        isHit=true;

        if(isRight==true){head_mc.x-=1}
        if(isLeft==true){head_mc.x+=1}
        if(isUp==true){head_mc.y+=1}
        if(isDown==true){head_mc.y-=1}
    }
    else
    {
        isHit=false;
    }                                        
 }

我使用退回到相反的方向。