Jadi untuk menjawab pertanyaan lain, saya mempelajari python + pygame gerakan proyektil. Pada dasarnya saya ingin membuat sprite, kemudian ketika "diluncurkan" dengan kecepatan dan sudut awal akan berperilaku sesuai gravitasi dan fisika Newton.
Aplikasi demo saya membuat banyak proyektil acak. Untuk beberapa proyektil, mereka terbang, dalam jalur parabola yang benar, sebelum mendarat; sempurna!
Namun:
- Sepertinya tidak ada proyektil yang bisa ke kiri (ke arah 270-360 derajat)
- Beberapa proyektil tidak pernah mendarat
Saya menduga ini karena fungsi math.cos()
dan math.sin()
yang akan mengubah tanda hasil, bergantung pada kuadrannya. Saya rasa saya juga memiliki asumsi buruk bahwa 0 derajat adalah "jam 12", dan ini sebenarnya 90 derajat.
Tentu saja hasil yang diharapkan adalah partikel dapat bergerak ke kiri dan ke kanan, dan tidak ada partikel yang terbang ke orbit.
import pygame
import random
import math
# Window size
WINDOW_WIDTH =1000
WINDOW_HEIGHT = 400
FPS = 60
# background colours
INKY_GREY = ( 128, 128, 128 )
# milliseconds since start
NOW_MS = 0
class ProjectileSprite( pygame.sprite.Sprite ):
GRAVITY = -9.8
def __init__( self, bitmap, velocity=0, angle=0 ):
pygame.sprite.Sprite.__init__( self )
self.image = bitmap
self.rect = bitmap.get_rect()
self.start_x = WINDOW_WIDTH // 2
self.start_y = WINDOW_HEIGHT - self.rect.height
self.rect.center = ( ( self.start_x, self.start_y ) )
# Physics
self.setInitialVelocityRadians( velocity, angle )
def setInitialVelocityRadians( self, velocity, angle_rads ):
global NOW_MS
self.start_time = NOW_MS
self.velocity = velocity
self.angle = angle_rads
def update( self ):
global NOW_MS
if ( self.velocity > 0 ):
time_change = ( NOW_MS - self.start_time ) / 150.0 # Should be 1000, but 100 looks better
if ( time_change > 0 ):
# re-calcualte the velocity
velocity_x = self.velocity * math.cos( self.angle )
velocity_y = self.velocity * math.sin( self.angle ) - ( self.GRAVITY * time_change )
# re-calculate the displacement
# x
displacement_x = velocity_x * time_change * math.cos( self.angle )
# y
half_gravity_time_squared = ( self.GRAVITY * ( time_change * time_change ) ) / 2.0
displacement_y = ( velocity_y * time_change * math.sin( self.angle ) ) - half_gravity_time_squared
# reposition sprite
self.rect.center = ( ( self.start_x + int( displacement_x ), self.start_y - int( displacement_y ) ) )
# Stop at the bottom of the window
if ( self.rect.y >= WINDOW_HEIGHT - self.rect.height ):
self.rect.y = WINDOW_HEIGHT - self.rect.height
self.velocity = 0
#self.kill()
### MAIN
pygame.init()
SURFACE = pygame.HWSURFACE | pygame.DOUBLEBUF | pygame.RESIZABLE
WINDOW = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), SURFACE )
pygame.display.set_caption("Projectile Motion Example")
# Load resource image(s)
sprite_image = pygame.image.load( "ball.png" )#.convert_alpha()
# Make some sprites
SPRITES = pygame.sprite.Group()
for i in range( 20 ):
speed = random.randrange( 10, 50 )
if ( random.randrange( -100, 101 ) > 0 ):
angle = math.radians( random.randrange( 0, 45 ) ) # 0-45 degrees
else:
angle = math.radians( random.randrange( 315, 360 ) ) # minus 0-45 degrees
new_sprite = ProjectileSprite( sprite_image, speed, angle )
SPRITES.add( new_sprite )
clock = pygame.time.Clock()
done = False
while not done:
NOW_MS = pygame.time.get_ticks()
# Handle user-input
for event in pygame.event.get():
if ( event.type == pygame.QUIT ):
done = True
elif ( event.type == pygame.KEYDOWN ):
if ( event.unicode == '+' or event.scancode == pygame.K_PLUS ):
# Pressing '+' adds a new projectile sprite
speed = random.randrange( 10,100 )
angle = math.radians( random.randrange( -45, 45 ) )
new_sprite = ProjectileSprite( sprite_image, speed, angle )
SPRITES.add( new_sprite )
# Handle continuous-keypresses
keys = pygame.key.get_pressed()
if ( keys[pygame.K_ESCAPE] ):
# [Esc] exits too
done = True
# Repaint the screen
WINDOW.fill( INKY_GREY )
SPRITES.update() # re-position the sprites
SPRITES.draw( WINDOW ) # draw the sprites
pygame.display.flip()
# Update the window, but not more than 60fps
clock.tick_busy_loop( FPS )
pygame.quit()
Rumus untuk aplikasi ini diambil langsung dari artikel wikipedia.
print()
untuk menampilkan nilai dalam variabel pada momen berbeda dan untuk menampilkan informasi bagian kode mana yang dieksekusi. Ini dapat membantu untuk menemukan masalah. Atau pelajari cara menggunakan debuger. - person furas   schedule 24.04.2019angle = math.radians( random.randrange(-45, 45)+270 )
. Jika saya menggunakan minus divelocity_x = -self.velocity * math.cos( self.angle )
maka semua bola hanya bergerak ke arah kiri. Anda bisa menggunakan kecepatan plus dan minus acak. - person furas   schedule 24.04.2019