当我在 Pygame 中按相应的键时图像不会移动

Image won't move when I press corresponding keys in Pygame

我只是为了好玩和学习新东西而开始编写代码,但是我已经 运行 解决了这个问题,并且希望得到一些关于我做错了什么的具体意见。在我的项目中,此时我正在尝试使用箭头键使图像左右移动。我已经让图像正常显示,但它不会响应按键而移动。欢迎任何意见。

`import pygame, sys, random

pygame.init()
clock = pygame.time.Clock()

screen_width = 1280
screen_height = 800
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Invader slim")
surface = screen.get_rect()

DIS = (100, 100)
pygame.image.load('sprite_soldier.png')
player_image = pygame.image.load('sprite_soldier.png').convert_alpha()
player_soldier = pygame.transform.scale(player_image, DIS)
player = screen.blit(player_soldier, (screen_width/2 - 10, screen_height - 100))

bg_color = pygame.Color(0, 100, 100)
green = pygame.Color(0, 255, 0)
white = pygame.Color('white')
light_gray = pygame.Color(200, 200, 200)


torpedo = pygame.Rect(screen_width/2 - 10, screen_height - 100, 20, 20)

player_x = player.x
move_left = False
move_right = False


while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                move_right = True
            if event.key == pygame.K_LEFT:
                move_left = True
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_RIGHT:
                move_right = False
            if event.key == pygame.K_LEFT:
                move_left = False
    if move_right:
        player_x += 10
    elif move_left:
        player_x -= 10

    if player.x >= screen_width:
        move_right = False
    if player.x <= 0:
        move_left = False

    pygame.display.flip()
    clock.tick(60)

您必须每帧再次将图像绘制到屏幕上。你可以这样做:

import pygame, sys, random

pygame.init()

FPS = 60

clock = pygame.time.Clock()

screen_width, screen_height = 1280, 800
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Invader slim")

DIS = (100, 100)
player_image = pygame.image.load('sprite_soldier.png').convert_alpha()
player_soldier = pygame.transform.scale(player_image, DIS)
player_rect = player_soldier.get_rect(center=screen_width / 2 - 10, screen_height - 100)

bg_color = pygame.Color(0, 100, 100)
green = pygame.Color(0, 255, 0)
white = pygame.Color('white')
light_gray = pygame.Color(200, 200, 200)
   
torpedo = pygame.Rect(screen_width / 2 - 10, screen_height - 100, 20, 20)

move_left = False
move_right = False


def draw():
   screen.fill(bg_color)
   screen.blit(player_soldier, player_rect)
   pygame.display.update()


while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                move_right = True
            if event.key == pygame.K_LEFT:
                move_left = True
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_RIGHT:
                move_right = False
            if event.key == pygame.K_LEFT:
                move_left = False

    if move_right:
        player_rect.x += 10
    elif move_left:
        player_rect.x -= 10

    if player_rect.x >= screen_width:
        move_right = False
    if player_rect.x <= 0:
        move_left = False

    pygame.display.flip()
    clock.tick(FPS)

我还更改了一些内容,例如添加 player_rect 变量。 我还尝试使用 FPS 变量和一些空行使其更具可读性。

您错过了在应用程序循环中的新位置绘制播放器:

while True:
    # [...]

    screen.fill(0)
    player = screen.blit(player_soldier, (player_x, screen_height - 100))
    pygame.display.flip()
    clock.tick(60)

使用 pygame.key.get_pressed() 代替 KEYDOWN 事件:

run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        
    keys = pygame.key.get_pressed()
    player_x += 10 * (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT])

    screen.fill(0)
    player = screen.blit(player_soldier, (player_x, screen_height - 100))
    pygame.display.flip()
    clock.tick(60)

pygame.quit()
sys.exit()

典型的 PyGame 应用程序循环必须:

键盘事件(参见 pygame.event 模块)仅在键状态改变时发生一次。 KEYDOWN 事件在每次按下一个键时发生一次。 KEYUP 每松开一个键就会出现一次。使用键盘事件进行单个操作或逐步移动。

pygame.key.get_pressed() returns a sequence with the state of each key. If a key is held down, the state for the key is True, otherwise False. Use pygame.key.get_pressed() 评估按钮的当前状态并获得连续移动


完整示例:

import pygame, sys, random

pygame.init()
clock = pygame.time.Clock()

screen_width = 1280
screen_height = 800
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Invader slim")
surface = screen.get_rect()

DIS = (100, 100)
player_image = pygame.image.load('sprite_soldier.png').convert_alpha()
player_soldier = pygame.transform.scale(player_image, DIS)
player_rect = player_soldier.get_rect(midbottom =  (screen_width/2, screen_height))

bg_color = pygame.Color(0, 100, 100)
green = pygame.Color(0, 255, 0)
white = pygame.Color('white')
light_gray = pygame.Color(200, 200, 200)


torpedo = pygame.Rect(screen_width/2 - 10, screen_height - 100, 20, 20)

run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        
    keys = pygame.key.get_pressed()
    player_rect.x += 10 * (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT])
    player_rect.clamp_ip(surface)

    screen.fill(0)
    player = screen.blit(player_soldier, player_rect)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()
sys.exit()

您已经更新了玩家的位置,但还没有将 sprite 复制到新位置。此外,您还必须在 blit 更新之前“清除”屏幕,否则您只会画一条线。

# screen.fill() will 'clear' the screen of previous blits
screen.fill('black)

# Show the player at the new position
screen.blit(player_soldier, (player_x, screen_height - 100))

# pygame.display.flip() will show the updated screen
pygame.display.flip()
clock.tick(60)

屏幕必须在 drawing/bliting 个精灵之前清空。这样可以防止拖尾效应。

Sprites 必须每帧 redrawn/blited 到屏幕才能实现 'movement'。

这两个步骤必须在显示新屏幕之前的每一帧完成。