Проблема с формулой в PyGame
Хочу сделать простейшую функцию прыжка через параболу, но столкнулся с тем, что в pygame позиция может быть только целым числом, а результат функции - дробное, поэтому с каждым прыжком уровень бокса персонажа повышается. Прыжок:
if player.jumping:
if jump_height >= -15:
player.rect.y -= decimal.Decimal((jump_height ** 2) / 2) if jump_height >= 0 else -decimal.Decimal((jump_height ** 2) / 2)
jump_height -= 1
else:
player.jumping = False
player.rect.y += 8
jump_height = 15
Весь код:
import pygame
import os
import decimal
# VARIABLES
WIDTH = 1920
HEIGHT = 1080
FPS = 60
player_speed = 15
running = True
jumping = False
jump_height = 15
clock = pygame.time.Clock()
# INITIALIZING
pygame.init()
pygame.mixer.init()
main_window = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("TestGame")
sprites = pygame.sprite.Group()
# ASSETS
game_folder = os.path.dirname(__file__)
img_folder = os.path.join(game_folder, 'img')
player_img = pygame.image.load(os.path.join(img_folder, 'player.png'))
player_sneaking_img = pygame.image.load(os.path.join(img_folder, 'sneaking.png'))
# CLASSES
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = player_img
self.rect = self.image.get_rect()
self.rect.center = (WIDTH / 2, HEIGHT - 100)
self.sneaking = False
self.jumping = False
def move(self, direction):
if self.rect.left > WIDTH:
self.rect.right = 0
elif self.rect.right < 0:
self.rect.left = WIDTH
elif direction == 2:
self.rect.x += player_speed
elif direction == 3:
self.sneaking = True
rect = (self.rect.center[0], self.rect.bottom - (0.75 * self.rect.height) / 2)
self.image = player_sneaking_img
self.rect = self.image.get_rect()
self.rect.center = rect
elif direction == 4:
self.rect.x -= player_speed
# FUNCTIONS
def movements_handler():
global player_speed
key = pygame.key.get_pressed()
if (key[pygame.K_w] or key[pygame.K_UP]) and not player.jumping and not player.sneaking:
player.jumping = True
if key[pygame.K_d] or key[pygame.K_RIGHT]:
player.move(2)
if (key[pygame.K_s] or key[pygame.K_DOWN]):
if not jumping:
player_speed /= 2
player.move(3)
if key[pygame.K_a] or key[pygame.K_LEFT]:
player.move(4)
player = Player()
sprites.add(player)
# PROGRAM
while running:
clock.tick(FPS)
# EVENT HANDLER
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYUP:
if event.key == pygame.K_s or event.key == pygame.K_DOWN:
player.sneaking = False
player.image = player_img
player.rect = player.image.get_rect()
player_speed = 8
movements_handler()
# UPDATE
if player.jumping:
if jump_height >= -15:
player.rect.y -= decimal.Decimal((jump_height ** 2) / 2) if jump_height >= 0 else -decimal.Decimal((jump_height ** 2) / 2)
jump_height -= 1
else:
player.jumping = False
player.rect.y += 8
jump_height = 15
# RENDER
main_window.fill('white')
sprites.draw(main_window)
pygame.display.flip()
# QUIT
pygame.quit()
Получилось немного стабилизировать это с помощью модуля decimal + отнимая каждый раз от высоты 8 пикселей, но мне нужен какой нибудь более универсальный/надежный способ.