Математика / Расчеты для бесконечного / повторяющегося мира с вращением - PullRequest
9 голосов
/ 11 ноября 2011

Как мне создать бесконечный / повторяющийся мир, который управляет вращением, как в этой игре:

http://bloodfromastone.co.uk/retaliation.html

Я закодировал свой вращающийся движущийся мир, имея такую ​​иерархию, как эта:

Сцена
- mainLayer (CCLayer)
- вращениеLayer (CCNode)
- positionLayer (CCNode)

ВращенияLayer и positionLayer имеют одинаковый размер (4000x4000 px прямо сейчас).

Я вращаю весь мир, вращая вращение слоя, и перемещаю весь мир, перемещая положение слоя, так что игрок всегда остается в центре экрана устройства, и это мир, которыйдвигается и вращается.

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

Теперь я не думаю, что мне нужна какая-либо помощь, связанная с cocos2d-iphone здесь.Мне нужен какой-то способ вычислить, находится ли мой игрок за пределами мира, а затем какой-то способ вычислить, какую новую позицию я должен дать миру, чтобы обернуть мир.

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

Видимый прямоугольник внутри круга окружностей внутри повернутого квадратного мира:
Visible rectangle well inside bounds circle inside a rotated square world

Верх видимого прямоугольника, ударяющего границы круга внутри повернутого квадратаworld:
enter image description here

Повернутый квадратный мир перемещен в противоположную вертикальную позицию, так что нижняя часть видимого прямоугольника теперь пересекает границы круга внутри повернутого мира:
enter image description here

Другой примерверхней части видимого прямоугольника, попадающего в круг границ внутри повернутого квадратного мира, чтобы проиллюстрировать другой сценарий:
enter image description here

И снова повернутый квадратный мир переместился в противоположную вертикальную позицию, так что дно видимого прямоугольника теперь пересекает границыкруг внутри вращающегося мира:
And again rotated square world moved to opposite vertical position so that bottom of visible rectangle now hitting bounds circle inside rotated world

Перемещение позиции Layer в не повернутой ситуации - это математика, которую я понял, поскольку я сказал, что могу понять это, пока мир делаетне получается вращаться, но это так.World / CCNode (positionLayer), который перемещается / позиционируется, находится внутри world / CCNode (revolutionLayer), который вращается.Якорная точка для вращающегося слоя, который вращается, всегда находится в центре экрана, но когда перемещаемый элемент PositionLayer находится внутри вращающегося слоя, он вращается вокруг точки привязки вращающего слоя.И тогда я теряюсь ... Когда я, например, перемещаю positionLayer достаточно вниз, чтобы его верхняя граница достигла верхней части экрана, мне нужно обернуть этот positionLayer, как описывает JohnPS, но не так просто, мне нужно обернуть его в векторном видена вращение слоя вращения CCNode.Это я не знаю, как сделать.

Спасибо
Søren

Ответы [ 3 ]

7 голосов
/ 19 ноября 2011

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

Circles on a torus.

Если вы последуете за этими кругами, то окажетесь там, где начали,Также обратите внимание, что независимо от того, как вы двигаетесь по поверхности, вы никак не достигнете «края».На поверхности тора такого нет, поэтому его полезно использовать в качестве бесконечного 2D-мира.Другая причина, по которой это полезно, состоит в том, что уравнения довольно просты.Вы указываете, где на торе вы находитесь под двумя углами: угол, который вы путешествуете от «начала» на фиолетовом круге, чтобы найти красный круг, и угол, который вы путешествуете на красном круге, чтобы найти интересующую вас точку. Оба этиУглы намотки на 360 градусов.Давайте назовем два угла theta и phi.Это координаты вашего корабля в мире, и то, что вы изменяете, когда меняете скорости и т. Д. Вы в основном используете их как свои x и y, за исключением того, что вы всегда должны использовать модуль при изменении их (ваш мир будет только на 360 градусов в каждом направлении, тогда он будет вращаться вокруг).

Предположим теперь, что ваш корабль находится в координатах (theta_ship,phi_ship) и имеет ориентацию gamma_ship.Вы хотите нарисовать квадратное окно с кораблем в его центре и длиной / шириной, равным некоторому проценту n всего мира (скажем, вы хотите видеть только четверть мира за один раз, тогда вы должны установить n = sqrt(1/4) = 1/2и длина и ширина окна должны быть установлены на n*2*pi = pi).Для этого вам нужна функция, которая берет точку, представленную в экранных координатах (x и y), и выплевывает точку в мировых координатах (theta и phi).Например, если вы спросили его, какой части мира соответствует (0,0), он должен вернуть координаты корабля (theta_ship,phi_ship).Если ориентация корабля равна нулю (x и y будут выровнены с theta и phi), тогда некоторая координата (x_0,y_0) будет соответствовать (theta_ship+k*x_0, phi_ship+k*y_0), где k - некоторый коэффициент масштабирования, связанныйсколько мира можно увидеть на экране и границы на x и y.Поворот на gamma_ship вводит немного триггера, подробно описанного в функции ниже.Смотрите рисунок для точного определения количества.! Синий - система координат экрана, красный - мировая система координат и переменные конфигурации (вещи, которые описывают, где в мире находится корабль).Объект, представленный в мировых координатах, зеленый.

Функция преобразования координат может выглядеть примерно так:

# takes a screen coordinate and returns a world coordinate
function screen2world(x,y)
    # this is the angle between the (x,y) vector and the center of the screen           
    alpha = atan2(x,y); 
    radius = sqrt(x^2 + y^2); # and the distance to the center of the screen

    # this takes into account the rotation of the ship with respect to the torus coords
    beta = alpha - pi/2 + gamma_ship;

    # find the coordinates
    theta = theta_ship + n*radius*cos(beta)/(2*pi);
    phi = phi_ship + n*radius*sin(beta)/(2*pi));

    # return the answer, making sure it is between 0 and 2pi
    return (theta%(2*pi),phi%(2*pi))

и это, в общем-то, я думаю.Математика - это просто относительно простая задача, вы должны сделать небольшой рисунок, чтобы убедить себя, что это правильно.В качестве альтернативы вы можете получить тот же ответ в несколько более автоматизированной форме, используя матрицы вращений и их старшего брата, преобразования твердого тела (специальная евклидова группа SE (2)).Для последнего я предлагаю прочитать первые несколько глав Murray, Li, Sastry , которая бесплатна онлайн.

Если вы хотите сделать обратное (перейти от мировых координат к экранным координатам), вам придется сделать более или менее то же самое, но в обратном порядке:

beta = atan2(phi-phi_ship, theta-theta_ship);
radius = 2*pi*(theta-theta_ship)/(n*cos(beta));
alpha = beta + pi/2 - gamma_ship;
x = radius*cos(alpha);
y = radius*sin(alpha);
2 голосов
/ 11 ноября 2011

Вы должны определить, что вы хотите, чтобы "противоположные границы" означали. Для двухмерных примеров см. Фундаментальный многоугольник . Есть 4 способа, которыми вы можете отобразить стороны квадрата на другие стороны, и вы получите сферу, реальную проективную плоскость, бутылку Клейна или тор. Классическая аркадная игра Астероиды на самом деле имеет игровую поверхность тора.

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

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

Edit:

Скажем, у вас есть двумерная карта и вы хотите обернуть ее, как в Астероидах.

Если на карте 1000x1000 единиц, x=0 - это левая граница карты, x=999 - правая граница, и вы смотрите вправо и видите 20 единиц впереди. Затем на x=995 вы хотите увидеть до 1015, но это не на правой стороне карты, поэтому 1015 должно стать 15.

Если вы находитесь на x=5 и смотрите влево 20 единиц, то вы видите x=-15, которым вы действительно хотите быть 985.

Чтобы получить эти числа (всегда от 0 до 999), когда вы смотрите за границу карты, вам нужно использовать оператор по модулю .

new_x = x % 1000; // in many programming languages

Когда x отрицательно, каждый язык программирования обрабатывает результат x % 1000 по-своему. Это даже можно определить реализацией. то есть он не всегда будет положительным (между 0 и 999), поэтому использовать его будет безопаснее:

new_x = (x + 1000) % 1000; // result 0 to 999, when x >= -1000

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

0 голосов
/ 18 ноября 2011

Я новичок в Cocos2d, но я думаю, что могу попробовать помочь вам с проблемой вычисления геометрии, поскольку, как вы сказали, это не базовый вопрос.

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

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

Если вы просто хотите проверить, находится ли он внутри круга, просто проверьте, все ли четыре ребра находятся внутри круга.

В случае, если вы хотите узнать, какой край касается окружностикруг, просто проверьте тот, который находится дальше всего от точки x = 0 y = 0, так как якорь будет в центре.

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

...