I'm very new to python and pygame and I was trying to make a top-down shooter style game. I managed to get many components working but I cant get the blocks that I shoot at to show up in the rooms I created in the game. I moved the code for it to the game function and it shows up on screen but when you move between rooms they stay the same, for the time being I commented that part out. I want each room to have their own blocks that I can shoot, but when I try putting the code into each room class it does not show up on the screen. I'm pretty sure nothing is drawn over it. I want to know why the walls are being drawn but not the blocks. Any help is appreciated.
import pygame, sys, math, random
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
PURPLE = (255, 0, 255)
click = False
# Call this function so the Pygame library can initialize itself
pygame.init()
# Create an 800x600 sized screen
WIDTH = 800
HEIGHT = 600
screen = pygame.display.set_mode([WIDTH, HEIGHT])
# Set the title of the window
pygame.display.set_caption('Maze Runner')
class Wall(pygame.sprite.Sprite):
def __init__(self, x, y, width, height, color):
# 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(color)
# Make our top-left corner the passed-in location.
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
class Block(pygame.sprite.Sprite):
def __init__(self, color):
# Call the parent class (Sprite) constructor
super().__init__()
self.image = pygame.Surface([20, 20])
self.image.fill(color)
self.rect = self.image.get_rect()
class Player(pygame.sprite.Sprite):
# Set speed vector
change_x = 0
change_y = 0
def __init__(self, x, y):
# Call the parent's constructor
super().__init__()
# 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.y = y
self.rect.x = x
def changespeed(self, x, y):
self.change_x += x
self.change_y += y
def move(self, walls):
# 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, 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, 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 Bullet(pygame.sprite.Sprite):
def __init__(self, start_x, start_y, dest_x, dest_y):
# Call the parent class (Sprite) constructor
super().__init__()
# Set up the image for the bullet
self.image = pygame.Surface([5, 5])
self.image.fill(BLUE)
self.rect = self.image.get_rect()
# Move the bullet to our starting location
self.rect.x = start_x
self.rect.y = start_y
# Because rect.x and rect.y are automatically converted
# to integers, we need to create different variables that
# store the location as floating point numbers. Integers
# are not accurate enough for aiming.
self.floating_point_x = start_x
self.floating_point_y = start_y
# Calculation the angle in radians between the start points
# and end points. This is the angle the bullet will travel.
x_diff = dest_x - start_x
y_diff = dest_y - start_y
angle = math.atan2(y_diff, x_diff);
# Taking into account the angle, calculate our change_x
# and change_y. Velocity is how fast the bullet travels.
velocity = 5
self.change_x = math.cos(angle) * velocity
self.change_y = math.sin(angle) * velocity
def update(self):
""" Move the bullet. """
# The floating point x and y hold our more accurate location.
self.floating_point_y += self.change_y
self.floating_point_x += self.change_x
# The rect.x and rect.y are converted to integers.
self.rect.y = int(self.floating_point_y)
self.rect.x = int(self.floating_point_x)
# If the bullet flies of the screen, get rid of it.
if self.rect.x < 0 or self.rect.x > WIDTH or self.rect.y < 0 or self.rect.y > HEIGHT:
self.kill()
class Room(object):
# Each room has a list of walls, and of enemy sprites.
wall_list = None
enemy_sprites = None
block_list = None
def __init__(self):
""" Constructor, create our lists. """
self.wall_list = pygame.sprite.Group()
self.enemy_sprites = pygame.sprite.Group()
self.block_list = pygame.sprite.Group()
self.movingsprites = pygame.sprite.Group()
class Room1(Room):
def __init__(self):
super().__init__()
# Make the walls. (x_pos, y_pos, width, height)
# This is a list of walls. Each is in the form [x, y, width, height]
walls = [[0, 0, 20, 250, WHITE],
[0, 350, 20, 250, WHITE],
[780, 0, 20, 250, WHITE],
[780, 350, 20, 250, WHITE],
[20, 0, 760, 20, WHITE],
[20, 580, 760, 20, WHITE],
[390, 50, 20, 500, BLUE]
]
# Loop through the list. Create the wall, add it to the list
for item in walls:
wall = Wall(item[0], item[1], item[2], item[3], item[4])
self.wall_list.add(wall)
for i in range(10):
# This represents a block
block = Block(GREEN)
# Set a random location for the block
block.rect.x = random.randrange(WIDTH - 50)
block.rect.y = random.randrange(HEIGHT - 50)
# Add the block to the list of objects
self.block_list.add(block)
self.movingsprites.add(block)
class Room2(Room):
def __init__(self):
super().__init__()
walls = [[0, 0, 20, 250, RED],
[0, 350, 20, 250, RED],
[780, 0, 20, 250, RED],
[780, 350, 20, 250, RED],
[20, 0, 760, 20, RED],
[20, 580, 760, 20, RED],
[190, 50, 20, 500, GREEN],
[590, 50, 20, 500, GREEN]
]
for item in walls:
wall = Wall(item[0], item[1], item[2], item[3], item[4])
self.wall_list.add(wall)
block = Block(RED)
block.rect.x = 200
block.rect.y = 200
self.block_list.add(block)
self.movingsprites.add(block)
class Room3(Room):
def __init__(self):
super().__init__()
walls = [[0, 0, 20, 250, PURPLE],
[0, 350, 20, 250, PURPLE],
[780, 0, 20, 250, PURPLE],
[780, 350, 20, 250, PURPLE],
[20, 0, 760, 20, PURPLE],
[20, 580, 760, 20, PURPLE]
]
for item in walls:
wall = Wall(item[0], item[1], item[2], item[3], item[4])
self.wall_list.add(wall)
for x in range(100, 800, 100):
for y in range(50, 451, 300):
wall = Wall(x, y, 20, 200, RED)
self.wall_list.add(wall)
for x in range(150, 700, 100):
wall = Wall(x, 200, 20, 200, WHITE)
self.wall_list.add(wall)
def draw_text(text, font, color, surface, x, y):
textobj = font.render(text, 1, color)
textrect = textobj.get_rect()
textrect.topleft = (x, y)
surface.blit(textobj, textrect)
def main_menu():
done = False
while not done:
font = pygame.font.SysFont('Calibri', 20, True, False)
clock = pygame.time.Clock()
screen.fill(BLACK)
draw_text('main menu', font, WHITE, screen, 20, 20)
mx, my = pygame.mouse.get_pos()
button_1 = pygame.Rect(50, 100, 200, 50)
if button_1.collidepoint((mx, my)):
if click:
game()
pygame.draw.rect(screen, RED, button_1)
draw_text('Play', font, WHITE, screen, 60, 110)
click = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
done = True
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
click = True
pygame.display.flip()
clock.tick(60)
pygame.quit()
def game():
# Create the player paddle object
player = Player(50, 50)
movingsprites = pygame.sprite.Group()
movingsprites.add(player)
bullet_list = pygame.sprite.Group()
walls = pygame.sprite.Group()
wall_list = pygame.sprite.Group()
block_list = pygame.sprite.Group()
#for i in range(10):
## This represents a block
#block = Block(GREEN)
## Set a random location for the block
#block.rect.x = random.randrange(WIDTH - 50)
#block.rect.y = random.randrange(HEIGHT - 50)
## Add the block to the list of objects
#block_list.add(block)
#movingsprites.add(block)
rooms = []
room = Room1()
rooms.append(room)
room = Room2()
rooms.append(room)
room = Room3()
rooms.append(room)
current_room_no = 0
current_room = rooms[current_room_no]
clock = pygame.time.Clock()
done = False
while not done:
# --- Event Processing ---
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(-5, 0)
if event.key == pygame.K_RIGHT:
player.changespeed(5, 0)
if event.key == pygame.K_UP:
player.changespeed(0, -5)
if event.key == pygame.K_DOWN:
player.changespeed(0, 5)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
done = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.changespeed(5, 0)
if event.key == pygame.K_RIGHT:
player.changespeed(-5, 0)
if event.key == pygame.K_UP:
player.changespeed(0, 5)
if event.key == pygame.K_DOWN:
player.changespeed(0, -5)
if event.type == pygame.MOUSEBUTTONDOWN:
# Fire a bullet if the user clicks the mouse button
# Get the mouse position
pos = pygame.mouse.get_pos()
mouse_x = pos[0]
mouse_y = pos[1]
# Create the bullet based on where we are, and where we want to go.
bullet = Bullet(player.rect.x, player.rect.y, mouse_x, mouse_y)
# Add the bullet to the lists
movingsprites.add(bullet)
bullet_list.add(bullet)
# --- Game Logic ---
player.move(current_room.wall_list)
movingsprites.update()
if player.rect.x < -15:
if current_room_no == 0:
current_room_no = 2
current_room = rooms[current_room_no]
player.rect.x = 790
elif current_room_no == 2:
current_room_no = 1
current_room = rooms[current_room_no]
player.rect.x = 790
else:
current_room_no = 0
current_room = rooms[current_room_no]
player.rect.x = 790
if player.rect.x > WIDTH + 1:
if current_room_no == 0:
current_room_no = 1
current_room = rooms[current_room_no]
player.rect.x = 0
elif current_room_no == 1:
current_room_no = 2
current_room = rooms[current_room_no]
player.rect.x = 0
else:
current_room_no = 0
current_room = rooms[current_room_no]
player.rect.x = 0
for bullet in bullet_list:
# See if it hit a block
block_hit_list = pygame.sprite.spritecollide(bullet, block_list, True)
# For each block hit, remove the bullet and add to the score
for block in block_hit_list:
bullet_list.remove(bullet)
movingsprites.remove(bullet)
# Remove the bullet if it flies up off the screen
if bullet.rect.y < -10:
bullet_list.remove(bullet)
movingsprites.remove(bullet)
# --- Drawing ---
screen.fill(BLACK)
block_list.draw(screen)
movingsprites.draw(screen)
current_room.wall_list.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
if __name__ == "__main__":
main_menu()
Sorry about the long code, this is my first time asking a question here. Once again any help is appreciated.
You need to make the blocks list a property of the room class, and then draw them in draw. Notice how in draw, I call
current_room.block_list.draw(screen)
So is this what you mean:
import pygame, sys, math, random
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
PURPLE = (255, 0, 255)
click = False
# Call this function so the Pygame library can initialize itself
pygame.init()
# Create an 800x600 sized screen
WIDTH = 800
HEIGHT = 600
screen = pygame.display.set_mode([WIDTH, HEIGHT])
# Set the title of the window
pygame.display.set_caption('Maze Runner')
class Wall(pygame.sprite.Sprite):
def __init__(self, x, y, width, height, color):
# 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(color)
# Make our top-left corner the passed-in location.
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
class Block(pygame.sprite.Sprite):
def __init__(self, color):
# Call the parent class (Sprite) constructor
super().__init__()
self.image = pygame.Surface([20, 20])
self.image.fill(color)
self.rect = self.image.get_rect()
class Player(pygame.sprite.Sprite):
# Set speed vector
change_x = 0
change_y = 0
def __init__(self, x, y):
# Call the parent's constructor
super().__init__()
# 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.y = y
self.rect.x = x
def changespeed(self, x, y):
self.change_x += x
self.change_y += y
def move(self, walls):
# 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, 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, 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 Bullet(pygame.sprite.Sprite):
def __init__(self, start_x, start_y, dest_x, dest_y):
# Call the parent class (Sprite) constructor
super().__init__()
# Set up the image for the bullet
self.image = pygame.Surface([5, 5])
self.image.fill(BLUE)
self.rect = self.image.get_rect()
# Move the bullet to our starting location
self.rect.x = start_x
self.rect.y = start_y
# Because rect.x and rect.y are automatically converted
# to integers, we need to create different variables that
# store the location as floating point numbers. Integers
# are not accurate enough for aiming.
self.floating_point_x = start_x
self.floating_point_y = start_y
# Calculation the angle in radians between the start points
# and end points. This is the angle the bullet will travel.
x_diff = dest_x - start_x
y_diff = dest_y - start_y
angle = math.atan2(y_diff, x_diff);
# Taking into account the angle, calculate our change_x
# and change_y. Velocity is how fast the bullet travels.
velocity = 5
self.change_x = math.cos(angle) * velocity
self.change_y = math.sin(angle) * velocity
def update(self):
""" Move the bullet. """
# The floating point x and y hold our more accurate location.
self.floating_point_y += self.change_y
self.floating_point_x += self.change_x
# The rect.x and rect.y are converted to integers.
self.rect.y = int(self.floating_point_y)
self.rect.x = int(self.floating_point_x)
# If the bullet flies of the screen, get rid of it.
if self.rect.x < 0 or self.rect.x > WIDTH or self.rect.y < 0 or self.rect.y > HEIGHT:
self.kill()
class Room(object):
# Each room has a list of walls, and of enemy sprites.
wall_list = None
enemy_sprites = None
block_list = None
def __init__(self):
""" Constructor, create our lists. """
self.wall_list = pygame.sprite.Group()
self.enemy_sprites = pygame.sprite.Group()
self.block_list = pygame.sprite.Group()
self.movingsprites = pygame.sprite.Group()
for i in range(10):
# This represents a block
block = Block(GREEN)
# Set a random location for the block
block.rect.x = random.randrange(WIDTH - 50)
block.rect.y = random.randrange(HEIGHT - 50)
# Add the block to the list of objects
self.block_list.add(block)
self.movingsprites.add(block)
class Room1(Room):
def __init__(self):
super().__init__()
# Make the walls. (x_pos, y_pos, width, height)
# This is a list of walls. Each is in the form [x, y, width, height]
walls = [[0, 0, 20, 250, WHITE],
[0, 350, 20, 250, WHITE],
[780, 0, 20, 250, WHITE],
[780, 350, 20, 250, WHITE],
[20, 0, 760, 20, WHITE],
[20, 580, 760, 20, WHITE],
[390, 50, 20, 500, BLUE]
]
# Loop through the list. Create the wall, add it to the list
for item in walls:
wall = Wall(item[0], item[1], item[2], item[3], item[4])
self.wall_list.add(wall)
for i in range(10):
# This represents a block
block = Block(GREEN)
# Set a random location for the block
block.rect.x = random.randrange(WIDTH - 50)
block.rect.y = random.randrange(HEIGHT - 50)
# Add the block to the list of objects
self.block_list.add(block)
self.movingsprites.add(block)
class Room2(Room):
def __init__(self):
super().__init__()
walls = [[0, 0, 20, 250, RED],
[0, 350, 20, 250, RED],
[780, 0, 20, 250, RED],
[780, 350, 20, 250, RED],
[20, 0, 760, 20, RED],
[20, 580, 760, 20, RED],
[190, 50, 20, 500, GREEN],
[590, 50, 20, 500, GREEN]
]
for item in walls:
wall = Wall(item[0], item[1], item[2], item[3], item[4])
self.wall_list.add(wall)
block = Block(RED)
block.rect.x = 200
block.rect.y = 200
self.block_list.add(block)
self.movingsprites.add(block)
class Room3(Room):
def __init__(self):
super().__init__()
walls = [[0, 0, 20, 250, PURPLE],
[0, 350, 20, 250, PURPLE],
[780, 0, 20, 250, PURPLE],
[780, 350, 20, 250, PURPLE],
[20, 0, 760, 20, PURPLE],
[20, 580, 760, 20, PURPLE]
]
for item in walls:
wall = Wall(item[0], item[1], item[2], item[3], item[4])
self.wall_list.add(wall)
for x in range(100, 800, 100):
for y in range(50, 451, 300):
wall = Wall(x, y, 20, 200, RED)
self.wall_list.add(wall)
for x in range(150, 700, 100):
wall = Wall(x, 200, 20, 200, WHITE)
self.wall_list.add(wall)
def draw_text(text, font, color, surface, x, y):
textobj = font.render(text, 1, color)
textrect = textobj.get_rect()
textrect.topleft = (x, y)
surface.blit(textobj, textrect)
def main_menu():
done = False
while not done:
font = pygame.font.SysFont('Calibri', 20, True, False)
clock = pygame.time.Clock()
screen.fill(BLACK)
draw_text('main menu', font, WHITE, screen, 20, 20)
mx, my = pygame.mouse.get_pos()
button_1 = pygame.Rect(50, 100, 200, 50)
if button_1.collidepoint((mx, my)):
if click:
game()
pygame.draw.rect(screen, RED, button_1)
draw_text('Play', font, WHITE, screen, 60, 110)
click = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
done = True
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
click = True
pygame.display.flip()
clock.tick(60)
pygame.quit()
def game():
# Create the player paddle object
player = Player(50, 50)
movingsprites = pygame.sprite.Group()
movingsprites.add(player)
bullet_list = pygame.sprite.Group()
walls = pygame.sprite.Group()
wall_list = pygame.sprite.Group()
block_list = pygame.sprite.Group()
rooms = []
room = Room1()
rooms.append(room)
room = Room2()
rooms.append(room)
room = Room3()
rooms.append(room)
current_room_no = 0
current_room = rooms[current_room_no]
clock = pygame.time.Clock()
done = False
while not done:
# --- Event Processing ---
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(-5, 0)
if event.key == pygame.K_RIGHT:
player.changespeed(5, 0)
if event.key == pygame.K_UP:
player.changespeed(0, -5)
if event.key == pygame.K_DOWN:
player.changespeed(0, 5)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
done = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.changespeed(5, 0)
if event.key == pygame.K_RIGHT:
player.changespeed(-5, 0)
if event.key == pygame.K_UP:
player.changespeed(0, 5)
if event.key == pygame.K_DOWN:
player.changespeed(0, -5)
if event.type == pygame.MOUSEBUTTONDOWN:
# Fire a bullet if the user clicks the mouse button
# Get the mouse position
pos = pygame.mouse.get_pos()
mouse_x = pos[0]
mouse_y = pos[1]
# Create the bullet based on where we are, and where we want to go.
bullet = Bullet(player.rect.x, player.rect.y, mouse_x, mouse_y)
# Add the bullet to the lists
movingsprites.add(bullet)
bullet_list.add(bullet)
# --- Game Logic ---
player.move(current_room.wall_list)
movingsprites.update()
if player.rect.x < -15:
if current_room_no == 0:
current_room_no = 2
current_room = rooms[current_room_no]
player.rect.x = 790
elif current_room_no == 2:
current_room_no = 1
current_room = rooms[current_room_no]
player.rect.x = 790
else:
current_room_no = 0
current_room = rooms[current_room_no]
player.rect.x = 790
if player.rect.x > WIDTH + 1:
if current_room_no == 0:
current_room_no = 1
current_room = rooms[current_room_no]
player.rect.x = 0
elif current_room_no == 1:
current_room_no = 2
current_room = rooms[current_room_no]
player.rect.x = 0
else:
current_room_no = 0
current_room = rooms[current_room_no]
player.rect.x = 0
for bullet in bullet_list:
# See if it hit a block
block_hit_list = pygame.sprite.spritecollide(bullet, block_list, True)
# For each block hit, remove the bullet and add to the score
for block in block_hit_list:
bullet_list.remove(bullet)
movingsprites.remove(bullet)
# Remove the bullet if it flies up off the screen
if bullet.rect.y < -10:
bullet_list.remove(bullet)
movingsprites.remove(bullet)
# --- Drawing ---
screen.fill(BLACK)
current_room.block_list.draw(screen)
movingsprites.draw(screen)
current_room.wall_list.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
if __name__ == "__main__":
main_menu()
Also, if you change the collision detection to this:
for bullet in bullet_list:
# See if it hit a block
block_hit_list = pygame.sprite.spritecollide(bullet, current_room.block_list, True)
It will detect bullet hits against the rooms blocks
I'm looking to make some enemies in my game drop "UP Points" (Upgrade Points in the form of small yellow squares) when I shoot them. I've tried a few different things but can't seem to figure out how to spawn these collectable points in place of where an enemy just died. Does anyone have any ideas about how I could implement this?
UP class:
class Up(pygame.sprite.Sprite):
def __init__(self, color):
super().__init__()
self.image = pygame.Surface([5, 5])
self.image.fill(color)
self.rect = self.image.get_rect()
Here's the loop for when an enemy gets shot and dies:
for bullet in bullet_list: #For each bullet:
# Whenever a bullet collides with a zombie,
block_hit_list = pygame.sprite.spritecollide(bullet, zombie_list, True)
for i in block_hit_list:
# Destroy the bullet and zombie and add to the score
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
score += 100
Sorry for not posting my whole code, the main game loop is at the bottom :)
import pygame
import math
import random
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
ORANGE = (255, 119, 0)
ZOMBIE_GREEN = (122, 172, 34)
YELLOW = (255, 255, 0)
cursor_x = 100
cursor_y = 100
class Player(pygame.sprite.Sprite):
def __init__(self, color):
super().__init__()
# pygame.Surface will create a rectangle with the width and height given
# and the command below it tells it to fill it in with that color
self.image = pygame.Surface([15, 15])
self.image.fill(color)
self.rect = self.image.get_rect()
# This defines the starting position (x, y)
# of whatever sprite is passed through
self.rect.x = 600
self.rect.y = 300
# This is the current speed it will move when drawn
self.change_x = 0
self.change_y = 0
self.walls = None
# Defines how the player will move
def movement(self, x, y):
self.change_x += x
self.change_y += y
# Updates the information so the screen shows the player moving
def update(self):
self.rect.x += self.change_x
block_hit_list = pygame.sprite.spritecollide(self, self.walls, False)
for block in block_hit_list:
if self.change_x > 0:
self.rect.right = block.rect.left
else:
self.rect.left = block.rect.right
self.rect.y += self.change_y
block_hit_list = pygame.sprite.spritecollide(self, self.walls, False)
for block in block_hit_list:
if self.change_y > 0:
self.rect.bottom = block.rect.top
else:
self.rect.top = block.rect.bottom
class Enemy(pygame.sprite.Sprite):
def __init__(self, color):
super().__init__()
self.image = pygame.Surface([20, 20])
self.image.fill(color)
self.rect = self.image.get_rect()
self.pos_x = self.rect.x = random.randrange(35, screen_width - 35)
self.pos_y = self.rect.y = random.randrange(35, screen_height - 135)
# How Zombies move towards player
def update(self):
zombie_vec_x = self.rect.x - player.rect.x
zombie_vec_y = self.rect.y - player.rect.y
vec_length = math.sqrt(zombie_vec_x ** 2 + zombie_vec_y ** 2)
if self.rect.x != player.rect.x and self.rect.y != player.rect.y:
zombie_vec_x = (zombie_vec_x / vec_length) * 1 # These numbers determine
zombie_vec_y = (zombie_vec_y / vec_length) * 1 # zombie movement speed
self.pos_x -= zombie_vec_x
self.pos_y -= zombie_vec_y
self.rect.x = self.pos_x
self.rect.y = self.pos_y
block_hit_list = pygame.sprite.spritecollide(self, sprites_list, False)
for block in block_hit_list:
if self.rect.x > 0:
self.rect.right = block.rect.left
elif self.rect.x < 0:
self.rect.left = block.rect.right
elif self.rect.y > 0:
self.rect.bottom = block.rect.top
else:
self.rect.top = block.rect.bottom
class Wall(pygame.sprite.Sprite):
def __init__(self, color, x, y, width, height):
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(color)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
class Cursor(pygame.sprite.Sprite):
def __init__(self, width, height):
self.groups = all_sprites_list
self._layer = 1
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([width, height])
self.image.fill(RED)
self.rect = self.image.get_rect()
self.walls = None
# This updates the cursor to move along with your
# mouse position (defined in control logic)
def update(self):
self.rect.x = cursor_x
self.rect.y = cursor_y
class Bullet(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface([8, 8])
self.image.fill(ORANGE)
self.rect = self.image.get_rect()
# Instead of using the rect. positions, we'll use pos_ variables
# to calculate position. This is because the rect. uses integers
# while a variable can have exact float numbers. This will keep
# the bullets trajectory exact istead of useing a general
# (rounded) whole number <3
self.pos_x = player.rect.x + 4 # Set up pos_x and pos_y here
self.pos_y = player.rect.y + 4 # rather than rect.x and rect.y
self.walls = None
self.change_x = 0
self.change_y = 0
speed = 6
bullet_vec_x = (cursor.rect.x - 4) - player.rect.x
bullet_vec_y = (cursor.rect.y - 4) - player.rect.y
vec_length = math.sqrt(bullet_vec_x ** 2 + bullet_vec_y ** 2)
bullet_vec_x = (bullet_vec_x / vec_length) * speed
bullet_vec_y = (bullet_vec_y / vec_length) * speed
self.change_x += bullet_vec_x
self.change_y += bullet_vec_y
def update(self):
self.pos_x += self.change_x # Update pos_x and pos_y. They will become floats
self.pos_y += self.change_y # which will let them maintain sub-pixel accuracy.
self.rect.x = self.pos_x # Copy the pos values into the rect, where they will be
self.rect.y = self.pos_y # rounded off. That's OK since we never read them back.
pygame.init()
screen_size = pygame.display.Info()
size = (1300, 720)
screen = pygame.display.set_mode(size)
#size = (screen_size.current_w, screen_size.current_h)
#screen = pygame.display.set_mode(
# ((screen_size.current_w, screen_size.current_h)),pygame.FULLSCREEN
# )
screen_width = screen_size.current_w
screen_height = screen_size.current_h
pygame.display.set_caption("Zombie Shooter")
wall_list = pygame.sprite.Group()
zombie1_list = pygame.sprite.Group()
sprites_list = pygame.sprite.Group()
bullet_list = pygame.sprite.Group()
all_sprites_list = pygame.sprite.Group()
# Walls are made here = (x_coord for where it starts,
# y_coord for where it starts, width of wall, height of wall)
# These walls are made with fullscreen dimentions, not any set dimentions
# Left
wall = Wall(BLUE, 0, 0, 10, screen_height)
wall_list.add(wall)
all_sprites_list.add(wall)
# Top
wall = Wall(BLUE, 0, 0, screen_width, 10)
wall_list.add(wall)
all_sprites_list.add(wall)
# Bottom
wall = Wall(BLUE, 0, screen_height - 10, screen_width, 10)
wall_list.add(wall)
all_sprites_list.add(wall)
# Right
wall = Wall(BLUE, screen_width - 10, 0, 10, screen_width)
wall_list.add(wall)
all_sprites_list.add(wall)
# HUD Border
wall = Wall(BLUE, 0, screen_height - 100, screen_width, 10)
wall_list.add(wall)
all_sprites_list.add(wall)
# This creates the actual player with the parameters set in ( ).
# However, we must add the player to the all_sprites_list
# so that it will actually be drawn to the screen with the draw command
# placed right after the screen.fill(BLACK) command.
player = Player(WHITE)
player.walls = wall_list
all_sprites_list.add(player)
zombie = Enemy(ZOMBIE_GREEN)
zombie.walls = wall_list
for i in range(5):
zombie = Enemy(ZOMBIE_GREEN)
all_sprites_list.add(zombie)
zombie1_list.add(zombie)
sprites_list.add(zombie)
cursor = Cursor(7, 7)
cursor.walls = wall_list
all_sprites_list.add(cursor)
bullet = Bullet()
font = pygame.font.SysFont("crushed", 30)
score = 0
up_score = 0
done = False
clock = pygame.time.Clock()
pygame.mouse.set_visible(0)
# -------- Main Program Loop -----------
while not done:
# --- Main event loop ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# Press 'P' to quit the game_____
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_p:
done = True
#________________________________
# Keyboard controls. The numbers inside change the speed of the player
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
player.movement(-4, 0)
elif event.key == pygame.K_d:
player.movement(4, 0)
elif event.key == pygame.K_w:
player.movement(0, -4)
elif event.key == pygame.K_s:
player.movement(0, 4)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_a:
player.movement(4, 0)
elif event.key == pygame.K_d:
player.movement(-4, 0)
elif event.key == pygame.K_w:
player.movement(0, 4)
elif event.key == pygame.K_s:
player.movement(0, -4)
# ___________________________________________________________________
# Mouse Controls----------------------------
pos = pygame.mouse.get_pos()
cursor_x = pos[0]
cursor_y = pos[1]
if cursor_x <= 10:
cursor_x = 10
if cursor_x >= (screen_width - 17):
cursor_x = (screen_width - 17)
if cursor_y <= 10:
cursor_y = 10
if cursor_y >= (screen_height - 107):
cursor_y = (screen_height - 107)
elif event.type == pygame.MOUSEBUTTONDOWN:
bullet = Bullet()
all_sprites_list.add(bullet)
bullet_list.add(bullet)
#--------------------------------------------
all_sprites_list.update()
# How bullets vanish when they hit a sprite or a wall______________________
for bullet in bullet_list: #For each bullet:
# Whenever a bullet collides with a zombie,
block_hit_list = pygame.sprite.spritecollide(bullet, zombie1_list, True)
for i in block_hit_list:
# Destroy the bullet and zombie and add to the score
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
score += 100
for bullet in bullet_list:
block_hit_list = pygame.sprite.spritecollide(bullet, wall_list, False)
for i in block_hit_list:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
#--------------------------------------------------------------------------
cursor.update()
bullet_list.update()
sprites_list.update()
pygame.mouse.set_visible(0)
screen.fill(BLACK)
all_sprites_list.draw(screen)
text = font.render("Score: " + str(score), True, WHITE)
screen.blit(text, [30, screen_height - 64])
pygame.display.flip()
clock.tick(60)
pygame.quit()
What you will have to do is before you destroy the zombie sprite grab its location and draw the UP coin. Then make sure that whenever the player controlled sprite, in this case the bullet, upon contact "collects" the coin. I haven't worked with python that much but the main code would look something like this:
def drawCoin():
zombieCoords = grabZombieCoords()
drawSprite(zombieCoords())
This would essentially just get the coordinates of the zombie, destroy it, and then place the coin at the last known location of the zombie.
Hope this helps.
Change your Up class to accept an argument pos, and use it to set the starting position:
class Up(pygame.sprite.Sprite):
def __init__(self, color, pos):
super().__init__()
self.image = pygame.Surface([5, 5])
self.image.fill(color)
self.rect = self.image.get_rect(center=pos)
Now, when you hit a zombie, create an Up, using the position of the zombie you just killed.
for bullet in bullet_list:
block_hit_list = pygame.sprite.spritecollide(bullet, zombie_list, True)
for i in block_hit_list:
# just use .kill() to remove a Sprite from all of its Groups
# kill() may get called multiple times, but that does not hurt
bullet.kill()
score += 100
# create an Up for each killed zombie
# takes two arguments: color and pos
# we call .add() to add the Sprite immediately to
# the all_sprites_list and the up_list
Up((255, 0, 0), i.rect.center).add(all_sprites_list, up_list)
You didn't show the rest of your code, but I guess you call .draw and .update on your all_sprites_list and create a Group called up_list.