Вращающиеся кординаты вокруг оси? (тетрис) - PullRequest
4 голосов
/ 22 сентября 2009

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

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

Любые предложения будут с благодарностью,

Спасибо.

Ответы [ 5 ]

5 голосов
/ 04 января 2010

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

Матрица вращения для вращения против часовой стрелки вокруг начала координат:

[0 -1]
[1  0]

Теперь предположим, что у вас есть список координат [(0, 1), (1, 1), (2, 1), (3, 1)], представляющих I-блок в его начальной позиции:

 0123
0....
1####
2....
3....

Обратите внимание, что я использую не декартову систему координат, а обычные экранные координаты, начиная с верхнего левого угла. Чтобы правильно повернуть блок, сначала нужно учесть изменение оси y. Матрица вращения становится:

[ 0 1]  ->  x_new = y_old
[-1 0]  ->  y_new = -x_old

Затем, чтобы вращаться вокруг точки поворота, перед вращением необходимо сместить координаты, чтобы точка поворота стала исходной точкой (называемой sb ниже), и сдвинуть их назад после вращения (называемой sa ниже). ):

x_new = sa_x + (y_old - sb_x)
y_new = sa_y - (x_old - sb_y)

Обычно у вас было бы sb = sa, но для блоков тетриса точка разворота иногда находится на сетке между двумя ячейками (для I- и O-блоков) и иногда в центре ячейки (для всех других блоков) .

Оказывается,

sa_x = 0
sb_x = 0
sa_y = 1
sb_y = me - 2

, где me - это максимальная протяженность (то есть 2, 3 или 4) блока для поворота, работает для всех блоков. Итак, подведя итог, вы получите:

x_new = y_old
y_new = 1 - (x_old - (me - 2))

Вращение по часовой стрелке аналогично, но если вы кешируете координаты для всех для ориентаций блоков, вам понадобится только одно направление.

Для других систем вращения могут работать другие значения переменных сдвига, но вам, возможно, придется снова сдвигать часть, в зависимости от текущей ориентации блока (сравните Вращение SRS с Вращение DTET I-блока, чтобы понять, что я имею в виду).

5 голосов
/ 22 сентября 2009

Конечно, ищите «аффинное преобразование». Но в вашем случае получается ровно четыре возможных поворота объекта в дискретных углах - нет 70,3 °; вращение, это просто 0, 90 & deg ;, 180 & deg ;, 270 & deg ;. Так почему бы не вычислить заранее?

1 голос
/ 22 сентября 2009

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

Википедия: Матрица вращения

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

0 голосов
/ 14 марта 2017

Я сам столкнулся с этой проблемой и нашел отличную страницу википедии по этому вопросу (в параграфе «Общие вращения»:
https://en.wikipedia.org/wiki/Rotation_matrix#Ambiguities

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

Я надеюсь, что будет полезно лучше понять, как это работает.

Чтобы быстро проверить это, вы можете скопировать / вставить его здесь:
http://www.codeskulptor.org/

triangle = [[0,0],[5,0],[5,2]]
coordinates_a = triangle[0]
coordinates_b = triangle[1]
coordinates_c = triangle[2]

def rotate90ccw(coordinates):
    print "Start coordinates:"
    print coordinates
    old_x = coordinates[0]
    old_y = coordinates[1]
# Here we apply the matrix coming from Wikipedia
# for 90 ccw it looks like:
# 0,-1
# 1,0
# What does this mean?
#
# Basically this is how the calculation of the new_x and new_y is happening:
# new_x = (0)(old_x)+(-1)(old_y)
# new_y = (1)(old_x)+(0)(old_y)
#
# If you check the lonely numbers between parenthesis the Wikipedia matrix's numbers finally start making sense.
# All the rest is standard formula, the same behaviour will apply to other rotations
    new_x = -old_y
    new_y = old_x
    print "End coordinates:"
    print [new_x, new_y]

def rotate180ccw(coordinates):
    print "Start coordinates:"
    print coordinates
    old_x = coordinates[0]
    old_y = coordinates[1] 
    new_x = -old_x
    new_y = -old_y
    print "End coordinates:"
    print [new_x, new_y]

def rotate270ccw(coordinates):
    print "Start coordinates:"
    print coordinates
    old_x = coordinates[0]
    old_y = coordinates[1]  
    new_x = -old_x
    new_y = -old_y
    print "End coordinates:"
    print [new_x, new_y]

print "Let's rotate point A 90 degrees ccw:"
rotate90ccw(coordinates_a)
print "Let's rotate point B 90 degrees ccw:"
rotate90ccw(coordinates_b)
print "Let's rotate point C 90 degrees ccw:"
rotate90ccw(coordinates_c)
print "=== === === === === === === === === "
print "Let's rotate point A 180 degrees ccw:"
rotate180ccw(coordinates_a)
print "Let's rotate point B 180 degrees ccw:"
rotate180ccw(coordinates_b)
print "Let's rotate point C 180 degrees ccw:"
rotate180ccw(coordinates_c)
print "=== === === === === === === === === "
print "Let's rotate point A 270 degrees ccw:"
rotate270ccw(coordinates_a)
print "Let's rotate point B 270 degrees ccw:"
rotate270ccw(coordinates_b)
print "Let's rotate point C 270 degrees ccw:"
rotate270ccw(coordinates_c)
print "=== === === === === === === === === "
0 голосов
/ 05 февраля 2010

Полагаю, вы уже закончили. Я не программист, но я помню, что делал это в универе. У нас просто было 4 разных объекта (с разными поворотами) для каждого куска. Например, форма «L» имеет кусок 1,2,3,4. Если ваша активная фигура в 3 и вы вращаете по часовой стрелке, вы загружаете фигуру 4, снова вращаетесь по часовой стрелке и загружаете фигуру 1.

...