Pygame 精灵运动故障

Pygame Sprite Movement glitch

我正在做一个 pygame 项目,但我对角色的移动有一些疑虑。动画不同步(用蹩脚的术语),当我向右或向左移动时,假设有一个角色向左或向右平滑移动的动画,但在我的情况下,当向左或向右移动时,我仍然可以看到当角色在行走运动中处于空闲位置时尾随角色的角色图像。我也有一个问题,当我的角色跳跃时它不会自己回来。我调整了屏幕的字符速度和刷新率,但似乎无济于事。下面是我的代码和图片。

文件1.处理运行游戏

import sys
import os
import pygame
from game_settings import GameSettings
from knight import Knight


class AlienApocalypse:
    """Overall class to manage game assets and behaviour"""

    def __init__(self):
        """Initialize the game and create game resources"""
        self.walking_step = 6
        pygame.init()
        self.settings = GameSettings()
        # Set up a clock that regulates the FPS of the game window
        self.clock = pygame.time.Clock()
        self.settings.vertical_momentum = 0

        drivers = ['directfb', 'fbcon', 'svgalib']

        found = False
        for driver in drivers:
            if not os.getenv('SDL_VIDEODRIVER'):
                os.putenv('SDL_VIDEODRIVER', driver)
            try:
                pygame.display.init()
            except pygame.error:
                print('Driver: {0} failed.'.format(driver))
                continue
            found = True
            break

        if not found:
            raise Exception('No suitable video driver found!')

        self.screen_window = pygame.display.set_mode((self.settings.screen_width, self.settings.screen_height))
        pygame.display.set_caption("Alien Apocalypse")

        """Setting background color"""
        self.background_color = (0, 0, 255)

        self.knight = Knight(self)

    def run_game(self):
        """Start the main loop for the game"""
        while True:
            self.clock.tick(27)
            self._check_events()
            self.knight.update()
            self._update_screen()

    def _check_events(self):
        """Respond to key presses and mouse events."""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                self._check_keydown_event(event)

            elif event.type == pygame.KEYUP:
                self._check_keyup_event(event)

    def _check_keydown_event(self, event):
        """Respond to KEYDOWN presses"""
        if event.key == pygame.K_RIGHT:
            self.knight.moving_right = True
        elif event.key == pygame.K_LEFT:
            self.knight.moving_left = True
        elif event.key == pygame.K_SPACE:
            self.knight.jump_move = True
        elif event.key == pygame.K_q:
            sys.exit()

    def _check_keyup_event(self, event):
        """Respond to KEY releases"""
        if event.key == pygame.K_RIGHT:
            self.knight.moving_right = False
        elif event.key == pygame.K_LEFT:
            self.knight.moving_left = False
        elif event.key == pygame.K_SPACE:
            self.knight.jump_move = False

    def _update_screen(self):
        # Redraw the screen during each pass through the loop.
        self.screen_window.fill(self.settings.background_color)
        self.knight.blitme()

        # Make the most recently drawn screen visible.
        pygame.display.flip()
        self.clock.tick(60)


if __name__ == "__main__":
    """Make a game instance, and run the game"""
    ap = AlienApocalypse()
    ap.run_game()

文件2。处理游戏设置

class GameSettings:
    """This class stores all the game settings"""

    def __init__(self):
        """Initialize the game's settings attributes"""
        # Screen settings
        self.screen_width = 1200
        self.screen_height = 800
        self.background_color = (0, 0, 255)
        self.vertical_momentum = 0

        # Knight settings
        self.knight_speed = 2.5

        # Bullet/Sword settings
        self.bullet_speed = 1.0
        self.bullet_width = 3
        self.bullet_height = 15
        self.bullet_color = (255, 60, 60)

文件 3. 处理我的游戏角色的设置和属性

import pygame
from pygame.sprite import Sprite


class Knight:
    """A class that manages the character knight"""

    def __init__(self, ap_game):
        """Initialize the knight and set its starting position."""
        self.neg = 0
        self.screen_window = ap_game.screen_window
        self.settings = ap_game.settings
        self.screen_window_rect = ap_game.screen_window.get_rect()

        # Load images for character walking movement
        self.walk_left = [
            pygame.image.load("/Users/username/Desktop/alien_apocalypse/craftpix-891165-assassin-mage-viking-free"
                              "-pixel-art-game-heroes/PNG/Knight/walk_left/walk_left1.bmp"),
            pygame.image.load("/Users/username/Desktop/alien_apocalypse/craftpix-891165-assassin-mage-viking-free"
                              "-pixel-art-game-heroes/PNG/Knight/walk_left/walk_left2.bmp"),
            pygame.image.load("/Users/username/Desktop/alien_apocalypse/craftpix-891165-assassin-mage-viking-free"
                              "-pixel-art-game-heroes/PNG/Knight/walk_left/walk_left3.bmp"),
            pygame.image.load("/Users/username/Desktop/alien_apocalypse/craftpix-891165-assassin-mage-viking-free"
                              "-pixel-art-game-heroes/PNG/Knight/walk_left/walk_left4.bmp"),
            pygame.image.load("/Users/username/Desktop/alien_apocalypse/craftpix-891165-assassin-mage-viking-free"
                              "-pixel-art-game-heroes/PNG/Knight/walk_left/walk_left5.bmp"),
            pygame.image.load("/Users/username/Desktop/alien_apocalypse/craftpix-891165-assassin-mage-viking-free"
                              "-pixel-art-game-heroes/PNG/Knight/walk_left/walk_left6.bmp")
        ]
        self.walk_right = [
            pygame.image.load("/Users/username/Desktop/alien_apocalypse/craftpix-891165-assassin-mage-viking-free"
                              "-pixel-art-game-heroes/PNG/Knight/Walk_right/walk1.bmp"),
            pygame.image.load("/Users/username/Desktop/alien_apocalypse/craftpix-891165-assassin-mage-viking-free"
                              "-pixel-art-game-heroes/PNG/Knight/Walk_right/walk2.bmp"),
            pygame.image.load("/Users/username/Desktop/alien_apocalypse/craftpix-891165-assassin-mage-viking-free"
                              "-pixel-art-game-heroes/PNG/Knight/Walk_right/walk3.bmp"),
            pygame.image.load("/Users/username/Desktop/alien_apocalypse/craftpix-891165-assassin-mage-viking-free"
                              "-pixel-art-game-heroes/PNG/Knight/Walk_right/walk4.bmp"),
            pygame.image.load("/Users/username/Desktop/alien_apocalypse/craftpix-891165-assassin-mage-viking-free"
                              "-pixel-art-game-heroes/PNG/Knight/Walk_right/walk5.bmp"),
            pygame.image.load("/Users/username/Desktop/alien_apocalypse/craftpix-891165-assassin-mage-viking-free"
                              "-pixel-art-game-heroes/PNG/Knight/Walk_right/walk6.bmp")
        ]

        # Load the character - Knight knight_idle and get its rect.
        image_file = "/Users/user/Desktop/alien_apocalypse/craftpix-891165-assassin-mage-viking-free-pixel-art" \
                     "-game-heroes/PNG/Knight/Idle/idle1.bmp"

        self.knight_idle = pygame.image.load(image_file)
        self.rect = self.knight_idle.get_rect()

        # Start each new character at the center of the screen.
        self.rect.center = self.screen_window_rect.center

        # Store the decimal value for the knight's horizontal position.
        self.x = float(self.rect.x)
        # Store the decimal value for the `knight's vertical position.
        self.y = float(self.rect.y)

        # Movement flag
        self.moving_right = False
        self.moving_left = False
        self.jump_move = False
        self.walk_count = 0
        self.jump_count = 10

    def update(self):
        """Update the knight's position based on the movement flag."""
        # Update the knight's x value, not the rect
        if self.moving_right and self.rect.right < self.screen_window_rect.right:
            self.x += self.settings.knight_speed

        if self.moving_left and self.rect.left > 0:
            self.x -= self.settings.knight_speed

        if self.jump_move:
            if self.jump_count >= -10:
                self.neg = 1
                if self.jump_count < 0:
                    self.neg = -1
                self.y -= (self.jump_count ** 2) * 0.5 * self.neg
                self.jump_count -= 1
            else:
                self.jump_count = 10

        # Update rect object from self.x.
        self.rect.x = self.x
        # Update rect object from self.y.
        self.rect.y = self.y

    def blitme(self):
        """Draw the character at its current location."""
        self.screen_window.blit(self.knight_idle, self.rect)
        if self.walk_count + 1 >= 18:
            self.walk_count = 0
        if self.moving_left:
            self.screen_window.blit(self.walk_left[self.walk_count // 3], self.rect)
            self.walk_count += 1

        elif self.moving_right:
            self.screen_window.blit(self.walk_right[self.walk_count // 3], self.rect)
            self.walk_count += 1
        else:
            self.screen_window.blit(self.knight_idle, self.rect)

当角色向左或向右走时游戏window的图像: character walking left

character walking left

but in my case when the is moving either left or right I can still see the character image for when the character is in an idle position trailing the character when in walking motion.

这是因为您在 Knight.blitme 中所做的第一件事是在空闲位置绘制角色。然后在其上绘制左图或右图:

class Knight:
    # [...]

        def blitme(self):
        """Draw the character at its current location."""

        # self.screen_window.blit(self.knight_idle, self.rect) <------ DELETE

        if self.walk_count + 1 >= 18:
            self.walk_count = 0
        if self.moving_left:
            self.screen_window.blit(self.walk_left[self.walk_count // 3], self.rect)
            self.walk_count += 1
        elif self.moving_right:
            self.screen_window.blit(self.walk_right[self.walk_count // 3], self.rect)
            self.walk_count += 1
        else:
            self.screen_window.blit(self.knight_idle, self.rect)


I also have an issue when my character jumps it doesn't come back

只有按住该键才能跳转,因为跳转会被_check_keyup_event取消。

_check_keyup_event 中删除 self.knight.jump_move = False:

def _check_keyup_event(self, event):
    """Respond to KEY releases"""
    if event.key == pygame.K_RIGHT:
        self.knight.moving_right = False
    elif event.key == pygame.K_LEFT:
        self.knight.moving_left = False

    # DELETE
    #elif event.key == pygame.K_SPACE:
    #    self.knight.jump_move = False

但是跳完了再做:

class Knight:
    # [...]

    def update(self):
        # [...]

         if self.jump_move:
            if self.jump_count >= -10:
                self.neg = 1
                if self.jump_count < 0:
                    self.neg = -1
                self.y -= (self.jump_count ** 2) * 0.5 * self.neg
                self.jump_count -= 1
            else:
                self.jump_count = 10
                self.jump_move = False # <------