pygame を使用して単純な 2D ウィンドウで重力をシミュレートしようとしています。それは非常に単純なもの (ドットが再び上昇して下降する) であり、メカニズムを理解しています。つまり、ベクトルとしての速度と、メインループを実行するたびに重力を表す値 g によって y 部分が一貫して減少し、その後の位置の更新ドット。
すべて正常に動作していますが、挿入する正しい値を選択するのに問題があります。現時点ではすべて試行錯誤です。半現実的な軌道を実現するために、どの数値を使用するかを決定する方法について、適切な経験則はありますか?
以下に最小限の例を挿入しました。質問にとって重要な値は次のとおりです。
window = (640, 480) # pixels
initial_speed = 20 # pixels per update along the y axis
gravity = 0.4 # deduction on initial_speed per update
では、なぜこれらの数字がたまたま錯覚を起こさせるのでしょうか? 何年も前に物理学の授業で学んだ式を最初に使用しようとしましたが、単位変換の有無にかかわらず、シミュレーションは正しくありませんでした. ほとんどの場合、ボールさえ見えませんでしたが、試行錯誤して上記の値を見つけました。
事前にご協力いただきありがとうございます。さらに情報が必要な場合は、コメントを投稿してください。
これが最小限の例です。vector2D ライブラリは pygame の Web サイトから便利に借用したことに注意してください (このリンクをたどってください) 。
#!/usr/bin/env python
import pygame
from pygame.locals import *
from vector2D import Vec2d
pygame.init()
GRAVITY = 0.4
class Dot(pygame.sprite.Sprite):
def __init__(self, screen, img_file, init_position, init_direction, speed):
pygame.sprite.Sprite.__init__(self)
self.screen = screen
self.speed = Vec2d(speed)
self.base_image = pygame.image.load(img_file).convert_alpha()
self.image = self.base_image
# A vector specifying the Dot's position on the screen
self.pos = Vec2d(init_position)
# The direction is a normalized vector
self.direction = Vec2d(init_direction).normalized()
def blitme(self):
""" Blit the Dot onto the screen that was provided in
the constructor.
"""
self.screen.blit(self.image, self.pos)
def update(self):
self.speed.y -= GRAVITY
displacement = Vec2d(
self.direction.x * self.speed.x,
self.direction.y * self.speed.y
)
self.pos += displacement
def main():
DIMENSION = SCREEN_WIDTH, SCREEN_HEIGHT = 640, 480
BG_COLOUR = 0,0,0
# Creating the screen
window = screen = pygame.display.set_mode(
(SCREEN_WIDTH, SCREEN_HEIGHT), 0, 32)
screen = pygame.display.get_surface()
clock = pygame.time.Clock()
dot = Dot(screen, "my/path/to/dot.jpg", (180, SCREEN_HEIGHT),
(0, -1), (0, 20))
mainloop = True
while mainloop:
# Limit frame speed to 50 FPS
time_passed = clock.tick(50)
for event in pygame.event.get():
if event.type == pygame.QUIT:
mainloop = False
# Redraw the background
screen.fill(BG_COLOUR)
dot.update()
dot.blitme()
pygame.display.flip()
if __name__ == '__main__':
main()