Проверка теста попадания персонажа со всеми объектами сцены в AS3

Хорошо, вот моя проблема, и это займет немного времени, чтобы объяснить.

Для класса разрабатывали аркадную игру в AS3. В университете есть аркадный автомат, а операционная система для него была разработана нашим преподавателем и предлагает комплект разработчика программного обеспечения. В нем нет ничего сумасшедшего, поэтому большая часть этого довольно проста. Я просто хотел указать на это главным образом потому, что вместо события ENTER_FRAME и функции цикла я использую функцию переопределения, называемую update(), которую SDK предлагает для выполнения обновлений в каждом кадре.

Хорошо с этим, вот моя проблема. У меня есть класс документа под названием GameState, и он, по сути, обрабатывает игру в этом состоянии. В этом классе я настраиваю мир и персонажа. Сейчас это всего лишь 2 горы, 2 замка, 3 острова и персонаж.

private function initWorld():void
    {
        trace("World has initiated");
        addChild(hazardArea)
        positionElement(hazardArea, 0, 560);

        addChild(mountainSideRight);
        positionElement(mountainSideRight, 730, 200)

        addChild(mountainSideLeft);
        positionElement(mountainSideLeft, 0, 200);

        addChild(castleOne);
        positionElement(castleOne, 5, 160);

        addChild(castleTwo);
        positionElement(castleTwo, 765, 160);

        addIslands();
    }

Элемент position — это просто функция, которая устанавливает координаты x и y MC, добавленного на сцену. Теперь я также создал переопределение для AddChild, так что каждый раз, когда я добавляю дочерний элемент на сцену, он сохраняет его в массиве, к которому я могу получить доступ позже:

override public function addChild(object:*):void
    {
        super.addChild(object);
        worldObjects.push(object);
    }

Хорошо, и три острова добавляются через addIsland, который выглядит так:

private function addIslands():void
    {
        var island:Array = Islands.getIslandCords();
        for (var x:int = 0; x < DiceNumbers.NUM_ISLS; x++) 
        {
            addChild(island[x].mc);
            positionElement(island[x].mc, island[x].x, island[x].y);

        }
    }

Islands - это просто класс, который находит позицию для моих 3 островов с кучей математики и прочего... на самом деле не имеет значения, что возвращаемый массив - это всего лишь 3 объекта, которые содержат экземпляр moveclip и координаты x и y для этого.

У меня также есть отдельный класс персонажей, который представляет моего дварфа (персонажа в моей игре). В классе нет ничего странного, за исключением того, что у меня есть система гравитации, которая выглядит так:

var gravity:Number = 2;
public var moveX:Number = 300;
public var moveY:Number = 50;
public var xSpeed:Number = 0;
public var ySpeed:Number = 2;
public static const playerSpeed:Number = 3;
public var friction:Number = .75;

а затем функция update(), о которой я упоминал, работает как цикл EVENT_FRAME, имеет в себе это:

public function update():void
{
    xSpeed *= friction;
    moveX += xSpeed;
    moveY += ySpeed
    theDwarf.y += gravity;

    this.x = moveX;
    this.y = moveY;

    updateControls();
}

theDwarf является экземпляром моего видеоклипа о дварфах, а updateControls предоставляет функциональные возможности для перемещения моего дварфа.

Итак, наконец, в моем классе GameState в функции update() я вызываю свой класс коллизий и передаю ему массив со всеми объектами из сцены. В этом классе я проверяю столкновение:

public function checkCollision(listOfObjects:Vector.<MovieClip>):void
    {   

        for (var i:int = 0; i < worldObjects.length; i++) {
            if(worldObjects[i] is Player){

                var objOne:MovieClip = worldObjects[i];             
                for (var j:int = 0; j < worldObjects.length; j++){
                    if (j == i){
                        // elimates self comparisons.
                    }
                    else{
                        var objTwo:MovieClip = worldObjects[j];
                        checkIntersect(objOne, objTwo )
                    }
                }
            }
        }
    }

private function checkIntersect(player:MovieClip, objTwo:MovieClip):void
    {
        if(player.hitTestObject(objTwo)){
            player.ySpeed = -1;
        }
        else{
            player.ySpeed = 2;
        }
    }

И моя проблема заключается в следующем: эта функция проверяет моего игрока на соответствие КАЖДОМУ объекту на сцене. Таким образом, несмотря на то, что мой гном приземляется на 1 остров, он не задевает 2 других острова, и поэтому ySpeed ​​​​сбрасывается до 2. Если я избавлюсь от оператора else, гравитация моего гнома никогда не вернется к 2, и он никогда больше не упадет. Я НЕ МОГУ найти решение для этого... я так старался найти способ обойти это, и я так озадачен... Я хочу, чтобы мой гном упал, если только он не находится на одном из моих островов или на горе. Я надеюсь, что я был достаточно ясен, чтобы объяснить мою проблему, теперь это стало ОГРОМНЫМ постом... :D СПАСИБО!


person Chris Shields    schedule 21.02.2013    source источник
comment
Вы должны разорвать цикл, если вы нажмете на объект, поэтому он не будет выполнять дальнейшую проверку и, возможно, сбрасывать скорость игрока.   -  person Urosan    schedule 21.02.2013


Ответы (1)


Чтобы лучше объяснить мой предыдущий комментарий, вы должны изменить эти последние 2 функции следующим образом:

public function checkCollision(listOfObjects:Vector.<MovieClip>):void
{   

   OuterLoop: for (var i:int = 0; i < worldObjects.length; i++) {
        if(worldObjects[i] is Player){

            var objOne:MovieClip = worldObjects[i];             
            for (var j:int = 0; j < worldObjects.length; j++){
                if (j == i){
                    // elimates self comparisons.
                }
                else{
                    var objTwo:MovieClip = worldObjects[j];
                    player.ySpeed = checkIntersect(objOne, objTwo )
                    if (player.ySpeed == -1)
                        break OuterLoop;
                }
            }
        }
    }
}

private function checkIntersect(player:MovieClip, objTwo:MovieClip):int
{
    if(player.hitTestObject(objTwo)){
        return -1;
    }
    else{
        return 2;
    }
}

Это также можно сделать лучше. но это самое быстрое решение вашей проблемы.

person Urosan    schedule 21.02.2013
comment
Спасибо!! Ваш пример у меня не сработал. Player является частным свойством checkIntersect и не существует в checkCollision, хотя его можно просто изменить на objOne, но даже в этом случае я проверил это, и мой карлик вообще не упал. ОДНАКО! благодаря вашей логике я просто реализовал это по-другому, где checkIntersect возвращает логическое значение, false, если нет попадания или true, если попадание. Затем в checkCollision я создаю логическую переменную с именем hit, а затем назначаю ей возврат checkIntersect и создаю аналогичное условие if, а если TRUE, я просто возвращаю функцию. Кажется, пока работает!! - person Chris Shields; 21.02.2013
comment
Кроме того, мне было бы очень интересно, как это можно сделать лучше, если у вас есть время. - person Chris Shields; 21.02.2013