I've tried everything and cannot get how I check if my two blocks have collided.
Here's my code:
import pygame
import random
pygame.init()
display_width = 600
display_height = 300
class player:#Just info for player
width = 30
height = 30
x = display_width // 2
y = display_height - height - 5
a = x + 30
pic = 'SnakePart.png'
thing = pygame.image.load(pic)
def place(x,y):#function for placing player object
gameDisplay.blit(player.thing, (player.x,player.y))
class enemy:#enemy info class
width = 30
height = 30
x = random.randint(0,display_width - width)
y = 1
a = x + 30
pic = 'Apple.png'
thing = pygame.image.load(pic)
speed = 10#sets speed
def change_x():
enemy.x = random.randint(0,display_width - enemy.width)
def change_y():
enemy.y += enemy.speed
def make(x,y):#set up funtion
gameDisplay.blit(enemy.thing, (x,y))
def respawn():#reseting enemy entity
enemy.y = 1
gameDisplay.blit(enemy.thing, (enemy.x,enemy.y))
player.thing#uses the variables in the classes to set up the images for use
enemy.thing
black = (0,0,0)
white = (255,255,255)
player_height = 30
player_width = 30
clock = pygame.time.Clock()
x_change = 0#This is to make movment
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('Bullet Hell.')
dodged = 0#counter will be used in the more polished vesion.
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:#Checks for keypress, to make player entity move
if event.key == pygame.K_RIGHT:
x_change = 5
if event.key == pygame.K_LEFT:
x_change = -5
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or pygame.K_LEFT:
x_change = 0
player.x += x_change
gameDisplay.fill(black)
enemy.make(enemy.x,enemy.y)
player.place(player.x,player.y)
enemy.change_y()
if enemy.y > display_height:#Brings enemy back to top once it has gotten to th bottom
enemy.change_x()
dodged += 1
enemy.respawn()
pygame.display.update()
clock.tick(60)
It's all really the collision and I think I'll be good. Oh yeah, if you guys could also tell me how to display text that would be great!
Take a look at the pygame.Rect class and its collision detection methods. Give your objects rects as attributes which you get by calling the .get_rect() method of the images/surfaces. Update the coordinates of these rects each frame and in your main loop call player.rect.colliderect(enemy.rect) to check if the two rects collide.
import pygame
import random
pygame.init()
BLACK = pygame.Color('black')
display = pygame.display.set_mode((600, 300))
# Create a rect with the dimensions of the screen at coords (0, 0).
display_rect = display.get_rect()
clock = pygame.time.Clock()
# SNAKE_IMAGE = pygame.image.load('SnakePart.png').convert_alpha()
# APPLE_IMAGE = pygame.image.load('Apple.png').convert_alpha()
# Replacement images.
SNAKE_IMAGE = pygame.Surface((30, 30))
SNAKE_IMAGE.fill((30, 150, 0))
APPLE_IMAGE = pygame.Surface((30, 30))
APPLE_IMAGE.fill((150, 30, 0))
class Player:
def __init__(self):
self.x = display_rect.w // 2
self.y = display_rect.h - 30 - 5
self.image = SNAKE_IMAGE
# Create a rect with the size of the image at coords (0, 0).
self.rect = self.image.get_rect()
# Set the topleft coords of the rect.
self.rect.x = self.x
self.rect.y = self.y
self.x_change = 0
def update(self):
"""Move the player."""
self.x += self.x_change
# Always update the rect, because it's
# needed for the collision detection.
self.rect.x = self.x
def draw(self, display):
display.blit(self.image, self.rect)
class Enemy:
def __init__(self):
self.x = random.randint(0, display_rect.w - 30)
self.y = 1
self.image = APPLE_IMAGE
# You can also pass the coords directly to `get_rect`.
self.rect = self.image.get_rect(topleft=(self.x, self.y))
self.speed = 10
def change_x(self):
self.x = random.randint(0, display_rect.w - self.rect.w)
self.rect.x = self.x
def change_y(self):
self.y += self.speed
self.rect.y = self.y
def draw(self, display):
display.blit(self.image, self.rect)
def reset(self):
"""Reset self.y position."""
self.y = -30
player = Player()
enemy = Enemy()
dodged = 0
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
player.x_change = 5
if event.key == pygame.K_LEFT:
player.x_change = -5
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or pygame.K_LEFT:
player.x_change = 0
# Game logic.
player.update()
enemy.change_y()
# Brings enemy back to top once it has gotten to th bottom
if enemy.y > display_rect.h:
enemy.change_x()
dodged += 1
enemy.reset()
# Check if the player and the rect collide.
if player.rect.colliderect(enemy.rect):
print('Collided!')
# Draw everything.
display.fill(BLACK)
enemy.draw(display)
player.draw(display)
pygame.display.update()
clock.tick(60)
pygame.quit()
I've changed some more things (btw, better call the images self.image not thing ;)) especially in the classes:
The attributes of the classes should be in __init__ methods to make them instance attributes instead of class attributes (which get shared by all instances). Also, check out how to create instances of your classes.
The methods should all have self as their first parameter (that's a reference to the instance). To access the attributes inside of the classes prepend them with self, e.g. self.x += self.x_change.
The player.x += x_change line fits better inside the Player class' update method, so you can just update the position and other player attributes by calling player.update().
There's a convention that class names should be uppercase MyClass whereas instances should have lowercase names my_instance.
Related
Heres my code
import pygame, os
os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()
win = pygame.display
d = win.set_mode((1200, 600))
class player:
def __init__(self, x, y, height, width):
self.x = x
self.y = y
self.height = height
self.width = width
self.speed = 2
def draw(self):
pygame.draw.rect(d, (0, 0, 0), (self.x, self.y, self.width, self.height))
def move_left(self):
self.x -= self.speed
def move_right(self):
self.x += self.speed
class bullet:
def __init__(self):
self.radius = 10
self.speed = 20
def shoot(self):
x = p.x
y = p.y
self.shooting = True
while self.shooting:
d.fill((98, 98, 98))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
y -= self.speed
pygame.draw.circle(d, (255, 0, 0), (x, y), self.radius)
pygame.time.Clock().tick(100)
win.update()
if y <= 0:
self.shooting = False
b = bullet()
p = player(600, 500, 50, 30)
while True:
d.fill((98, 98, 98))
p.draw()
for event in pygame.event.get():
pass
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
b.shoot()
if event.key == pygame.K_LEFT:
p.move_left()
if event.key == pygame.K_RIGHT:
p.move_right()
win.update()
This is what i could come up with after a few Trial and errors but it is really uneffective. Firstly the player disappers when i press space bar. I guess this is obvious as i have a different loops for shooting and player but i dont know how to get around it and implement both shooting and player in the same loop.
The second probllem i am having is breaking the while self.shooting: loop. I tried breaking it when y reaches a certain point by doing this
if y <= 0:
self.shooting = False
but this dosent break. Instead, it restarts the loop all over again.
Another weird problem i am having is that everytime i move mouse(slightly fast) or press a bunch of buttons at once, it breaks the while self.shooting loop.
The general approach to firing bullets is to store the positions of the bullets in a list (bullet_list). When a bullet is fired, add the bullet's starting position ([start_x, start_y]) to the list. The starting position is the position of the object (player or enemy) that fires the bullet. Use a for-loop to iterate through all the bullets in the list. Move position of each individual bullet in the loop. Remove a bullet from the list that leaves the screen (bullet_list.remove(bullet_pos)). For this reason, a copy of the list (bullet_list[:]) must be run through (see How to remove items from a list while iterating?). Use another for-loop to blit the remaining bullets on the screen:
bullet_list = []
while run == True:
# [...]
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullet_list.append([start_x, start_y])
for bullet_pos in bullet_list[:]:
bullet_pos[0] += move_bullet_x
bullet_pos[1] += move_bullet_y
if not screen.get_rect().colliderect(bullet_image.get_rect(center = bullet_pos))
bullet_list.remove(bullet_pos)
# [...]
for bullet_pos in bullet_list[:]
screen.blit(bullet_image, bullet_image.get_rect(center = bullet_pos))
# [...]
See also Shoot bullet.
Please note, that class names should normally use the CapWords convention.
(See Style Guide for Python Code - Class names)
That means it has to be Player and Bullet rather than player and bullet
You have an application loop, so use it. All the objects are continuously updated and drawn in the main application loop, in each frame.
The class Bullet do not need any loop. The constructor has to have parameters for the position (x, y). Further it needs on method which changes the position and one which draws the bullet:
class Bullet:
def __init__(self, x, y):
self.radius = 10
self.speed = 10
self.x = x
self.y = y
def update(self):
self.y -= self.speed#
def draw(self):
pygame.draw.circle(d, (255, 0, 0), (self.x, self.y), self.radius)
Use a list of bullets. Create a new bullet when space is pressed. Move the bullets (update) in every frame an remove a bullet if it is out of the window. Draw the remaining bullets in every frame:
bullets = []
# [...]
while run:
for event in pygame.event.get():
# [...]
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullets.append(Bullet(p.x+p.width//2, p.y))
# [...]
for b in bullets:
b.update()
if b.y < 0:
bullets.remove(b)
# [...]
for b in bullets:
b.draw()
Furthermore use pygame.key.get_pressed() use to get the state of the keys in every frame and to update the position of the player:
while run:
# [...]
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
p.move_left()
if keys[pygame.K_RIGHT]:
p.move_right()
Complete example:
import pygame, os
os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()
win = pygame.display
d = win.set_mode((1200, 600))
clock = pygame.time.Clock()
class Player:
def __init__(self, x, y, height, width):
self.x = x
self.y = y
self.height = height
self.width = width
self.speed = 2
def draw(self):
pygame.draw.rect(d, (0, 0, 0), (self.x, self.y, self.width, self.height))
def move_left(self):
self.x -= self.speed
def move_right(self):
self.x += self.speed
class Bullet:
def __init__(self, x, y):
self.radius = 10
self.speed = 10
self.x = x
self.y = y
def update(self):
self.y -= self.speed#
def draw(self):
pygame.draw.circle(d, (255, 0, 0), (self.x, self.y), self.radius)
bullets = []
p = Player(600, 500, 50, 30)
run = True
while run:
clock.tick(100)
# handel events
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullets.append(Bullet(p.x+p.width//2, p.y))
# update objects
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
p.move_left()
if keys[pygame.K_RIGHT]:
p.move_right()
for b in bullets:
b.update()
if b.y < 0:
bullets.remove(b)
# clear display
d.fill((98, 98, 98))
# draw scene
for b in bullets:
b.draw()
p.draw()
# update display
win.update()
Heres my code
import pygame, os
os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()
win = pygame.display
d = win.set_mode((1200, 600))
class player:
def __init__(self, x, y, height, width):
self.x = x
self.y = y
self.height = height
self.width = width
self.speed = 2
def draw(self):
pygame.draw.rect(d, (0, 0, 0), (self.x, self.y, self.width, self.height))
def move_left(self):
self.x -= self.speed
def move_right(self):
self.x += self.speed
class bullet:
def __init__(self):
self.radius = 10
self.speed = 20
def shoot(self):
x = p.x
y = p.y
self.shooting = True
while self.shooting:
d.fill((98, 98, 98))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
y -= self.speed
pygame.draw.circle(d, (255, 0, 0), (x, y), self.radius)
pygame.time.Clock().tick(100)
win.update()
if y <= 0:
self.shooting = False
b = bullet()
p = player(600, 500, 50, 30)
while True:
d.fill((98, 98, 98))
p.draw()
for event in pygame.event.get():
pass
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
b.shoot()
if event.key == pygame.K_LEFT:
p.move_left()
if event.key == pygame.K_RIGHT:
p.move_right()
win.update()
This is what i could come up with after a few Trial and errors but it is really uneffective. Firstly the player disappers when i press space bar. I guess this is obvious as i have a different loops for shooting and player but i dont know how to get around it and implement both shooting and player in the same loop.
The second probllem i am having is breaking the while self.shooting: loop. I tried breaking it when y reaches a certain point by doing this
if y <= 0:
self.shooting = False
but this dosent break. Instead, it restarts the loop all over again.
Another weird problem i am having is that everytime i move mouse(slightly fast) or press a bunch of buttons at once, it breaks the while self.shooting loop.
The general approach to firing bullets is to store the positions of the bullets in a list (bullet_list). When a bullet is fired, add the bullet's starting position ([start_x, start_y]) to the list. The starting position is the position of the object (player or enemy) that fires the bullet. Use a for-loop to iterate through all the bullets in the list. Move position of each individual bullet in the loop. Remove a bullet from the list that leaves the screen (bullet_list.remove(bullet_pos)). For this reason, a copy of the list (bullet_list[:]) must be run through (see How to remove items from a list while iterating?). Use another for-loop to blit the remaining bullets on the screen:
bullet_list = []
while run == True:
# [...]
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullet_list.append([start_x, start_y])
for bullet_pos in bullet_list[:]:
bullet_pos[0] += move_bullet_x
bullet_pos[1] += move_bullet_y
if not screen.get_rect().colliderect(bullet_image.get_rect(center = bullet_pos))
bullet_list.remove(bullet_pos)
# [...]
for bullet_pos in bullet_list[:]
screen.blit(bullet_image, bullet_image.get_rect(center = bullet_pos))
# [...]
See also Shoot bullet.
Please note, that class names should normally use the CapWords convention.
(See Style Guide for Python Code - Class names)
That means it has to be Player and Bullet rather than player and bullet
You have an application loop, so use it. All the objects are continuously updated and drawn in the main application loop, in each frame.
The class Bullet do not need any loop. The constructor has to have parameters for the position (x, y). Further it needs on method which changes the position and one which draws the bullet:
class Bullet:
def __init__(self, x, y):
self.radius = 10
self.speed = 10
self.x = x
self.y = y
def update(self):
self.y -= self.speed#
def draw(self):
pygame.draw.circle(d, (255, 0, 0), (self.x, self.y), self.radius)
Use a list of bullets. Create a new bullet when space is pressed. Move the bullets (update) in every frame an remove a bullet if it is out of the window. Draw the remaining bullets in every frame:
bullets = []
# [...]
while run:
for event in pygame.event.get():
# [...]
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullets.append(Bullet(p.x+p.width//2, p.y))
# [...]
for b in bullets:
b.update()
if b.y < 0:
bullets.remove(b)
# [...]
for b in bullets:
b.draw()
Furthermore use pygame.key.get_pressed() use to get the state of the keys in every frame and to update the position of the player:
while run:
# [...]
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
p.move_left()
if keys[pygame.K_RIGHT]:
p.move_right()
Complete example:
import pygame, os
os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()
win = pygame.display
d = win.set_mode((1200, 600))
clock = pygame.time.Clock()
class Player:
def __init__(self, x, y, height, width):
self.x = x
self.y = y
self.height = height
self.width = width
self.speed = 2
def draw(self):
pygame.draw.rect(d, (0, 0, 0), (self.x, self.y, self.width, self.height))
def move_left(self):
self.x -= self.speed
def move_right(self):
self.x += self.speed
class Bullet:
def __init__(self, x, y):
self.radius = 10
self.speed = 10
self.x = x
self.y = y
def update(self):
self.y -= self.speed#
def draw(self):
pygame.draw.circle(d, (255, 0, 0), (self.x, self.y), self.radius)
bullets = []
p = Player(600, 500, 50, 30)
run = True
while run:
clock.tick(100)
# handel events
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullets.append(Bullet(p.x+p.width//2, p.y))
# update objects
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
p.move_left()
if keys[pygame.K_RIGHT]:
p.move_right()
for b in bullets:
b.update()
if b.y < 0:
bullets.remove(b)
# clear display
d.fill((98, 98, 98))
# draw scene
for b in bullets:
b.draw()
p.draw()
# update display
win.update()
I'm working on this prototype in pygame where you control a square and I'm currently working on collisions with other objects. When the player collides with the object, the player should not be able to move into the object.
import pygame,sys
pygame.init()
Clock = pygame.time.Clock()
FPS = 60
size = [1000,800]
bg = [0,0,0]
screen = pygame.display.set_mode(size)
pygame.display.set_caption('Movement')
class Player:
def __init__(self,vel,x,y):
self.vel = vel
self.x = x
self.y = y
self.jump = False
def move(self):
k = pygame.key.get_pressed()
if k[pygame.K_a]:
self.x -= self.vel
if k[pygame.K_d]:
self.x += self.vel
if k[pygame.K_w]:
self.y -= self.vel
if k[pygame.K_s]:
self.y += self.vel
def draw(self):
pygame.draw.rect(screen,"red",(self.x,self.y,50,50))
def bordercollsion(self):
if self.x <=0:
self.x=0
if self.x >=950:
self.x=950
if self.y <=0:
self.y=0
if self.y >=750:
self.y=750
def do(self):
self.move()
self.draw()
self.bordercollsion()
player = Player(1,500,600)
while True:
screen.fill(bg)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
print(pygame.key.name(event.key))
if event.key == pygame.K_ESCAPE:
run = False
pygame.quit
sys.exit()
player.do()
en = pygame.draw.rect(screen,"blue",(10,20,50,50))
pygame.display.update()
See How do I detect collision in pygame?. Use pygame.Rect/colliderect to detect collisions of rectangles.
Store the position of the player
player_pos = player.x, player.y
Move the palyer:
player.do()
Set up a rectangle for the player and the obstacle:
player_rect = pygame.Rect(player.x, player.y, 50, 50)
obstacle_rect = pygame.Rect(10, 20, 50, 50)
Reset the position of the player, when the rectangles collide:
if player_rect.colliderect(obstacle_rect):
player.x, player.y = player_pos
Complete application loop
while True:
screen.fill(bg)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
print(pygame.key.name(event.key))
if event.key == pygame.K_ESCAPE:
run = False
pygame.quit
sys.exit()
player_pos = player.x, player.y
player.do()
player_rect = pygame.Rect(player.x, player.y, 50, 50)
obstacle_rect = pygame.Rect(10, 20, 50, 50)
if player_rect.colliderect(obstacle_rect):
player.x, player.y = player_pos
en = pygame.draw.rect(screen,"blue",(10,20,50,50))
pygame.display.update()
I see that someone has already posted a good answer to your question, but my answer has been shoe-horned into your original code. I've marked my changes with '###' to make them easier to find/identify.
There are a few ways to detect a collision in PyGame; this demonstrates PyGames colliderect() method. There is also a method using sprites and masking. The method you use depends on what you need.
import pygame,sys
pygame.init()
Clock = pygame.time.Clock()
FPS = 60
size = [1000,800]
bg = [0,0,0]
screen = pygame.display.set_mode(size)
pygame.display.set_caption('Movement')
class Buscemi(): ### new class for the blue square
'''Blue rectangle with which we must collide!''' ###
# def __init__(self):
# pass
# Normally you'd have an __init__() method, but this is one of
# those unusual cases were we don't actually need one. It still
# returns a Buscemi object
def draw(self): ###
'''Draws the rectangle and returns the Rect().''' ###
return pygame.draw.rect(screen,"blue",(10,20,50,50)) ###
class Player:
def __init__(self,vel,x,y,buscemi): ### added buscemi argument
self.vel = vel
self.buscemi=buscemi ### blue rectangle
self.x = x
self.y = y
self.xold = None ### for storing x before moving
self.yold = None ### for storing y before moving
self.jump = False
self.draw() ### because we need self.dude
def move(self):
if not self.dude.colliderect(self.buscemi.draw()): ### redraw blue and check collision
k = pygame.key.get_pressed()
self.xold = self.x ###
self.yold = self.y ###
if k[pygame.K_a]:
self.x -= self.vel
if k[pygame.K_d]:
self.x += self.vel
if k[pygame.K_w]:
self.y -= self.vel
if k[pygame.K_s]:
self.y += self.vel
else: ### restore x and y
self.x = self.xold ###
self.y = self.yold ###
def draw(self):
self.dude = pygame.draw.rect(screen,"red",(self.x,self.y,50,50)) ### named the rectangle
def bordercollsion(self):
if self.x <=0:
self.x=0
if self.x >=950:
self.x=950
if self.y <=0:
self.y=0
if self.y >=750:
self.y=750
def do(self):
self.move()
self.draw()
self.bordercollsion()
en = Buscemi() ### we need en as an object
player = Player(1,500,600,en) ### added one more argument
while True:
screen.fill(bg)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
print(pygame.key.name(event.key))
if event.key == pygame.K_ESCAPE:
run = False
pygame.quit
sys.exit()
# en = pygame.draw.rect(screen,"blue",(10,20,50,50)) ### made a class out of this
player.do()
pygame.display.update()
I am stuck on how to write my collision function in my player class. Also should I put my collision check function in my player class or should it be in my bullet class? I honestly don't know. I mean common sense says my bullet should have the collision check function in it, just because I want the top of my bullet checking if it hits a falling cement block sprite, but I don't know.... I would appreciate an answer on how to code my collision function. This would really help me out. My collision function is right below my shoot function in my player class.
My code:
import pygame
pygame.init()
#screen settings
WIDTH = 1000
HEIGHT = 400
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("AutoPilot")
screen.fill((255, 255, 255))
#fps
FPS = 120
clock = pygame.time.Clock()
#load images
bg = pygame.image.load('background/street.png').convert_alpha() # background
bullets = pygame.image.load('car/bullet.png').convert_alpha()
debris_img = pygame.image.load('debris/cement.png')
#define game variables
shoot = False
#player class
class Player(pygame.sprite.Sprite):
def __init__(self, scale, speed):
pygame.sprite.Sprite.__init__(self)
self.bullet = pygame.image.load('car/bullet.png').convert_alpha()
self.bullet_list = []
self.speed = speed
#self.x = x
#self.y = y
self.moving = True
self.frame = 0
self.flip = False
self.direction = 0
#load car
self.images = []
img = pygame.image.load('car/car.png').convert_alpha()
img = pygame.transform.scale(img, (int(img.get_width()) * scale, (int(img.get_height()) * scale)))
self.images.append(img)
self.image = self.images[0]
self.rect = self.image.get_rect()
self.update_time = pygame.time.get_ticks()
self.movingLeft = False
self.movingRight = False
self.rect.x = 465
self.rect.y = 325
#draw car to screen
def draw(self):
screen.blit(self.image, (self.rect.centerx, self.rect.centery))
#move car
def move(self):
#reset the movement variables
dx = 0
dy = 0
#moving variables
if self.movingLeft and self.rect.x > 33:
dx -= self.speed
self.flip = True
self.direction = -1
if self.movingRight and self.rect.x < 900:
dx += self.speed
self.flip = False
self.direction = 1
#update rectangle position
self.rect.x += dx
self.rect.y += dy
#shoot
def shoot(self):
bullet = Bullet(self.rect.centerx + 18, self.rect.y + 30, self.direction)
bullet_group.add(bullet)
#def collision(self):
#write code here
#bullet class
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y, direction):
pygame.sprite.Sprite.__init__(self)
self.speed = 5
self.image = bullets
self.rect = self.image.get_rect()
self.rect.center = (x,y)
self.direction = direction
def update(self):
self.rect.centery -= self.speed
#check if bullet has gone off screen
if self.rect.top < 1:
self.kill()
#debris class
class Debris(pygame.sprite.Sprite):
def __init__(self, x, y, scale, speed):
pygame.sprite.Sprite.__init__(self)
self.scale = scale
self.x = x
self.y = y
self.speed = speed
self.vy = 0
self.on_ground = True
self.move = True
self.health = 4
self.max_health = self.health
self.alive = True
#load debris
self.image = debris_img
self.rect = self.image.get_rect()
self.rect.center = (x,y)
######################CAR/DEBRIS##########################
player = Player(1,5)
debris = Debris(300,15,1,5)
##########################################################
#groups
bullet_group = pygame.sprite.Group()
debris_group = pygame.sprite.Group()
debris_group.add(debris)
#game runs here
run = True
while run:
#draw street
screen.blit(bg, [0, 0])
#update groups
bullet_group.update()
bullet_group.draw(screen)
debris_group.update()
debris_group.draw(screen)
#draw car
player.draw()
player.move()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#check if key is down
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
run = False
if event.key == pygame.K_a:
player.movingLeft = True
if event.key == pygame.K_d:
player.movingRight = True
if event.key == pygame.K_SPACE:
player.shoot()
shoot = True
#check if key is up
if event.type == pygame.KEYUP:
if event.key == pygame.K_a:
player.movingLeft = False
if event.key == pygame.K_d:
player.movingRight = False
#update the display
pygame.display.update()
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
I suggest reading How do I detect collision in pygame?. Use pygame.sprite.spritecollide() for the collision detection. Set the dokill argument True. So the bullets gat automatically destroyed.
The following code is base on one of your previous questions: Check collision of bullet sprite hitting cement block sprite
class Car(pygame.sprite.Sprite):
# [...]
def collision(self, debris_group):
for debris in debris_group:
if pygame.sprite.spritecollide(debris, bullet_group, True):
debris.health -= 1
if debris.health <= 0:
debris.kill()
So, I'm a beginner to Python and Pygame and would like some help. I'm trying to make a game similar to Asteroids and I've made most of this program by looking around at other examples on the internet. However, I'm stuck on this problem: how do I get an enemy sprite to follow the player sprite? I've googled how to do so and tried implementing the same thing on my code but the sprite just stays in one place and doesn't follow the player. I've used the vector stuff to create the player sprite and I still barely understand how that works. I'm sort of on a tight schedule so I don't have time to thoroughly understand this stuff but I intend to later. Sorry if I haven't explained my code properly but I'm still trying to understand how Pygame works and most of this code is basically just copied.
import random, math, pygame, time, sys
from pygame.locals import *
from pygame.math import Vector2
######Setting up Variables
class settings:
fps = 30
windowwidth = 590
windowheight = 332
class ship:
HEALTH = 3
SPEED = 4
SIZE = 25
class colours:
black = (0, 0, 0)
white = (255, 255, 255)
###########################
######################################################################################
class Player(pygame.sprite.Sprite):
def __init__(self,image_file , pos=(0,0)):
super(Player, self).__init__()
self.image = pygame.image.load(image_file)
self.image = pygame.transform.scale(self.image, (25,25))
self.original_image = self.image
self.rect = self.image.get_rect(center=pos)
self.position = Vector2(pos)
self.direction = Vector2(1, 0)
self.speed = 0
self.angle_speed = 0
self.angle = 0
def update(self):
if self.angle_speed != 0:
self.direction.rotate_ip(self.angle_speed)
self.angle += self.angle_speed
self.image = pygame.transform.rotate(self.original_image, -self.angle)
self.rect = self.image.get_rect(center=self.rect.center)
self.position += self.direction * self.speed
self.rect.center = self.position
class Enemy(pygame.sprite.Sprite):
def __init__(self, image_file, pos=(0,0)):
super(Enemy, self).__init__()
self.image = pygame.image.load(image_file)
self.image = pygame.transform.scale(self.image, (25, 25))
self.original_image = self.image
self.rect = self.image.get_rect(center=pos)
self.speed = 1
def move_towards_player(self, Player):
dx, dy = self.rect.x - Player.rect.x, self.rect.y - Player.rect.y
dist = math.hypot(dx, dy)
dx, dy = dx/dist, dy/dist
self.rect.x += dx * self.speed
self.rect.y += dy * self.speed
class Background(pygame.sprite.Sprite):
def __init__(self, image_file, location):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
def main():
pygame.init()
screen = pygame.display.set_mode((settings.windowwidth, settings.windowheight))
pygame.display.set_caption('Final Game')
background = Background('space.jpg',[0,0])
global player, enemy
player = Player('SpaceShip.png',[200,100])
playersprite = pygame.sprite.RenderPlain((player))
enemy = Enemy('Enemy Hexagon.png',[300,150])
enemysprite = pygame.sprite.RenderPlain((enemy))
fpsClock = pygame.time.Clock()
intro = True
while intro == True:
myFont = pygame.font.SysFont('freesansbold.ttf', 75)
otherFont = pygame.font.SysFont('freesansbold.ttf', 30)
SurfaceFont = myFont.render("Space Destroyer", True, (colours.white))
SurfaceFont2 = otherFont.render("Press Space to Start", True, (colours.white))
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_SPACE:
intro= False
screen.blit(SurfaceFont,(50,50))
screen.blit(SurfaceFont2,(125,125))
pygame.display.flip()
screen.blit(background.image, background.rect)
while intro == False:
fpsClock.tick(settings.fps)
for event in pygame.event.get():
enemy.rect.x
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_UP:
player.speed += 4
if event.key == K_LEFT:
player.angle_speed = -4
if event.key == K_RIGHT:
player.angle_speed = 4
if player.position.y < 0:
player.position = (player.position.x ,332)
elif player.position.y > settings.windowheight:
player.position = (player.position.x, 0)
elif player.position.x < 0:
player.position = (590, player.position.y)
elif player.position.x > settings.windowwidth:
player.position = (0, player.position.y)
elif event.type == KEYUP:
if event.key == K_LEFT:
player.angle_speed = 0
if event.key == K_RIGHT:
player.angle_speed = 0
if event.key == K_UP:
player.speed = 0
screen.fill(colours.white)
screen.blit(background.image, background.rect)
enemysprite.draw(screen)
enemysprite.update()
playersprite.draw(screen)
playersprite.update()
pygame.display.update()
playersprite.update()
pygame.display.flip()
if __name__ == '__main__': main()
You never called move_towards_player. Try adding this:
...
enemysprite.draw(screen)
enemysprite.update()
playersprite.draw(screen)
playersprite.update()
enemy.move_towards_player(player)
...