Рассчитать гравитацию / прыжок в pygame

Как лучше всего рассчитать гравитацию в pygame? Мне в основном это просто нужно, чтобы, когда игрок нажимает «Вверх», персонаж прыгает. Вот мой код (просто белый экран с красным блоком, который движется)

import pygame
import random

# Define colors
black    = (   0,   0,   0)
white    = ( 255, 255, 255)
green    = (   0, 255,   0)
red      = ( 255,   0,   0)

#Classes
class Player(pygame.sprite.Sprite):
    def __init__(self, color, width, height):
        pygame.sprite.Sprite.__init__(self) 
        self.image = pygame.Surface([width, height])
        self.image.fill(color)
        self.rect = self.image.get_rect()

    def move(self, x_change, y_change):
        self.rect.x += x_change
        self.rect.y +=  y_change


#Lists
all_sprites_list = pygame.sprite.Group()

#Spawn player
player = Player(red,16,16) 
all_sprites_list.add(player)
player.rect.x = 0
player.rect.y = 484

#Initalize
pygame.init()
#Set the width and height of the screen [width,height]
screen_height = 700
screen_width = 500
size=[screen_height,screen_width]
screen=pygame.display.set_mode(size)
#Name on top tab
pygame.display.set_caption("My Game")

#DONT CHANGE
done = False
clock=pygame.time.Clock()

#MAIN LOOP
while done == False:
    for event in pygame.event.get(): # User did something
        if event.type == pygame.QUIT: # If user clicked close
            done = True # Quit

        if event.type == pygame.KEYUP:
                    # If it is an arrow key, reset vector back to zero
                    if event.key == pygame.K_LEFT:
                        None      

    keyDown = pygame.key.get_pressed()
    if keyDown[pygame.K_RIGHT]:
        player.move(3, 0)   
    if keyDown[pygame.K_LEFT]:
        player.move(-3, 0)        
    if keyDown[pygame.K_DOWN]:
        player.move(0, 3)                        
    if keyDown[pygame.K_UP]:
        player.move(0,-3)

    #If player hits side of screen, do this
    if player.rect.x < 0:
        player.rect.x = 0
    if player.rect.x > 684:
        player.rect.x = 684
    if player.rect.y < 0:
        player.rect.y = 0
    if player.rect.y > 484:
        player.rect.y = 484    


    #Clear screen
    screen.fill(white)

    #Drawing
    all_sprites_list.draw(screen)

    #FPS Lock
    clock.tick(60)

    #Update screen
    pygame.display.flip()

# Close the window and quit.
pygame.quit()

person user3161089    schedule 06.01.2014    source источник
comment
Физика pygame - это то, что вам нужно исследовать   -  person Tony Hopkinson    schedule 06.01.2014


Ответы (1)


Клоны Super Mario обычно перемещаются на определенное количество времени вверх, а затем вниз, пока не ударяются о что-нибудь твердое (пол или, возможно, черепаху). Как вы знаете, это выглядит очень нереально.

Физическая формула для «прыжков и падений»: d = (at²)/2, где d - расстояние, на которое подпрыгнул, a - сила тяжести, а t - время. Однако для простой игры, которую можно настроить :)

  1. Установите целевую «высоту» для прыжков; например, всего 32 пикселя.
  2. Используйте 1 для силы тяжести.
  3. Измерьте время t в игровых тиках.
  4. Это дает вам время, необходимое для достижения 32 пикселей:

     32 = (t²)/2
     t² = 64
     t = 8
    
  5. «Скорость» вашего прыжка v = at. Поскольку вы предполагаете a=1 выше, v = t, то есть v = 8. Как оказалось, ваш начальный ypos должен быть установлен на speed/2 (вероятно, потому что это приблизительное значение ..)

  6. В каждом следующем игровом тике добавляйте speed к вашей позиции y и вычтите 1 из speed.
  7. Теперь в каждом игровом тике с момента нажатия клавиши «вверх» будет происходить следующее (при условии y=0 в начале):

    1. speed = 8 -> y=4 (since this is "jump 0")
    2. speed = 7 -> y=11
    3. speed = 6 -> y=17
    4. speed = 5 -> y=22
    5. speed = 4 -> y=26
    6. speed = 3 -> y=29
    7. speed = 2 -> y=31
    8. speed = 1 -> y=32
    9. speed = 0 -> y=32
    10. speed = -1 -> y=31
    11. speed = -2 -> y=29 ... снова до 0 (но проверьте переполнение на предмет ниже нуля).

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


Редактировать

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

Проблема заключается в моем утверждении, что если ваша начальная скорость - в начале прыжка - равна 8 (пикселей за такт игры), вы в конечном итоге окажетесь ровно на 8 пикселей выше в «конце» этого такта. . Вы этого не сделаете, потому что "гравитация" срабатывает сразу же, как только вы отрываетесь от земли. В «конце» игрового тика ваша скорость снизилась до 7; следовательно, ваша средняя скорость не 8 от начала до конца этого тика, она всего 7.5, и вы получите Y-положение 7,5 пикселей. То же самое касается каждого следующего тика; ваша скорость по-прежнему снижается на 1 за тик.

Итак, после (правильно рассчитанного!) Общего времени прыжка, равного 8 тикам, вы проехали

7.5 + 6.5 + 5.5 + 4.5 + 3.5 + 2.5 + 1.5 + 0.5 = 32 pixels

Его можно «правильно» реализовать, но он вводит арифметику с плавающей запятой в то, что в настоящее время является вычислением только для целых чисел, и вам потребуется нарисовать свой спрайт в позиции y, равной «7,5 пикселей». Вычисления с плавающей запятой могут страдать от округления и проблем с «точным» сравнением, поэтому лучше по возможности избегать этого - особенно для такой простой физики.

person Jongware    schedule 06.01.2014
comment
Вы сами пишете этот код? Если да, не могли бы вы поделиться им со мной, чтобы я мог посмотреть, как это работает? - person user3161089; 06.01.2014
comment
В строке 1. speed = 8 - ›y = 4 не должен ли y быть немного больше? - person kame; 06.01.2014
comment
@kame: нет, по какой-то причине нужно немного возиться. При начальной скорости 8 расстояние вверх будет 8*8/2 = 32, но 8+7+6+5+4+3+2+1 в сумме дает 36. При всех начальных скоростях я всегда получаю одни и те же speed/2 пикселя слишком высоко. Кажется, я не могу понять, откуда взялось несоответствие: P Попробовать первое значение легче, чем распределить ошибку по нескольким тикам. - person Jongware; 06.01.2014
comment
Понятно. Проблема в том, что вы не можете использовать значения с плавающей запятой. - person kame; 06.01.2014
comment
Если кто-то из вас узнает, как это сделать, было бы здорово, если бы вы могли прислать мне код - person user3161089; 07.01.2014
comment
Пошаговая инструкция должна была быть достаточно поучительной. Вы знаете, как выполнять простое сложение и вычитание в Python? - person Jongware; 07.01.2014
comment
Сам разобрался :) - person user3161089; 07.01.2014
comment
Просто я сначала не понял, о чем вы говорите. Пришлось перечитать несколько раз - person user3161089; 07.01.2014