AS3 Остановить движение персонажа через стены - PullRequest
2 голосов
/ 09 октября 2011

Я хочу остановить движение мувиклипов, когда оно падает на стену (еще один мувиклип). Пример ниже работает, но после столкновения мувиклип «блокирует» все движение влево ... Мой вопрос к вам: это хороший способ и почему он не работает хорошо?

Там будет что-то не так в этом коде, но я учусь. А пока пример с клавишей 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 ]

4 голосов
/ 09 октября 2011
if (leftArrow && ! hitting)

char будет двигаться, если hitting - ложь.Когда char.hitTestObject(bounds) равно true, вы устанавливаете hitting в значение true.Вы не устанавливаете hitting снова в false где-либо.Вот почему, когда левая стена поражена, она навсегда прекращает движение влево.Вам нужно выяснить подходящее условие, чтобы снова установить hitting в false.

Добавление ветки else в detectHit должно решить проблему.

function detectHit(e:Event):void {
   if(char.hitTestObject(bounds))
   {
       hitting = true;
   } else { 
       hitting = false;    // add this
   }
}
1 голос
/ 14 марта 2013

Посмотрите на мою подсказку,

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;
    }                                        
 }

Вместо этого я использую шаг назад в противоположном направлении.

1 голос
/ 09 октября 2011

Несмотря на то, что метод Taskinoor должен работать, я бы предложил другой способ сделать ваши хит-тесты.

Поскольку вы, вероятно, создаете игру (персонаж и границы), у вас будет более одной границы. В этом случае я бы настоятельно рекомендовал тестирование растровых изображений. Таким образом, вы можете создать все свои границы в одном мувиклипе и проверить его на попадание.

Я объясню это на примере лабиринта. В этом случае лабиринт представлял собой несколько строк в видеоролике, случайно собранных вместе. Если вы используете HitTestObject и не нажимаете ни на одну из линий, но ваш персонаж находится над мувиклипом, hitTestObject вернет true, даже если вы не ударяете по стене. Используя bitmapHitTesting, вы можете решить эту проблему (BitmapHitTest учитывает прозрачные пиксели, а hitTestObject - нет).

Ниже вы можете найти пример того, как сделать bitmapHitTesting. Создание растровых изображений в этой функции не обязательно, если они не меняют форму. В этом случае я бы предложил разместить код для растровых данных в методе add_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;
}
...