Диагональное движение спрайтов в Pygame, Python 3

В настоящее время я делаю игру, используя Pygame, Python 3, и одна из ошибок, которые у меня есть, - это то, как движутся выстрелы. Игра представляет собой 2D-шутер с видом сверху, а код для механики стрельбы игрока приведен ниже:

(player_rect - это Rect для игрока, bullet_speed - это предопределенное int)

if pygame.mouse.get_pressed()[0]:
    dx = mouse_pos[0]-player_rect.centerx
    dy = mouse_pos[1]-player_rect.centery
    x_speed = bullet_speed/(math.sqrt(1+((dy**2)/(dx**2))))
    y_speed = bullet_speed/(math.sqrt(1+((dx**2)/(dy**2))))
    if dx < 0:
        x_speed *= -1
    if dy < 0:
        y_speed *= -1
    #surface, rect, x-speed, y-speed
    player_shots.append([player_shot_image, player_shot_image.get_rect(centerx=player_rect.centerx, centery=player_rect.centery), x_speed, y_speed])

Позже в цикле есть эта часть кода:

for player_shot_counter in range(len(player_shots)):
    player_shots[player_shot_counter][1][0] += player_shots[player_shot_counter][2]
    player_shots[player_shot_counter][1][1] += player_shots[player_shot_counter][3]

Эта механика работает в основном нормально, за исключением одной серьезной ошибки: чем медленнее выстрел, тем он менее точен, поскольку pygame.Rect[0] и pygame.Rect[1] могут быть только целыми числами. Например, если player_rect.center равно (0, 0), позиция мыши (100, 115) и скорость_пуля10, тогда x_speed автоматически округлится до 7 и y_speed до 8, в результате чего пуля в конечном итоге пройдет через точку (98, 112). Однако, если bullet_speed 5, то пуля пройдет через точку (99, 132).

Есть ли способ обойти это в pygame?

Заранее благодарю за любую помощь!


person Vladimir Shevyakov    schedule 22.07.2016    source источник
comment
Насколько мне известно, лучшее решение, которое у вас есть на данный момент, - это отслеживать реальную позицию в координатах с плавающей запятой, а затем, когда дело доходит до переноса вашего спрайта на экран, округлить его соответствующим образом. Этот ресурс был мне полезен: переход на субпиксель с pygame. Что-то, что также будет влиять на вас, это то, что вы, кажется, не учитываете time при настройке скорости пули. Это вызовет большую погрешность в позиционировании пули.   -  person Jonathon Ogden    schedule 22.07.2016
comment
Еще одно предложение относительно вашего кода позиционирования и таких строк: math.sqrt(1+((dx**2)/(dy**2))): знаете ли вы, что pygame имеет Vector2, который представляет координаты x, y и имеет такие функции, как math.length, которые избавляют вас от необходимости писать такой код позиционирования?   -  person Jonathon Ogden    schedule 22.07.2016
comment
@JonathonOgden Спасибо, я на самом деле не знал, что pygame имеет класс Vector2, и вместо этого использовал список с двумя объектами. Но что такое math.length?   -  person Vladimir Shevyakov    schedule 23.07.2016
comment
math.length эквивалентно math.sqrt(vec.x**2 + vec.y**2), то есть величине или длине вектора. Ссылка Vector2.length   -  person Jonathon Ogden    schedule 23.07.2016


Ответы (1)


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

person awerries    schedule 22.07.2016
comment
Не уверен, как я это пропустил, код исправлен! Спасибо! - person Vladimir Shevyakov; 23.07.2016