Search code examples
pythonpygame

How Can I Make An Arrow Image Move Rotated Direction?


I have an arrow image that rotates left and right VIDEO as you can see in the video when I click my arrow stops rotating and I want it to move the direction it stopped rotating on how would I do that? right now I only have it so when I click the rotation stops but not really sure how I could make it move the direction it stopped rotating on

enter image description here

I tried to make it so when the player clicks the arrow starts to move but its the same thing it doesnt move towards like the rotated place it will just move my arrow down VIDEO

rotating_arrow = True

move = False
# our main loop
run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

        if event.type == pygame.MOUSEBUTTONDOWN:
            rotating_arrow = False
            move = True


    if move:
        move_angle = bow2.angle + 15 # The arrow is painted approximately 15° downwards
        speed = 20
        move_vec = pygame.math.Vector2(speed, 0).rotate(move_angle)
        bow2.x += move_vec.x
        bow2.y += move_vec.y
        bow2.rect.topleft = round(bow2.x), round(bow2.y)

this is how my rotated image is set



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)


my arrow class

class arrow:
    def __init__(self,x,y,height,width,color):
        self.x = x
        self.y = y
        self.height = height
        self.width = width
        self.color = color
        self.shootsright = pygame.image.load("ner.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)
        self.angle = 0
        self.gun_size = self.image.get_size()
        self.pivot = (8,  self.gun_size[1]//2)
        
        
        self.rect = pygame.Rect(x,y,height,width)
    def draw(self):


        blitRotate(window, self.image, self.rect.center,  self.pivot,  self.angle)
        pygame.draw.rect(window,self.color,self.rect)




Solution

  • If you want to fire a bullet in a certain direction, the direction is defined the moment the bullet is fired, but it does not change continuously. This means that after the arrow is fired, the angle will not change.

    Compute the direction of the arrow by the trigonometric functions sin and cos. Define the speed of the arrow. Change the position attributes (x, y) of the arrow in each frame:

    speed = 20
    self.x += speed * math.cos(math.radians(move_angle))
    self.y -= speed * math.sin(math.radians(move_angle))
    

    Update the rect attribute:

    self.rect.topleft = round(self.x), round(self.y)
    

    Since the arrow picture is painted at a certain angle, the motion angle may need to be corrected:

    move_angle = self.angle - 15 # The arrow is painted approximately 15° downwards
    

    Complete arrow.draw method:

    class arrow:
       # [...]
    
       def draw(self):
            move_angle = self.angle - 15 # The arrow is painted approximately 15° downwards
            speed = 20
            self.x += speed * math.cos(math.radians(move_angle))
            self.y -= speed * math.sin(math.radians(move_angle))
            self.rect.topleft = round(self.x), round(self.y)
    
            blitRotate(window, self.image, self.rect.center,  self.pivot,  self.angle)
            pygame.draw.rect(window,self.color,self.rect)