Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Определить ближайший объект (http://www.flasher.ru/forum/showthread.php?t=160518)

Scorp2008 13.07.2011 17:46

Определить ближайший объект
 
В игре реализовал проверку на столкновение между пулей и врагами ПОСРЕДСТВОМ ПЕРЕСЕЧЕНИИ ЛИНИИ И КВАДРАТА (т.е. это не ХитТест, это отдельная функция), всё работает, но проблема в том что первоначальное опужие не должно постреливать сразу 2 врагов, а получается что простреливает. Алгоритм такой что все враги которые попали под линию выстрела - получают ранение, а хотелось бы чтобы только ближайший к герою враг. Единственное что в голову мне приходит так это до того как делать ранение - определять всех врагов которые попали под линию, далее сравнивать их координаты с координатами героя и который ближе всего - получает ранение. Но может есть путь поудобнее и попроще? Спасибо.

NikolyA 13.07.2011 17:49

http://xitri.com/2009/03/19/crimsonl...ionscript.html

Scorp2008 13.07.2011 17:58

Вы вообще читаете что написано в теме? Блог хитри я весь перечитал еще когда на АС 2 писал, и статься совершенно не в тему. Вопрос мой возникает из того что у меня столкновение определяются пересечением линии и квадрата, а в статье Хитри вообще HitTest делается и такого вопроса в принципе не может там возникнуть.

DaFive 13.07.2011 17:59

А зачем проверять всех на линии? Сделать проверку до первого определения столкновения. Наверняка циклом бегаете.
Код AS3:

if(!враг_задет)
{
враг_задет = true;
экшн
}


Scorp2008 13.07.2011 18:01

Функция определяет всех на линии, задаем конец и начало линии и она выдает массив точек пересечения. Не пишите чуши пожалуйста если до конца не понимаете о чём я.

DaFive 13.07.2011 18:05

Так и напишите как действует ваш алгоритм, прежде чем вопросы задавать, чтобы другим все ясно было.

Scorp2008 13.07.2011 18:07

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

Добавлено через 1 минуту
Просто поражают люди лишь бы что-нибудь вякнуть даже не вникнув в суть вопроса и не прочитав внимательно.

i.o. 13.07.2011 18:10

ну раз выдает массив, то нужно отсортировать его по расстоянию от стрелка до объекта. А потом взять первый объект и все.

Scorp2008 13.07.2011 18:12

i.o. выдает массив точек пересечения, но не массив объектов которые пересекаются. Хотя массив объектов которые пересекаются отсюда сделать не сложно, вопрос то в том и состоит, как отсортировать их по расстоянию от стрелка до объекта?

DaFive 13.07.2011 18:13

Если кому-то не хватает мозга определить пересечение с первым попавшимся от начала линии квадратом по одинаковым для всех законам геометрии - тут уже никто помочь не сможет.

Scorp2008 13.07.2011 18:18

DaFive - Опять хероту какую-то написал, лишь бы повякать. "с первым попавшимся" - ты точно идиот, квадраты не попадаются по очереди, а определяются все разом (а точнее определяются точки пересечения, а самый первый вопрос как раз и состоял в том чтобы определить ближайшую из них), и раз ты пишешь такую хрень то просто не представляешь себе как действует эта функция по общим законам геометрии и вякаешь не по теме.

Zebestov 13.07.2011 18:32

DaFive, Scorp2008 получают замечание за оскорбления.

Scorp2008 13.07.2011 18:57

Хорошо.
Повторю вопрос для i.o. а то насвинячили тут.
i.o. - выдает массив точек пересечения, но не массив объектов которые пересекаются. Хотя массив объектов которые пересекаются отсюда сделать не сложно, вопрос то в том и состоит, как отсортировать их по расстоянию от стрелка до объекта?

i.o. 13.07.2011 19:09

Создайте пустой массив, в который будете добавлять объекты, которые пересекаются с отрезком. Перебирайте объекты и смотрите пересечение с линией. Если пересечение имеет место быть - добавить в массив объект примерно такого вида
Код AS3:

{ object: null, distance: NaN }

(либо заранее определите спец класс) вместо null и NaN подставите реальные значения.
После того, как все объекты будут перебраны, отсортируйте получившийся массив по полю "distance", использую метод sortOn.
Останется только взять первый элемент, если длина массива получилась больше нуля.

Zebestov 13.07.2011 19:15

Если все точки лежат на одной линии, то можно не вычислять дорогой distance, а оперировать лишь одной из координат на выбор. Иначе говоря, по условиям задачи мы опираемся на факт, что если на проекции на ось X (или Y) точка самая близкая к стрелку, то и на самой линии она тоже самая близкая.

Добавлено через 2 минуты
Ну если вдруг непонятно: кому принадлежит самая близкая точка пересечения, тому и капут.

i.o. 13.07.2011 19:19

не совсем, есть и частные случаи - прямая параллельна ОХ или ОY )
Вместо distance можно вычислять расстояние без извлечения корня.

Zebestov 13.07.2011 19:21

Цитата:

Сообщение от i.o. (Сообщение 1011530)
не совсем, есть и частные случаи - прямая параллельна ОХ или ОY )
Вместо distance можно вычислять расстояние без извлечения корня.

Когда я говорил "на выбор", я не запрещал делать этот выбор динамически (один if все решит). Это всяко быстрее, чем если даже не вычислять корень суммы произведений.

Scorp2008 13.07.2011 23:18

Спасибо вам, вот уже наваял код который заносит все объекты которые пересекаются в отдельным массив, а также определяют дистанцию. Вот (по одной координате не стал делать, т.к. с любоый стороны ведь враг подойти может, и то что по одной координате он ближе всего не значит что он ближе всего вообще):
Код AS3:

for (var k:uint = 0; k < sad.length; k++) {
var sadV:Point = sad[k].localToGlobal(new Point(stage.x, stage.y));
var pow1:Number = (bodyconm.x - sadV.x);
pow1 *= pow1;
var pow2:Number = (bodyconm.y - sadV.y);
pow2 *= pow2;
var distance:Number = Math.sqrt(pow1 + pow2);
trace(distance);
}

Вроде дистанция определяется верно, sad - это уже массив с объектами которые пересеклись. А вот дальше загвоздка, что-то не пойму как быстренько определить наименьшее значение и воздействовать на него этот элемент?
P.S.: localToGlobal делаю потому что враги у меня расположены внутри клипа карты, который я двигаю вместо игрока когда двигаюсь.

Я так понял дальше нужно как говорит i.o. "добавить в массив объект примерно такого вида..." - именно с этим и не ясно совсем, можно пояснить как оно в коде выглядеть будет? А также это самый краткий путь? что-то столько вычислений делается, как бы думаю тормозов не было при большом количество врагов.

GBee 13.07.2011 23:40

может в этом цикле сразу и запоминать объект с самой короткой дистанцией? Чтобы два раза не бегать по массиву

Scorp2008 13.07.2011 23:45

GBee, ну вот я и не знаю как поступить, с математикой у меня туго, всё больше готовое ищу и вставляю, а как в этом же цикле определить наименьшее из них и воздейстсовать на этот элемент?

GBee 14.07.2011 00:20

хм, так у вас сейчас, судя по коду только точки пересечения без самих объектов.

Код AS3:

var nearPoint:Point;
var minDist:Number = Number.MAX_VALUE;
for() //ваш цикл
{
    ...
    var distance:Number = Math.sqrt(pow1 + pow2);
    if(distance<minDist)
    {
        minDist = distance;
        nearPoint = sadV;
    }
}

Добавлено через 6 минут
Ну и стандартные советы для ускорения работы

1) длину массива в переменную
2) точку new Point(stage.x, stage.y) создать вне цикла, да и смущает меня что-то вообще
3) bodyconm.x и y тоже можно в переменные вынести перед циклом.

не совет, просто для справки
4) есть статический метод Point.distance, вроде точки кушает. Не знаю быстрее ли расчетов.

Scorp2008 14.07.2011 02:28

спасибо, утром разбираться буду в вашем коде, опробую :) А про массив, так массив sad - это массив не точек, а именно массив элементов которые пересекаются с линией, а сам массив точек он выше и я не стал тот код сюда копировать.

Добавлено через 1 минуту
А советы для ускорения работы, реально ли созданием точки new Point(stage.x, stage.y) вне цикла что-то ускорить? )) Просто мне кажется это очень незначительная вещь, а оптимизация делается несклько поглобальнее, хотя и такие мелочи постараюсь учесть.

hartman 14.07.2011 11:15

не самый эффективный способ обращения за помощью, с наездами на всех кто пытается вникнуть в задачу. есть предположение, что по законам геометрии (что это!?) линия может пересекать квадрат в одной точке или в двух, как вообще понять из этого массива что где пересекается? может быть берется только одна точка для каждого квадрата?

willis83 14.07.2011 11:30

а можно поинтересоваться, какой вид игры? Если вид сверху, и цели могут приближаться со всех сторон, то посложнее, т.к. расстояние надо искать по геометрическим формулам, а если что-то подобное старой доброй контре, даже учитывая то что враги могут подступать с обеих сторон, то есть смысл просто вычислять модуль разницы по координате х между стрелком и целью

Scorp2008 14.07.2011 12:51

willis83 - да, вид сверху, писал где-то постом выше, что игроки могут подойти с любой стороны, поэтому решение с одной координатой не годится. Сейчас начну делать по коду GBee, посмотрим получится ли. Но уже плохо то что со 100 врагами (создаю одновременно) - игра начинает тормозить, правда тормозит она даже когда просто 100 врагов идут на тебя (т.е. не из-за рассчётов стрельбы), но это я уже отдельную тему создам с вопросом об оптимизации.

alatar 14.07.2011 13:52

Корень вычислять смысла нет, для сравнения подойдет и квадрат дистанции.

Scorp2008 14.07.2011 16:12

Цитата:

Сообщение от alatar (Сообщение 1011659)
Корень вычислять смысла нет, для сравнения подойдет и квадрат дистанции.

Да, оптимизацией нужно заняться, но это попозже. Просто я так в уме не знаю этих функций, если бы вы написали как оно вычисляется хотяб просто чистой функцией геометрии - переделал бы, а так позже, поищу-переделаю.

А так - всем спасибо, то что нужно было по теме - реализовал.


Часовой пояс GMT +4, время: 16:46.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.