1

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)


juba1029
  • 47
  • 4

1 Answers1

1

If you place an object near a wall and rotate it, it may intersect with the wall:

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 and Pygame mask collision and How can I made a collision mask?.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • Sorry, I don't understand your first suggestion: rotate object -> collision test -> rotation when a collision is detected. Also, will using masks get rid of my collision problem or is that just to make it look smoother – juba1029 Jan 09 '23 at 19:48
  • @juba1029 1. Should be "undo rotation when a collision is detected". 2. "Also, will using masks get rid of my collision problem" - No, not completely, but it can reduce the cases where a rotation causes a collision. It depends on the player sprite . (if the sprite was a circle, you would be rid of the problem). – Rabbid76 Jan 09 '23 at 19:51