英文:
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("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 # 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 == "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)
#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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论