import pygame
#Colours used throughout the game
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
BackGround = ('D:\Idea 2\sky_colour_image.jpg', [0,0])
# Screen dimensions
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
#Player class
class Player(pygame.sprite.Sprite):
#Player image
def __init__(self):
super().__init__()
# Create an image of the block, and fill it with a color.
# This could also be an image loaded from the disk.
width = 40
height = 40
self.image = pygame.Surface([width, height])
self.image.fill(BLUE)
# Set a referance to the image rect.
self.rect = self.image.get_rect()
# Set speed vector of player
self.change_x = 0
self.change_y = 0
# List of sprites we can bump against
self.level = None
def update(self):
""" Move the player. """
# Gravity
self.calc_grav()
# Move left/right
self.rect.x += self.change_x
# See if we hit anything
block_hit_list = pygame.sprite.spritecollide(self,self.level.platform_list, False)
for block in block_hit_list:
# If we are moving right,
# set our right side to the left side of the item we hit
if self.change_x > 0:
self.rect.right = block.rect.left
elif self.change_x < 0:
# Otherwise if we are moving left, do the opposite.
self.rect.left = block.rect.right
# Move up/down
self.rect.y += self.change_y
# Check and see if we hit anything
block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
for block in block_hit_list:
# Reset our position based on the top/bottom of the object.
if self.change_y > 0:
self.rect.bottom = block.rect.top
elif self.change_y < 0:
self.rect.top = block.rect.bottom
# Stop our vertical movement
self.change_y = 0
def calc_grav(self):
if self.change_y == 0:
self.change_y = 1
else:
self.change_y += .35
# See if we are on the ground.
if self.rect.y >= SCREEN_HEIGHT - self.rect.height and self.change_y >= 0:
self.change_y = 0
self.rect.y = SCREEN_HEIGHT - self.rect.height
def jump(self):
# move down a bit and see if there is a platform below us.
# Move down 2 pixels because it doesn't work well if we only move down
# 1 when working with a platform moving down.
self.rect.y += 2
platform_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
self.rect.y -= 2
# If it is ok to jump, set our speed upwards
if len(platform_hit_list) > 0 or self.rect.bottom >= SCREEN_HEIGHT:
self.change_y = -10
# Player-controlled movement:
def go_left(self):
self.change_x = -6
def go_right(self):
self.change_x = 6
def stop(self):
self.change_x = 0
class Platform(pygame.sprite.Sprite):
def __init__(self, width, height):
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(GREEN)
self.rect = self.image.get_rect()
class Level(object):
def __init__(self, player):
self.platform_list = pygame.sprite.Group()
self.enemy_list = pygame.sprite.Group()
self.player = player
# Update everythign on this level
def update(self):
self.platform_list.update()
self.enemy_list.update()
def draw(self, screen):
# Draw the background
screen.fill(BLUE)
# Draw all the sprite lists that we have
self.platform_list.draw(screen)
self.enemy_list.draw(screen)
# Background class
class Background(pygame.sprite.Sprite):
def __init__(self, image_file, location):
pygame.sprite.Sprite.__init__(self) #call Sprite initializer
self.image = pygame.image.load("D:\Idea 2\sky_colour_image.jpg")
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
# Create platforms for the level
class Level_01(Level):
def __init__(self, player):
# Call the parent constructor
Level.__init__(self, player)
# Array with width, height, x, and y of platform
level = [[210, 70, 500, 500],
[210, 70, 200, 400],
[210, 70, 600, 300],
]
# Go through the array above and add platforms
for platform in level:
block = Platform(platform[0], platform[1])
block.rect.x = platform[2]
block.rect.y = platform[3]
block.player = self.player
self.platform_list.add(block)
def main():
pygame.init()
# Set the height and width of the screen
size = [SCREEN_WIDTH, SCREEN_HEIGHT]
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Platformer Jumper")
# Create the player
player = Player()
# Create all the levels
level_list = []
level_list.append( Level_01(player) )
# Set the current level
current_level_no = 0
current_level = level_list[current_level_no]
active_sprite_list = pygame.sprite.Group()
player.level = current_level
player.rect.x = 340
player.rect.y = SCREEN_HEIGHT - player.rect.height
active_sprite_list.add(player)
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
# -------- Main Program Loop -----------
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.go_left()
if event.key == pygame.K_RIGHT:
player.go_right()
if event.key == pygame.K_UP:
player.jump()
screen.fill([255, 255, 255])
screen.blit(BackGround.image, BackGround.rect)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT and player.change_x < 0:
player.stop()
if event.key == pygame.K_RIGHT and player.change_x > 0:
player.stop()
# Update the player.
active_sprite_list.update()
# Update items in the level
current_level.update()
# If the player gets near the right side, shift the world left (-x)
if player.rect.right > SCREEN_WIDTH:
player.rect.right = SCREEN_WIDTH
# If the player gets near the left side, shift the world right (+x)
if player.rect.left < 0:
player.rect.left = 0
current_level.draw(screen)
active_sprite_list.draw(screen)
# Limit to 60 frames per second
clock.tick(60)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
if __name__ == "__main__":
main()
So far this is supposed to be (nothing exciting yet) a simple platform jumper with sky backgrouns. Creating a game for a computing project, not that experienced in python. Aim to be adding in moving platforms etc soon, if anyone could help with that or the error I'd appreciate it.
Basically you are asking an object (looks like self here) and asking it for the image that is part of it. BUT the tuple doesn't have an attribute of image.
Not sure here, but I think you may have an indent error.
def __init__() should be indented since it is a method on your class. Python does not use curly braces, but space is significant.
Related
This is my Player class,
I currently have both players interacting with the walls (which is a separate class in the code but not pasted onto this question) but I need a way to prevent players from walking through each other just as players can't walk through walls. The issue is that I can use self.rect.right = block.rect.left to prevent the player from going through the wall when its right side touches the left side of the wall but I cannot use self.rect.right = self.rect.left to prevent player one from going through player 2 because it does not specify that one refers to player one and the other refers to player 2. Any suggestions would be appreciated.
class Player(pygame.sprite.Sprite):
# Constructor function
def __init__(self, x, y, colour):
# Call the parent's constructor
super().__init__()
# Set height, width
self.image = pygame.Surface([50, 50])
self.image.fill(colour)
# Make our top-left corner the passed-in location.
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
# Set speed vector
self.change_x = 0
self.change_y = 0
self.walls = None
def changespeed(self, x, y):
self.change_x += x
self.change_y += y
def update(self):
# Move left/right
self.rect.x += self.change_x
# Did this update cause us to hit a wall?
block_hit_list = pygame.sprite.spritecollide(self, self.walls, False)
for block in block_hit_list:
# If we are moving right, set our right side to the left side of
# the item we hit
if self.change_x > 0:
self.rect.right = block.rect.left
else:
# Otherwise if we are moving left, do the opposite.
self.rect.left = block.rect.right
# Move up/down
self.rect.y += self.change_y
# Check and see if we hit anything
block_hit_list = pygame.sprite.spritecollide(self, self.walls, False)
for block in block_hit_list:
# Reset our position based on the top/bottom of the object.
if self.change_y > 0:
self.rect.bottom = block.rect.top
else:
self.rect.top = block.rect.bottom
This is where I create the players as objects
P1 = Player(200, 200, BLUE)
P2 = Player(300, 300, WHITE)
P1.walls = wall_list
P2.walls = wall_list
all_sprite_list.add(P1)
all_sprite_list.add(P2)
Full code:
import pygame
import ctypes
user32 = ctypes.windll.user32
# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BLUE = (50, 50, 255)
# Screen dimensions
SCREEN_WIDTH = user32.GetSystemMetrics(78)#1600
SCREEN_HEIGHT = user32.GetSystemMetrics(79)#900
WALL_THICKNESS = 10
MAP_WIDTH = SCREEN_WIDTH - 300 #1300
MAP_HEIGHT = SCREEN_HEIGHT - 160 #700
HEIGHT = SCREEN_HEIGHT - MAP_HEIGHT
#START CORDS = 150, 150
class Player(pygame.sprite.Sprite):
# Constructor function
def __init__(self, x, y, colour):
# Call the parent's constructor
super().__init__()
# Set height, width
self.image = pygame.Surface([50, 50])
self.image.fill(colour)
# Make our top-left corner the passed-in location.
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
# Set speed vector
self.change_x = 0
self.change_y = 0
self.walls = None
def changespeed(self, x, y):
self.change_x += x
self.change_y += y
def update(self):
# Move left/right
self.rect.x += self.change_x
# Did this update cause us to hit a wall?
block_hit_list = pygame.sprite.spritecollide(self, self.walls, False)
for block in block_hit_list:
# If we are moving right, set our right side to the left side of
# the item we hit
if self.change_x > 0:
self.rect.right = block.rect.left
else:
# Otherwise if we are moving left, do the opposite.
self.rect.left = block.rect.right
# Move up/down
self.rect.y += self.change_y
# Check and see if we hit anything
block_hit_list = pygame.sprite.spritecollide(self, self.walls, False)
for block in block_hit_list:
# Reset our position based on the top/bottom of the object.
if self.change_y > 0:
self.rect.bottom = block.rect.top
else:
self.rect.top = block.rect.bottom
class Wall(pygame.sprite.Sprite):
def __init__(self, x, y, width, height):
# Call the parent's constructor
super().__init__()
# Make a blue wall, of the size specified in the parameters
self.image = pygame.Surface([width, height])
self.image.fill(BLUE)
# Make our top-left corner the passed-in location.
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
# Call this function so the Pygame library can initialize itself
pygame.init()
# Create an 800x600 sized screen
screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT], pygame.FULLSCREEN)
# Set the title of the window
pygame.display.set_caption('Haste')
# List to hold all the sprites
all_sprite_list = pygame.sprite.Group()
# Make the walls. (x_pos, y_pos, width, height)
wall_list = pygame.sprite.Group()
#--------------------------------------------------------------------WALLS
#OUTER WALL 700 1500 - 1490. 1300
wall = Wall(150, 150, WALL_THICKNESS, MAP_HEIGHT - 150)#map height (left verticle)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(160, 150, MAP_WIDTH, WALL_THICKNESS)#(top across)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(160, MAP_HEIGHT - 10, MAP_WIDTH, WALL_THICKNESS)#(bottom across)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(MAP_WIDTH + 150, 150, WALL_THICKNESS, MAP_HEIGHT - 150)#(right verticle)
wall_list.add(wall)
all_sprite_list.add(wall)
# Create the player paddle object
P1 = Player(200, 200, BLUE)
P2 = Player(300, 300, WHITE)
P1.walls = wall_list
P2.walls = wall_list
all_sprite_list.add(P1)
all_sprite_list.add(P2)
clock = pygame.time.Clock()
done = False
sped = 9
speed = -9
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
P1.changespeed(speed, 0)
if event.key == pygame.K_RIGHT:
P1.changespeed(sped, 0)
if event.key == pygame.K_UP:
P1.changespeed(0, speed)
if event.key == pygame.K_DOWN:
P1.changespeed(0, sped)
if event.key == pygame.K_a:
P2.changespeed(speed, 0)
if event.key == pygame.K_d:
P2.changespeed(sped, 0)
if event.key == pygame.K_w:
P2.changespeed(0, speed)
if event.key == pygame.K_s:
P2.changespeed(0, sped)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
P1.changespeed(sped, 0)
if event.key == pygame.K_RIGHT:
P1.changespeed(speed, 0)
if event.key == pygame.K_UP:
P1.changespeed(0, sped)
if event.key == pygame.K_DOWN:
P1.changespeed(0, speed)
if event.key == pygame.K_a:
P2.changespeed(sped, 0)
if event.key == pygame.K_d:
P2.changespeed(speed, 0)
if event.key == pygame.K_w:
P2.changespeed(0, sped)
if event.key == pygame.K_s:
P2.changespeed(0, speed)
all_sprite_list.update()
screen.fill(BLACK)
all_sprite_list.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
I cannot use self.rect.right = self.rect.left ...
Correct: you have to write your code to refer to each Player as appropriate. You cannot refer to both of them as self.
Very simply, you have to use the appropriate variables, such as:
P1.rect.right == P2.rect.left
Whether you design this as a loop through player pairings, or check each player in turn against each of the others, depends on your system design. For instance, given only two players, you simply write a loop that flips between the two players:
active, passive = P1, P2 # P1 is the currently active player
while run_game:
...
if active.rect.right == passive.rect.left:
... #avoid collision
...
# Switch active player (take turns) at end of loop
active, passive = passive, active
I following this tutorial and I have added class Opponent() to class Platform() as shown here. Next I have been trying to add groupcollide_and_loop_for to the complete code so that the opponent is removed when hit by the bullet. I have been looking at this question about using groupcollide within class Opponent() itself. I tried several ways to call groupcollide inside def main in while not done but I didn't get any results or any errors, it just didn't work.
groupcollide_and_loop_for:
collided_opponents = pygame.sprite.groupcollide(opponents, bullet_list, False, True)
for opponent, bullets in collided_opponents.items():
for bullet in bullets:
score += 1 # Increment the score.
opponent.lives -= 1 # Decrement the lives.
pygame.display.set_caption(str(score))
Deploy the groupcollide and for loop above to the code below:
import pygame
# Global constants
bulletpicture = pygame.image.load("bullet.png")
# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
# Screen dimensions
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
class Player(pygame.sprite.Sprite):
"""
This class represents the bar at the bottom that the player controls.
"""
# -- Methods
def __init__(self):
""" Constructor function """
# Call the parent's constructor
super().__init__()
# Create an image of the block, and fill it with a color.
# This could also be an image loaded from the disk.
width = 40
height = 60
self.image = pygame.Surface([width, height])
self.image.fill(RED)
# Set a referance to the image rect.
self.rect = self.image.get_rect()
# Set speed vector of player
self.change_x = 0
self.change_y = 0
# List of sprites we can bump against
self.level = None
def update(self):
""" Move the player. """
# Gravity
self.calc_grav()
# Move left/right
self.rect.x += self.change_x
# See if we hit anything
block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
for block in block_hit_list:
# If we are moving right,
# set our right side to the left side of the item we hit
if self.change_x > 0:
self.rect.right = block.rect.left
elif self.change_x < 0:
# Otherwise if we are moving left, do the opposite.
self.rect.left = block.rect.right
# Move up/down
self.rect.y += self.change_y
# Check and see if we hit anything
block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
for block in block_hit_list:
# Reset our position based on the top/bottom of the object.
if self.change_y > 0:
self.rect.bottom = block.rect.top
elif self.change_y < 0:
self.rect.top = block.rect.bottom
# Stop our vertical movement
self.change_y = 0
def calc_grav(self):
""" Calculate effect of gravity. """
if self.change_y == 0:
self.change_y = 1
else:
self.change_y += .35
# See if we are on the ground.
if self.rect.y >= SCREEN_HEIGHT - self.rect.height and self.change_y >= 0:
self.change_y = 0
self.rect.y = SCREEN_HEIGHT - self.rect.height
def jump(self):
""" Called when user hits 'jump' button. """
# move down a bit and see if there is a platform below us.
# Move down 2 pixels because it doesn't work well if we only move down 1
# when working with a platform moving down.
self.rect.y += 2
platform_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
self.rect.y -= 2
# If it is ok to jump, set our speed upwards
if len(platform_hit_list) > 0 or self.rect.bottom >= SCREEN_HEIGHT:
self.change_y = -10
# Player-controlled movement:
def go_left(self):
""" Called when the user hits the left arrow. """
self.change_x = -6
def go_right(self):
""" Called when the user hits the right arrow. """
self.change_x = 6
def stop(self):
""" Called when the user lets off the keyboard. """
self.change_x = 0
class Platform(pygame.sprite.Sprite):
""" Platform the user can jump on """
def __init__(self, width, height):
""" Platform constructor. Assumes constructed with user passing in
an array of 5 numbers like what's defined at the top of this code.
"""
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(GREEN)
self.rect = self.image.get_rect()
class Level():
""" This is a generic super-class used to define a level.
Create a child class for each level with level-specific
info. """
def __init__(self, player):
""" Constructor. Pass in a handle to player. Needed for when moving
platforms collide with the player. """
self.platform_list = pygame.sprite.Group()
self.enemy_list = pygame.sprite.Group()
self.player = player
# How far this world has been scrolled left/right
self.world_shift = 0
# Update everythign on this level
def update(self):
""" Update everything in this level."""
self.platform_list.update()
self.enemy_list.update()
def draw(self, screen):
""" Draw everything on this level. """
# Draw the background
screen.fill(BLUE)
# Draw all the sprite lists that we have
self.platform_list.draw(screen)
self.enemy_list.draw(screen)
def shift_world(self, shift_x):
""" When the user moves left/right and we need to scroll
everything: """
# Keep track of the shift amount
self.world_shift += shift_x
# Go through all the sprite lists and shift
for platform in self.platform_list:
platform.rect.x += shift_x
for enemy in self.enemy_list:
enemy.rect.x += shift_x
class Bullet(pygame.sprite.Sprite):
"""This class represents the bullet."""
def __init__(self,x,y):
super().__init__()
self.image = bulletpicture
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def update(self):
"""Move the bullet."""
self.rect.y -= 5
# Remove the bullet if it flies up off the screen
if self.rect.y < -12:
self.kill() # Remove the sprite from all sprite groups.
class Opponent(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("cowboy.png") #.convert()
self.rect = self.image.get_rect()
self.lives = 1
self.rect.x = 50
self.rect.y = 280
self.change_x = 1
self.change_y = 0
# List of sprites we can bump against
self.level = None
pass
def update(self):
if self.lives <= 0:
self.kill() # Remove the sprite from all sprite groups.
self.rect.x += self.change_x
if self.rect.x > 280:
self.change_x *= -1
self.rect.x += self.change_x
if self.rect.x < 0:
self.change_x *= -1
self.rect.x += self.change_x
pass
# Create platforms for the level
class Level_01(Level):
""" Definition for level 1. """
def __init__(self, player):
""" Create level 1. """
# Call the parent constructor
Level.__init__(self, player)
self.level_limit = -1000
# Array with width, height, x, and y of platform
level = [[210, 70, 500, 500],
[210, 70, 800, 400],
[210, 70, 1000, 500],
[210, 70, 1120, 280],
]
# Go through the array above and add platforms
for platform in level:
block = Platform(platform[0], platform[1])
block.rect.x = platform[2]
block.rect.y = platform[3]
block.player = self.player
self.platform_list.add(block)
for enemy in level:
opponent = Opponent()
opponent.rect.x = 150
opponent.rect.y = 280
opponent.player = self.player
self.enemy_list.add(opponent)
# Create platforms for the level
class Level_02(Level):
""" Definition for level 2. """
def __init__(self, player):
""" Create level 1. """
# Call the parent constructor
Level.__init__(self, player)
self.level_limit = -1000
# Array with type of platform, and x, y location of the platform.
level = [[210, 30, 450, 570],
[210, 30, 850, 420],
[210, 30, 1000, 520],
[210, 30, 1120, 280],
]
# Go through the array above and add platforms
for platform in level:
block = Platform(platform[0], platform[1])
block.rect.x = platform[2]
block.rect.y = platform[3]
block.player = self.player
self.platform_list.add(block)
def main():
""" Main Program """
pygame.init()
# Set the height and width of the screen
size = [SCREEN_WIDTH, SCREEN_HEIGHT]
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Side-scrolling Platformer")
# Create the player
player = Player()
# Create all the levels
level_list = []
level_list.append(Level_01(player))
level_list.append(Level_02(player))
# Set the current level
current_level_no = 0
current_level = level_list[current_level_no]
active_sprite_list = pygame.sprite.Group()
player.level = current_level
player.rect.x = 340
player.rect.y = SCREEN_HEIGHT - player.rect.height
active_sprite_list.add(player)
# --- NEW
bullet_list = pygame.sprite.Group()
player_list = pygame.sprite.Group()
player_list.add(player)
opponent = Opponent()
opponents = pygame.sprite.Group()
opponents.add(opponent)
score = 0
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
# -------- Main Program Loop -----------
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
# Click a mouse button to instantiate a bullet.
bullet = Bullet(player.rect.x,player.rect.y)
bullet_list.add(bullet)
active_sprite_list.add(bullet)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.go_left()
if event.key == pygame.K_RIGHT:
player.go_right()
if event.key == pygame.K_UP:
player.jump()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT and player.change_x < 0:
player.stop()
if event.key == pygame.K_RIGHT and player.change_x > 0:
player.stop()
# Update the player.
active_sprite_list.update()
# ----- The code commented below is what I tried in many ways
#collided_opponents = pygame.sprite.groupcollide(opponents, bullet_list, False, True)
#for opponent, bullets in collided_opponents.items():
# for bullet in bullets:
# score += 1 # Increment the score.
# opponent.lives -= 1 # Decrement the lives.
# pygame.display.set_caption(str(score))
# Update items in the level
current_level.update()
# If the player gets near the right side, shift the world left (-x)
if player.rect.right >= 500:
diff = player.rect.right - 500
player.rect.right = 500
current_level.shift_world(-diff)
# If the player gets near the left side, shift the world right (+x)
if player.rect.left <= 120:
diff = 120 - player.rect.left
player.rect.left = 120
current_level.shift_world(diff)
# If the player gets to the end of the level, go to the next level
current_position = player.rect.x + current_level.world_shift
if current_position < current_level.level_limit:
player.rect.x = 120
if current_level_no < len(level_list)-1:
current_level_no += 1
current_level = level_list[current_level_no]
player.level = current_level
# ALL CODE TO DRAW SHOULD GO BELOW THIS COMMENT
current_level.draw(screen)
active_sprite_list.draw(screen)
# ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT
# Limit to 60 frames per second
clock.tick(60)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# Be IDLE friendly. If you forget this line, the program will 'hang'
# on exit.
pygame.quit()
if __name__ == "__main__":
main()
I used print() to see position for opponent and bullet. And I found that opponent never change position.
After digging in code I found you create two opponents.
in main() you create opponent which is not added to active_sprite_list so it doesn't move and it isn't displayed but you use it to check collision
in Level_01() you create opponent which is added to active_sprite_list so it moves and it is displayed on screen but you don't use it to check collision.
Because you check collision with opponent which never move so it never collide with bullet.
In main() you have to remove
opponent = Opponent()
opponents = pygame.sprite.Group()
opponents.add(opponent)
and use
#opponents = level_list[current_level_no].enemy_list
opponents = current_level.enemy_list
And use it also when you change level
current_level_no += 1
current_level = level_list[current_level_no]
#opponents = level_list[current_level_no].enemy_list
opponents = current_level.enemy_list
When i move right using the right key, i accelerate to a max speed. When i release it, i do decelerate to a stop so that is fine. However, when moving left using the left key, and after releasing it, i continue moving at a fixed speed and then come to an abrupt stop after a short while. Any idea what could be wrong with my code?
The original code is from http://programarcadegames.com/python_examples/show_file.php?file=platform_jumper.py
import pygame
# Global constants
# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
# Screen dimensions
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
class Player(pygame.sprite.Sprite):
""" This class represents the bar at the bottom that the player
controls. """
# -- Methods
def __init__(self):
""" Constructor function """
# Call the parent's constructor
super().__init__()
# Create an image of the block, and fill it with a color.
# This could also be an image loaded from the disk.
width = 40
height = 60
self.image = pygame.Surface([width, height])
self.image.fill(RED)
# Set a referance to the image rect.
self.rect = self.image.get_rect()
# Set speed vector of player
self.xVel = 0
self.yVel = 0
# List of sprites we can bump against
self.level = None
def update(self):
""" Move the player. """
# Gravity
self.calc_grav()
# Move left/right
# See if we hit anything
block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
for block in block_hit_list:
# If we are moving right,
# set our right side to the left side of the item we hit
if self.xVel > 0:
self.rect.right = block.rect.left
elif self.xVel < 0:
# Otherwise if we are moving left, do the opposite.
self.rect.left = block.rect.right
# Move up/down
self.rect.y += self.yVel
# Check and see if we hit anything
block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
for block in block_hit_list:
# Reset our position based on the top/bottom of the object.
if self.yVel > 0:
self.rect.bottom = block.rect.top
elif self.yVel < 0:
self.rect.top = block.rect.bottom
# Stop our vertical movement
self.yVel = 0
def calc_grav(self):
""" Calculate effect of gravity. """
if self.yVel == 0:
self.yVel = 1
else:
self.yVel += .35
# See if we are on the ground.
if self.rect.y >= SCREEN_HEIGHT - self.rect.height and self.yVel >= 0:
self.yVel = 0
self.rect.y = SCREEN_HEIGHT - self.rect.height
def jump(self):
""" Called when user hits 'jump' button. """
# move down a bit and see if there is a platform below us.
# Move down 2 pixels because it doesn't work well if we only move down
# 1 when working with a platform moving down.
self.rect.y += 2
platform_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
self.rect.y -= 2
# If it is ok to jump, set our speed upwards
if len(platform_hit_list) > 0 or self.rect.bottom >= SCREEN_HEIGHT:
self.yVel = -10
class Platform(pygame.sprite.Sprite):
""" Platform the user can jump on """
def __init__(self, width, height):
""" Platform constructor. Assumes constructed with user passing in
an array of 5 numbers like what's defined at the top of this
code. """
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(GREEN)
self.rect = self.image.get_rect()
class Level(object):
""" This is a generic super-class used to define a level.
Create a child class for each level with level-specific
info. """
def __init__(self, player):
""" Constructor. Pass in a handle to player. Needed for when moving platforms
collide with the player. """
self.platform_list = pygame.sprite.Group()
self.enemy_list = pygame.sprite.Group()
self.player = player
# Background image
self.background = None
# Update everythign on this level
def update(self):
""" Update everything in this level."""
self.platform_list.update()
self.enemy_list.update()
def draw(self, screen):
""" Draw everything on this level. """
# Draw the background
screen.fill(BLUE)
# Draw all the sprite lists that we have
self.platform_list.draw(screen)
self.enemy_list.draw(screen)
# Create platforms for the level
class Level_01(Level):
""" Definition for level 1. """
def __init__(self, player):
""" Create level 1. """
# Call the parent constructor
Level.__init__(self, player)
# Array with width, height, x, and y of platform
level = [[210, 70, 500, 500],
[210, 70, 200, 400],
[210, 70, 600, 300],
]
# Go through the array above and add platforms
for platform in level:
block = Platform(platform[0], platform[1])
block.rect.x = platform[2]
block.rect.y = platform[3]
block.player = self.player
self.platform_list.add(block)
def main():
""" Main Program """
pygame.init()
# Set the height and width of the screen
size = [SCREEN_WIDTH, SCREEN_HEIGHT]
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Platformer Jumper")
# Create the player
player = Player()
# Create all the levels
level_list = []
level_list.append(Level_01(player))
# Set the current level
current_level_no = 0
current_level = level_list[current_level_no]
active_sprite_list = pygame.sprite.Group()
player.level = current_level
player.rect.x = 340
player.rect.y = SCREEN_HEIGHT - player.rect.height
active_sprite_list.add(player)
accel_x = 0
max_speed = 6
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
# -------- Main Program Loop -----------
while not done:
player_running = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
accel_x = -0.5
if event.key == pygame.K_RIGHT:
accel_x = 0.5
if event.key == pygame.K_SPACE:
player.jump()
elif event.type == pygame.KEYUP:
if event.key in (pygame.K_LEFT, pygame.K_RIGHT):
accel_x = 0
player.xVel += accel_x # Accelerate.
if abs(player.xVel) >= max_speed: # If max_speed is exceeded.
# Normalize the x_change and multiply it with the max_speed.
player.xVel = player.xVel / abs(player.xVel) * max_speed
# Decelerate if no key is pressed.
if accel_x == 0:
player.xVel *= 0.5
player.rect.x += player.xVel
# Update the player.
active_sprite_list.update()
# Update items in the level
current_level.update()
# If the player gets near the right side, shift the world left (-x)
if player.rect.right > SCREEN_WIDTH:
player.rect.right = SCREEN_WIDTH
# If the player gets near the left side, shift the world right (+x)
if player.rect.left < 0:
player.rect.left = 0
# ALL CODE TO DRAW SHOULD GO BELOW THIS COMMENT
current_level.draw(screen)
active_sprite_list.draw(screen)
# ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT
# Limit to 60 frames per second
clock.tick(60)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# Be IDLE friendly. If you forget this line, the program will 'hang'
# on exit.
pygame.quit()
if __name__ == "__main__":
main()
The isssue is caused, because the pygame.Rect operates with integral data:
The coordinates for Rect objects are all integers. [...]
When you do
player.rect.x += player.xVel
it is the same as you would do:
player.rect.x = int(player.rect.x + player.xVel)
The fraction part of player.xVel gets lost. The result of the addition operation is truncated and the player tends to the coordinate with the lower value (left).
Add a floating point x coordinate (self.px) to the class Player and use it to calculate the position of the player. Use round to set the integral rectangle position from self.px:
class Player(pygame.sprite.Sprite):
def __init__(self):
# [...]
# Set a referance to the image rect.
self.rect = self.image.get_rect()
self.px = self.rect.x
# [...]
def update(self):
# [...]
block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
for block in block_hit_list:
# If we are moving right,
# set our right side to the left side of the item we hit
if self.xVel > 0:
self.rect.right = block.rect.left
elif self.xVel < 0:
# Otherwise if we are moving left, do the opposite.
self.rect.left = block.rect.right
self.px = self.rect.x
def main():
# [...]
player.rect.x = 340
player.px = player.rect.x
# [...]
while not done:
# [...]
player.px += player.xVel
player.rect.x = round(player.px)
# [...]
This question already has answers here:
Problems getting pygame to show anything but a blank screen on Macos
(10 answers)
pygame installation issue in mac os
(5 answers)
Closed 2 years ago.
I run my code for my game and I get this error:
for event in pygame.event.get():
pygame.error: video system not initialized
This is my code here, I decided to post all of it incase there is another variable that is affecting it. I have looked online and only seen answers that say "You have no included pygame.init()"
import pygame
import random
import os
import sys
# Global constants
# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
# Screen dimensions
SCREEN_WIDTH = 1024
SCREEN_HEIGHT = 400
game_folder = os.path.dirname(__file__)
img_folder = os.path.join(game_folder, "PyGame Images")
class Player(pygame.sprite.Sprite):
"""
This class represents the bar at the bottom that the player controls.
"""
# -- Methods
def __init__(self):
""" Constructor function """
# Call the parent's constructor
super().__init__()
# Create an image of the block, and fill it with a color.
# This could also be an image loaded from the disk.
width = 40
height = 60
self.image = pygame.image.load(os.path.join(img_folder,"0.png")).convert()
self.image.set_colorkey(BLACK)
# Set a referance to the image rect.
self.rect = self.image.get_rect()
# Set speed vector of player
self.change_x = 0
self.change_y = 0
# List of sprites we can bump against
self.level = None
def update(self):
""" Move the player. """
# Gravity
self.calc_grav()
# Move left/right
self.rect.x += self.change_x
# See if we hit anything
block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
for block in block_hit_list:
# If we are moving right,
# set our right side to the left side of the item we hit
if self.change_x > 0:
self.rect.right = block.rect.left
elif self.change_x < 0:
# Otherwise if we are moving left, do the opposite.
self.rect.left = block.rect.right
# Move up/down
self.rect.y += self.change_y
# Check and see if we hit anything
block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
for block in block_hit_list:
# Reset our position based on the top/bottom of the object.
if self.change_y > 0:
self.rect.bottom = block.rect.top
elif self.change_y < 0:
self.rect.top = block.rect.bottom
# Stop our vertical movement
self.change_y = 0
def calc_grav(self):
""" Calculate effect of gravity. """
if self.change_y == 0:
self.change_y = 1
else:
self.change_y += .35
# See if we are on the ground.
if self.rect.y >= SCREEN_HEIGHT - self.rect.height and self.change_y >= 0:
self.change_y = 0
self.rect.y = SCREEN_HEIGHT - self.rect.height
def jump(self):
""" Called when user hits 'jump' button. """
# move down a bit and see if there is a platform below us.
# Move down 2 pixels because it doesn't work well if we only move down 1
# when working with a platform moving down.
self.rect.y += 2
platform_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
self.rect.y -= 2
# If it is ok to jump, set our speed upwards
if len(platform_hit_list) > 0 or self.rect.bottom >= SCREEN_HEIGHT:
self.change_y = -10
# Player-controlled movement:
def go_left(self):
""" Called when the user hits the A key. """
self.change_x = -6
def go_right(self):
""" Called when the user hits the D key. """
self.change_x = 6
def stop(self):
""" Called when the user lets off the keyboard. """
self.change_x = 0
class Platform(pygame.sprite.Sprite):
""" Platform the user can jump on """
def __init__(self, width, height):
""" Platform constructor. Assumes constructed with user passing in
an array of 5 numbers like what's defined at the top of this code.
"""
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(GREEN)
self.rect = self.image.get_rect()
return
class Level():
""" This is a generic super-class used to define a level.
Create a child class for each level with level-specific
info. """
def __init__(self, player):
""" Constructor. Pass in a handle to player. Needed for when moving
platforms collide with the player. """
self.platform_list = pygame.sprite.Group()
self.enemy_list = pygame.sprite.Group()
self.player = player
# How far this world has been scrolled left/right
self.world_shift = 0
# Update everythign on this level
def update(self):
""" Update everything in this level."""
self.platform_list.update()
self.enemy_list.update()
def draw(self, screen):
""" Draw everything on this level. """
# Draw the background
screen.fill(BLUE)
# Draw all the sprite lists that we have
self.platform_list.draw(screen)
self.enemy_list.draw(screen)
def shift_world(self, shift_x):
""" When the user moves left/right and we need to scroll
everything: """
# Keep track of the shift amount
self.world_shift += shift_x
# Go through all the sprite lists and shift
for platform in self.platform_list:
platform.rect.x += shift_x
for enemy in self.enemy_list:
enemy.rect.x += shift_x
# Create platforms for the level
class Level_01(Level):
""" Definition for level 1. """
def __init__(self, player):
""" Create level 1. """
# Call the parent constructor
Level.__init__(self, player)
self.level_limit = -1000
# Array with width, height, x, and y of platform
level = [[210, 70, 500, 500],
[210, 70, 800, 400],
[210, 70, 1000, 500],
[210, 70, 1120, 280],
]
# Go through the array above and add platforms
for platform in level:
block = Platform(platform[0], platform[1])
block.rect.x = platform[2]
block.rect.y = platform[3]
block.player = self.player
self.platform_list.add(block)
# Create platforms for the level
class Level_02(Level):
""" Definition for level 2. """
def __init__(self, player):
""" Create level 1. """
# Call the parent constructor
Level.__init__(self, player)
self.level_limit = -1000
# Array with type of platform, and x, y location of the platform.
level = [[210, 30, 450, 570],
[210, 30, 850, 420],
[210, 30, 1000, 520],
[210, 30, 1120, 280],
]
# Go through the array above and add platforms
for platform in level:
block = Platform(platform[0], platform[1])
block.rect.x = platform[2]
block.rect.y = platform[3]
block.player = self.player
self.platform_list.add(block)
def main():
""" Main Program """
pygame.init()
mouse.set.visible(True)
# Set the height and width of the screen
size = [SCREEN_WIDTH, SCREEN_HEIGHT]
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Dash Dojo")
# Create the player
player = Player()
# Create all the levels
level_list = []
level_list.append(Level_01(player))
level_list.append(Level_02(player))
# Set the current level
current_level_no = 0
current_level = level_list[current_level_no]
active_sprite_list = pygame.sprite.Group()
player.level = current_level
player.rect.x = 340
player.rect.y = SCREEN_HEIGHT - player.rect.height
active_sprite_list.add(player)
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
# -------- Main Program Loop -----------
player_images = []
player_images.append(pygame.image.load(os.path.join(img_folder,'15.png')))
player_images.append(pygame.image.load(os.path.join(img_folder,'16.png')))
player_images.append(pygame.image.load(os.path.join(img_folder,'17.png')))
player_images.append(pygame.image.load(os.path.join(img_folder,'18.png')))
player_images.append(pygame.image.load(os.path.join(img_folder,'19.png')))
player_images.append(pygame.image.load(os.path.join(img_folder,'20.png')))
player_images.append(pygame.image.load(os.path.join(img_folder,'21.png')))
player_images.append(pygame.image.load(os.path.join(img_folder,'22.png')))
player_images.append(pygame.image.load(os.path.join(img_folder,'23.png')))
player_images.append(pygame.image.load(os.path.join(img_folder,'24.png')))
player_current = 0
player = player_images[ player_current ]
playerX = 610
playerY = 350
walking = False
walking_steps = 0
# --- events ---
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
player_current = (player_current + 1) % len(player_images)
player = pygame.image.load(images_running[player_current])
player.go_left()
if event.key == pygame.K_d:
player.go_right()
if event.key == pygame.K_w:
player.jump()
if event.type == pygame.KEYUP:
if event.key == pygame.K_a and player.change_x < 0:
player.stop()
if event.key == pygame.K_d and player.change_x > 0:
player.stop()
# --- moves ---
if walking == True:
# here you need to check some counter
# if it is time for next step to walk slower
# but don't use `time.sleep()`
if walking_steps > 0:
player_current = (player_current + 1) % len(player_images)
player = player_images[ player_current ]
playerY = playerY + 1
walking_steps -= 1
else:
walking = False
# --- draws ---
screen.fill((0, 0, 0))
screen.blit(player, (playerX, playerY))
pygame.display.flip()
# Update the player
active_sprite_list.update()
# Update items in the level
current_level.update()
# If the player gets near the right side, shift the world left (-x)
if player.rect.right >= 500:
diff = player.rect.right - 500
player.rect.right = 500
current_level.shift_world(-diff)
# If the player gets near the left side, shift the world right (+x)
if player.rect.left <= 120:
diff = 120 - player.rect.left
player.rect.left = 120
current_level.shift_world(diff)
# If the player gets to the end of the level, go to the next level
current_position = player.rect.x + current_level.world_shift
if current_position < current_level.level_limit:
player.rect.x = 120
if current_level_no < len(level_list)-1:
current_level_no += 1
current_level = level_list[current_level_no]
player.level = current_level
# ALL CODE TO DRAW SHOULD GO BELOW THIS COMMENT
current_level.draw(screen)
active_sprite_list.draw(screen)
# ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT
# Limit to 60 frames per second
clock.tick(60)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# Be IDLE friendly. If you forget this line, the program will 'hang'
# on exit.
pygame.quit()
if __name__ == "__main__":
main()
When this part of the code has been run, it shows the sprite however when the arrow keys are pressed nothing moves, ive tried to use print statements to attempt to debug but nothing has come up, what is the issue and how do i solve it? Here ive added everything relating to the movement in my program the other files include the screen and the exit loop
from spritechanges import *
from lklk import *
import pygame
import time
WHITE = (255, 255, 255)
BLACK = (0, 0, 0, 0)
clock = pygame.time.Clock()
FPS = 120
# Create a surface/image and draw a circle onto it.
sprite_image = pygame.Surface((50, 50))
pygame.draw.circle(sprite_image, WHITE, [25, 25], 20)
# Create surface/image draw a line onto it
width = 40
height = 60
# Create an instance of the Sprite class.
class Sprite(pygame.sprite.Sprite):
def __init__(self, pos):
super(Sprite, self).__init__() # platform
self.width = width
self.height = height
self.platform = pygame.Surface((width, height))
self.platform.fill(WHITE)
# set a reference to the image rect
self.rect = self.platform.get_rect()
# Assign the global image to `self.image`.
self.image = sprite_image
# Create a rect which will be used as blit
# position and for the collision detection.
self.rect = self.image.get_rect()
# Set the rect's center to the passed `pos`.
self.rect.center = pos
self._vx = 0
self._vy = 0
# Assign the pos also to these attributes.
self._spritex = pos[0]
self._spritey = pos[1]
# set of sprites sprite can bump against
self.level = None
def update(self):
self._gravity = 99
block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
for block in block_hit_list:
if self._vx > 0:
self.rect.right = block.rect.left
elif self._vx < 0:
# Otherwise if we are moving left, do the opposite.
self.rect.left = block.rect.right
self.rect.y += self.change_y
# Check and see if we hit anything
block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
for block in block_hit_list:
# Reset our position based on the top/bottom of the object.
if self._vy > 0:
self.rect.bottom = block.rect.top
elif self._vy < 0:
self.rect.top = block.rect.bottom
# Stop our vertical movement
self._vy = 0
self._vx = 0
self.rect.y += 2
platform_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
self.rect.y -= 2
# If it is ok to jump, set our speed upwards
if len(platform_hit_list) > 0 or self.rect.bottom >= H:
self._xy = -10
# Player-controlled movement:
def go_left(self):
""" Called when the user hits the left arrow. """
self._vx = -6
def go_right(self):
""" Called when the user hits the right arrow. """
self._vx = 6
def stop(self):
""" Called when the user lets off the keyboard. """
self._vx = 0
# Adjust the position.
self._spritex += self._vx
self._spritey += self._vy
# And update the center of the rect.
self.rect.center = (self._spritex, self._spritey)
sprite = Sprite([400, 550])
active_sprite_list = pygame.sprite.Group()
sprite.level = current_level
sprite.rect.x = 340
sprite.rect.y = H - sprite.rect.height
active_sprite_list.add(sprite)
done = True
while not done:
events()
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
sprite.go_left()
if event.key == pygame.K_RIGHT:
sprite.go_right()
if event.key == pygame.K_UP:
sprite.jump()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT and sprite.change_x < 0:
sprite.stop()
if event.key == pygame.K_RIGHT and sprite.change_x > 0:
sprite.stop()
# If the player gets near the right side, shift the world left (-x)
if sprite.rect.right > W:
sprite.rect.right = W
# If the player gets near the left side, shift the world right (+x)
if sprite.rect.left < 0:
sprite.rect.left = 0
DS.fill(BLACK)
# Blit the sprite's image at the sprite's rect.topleft position.
DS.blit(sprite.image, sprite.rect)
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
There's some code in the stop method that should be in the update method. The jump code needs to be in a separate jump method. Also, call active_sprite_list.update() in the main while loop to update all contained sprites and active_sprite_list.draw(DS) to draw them. Here's a complete working example:
import pygame
pygame.init()
clock = pygame.time.Clock()
FPS = 60
DS = pygame.display.set_mode((640, 480))
sprite_image = pygame.Surface((50, 50), pygame.SRCALPHA)
pygame.draw.circle(sprite_image, (90, 100, 200), [25, 25], 25)
W, H = DS.get_size()
class Platform(pygame.sprite.Sprite):
def __init__(self, x, y, w, h):
super(Platform, self).__init__()
self.image = pygame.Surface((w, h))
self.image.fill((90, 90, 120))
self.rect = self.image.get_rect(topleft=(x, y))
class Sprite(pygame.sprite.Sprite):
def __init__(self, pos):
super(Sprite, self).__init__()
self.image = sprite_image
self.rect = self.image.get_rect()
self.rect.center = pos
self._vx = 0
self._vy = 0
self._spritex = pos[0]
self._spritey = pos[1]
self.level = None
self._gravity = .9
def update(self):
# Adjust the x-position.
self._spritex += self._vx
self.rect.centerx = self._spritex # And update the rect.
block_hit_list = pygame.sprite.spritecollide(self, self.level, False)
for block in block_hit_list:
if self._vx > 0:
self.rect.right = block.rect.left
elif self._vx < 0:
# Otherwise if we are moving left, do the opposite.
self.rect.left = block.rect.right
self._spritex = self.rect.centerx # Update the position.
# Adjust the y-position.
self._vy += self._gravity # Accelerate downwards.
self._spritey += self._vy
self.rect.centery = self._spritey # And update the rect.
# Check and see if we hit anything
block_hit_list = pygame.sprite.spritecollide(self, self.level, False)
for block in block_hit_list:
# Reset our position based on the top/bottom of the object.
if self._vy > 0:
self.rect.bottom = block.rect.top
elif self._vy < 0:
self.rect.top = block.rect.bottom
self._spritey = self.rect.centery # Update the position.
# Stop our vertical movement
self._vy = 0
def jump(self):
self.rect.y += 2
platform_hit_list = pygame.sprite.spritecollide(self, self.level, False)
self.rect.y -= 2
# If it is ok to jump, set our speed upwards
if len(platform_hit_list) > 0 or self.rect.bottom >= H:
self._vy = -17
def go_left(self):
""" Called when the user hits the left arrow. """
self._vx = -3
def go_right(self):
""" Called when the user hits the right arrow. """
self._vx = 3
def stop(self):
""" Called when the user lets off the keyboard. """
self._vx = 0
sprite = Sprite([60, 60])
active_sprite_list = pygame.sprite.Group(sprite)
sprite.level = pygame.sprite.Group(
Platform(20, 400, 200, 20), Platform(220, 300, 20, 120),
Platform(220, 300, 300, 20))
active_sprite_list.add(sprite.level)
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
sprite.go_left()
if event.key == pygame.K_RIGHT:
sprite.go_right()
if event.key == pygame.K_UP:
sprite.jump()
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT and sprite._vx < 0:
sprite.stop()
if event.key == pygame.K_RIGHT and sprite._vx > 0:
sprite.stop()
# If the player gets near the right side, shift the world left (-x)
if sprite.rect.right > W:
sprite.rect.right = W
# If the player gets near the left side, shift the world right (+x)
if sprite.rect.left < 0:
sprite.rect.left = 0
active_sprite_list.update()
DS.fill((50, 50, 50))
# Blit the sprite's image at the sprite's rect.topleft position.
active_sprite_list.draw(DS)
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
Is this the problem?
self._vx = 0
Whenever the user lets off the keyboard, you end up adjusting the position by zero?