#flash #actionscript-3 #collision-detection
#flash #actionscript-3 #обнаружение столкновений
Вопрос:
Я пытаюсь сделать свою первую игру в Actionscript 3. Это простая артиллерийская игра, в которой у вас есть пистолет в нижнем левом углу и ИИ, летающие по экрану, которые вы должны сбивать. Теперь, в классификационном шутере, это достигается либо выстрелом из пистолета и попаданием этой пули с помощью видеоролика AI, либо простым удалением (или воспроизведением анимации смерти) видеоролика AI. Но вот в чем проблема. Я не хочу делать ни то, ни другое. Я хочу показать пистолет с быстрой скорострельностью и, следовательно, без пуль. И я также не хочу, чтобы игрок нажимал точно НА видеоролик AI, чтобы уничтожить их (должно быть достаточно просто пушки / башни, направленной в правильном направлении). направление). Итак, вот что я попробовал.
Это изображение должно помочь представить все это.
-
Попытался прикрепить «линию» к турели и проверить наличие столкновения с помощью AI clip. Очевидно, что это не удалось из-за проблемы с ограничительной рамкой, когда линия наклонена.
-
Я попытался поместить несколько крошечных видеороликов в строку и перебирать их в цикле и проверять наличие каких-либо столкновений с ИИ. Этот метод частично работал, но он был слишком медленным и не казался «правильным» методом.
-
Я рисую 2 гипотетические линии. Один между p1 и p2, а другой соединяет p3 и p4 (см. Изображение выше). p3 —- длина p4 = AI.width и представляет собой горизонтальную линию, проходящую прямо через центр видеоролика AI. При щелчке мыши я проверяю наличие любого пересечения между этими двумя строками. Теперь, если у меня на экране несколько ИИ, мне снова нужно перебрать каждый из них, нарисовать новый 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 amp;amp; alive) {
alive = false;
basicAI.gotoAndPlay(2);
}
}
Ответ №1:
Все ваши текущие методы, по сути, полагаются на средство визуализации 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
}
}
Это всего лишь псевдокод, но, надеюсь, вы поняли идею. В любом случае, именно так я бы это сделал — это будет масштабироваться намного быстрее, чем все, что вы делаете при реальном тестировании, и для описанного случая это должно работать так же хорошо.