Pygame Pixel Perfect Collision не работает должным образом - PullRequest
0 голосов
/ 05 августа 2020

Я создаю тетрис с помощью pygame. Я хочу использовать обнаружение столкновений, чтобы, когда фигура в игре вступает в контакт с любыми другими ранее воспроизведенными фигурами, я могу остановить фигуру в соответствии с logi c тетриса. Я столкнулся с идеальным столкновением пикселей с использованием масок. Я следил за некоторыми учебными пособиями в Интернете, однако определение пикселей возвращает значение true каждый раз, когда в игру вступает новая форма, а не при столкновении каких-либо фигур. заранее извините за длинный код, это самый минимум для кода, который действительно и все еще содержит игровой элемент. Я думаю, что что-то не так с моим подходом, который вызывает эту ошибку. У меня в основном есть функция, заключающаяся в том, что каждый раз, когда фигура в игре соприкасается с «полом», эта фигура удерживается в этом положении, и создается новая фигура. Я думаю, что ive слишком усложнил его, в свою очередь, создав эту ошибку. заранее спасибо

import pygame
import sys
import shapelogic

pygame.init()

screensize = width, height = 800, 595

screen = pygame.display.set_mode(screensize)



background_image =pygame.image.load("/Users/marceason/PycharmProjects/Tetris/Wooden_background.jpg").convert_alpha()

myshape = 0
stop_movement = 0
blit_count = 0
stored_shapes = pygame.sprite.Group()
stored_shapes_with_coords = []
extra_blit_required = False


index = 0
count = 0
listofshapes = []

class shapemanager():

    def __init__(self):

        self.listofshapes = []


    def create_another_instance(self):

        global count
        count += 1
        string = "Shape_{0},".format(count)

        another_shape = Shape(string)
        self.listofshapes.append(another_shape)
        global index
        object = self.listofshapes[index]
        index += 1
        return object


def load_shape(self):
    shape = self.create_another_instance()
    shape.load_shapes()







class Shape(pygame.sprite.Sprite):

def __init__(self, name):
    pygame.sprite.Sprite.__init__(self)

    self.name = name
    self.x = 50
    self.y = 100
    self.move_event = pygame.USEREVENT + 1
    self.reached_bottom_event = pygame.USEREVENT + 2
    self.one_sec_timer = 1000
    self.half_sec_timer = 500

    self.reachbottomflag = False
    self.movement_possible = True

    self.image = pygame.image.load(
"/Users/marceason/PycharmProjects/Tetris/Tetris_Shapes/Green_Shape_1_Position_1.png")
    self.mask = pygame.mask.from_surface(self.image)
    self.rect = self.image.get_rect()


def move_shape(self):
    if self.movement_possible:
        key_input = pygame.key.get_pressed()
        if key_input[pygame.K_LEFT]:
            self.x -= 16
        if key_input[pygame.K_RIGHT]:
            self.x += 16
        if not self.reachbottomflag:
            if key_input[pygame.K_DOWN]:
                self.y += 16


def reachbottom(self):

    if self.y >= 560:
        self.reachbottomflag = True

def no_movement_possible(self):

    self.movement_possible = False





def assign_shape():

global myshape
global stop_movement
myshape = sl.create_another_instance()
pygame.time.set_timer(myshape.move_event, myshape.one_sec_timer)
stop_movement = pygame.time.set_timer(myshape.reached_bottom_event, myshape.half_sec_timer)


def blit_used_shapes():

global screen
global blit_count
blit_count = len(stored_shapes_with_coords)
local_count = 0
while local_count < blit_count:
    screen.blit(stored_shapes_with_coords[local_count][0], (stored_shapes_with_coords[local_count][1], stored_shapes_with_coords[local_count][2]))
    local_count += 1


sl = shapemanager()





##### HERE IS THE PIXEL DETECTION #####
result = pygame.sprite.spritecollide(myshape, stored_shapes, False, pygame.sprite.collide_mask)


## Main loop ##

assign_shape()

while True:

for event in pygame.event.get():
    if event.type == pygame.QUIT: sys.exit()
    screen.blit(background_image, (0, 0))
    screen.blit(myshape.image, (myshape.x, myshape.y))
    myshape.move_shape()



    key_input = pygame.key.get_pressed()
    if key_input[pygame.K_SPACE]:
        myshape.rotate_shape()


    myshape.reachbottom()
    if myshape.reachbottomflag:
        if event.type == myshape.reached_bottom_event:
            myshape.no_movement_possible()
            stored_shape_tuple = [myshape.image, myshape.x, myshape.y]
            stored_shapes_with_coords.append(stored_shape_tuple)
            stored_shapes.add(myshape)

            extra_blit_required = True

            assign_shape()
            ####### PIXEL DETECTION IS HERE IN FOR LOOP ####
            if result:
                print("this should only execute when two shapes touch!!")

    if extra_blit_required:
        blit_used_shapes()

    pygame.display.update()

1 Ответ

3 голосов
/ 05 августа 2020

Проблема в том, что вы не обновляете атрибут спрайтов rect. Все спрайты rect имеют позицию (0, 0) (поскольку вы не устанавливаете его при вызове на self.image.get_rect()), и в результате все маски будут перекрываться и сталкиваться.

Если вы читаете в документации для pygame.sprite.collide_mask вы заметите, что там говорится, что ваши спрайты должны иметь атрибуты mask и rect. У вас есть rect в вашем спрайте, и вы устанавливаете его в __init__(), но вы не обновляете его при перемещении спрайта. Вы просто меняете атрибуты x и y, не изменяя положение rect. Причина, по которой collide_mask хочет rect, заключается в том, что он использует его для определения параметра offset для вызова pygame.mask.Mask.overlap () , который он использует. Важно понимать, что сами маски не имеют позиции, им нужны rect s для определения относительного положения масок.

Это похоже на изображения / поверхности, не имеющие положения и нуждающиеся в a rect, чтобы отслеживать это для них.

По отдельному вопросу, то, как вы переносите спрайты на экран, не имеет смысла. Вы не используете возможности групп спрайтов для рисования и, что еще хуже, сохраняете изображение, x и y спрайта в отдельном списке и не включаете его в сам спрайт. Вам следует go посмотреть несколько примеров кода на основе спрайтов pygame. Примеров множество.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...