2

my player gun rotation towards the mouse is messed up and I dont know how to fix it

VIDEp as you can see there its rotating fine towards the left but when I try to rotate towards right it glitches and guns mouth faces down

class player:
    def __init__(self,x,y,height,width,color):
         #[......]
        self.shootsright = pygame.image.load("gun.png")


        self.image = self.shootsright
        self.rect  = self.image.get_rect(center = (self.x, self.y))
        self.look_at_pos = (self.x, self.y)

        self.isLookingAtPlayer = False
        self.look_at_pos = (x,y)
      # -----------------------------
    def draw(self):
   #[....]
     
        # rotatiing the gun
        dx = self.look_at_pos[0] - self.rect.centerx
        dy = self.look_at_pos[1] - self.rect.centery 
        angle = (300/math.pi) * math.atan2(dx, dy)
        self.image = pygame.transform.rotate(self.shootsright, angle)
        self.rect  = self.image.get_rect(center = self.rect.center)
 
    def lookAt( self, coordinate ):
        self.look_at_pos = coordinate

my full player class

# the block class
class player:
    def __init__(self,x,y,height,width,color):
        self.x = x
        self.y = y
        self.height = height
        self.width = width
        self.color = color
        # for it to jump
        self.isJump = False
        self.JumpCount = 10
        # for making it fall
        self.fall = 0
        # how fast it is moving
        self.speed = 4
        self.rect = pygame.Rect(x,y,height,width)
        # players health
        self.health = 10
        # gun image
           #-------------------------------------------------------
            # Make a Reference Copy of the bitmap for later rotation
        self.shootsright = pygame.image.load("gun.png")


        self.image = self.shootsright
        self.rect  = self.image.get_rect(center = (self.x, self.y))
        self.look_at_pos = (self.x, self.y)

        self.isLookingAtPlayer = False
        self.look_at_pos = (x,y)
        
        # hitboxes
        self.hitbox = (self.x + 20, self.y, 28,60)
        self.gunhitbox = (self.x + 20, self.y, 28,60)
    def draw(self):
        self.rect.topleft = (self.x,self.y)
        pygame.draw.rect(window,self.color,self.hitbox)
        # draw the players health
        pygame.draw.rect(window, (255,0,0), (self.hitbox[0], self.hitbox[1] - 40, 80, 10)) # NEW
        pygame.draw.rect(window, (0,255,0), (self.hitbox[0], self.hitbox[1] - 40, 80 - (5 * (10 - self.health)), 10))
        self.hitbox = (self.x + -8, self.y + 20 , 41,41)
        # the guns hitbox

        # rotatiing the gun
        dx = self.look_at_pos[0] - self.rect.centerx
        dy = self.look_at_pos[1] - self.rect.centery 
        angle = (300/math.pi) * math.atan2(dx, dy)
        self.image = pygame.transform.rotate(self.shootsright, angle)
        self.rect  = self.image.get_rect(center = self.rect.center)

        self.gunhitbox = (self.x + 8, self.y + -20 , 31,57)
        window.blit(self.image,self.gunhitbox)
    def lookAt( self, coordinate ):
        self.look_at_pos = coordinate


enter image description here

my full code you could test it you just need that gun above

# the block class
class player:
    def __init__(self,x,y,height,width,color):
        self.x = x
        self.y = y
        self.height = height
        self.width = width
        self.color = color
        # for it to jump
        self.isJump = False
        self.JumpCount = 10
        # for making it fall
        self.fall = 0
        # how fast it is moving
        self.speed = 4
        self.rect = pygame.Rect(x,y,height,width)
        # players health
        self.health = 10
        # gun image
           #-------------------------------------------------------
            # Make a Reference Copy of the bitmap for later rotation
        self.shootsright = pygame.image.load("gun.png")


        self.image = self.shootsright
        self.rect  = self.image.get_rect(center = (self.x, self.y))
        self.look_at_pos = (self.x, self.y)

        self.isLookingAtPlayer = False
        self.look_at_pos = (x,y)
        
        # hitboxes
        self.hitbox = (self.x + 20, self.y, 28,60)
        self.gunhitbox = (self.x + 20, self.y, 28,60)
    def draw(self):
        self.rect.topleft = (self.x,self.y)
        pygame.draw.rect(window,self.color,self.hitbox)
        # draw the players health
        pygame.draw.rect(window, (255,0,0), (self.hitbox[0], self.hitbox[1] - 40, 80, 10)) # NEW
        pygame.draw.rect(window, (0,255,0), (self.hitbox[0], self.hitbox[1] - 40, 80 - (5 * (10 - self.health)), 10))
        self.hitbox = (self.x + -8, self.y + 20 , 41,41)
        # the guns hitbox

        # rotatiing the gun
        dx = self.look_at_pos[0] - self.rect.centerx
        dy = self.look_at_pos[1] - self.rect.centery 
        angle = (300/math.pi) * math.atan2(dx, dy)
        self.image = pygame.transform.rotate(self.shootsright, angle)
        self.rect  = self.image.get_rect(center = self.rect.center)

        self.gunhitbox = (self.x + 8, self.y + -20 , 31,57)
        window.blit(self.image,self.gunhitbox)
    def lookAt( self, coordinate ):
        self.look_at_pos = coordinate


Habib Ismail
  • 69
  • 5
  • 16

1 Answers1

1

If the gun rotates around its center, then you have to draw the gun at self.rect rather than self.gunhitbox.

window.blit(self.image,self.gunhitbox)

window.blit(self.image, self.rect)

If the gun has to rotate a round the player, then read How can you rotate an image around an off center pivot in Pygame

Add the function, which rotates an image around an off center pivot to the applicaition:

def blitRotate(surf, image, pos, originPos, angle):

    # calcaulate the axis aligned bounding box of the rotated image
    w, h         = image.get_size()
    sin_a, cos_a = math.sin(math.radians(angle)), math.cos(math.radians(angle)) 
    min_x, min_y = min([0, sin_a*h, cos_a*w, sin_a*h + cos_a*w]), max([0, sin_a*w, -cos_a*h, sin_a*w - cos_a*h])

    # calculate the translation of the pivot 
    pivot        = pygame.math.Vector2(originPos[0], -originPos[1])
    pivot_rotate = pivot.rotate(angle)
    pivot_move   = pivot_rotate - pivot

    # calculate the upper left origin of the rotated image
    origin = (pos[0] - originPos[0] + min_x - pivot_move[0], pos[1] - originPos[1] - min_y + pivot_move[1])

    # get a rotated image
    rotated_image = pygame.transform.rotate(image, angle)

    # rotate and blit the image
    surf.blit(rotated_image, origin)

Use the function which rotates and blit the gun, in player.draw:

class player:  
    # [...]

    def draw(self):
        # [...]

        # rotatiing the gun
        dx = self.look_at_pos[0] - self.rect.centerx
        dy = self.look_at_pos[1] - self.rect.centery 
        
        angle = (300/math.pi) * math.atan2(-dy, dx)
  
        gun_size = self.image.get_size()
        pivot = (8, gun_size[1]//2)
        blitRotate(window, self.image, self.rect.center, pivot, angle)

Rabbid76
  • 202,892
  • 27
  • 131
  • 174