围绕中心旋转玩家可以正常运作,但与墙壁的碰撞不再起作用。

huangapple go评论59阅读模式
英文:

rotating player around center works but collisions with walls don't anymore

问题

我可以平滑地围绕玩家的中心位置旋转。然而,当我到达墙壁并且以对角线旋转时,玩家会传送到地图上的另一个位置。我认为这是因为当玩家旋转时,玩家矩形变大了,但我不确定如何修复它。这是我玩家类中的相关代码:

编辑:我现在通过创建一个围绕原始玩家图像的矩形(self.hitbox_rect)来修复了墙壁碰撞问题,因此在旋转时保持相同的大小。我的碰撞代码检查玩家是否与这个较小的矩形相撞。然而,现在我有一个问题:当我靠近墙壁并旋转时,我的相机会抖动。我已经更新了我的代码,并且还添加了一些关于相机类的信息 - 也许这与问题相关?

class Player(pygame.sprite.Sprite):
    def __init__(self, pos):
        super().__init__()
        self.player_img = pygame.image.load("handgun/move/survivor-move_handgun_0.png").convert_alpha()
        self.image = self.player_img
        self.image = pygame.transform.rotozoom(self.image, 0, 0.35)
        self.original_image = self.image  
        self.rect = self.image.get_rect(center=pos)

        self.player_speed = 10  # 曾经是4
        self.shoot = False
        self.shoot_cooldown = 0
        self.bullet = Bullet(self.rect.centerx, self.rect.centery)
        self.pos = pos

        self.hitbox_rect = self.original_image.get_rect(center=pos)

    def player_turning(self):
        self.mouse_coords = pygame.mouse.get_pos()

        self.x_change_mouse_player = (self.mouse_coords[0] - (WIDTH // 2))
        self.y_change_mouse_player = (self.mouse_coords[1] - (HEIGHT // 2))
        self.angle = int(math.degrees(math.atan2(self.y_change_mouse_player, self.x_change_mouse_player)))
        self.angle = (self.angle + 360) % 360

        self.image = pygame.transform.rotate(self.original_image, -self.angle)
        self.rect = self.image.get_rect(center=self.rect.center)

    def check_collision(self, direction):
        for sprite in obstacles_group:
            if sprite.rect.colliderect(self.hitbox_rect):
                if direction == "horizontal":
                    if self.velocity_x > 0:
                        self.rect.right = sprite.rect.left
                        self.hitbox_rect.right = sprite.rect.left
                    if self.velocity_x < 0:
                        self.rect.left = sprite.rect.right
                        self.hitbox_rect.left = sprite.rect.right

                if direction == "vertical":
                    if self.velocity_y < 0:
                        self.rect.top = sprite.rect.bottom
                        self.hitbox_rect.top = sprite.rect.bottom
                    if self.velocity_y > 0:
                        self.rect.bottom = sprite.rect.top
                        self.hitbox_rect.bottom = sprite.rect.top

    def move(self):
        self.rect.centerx += self.velocity_x
        self.hitbox_rect.x += self.velocity_x
        self.check_collision("horizontal")
        self.rect.centery += self.velocity_y
        self.hitbox_rect.y += self.velocity_y
        self.check_collision("vertical")

class Camera(pygame.sprite.Group):
    def __init__(self):
        super().__init__()
        self.offset = pygame.math.Vector2()
        self.floor_rect = background.get_rect(topleft=(0, 0))

        self.create_map()

    def custom_draw(self):
        self.offset.x = player.rect.centerx - (WIDTH // 2)
        self.offset.y = player.rect.centery - (HEIGHT // 2)

        # 画地板
        floor_offset_pos = self.floor_rect.topleft - self.offset
        screen.blit(background, floor_offset_pos)

        for sprite in all_sprites_group:
            offset_pos = sprite.rect.topleft - self.offset
            screen.blit(sprite.image, offset_pos)
英文:

I can rotate the player around its center position smoothly. However when I reach wall and rotate diagonally, the player teleports to another location on the map. I believe this is due to my player rect being larger when it rotates but I am not sure how to fix it. Here is the relevant code in my player class:

EDIT: I have now fixed the wall collision by creating a rectangle (self.hitbox_rect) that surrounds the original player image, and thus stays the same size whilst rotating. My collision code checks if the player collides with this smaller rectangle. However, I now have an issue which is: my camera keeps shaking when i am close to a wall and rotating. I have updated my code and also added some info about the camera class - maybe it is relevant?

class Player(pygame.sprite.Sprite):
    def __init__(self, pos):
        super().__init__()
        self.player_img = pygame.image.load(&quot;handgun/move/survivor-move_handgun_0.png&quot;).convert_alpha()
        self.image = self.player_img
        self.image = pygame.transform.rotozoom(self.image, 0, 0.35)
        self.original_image = self.image  
        self.rect = self.image.get_rect(center = pos)

        self.player_speed = 10 # was 4
        self.shoot = False
        self.shoot_cooldown = 0
        self.bullet = Bullet(self.rect.centerx, self.rect.centery)
        self.pos = pos

        self.hitbox_rect = self.original_image.get_rect(center = pos)

 
    def player_turning(self): 
        self.mouse_coords = pygame.mouse.get_pos() 

        self.x_change_mouse_player = (self.mouse_coords[0] - (WIDTH // 2))
        self.y_change_mouse_player = (self.mouse_coords[1] - (HEIGHT // 2))
        self.angle = int(math.degrees(math.atan2(self.y_change_mouse_player, self.x_change_mouse_player)))
        self.angle = (self.angle + 360) % 360

        self.image = pygame.transform.rotate(self.original_image, -self.angle)
        self.rect = self.image.get_rect(center=self.rect.center)


    def check_collision(self, direction): 
        for sprite in obstacles_group:
            if sprite.rect.colliderect(self.hitbox_rect):
                if direction == &quot;horizontal&quot;:
                    if self.velocity_x &gt; 0:
                        self.rect.right = sprite.rect.left
                        self.hitbox_rect.right = sprite.rect.left 
                    if self.velocity_x &lt; 0:
                        self.rect.left = sprite.rect.right
                        self.hitbox_rect.left = sprite.rect.right
                
                if direction == &quot;vertical&quot;:
                    if self.velocity_y &lt; 0:
                        self.rect.top = sprite.rect.bottom
                        self.hitbox_rect.top = sprite.rect.bottom
                    if self.velocity_y &gt; 0:
                        self.rect.bottom = sprite.rect.top
                        self.hitbox_rect.bottom = sprite.rect.top

    def move(self):
        self.rect.centerx += self.velocity_x
        self.hitbox_rect.x += self.velocity_x
        self.check_collision(&quot;horizontal&quot;)
        self.rect.centery += self.velocity_y
        self.hitbox_rect.y += self.velocity_y
        self.check_collision(&quot;vertical&quot;)

class Camera(pygame.sprite.Group):
def __init__(self):
super().__init__()
self.offset = pygame.math.Vector2()
self.floor_rect = background.get_rect(topleft = (0,0))
self.create_map()
def custom_draw(self):
self.offset.x = player.rect.centerx - (WIDTH // 2)
self.offset.y = player.rect.centery - (HEIGHT // 2)
#draw the floor
floor_offset_pos = self.floor_rect.topleft - self.offset
screen.blit(background, floor_offset_pos)
for sprite in all_sprites_group:
offset_pos = sprite.rect.topleft - self.offset
screen.blit(sprite.image, offset_pos)
</details>
# 答案1
**得分**: 1
如果您将物体放在墙附近并旋转它,它可能会与墙相交:
有许多不同的方法来解决这个问题。一种选择是,如果物体在旋转后与墙相交,则可能不旋转:
1. 旋转物体
2. 碰撞测试
3. 在检测到碰撞时取消旋转
另一种方法是在旋转后校正物体的位置:
1. 旋转物体
2. 碰撞测试
3. 当检测到碰撞时,将物体移动到一侧,以使其不再相撞
---
请注意,当使用碰撞检测与掩码时,旋转物体可能会导致较少的碰撞。请参阅[PyGame使用掩码进行碰撞检测](https://stackoverflow.com/questions/57455811/pygame-collision-with-masks)以及[Pygame掩码碰撞](https://stackoverflow.com/questions/60077813/pygame-mask-collision)和[如何创建碰撞掩码?](https://stackoverflow.com/questions/56043600/how-can-i-made-a-collision-mask)。
<details>
<summary>英文:</summary>
If you place an object near a wall and rotate it, it may intersect with the wall:
[![][1]][1]
There are many different ways to solve this problem. One option would be that the object may not be rotated if it intersects with the wall after rotation:
1. rotate object
2. collision test
3. undo rotation when a collision is detected
Another object would be to correct the position of the object after the rotation:
1. rotate object
2. collision test
3. when a collision is detected, the object is shifted to the side so that it no longer collides
---
Note that you might get fewer collisions from rotated objects when using collision detection with mask. See [PyGame collision with masks](https://stackoverflow.com/questions/57455811/pygame-collision-with-masks) and
[Pygame mask collision](https://stackoverflow.com/questions/60077813/pygame-mask-collision) and [How can I made a collision mask?](https://stackoverflow.com/questions/56043600/how-can-i-made-a-collision-mask).
[1]: https://i.stack.imgur.com/rQnIg.gif
</details>

huangapple
  • 本文由 发表于 2023年1月9日 05:08:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/75051311.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定