Существует руководство по созданию прыгающего мяча, которое, я думаю, может быть полезным. тебе.
Теперь, чтобы добавить гравитацию в эту симуляцию, вы просто добавляете некоторую дополнительную скорость в направлении Y каждый раз в цикле:
speed[1] += gravity
Однако то, что вы получите, довольно глупо, поскольку изображение быстро опускается ниже нижней части окна, и его больше никогда не видно :)
Следовательно, следующим шагом будет обрезание положения мяча, чтобы он оставался в окне:
import os
import sys, pygame
pygame.init()
size = width, height = 320, 240
speed = [1, 1]
black = 0, 0, 0
gravity = 0.1
screen = pygame.display.set_mode(size)
image_file = os.path.expanduser("~/pybin/pygame_examples/data/ball.png")
ball = pygame.image.load(image_file)
ballrect = ball.get_rect()
def clip(val, minval, maxval):
return min(max(val, minval), maxval)
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
speed[1] += gravity
ballrect = ballrect.move(speed)
if ballrect.left < 0 or ballrect.right > width:
speed[0] = -speed[0]
if ballrect.top < 0 or ballrect.bottom > height:
speed[1] = -speed[1]
# clip the position to remain in the window
ballrect.left = clip(ballrect.left, 0, width)
ballrect.right = clip(ballrect.right, 0, width)
ballrect.top = clip(ballrect.top, 0, height)
ballrect.bottom = clip(ballrect.bottom, 0, height)
screen.fill(black)
screen.blit(ball, ballrect)
pygame.display.flip()
Хорошо, теперь вы можете включить это в свой текущий код, и все будет готово. Однако есть некоторые вещи, которые вы можете сделать, чтобы сделать ваш код более организованным и менее повторяющимся.
Например, рассмотрим массивные блоки if...then
, следующие за
for event in pygame.event.get():
Вы можете переписать его как-то так:
delta = {
pygame.K_LEFT: (-20, 0),
pygame.K_RIGHT: (+20, 0),
pygame.K_UP: (0, -20),
pygame.K_DOWN: (0, +20),
}
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
deltax, deltay = delta.get(event.key, (0, 0))
ball.speed[0] += deltax
ball.speed[1] += deltay
Вы также можете извлечь выгоду из помещения всей логики, связанной с движением вашего изображения, в класс:
class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.speed = [0, 0]
area = pygame.display.get_surface().get_rect()
self.width, self.height = area.width, area.height
def update(self):
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > self.width:
self.speed[0] = -self.speed[0]
if self.rect.top < 0 or self.rect.bottom > self.height:
self.speed[1] = -self.speed[1]
self.rect.left = clip(self.rect.left, 0, self.width)
self.rect.right = clip(self.rect.right, 0, self.width)
self.rect.top = clip(self.rect.top, 0, self.height)
self.rect.bottom = clip(self.rect.bottom, 0, self.height)
Обратите внимание, что метод update
очень похож на код, представленный в руководстве. Одна из приятных особенностей создания класса Ball заключается в том, что остальной части вашей программы не нужно много знать о том, как движется Ball. Вся логика в Ball.update
. Кроме того, это позволяет легко создавать множество мячей. И вы можете создать другие классы (самолеты, птицы, весла и т. д.), которые тоже двигаются по-другому, и относительно безболезненно добавить их в свою симуляцию.
Итак, собрав все это вместе, вы получите что-то вроде этого:
"""
http://stackoverflow.com/a/15459868/190597 (unutbu)
Based on http://www.pygame.org/docs/tut/intro/intro.html
Draws a red ball bouncing around in the window.
Pressing the arrow keys moves the ball
"""
import sys
import pygame
import os
image_file = os.path.expanduser("~/pybin/pygame_examples/data/ball.png")
delta = {
pygame.K_LEFT: (-20, 0),
pygame.K_RIGHT: (+20, 0),
pygame.K_UP: (0, -20),
pygame.K_DOWN: (0, +20),
}
gravity = +1
class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.speed = [0, 0]
area = pygame.display.get_surface().get_rect()
self.width, self.height = area.width, area.height
def update(self):
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > self.width:
self.speed[0] = -self.speed[0]
if self.rect.top < 0 or self.rect.bottom > self.height:
self.speed[1] = -self.speed[1]
self.rect.left = clip(self.rect.left, 0, self.width)
self.rect.right = clip(self.rect.right, 0, self.width)
self.rect.top = clip(self.rect.top, 0, self.height)
self.rect.bottom = clip(self.rect.bottom, 0, self.height)
def clip(val, minval, maxval):
return min(max(val, minval), maxval)
class Main(object):
def __init__(self):
self.setup()
def setup(self):
pygame.init()
size = (self.width, self.height) = (640,360)
self.screen = pygame.display.set_mode(size, 0, 32)
self.ball = Ball()
self.setup_background()
def setup_background(self):
self.background = pygame.Surface(self.screen.get_size())
self.background = self.background.convert()
self.background.fill((0, 0, 0))
self.screen.blit(self.background, (0, 0))
pygame.display.flip()
def draw(self):
self.screen.blit(self.background, (0, 0))
self.screen.blit(self.ball.image, self.ball.rect)
pygame.display.flip()
def event_loop(self):
ball = self.ball
friction = 1
while True:
for event in pygame.event.get():
if ((event.type == pygame.QUIT) or
(event.type == pygame.KEYDOWN and
event.key == pygame.K_ESCAPE)):
sys.exit()
elif event.type == pygame.KEYDOWN:
deltax, deltay = delta.get(event.key, (0, 0))
ball.speed[0] += deltax
ball.speed[1] += deltay
friction = 1
elif event.type == pygame.KEYUP:
friction = 0.99
ball.speed = [friction*s for s in ball.speed]
ball.speed[1] += gravity
ball.update()
self.draw()
pygame.time.delay(10)
if __name__ == '__main__':
app = Main()
app.event_loop()
person
unutbu
schedule
14.05.2013