当前位置: 首页 > 知识库问答 >
问题:

仅检查一侧的子画面冲突

暨鹭洋
2023-03-14

嘿,我的游戏代码有问题。例如,有没有办法检查我的玩家sprite(英雄)右侧是否与obstacle_sprite组发生碰撞?

我只能弄清楚如何检查一般的碰撞,但如果玩家的右侧与障碍物相撞,我只想获得真正的输出。

在我的代码中,我使用一个隐形精灵作为hitbox,并将玩家吸引到这个隐形精灵中以检查碰撞,但使其看起来像障碍物拒绝玩家移动。

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()

共有1个答案

卢知
2023-03-14

如果你跟踪你的球员的速度,会更容易;这将使处理跳跃也不那么复杂。

AFAIK的一个常用技术是进行两次碰撞检测:一次针对x轴,一次针对y轴。

这是我如何更改代码的。如您所见,检查碰撞的一侧就像检查xvel一样简单

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()

 类似资料:
  • 这是我检测碰撞的代码,但它只适用于矩形: }

  • 我有这个骑士角色,有一把剑和一个攻击动画。我想检查剑是否与敌人相撞,然后降低敌人的生命值。我设法做到了这一点,但每次sowrd的对撞机击中敌人的对撞机时,我都有互动。显然我不想那样,但互动应该只在玩家进攻时发生。我尝试了不同的approahces: 通过在字符脚本中执行此操作,使用布尔值检查攻击 这是敌人的剧本 使用而不是 到目前为止似乎没有什么工作,我知道我错过了一些愚蠢的东西,当你们告诉我,请

  • 我目前正在开发一款2D无休止跑者,用Swift3编写,并使用Spritekit。 简短的问题: 有没有办法只检查我的角色的矩形物理体右侧的碰撞? 更多信息: 角色运行的平台由拼图块组成,用户在游戏进行时在此基础上进行构建。角色从左到右,相对于背景(从右到左)。 我希望角色在与右侧的棋子相撞时自动跳跃。然而,玩家放在他右边的任何棋子(与角色的Y值相同)都与他下面的棋子属于同一等级。 因此,只要游戏检

  • 使用Chrome DevTools Animations(动画)检查器检查和修改动画。 TL;DR 通过打开Animation Inspector(动画检查器)捕获动画。它会自动检测动画并将它们分组。 通过减慢动画,重播动画,或查看源代码,来检查动画。 通过更改动画的时间,延迟,持续时间或关键帧偏移来修改动画。 概述 在Chrome DevTools动画检查主要有两个目的。 检查动画。 您希望减慢

  • 我在做一个小的迷你瓷砖引擎游戏。我目前正致力于实现简单的基于块的碰撞检测,然而我遇到了实际的问题。我已经在谷歌上搜索了几个小时,查看了不同的实现,但似乎无法理解它。我目前的努力(只在玩家向右移动时检测碰撞),大部分工作,但允许玩家通过障碍物的底部。碰撞使用法线映射数组来检测碰撞,映射中的任何值2都是一个实体对象。 我明白了我需要做什么的概念--在我移动我的玩家之前,计算玩家将最终进入哪个单元格。检

  • 我只使用Box2D进行碰撞检测。我的代码与Ray Wenderlich教程中的代码类似。 我遇到了这个方法的问题。由于代码绕过了Box2D模拟,因此没有碰撞响应。因此,精灵可以重叠。我知道Box2D冲突API提供了一个单位法向量来帮助解决冲突。然而,这个矢量传达的是方向,而不是大小。因此,我无法确定应该将重叠的sprites移动多远。有人知道如何使用Box2D冲突API手动解决重叠问题吗?