问题描述
我正在使用pygame制作平台游戏,我想为其添加重力。
现在,只有按箭头键时会移动的图片,下一步是重力。这是我的代码:
I'm making a platform game with pygame, and I would like to add gravity to it.Right now I only have a picture which moves when I press the arrow keys, and my next step would be gravity. Here's my code:
import pygame, sys
from pygame.locals import *
pygame.init()
FPS = 30
fpsClock = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((400, 300), 0, 32)
pygame.display.set_caption("Jadatja")
WHITE = (255, 255, 255)
catImg = pygame.image.load("images/cat.png")
catx = 10
caty = 10
movingRight = False
movingDown = False
movingLeft = False
movingUp = False
while True: #main game loop
#update
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_RIGHT:
#catx += 5
movingRight = True
movingLeft = False
elif event.key == K_DOWN:
#caty += 5
movingDown = True
movingUp = False
elif event.key == K_LEFT:
#catx -= 5
movingLeft = True
movingRight = False
elif event.key == K_UP:
#caty -= 5
movingUp = True
movingDown = False
if event.type == KEYUP:
if event.key == K_RIGHT:
movingRight = False
if event.key == K_DOWN:
movingDown = False
if event.key == K_LEFT:
movingLeft = False
if event.key == K_UP:
movingUp = False
#actually make the player move
if movingRight == True:
catx += 5
if movingDown == True:
caty += 5
if movingLeft == True:
catx -= 5
if movingUp == True:
caty -= 5
#exit
for event in pygame.event.get():
if event.type == KEYUP:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
if event.type == QUIT:
pygame.quit()
sys.exit()
#draw
DISPLAYSURF.fill(WHITE)
DISPLAYSURF.blit(catImg, (catx, caty))
pygame.display.update()
fpsClock.tick(FPS)
我不确定100%此代码是否像我想的那样平滑,但我希望你们能有所作为。
I'm not 100% sure if this code is as smooth as I think it is, but I hope you guys can make something of it.
谢谢
推荐答案
有,用于创建弹跳球,我认为这可能
There is a tutorial for creating a bouncing ball which I think might be helpful to you.
现在,要将重力添加到该模拟中,您每次在循环中只需在y方向上增加一些额外的速度:
Now, to add gravity to that simulation, you'd simply add some extra speed in the y-direction every time through the loop:
speed[1] += gravity
但是,最终的结果有点愚蠢,因为图像迅速下降到窗口底部以下,从不再次出现:)
What you end up with is kind of goofy however, since the image quickly descends below the bottom of the window never to be seen again :)
因此,下一步是剪切球的位置,使其必须保留在窗口中:
The next step is therefore to clip the position of the ball so it must remain in the window:
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()
好的,现在您可以将其合并到当前代码中,并且将关闭并运行。但是,您可以做一些事情来使代码更有条理,减少重复。
Okay, now you can incorporate that in your current code and you'll be off and running. However, there are some things you can do to make your code more organized and less repetitive.
例如,考虑大量的 ...然后
For example, consider the massive if...then
blocks that follow
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
将与图像移动相关的所有逻辑都放入一个类中,您还可以从中受益:
You could also benefit from putting all the logic associated with the movement of your image into a class:
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
中。而且,它易于实例化许多球。您还可以创建其他类(飞机,鸟,桨等),它们也以不同的方式移动,并将它们相对轻松地添加到模拟中。
Notice the update
method is very similar to the code presented by the tutorial. One of the nice things about creating a Ball class is that the rest of your program does not need to know much about how a Ball moves. All the logic is in Ball.update
. Moreover, it makes it easy to instantiate many balls. And you could create other classes (airplanes, birds, paddles, etc.) that move differently too and add them to your simulation relatively painlessly.
因此,将它们放在一起,您最终会得到这样的结果:
So, putting it all together, you would end up with something like this:
"""
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()
这篇关于pygame中的重力的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!