仅检查一侧的精灵碰撞

问题描述 投票:1回答:1

嘿,我的游戏代码有问题。有没有一种方法可以检查例如我的玩家精灵(英雄)的右侧是否与障碍物-sprite组碰撞?

我通常只能弄清楚如何检查碰撞,但是如果玩家的右侧与障碍物碰撞,我只想要一个真实的输出。

在我的代码中,我使用一个不可见的精灵作为击打盒,并将播放器吸引到该不可见的精灵中以检查碰撞,但看起来像障碍物阻止了玩家的移动。

import pygame

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
PINK = (230, 77, 149)

FPS = 60

window_width = 900
window_height = 600
window_color = WHITE

window = pygame.display.set_mode((window_width, window_height))
window.fill(window_color)
pygame.display.set_caption("Bub - the game")

clock = pygame.time.Clock()

class Player(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height, velocity, color):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((width + 2*velocity, height + 2*velocity))
        self.rect = self.image.get_rect()
        self.rect.topleft = (x - velocity, y - velocity)
        self.velocity = velocity
        self.is_jump = False
        self.jump_count = 15
        self.fall_count = 1
        self.ground = self.rect.bottom
        self.body = pygame.Rect(x, y, width, height)
        pygame.draw.rect(window, color, self.body)

    def move(self):
        key = pygame.key.get_pressed()

        if key[pygame.K_a] and self.rect.left >= 0:
            self.rect.x -= self.velocity
        if key[pygame.K_d] and self.rect.right <= window_width:
            self.rect.x += self.velocity
        if not self.is_jump:    
            if key[pygame.K_SPACE] and self.rect.bottom == self.ground:
                self.is_jump = True
        else:
            if self.jump_count >= 0:
                self.rect.y -= round((self.jump_count ** 2) * 0.1)
                self.jump_count -= 1
            else:
                self.jump_count = 15
                self.is_jump = False

    def gravity(self):
        if not self.is_jump and self.rect.bottom != self.ground:
            self.rect.y += round((self.fall_count ** 2) * 0.1)

            if self.fall_count <= 15:
                self.fall_count += 1
        else:
            self.fall_count = 1


    def update(self):
        self.move()
        self.gravity()
        pygame.draw.rect(window, BLACK, self.body)
        self.body.topleft = (self.rect.x + self.velocity, self.rect.y + self.velocity)



class Obstacle(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height, color):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((width, height))
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)



player_sprite = pygame.sprite.Group()
obstacle_sprite = pygame.sprite.Group()


hero = Player(0, 570, 30, 30, 5, BLACK)
player_sprite.add(hero)

obstacle_1 = Obstacle(100, 585, 120, 30, PINK)
obstacle_sprite.add(obstacle_1)


run = True

while run:

    clock.tick(FPS)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    window.fill(window_color)
    player_sprite.update()
    player_sprite.draw(window)
    obstacle_sprite.update()
    obstacle_sprite.draw(window)
    pygame.display.update()

pygame.quit()
python python-3.x pygame sprite collision-detection
1个回答
0
投票

如果您跟踪播放器的速度,会更容易;这将使跳跃的处理也不再那么复杂。

[常见的AFAIK技术是执行两次碰撞检测:一次用于x轴,一次用于y轴。

这是我更改您的代码的方式。如您所见,检查碰撞的一侧就像检查xvel < 0xvel > 0一样容易:

import pygame
pygame.init()

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
PINK = (230, 77, 149)

FPS = 60

window_width = 900
window_height = 600
window_color = WHITE

window = pygame.display.set_mode((window_width, window_height))
window.fill(window_color)
pygame.display.set_caption("Bub - the game")

clock = pygame.time.Clock()

class Toast(pygame.sprite.Sprite):
    def __init__(self, *grps):
        super().__init__(*grps)
        self.image = pygame.Surface((900, 200))
        self.image.fill(WHITE)
        self.rect = self.image.get_rect(topleft=(10, 10))
        self.font = pygame.font.SysFont(None, 32)

    def shout(self, message):
        self.text = self.font.render(message, True, BLACK)
        self.image.fill(WHITE)
        self.image.blit(self.text, (0, 0))

class Player(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height, velocity, color, *grps):
        super().__init__(*grps)
        self.image = pygame.Surface((width + 2*velocity, height + 2*velocity))
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.rect.topleft = (x - velocity, y - velocity)
        self.velocity = velocity
        self.on_ground = True
        self.xvel = 0
        self.yvel = 0

    def collide(self, xvel, yvel, obstacle_sprites):
        global toast
        for p in pygame.sprite.spritecollide(self, obstacle_sprites, False):
            if xvel > 0:
                self.rect.right = p.rect.left
                toast.shout('collide RIGHT')
            if xvel < 0:
                self.rect.left = p.rect.right
                toast.shout('collide LEFT')
            if yvel > 0:
                self.rect.bottom = p.rect.top
                self.on_ground = True
                self.yvel = 0
                toast.shout('collide BOTTOM')
            if yvel < 0:
                self.rect.top = p.rect.bottom
                self.yvel = 0
                toast.shout('collide TOP')

    def update(self, obstacle_sprites):
        global toast
        key = pygame.key.get_pressed()

        self.xvel = 0
        if key[pygame.K_a]:
            self.xvel =- self.velocity
        if key[pygame.K_d]:
            self.xvel = self.velocity

        if self.on_ground:
            if key[pygame.K_SPACE]:
                toast.shout('JUMPING')
                self.on_ground = False
                self.yvel = -20
        else:
            self.yvel += 1

        self.rect.left += self.xvel
        self.collide(self.xvel, 0, obstacle_sprites)

        self.rect.top += self.yvel
        self.on_ground = False
        self.collide(0, self.yvel, obstacle_sprites)

        self.rect.clamp_ip(pygame.display.get_surface().get_rect())
        if self.rect.bottom == pygame.display.get_surface().get_rect().bottom:
            self.on_ground = True

class Obstacle(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(center=(x, y))

all_sprites = pygame.sprite.Group()
player_sprite = pygame.sprite.Group()
obstacle_sprites = pygame.sprite.Group()

toast = Toast(all_sprites)
hero = Player(0, 570, 30, 30, 5, GREEN, all_sprites, player_sprite)

for x in [
    (100, 585, 120, 30),
    (300, 535, 120, 30),
    (500, 485, 120, 30)
    ]:
    Obstacle(*x, PINK, all_sprites, obstacle_sprites)

run = True

while run:

    clock.tick(FPS)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    window.fill(window_color)
    all_sprites.update(obstacle_sprites)
    all_sprites.draw(window)
    pygame.display.update()

pygame.quit()

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.