As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center 指导。




8年前关闭。




我正在用 pygame 制作一个平台游戏,我想为它添加重力。
现在我只有一张按箭头键会移动的图片,我的下一步将是重力。这是我的代码:
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% 确定这段代码是否像我想象的那样流畅,但我希望你们能有所作为。

谢谢

最佳答案

a tutorial 用于创建弹跳球,我认为这可能对您有所帮助。

现在,要为该模拟添加重力,您只需在每次循环时在 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()

关于python - pygame中的重力,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16551009/

10-13 05:04