Reputation: 103
I'm working on a pygame project but I'm having a few complications with the character's movement. The animation is not in sync (in lame terms), when I move right or left there is suppose to be an animation of the character moving left or right smoothly 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. I also have an issue when my character jumps it doesn't come back own. I tweaked the character speed and refresh rate of the screen but nothing seems to help. Here is my code and image below.
File 1. Handles the running of the game
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()
File2. Handles the game settings
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)
File 3. Handles the settings and attributes for my game character
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)
Images of game window when the character walks left or right: character walking left
Upvotes: 3
Views: 602
Reputation: 210968
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.
This because the first what you do in Knight.blitme
, is to draw the character in idle position. Then the left or right images is draw on top of it:
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
Jumping works only if the key is hold down, because jumping is canceled by _check_keyup_event
.
Remove self.knight.jump_move = False
from _check_keyup_event
:
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
But do it when the jump is finished:
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 # <------
Upvotes: 4