I am trying to use pygame.KEYDOWN so that when I press the key represented by pygame.K_q the block that the player has collided with can be dragged (pick up) to where the player moves as it is done using pygame.MOUSEBUTTONDOWN in this tutorial.
But pressing the q key to drag the block does not work...
This need of mine arose when trying to implement this functionality in another larger code. So I decided to get this other tutorial2 to set up my MWE. I looked to see if anyone had already asked about it but I just found relative but not exact questions that used a very different or very large code structure and I still haven't figured out why I can't get my MWE code to work. This should be a simple question and someone may have already posted this question, so if so let me know where there is a question already posted that clarifies my question.
My MWE:
import pygame
import random
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
class Block(pygame.sprite.Sprite):
"""
This class represents the block to be picked up.
It derives from the "Sprite" class in Pygame.
"""
def __init__(self, color, width, height):
""" Constructor. Pass in the color of the block,
and its x and y position. """
# Call the parent class (Sprite) 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.
self.image = pygame.Surface([width, height])
self.image.fill(color)
# Fetch the rectangle object that has the dimensions of the image
# image.
# Update the position of this object by setting the values
# of rect.x and rect.y
self.rect = self.image.get_rect()
class Player(pygame.sprite.Sprite):
""" The class is the player-controlled sprite. """
carry_block_list = []
def __init__(self, x, y):
"""Constructor function"""
# Call the parent's constructor
super().__init__()
# Set height, width
self.image = pygame.Surface([15, 15])
self.image.fill(RED)
# Make our top-left corner the passed-in location.
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def update(self):
diff_x = self.rect.x - 4
diff_y = self.rect.y - 4
# Loop through each block that we are carrying and adjust
# it by the amount we moved.
for block in self.carry_block_list:
block.rect.x -= diff_x
block.rect.y -= diff_y
print("something")
# Call this function so the Pygame library can initialize itself
pygame.init()
# Create an 800x600 sized screen
screen_width = 700
screen_height = 400
screen = pygame.display.set_mode([screen_width, screen_height])
# Set the title of the window
pygame.display.set_caption('Move Sprite With Keyboard')
# Create the player paddle object
player = Player(50, 50)
all_sprites_list = pygame.sprite.Group()
all_sprites_list.add(player)
block_list = pygame.sprite.Group()
for i in range(50):
# This represents a block
block = Block(BLACK, 20, 15)
# Set a random location for the block
block.rect.x = random.randrange(screen_width)
block.rect.y = random.randrange(screen_height)
# Add the block to the list of objects
block_list.add(block)
all_sprites_list.add(block)
clock = pygame.time.Clock()
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_q:
print("pick up")
# When the mouse button is pressed, see if we are in contact with
# other sprites:
blocks_hit_list = pygame.sprite.spritecollide(player, block_list, False)
# Set the list of blocks we are in contact with as the list of
# blocks being carried.
player.carry_block_list = blocks_hit_list
if event.key == pygame.K_l:
print("let go")
# When we let up on the mouse, set the list of blocks we are
# carrying as empty.
player.carry_block_list = []
if event.key == pygame.K_LEFT:
player.rect.x -= player.rect.width
elif event.key == pygame.K_RIGHT:
player.rect.x += player.rect.width
elif event.key == pygame.K_UP:
player.rect.y -= player.rect.height
elif event.key == pygame.K_DOWN:
player.rect.y += player.rect.height
# -- Draw everything
# Clear screen
screen.fill(WHITE)
# Draw sprites
all_sprites_list.draw(screen)
# Flip screen
pygame.display.flip()
# Pause
clock.tick(40)
pygame.quit()
You move blocks in Player.update() but you never execute it
First I tried to execute this function in every loop but finally I changed this function to run only when players is moved
def update(self, diff_x, diff_y):
# Loop through each block that we are carrying and adjust
# it by the amount we moved.
for block in self.carry_block_list:
block.rect.x += diff_x
block.rect.y += diff_y
and
if event.key == pygame.K_LEFT:
player.rect.x -= player.rect.width
player.update(-player.rect.width, 0)
elif event.key == pygame.K_RIGHT:
player.rect.x += player.rect.width
player.update(player.rect.width, 0)
elif event.key == pygame.K_UP:
player.rect.y -= player.rect.height
player.update(0, -player.rect.height)
elif event.key == pygame.K_DOWN:
player.rect.y += player.rect.height
player.update(0, player.rect.height)
Full code:
import pygame
import random
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
class Block(pygame.sprite.Sprite):
"""
This class represents the block to be picked up.
It derives from the "Sprite" class in Pygame.
"""
def __init__(self, color, width, height):
""" Constructor. Pass in the color of the block,
and its x and y position. """
# Call the parent class (Sprite) 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.
self.image = pygame.Surface([width, height])
self.image.fill(color)
# Fetch the rectangle object that has the dimensions of the image
# image.
# Update the position of this object by setting the values
# of rect.x and rect.y
self.rect = self.image.get_rect()
class Player(pygame.sprite.Sprite):
""" The class is the player-controlled sprite. """
carry_block_list = []
def __init__(self, x, y):
"""Constructor function"""
# Call the parent's constructor
super().__init__()
# Set height, width
self.image = pygame.Surface([15, 15])
self.image.fill(RED)
# Make our top-left corner the passed-in location.
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def update(self, diff_x, diff_y):
# Loop through each block that we are carrying and adjust
# it by the amount we moved.
for block in self.carry_block_list:
block.rect.x += diff_x
block.rect.y += diff_y
# Call this function so the Pygame library can initialize itself
pygame.init()
# Create an 800x600 sized screen
screen_width = 700
screen_height = 400
screen = pygame.display.set_mode([screen_width, screen_height])
# Set the title of the window
pygame.display.set_caption('Move Sprite With Keyboard')
# Create the player paddle object
player = Player(50, 50)
all_sprites_list = pygame.sprite.Group()
all_sprites_list.add(player)
block_list = pygame.sprite.Group()
for i in range(50):
# This represents a block
block = Block(BLACK, 20, 15)
# Set a random location for the block
block.rect.x = random.randrange(screen_width)
block.rect.y = random.randrange(screen_height)
# Add the block to the list of objects
block_list.add(block)
all_sprites_list.add(block)
clock = pygame.time.Clock()
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_p:
# When the mouse button is pressed, see if we are in contact with
# other sprites:
blocks_hit_list = pygame.sprite.spritecollide(player, block_list, False)
# Set the list of blocks we are in contact with as the list of
# blocks being carried.
player.carry_block_list = blocks_hit_list
if event.key == pygame.K_l:
# When we let up on the mouse, set the list of blocks we are
# carrying as empty.
player.carry_block_list = []
if event.key == pygame.K_LEFT:
player.rect.x -= player.rect.width
player.update(-player.rect.width, 0)
elif event.key == pygame.K_RIGHT:
player.rect.x += player.rect.width
player.update(player.rect.width, 0)
elif event.key == pygame.K_UP:
player.rect.y -= player.rect.height
player.update(0, -player.rect.height)
elif event.key == pygame.K_DOWN:
player.rect.y += player.rect.height
player.update(0, player.rect.height)
# -- Draw everything
# Clear screen
screen.fill(WHITE)
# Draw sprites
all_sprites_list.draw(screen)
# Flip screen
pygame.display.flip()
# Pause
clock.tick(40)
pygame.quit()
Related
I just edited below to simplify, and update my problems status.
I have made a simple enemy class called 'Wolf'. Before I pulled this text out into a new file, my main file ran with no errors.
IF I TRY TO IMPORT ONLY WOLF:
from Enemy Import Wolf
I get the following:
ImportError: cannot import name 'Wolf' from 'Enemy'
Below are all of my files.
When I run my main program, the game runs but crashes when I close it and gives me an error.
Enemy.py
import pygame
import random
import Colors
class Wolf(pygame.sprite.Sprite):
def __init__(self, color, width, height):
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(color)
self.rect = self.image.get_rect()
Main_Game_File.py
import pygame
import random
import Colors
import Player
import Enemy
# Initialize Pygame
pygame.init()
# Set the height and width of the screen
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode([screen_width, screen_height])
#SPRITE LIST CREATIONS
wolf_list = pygame.sprite.Group()
poison_wolf_list = pygame.sprite.Group()
# This is a list of every sprite.
# All blocks and the player block as well.
all_sprites_list = pygame.sprite.Group()
for i in range(50):
# This represents a single block
wolf = Wolf(Colors.GREEN, 20, 15)
# Set a random location for the block
wolf.rect.x = random.randrange(screen_width)
wolf.rect.y = random.randrange(screen_height)
# Add the block to the list of objects
wolf_list.add(wolf)
all_sprites_list.add(wolf)
for i in range(50):
# This represents a single block
wolf = Wolf(Colors.RED, 20, 15)
# Set a random location for the block
wolf.rect.x = random.randrange(screen_width)
wolf.rect.y = random.randrange(screen_height)
# Add the block to the list of objects
poison_wolf_list.add(wolf)
all_sprites_list.add(wolf)
#Since this will repeat 50 times, you will create 50 red blocks
#This adds all 50 blocks to the bad_block_list, and the all_sprites_list.
# Create a RED player block
player = Player.Player(100, 100)
all_sprites_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()
score = 0
# -------- Main Program Loop -----------
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# Set the speed based on the key pressed
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
player.changespeed(-3, 0)
elif event.key == pygame.K_d:
player.changespeed(3, 0)
elif event.key == pygame.K_w:
player.changespeed(0, -3)
elif event.key == pygame.K_s:
player.changespeed(0, 3)
# Reset speed when key goes up
elif event.type == pygame.KEYUP:
if event.key == pygame.K_a:
player.changespeed(3, 0)
elif event.key == pygame.K_d:
player.changespeed(-3, 0)
elif event.key == pygame.K_w:
player.changespeed(0, 3)
elif event.key == pygame.K_s:
player.changespeed(0, -3)
# Clear the screen
screen.fill(Colors.WHITE)
# Game Logic
all_sprites_list.update()
# See if the player block has collided with anything.
wolf_list = pygame.sprite.spritecollide(player, wolf_list, True)
poison_wolf_list = pygame.sprite.spritecollide(player, poison_wolf_list, True)
# Check the list of collisions.
for block in wolf_list:
score += 1
print(score)
for block in poison_wolf_list:
score -= 1
print(score)
# Draw all the spites
all_sprites_list.draw(screen)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# Limit to 60 frames per second
clock.tick(60)
pygame.quit()
Player.py
import pygame
import random
import Colors
class Player(pygame.sprite.Sprite):
""" The class is the player-controlled sprite. """
# -- Methods
def __init__(self, x, y):
"""Constructor function"""
# Call the parent's constructor
super().__init__()
# Set height, width
self.image = pygame.Surface([15, 15])
self.image.fill(Colors.BLUE)
# Make our top-left corner the passed-in location.
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# -- Attributes
# Set speed vector
self.change_x = 0
self.change_y = 0
def changespeed(self, x, y):
""" Change the speed of the player"""
self.change_x += x
self.change_y += y
def update(self):
""" Find a new position for the player"""
self.rect.x += self.change_x
self.rect.y += self.change_y
Colors
# Colors
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = ( 0, 225, 0)
BLUE = ( 0, 0, 225)
In Main_Game_File.py lines 91/92, you're overwriting the Groups with lists.
Use Enemy.Wolf for the imports and change those lines.
wolf_list_2 = pygame.sprite.spritecollide(player, wolf_list, True)
poison_wolf_list_2 = pygame.sprite.spritecollide(player, poison_wolf_list, True)
# Check the list of collisions.
for block in wolf_list_2:
score += 1
print(score)
for block in poison_wolf_list_2:
score -= 1
print(score)
# Draw all the spites
all_sprites_list.draw(screen)
You simply need to prefix it with the module import name.
import Enemy
# [...]
mr_wolf = Enemy.Wolf(Colors.GREEN, 20, 15) # <-- HERE
Or use the import * notation:
from Enemy import * # <-- HERE
# [...]
mr_wolf = Wolf(Colors.GREEN, 20, 15) # (no change)
How modules are imported changes the naming scope.
Or of course, you can import only Wolf from Enemy too:
from Enemy import Wolf # <-- HERE
# [...]
mr_wolf = Wolf(Colors.GREEN, 20, 15) # (no change)
EDIT: Example files:
Enemy.py ~
import pygame
class Wolf(pygame.sprite.Sprite):
def __init__(self, color, width, height):
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(color)
self.rect = self.image.get_rect()
def __str__( self ):
return "Wolf at (%d,%d) size %dx%d" % ( self.rect.x, self.rect.y, self.rect.width, self.rect.height )
main.py ~
import Enemy
YELLOW = ( 255, 255, 0 )
mr_wolf = Enemy.Wolf( YELLOW, 10, 10)
print( str( mr_wolf ) )
Which gives:
# python3 ./main.py
pygame 1.9.4.post1
Hello from the pygame community. https://www.pygame.org/contribute.html
Wolf at (0,0) size 10x10
I am having troubles with an assignment for school and my teacher doesn't know enough about coding to help me.
The link to the assignment is here:
http://programarcadegames.com/index.php?lang=en&chapter=lab_sprite_moving
I got to step 6 on the assignment where it wants me to make the green blocks move but I cant seem to figure out how to make the update method work (I called it update_good in my code).
When I try the run the code it comea up with the error AttributeError: 'Group' object has no attribute 'update_good'
Here is my code
import pygame
import random
import block_library
import good_block_library
A_Block = block_library.Block
A_Good_Block = good_block_library.good_block
# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
class Player(pygame.sprite.Sprite):
""" The class is the player-controlled sprite. """
# -- Methods
def __init__(self, x, y):
"""Constructor function"""
# Call the parent's constructor
super().__init__()
# Set height, width
self.image = pygame.Surface([15, 15])
self.image.fill(BLUE)
# Make our top-left corner the passed-in location.
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# -- Attributes
# Set speed vector
self.change_x = 0
self.change_y = 0
def changespeed(self, x, y):
""" Change the speed of the player"""
self.change_x += x
self.change_y += y
def update(self):
""" Find a new position for the player"""
self.rect.x += self.change_x
self.rect.y += self.change_y
# Initialize Pygame
pygame.init()
# Set the height and width of the screen
screen_width = 700
screen_height = 400
screen = pygame.display.set_mode([screen_width, screen_height])
bump_sound = pygame.mixer.Sound("bump.wav")
good_sound = pygame.mixer.Sound("good_block.wav")
bad_sound = pygame.mixer.Sound("bad_block.wav")
# This is a list of 'sprites.' Each block in the program is
# added to this list. The list is managed by a class called 'Group.'
good_block_list = pygame.sprite.Group()
bad_block_list = pygame.sprite.Group()
# This is a list of every sprite.
# All blocks and the player block as well.
all_sprites_list = pygame.sprite.Group()
for i in range(50):
# This represents a block
A_Good_Block = A_Block(GREEN, 20, 15)
# Set a random location for the block
A_Good_Block.rect.x = random.randrange(screen_width)
A_Good_Block.rect.y = random.randrange(screen_height)
# Add the block to the list of objects
good_block_list.add(A_Good_Block)
all_sprites_list.add(A_Good_Block)
for i in range(50):
# This represents a block
bad_block = A_Block(RED, 20, 15)
# Set a random location for the block
bad_block.rect.x = random.randrange(screen_width)
bad_block.rect.y = random.randrange(screen_height)
# Add the block to the list of objects
bad_block_list.add(bad_block)
all_sprites_list.add(bad_block)
# Create a player block
player = Player(10, 15)
all_sprites_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()
score = 0
# -------- Main Program Loop -----------
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:
player.changespeed(-3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, -3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, 3)
# Reset speed when key goes up
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.changespeed(3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(-3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, 3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, -3)
# Clear the screen
screen.fill(WHITE)
#!!!! this is where the problem occurs v
good_block_list.update_good()
all_sprites_list.update()
# See if the player block has collided with anything.
blocks_hit_list = pygame.sprite.spritecollide(player, good_block_list, True)
blocks_hit_list2 = pygame.sprite.spritecollide(player, bad_block_list, True)
# Check the list of collisions.
for block in blocks_hit_list:
score += 1
good_sound.play()
for block in blocks_hit_list2:
score-= 1
bad_sound.play()
font = pygame.font.SysFont('Calibri', 25, True, False)
text = font.render("Score: " + str(score), True, BLACK)
screen.blit(text, [30, 350])
# Draw all the spites
all_sprites_list.draw(screen)
if player.rect.y == 0 or player.rect.y == 399:
bump_sound.play()
if player.rect.x == 1 or player.rect.x == 700:
bump_sound.play()
# update the screen
pygame.display.flip()
# Limit to 60 frames per second
clock.tick(60)
pygame.quit()
Below is the program I import that contains the good_block class and the update_good function. I think the problem might be in here
def main():
pass
if __name__ == '__main__':
main()
import pygame
import block_library
import random
GREEN = (0, 255, 0)
screen_width = 700
screen_height = 400
A_Block = block_library.Block
change_x = random.randint(-3,3)
change_y = random.randint(-3,3)
good_block_list = pygame.sprite.Group()
all_sprites_list = pygame.sprite.Group()
class good_block(A_Block):
def changespeed(self, x, y):
""" Change the speed of the player"""
self.change_x += x
self.change_y += y
def update_good(self):
self.rect.x += self.change_x
self.rect.y += self.change_y
Below is the library has the class that A_good_block is inherited from
import pygame
import random
class Block(pygame.sprite.Sprite):
"""
This class represents the ball.
It derives from the "Sprite" class in Pygame.
"""
def __init__(self, color, width, height):
""" Constructor. Pass in the color of the block,
and its x and y position. """
# Call the parent class (Sprite) 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.
self.image = pygame.Surface([width, height])
self.image.fill(color)
# Fetch the rectangle object that has the dimensions of the image
# image.
# Update the position of this object by setting the values
# of rect.x and rect.y
self.rect = self.image.get_rect()
self.change_x = random.randint(-3,3)
self.change_y = random.randint(-3,3)
Please help
The problem is that you don't fully understand what you're code is doing.
The reason why the code all_sprites_list.update() works is because that method is actually defined for that object. You have a pygame Group object which has it's own methods that you can read about here: https://www.pygame.org/docs/ref/sprite.html#pygame.sprite.Group.
What you'll find is that the update() method is there but there isn't any update_good() method. The docs say that the update() method calls the update() method off every Sprite contained in it.
So it seems simple, just change update_good() to update() and then call the update() method of the Group and it will work.
I am working through the programarcadegames labs using python and pygame and I am stuck. When I am running this code, I am doing something wrong when I am initializing the block and player classes. The player class is supposed to be its own class and not an instance of Block class.
When I run this program, I am getting this error:
'Block' object has no attribute 'changespeed'
import pygame
import random
# Define some colors
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
class Block(pygame.sprite.Sprite):
def __init__(self, color, width, height):
""" Constructor. Pass in the color of the block,
and its x and y position. """
# Call the parent class (Sprite) 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.
self.image = pygame.Surface([width, height])
self.image.fill(color)
# Fetch the rectangle object that has the dimensions of the image
# image.
# Update the position of this object by setting the values
# of rect.x and rect.y
self.rect = self.image.get_rect()
class Player (pygame.sprite.Sprite):
""" The class is the player-controlled sprite. """
def __init__(self,x,y):
"""Constructor function"""
# Call the parent's constructor
super().__init__()
# -- methods
# Set height, width
self.image = pygame.Surface([15, 15])
self.image.fill(BLACK)
# Make our top-left corner the passed-in location.
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# -- Attributes
# Set speed vector
self.change_x = 0
self.change_y = 0
def changespeed(self, x, y):
""" Change the speed of the player"""
self.change_x += x
self.change_y += y
def update(self):
""" Find a new position for the player"""
self.rect.x += self.change_x
self.rect.y += self.change_y
# Initialize Pygame
pygame.init()
# Set the height and width of the screen
screen_width = 700
screen_height = 400
screen = pygame.display.set_mode([screen_width, screen_height])
# This is a list of 'sprites.' Each block in the program is
# added to this list. The list is managed by a class called 'Group.'
block_list = pygame.sprite.Group()
# This is a list of every sprite.
# All blocks and the player block as well.
all_sprites_list = pygame.sprite.Group()
for i in range(50):
# This represents a block
block = Block(BLACK, 20, 15)
# Set a random location for the block
block.rect.x = random.randrange(screen_width)
block.rect.y = random.randrange(screen_height)
# Add the block to the list of objects
block_list.add(block)
all_sprites_list.add(block)
# Create a RED player block
player = Block(BLUE, 20, 15)
all_sprites_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()
score = 0
# -------- Main Program Loop -----------
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# Set the speed based on the key pressed
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.changespeed(-3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, -3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, 3)
# Reset speed when key goes up
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.changespeed(3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(-3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, 3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, -3)
# Clear the screen
screen.fill(WHITE)
# Get the current mouse position. This returns the position
# as a list of two numbers.
#pos = pygame.mouse.get_pos()
# Fetch the x and y out of the list,
# just like we'd fetch letters out of a string.
# Set the player object to the mouse location
#player.rect.x = pos[0]
#player.rect.y = pos[1]
# See if the player block has collided with anything.
blocks_hit_list = pygame.sprite.spritecollide(player, block_list, True)
# Check the list of collisions.
for block in blocks_hit_list:
score += 1
print(score)
# This calls update on all the sprites
all_sprites_list.update()
# Draw all the spites
all_sprites_list.draw(screen)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# Limit to 60 frames per second
clock.tick(60)
pygame.quit()
Here's the problem: player = Block(BLUE, 20, 15). The player is a Block instance not a Player instance and blocks have got no changespeed method.
I am currently working on a square collecting game in which the User/Player will be a blue square that can only collect squares that are smaller than the player's square. These are represented by color, if the square is smaller than the player than it is green, if it is bigger it will be red.
I have run into a problem where I can not figure out how to INCREASE THE SIZE of the Player when the player collides with the green squares. I have tried a number of different things that don't seem to work and would appreciate some different options to try and accomplish this task.
Here is the code that I am currently using:
import pygame
import random
# Define some colors
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
class Block(pygame.sprite.Sprite):
"""
This class represents the ball.
It derives from the "Sprite" class in Pygame.
"""
def __init__(self, color, width, height):
""" Constructor. Pass in the color of the block,
and its x and y position. """
# Call the parent class (Sprite) 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.
self.image = pygame.Surface([width, height])
self.image.fill(color)
# Fetch the rectangle object that has the dimensions of the image
# image.
# Update the position of this object by setting the values
# of rect.x and rect.y
self.rect = self.image.get_rect()
class Player(pygame.sprite.Sprite):
""" The class is the player-controlled sprite. """
# -- Methods
def __init__(self, x, y):
"""Constructor function"""
# Call the parent's constructor
super().__init__()
# Set height, width
self.image = pygame.Surface([15, 15])
self.image.fill(BLUE)
# Make our top-left corner the passed-in location.
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# -- Attributes
# Set speed vector
self.change_x = 0
self.change_y = 0
def changespeed(self, x, y):
""" Change the speed of the player"""
self.change_x += x
self.change_y += y
def update(self):
""" Find a new position for the player"""
# move left or right
self.rect.x += self.change_x
if self.rect.x <= 0:
self.rect.x = 1
wall_sound.play()
if self.rect.x >= 680:
self.rect.x = 679
wall_sound.play()
# move up or down
self.rect.y += self.change_y
if self.rect.y <= 0:
self.rect.y = 1
wall_sound.play()
if self.rect.y >= 385:
self.rect.y = 384
wall_sound.play()
# Initialize Pygame
pygame.init()
# Set the height and width of the screen
screen_width = 700
screen_height = 400
screen = pygame.display.set_mode([screen_width, screen_height])
# This is a list of 'sprites.' Each block in the program is
# added to this list. The list is managed by a class called 'Group.'
block_list = pygame.sprite.Group()
# This is a list of every sprite.
# All blocks and the player block as well.
all_sprites_list = pygame.sprite.Group()
# Create a BLUE player block
p_width = 30
p_height = 25
p_size = (p_width, p_height)
player = Player(p_width, p_height)
all_sprites_list.add(player)
# BLOCK LIST
for i in range(50):
width = random.randrange(20, 50)
height = width - 5
b_size = (width, height)
if b_size <= p_size:
color = GREEN
if b_size > p_size:
color = RED
# This represents a block
block = Block(color, width, height)
# Set a random location for the block
block.rect.x = random.randrange(screen_width - width)
block.rect.y = random.randrange(screen_height - height)
# Add the block to the list of objects
block_list.add(block)
all_sprites_list.add(block)
# Loop until the user clicks the close button.
done = False
# Pygame sound effects
collect_good = pygame.mixer.Sound("SnowWalk.ogg")
collect_bad = pygame.mixer.Sound("icebreaks.ogg")
wall_sound = pygame.mixer.Sound("evillaugh.ogg")
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
font = pygame.font.Font(None, 25)
score = 0
# -------- Main Program Loop -----------
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# Set the speed based on the key pressed
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.changespeed(-3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, -3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, 3)
# Reset speed when key goes up
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.changespeed(3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(-3, 0)
eli
# See if the player block has collided with anything.
#good
blocks_hit_list = pygame.sprite.spritecollide(player, block_list, True)
# Check the list of collisions.
#good
for block in blocks_hit_list:
score += 1
collect_good.play()
if score <= -1:
done = True
# Draw all the spites
all_sprites_list.draw(screen)
text = font.render("Score: " + str(score), True, BLACK)
screen.blit(text, [20, 300])
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# Limit to 60 frames per second
clock.tick(60)
pygame.quit()f event.key == pygame.K_UP:
player.changespeed(0, 3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, -3)
# This calls update on all the sprites
all_sprites_list.update()
# Clear the screen
screen.fill(WHITE)
# See if the player block has collided with anything.
#good
blocks_hit_list = pygame.sprite.spritecollide(player, block_list, True)
# Check the list of collisions.
#good
for block in blocks_hit_list:
score += 1
collect_good.play()
if score <= -1:
done = True
# Draw all the spites
all_sprites_list.draw(screen)
text = font.render("Score: " + str(score), True, BLACK)
screen.blit(text, [20, 300])
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# Limit to 60 frames per second
clock.tick(60)
pygame.quit()
Make the player constructor take the width and height as well as the x and y. In the collision check, increase these and create a new image for the player with the new increased x and y values. Don't forget to reset the player rect at the same time as well.
Also, you are passing the width and height in and using them as x and y not width and height.
hey guys, was trying to build pacman using pygame, have a small problem. When the pacman is moving if i press a key then it changes direction, unfortunately if there is a wall above then the pacman stops at that place and points upwards until i change the direction. I want help with how to find out if the block 3 or 4 units of pacman.rect.y belongs to sprite group level which has all the walls and stuff ..
Here's a longer example of a working game with walls:
# Sample Python/Pygame Programs
# Simpson College Computer Science
# http://cs.simpson.edu/?q=python_pygame_examples
import pygame
black = (0,0,0)
white = (255,255,255)
blue = (0,0,255)
# This class represents the bar at the bottom that the player controls
class Wall(pygame.sprite.Sprite):
# Constructor function
def __init__(self,x,y,width,height):
# Call the parent's constructor
pygame.sprite.Sprite.__init__(self)
# 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.top = y
self.rect.left = x
# This class represents the bar at the bottom that the player controls
class Player(pygame.sprite.Sprite):
# Set speed vector
change_x=0
change_y=0
# Constructor function
def __init__(self,x,y):
# Call the parent's constructor
pygame.sprite.Sprite.__init__(self)
# Set height, width
self.image = pygame.Surface([15, 15])
self.image.fill(white)
# Make our top-left corner the passed-in location.
self.rect = self.image.get_rect()
self.rect.top = y
self.rect.left = x
# Change the speed of the player
def changespeed(self,x,y):
self.change_x+=x
self.change_y+=y
# Find a new position for the player
def update(self,walls):
# Get the old position, in case we need to go back to it
old_x=self.rect.left
new_x=old_x+self.change_x
self.rect.left = new_x
# Did this update cause us to hit a wall?
collide = pygame.sprite.spritecollide(self, walls, False)
if collide:
# Whoops, hit a wall. Go back to the old position
self.rect.left=old_x
old_y=self.rect.top
new_y=old_y+self.change_y
self.rect.top = new_y
# Did this update cause us to hit a wall?
collide = pygame.sprite.spritecollide(self, walls, False)
if collide:
# Whoops, hit a wall. Go back to the old position
self.rect.top=old_y
score = 0
# Call this function so the Pygame library can initialize itself
pygame.init()
# Create an 800x600 sized screen
screen = pygame.display.set_mode([800, 600])
# Set the title of the window
pygame.display.set_caption('Test')
# Create a surface we can draw on
background = pygame.Surface(screen.get_size())
# Used for converting color maps and such
background = background.convert()
# Fill the screen with a black background
background.fill(black)
# Create the player paddle object
player = Player( 50,50 )
movingsprites = pygame.sprite.RenderPlain()
movingsprites.add(player)
# Make the walls. (x_pos, y_pos, width, height)
wall_list=pygame.sprite.RenderPlain()
wall=Wall(0,0,10,600)
wall_list.add(wall)
wall=Wall(10,0,790,10)
wall_list.add(wall)
wall=Wall(10,200,100,10)
wall_list.add(wall)
clock = pygame.time.Clock()
done = False
while done == False:
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.changespeed(-3,0)
if event.key == pygame.K_RIGHT:
player.changespeed(3,0)
if event.key == pygame.K_UP:
player.changespeed(0,-3)
if event.key == pygame.K_DOWN:
player.changespeed(0,3)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.changespeed(3,0)
if event.key == pygame.K_RIGHT:
player.changespeed(-3,0)
if event.key == pygame.K_UP:
player.changespeed(0,3)
if event.key == pygame.K_DOWN:
player.changespeed(0,-3)
player.update(wall_list)
screen.fill(black)
movingsprites.draw(screen)
wall_list.draw(screen)
pygame.display.flip()
clock.tick(40)
pygame.quit()
You could use:
http://www.pygame.org/docs/ref/sprite.html#pygame.sprite.spritecollide
pacman.rect.y = pacman.rect.y - 3
colliding = pygame.sprite.spritecollide(pacman, level)
if colliding:
can_move_upwards = False
else:
can_move_upwards = True
pacman.rect.y = pacman.rect.y + 3
And do the same for every direction you want to test.