How to make sprites spawn at random? - python

I am fairly new at pygame so I need some help with a few problems. I'm doing a snake game but with enemies and a "maze".
My biggest problem is, I think, rather glaring if you run my code. I have coded the 'food' to appear at random but instead of appearing at 1 random place, it is moving around the screen. [SOLVED]
My second problem is that I want to spawn several enemies (around 5) at random locations instead of just one enemy but I don't know how to.
My third problem is bullet to wall collision detection. It works if I shoot the bullets one at a time but if I shoot multiple bullets at once, all the bullets will pass through the wall except the last one which will hit the wall.
These are the enemy codes:
Code is removed for now. Will re-upload in 1 to 2 months.
enemy = Enemy(500, 500, 1, wall_list)
all_sprite_list.add(enemy)
These are the codes for the bullets:
Code is removed for now. Will re-upload in 1 to 2 months.
Code is removed for now. Will re-upload in 1 to 2 months.
and this is my entire code if it helps:
Code is removed for now. Will re-upload in 1 to 2 months.
I appreciate any help I can get, even if its not related to the questions that I asked above. Thank you so much for your help!

You can add an instance to the Enemy class and spawn it to add another enemy, just give it some different coordinates then the first one.:
enemy = Enemy(500, 500, 1, wall_list)
enemy2 = Enemy(400,400,1, wall_list)
all_sprite_list.add(enemy)
all_sprite_list.add(enemy2)
For the food, id add another class like you did before.
class Food(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface([10,10])
self.image.fill(green)
self.rect = self.image.get_rect()
self.rect.x = random.randrange(20,780)
self.rect.y = random.randrange(20,780)
remove the following line:
pygame.draw.rect(win,green,[randfoodx,randfoody,10,10])
add this in the same location as where you spawn the enemies and the player sprites:
food = Food()
all_sprite_list.add(food)
For the bullet problem you mentioned, change the following line:
if pygame.sprite.spritecollideany(bullet, wall_list):
into:
if pygame.sprite.spritecollideany(self, wall_list):
This is important since when you spawn a new bullet, the bullet variable name will be overwritten.
all together:
#Import
import pygame
import math
import time
import random
from pygame.locals import *
#Initialize
pygame.init()
pygame.mixer.init()
clock=pygame.time.Clock()
win = pygame.display.set_mode((800,800))
pygame.display.set_caption("Essential Python CA1")
#Define
black = (0, 0, 0)
white = (255, 250, 250)
green = (0, 255, 0)
red = (255, 0, 0)
blue = (70,130,180)
font = pygame.font.Font(None, 60)
display_instructions = True
instruction_page = 1
#Bullet
class Bullet(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface([5, 5])
self.image.fill(green)
self.rect = self.image.get_rect()
def update(self):
self.rect.move_ip(self.vec.x, self.vec.y)
if pygame.sprite.spritecollideany(self, wall_list):
self.kill()
#Enemy
class Enemy(pygame.sprite.Sprite):
def __init__(self, x, y, speed, walls):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([20, 20])
self.image.fill(red)
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
self.speed = speed # speed of the enemy
self.walls = walls # walls for the collision test
def move(self, player):
dx, dy = player.rect.x - self.rect.x, player.rect.y - self.rect.y
dist = math.hypot(dx, dy)
dx, dy = dx / dist, dy / dist
Enemy.move_x = dx * self.speed
Enemy.move_y = dy * self.speed
def update(self):
self.rect.x += round(self.move_x)
block_collide = pygame.sprite.spritecollide(self, self.walls, False)
for block in block_collide:
if self.move_x > 0:
self.rect.right = block.rect.left
else:
self.rect.left = block.rect.right
self.rect.y += round(self.move_y)
block_collide = pygame.sprite.spritecollide(self, self.walls, False)
for block in block_collide:
if self.move_y > 0:
self.rect.bottom = block.rect.top
else:
self.rect.top = block.rect.bottom
#Player
class Player(pygame.sprite.Sprite):
move_x = 0
move_y = 0
walls = None
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([20, 20])
self.image.fill(white)
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
def move(self, x, y):
self.move_x += x
self.move_y += y
def update(self):
self.rect.x += self.move_x
block_collide = pygame.sprite.spritecollide(self, self.walls, False)
for block in block_collide:
if self.move_x > 0:
self.rect.right = block.rect.left
else:
self.rect.left = block.rect.right
self.rect.y += self.move_y
block_collide = pygame.sprite.spritecollide(self, self.walls, False)
for block in block_collide:
if self.move_y > 0:
self.rect.bottom = block.rect.top
else:
self.rect.top = block.rect.bottom
#Maze
class Wall(pygame.sprite.Sprite):
def __init__(self, x, y, width, height):
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(blue)
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
class Food(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.width = 10
self.height = 10
self.image = pygame.Surface([10,10])
self.image.fill(green)
self.rect = self.image.get_rect()
self.rect.x = random.randrange(20,780)
self.rect.y = random.randrange(20,780)
all_sprite_list = pygame.sprite.Group()
wall_list = pygame.sprite.Group()
walls = ((0, 0, 10, 800),
(40, 40, 10, 75),
(50, 40, 190, 10),
(790, 10, 10, 800),
(10, 0, 800, 10),
(10, 790, 800, 10),
(50, 750, 170, 10),
(40, 145, 10, 615),
(80, 710, 310, 10),
(250, 750, 110, 10),
(390, 680, 10, 80),
(400, 750, 200, 10),
(430, 710, 10, 50),
(470, 710, 200, 10),
(630, 750, 130, 10),
(750, 40, 10, 720),
(550, 40, 210, 10),
(270, 40, 250, 10),
(410, 80, 310, 10),
(410, 120, 310, 10),
(80, 80, 300, 10),
(370, 40, 10, 90),
(130, 120, 240, 10),
(300, 160, 450, 10),
(50, 160, 220, 10),
(700, 710, 50, 10),
(80, 670, 670, 10),
(80, 160, 10, 510),
(80, 200, 100, 10),
(210, 200, 120, 10),
(270, 200, 10, 90),
(120, 240, 150, 10),
(80, 280, 250, 10),
(360, 200, 100, 10),
(310, 240, 150, 10),
(460, 160, 10, 130),
(360, 280, 100, 10))
for wall_coords in walls:
wall = Wall(*wall_coords)
wall_list.add(wall)
all_sprite_list.add(wall)
player = Player(10, 10)
player.walls = wall_list
enemy = Enemy(500, 500, 1, wall_list)
enemy2 = Enemy(400,400,1, wall_list)
all_sprite_list.add(enemy)
all_sprite_list.add(enemy2)
food = Food()
all_sprite_list.add(food)
all_sprite_list.add(player)
#Start screen Loop
done = False
while not done and display_instructions:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = False
if event.type == pygame.MOUSEBUTTONDOWN:
instruction_page += 1
if instruction_page == 2:
display_instructions = False
# Set the screen background
win.fill(black)
if instruction_page == 1:
text = font.render("Instructions:", True, white)
win.blit(text, [10, 20])
text = font.render("Use WASD, or the Arrow Keys to move", True, white)
win.blit(text, [10, 100])
text = font.render("Left click to shoot", True, white)
win.blit(text, [10, 150])
text = font.render("Can you beat your highscore?", True, red)
win.blit(text, [100, 370])
text = font.render("Click to start", True, white)
win.blit(text, [270, 600])
clock.tick(60)
pygame.display.flip()
# Programme loop
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == ord('a'):
player.move(-2, 0)
elif event.key == pygame.K_RIGHT or event.key == ord('d'):
player.move(2, 0)
elif event.key == pygame.K_UP or event.key == ord('w'):
player.move(0, -2)
elif event.key == pygame.K_DOWN or event.key == ord('s'):
player.move(0, 2)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == ord('a'):
player.move(2, 0)
elif event.key == pygame.K_RIGHT or event.key == ord('d'):
player.move(-2, 0)
elif event.key == pygame.K_UP or event.key == ord('w'):
player.move(0, 2)
elif event.key == pygame.K_DOWN or event.key == ord('s'):
player.move(0, -2)
elif event.type == pygame.MOUSEBUTTONDOWN:
aim_pos = event.pos
player_position = player.rect.center
bullet_vec = pygame.math.Vector2(aim_pos[0] - player_position[0], aim_pos[1] - player_position[1]).normalize() * 10
bullet = Bullet()
bullet.rect.center = player.rect.center
bullet.vec = bullet_vec
all_sprite_list.add(bullet)
enemy.move(player)
all_sprite_list.update()
win.fill(black)
all_sprite_list.draw(win)
# pygame.draw.rect(win,green,[randfoodx,randfoody,10,10])
pygame.display.flip()
clock.tick(100)
pygame.quit()

For the food issue, you'd need it to only generate a piece of food if there are none on the map. Or if there were less than x. So set a numberOfFood variable, and instead of while run: you could put while numberOfFood < 2:

Related

Pygame block sprites not being drawn on screen

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

In pygame, I am trying to make a ball disappear when it hits one of my images, I would like sprites not to be used because I have not learned them [duplicate]

For some reason the Colliderect won't work and the rain passes through pavement. This is really annoying because all of those unused sprites create tons of lag.
import pygame
import random
class Square(pygame.sprite.Sprite):
def __init__(self, x, y, size1, size2, speedx, speedy, colour):
super().__init__()
self.image = pygame.Surface([size1, size2])
self.image.fill(colour)
self.speedx = speedx
self.speedy = speedy
self.rect=self.image.get_rect()
self.rect.x=x
self.rect.y=y
def update(self):
square_colour = (random.randint(0,255), random.randint(0,255), random.randint(0,255))
self.rect.x = self.rect.x + self.speedx
self.rect.y = self.rect.y + self.speedy
my_square = Square(0, 705, 20, 30, 1, 0, (0, 0, 0))
pavement = Square(0, 735, 750, 15, 0 , 0, (100, 100, 100))
allspriteslist = pygame.sprite.Group()
allspriteslist.add(my_square)
allspriteslist.add(pavement)
pygame.init()
screen = pygame.display.set_mode([750,750])
pygame.display.set_caption('Snake Example')
clock = pygame.time.Clock()
background_colour = (150, 150, 150)
done = False
while not done:
r = Square(random.randint(0, 747), 0, 3, 7, 0, 5, (137, 200, 230))
allspriteslist.add(r)
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
done = True
if my_square.rect.x > 750:
my_square.rect.x = - 10
if my_square.rect.x < - 50:
my_square.rect.x = 800
if r.rect.colliderect(pavement.rect):
allspriteslist.remove(r)
screen.fill(background_colour)
allspriteslist.draw(screen)
allspriteslist.update()
pygame.display.flip()
You have to detect the collision of all the raindrops with the pavement.
Add a group for the raindrops:
rain = pygame.sprite.Group()
Add each rain drop to the group:
done = False
while not done:
r = Square(random.randint(0, 747), 0, 3, 7, 0, 5, (137, 200, 230))
allspriteslist.add(r)
rain.add(r)
And remove a drop if it hits the ground, by pygame.sprite.Sprite.kill():
done = False
while not done:
# [...]
for r in rain:
if r.rect.colliderect(pavement.rect):
r.kill()
Removing the rain drops can be simplified by using pygame.sprite.spritecollide() and passing True to the argument dokill:
done = False
while not done:
# [...]
pygame.sprite.spritecollide(pavement, rain, True)
Complete example code:
import pygame
import random
class Square(pygame.sprite.Sprite):
def __init__(self, x, y, size1, size2, speedx, speedy, colour):
super().__init__()
self.image = pygame.Surface([size1, size2])
self.image.fill(colour)
self.speedx = speedx
self.speedy = speedy
self.rect=self.image.get_rect()
self.rect.x=x
self.rect.y=y
def update(self):
square_colour = (random.randint(0,255), random.randint(0,255), random.randint(0,255))
self.rect.x = self.rect.x + self.speedx
self.rect.y = self.rect.y + self.speedy
my_square = Square(0, 705, 20, 30, 1, 0, (0, 0, 0))
pavement = Square(0, 735, 750, 15, 0 , 0, (100, 100, 100))
allspriteslist = pygame.sprite.Group()
allspriteslist.add(my_square)
allspriteslist.add(pavement)
rain = pygame.sprite.Group()
pygame.init()
screen = pygame.display.set_mode([750,750])
pygame.display.set_caption('Snake Example')
clock = pygame.time.Clock()
background_colour = (150, 150, 150)
done = False
while not done:
r = Square(random.randint(0, 747), 0, 3, 7, 0, 5, (137, 200, 230))
allspriteslist.add(r)
rain.add(r)
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
done = True
if my_square.rect.x > 750:
my_square.rect.x = - 10
if my_square.rect.x < - 50:
my_square.rect.x = 800
pygame.sprite.spritecollide(pavement, rain, True)
screen.fill(background_colour)
allspriteslist.draw(screen)
allspriteslist.update()
pygame.display.flip()

How to determine why objects pass through each other in Colliderect

For some reason the Colliderect won't work and the rain passes through pavement. This is really annoying because all of those unused sprites create tons of lag.
import pygame
import random
class Square(pygame.sprite.Sprite):
def __init__(self, x, y, size1, size2, speedx, speedy, colour):
super().__init__()
self.image = pygame.Surface([size1, size2])
self.image.fill(colour)
self.speedx = speedx
self.speedy = speedy
self.rect=self.image.get_rect()
self.rect.x=x
self.rect.y=y
def update(self):
square_colour = (random.randint(0,255), random.randint(0,255), random.randint(0,255))
self.rect.x = self.rect.x + self.speedx
self.rect.y = self.rect.y + self.speedy
my_square = Square(0, 705, 20, 30, 1, 0, (0, 0, 0))
pavement = Square(0, 735, 750, 15, 0 , 0, (100, 100, 100))
allspriteslist = pygame.sprite.Group()
allspriteslist.add(my_square)
allspriteslist.add(pavement)
pygame.init()
screen = pygame.display.set_mode([750,750])
pygame.display.set_caption('Snake Example')
clock = pygame.time.Clock()
background_colour = (150, 150, 150)
done = False
while not done:
r = Square(random.randint(0, 747), 0, 3, 7, 0, 5, (137, 200, 230))
allspriteslist.add(r)
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
done = True
if my_square.rect.x > 750:
my_square.rect.x = - 10
if my_square.rect.x < - 50:
my_square.rect.x = 800
if r.rect.colliderect(pavement.rect):
allspriteslist.remove(r)
screen.fill(background_colour)
allspriteslist.draw(screen)
allspriteslist.update()
pygame.display.flip()
You have to detect the collision of all the raindrops with the pavement.
Add a group for the raindrops:
rain = pygame.sprite.Group()
Add each rain drop to the group:
done = False
while not done:
r = Square(random.randint(0, 747), 0, 3, 7, 0, 5, (137, 200, 230))
allspriteslist.add(r)
rain.add(r)
And remove a drop if it hits the ground, by pygame.sprite.Sprite.kill():
done = False
while not done:
# [...]
for r in rain:
if r.rect.colliderect(pavement.rect):
r.kill()
Removing the rain drops can be simplified by using pygame.sprite.spritecollide() and passing True to the argument dokill:
done = False
while not done:
# [...]
pygame.sprite.spritecollide(pavement, rain, True)
Complete example code:
import pygame
import random
class Square(pygame.sprite.Sprite):
def __init__(self, x, y, size1, size2, speedx, speedy, colour):
super().__init__()
self.image = pygame.Surface([size1, size2])
self.image.fill(colour)
self.speedx = speedx
self.speedy = speedy
self.rect=self.image.get_rect()
self.rect.x=x
self.rect.y=y
def update(self):
square_colour = (random.randint(0,255), random.randint(0,255), random.randint(0,255))
self.rect.x = self.rect.x + self.speedx
self.rect.y = self.rect.y + self.speedy
my_square = Square(0, 705, 20, 30, 1, 0, (0, 0, 0))
pavement = Square(0, 735, 750, 15, 0 , 0, (100, 100, 100))
allspriteslist = pygame.sprite.Group()
allspriteslist.add(my_square)
allspriteslist.add(pavement)
rain = pygame.sprite.Group()
pygame.init()
screen = pygame.display.set_mode([750,750])
pygame.display.set_caption('Snake Example')
clock = pygame.time.Clock()
background_colour = (150, 150, 150)
done = False
while not done:
r = Square(random.randint(0, 747), 0, 3, 7, 0, 5, (137, 200, 230))
allspriteslist.add(r)
rain.add(r)
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
done = True
if my_square.rect.x > 750:
my_square.rect.x = - 10
if my_square.rect.x < - 50:
my_square.rect.x = 800
pygame.sprite.spritecollide(pavement, rain, True)
screen.fill(background_colour)
allspriteslist.draw(screen)
allspriteslist.update()
pygame.display.flip()

Python collisions

I have recently learned python and have a school project involving pygame, but we weren't taught much, anyways I have been trying to make a maze in which the player (the white square), collides with the red block (the endpoint) something happens (a task takes place as a result of the collision), but I have tried various things but nothing seems to be working (I am still VERY new to pygame). Well, thanks for any help, but bear in mind that i am a beginner an that there are probably many mistakes in my code
import pygame
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BLUE = (50, 50, 255)
GREEN = (33,206,14)
RED = (255,0,0)
GREY = (43,44,61)
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
# Call the parent's constructor
super().__init__()
#self.image = pygame.image.load("basketballsprite.png").convert()
#self.image.set_colorkey(WHITE)
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
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):
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:
# Otherwise if we are moving left, do the opposite.
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
#if pygame.sprite.spritecollide(Endpoint, self.image,True):
class Wall(pygame.sprite.Sprite):
def __init__(self, x, y, width, height):
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(GREY)
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
class Endpoint(pygame.sprite.Sprite):
def __init__(self, x, y, width, height):
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(RED)
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
pygame.init()
screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])
pygame.display.set_caption('A "Little" Maze Game...')
all_sprite_list = pygame.sprite.Group()
wall_list = pygame.sprite.Group()
Endpoint_list = pygame.sprite.Group()
wall = Wall(0, 0, 10, 600)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(0, 590, 400, 10)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(450, 590, 390, 10)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(10, 0, 790, 10)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(30, 200, 85, 10)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(790, 0, 10, 800)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(70, 0, 10, 80)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(390, 500, 10, 150)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(450, 500, 10, 150)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(790, 0, 10, 800)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(400, 600, 2000, 15)
wall_list.add(wall)
all_sprite_list.add(wall)
Endpoint = Endpoint(400, 590, 50, 15)
wall_list.add(wall)
all_sprite_list.add(Endpoint)
wall = Wall(35, 100, 50, 10)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(100, 95, 10, 80)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(100, 10, 10, 65)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(130, 200, 10, 90)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(130, 225, 90, 10)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(50, 100, 10, 45)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(10, 160, 40, 10)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(300, 200, 10, 250)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(240, 260, 60, 10)
wall_list.add(wall)
all_sprite_list.add(wall)
'''
wall = Wall(x, y, width, height)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(x, y, width, height)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(x, y, width, height)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(x, y, width, height)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(x, y, width, height)
wall_list.add(wall)
all_sprite_list.add(wall)
'''
player = Player(34, 34)
player.walls = wall_list
all_sprite_list.add(player)
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_LEFT:
player.changespeed(-2, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(2, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, -2)
elif event.key == pygame.K_DOWN:
player.changespeed(0, 2)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.changespeed(2, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(-2, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, 2)
elif event.key == pygame.K_DOWN:
player.changespeed(0, -2)
screen.fill(BLACK)
if pygame.sprite.spritecollideany(player,Endpoint_list):
exit()
all_sprite_list.update()
pygame.draw.circle(screen, BLUE, [40, 40], 30)
all_sprite_list.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
You just need to add the Endpoint instance to the Endpoint_list which you use for the collision detection. Also, don't use the same name for the instance and the class, otherwise you're overriding the class and can't create new instances anymore.
endpoint = Endpoint(400, 590, 50, 15) # Just use a lowercase name for the instance.
all_sprite_list.add(endpoint)
Endpoint_list.add(endpoint)
Alternatively, you could use the pygame.sprite.collide_rect() function.
if pygame.sprite.collide_rect(player, endpoint):
print('exit reached')
Or just the colliderect method of the rects:
if player.rect.colliderect(endpoint):

I am making a pygame version of galaga. There is a weird error(see below)

This is the error:
Traceback (most recent call last):
File "C:/Users/Lucas/PycharmProjects/FirstPyGame/Main.py", line 117, in <module>
player.changespeed(3, 0)
File "C:/Users/Lucas/PycharmProjects/FirstPyGame/Main.py", line 42, in changespeed
self.change_x += x
AttributeError: 'Ship' object has no attribute 'change_x'
Here is my code:
import pygame
import random
pygame.init()
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 255, 255)
size = [800, 600]
x_coord = 400
y_coord = 600
x_speed = 0
y_speed = 0
font = pygame.font.SysFont("Calibri", 25, True, False)
snow_list = []
for i in range(50):
x = random.randrange(0, 800)
y = random.randrange(0, 600)
snow_list.append([x, y])
pygame.display.set_caption("Star Fighter")
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
class Ship(pygame.sprite.Sprite):
def ___init__(self, x, y):
super().__init__()
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.change_x = 0
self.change_y = 0
def changespeed(self, x, y):
self.change_x += x
self.change_y += y
def update(self):
self.rect.x += self.change_x
self.rect.y += self.change_y
def DrawShip(screen, x, y):
a = pygame.draw.rect(screen, WHITE, ((x_coord - 5), (y_coord - 60), 10, 10))
b = pygame.draw.rect(screen, WHITE, ((x_coord - 15), (y_coord - 50), 10, 10))
c = pygame.draw.rect(screen, RED, ((x_coord - 5), (y_coord - 50), 10, 10))
d = pygame.draw.rect(screen, WHITE, ((x_coord + 5), (y_coord - 50), 10, 10))
class Block(pygame.sprite.Sprite):
def __init__(self, color):
super().__init__()
self.image = pygame.Surface([20, 15])
self.image.fill(color)
self.rect = self.image.get_rect()
def ScrollStars():
for i in range(len(snow_list)):
pygame.draw.circle(screen, WHITE, snow_list[i], 3)
snow_list[i][1] += 1
if snow_list[i][1] > 600:
y = random.randrange(-50, -10)
snow_list[i][1] = y
x = random.randrange(0, 800)
snow_list[i][0] = x
class Bullet(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface([4, 10])
self.image.fill(WHITE)
self.rect = self.image.get_rect()
def update(self):
self.rect.y -= 3
all_sprites_list = pygame.sprite.Group()
block_list = pygame.sprite.Group()
bullet_list = pygame.sprite.Group()
for i in range(50):
# This represents a block
block = Block(BLUE)
# Set a random location for the block
block.rect.x = random.randrange(800)
block.rect.y = random.randrange(300)
# Add the block to the list of objects
block_list.add(block)
all_sprites_list.add(block)
score = 0
player = Ship()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
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_SPACE:
bullet = Bullet()
bullet.rect.x = x_coord
bullet.rect.y = 550
all_sprites_list.add(bullet)
bullet_list.add(bullet)
elif event.key == pygame.K_q:
running = False
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)
if event.key == pygame.K_LEFT or pygame.K_RIGHT:
x_speed = 0
if event.type == pygame.K_UP or pygame.K_DOWN:
y_speed = 0
for bullet in bullet_list:
block_hit_list = pygame.sprite.spritecollide(bullet, block_list, True)
for block in block_hit_list:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
score += 1
if bullet.rect.y < -10:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
x_coord = x_coord + x_speed
y_coord = y_coord + y_speed
all_sprites_list.update()
screen.fill(BLACK)
all_sprites_list.draw(screen)
Ship.DrawShip(screen, x_coord, y_coord)
pygame.display.update()
clock.tick(70)
pygame.quit()
Could someone explain the error that I am having? I am a beginner and I do not understand it very well. It says that the Ship class has no attribute 'change_x' but it does, right? Sorry if this doesn't make any sense, but someone please help me with this. I would really appreciate it.
The issue is caused by a typo. The name of the constructor is __init__ rather than ___init__:
def ___init__(self, x, y):
def __init__(self, x, y):

Categories