pygame如何固定玩家在与蒙版的顶部/底部相撞时向左/右方向相反的方向

发布于 2025-01-28 21:55:59 字数 3299 浏览 4 评论 0 原文

我有一个程序,可以检测面具碰撞并移动玩家以防止其重叠。 它通过根据玩家移动的方向移动播放器的尺寸来移动玩家的尺寸来工作。

但是,当我按照相同的左/右上/向上/向上/向上/向下/向下键(左 +向下,...)时,播放器不会重叠,但也朝着被按下的左/右键的相反方向移动(左 + down - > 右 + dowbn):

我尝试使玩家在掩码的顶部或底部时朝着正确的方向发展,而不是在掩码外边缘时调用 player.move()是越野车还是不起作用。

import pygame
import sprites

SCREEN_HEIGHT, SCREEN_WIDTH = 800, 800
running = True

pygame.init()

screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = pygame.time.Clock()

player = sprites.Block((100, 100))
block2 = sprites.Block((100, 100))
blocks = pygame.sprite.Group(block2)

block2.rect.topleft = 150, 150

while running:
    events = pygame.event.get()

    screen.fill((100, 100, 100))
    for event in events:
        if event.type == pygame.QUIT:
            running = False

    player.move(screen.get_rect())

    def check_collisions():
        collided_blocks = pygame.sprite.spritecollide(player, blocks, False, pygame.sprite.collide_mask)

        if collided_blocks:
            for block in collided_blocks:
                offset = (player.rect.x - block.rect.x, player.rect.y - block.rect.y)
                connected_comps = block.mask.connected_components()
                intersection_masks = player.mask.overlap_mask(block.mask, offset).connected_components()

                for comp in connected_comps:
                    for i_mask in intersection_masks:
                        offset = (0, 0)

                        if i_mask.overlap(comp, offset):
                            i_mask_rect = i_mask.get_bounding_rects()[0]

                            i_mask_rect.topleft = block.rect.x + i_mask_rect.x, block.rect.y + i_mask_rect.y

                            displacement = [i_mask_rect.width * -player.direction[0],
                                            i_mask_rect.height * -player.direction[1]]

                            player.rect.move_ip(displacement[0], displacement[1])
                            return

    check_collisions()

    blocks.draw(screen)
    screen.blit(player.image, player.rect)

    clock.tick(144)
    pygame.display.flip()

Sprites 模块:

import pygame


class Block(pygame.sprite.Sprite):
    def __init__(self, size):
        self.image = pygame.image.load("flappy_bird.png").convert_alpha()
        self.rect = self.image.get_rect()
        self.mask = pygame.mask.from_surface(self.image)

        self.direction = (0, 0)
        self.speed = 1

        super().__init__()

    def move(self, screen_rect):
        pressed_keys = pygame.key.get_pressed()

        self.direction = (0, 0)
        if pressed_keys[pygame.K_w]:
            self.rect.move_ip(0, -self.speed)
            self.direction = 0, -1
        if pressed_keys[pygame.K_s]:
            self.rect.move_ip(0, self.speed)
            self.direction = 0, 1
        if pressed_keys[pygame.K_a]:
            self.rect.move_ip(-self.speed, 0)
            self.direction = -1, 0
        if pressed_keys[pygame.K_d]:
            self.rect.move_ip(self.speed, 0)
            self.direction = 1, 0

        self.rect.clamp_ip(screen_rect)

I have a program that detects mask collisions and moves the player to prevent it overlapping.
It program works by moving the player by the dimensions of the area that is overlapped depending on the direction the player is moving.

But when I press the left/right and up/down keys at the same (left + down, ...), the player doesn't overlap, but also moves in the opposite direction of the left/right key that is being pressed (left + down -> right + dowbn): example (text shows the direction)

I've tried making the player go in the proper direction when its on the top or bottom of the mask and not calling player.move() when on the outer edge of the mask, but each is either buggy or doesn't work.

import pygame
import sprites

SCREEN_HEIGHT, SCREEN_WIDTH = 800, 800
running = True

pygame.init()

screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = pygame.time.Clock()

player = sprites.Block((100, 100))
block2 = sprites.Block((100, 100))
blocks = pygame.sprite.Group(block2)

block2.rect.topleft = 150, 150

while running:
    events = pygame.event.get()

    screen.fill((100, 100, 100))
    for event in events:
        if event.type == pygame.QUIT:
            running = False

    player.move(screen.get_rect())

    def check_collisions():
        collided_blocks = pygame.sprite.spritecollide(player, blocks, False, pygame.sprite.collide_mask)

        if collided_blocks:
            for block in collided_blocks:
                offset = (player.rect.x - block.rect.x, player.rect.y - block.rect.y)
                connected_comps = block.mask.connected_components()
                intersection_masks = player.mask.overlap_mask(block.mask, offset).connected_components()

                for comp in connected_comps:
                    for i_mask in intersection_masks:
                        offset = (0, 0)

                        if i_mask.overlap(comp, offset):
                            i_mask_rect = i_mask.get_bounding_rects()[0]

                            i_mask_rect.topleft = block.rect.x + i_mask_rect.x, block.rect.y + i_mask_rect.y

                            displacement = [i_mask_rect.width * -player.direction[0],
                                            i_mask_rect.height * -player.direction[1]]

                            player.rect.move_ip(displacement[0], displacement[1])
                            return

    check_collisions()

    blocks.draw(screen)
    screen.blit(player.image, player.rect)

    clock.tick(144)
    pygame.display.flip()

sprites module:

import pygame


class Block(pygame.sprite.Sprite):
    def __init__(self, size):
        self.image = pygame.image.load("flappy_bird.png").convert_alpha()
        self.rect = self.image.get_rect()
        self.mask = pygame.mask.from_surface(self.image)

        self.direction = (0, 0)
        self.speed = 1

        super().__init__()

    def move(self, screen_rect):
        pressed_keys = pygame.key.get_pressed()

        self.direction = (0, 0)
        if pressed_keys[pygame.K_w]:
            self.rect.move_ip(0, -self.speed)
            self.direction = 0, -1
        if pressed_keys[pygame.K_s]:
            self.rect.move_ip(0, self.speed)
            self.direction = 0, 1
        if pressed_keys[pygame.K_a]:
            self.rect.move_ip(-self.speed, 0)
            self.direction = -1, 0
        if pressed_keys[pygame.K_d]:
            self.rect.move_ip(self.speed, 0)
            self.direction = 1, 0

        self.rect.clamp_ip(screen_rect)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

以酷 2025-02-04 21:55:59

返回每个密钥状态的序列。如果按住密钥,则密钥的状态为 1 ,否则 0 。因此,当用按下2个键[pygame.k_d] - persed_keys [pygame.k_a] pressed_keys [pygame.k_s] - persed_keys [pygame.k_w]

class Block(pygame.sprite.Sprite):
    # [...]

    def move(self, screen_rect):
        pressed_keys = pygame.key.get_pressed()

        self.direction = (
            pressed_keys[pygame.K_d] - pressed_keys[pygame.K_a], 
            pressed_keys[pygame.K_s] - pressed_keys[pygame.K_w])
        
        self.rect.move_ip(
            self.direction[0] * self.speed
            self.direction[1] * self.speed)
        self.rect.clamp_ip(screen_rect)

pygame.key.get_pressed() returns a sequence with the state of each key. If a key is held down, the state for the key is 1, otherwise 0. So you can calculate the resulting movement when 2 keys are pressed with pressed_keys[pygame.K_d] - pressed_keys[pygame.K_a] and pressed_keys[pygame.K_s] - pressed_keys[pygame.K_w]:

class Block(pygame.sprite.Sprite):
    # [...]

    def move(self, screen_rect):
        pressed_keys = pygame.key.get_pressed()

        self.direction = (
            pressed_keys[pygame.K_d] - pressed_keys[pygame.K_a], 
            pressed_keys[pygame.K_s] - pressed_keys[pygame.K_w])
        
        self.rect.move_ip(
            self.direction[0] * self.speed
            self.direction[1] * self.speed)
        self.rect.clamp_ip(screen_rect)
八巷 2025-02-04 21:55:59

检查他们何时重叠,如果他们这样做,而不是根据运动的运动移动,则将他们移至块位置减去玩家的宽度。

Check when they're overlapping and if they do then instead of moving the player based on their movement move them to the blocks position minus the players width.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文