Как реализовать столкновение со стеной, когда стены - одна группа, а мои спрайты - в другой - PullRequest
0 голосов
/ 20 апреля 2019

Я делаю игру, в которой игрок движется через уровень, цель движется случайным образом через уровень и есть охранники (пока не участвующие в игре).У меня возникают проблемы при реализации столкновения со стеной, так как мои спрайты - это круги, а мои стены - прямоугольники, поэтому я не знаю, как это сделать, стены и спрайты относятся к разным классам и группам.

Я имеюдумал об использовании масок для моих спрайтов, но я не уверен, как это сделать.Я также не знаю, как спроектировать метод для столкновения со стеной, так как текущий посылает моего игрока (у меня это не работает и для цели) к нижней части любой стены.

class characters(pygame.sprite.Sprite):
    def __init__(self, colour, width, height):
        super().__init__()
        self.colour = colour
        self.width = width
        self.height = height
        self.image = pygame.Surface([self.width, self.height])
        self.image.fill(white)
        self.image.set_colorkey(white)
        self.rect = self.image.get_rect() 
        pygame.draw.circle(self.image, self.colour, [int(self.width/2), int(self.height/2)], int(self.width/2))

    def moveRight(self, pixels):
        self.rect.x += pixels

    def moveLeft(self, pixels):
        self.rect.x -= pixels

    def moveUp(self, pixels):
        self.rect.y -= pixels

    def moveDown(self, pixels):
        self.rect.y += pixels

    def moveRandom(self, pixels, clockrate, count, xdirection, ydirection):
        self.rect.x += pixels * xdirection
        self.rect.y += pixels * ydirection
        #print(self.rect.x,self.rect.y)

    def wallCollide(self):
        x = self.rect.x
        for xpos in [-5,5]:
            self.rect.x += xpos
            if pygame.sprite.spritecollide(self, wallSet, False, pygame.sprite.collide_rect):
                self.rect.x -= xpos
            else:
                self.rect.x = x
        y = self.rect.y
        for ypos in [-5,5]:
            self.rect.y += ypos
            if pygame.sprite.spritecollide(self, wallSet, False, pygame.sprite.collide_rect):
                self.rect.y -= ypos
            else:
                self.rect.y = y

Я попробовал маску в классе стен ниже, не думаю, что она работает.

class walls(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height):
        super().__init__()
        self.width  = width
        self.height = height
        self.x      = x
        self.y      = y

        self.image = pygame.Surface([width,height])
        self.image.fill(black)
        #self.image.set_colorkey(black) Using this will make the walls invisible as I have textured walls drawn over
        self.rect = self.image.get_rect(topleft=(self.x, self.y))
        pygame.mask.from_surface(self.image)

Я дал только одну стену и уменьшил разрешение, так как это намного проще, пока я пишу свой код.Разрешение должно быть 1920 на 1080. Используйте 600 на 650, чтобы увидеть две стены.

characterSet = pygame.sprite.Group()
player = characters(black, 30, 30)
target = characters(green, 30, 30)
characterSet.add(player, target)

wallSet = pygame.sprite.Group()
Wall1 = walls(288,176, 200,142)
Wall2 = walls(286,427, 201,140)
wallSet.add(Wall1,Wall2)

Основной игровой цикл

while not end:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            end = True

    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        player.moveLeft(5)
    if keys[pygame.K_RIGHT]:
        player.moveRight(5)
    if keys[pygame.K_UP]:
        player.moveUp(5)
    if keys[pygame.K_DOWN]:
        player.moveDown(5)

    if count%clockrate == 0:
        xdirection = random.choice(direction)
        ydirection = random.choice(direction)
    target.moveRandom(2, clockrate, count, xdirection, ydirection)
    count += 1

    if pygame.sprite.spritecollide(player, wallSet, False, pygame.sprite.collide_rect):
        player.wallCollide()
    gameDisplay.blit(level1,[0,0])
    wallSet.draw(gameDisplay)
    gameDisplay.blit(innerWalls,[0,0])
    characterSet.draw(gameDisplay)

1 Ответ

1 голос
/ 22 апреля 2019

Если я правильно понимаю, у вас есть список объектов стены и список объектов персонажей, и вы хотите проверить столкновение между ними. это можно сделать быстро, зациклив оба списка:

for wall in WallSet:
    for character in CharacterSet:
        character.checkCollision(wall)

Метод checkCollision() может быть очень простым, проверяя, не перекрывают ли прямоугольники вокруг ваших объектов несколько операторов if. Если вы хотите, чтобы этот метод checkCollisions() работал хорошо для закругленных символов, вам нужно написать что-нибудь более изощренное. Я бы предложил:

  1. Напишите функцию, которая будет давать точку внутри прямоугольника, ближайшую к другой точке (сложная часть! Хотя я уверен, что есть уроки о том, как это сделать онлайн)

  2. Возьмите эту точку внутри прямоугольника стены и убедитесь, что она достаточно далеко от средней позиции персонажа, чтобы не столкнуться.

Надеюсь, это поможет! Что касается будущих вопросов, я бы предложил очень четко задать 1 вопрос и сократить код, который вы публикуете в дальнейшем. На вопрос, который вы задаете, количество отправленного вами кода слишком велико, и, вероятно, от него отказались потенциальные ответчики за последние 2 дня.

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