pygame почему моя коллизия с масками не работает

1004w

Новичок
Пользователь
Июл 23, 2024
2
2
1
Привет! Я уже задавал этот вопрос на другом форуме, но мне никто не ответил, помогите хоть вы пожалуйста :)

в это коде

Python:
self.square_rect = pygame.Rect(200, 200, 100, 100)
square_mask = pygame.mask.from_surface(pygame.Surface((100,100),pygame.SRCALPHA))
pygame.draw.rect(square_mask.to_surface(), (255,255,255), square_mask.get_rect())
player_mask = pygame.mask.from_surface(self.player.image)
offset_x = self.square_rect.x - self.player.x
offset_y = self.square_rect.y - self.player.y
overlap_mask = player_mask.overlap(square_mask, (offset_x, offset_y))
print(overlap_mask)
print (offset_x)
print (offset_y)
if overlap_mask:
print("10")
Хочу сделать так, что если player (квадрат) находится под квадратом self.square_rect, то код print ("10) выполняется. Но почему-то, даже если я стою на квадрате, этот код не выполняется и столкновение не определяется.

принты дают мне такую инфу:

None

0

-4

то есть я точно под квадратом но коллизия не детектится, почему я не могу понять. Если что вот полный код:

Python:
import pygame
import math
import random
import numpy
pygame.init()
class GameData:
def __init__(self):

self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
self.screen_x, self.screen_y = self.screen.get_size()
self.left_wall_rect = pygame.Rect(0, 0, round(self.screen_x * 0.01), self.screen_y)
self.right_wall_rect = pygame.Rect(round(self.screen_x * 0.99), 0, round(self.screen_x * 0.01), self.screen_y)
self.top_wall_rect = pygame.Rect(0, 0, self.screen_x, round(self.screen_y * 0.01))
self.bottom_wall_rect = pygame.Rect(0, round(self.screen_y * 0.99), self.screen_x, round(self.screen_y * 0.01))
self.walls_rects = [self.left_wall_rect,self.right_wall_rect, self.top_wall_rect, self.bottom_wall_rect]

self.player_speed = round ((self.screen_x + self.screen_y) * 0.0025)
self.clock = pygame.time.Clock()
self.изображения = {
"spike": pygame.image.load("images/spike.png").convert_alpha(),
"player": pygame.image.load("images/player.png").convert_alpha(),
} # - ЭТО ПРОСТО ЗЕЛЁНЫЙ КВАДРАТ
def calculate_velocity(self, angle, speed):
velocityX = speed * numpy.cos(numpy.deg2rad(angle))
velocityY = speed * numpy.sin(numpy.deg2rad(angle))
return velocityX, velocityY

class Player ():
def __init__(self, gamedata):
self.gamedata = gamedata
self.image = self.gamedata.изображения["player"]
self.x = self.gamedata.screen_x // 2
self.y = self.gamedata.screen_y // 2
self.rect = self.image.get_rect(center=(self.x, self.y))
self.alive = True
def draw (self):
self.gamedata.screen.blit (self.image, (self.x, self.y))
class Game:
def __init__(self, gamedata, player):
self.gamedata = gamedata
self.spikes = []
self.player = player
self.running = True
self.square_rect = pygame.Rect(200, 200, 100, 100)
def update_events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
keys = pygame.key.get_pressed()
dx = 0
dy = 0
if keys[pygame.K_LEFT]:
dx -= 1
if keys[pygame.K_RIGHT]:
dx += 1
if keys[pygame.K_UP]:
dy -= 1
if keys[pygame.K_DOWN]:
dy += 1
self.dx = dx
self.dy = dy
def update_collisions(self):
dx = self.dx
dy = self.dy
self.player.x += dx * self.gamedata.player_speed
self.player.y += dy * self.gamedata.player_speed
player_left = self.player.x
player_right = self.player.x + self.player.image.get_width()
player_top = self.player.y
player_bottom = self.player.y + self.player.image.get_height()
if dx > 0:
if player_right > self.gamedata.right_wall_rect.left:
self.player.x = self.gamedata.right_wall_rect.left - self.player.image.get_width()
elif dx < 0:
if player_left < self.gamedata.left_wall_rect.right:
self.player.x = self.gamedata.left_wall_rect.right
player_left = self.player.x
player_right = self.player.x + self.player.image.get_width()
player_top = self.player.y
player_bottom = self.player.y + self.player.image.get_height()

if dy > 0:
if player_bottom > self.gamedata.bottom_wall_rect.top:
self.player.y = self.gamedata.bottom_wall_rect.top - self.player.image.get_height()
elif dy < 0:
if player_top < self.gamedata.top_wall_rect.bottom:
self.player.y = self.gamedata.top_wall_rect.bottom
self.square_rect = pygame.Rect(200, 200, 100, 100)
square_mask = pygame.mask.from_surface(pygame.Surface((100,100),pygame.SRCALPHA))
pygame.draw.rect(square_mask.to_surface(), (255,255,255), square_mask.get_rect())
player_mask = pygame.mask.from_surface(self.player.image)
offset_x = self.square_rect.x - self.player.x
offset_y = self.square_rect.y - self.player.y
overlap_mask = player_mask.overlap(square_mask, (offset_x, offset_y))
print(overlap_mask)
print (offset_x)
print (offset_y)
if overlap_mask:
print(10)

def draw(self):
self.gamedata.screen.fill ((0, 0, 0))
self.player.draw()
for spike in self.spikes:
spike.draw()
pygame.draw.rect(self.gamedata.screen, (255, 255, 255), self.square_rect)
pygame.display.flip()

def run(self):
while self.running:
self.update_events()
self.update_collisions()
self.draw()
self.gamedata.clock.tick(60)


gamedata = GameData()
player = Player (gamedata)
game = Game(gamedata, player)
game.run()
pygame.quit()
 
Последнее редактирование:
  • Мне нравится
Реакции: Dr. Mundo

1004w

Новичок
Пользователь
Июл 23, 2024
2
2
1
Короче, мне подсказали:

“in the first code block you've posted you have

square_mask = pygame.mask.from_surface(pygame.Surface((100,100),pygame.SRCALPHA))

you've created your 100x100 surface inline but you never use Surface.fill() to actually put something on your surface. This means your surface is empty and your mask is empty and has nothing to collide with. You need to fill your surface before you make the mask from it.”

это было решением. ПРоблема решена.


Python:
self.square_rect = pygame.Rect(200, 200, 100, 100)
square_surface = pygame.Surface((100, 100), pygame.SRCALPHA)
square_surface.fill((255, 255, 255))
square_mask = pygame.mask.from_surface(square_surface)
player_mask = pygame.mask.from_surface(self.player.image)
offset_x = self.square_rect.x - self.player.x
offset_y = self.square_rect.y - self.player.y
overlap_mask = player_mask.overlap(square_mask, (offset_x, offset_y))
print(overlap_mask)
print(offset_x)
print(offset_y)
if overlap_mask:
print(10)
 
  • Мне нравится
Реакции: Dr. Mundo

Dr. Mundo

Модератор
Команда форума
Модератор
Фев 13, 2024
26
1
3
Проблема в создании маски для квадрата. Вот исправленный код для проверки коллизии:

Python:
# В методе update_collisions()
self.square_rect = pygame.Rect(200, 200, 100, 100)
square_surface = pygame.Surface((100,100))
pygame.draw.rect(square_surface, (255,255,255), square_surface.get_rect())
square_mask = pygame.mask.from_surface(square_surface)

player_mask = pygame.mask.from_surface(self.player.image)
offset_x = self.square_rect.x - self.player.x
offset_y = self.square_rect.y - self.player.y
overlap_mask = player_mask.overlap(square_mask, (offset_x, offset_y))

if overlap_mask:
    print(10)

Основные изменения:
  1. Создаем Surface для квадрата
  2. Рисуем белый прямоугольник на этой поверхности
  3. Создаем маску из полученной поверхности
Раньше маска создавалась из пустой SRCALPHA поверхности, поэтому коллизия не определялась.
 

Dr. Mundo

Модератор
Команда форума
Модератор
Фев 13, 2024
26
1
3
@1004w спасибо за ваше решение! (y)
 

Форум IT Специалистов