Оптимизация обнаружения столкновений в Actionscript 3. - PullRequest
2 голосов
/ 25 октября 2011

Я пытаюсь сделать свою первую игру в ActionScript 3. Это простая артиллерийская игра, в которой у вас есть пистолет в левом нижнем углу и летающие по экрану ИИ, которых вы должны сбивать.Теперь, в классической стрелялке, этого можно достичь, либо выпустив пулю из оружия и выполнив хит-тест этой пули с помощью AI мувиклипа, либо просто удалив (или проиграв анимацию смерти) AI мувиклип.Но вот проблема.Я не хочу делать ни один из них.Я хочу показать пистолет с быстрой скорострельностью и, следовательно, без пуль.И я также не хочу, чтобы игрок щелкнул точно по мувиклипу ИИ, чтобы уничтожить их (достаточно лишь пистолета / башни, указывающей в правильном направлении).Итак, вот что я попробовал.

Это изображение должно помочь изобразить все это.

image

  1. Попытка прикрепить 'линию' к башне и проверить на столкновение сAI клип.Это явно не удалось из-за проблемы ограничивающего прямоугольника, когда линия наклонена

  2. Я попытался поместить несколько крошечных мувиклипов в строку и повторить их в цикле и проверить, нет ли столкновения с ИИ.Этот метод частично работал, но он был слишком медленным и не выглядел как «правильный» метод.

  3. Я рисую 2 гипотетические линии.Один между p1 и p2, а другой соединяет p3 и p4 (см. Изображение выше).p3 ---- длина p4 = AI.width и является горизонтальной линией, проходящей прямо через центр AI MovieClip.После щелчка мышью я проверяю любое пересечение между этими двумя линиями.Теперь, если у меня есть несколько ИИ на экране, снова мне нужно пройтись по каждому из них, нарисовать новый p3 ----- p4 и проверить на пересечение с p1 ----- p2.

Я использую метод 3 прямо сейчас, и у меня есть ощущение, что, как только я начну добавлять больше вещей в игру, частота кадров получит удар.Я уверен, что должен быть более простой / оптимизированный способ сделать это (может быть, что-то жестоко простое).Прикрепление некоторого соответствующего кода.

shipGame.as

var baseAI:BaseAI;
var AIList:Array= new Array;
public function shipGame():void{
            trace("still connected!!");
            /*
            irrelevant code..
            */
            stage.addEventListener(Event.ENTER_FRAME, updateGame);
            var a:MovieClip = new MovieClip;
            aiTimer = setInterval(StartAI, 2000);
}
public function StartAI():void {
            baseAI = new BaseAI(this);
            AIList.push(baseAI);
}

public function updateGame(event:Event):void    {
            /*
            code to rotate the turret here..
            */

            for (var i:int = 0; i < AIList.length; i++) 
            {
                if (AIList[i].myx < 100) {
                    AIList[i].basicAI.parent.removeChild(AIList[i].basicAI);
                    AIList.splice(i, 1);
                }
            }

            if (mouseDn) {
                basicTurret.gotoAndPlay(2);// Fire animation
                for (var j:int = 0; j < AIList.length; j++) 
                {
                    if ( intersection(AIList[j])) // intersection(bai:BaseAI) returns boolean. Works fine. 
                    {
                        AIList[j].shot = true;
                    }
                }
            }
}

BaseAI.as

var main:shipGame;
var myy:Number;
var myy:Number;
public function BaseAI(doc:shipGame):void{
            main = doc;
            basicAI = new BasicAI(); // BasicAI is a movieClip in the library
            main.addChild(basicAI);
            basicAI.x = 400;
            basicAI.y = Math.abs(Math.random() * (280)) + 20;
            myy = basicAI.y;
            basicAI.addEventListener(Event.ENTER_FRAME, keepMoving);
}

public function keepMoving(evt:Event):void {
        basicAI.x -= 5;
        myx = basicAI.x;

        if (shot && alive) {
            alive = false;
            basicAI.gotoAndPlay(2);
        }
}

1 Ответ

3 голосов
/ 25 октября 2011

Все ваши текущие методы в основном полагаются на рендер Flash, чтобы узнать, где находятся корабли и маркеры.Но в вашем случае, поскольку у вас относительно простые геометрические отношения между движущимися частями, было бы гораздо быстрее решить проблему аналитически.

Рассмотрим случай, когда корабль сидит точно на линии огня вашего оружия.,В этом случае пистолет, корабль и нижняя часть экрана образуют прямоугольный треугольник.Если мы определим theta как угол между пистолетом и нижней частью экрана, то будет выполняться следующее:

tangent(theta) = ship.y / ship.x

, где x и y измеряются вправо и вверх отпистолет.Теперь вы можете обобщить это и использовать его для тестирования попаданий.Когда пистолет выстрелит, сначала найдите theta.Затем для каждого корабля вы можете легко определить, насколько далеко по вертикали или горизонтали судно от линии огня, выполнив что-то вроде этого:

var theta = /*determine theta based on where the mouse was clicked*/
var tanTheta = tangent(theta);
for each (ship) {
    var gunX = ship.y / tanTheta;
    if ( abs(gunX - ship.x) < ship.width/2 ) {
        // a hit occurred
    }
}

Это просто псевдокод, но, надеюсь, вы поняли идею.Во всяком случае, так я бы это сделал - это будет масштабироваться намного быстрее, чем все, что вы делаете при тестировании реальных попаданий, и для описанного случая это должно работать точно так же.

...