Using mask for collision detection pygame [duplicate] - python

This question already has an answer here:
Pygame collision with masks
(1 answer)
Closed 2 years ago.
I am trying to make a game where your supposed to land the player on a surface. I have named this surface as 'lander'. Here is my player class:
class player:
def __init__(self, x, y, height, width):
self.ufo = pygame.image.load(r"C:\Users\rahul\OneDrive\Documents\A level python codes\lander\ufo.png")
self.ufo = pygame.transform.scale(self.ufo, (height, width))
self.height = height
self.width = width
self.x = x
self.y = y
self.speed = 0
self.score = 0
def draw(self):
g.screen.blit(self.ufo, (self.x, self.y))
def fly_up(self):
self.speed = 5
p.y = p.y -4
self.y -= self.speed
def fly_right(self):
self.speed = 5
p.y = p.y -4
self.x += self.speed
def fly_left(self):
self.speed = 5
p.y = p.y -4
self.x -= self.speed
Here is my lander class:
class lander:
def __init__(self, x, y, height, width):
self.x = x
self.y = y
self.height = height
self.width = width
self.color = (192, 192, 192)
def draw(self):
self.lander = pygame.draw.rect(g.screen, self.color, (self.x, self.y, self.width, self.height))
def move(self):
self.speed = 4
self.x -= self.speed
def lander_off_screen(self):
if self.x == 0 - p.height - 50:
self.x = 1200 + p.height + 50
self.y = random.randint(230, 590)
I want to detect if they are colliding using masks. However I am having a couple of problems.
Firstly I dont know how to convert self.lander to alpha. It gave me an error when I tried.
Even when I used an actual image instead of a rectange as lander, it didnt work like I
I wanted it to.
Thanks
My code so far for reference is here:
import pygame
import os
import random
import time
os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()
start = time.time()
def main():
class game:
def __init__(self, *args):
self.win = pygame.display
self.SH = 600
self.SW = 1200
self.screen = self.win.set_mode((self.SW, self.SH))
self.win.set_caption("UFO Lander")
self.white = (255, 255, 255)
self.red = (255, 0, 0)
self.green = (0, 255, 0)
self.transparent = (0, 0, 0, 0)
self.background = pygame.image.load(r"C:\Users\rahul\OneDrive\Documents\A level python codes\lander\background.png")
self.background = pygame.transform.scale(self.background, (self.SW, self.SH))
self.transparent = (0, 0, 0, 0)
clock = pygame.time.Clock()
self.FPS = 30
self.FPS = clock.tick(self.FPS)
self.gravity = 4
self.time_passed = pygame.time.get_ticks()/1000
def write(self, text, color, x , y, size):
font = pygame.font.SysFont("Aerial", size)
text = font.render(text, True, color)
textRect = text.get_rect()
self.screen.blit(text,(x , y))
def player_off_screen(self):
if p.x < 0:
p.x = 0
g.write("YOU CRASHED!!", self.red, 50, 250, 200)
g.win.update()
pygame.time.delay(1000)
main()
if p.x + p.height > 1200:
p.x = 1200 - p.height
g.write("YOU CRASHED!!", self.red, 50, 250, 200)
g.win.update()
pygame.time.delay(1000)
main()
if p.y < 0:
p.y = 0
g.write("YOU CRASHED!!", self.red, 50, 250, 200)
g.win.update()
pygame.time.delay(1000)
main()
if p.y + p.width > 600:
p.y = 600 - p.width
g.write("YOU CRASHED!!", self.red, 50, 250, 200)
g.win.update()
pygame.time.delay(1000)
main()
class thrust:
def __init__(self, x, y):
self.thrust = pygame.image.load(r"C:\Users\rahul\OneDrive\Documents\A level python codes\lander\thrust.png")
self.thrust = pygame.transform.scale(self.thrust, (100, 150))
self.x = x
self.y = y
def draw(self):
g.screen.blit(self.thrust, (self.x, self.y))
def update_x(self, variable):
self.x = p.x + variable
def update_y(self, variable):
self.y = p.y + variable
class player:
def __init__(self, x, y, height, width):
self.ufo = pygame.image.load(r"C:\Users\rahul\OneDrive\Documents\A level python codes\lander\ufo.png")
self.ufo = pygame.transform.scale(self.ufo, (height, width))
self.height = height
self.width = width
self.x = x
self.y = y
self.speed = 0
self.score = 0
def draw(self):
g.screen.blit(self.ufo, (self.x, self.y))
def fly_up(self):
self.speed = 5
p.y = p.y -4
self.y -= self.speed
def fly_right(self):
self.speed = 5
p.y = p.y -4
self.x += self.speed
def fly_left(self):
self.speed = 5
p.y = p.y -4
self.x -= self.speed
p = player(100, 100, 350, 150)
t = thrust(p.x, p.y)
t2 = thrust(p.x, p.y)
class obstacles:pass
class lander:
def __init__(self, x, y, height, width):
self.x = x
self.y = y
self.height = height
self.width = width
self.color = (192, 192, 192)
def draw(self):
self.lander = pygame.draw.rect(g.screen, self.color, (self.x, self.y, self.width, self.height))
def move(self):
self.speed = 4
self.x -= self.speed
def lander_off_screen(self):
if self.x == 0 - p.height - 50:
self.x = 1200 + p.height + 50
self.y = random.randint(230, 590)
class fuel:
def __init__(self):
self.x = 100
self.y = 60
self.height = 30
self.width = 300
def draw(self):
pygame.draw.rect(g.screen, g.white, (self.x, self.y, self.width, self.height))
def less_fuel(self):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT or (pygame.K_UP) or (pygame.K_LEFT):
self.change = 0.7
self.width -= self.change
def run_out(self):
if self.width < 0:
g.write("FUEL EMPTY!!", g.red, 50, 250, 200)
g.win.update()
pygame.time.delay(1000)
main()
f = fuel()
class menu: pass
g = game()
run = True
t = thrust(p.x, p.y)
l = lander(1200 - p.height - 50, random.randint(230, 590), 20, p.height+ 50)
while run:
g.screen.blit(g.background, (0, 0))
l.draw()
l.move()
g.write("s", g.white, 350, 10, 50)
g.write("Fuel: ", g.white ,10, 60, 50)
g.write("Score: %d" %(p.score), g.white, 1000, 10, 50)
p.draw()
p.y += g.gravity
g.player_off_screen()
l.lander_off_screen()
t.update_x(50)
t.update_y(110)
t2.update_x(200)
t2.update_y(110)
f.draw()
f.run_out()
try:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
f.less_fuel()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
p.fly_right()
if event.key == pygame.K_LEFT:
p.fly_left()
if event.key == pygame.K_UP:
t.draw()
t2.draw()
p.fly_up()
end = time.time()
duration = end - start
g.write("Total game time: %d" %(duration), g.white ,10, 10, 50)
except NameError:
pass
pygame.display.flip()
if __name__ == "__main__":
main()

Create a pygame.Surface with the size of the rectangle rather than drawing a rectangle:
class lander:
def __init__(self, x, y, height, width):
# [...]
self.image = pygame.Surface((width, height))
self.image.fill((192, 192, 192))
def draw(self):
self.lander = self.image.get_rect(topleft = (self.x, self.y))
g.screen.blit(self.image, self.lander)
Use pygame.mask.from_surface() to create a pygame.mask.Mask object from a Surface:
class player:
def __init__(self, x, y, height, width):
# [...]
self.mask = pygame.mask.from_surface(self.ufo)
class lander:
def __init__(self, x, y, height, width):
# [...]
self.mask = pygame.mask.from_surface(self.image)
Use overlap() to detect the collision of masks. The offset parameter of the method overlap() is the relative position of the othermask in relation to the pygame.mask.Mask object.
In the following p is an instance of player and l is an instance of lander. So the offset is calculated by subtracting the coordinates of p from the coordinates of l:
offset = (l.x - p.x), (l.y - p.y)
if p.mask.overlap(l.mask, offset):
print("hit")
Minimal example: repl.it/#Rabbid76/PyGame-SurfaceMaskIntersect
See also: Mask and Pygame collision with masks is not working

Related

Breakout Game erasing rectangles pygame

I'm making a breakout game using the pygame module, and I've established most of the functionalities. However, I'm having a hard time making the ball collide with the blocks at the top of the screen. Specifically in the "collisions" method in the main class. I wrote a for loop to iterate through the block list to check if the block collided with the ball, and if it did, then it would remove from the row_1 list the respective index of the block, theoretically erasing the block from the screen. But I get an AttributeError: 'pygame.Rect' object has no attribute 'collidirect'. I appreciate the help.
import pygame, sys
pygame.init()
clock = pygame.time.Clock()
screen_width = 600
screen_height = 750
black = (0, 0, 0)
white = (255, 255, 255)
purple = (138, 43, 226)
red = (255, 0, 0)
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Breakout Game")
class BLOCK:
def __init__(self):
self.width = 54
self.height = 20
self.row_1 = [[5, 20]]
self.blocks = []
for i in range(9):
self.row_1.append(self.row_1[-1][:])
self.row_1[-1][0] += 59
def draw_blocks(self):
for cor in self.row_1:
block_rect = pygame.Rect(cor[0], cor[1], self.width, self.height)
self.blocks.append(block_rect)
pygame.draw.rect(screen, red, block_rect)
class BALL:
def __init__(self):
self.width = 15
self.height = 15
self.x = screen_width/2 - self.width/2
self.y = screen_height/2 - self.height/2
self.speed_x = 5
self.speed_y = 5
self.ball_rect = pygame.Rect(self.x, self.y, self.width, self.height)
def draw_ball(self):
pygame.draw.ellipse(screen, white, self.ball_rect)
def move_ball(self):
self.x += self.speed_x
self.y += self.speed_y
self.ball_rect.topleft = (self.x, self.y)
def wall_collision(self):
if self.x >= screen_width - self.width:
self.speed_x *= -1
if self.x <= 0:
self.speed_x *= -1
if self.y >= screen_height - self.height:
self.x = screen_width/2 - self.width/2
self.y = screen_height / 2 - self.height/2
if self.y <= 0:
self.speed_y *= -1
class PADDLE:
def __init__(self):
self.width = 100
self.height = 10
self.x = screen_width/2 - self.width/2
self.y = 600
self.speed = 7
self.paddle_rect = pygame.Rect(self.x, self.y, self.width, self.height)
def draw_paddle(self):
pygame.draw.rect(screen, purple, self.paddle_rect)
def move_paddle(self):
key = pygame.key.get_pressed()
if key[pygame.K_LEFT]:
self.x -= self.speed
if key[pygame.K_RIGHT]:
self.x += self.speed
self.paddle_rect.topleft = (self.x, self.y)
class MAIN:
def __init__(self):
self.block = BLOCK()
self.ball = BALL()
self.paddle = PADDLE()
def draw(self):
self.block.draw_blocks()
self.ball.draw_ball()
self.paddle.draw_paddle()
def move(self):
self.ball.move_ball()
self.paddle.move_paddle()
def collisions(self):
self.ball.wall_collision()
if self.ball.ball_rect.colliderect(self.paddle.paddle_rect):
self.ball.speed_y *= -1
for block in self.block.blocks:
if block.collidirect(self.ball.ball_rect):
self.block.row_1.pop(self.block.blocks.index(block))
main = MAIN()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.fill(black)
main.draw()
main.move()
main.collisions()
pygame.display.flip()
clock.tick(60)
It's a typo. The name of the method is colliderect rather then collidirect:
if block.collidirect(self.ball.ball_rect):
if block.colliderect(self.ball.ball_rect):

Creating Multiple of the same image in pygame [duplicate]

This question already has answers here:
Spawning multiple instances of the same object concurrently in python
(1 answer)
Trying to delay a specific function for spawning enemy after a certain amount of time
(1 answer)
Closed 2 years ago.
I wonder how I can spawn objects (like an enemy) at a random position with a 2 seconds delay/cooldown.
I know how to spawn them at a random coordinate. But what I'm wondering is how I can spawn multiple objects and still keep track of the other ones that are already moving, kind of like you do when you shoot bullets in a pygame.
The time delay/cooldown I can probably solve just by using pygame.time.get_ticks(). So my main question is how I can spawn multiple objects and track them with hitboxes (which I have already made)
Here is the basic part that in this example spawns an asteroid.
class Enemy:
asteroids = [pygame.image.load('rock0.png'), pygame.image.load('rock1.png'), pygame.image.load('rock2.png'),
pygame.image.load('rock3.png'), pygame.image.load('rock4.png')]
def __init__(self, y, width, height):
self.width = width
self.height = height
self.vel = 1.5
self.x = random.randrange(screen_width - self.width * 2)
self.y = y
self.asteroid = random.choice(self.asteroids)
def draw(self, win):
self.move()
win.blit(self.asteroid, (self.x, self.y))
def move(self):
self.y = self.y + self.vel
Here is the entire code for anybody who needs it.
import pygame
import random
pygame.init()
screen_width = 500
screen_height = 500
win = pygame.display.set_mode((screen_width, screen_height))
walk_left = [pygame.image.load('sprite_5.png'), pygame.image.load('sprite_6.png')]
walk_right = [pygame.image.load('sprite_3.png'), pygame.image.load('sprite_4.png')]
standing = [pygame.image.load('sprite_0.png'), pygame.image.load('sprite_1.png'), pygame.image.load('sprite_2.png')]
class Player:
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height
self.vel = 4
self.left = False
self.right = False
self.standing = True
self.walk_count = 0
self.hitbox = (self.x + 2, self.y + 26, 123, 45)
def draw(self, win):
if self.walk_count + 1 >= 12:
self.walk_count = 0
if not self.standing:
if self.left:
win.blit(walk_left[self.walk_count // 6], (self.x, self.y))
self.walk_count += 1
elif self.right:
win.blit(walk_right[self.walk_count // 6], (self.x, self.y))
self.walk_count += 1
else:
win.blit(standing[self.walk_count // 4], (self.x, self.y))
self.walk_count += 1
self.hitbox = (self.x + 2, self.y + 26, 123, 45)
pygame.draw.rect(win, (255, 0, 0), self.hitbox, 2)
def move():
if keys[pygame.K_LEFT] and man.x > man.vel or keys[pygame.K_a] and man.x > man.vel:
man.x -= man.vel
man.left = True
man.right = False
man.standing = False
elif keys[pygame.K_RIGHT] and man.x < 500 - man.width - man.vel:
man.x += man.vel
man.left = False
man.right = True
man.standing = False
else:
man.standing = True
class Enemy:
asteroids = [pygame.image.load('rock0.png'), pygame.image.load('rock1.png'), pygame.image.load('rock2.png'),
pygame.image.load('rock3.png'), pygame.image.load('rock4.png')]
number = [0, 1, 2, 3, 4]
def __init__(self, y, width, height):
self.width = width
self.height = height
self.vel = 1.5
self.x = random.randrange(screen_width - self.width * 2)
self.y = y
self.index = random.choice(self.number)
self.hitbox = (self.x, self.y, self.width, self.height)
def draw(self, win):
self.move()
win.blit(self.asteroids[self.index], (self.x, self.y))
if self.index == 0:
self.hitbox = (self.x + 68, self.y + 68, self.width - 10, self.height - 14)
pygame.draw.rect(win, (255, 0, 0), self.hitbox, 2)
elif self.index == 1:
self.hitbox = (self.x + 38, self.y + 47, self.width + 20, self.height - 5)
pygame.draw.rect(win, (255, 0, 0), self.hitbox, 2)
elif self.index == 2:
self.hitbox = (self.x + 18, self.y + 12, self.width + 32, self.height + 30)
pygame.draw.rect(win, (255, 0, 0), self.hitbox, 2)
elif self.index == 3:
self.hitbox = (self.x + 20, self.y + 32, self.width + 16, self.height + 5)
pygame.draw.rect(win, (255, 0, 0), self.hitbox, 2)
else:
self.hitbox = (self.x + 4, self.y + 7, self.width - 24, self.height - 31)
pygame.draw.rect(win, (255, 0, 0), self.hitbox, 2)
def move(self):
self.y = self.y + self.vel
class Projectile:
def __init__(self, x, y, width, height, color):
self.x = x
self.y = y
self.width = width
self.height = height
self.color = color
self.vel = 5
def draw(self, win):
pygame.draw.rect(win, self.color, (self.x, self.y, self.height, self. width))
class Unit:
def __init__(self):
self.last = pygame.time.get_ticks()
self.cooldown = 200
def fire(self):
now = pygame.time.get_ticks()
if now - self.last >= self.cooldown:
self.last = now
spawn_bullet()
def spawn_bullet():
if keys[pygame.K_SPACE]:
bullets.append(Projectile((man.x + man.width // 2), (man.y - 7), 7, 3, (255, 0, 0)))
def re_draw():
win.fill((0, 0, 0))
asteroid.draw(win)
man.draw(win)
for bullet in bullets:
bullet.draw(win)
pygame.display.update()
delay = Unit()
man = Player(186, 400, 128, 128)
bullets = []
asteroid = Enemy(10, 64, 64)
run = True
clock = pygame.time.Clock()
while run:
last = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
for bullet in bullets:
if 0 < bullet.y < 500:
bullet.y -= bullet.vel
else:
bullets.pop(bullets.index(bullet))
keys = pygame.key.get_pressed()
move()
delay.fire()
clock.tick(60)
re_draw()
pygame.quit()
I recommend to use a timer event. Use pygame.time.set_timer() to repeatedly create an event on the event queue.
Use a pygame.sprite.Group and derive Enemy from pygame.sprite.Sprite to manage multiple enemies. Note it is important to use the attributes .image and .rect in a sprite. e.g.:
class Enemy(pygame.sprite.Sprite):
asteroids = [pygame.image.load('rock0.png'), pygame.image.load('rock1.png'), pygame.image.load('rock2.png'),
pygame.image.load('rock3.png'), pygame.image.load('rock4.png')]
def __init__(self, y, width, height):
super().__init__()
self.width = width
self.height = height
self.vel = 1.5
x = random.randrange(screen_width - self.width * 2)
self.image = random.choice(self.asteroids)
self.rect = self.image.get_rect(center = (x, y))
def move(self):
self.rect.y += self.vel
enemies = pygame.sprite.Group()
my_event_id = pygame.USEREVENT + 1
pygame.time.set_timer(my_event_id, 2000) # 2000 milliseconds = 2 seconds
run = True
while run:
last = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == my_event_id:
# spawn new enemy
enemies.add(Enemy(10, 64, 64))
# [...]
for e in enemies:
e.move()
# [...]
enemies.draw(win)
If you make Projectile a pygame.sprite.Sprite, then you can use and bullets a pygame.sprite.Group, then you can use pygame.sprite.spritecollide() or pygame.sprite.groupcollide() to find hits and kill the enemies. e.g.:
class Projectile(pygame.sprite.Sprite):
def __init__(self, x, y, width, height, color):
super().__init__()
self.image = pygame.Surface((width, height))
self.image.fill(color)
self.rect = self.image.get_rect(center = (x, y))
self.vel = 5
def move(self):
self.rect.y -= self.vel
bullets = pygame.sprite.Group()
def spawn_bullet():
if keys[pygame.K_SPACE]:
bullets.add(Projectile((man.x + man.width // 2), (man.y - 7), 3, 7, (255, 0, 0)))
def re_draw():
win.fill((0, 0, 0))
enemies.draw(win)
man.draw(win)
bullets.draw(win)
pygame.display.update()
while run:
# [...]
for e in enemies:
e.move()
if e.rect.y > 500:
e.kill()
for b in bullets:
b.move()
if 0 > b.rect.y or b.rect.y > 500:
b.kill()
pygame.sprite.groupcollide(bullets, enemies, True, True)
Full code:
import pygame
import random
pygame.init()
screen_width = 500
screen_height = 500
win = pygame.display.set_mode((screen_width, screen_height))
walk_left = [pygame.image.load('sprite_5.png'), pygame.image.load('sprite_6.png')]
walk_right = [pygame.image.load('sprite_3.png'), pygame.image.load('sprite_4.png')]
standing = [pygame.image.load('sprite_0.png'), pygame.image.load('sprite_1.png'), pygame.image.load('sprite_2.png')]
class Player:
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height
self.vel = 4
self.left = False
self.right = False
self.standing = True
self.walk_count = 0
self.hitbox = (self.x + 2, self.y + 26, 123, 45)
def draw(self, win):
if self.walk_count + 1 >= 12:
self.walk_count = 0
if not self.standing:
if self.left:
win.blit(walk_left[self.walk_count // 6], (self.x, self.y))
self.walk_count += 1
elif self.right:
win.blit(walk_right[self.walk_count // 6], (self.x, self.y))
self.walk_count += 1
else:
win.blit(standing[self.walk_count // 4], (self.x, self.y))
self.walk_count += 1
self.hitbox = (self.x + 2, self.y + 26, 123, 45)
pygame.draw.rect(win, (255, 0, 0), self.hitbox, 2)
def move():
if keys[pygame.K_LEFT] and man.x > man.vel or keys[pygame.K_a] and man.x > man.vel:
man.x -= man.vel
man.left = True
man.right = False
man.standing = False
elif keys[pygame.K_RIGHT] and man.x < 500 - man.width - man.vel:
man.x += man.vel
man.left = False
man.right = True
man.standing = False
else:
man.standing = True
class Enemy(pygame.sprite.Sprite):
asteroids = [pygame.image.load('rock0.png'), pygame.image.load('rock1.png'), pygame.image.load('rock2.png'),
pygame.image.load('rock3.png'), pygame.image.load('rock4.png')]
def __init__(self, y, width, height):
super().__init__()
self.width = width
self.height = height
self.vel = 1.5
x = random.randrange(screen_width - self.width * 2)
self.image = random.choice(self.asteroids)
self.rect = self.image.get_rect(topleft = (x, y))
def move(self):
self.rect.y += self.vel
class Projectile(pygame.sprite.Sprite):
def __init__(self, x, y, width, height, color):
super().__init__()
self.image = pygame.Surface((width, height))
self.image.fill(color)
self.rect = self.image.get_rect(topleft = (x, y))
self.vel = 5
def move(self):
self.rect.y -= self.vel
my_event_id = pygame.USEREVENT + 1
pygame.time.set_timer(my_event_id, 2000) # 2000 milliseconds = 2 seconds
class Unit:
def __init__(self):
self.last = pygame.time.get_ticks()
self.cooldown = 200
def fire(self):
now = pygame.time.get_ticks()
if now - self.last >= self.cooldown:
self.last = now
spawn_bullet()
def spawn_bullet():
if keys[pygame.K_SPACE]:
bullets.add(Projectile((man.x + man.width // 2), (man.y - 7), 3, 7, (255, 0, 0)))
def re_draw():
win.fill((0, 0, 0))
enemies.draw(win)
man.draw(win)
bullets.draw(win)
pygame.display.update()
delay = Unit()
man = Player(186, 400, 128, 128)
bullets = pygame.sprite.Group()
enemies = pygame.sprite.Group()
run = True
clock = pygame.time.Clock()
while run:
last = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == my_event_id:
# spawn new enemy
enemies.add(Enemy(10, 64, 64))
for e in enemies:
e.move()
if e.rect.y > 500:
e.kill()
for b in bullets:
b.move()
if 0 > b.rect.y or b.rect.y > 500:
b.kill()
pygame.sprite.groupcollide(bullets, enemies, True, True)
keys = pygame.key.get_pressed()
move()
delay.fire()
clock.tick(60)
re_draw()
pygame.quit()

Snake bodies not appending to snake correctly [duplicate]

This question already has an answer here:
How do I get the snake to grow and chain the movement of the snake's body?
(1 answer)
Closed 2 years ago.
I finally figured out how to add body parts to my snake, but they add on in an unusual way. I have been struggling on this for a while, and finally made it so they append. But they don't do it correctly. It seems like they append 1 pixel behind instead of a full bodies length. Does anyone know why?
# Constants
WIN_WIDTH = 500
WIN_HEIGHT = 600
HALF_WIN_WIDTH = WIN_WIDTH / 2
HALF_WIN_HEIGHT = WIN_HEIGHT / 2
FPS = 10
# Colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
DARK_GREEN = (0, 100, 0)
YELLOW = (255, 255, 0)
# Variables
screen = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT))
pygame.display.set_caption("Snake")
clock = pygame.time.Clock()
running = True
class Text:
def __init__(self, x, y, size, font, color, text):
self.x = x
self.y = y
self.size = size
self.font = font
self.color = color
self.text = text
def draw(self):
self.my_font = pygame.font.SysFont(self.font, self.size)
self.text_surface = self.my_font.render(self.text, True, self.color)
screen.blit(self.text_surface, (self.x, self.y))
class Food:
def __init__(self, x, y):
self.x = x
self.y = y
self.width = 25
self.height = 25
def draw(self):
self.rect = (self.x, self.y, self.width, self.height)
pygame.draw.rect(screen, BLUE, self.rect)
def events(self):
pass
def update(self):
pass
class Body:
def __init__(self, x, y):
self.x = x
self.y = y
self.width = 25
self.height = 25
def draw(self):
self.rect = pygame.Rect(self.x, self.y, self.width, self.height)
pygame.draw.rect(screen, YELLOW, self.rect)
# Snake class
class Snake:
def __init__(self, x, y):
self.x = x
self.y = y
self.width = 25
self.height = 25
self.direction = 1
self.kill = False
self.collide = False
self.speed = 3
self.score = 0
self.bodies = []
def draw(self):
self.rect = pygame.Rect(self.x, self.y, self.width, self.height)
pygame.draw.rect(screen, BLACK, self.rect)
def events(self):
# change direction on key press
self.keys = pygame.key.get_pressed()
if self.keys[pygame.K_UP] and self.direction != 3:
self.direction = 1
if self.keys[pygame.K_DOWN] and self.direction != 1:
self.direction = 3
if self.keys[pygame.K_LEFT] and self.direction != 2:
self.direction = 4
if self.keys[pygame.K_RIGHT] and self.direction != 4:
self.direction = 2
if self.rect.colliderect(food.rect):
self.speed += 0.5
food.x = random.randint(0, WIN_WIDTH)
food.y = random.randint(0, WIN_HEIGHT)
self.score += 5
self.colliide = False
self.bodies.append(Body(0, 0))
# Move the end bodies first in reverse order
for i in range(len(self.bodies)-1, 0, -1):
x = snake.bodies[i-1].x
y = snake.bodies[i-1].y
snake.bodies[i].x = x
snake.bodies[i].y = y
snake.bodies[i].draw()
# Move body 0 to where the head is
if len(snake.bodies) > 0:
x = snake.x
y = snake.y
snake.bodies[0].x = x
snake.bodies[0].y = y
snake.bodies[0].draw()
def update(self):
# move
if self.direction == 1:
self.y -= self.speed
if self.direction == 2:
self.x += self.speed
if self.direction == 3:
self.y += self.speed
if self.direction == 4:
self.x -= self.speed
# if on edge of screen
if self.rect.right > WIN_WIDTH:
self.kill = True
if self.x < 0:
self.kill = True
if self.y < 0:
self.kill = True
if self.rect.bottom > WIN_HEIGHT:
self.kill = True
# Create the snake object
snake = Snake(HALF_WIN_WIDTH, HALF_WIN_HEIGHT)
food = Food(random.randint(0, WIN_WIDTH), random.randint(0, WIN_HEIGHT))
# Main Loop
while running:
score_text = Text(220, 5, 40, 'arial', WHITE, f'Score: {snake.score}')
# Draw
screen.fill(DARK_GREEN)
snake.draw()
food.draw()
score_text.draw()
# Event handling
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if snake.kill:
running = False
snake.events()
# Update
snake.update()
food.update()
clock.tick(60)
pygame.display.update()
Thank you very much!
You have to track the positions which have been met by the snake. Add a list attribute self.position to the class Snake:
class Snake:
def __init__(self, x, y):
# [...]
self.positions = [(self.x, self.y)]
# [...]
Add the new position to the list when the snake moves:
class Snake:
# [...]
def update(self):
# move
if self.direction == 1:
self.y -= self.speed
if self.direction == 2:
self.x += self.speed
if self.direction == 3:
self.y += self.speed
if self.direction == 4:
self.x -= self.speed
# add ne position
if self.x != self.positions[0][0] or self.y != self.positions[0][1]:
self.positions.insert(0, (self.x, self.y))
Update the x and y coordinate of the body along the stored positions in events. Define a distance between the parts of the body (e.g. 35). And use a method getPos to get the position of a part, by its index:
class Snake:
# [...]
def events(self):
# change direction on key press
self.keys = pygame.key.get_pressed()
if self.keys[pygame.K_UP] and self.direction != 3:
self.direction = 1
if self.keys[pygame.K_DOWN] and self.direction != 1:
self.direction = 3
if self.keys[pygame.K_LEFT] and self.direction != 2:
self.direction = 4
if self.keys[pygame.K_RIGHT] and self.direction != 4:
self.direction = 2
if self.rect.colliderect(food.rect):
self.speed += 0.5
food.x = random.randint(100, WIN_WIDTH - 125)
food.y = random.randint(150, WIN_HEIGHT - 175)
self.score += 5
self.colliide = False
self.bodies.append(Body(0, 0))
# Move the end bodies first in reverse order
for i in range(len(self.bodies)):
pos = self.getPos(i+1, 35, i == len(self.bodies)-1)
snake.bodies[i].x = pos[0]
snake.bodies[i].y = pos[1]
snake.bodies[i].draw()
The arguments to method getPos are the index of the body part, the distance between the parts and delToEnd. delToEnd becomes true, when the last part of the body is get and indicates, that the positions at the end of the list, which are "behind" the last part of the snake can be deleted:
class Snake:
# [...]
def getPos(self, i, dist, delToEnd):
lenToI = i * dist
lenAct = 0
px, py = self.positions[-1]
for j in range(len(self.positions)-1):
px, py = self.positions[j]
pnx, pny = self.positions[j+1]
delta = math.sqrt((px-pnx)*(px-pnx) + (py-pny)*(py-pny))
lenAct += delta
if lenAct >= lenToI:
w = (lenAct - lenToI) / delta
px = pnx - (pnx-px) * w
py = pny - (pny-py) * w
if delToEnd:
del self.positions[j:]
break
return (round(px), round(py))

How can I make objects permanently stick in window without being refreshed in Pygame?

I am trying to recreate Atari Breakout using Pygame. I met with a problem, I put all three rows of the tiles in three lists and I want to print them and make them stay at the location before the ball hits them.
This is the code:
import pygame
import random
pygame.init()
screenWidth = 1200
screenHeight = 700
window = pygame.display.set_mode((screenWidth,screenHeight))
pygame.display.set_caption('Atari Breakout')
pygame.mouse.set_pos(-500,650)
class Plate():
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height
self.vel = 5
def draw_plate(self):
pygame.mouse.set_visible(True)
pos = pygame.mouse.get_pos()
self.x = pos[0]-100
pygame.draw.rect(window, (00,00,255), (self.x, self.y ,self.width, self.height))
class Circle():
def __init__(self, x, y, radius):
self.x = x
self.y = y
self.radius = radius
self.vel_x = 5
self.vel_y = 5
class Tiles():
def __init__(self, x, y, width, height, color):
self.x = x
self.y = y
self.width = width
self.height = height
self.color = color
def draw(self):
if self.color == 'red':
pygame.draw.rect(window, (255,0,0), (self.x, self.y, self.width, self.height))
elif self.color == 'green':
pygame.draw.rect(window, (44,176,55), (self.x, self.y, self.width, self.height))
elif self.color == 'blue':
pygame.draw.rect(window, (0,191,255), (self.x, self.y, self.width, self.height))
pygame.display.update()
def draw_titles():
first_row = []
second_row = []
third_row = []
preset_width1 = [70, 120, 200, 30, 240, 140, 130, 120, 80] # nine elements
preset_width2 = [70, 120, 200, 30, 240, 140, 130, 120, 80]
preset_width3 = [70, 120, 200, 30, 240, 140, 130, 120, 80]
random.shuffle(preset_width1)
random.shuffle(preset_width2)
random.shuffle(preset_width3)
#print(f'preset_width1 is: {preset_width1}')
put_width1 = []
put_width2 = []
put_width3 = []
for t in range(1,10):
if t==1:
width = preset_width1.pop(0)
put_width1.append(width)
#print(f'put_width1 is: {put_width1}')
if t==1:
x = 0 + 5
else:
add = sum(put_width1)
#print(f'add is: {add}')
x = t*5 + add
#print(f'x is: {x}')
if t>1:
width = preset_width1.pop(0)
put_width1.append(width)
#print(f'put_width1 is: {put_width1}')
y = 125
height = 35
first_row.append(Tiles(x,y,width,height,'red'))
if t == 9:
break
for t in range(1,10):
if t==1:
width = preset_width2.pop(0)
put_width2.append(width)
if t==1:
x = 0 + 5
else:
add = sum(put_width2)
x = t*5 + add
if t>1:
width = preset_width2.pop(0)
put_width2.append(width)
y = 170
height = 35
second_row.append(Tiles(x,y,width,height,'green'))
if t == 9:
break
for t in range(1,10):
if t==1:
width = preset_width3.pop(0)
put_width3.append(width)
if t==1:
x = 0 + 5
else:
add = sum(put_width3)
x = t*5 + add
if t>1:
width = preset_width3.pop(0)
put_width3.append(width)
y = 215
height = 35
third_row.append(Tiles(x,y,width,height,'blue'))
if t == 9:
break
for num in range(0,9):
first_row[num].draw()
for num in range(0,9):
second_row[num].draw()
for num in range(0,9):
third_row[num].draw()
keys = pygame.key.get_pressed()
if keys[pygame.K_BACKSPACE]:
run = False
# main loop
plate = Plate(10,650,200,40)
ball = Circle(600,300,10)
run = True
start = False
bounds = pygame.Rect(0, 0, 1200, 700)
while run:
pygame.time.Clock().tick(120)
for event in pygame.event.get():
if event == pygame.QUIT:
run = False
plate.draw_plate()
keys = pygame.key.get_pressed()
# bounce algorithem
if keys[pygame.K_SPACE]:
start = True
if start:
ball.y -= ball.vel_y
ball.x += ball.vel_x
if ball.x - ball.radius < bounds.left or ball.x + ball.radius > bounds.right:
ball.vel_x *= -1
if ball.y - ball.radius < bounds.top or ball.y + ball.radius > bounds.bottom:
ball.vel_y *= -1
pygame.draw.rect(window, (0, 0, 0), bounds, 1)
pygame.draw.circle(window, (44,176,55), (ball.x, ball.y), ball.radius)
#pygame.display.update()
draw_titles()
# close call
if keys[pygame.K_BACKSPACE]:
run = False
break
window.fill((0,0,0))
pygame.display.update()
pygame.quit()
This is the ideal situation:
But instead, it refreshes like crazy. I know the problem is I put the draw_titles() function inside of the main While loop. But I believe is the way I code the draw_tiles() function that made it not work. If I place draw_titles() before the loop, the tiles will appear and instantly disappear and both the ball and the plate will not display.
I did some research online and I see tutorial for text and images. For images, they use .blit() but I believe it is only for images.
I had tried many variations to fix this but to no avail. Please help.
Thank you.
Here's a quick fix:
import pygame
import random
pygame.init()
screenWidth = 1200
screenHeight = 700
window = pygame.display.set_mode((screenWidth,screenHeight))
pygame.display.set_caption('Atari Breakout')
pygame.mouse.set_pos(-500,650)
class Plate():
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height
self.vel = 5
def draw_plate(self):
pygame.mouse.set_visible(True)
pos = pygame.mouse.get_pos()
self.x = pos[0]-100
pygame.draw.rect(window, (00,00,255), (self.x, self.y ,self.width, self.height))
class Circle():
def __init__(self, x, y, radius):
self.x = x
self.y = y
self.radius = radius
self.vel_x = 5
self.vel_y = 5
class Tiles():
def __init__(self, x, y, width, height, color):
self.x = x
self.y = y
self.width = width
self.height = height
self.color = color
def draw(self):
if self.color == 'red':
pygame.draw.rect(window, (255,0,0), (self.x, self.y, self.width, self.height))
elif self.color == 'green':
pygame.draw.rect(window, (44,176,55), (self.x, self.y, self.width, self.height))
elif self.color == 'blue':
pygame.draw.rect(window, (0,191,255), (self.x, self.y, self.width, self.height))
first_row = []
second_row = []
third_row = []
def create_titles():
preset_width1 = [70, 120, 200, 30, 240, 140, 130, 120, 80] # nine elements
preset_width2 = [70, 120, 200, 30, 240, 140, 130, 120, 80]
preset_width3 = [70, 120, 200, 30, 240, 140, 130, 120, 80]
random.shuffle(preset_width1)
random.shuffle(preset_width2)
random.shuffle(preset_width3)
#print(f'preset_width1 is: {preset_width1}')
put_width1 = []
put_width2 = []
put_width3 = []
for t in range(1,10):
if t==1:
width = preset_width1.pop(0)
put_width1.append(width)
#print(f'put_width1 is: {put_width1}')
if t==1:
x = 0 + 5
else:
add = sum(put_width1)
#print(f'add is: {add}')
x = t*5 + add
#print(f'x is: {x}')
if t>1:
width = preset_width1.pop(0)
put_width1.append(width)
#print(f'put_width1 is: {put_width1}')
y = 125
height = 35
first_row.append(Tiles(x,y,width,height,'red'))
if t == 9:
break
for t in range(1,10):
if t==1:
width = preset_width2.pop(0)
put_width2.append(width)
if t==1:
x = 0 + 5
else:
add = sum(put_width2)
x = t*5 + add
if t>1:
width = preset_width2.pop(0)
put_width2.append(width)
y = 170
height = 35
second_row.append(Tiles(x,y,width,height,'green'))
if t == 9:
break
for t in range(1,10):
if t==1:
width = preset_width3.pop(0)
put_width3.append(width)
if t==1:
x = 0 + 5
else:
add = sum(put_width3)
x = t*5 + add
if t>1:
width = preset_width3.pop(0)
put_width3.append(width)
y = 215
height = 35
third_row.append(Tiles(x,y,width,height,'blue'))
if t == 9:
break
# main loop
plate = Plate(10,650,200,40)
ball = Circle(600,300,10)
run = True
start = False
bounds = pygame.Rect(0, 0, 1200, 700)
create_titles()
while run:
pygame.time.Clock().tick(120)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
# bounce algorithem
if keys[pygame.K_SPACE]:
start = True
# close call
if keys[pygame.K_BACKSPACE]:
run = False
break
if start:
ball.y -= ball.vel_y
ball.x += ball.vel_x
if ball.x - ball.radius < bounds.left or ball.x + ball.radius > bounds.right:
ball.vel_x *= -1
if ball.y - ball.radius < bounds.top or ball.y + ball.radius > bounds.bottom:
ball.vel_y *= -1
window.fill((0,0,0))
plate.draw_plate()
pygame.draw.rect(window, (0, 0, 0), bounds, 1)
pygame.draw.circle(window, (44,176,55), (ball.x, ball.y), ball.radius)
for tile in first_row:
tile.draw()
for tile in second_row:
tile.draw()
for tile in third_row:
tile.draw()
pygame.display.update()
pygame.quit()
When drawing to the screen, clear the screen surface first, then draw all objects, like this:
...
window.fill((0,0,0))
plate.draw_plate()
pygame.draw.rect(window, (0, 0, 0), bounds, 1)
pygame.draw.circle(window, (44,176,55), (ball.x, ball.y), ball.radius)
for tile in first_row:
tile.draw()
for tile in second_row:
tile.draw()
for tile in third_row:
tile.draw()
...
Note how all drawing related stuff is in one place. This way, it's clearer and less confusing.
You should make sure to only call pygame.display.flip() (or .update()) only once per frame (as Rabbid76 already said in a comment).
I also moved the lists outside the draw_titles function, which I renamed to create_titles. The function creates the tiles, so it should only be done once, not every frame.
You should also probably look into pygame's Sprite and Group class. Here's an example I hacked together which makes use of some pygame features:
import pygame
import random
class Paddle(pygame.sprite.Sprite):
def __init__(self, x, y, width, height, bounds, *grps):
super().__init__(*grps)
self.image = pygame.Surface((width, height))
self.image.fill((0,0,255))
self.rect = self.image.get_rect(topleft=(x, y))
self.bounds = bounds
def update(self, dt):
pos = pygame.mouse.get_pos()
self.rect.centerx = pos[0]
self.rect.clamp_ip(self.bounds)
class Circle(pygame.sprite.Sprite):
def __init__(self, x, y, radius, bounds, *grps):
super().__init__(*grps)
self.image = pygame.Surface((radius, radius))
self.image.set_colorkey((1, 2, 3))
self.image.fill((1, 2, 3))
self.rect = self.image.get_rect(topleft=(x, y))
pygame.draw.circle(self.image, (44,176,55), (radius//2, radius//2), 5)
self.vel = pygame.Vector2((5, 5))
self.pos = self.rect.center
self.bounds = bounds
def update(self, dt):
self.pos += self.vel * min(dt/15, 10)
self.rect.center = self.pos
if self.rect.left < self.bounds.left or self.rect.right > self.bounds.right:
self.vel.x *= -1
if self.rect.top < self.bounds.top or self.rect.bottom > self.bounds.bottom:
self.vel.y *= -1
self.rect.clamp_ip(self.bounds)
def bounce(self, sprite):
if self.rect.top <= sprite.rect.top or sprite.rect.bottom >= sprite.rect.bottom:
self.vel.y *= -1
elif self.rect.left <= sprite.rect.left or sprite.rect.right >= sprite.rect.right:
self.vel.x *= -1
class Tiles(pygame.sprite.Sprite):
def __init__(self, x, y, width, height, color, *grps):
super().__init__(*grps)
self.image = pygame.Surface((width, height))
self.image.fill(color)
self.rect = self.image.get_rect(topleft=(x, y))
def hit(self):
self.kill()
def main():
pygame.init()
screen = pygame.display.set_mode((1200, 700))
screen_rect = screen.get_rect()
pygame.display.set_caption('Atari Breakout')
sprites = pygame.sprite.Group()
tiles = pygame.sprite.Group()
paddle = Paddle(10,650,200,40, screen_rect, sprites)
ball = Circle(600,300,10, screen_rect, sprites)
preset = [70, 120, 200, 30, 240, 140, 130, 120, 80]
y = 215
for color in ['blue', 'green', 'red']:
x = 5
line = preset[:]
random.shuffle(line)
for width in line:
Tiles(x, y, width, 35, pygame.Color(color), sprites, tiles)
x += width + 5
y -= 45
dt = 0
clock = pygame.time.Clock()
while True:
pygame.time.Clock().tick(120)
# events
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_BACKSPACE:
return
# game logic
tile = pygame.sprite.spritecollideany(ball, tiles)
if tile:
tile.hit()
ball.bounce(tile)
if pygame.sprite.collide_rect(paddle, ball):
ball.bounce(paddle)
sprites.update(dt)
# drawing
screen.fill((0,0,0))
sprites.draw(screen)
pygame.draw.rect(screen, (0, 0, 0), screen_rect, 1)
pygame.display.update()
dt = clock.tick(120)
pygame.quit()
if __name__ == '__main__':
main()

Collision between masks in pygame

I have a problem with collisions in my game, spaceship's mask doesn't collide properly with a background and I believe that offset is a problem, however I'm not sure.
I've tried multiple collision techniques and checked a lot of answers to my problem, but none of them helped me.
import pygame as pg
import os
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (2, 29)
pg.init()
def gameLoop():
display_width = 1800
display_height = 1000
pg.display.set_caption("Kerbal Space Landing Simulator")
clock = pg.time.Clock()
display = pg.display.set_mode((display_width, display_height))
sprsp = pg.image.load('C:/Users/PC/PycharmProjects/untitled/sprspaceship.png').convert_alpha()
cosbg = pg.image.load('C:/Users/PC/PycharmProjects/untitled/cosmos bg.png').convert_alpha()
done = False
class Spaceship:
def __init__(self, x, y, mass):
self.x = x
self.y = y
self.width = 139
self.height = 106
self.velx = 0
self.vely = 0
self.mass = mass
self.color = (255, 255, 255)
self.spr = sprsp
self.fuel = 500
self.mask = pg.mask.from_surface(self.spr)
self.angle = 0
self.changerot = 0
def check_controls(self):
if keys[pg.K_SPACE] and self.fuel > 0:
if self.angle > 0:
self.vely += 0.005 * (self.angle - 90)
self.velx += -0.005 * self.angle
else:
self.vely += -0.005 * (self.angle + 90)
self.velx += -0.005 * self.angle
self.fuel += -3
if keys[pg.K_LEFT] and self.angle < 90:
self.angle += 2
if keys[pg.K_RIGHT] and self.angle > -90:
self.angle += -2
def update_pos(self):
self.vely += 0.01
self.x += self.velx
self.y += self.vely
self.mask = pg.mask.from_surface(self.spr)
def update_rotation(self):
self.rspr = pg.transform.rotate(self.spr, self.angle)
self.changerot -= self.angle
def draw(self):
if self.fuel > 0:
pg.draw.rect(display, (255, 255, 255), (display_width - 100, 100 + 500 - self.fuel, 10, self.fuel), 0)
display.blit(self.rspr, (int(self.x), int(self.y)))
self.changerot = 0
class Terrain(object):
def __init__(self, x, y):
self.x = x
self.y = y
self.mask = pg.mask.from_threshold(display, (160, 160, 160))
self.hitbox = pg.Rect(self.x, self.y, display_width, 500)
self.ox = display_width // 2 - self.x // 2
self.oy = display_height // 2 - self.y // 2
def draw(self):
pg.draw.rect(display, (160, 160, 160), (self.x, self.y, display_width, 500), 0)
spaceship = (Spaceship(500, 100, 1))
terrain = (Terrain(0, 800))
def redrawGameWindow():
display.blit(cosbg, (0, 0))
spaceship.draw()
terrain.draw()
pg.display.update()
def check_for_collisions():
offset = (int(spaceship.x - terrain.ox), int(spaceship.y - terrain.oy))
print(offset)
print(spaceship.mask.overlap(terrain.mask, offset))
return spaceship.mask.overlap(terrain.mask, offset)
# return spaceship.hitbox.colliderect(terrain.hitbox)
# return pg.sprite.spritecollide(spaceship.spr, terrain.mask, False, pg.sprite.collide_mask)
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
keys = pg.key.get_pressed()
mouse_pressed = pg.mouse.get_pressed()
x, y = pg.mouse.get_pos()
spaceship.check_controls()
spaceship.update_pos()
spaceship.update_rotation()
if check_for_collisions() is not None:
print('Hit! You\'ve hit the ground with the speed:', spaceship.vely)
exit()
redrawGameWindow()
clock.tick(60)
gameLoop()
Spaceship doesn't collide with the surface. I know how to fix it using simpler code, but in future I want to use randomly generated terrain. Could you help me with these collisions?
The mask for the Terrain is never set. Crate a proper Terrain mask:
class Terrain(object):
def __init__(self, x, y):
self.x = x
self.y = y
maskSurf = pg.Surface((display_width, display_height)).convert_alpha()
maskSurf.fill(0)
pg.draw.rect(maskSurf, (160, 160, 160), (self.x, self.y, display_width, 500), 0)
self.mask = pg.mask.from_surface(maskSurf)
print(self.mask.count())
# [...]
When using pygame.mask.Mask.overlap(), then you've to check the overlapping of the Spaceship and the Terrain, rather than the Terrain and the Spaceship.
Since the Terrain mask is a mask of the entire screen, the offset for the overlap() test is the position of the Spaceship:
def check_for_collisions():
offset = (int(spaceship.x), int(spaceship.y))
collide = terrain.mask.overlap(spaceship.mask, offset)
print(offset, collide)
return collide
Minimal example: repl.it/#Rabbid76/PyGame-SurfaceMaskIntersect
See also: Mask

Categories