I am trying to detect when two of my sprites collide. The first thing I did was create a rectangle around my player (called player.img) then another around the trees that I want to detect (called background.treesrect). I set the coordinates of the players rectangle equal to the coordinates that update when the player moves by the user pressing keys but the players rectangle doesnt move. Then I used the sprite.colliderect(sprite) function to detect if they collide and it doesnt detect. Can someone show my why my player rectangle isnt updating and anything else that may be wrong?
EDIT I just figured out the collision by putting the function that draws the rectangle into the game loop instead of the player class but I ran into another weird problem. The rectangle moves faster than the player sprite for some reason and I cant figure out how to make the player sprite on top of the background and not show the player rectangle.
import pygame
import sys
from pygame.locals import *
#starts the program
pygame.init()
white = (255, 255, 255)
black = (0, 0, 0)
red = (255, 0, 0)
blue = (0, 0, 255)
green = (0, 255, 0)
yellow = (255, 255, 153)
#creates a window of 800x600
setDisplay = pygame.display.set_mode((800, 600))
pygame.display.set_caption('Menu')
img = pygame.image.load('C:\\Users\\Ben\\Documents\\sprite.png')
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.img = pygame.image.load('C:\\Users\\Ben\\Documents\\sprite.png').convert()
self.imgx = 10
self.imgy = 10
self.setDisplay = pygame.display.get_surface()
self.x = self.imgx
self.y = self.imgy
self.rect = pygame.draw.rect(setDisplay, pygame.Color(0, 0, 255), pygame.Rect(self.x, self.y, 32, 32))
def draw(self):
self.setDisplay.blit(self.img)
def load(self, filename):
self.img = pygame.image.load('C:\\Users\\Ben\\Documents\\sprite.png').convert_alpha()
class Background(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.img = pygame.image.load('C:\\Users\\Ben\\Documents\\background.png').convert()
self.img2 = pygame.image.load('C:\\Users\\Ben\\Documents\\trees1.png').convert()
self.treesx = 0
self.treesy = 70
self.treesrect = pygame.draw.rect(setDisplay, pygame.Color(0, 0, 255),pygame.Rect(self.treesx, self.treesy, 376, 100))
def draw(self):
self.setDisplay.blit(self.img)
self.setDisplay.blit(self.img2)
def load(self, filename):
self.img = pygame.image.load('C:\\Users\\Ben\\Documents\\background.png').convert_alpha()
self.img2 = pygame.image.load('C:\\Users\\Ben\\Documents\\trees1.png').convert_alpha()
def detectCollision(sprite1, sprite2):
if sprite1.colliderect(sprite2):
print("worked")
player = Player()
background = Background()
def gameLoop():
imgx = 10
imgy = 10
lead_x_change = 0
lead_y_change = 0
move_variable = 5
while True:
pygame.display.flip()
for event in pygame.event.get():
#print (event)
if event.type == QUIT:
pygame.quit()
sys.exit()
setDisplay.blit(background.img, [0, 0])
setDisplay.blit(background.img2, [0, 0])
setDisplay.blit(player.img, [player.imgx, player.imgy])
if player.rect.colliderect(background.treesrect):
print("collided")
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
lead_x_change = -move_variable
player.x -= 10
elif event.key == pygame.K_UP:
lead_y_change = -move_variable
elif event.key == pygame.K_RIGHT:
player.imgx += 10
player.x += 10
elif event.key == pygame.K_DOWN:
lead_y_change = move_variable
player.y += 10
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
lead_x_change = 0
elif event.key == pygame.K_UP:
lead_y_change = 0
elif event.key == pygame.K_RIGHT:
lead_x_change = 0
elif event.key == pygame.K_DOWN:
lead_y_change = 0
print(player.x, player.y)
player.imgx += lead_x_change
player.imgy += lead_y_change
pygame.display.flip()
pygame.display.update()
gameLoop()
#start (0, 71)
#length (376, 71)
#width (0, 168)
I think this may be due to the fact that, in the class Player, self.rect isn't right. Instead try:
self.rect = self.img.get_rect()
also, in your main loop, why are you blit-ing stuff in the event for loop?
Only put the key presses in for event in pygame.event.get()
There are other things that are very wrong in the code.
May I recommend this excellent tutorial for making games with sprites in pygame.
Related
i am working on a top down racing game, and currently i am trying to get the car to go on top of the racetrack. There are 2 cars, one is the computer's car (not finished) and the other is the user controlled car, however when i run the programme the user's car is behind the track, but still moves normally. I have tried a few different things, but the user's car never seems to get on top of the track. So i am mainly asking how to get the user's car on top of the track.
Thank you
import math
import random
from tkinter import *
import pygame
class Buttons:
#window
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.quitButton = Button(frame, text="Race!", fg="red", command=frame.quit)
self.quitButton.pack(side=LEFT)
root = Tk()
b = Buttons(root)
root.mainloop()
pygame.mixer.pre_init(44100,16,2,4096)
pygame.init()
screen = pygame.display.set_mode((1280, 800))
rect = screen.get_rect()
clock = pygame.time.Clock()
#music
pygame.mixer.music.load("Noteblock.mp3")
pygame.mixer.music.set_volume(0.5)
pygame.mixer.music.play(-1)
WHITE = pygame.Color('white')
# Load images globally and reuse them in your program.
# Also use the `.convert()` or `.convert_alpha()` methods after
# loading the images to improve the performance.
VEHICLE1 = pygame.Surface((40, 70), pygame.SRCALPHA)
VEHICLE1.fill((130, 180, 20))
#blitting car onto 'rectangle car'
VEHICLE1 = pygame.image.load("YellowLambo.png")
screen.blit(VEHICLE1,(0,0))
pygame.display.update()
VEHICLE2 = pygame.Surface((40, 70), pygame.SRCALPHA)
VEHICLE2.fill((200, 120, 20))
#blitting computer's car
VEHICLE2 = pygame.image.load("RedLambo.png")
screen.blit(VEHICLE2,(0,0))
pygame.display.update()
BACKGROUND = pygame.Surface((1280, 800))
BACKGROUND.fill((127, 69, 2))
BACKGROUND = pygame.image.load("track1.png").convert()
screen.blit(BACKGROUND,(0,0))
pygame.display.update()
class Entity(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
class VehicleSprite(Entity):
MAX_FORWARD_SPEED = 10
MAX_REVERSE_SPEED = 2
ACCELERATION = 0.05
TURN_SPEED = 0.000000000001
def __init__(self, image, position):
Entity.__init__(self)
self.src_image = image
self.image = image
self.rect = self.image.get_rect(center=position)
self.position = pygame.math.Vector2(position)
self.velocity = pygame.math.Vector2(0, 0)
self.speed = self.direction = 0
self.k_left = self.k_right = self.k_down = self.k_up = 0
def update(self, time):
# SIMULATION
self.speed += self.k_up + self.k_down
# To clamp the speed.
self.speed = max(-self.MAX_REVERSE_SPEED,
min(self.speed, self.MAX_FORWARD_SPEED))
# Degrees sprite is facing (direction)
self.direction += (self.k_right + self.k_left)
rad = math.radians(self.direction)
self.velocity.x = -self.speed*math.sin(rad)
self.velocity.y = -self.speed*math.cos(rad)
self.position += self.velocity
self.image = pygame.transform.rotate(self.src_image, self.direction)
self.rect = self.image.get_rect(center=self.position)
class Background(pygame.sprite.Sprite):
def __init__(self, image, location):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.rect = self.image.get_rect(topleft=location)
def game_loop():
bike = VehicleSprite(VEHICLE1, rect.center)
pygame.sprite.LayeredUpdates.move_to_front
ball = VehicleSprite(VEHICLE2, rect.center)
bike_group = pygame.sprite.Group(bike)
ball_group = pygame.sprite.Group(ball)
all_sprites = pygame.sprite.Group(bike_group, ball_group)
background = Background(BACKGROUND, [0, 0])
camera = pygame.math.Vector2(0, 0)
done = False
while not done:
time = clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
# Bike Input (Player 1)
if event.key == pygame.K_d:
bike.k_right = -5
elif event.key == pygame.K_a:
bike.k_left = 5
elif event.key == pygame.K_w:
bike.k_up = 2
elif event.key == pygame.K_s:
bike.k_down = -2
elif event.key == pygame.K_ESCAPE:
done = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_d:
bike.k_right = 0
elif event.key == pygame.K_a:
bike.k_left = 0
elif event.key == pygame.K_w:
bike.k_up = 0
elif event.key == pygame.K_s:
bike.k_down = 0
camera -= bike.velocity
#screen.blit(background.image, background.rect)
all_sprites.update(time)
screen.fill(WHITE)
for sprite in all_sprites:
screen.blit(background.image, background.rect.topleft+camera)
screen.blit(sprite.image, sprite.rect.topleft+camera)
pygame.display.flip()
game_loop()
pygame.quit()
The problem lies in the for loop in which you blit the sprite images:
for sprite in all_sprites:
screen.blit(background.image, background.rect.topleft+camera)
screen.blit(sprite.image, sprite.rect.topleft+camera)
Here you blit the background and one of the sprites, then you blit the background again and the next sprite. So the background will be blit above the previous sprites in each iteration of the for loop.
Just blit the background once before the loop and then the sprites:
screen.fill(WHITE)
screen.blit(background.image, background.rect.topleft+camera)
for sprite in all_sprites:
screen.blit(sprite.image, sprite.rect.topleft+camera)
I think you should blit the racetrack before the cars.
BACKGROUND = pygame.Surface((1280, 800))
BACKGROUND.fill((127, 69, 2))
BACKGROUND = pygame.image.load("track1.png").convert()
screen.blit(BACKGROUND,(0,0))
put this before you blit the cars.
I was confused about how to make the user's car be visible on top of the background. At the moment, when you move the car the track and car move as they should, but the car is under the racetrack. I have tried different blitting orders and i attempted the LayeredUpdates function but it didn't help. I may have been doing it wrong as i am very new to python/pygame. So i would like to know how to get the car to be driving on the track.
Thank you
import math
import random
import pygame
pygame.mixer.pre_init(44100,16,2,4096)
pygame.init()
screen = pygame.display.set_mode((1280, 800))
rect = screen.get_rect()
clock = pygame.time.Clock()
#music
pygame.mixer.music.load("Wice.mp3")
pygame.mixer.music.set_volume(0.5)
pygame.mixer.music.play(-1)
WHITE = pygame.Color('white')
VEHICLE1 = pygame.Surface((40, 70), pygame.SRCALPHA)
VEHICLE1.fill((130, 180, 20))
#blitting car onto 'rectangle car'
VEHICLE1 = pygame.image.load("YellowLambo.png")
screen.blit(VEHICLE1,(0,0))
pygame.display.update()
VEHICLE2 = pygame.Surface((40, 70), pygame.SRCALPHA)
VEHICLE2.fill((200, 120, 20))
#blitting computer's car
VEHICLE2 = pygame.image.load("RedLambo.png")
screen.blit(VEHICLE2,(0,0))
BACKGROUND = pygame.Surface((1280, 800))
BACKGROUND.fill((127, 69, 2))
BACKGROUND = pygame.image.load("track1.png").convert()
screen.blit(BACKGROUND,(0,0))
pygame.display.update()
class Entity(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
class VehicleSprite(Entity):
MAX_FORWARD_SPEED = 10
MAX_REVERSE_SPEED = 2
ACCELERATION = 0.05
TURN_SPEED = 0.000000000001
def __init__(self, image, position):
Entity.__init__(self)
self.src_image = image
self.image = image
self.rect = self.image.get_rect(center=position)
self.position = pygame.math.Vector2(position)
self.velocity = pygame.math.Vector2(0, 0)
self.speed = self.direction = 0
self.k_left = self.k_right = self.k_down = self.k_up = 0
def update(self, time):
# SIMULATION
self.speed += self.k_up + self.k_down
# To clamp the speed.
self.speed = max(-self.MAX_REVERSE_SPEED,
min(self.speed, self.MAX_FORWARD_SPEED))
# Degrees sprite is facing (direction)
self.direction += (self.k_right + self.k_left)
rad = math.radians(self.direction)
self.velocity.x = -self.speed*math.sin(rad)
self.velocity.y = -self.speed*math.cos(rad)
self.position += self.velocity
self.image = pygame.transform.rotate(self.src_image, self.direction)
self.rect = self.image.get_rect(center=self.position)
class Background(pygame.sprite.Sprite):
def __init__(self, image, location):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.rect = self.image.get_rect(topleft=location)
def game_loop():
bike = VehicleSprite(VEHICLE1, rect.center)
pygame.sprite.LayeredUpdates.move_to_front
ball = VehicleSprite(VEHICLE2, rect.center)
bike_group = pygame.sprite.Group(bike)
ball_group = pygame.sprite.Group(ball)
all_sprites = pygame.sprite.Group(bike_group, ball_group)
background = Background(BACKGROUND, [0, 0])
camera = pygame.math.Vector2(0, 0)
done = False
while not done:
time = clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
# Bike Input (Player 1)
if event.key == pygame.K_d:
bike.k_right = -5
elif event.key == pygame.K_a:
bike.k_left = 5
elif event.key == pygame.K_w:
bike.k_up = 2
elif event.key == pygame.K_s:
bike.k_down = -2
elif event.key == pygame.K_ESCAPE:
done = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_d:
bike.k_right = 0
elif event.key == pygame.K_a:
bike.k_left = 0
elif event.key == pygame.K_w:
bike.k_up = 0
elif event.key == pygame.K_s:
bike.k_down = 0
camera -= bike.velocity
all_sprites.update(time)
screen.fill(WHITE)
screen.blit(background.image, background.rect)
for sprite in all_sprites:
screen.blit(background.image, background.rect.topleft+camera)
screen.blit(sprite.image, sprite.rect.topleft+camera)
pygame.display.flip()
game_loop()
pygame.quit()
Look at these lines:
screen.blit(background.image, background.rect)
for sprite in all_sprites:
screen.blit(background.image, background.rect.topleft+camera)
screen.blit(sprite.image, sprite.rect.topleft+camera)
For each sprite you blit to the screen, you blit the background image again.
I guess you want something like:
screen.blit(background.image, background.rect.topleft+camera)
for sprite in all_sprites:
screen.blit(sprite.image, sprite.rect.topleft+camera)
drawing the background only once.
Not sure if it makes a difference but have you tried to replace:
for sprite in all_sprites:
screen.blit(background.image, background.rect.topleft+camera)
screen.blit(sprite.image, sprite.rect.topleft+camera)
with
all_sprites.draw(screen)
i am making a top down car racing game as project (i'm new to python) and i want to know how to make the track (that i have made a background) move, so that when the user's car is moving, the track is essentially moving in the opposite direction so it looks like you are progressing through the course of the circuit. (The camera is focused on the user's car)
Thanks
import math
import random
import pygame
pygame.mixer.pre_init(44100,16,2,4096)
pygame.init()
screen = pygame.display.set_mode((1280, 800))
rect = screen.get_rect()
clock = pygame.time.Clock()
#music
pygame.mixer.music.load("Wice.mp3")
pygame.mixer.music.set_volume(0.5)
pygame.mixer.music.play(-1)
WHITE = pygame.Color('white')
VEHICLE1 = pygame.Surface((40, 70), pygame.SRCALPHA)
VEHICLE1.fill((130, 180, 20))
#blitting car onto 'rectangle car'
VEHICLE1 = pygame.image.load("YellowLambo.png")
screen.blit(VEHICLE1,(0,0))
pygame.display.update()
VEHICLE2 = pygame.Surface((40, 70), pygame.SRCALPHA)
VEHICLE2.fill((200, 120, 20))
#blitting computer's car
VEHICLE2 = pygame.image.load("RedLambo.png")
screen.blit(VEHICLE2,(0,0))
pygame.display.update()
BACKGROUND = pygame.Surface((1280, 800))
BACKGROUND.fill((127, 69, 2))
BACKGROUND = pygame.image.load("track.png").convert()
screen.blit(BACKGROUND,(0,0))
pygame.display.update()
class Entity(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
class VehicleSprite(Entity):
MAX_FORWARD_SPEED = 10
MAX_REVERSE_SPEED = 2
ACCELERATION = 0.05
TURN_SPEED = 0.000000000001
def __init__(self, image, position):
Entity.__init__(self)
self.src_image = image
self.image = image
self.rect = self.image.get_rect(center=position)
self.position = pygame.math.Vector2(position)
self.velocity = pygame.math.Vector2(0, 0)
self.speed = self.direction = 0
self.k_left = self.k_right = self.k_down = self.k_up = 0
def update(self, time):
# SIMULATION
self.speed += self.k_up + self.k_down
# To clamp the speed.
self.speed = max(-self.MAX_REVERSE_SPEED,
min(self.speed, self.MAX_FORWARD_SPEED))
# Degrees sprite is facing (direction)
self.direction += (self.k_right + self.k_left)
rad = math.radians(self.direction)
self.velocity.x = -self.speed*math.sin(rad)
self.velocity.y = -self.speed*math.cos(rad)
self.position += self.velocity
self.image = pygame.transform.rotate(self.src_image, self.direction)
self.rect = self.image.get_rect(center=self.position)
class Background(pygame.sprite.Sprite):
def __init__(self, image, location):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.rect = self.image.get_rect(topleft=location)
def game_loop():
background = Background(BACKGROUND, [0, 0])
bike = VehicleSprite(VEHICLE1, rect.center)
ball = VehicleSprite(VEHICLE2, rect.center)
bike_group = pygame.sprite.Group(bike)
ball_group = pygame.sprite.Group(ball)
all_sprites = pygame.sprite.Group(bike_group, ball_group)
camera = pygame.math.Vector2(0, 0)
done = False
while not done:
time = clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
# Bike Input (Player 1)
if event.key == pygame.K_d:
bike.k_right = -5
elif event.key == pygame.K_a:
bike.k_left = 5
elif event.key == pygame.K_w:
bike.k_up = 2
elif event.key == pygame.K_s:
bike.k_down = -2
elif event.key == pygame.K_ESCAPE:
done = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_d:
bike.k_right = 0
elif event.key == pygame.K_a:
bike.k_left = 0
elif event.key == pygame.K_w:
bike.k_up = 0
elif event.key == pygame.K_s:
bike.k_down = 0
camera -= bike.velocity
all_sprites.update(time)
screen.fill(WHITE)
screen.blit(background.image, background.rect)
for sprite in all_sprites:
screen.blit(sprite.image, sprite.rect.topleft+camera)
pygame.display.flip()
game_loop()
pygame.quit()
Just add the camera vector to the background.rect.topleft position as well:
screen.blit(background.image, background.rect.topleft+camera)
I have a problem with my game which isn't a bug but a problem. I am using spritesheets to make my game and using a for loop to call my Platform class automaticaly. However when I try to call the the platform class it just displays the whole spritesheet. There may be an error in the class platform or level_1 but I am not sure what it is. Please can you help me if you have pygame.
An image of what is happening
import pygame
# Colours + Global constants
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
RANDOM = (12, 211, 123)
WIDTH = 800
HEIGHT = 600
SIZE = (WIDTH, HEIGHT)
# CLASSES
# Block is the common platform
Platform class:
class Platform(pygame.sprite.Sprite):
def __init__(self, display, x_screen, y_screen, x_sheet, y_sheet, height, length):
super().__init__()
self.image = pygame.image.load("tiles_spritesheet.png")
self.rect = self.image.get_rect()
display.blit(self.image, (x_screen, y_screen), (x_sheet, y_sheet, height, length))
Level_1 class:
class Level01(Level):
def __init__(self, player1, monster, display):
# Initialise level1
super().__init__()
# Level01 things
block = Block(WIDTH*3, 3, BLACK)
Level.all_things = self.all_things
self.sprites.add(player1, monster)
self.platforms.add(block)
self.all_things.add(player1, block, monster)
theLevel = [[1, HEIGHT, 0, 0],
[1, HEIGHT, WIDTH*3, 0]]
level = [[600, 400, 710, 0, 70, 70]]
for platform in theLevel:
block = Block(platform[0], platform[1], RED)
block.rect.x = platform[2]
block.rect.y = platform[3]
self.platforms.add(block)
self.all_things.add(block)
for goodPlatform in level:
platform = Platform(display, goodPlatform[0], goodPlatform[1], goodPlatform[2], goodPlatform[3], goodPlatform[4], goodPlatform[5])
self.platforms.add(platform)
self.all_things.add(platform)
main:
def main():
# Init pygame
pygame.init()
# Set screen
background = pygame.image.load("background.jpg")
backgroundRect = background.get_rect()
display = pygame.display.set_mode(background.get_size())
# Creating FPS thingy
clock = pygame.time.Clock()
# Making levels + Player
monster = Monster(30, 30, RANDOM)
player = Player()
level_1 = Level01(player, monster, display)
# Choosing level
levelList = []
levelList.append(level_1)
currentLevelNumber = 0
currentLevel = levelList[currentLevelNumber]
y_speed = -5
# Game loop
loop = True
while loop == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
player.move_right()
if event.key == pygame.K_LEFT:
player.move_left()
if event.key == pygame.K_UP:
player.move_up(currentLevel.platforms)
if event.key == pygame.KMOD_LSHIFT and event.key == pygame.K_RIGHT:
player.sprint()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT and player.sprite_x_change < 0:
player.stop()
if event.key == pygame.K_RIGHT and player.sprite_x_change > 0:
player.stop()
if event.key == pygame.KMOD_LSHIFT:
player.sprite_x_change -= 10
# Update things
#monster.jump()
if player.rect.x > 400:
player.rect.x = 400
currentLevel.scroll_x(-10)
if player.rect.x >= WIDTH:
player.rect.x = WIDTH
currentLevel.scroll(0)
if player.rect.y >= HEIGHT:
main()
if player.sprite_x_change < 0 and player.rect.x >= 120:
currentLevel.scroll_x(0)
if currentLevel.shift_x >= WIDTH *3 - 400:
currentLevel.scroll_x(0)
sprite_x_change = 0
if player.rect.left <= 120 and player.sprite_x_change < 0:
player.rect.x = 120
player.rect.left = 120
currentLevel.scroll_x(10)
'''
if player.rect.y <= 300:
if player.standing == False and player.sprite_y_change < 0:
currentLevel.scroll_y(10)
if currentLevel.shift_y > 0:
y_speed = -4
if player.standing == True and player.rect.y < 300:
y_speed = 4
print(currentLevel.shift_y)
currentLevel.scroll_y(y_speed)
'''
display.blit(background, backgroundRect)
currentLevel.drawer(display)
# Refresh screen
player.updater(currentLevel.platforms)
clock.tick(30)
pygame.display.update()
pygame.quit()
loop = False
if __name__ == "__main__":
main()
Group use self.image and self.rect to blit element so
create subsurface using pygame.Surface.subsurface and (x_sheet, y_sheet, height, length) - and assign to self.image
assign (x_screen, y_screen, height, length) to self.rect
.
class Platform(pygame.sprite.Sprite):
def __init__(self, display, x_screen, y_screen, x_sheet, y_sheet, height, length):
super().__init__()
self.tiles = pygame.image.load("tiles_spritesheet.png")
self.image = self.tiles.subsurface(pygame.Rect(x_sheet, y_sheet, height, length))
self.rect = self.image.get_rect(x=x_screen, y=y_screen)
#display.blit(self.image, self.rect)
I am attempting to build a simple game with two sprites. I can't figure out how to add code that detects if a sprite is touching the other. I am also having trouble understanding the countless tutorials on this topic. If you could try and explain this to me as simply as possible that would be amazing!
import pygame
import sys
from pygame.locals import *
pygame.init()
black = (0, 0, 0)
white = (255, 255, 255)
bg = black
square = pygame.image.load('square.png')
square1 = pygame.image.load('square1.png')
screen = pygame.display.set_mode((640, 400))
UP = 'UP'
DOWN = 'DOWN'
LEFT = 'LEFT'
RIGHT = 'RIGHT'
direction = RIGHT
movex, movey, movex1, movey1 = 100, 100, 200, 200
class player1(pygame.sprite.Sprite):
"""Player 1"""
def __init__(self, xy):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load('square.png')
self.rect = self.image.get_rect()
class player2(pygame.sprite.Sprite):
"""Player 2"""
def __init__(self, xy):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load('square1.png')
self.rect = self.image.get_rect()
while True:
screen.fill(black)
collide = pygame.sprite.collide_mask(player1, player2)
if collide == True:
print 'collision!'
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_w:
movey -= 10
elif event.key == K_s:
movey += 10
elif event.key == K_a:
movex -= 10
elif event.key == K_d:
movex += 10
if event.key == K_UP:
movey1 -= 10
elif event.key == K_DOWN:
movey1 += 10
elif event.key == K_LEFT:
movex1 -= 10
elif event.key == K_RIGHT:
movex1 += 10
if event.type == QUIT:
pygame.quit()
sys.exit()
screen.blit(square, (movex, movey))
screen.blit(square1, (movex1, movey1))
pygame.display.update()
Some issues first:
pygame.sprite.collide_mask never returns True. It returns a point or None. So your check collide == True will never be evaluate to True
pygame.sprite.collide_mask excepts two Sprite instances, but you call it with class objects as arguments (collide_mask(player1, player2))
You only need pygame.sprite.collide_mask when you want to do pixel perfect collision detection
You actually don't use the classes player1 and player2 in the rest of your code
If you're using the Sprite class, a simply way for collision detection is to use the Group class. But since you only have two Sprites, you can simple check for an intersection of their Rects using colliderect.
I've updated your code to make use of the Sprite class:
import pygame
import sys
from pygame.locals import *
pygame.init()
black = (0, 0, 0)
white = (255, 255, 255)
screen = pygame.display.set_mode((640, 400))
class Player(pygame.sprite.Sprite):
def __init__(self, image, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image)
self.rect = self.image.get_rect(x=x, y=y)
player1, player2 = Player('square.png', 100, 100), Player('square1.png', 200, 200)
players = pygame.sprite.Group(player1, player2)
while True:
screen.fill(black)
if player1.rect.colliderect(player2.rect):
print 'collision!'
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_w:
player1.rect.move_ip(0, -10)
elif event.key == K_s:
player1.rect.move_ip(0, 10)
elif event.key == K_a:
player1.rect.move_ip(-10, 0)
elif event.key == K_d:
player1.rect.move_ip(10, 0)
if event.key == K_UP:
player2.rect.move_ip(0, -10)
elif event.key == K_DOWN:
player2.rect.move_ip(0, 10)
elif event.key == K_LEFT:
player2.rect.move_ip(-10, 0)
elif event.key == K_RIGHT:
player2.rect.move_ip(10, 0)
if event.type == QUIT:
pygame.quit()
sys.exit()
players.draw(screen)
pygame.display.update()
Collision detection is a broad topic, but this should get you started.