8

enter image description hereenter image description hereI am having an issue where my bullets dont look like they are coming out of my gun they look like they are coming out of the players body VIDEO as you can see in the video it shoots somewhere else or its the gun its the same thing for the left side it shoots good going up but it shoots bad going down VIDEO

enter image description here

I tried angeling my gun to 120 but what happens is everything good works for the right side not for the left side VIDEO as you can see it just glitches

my projectile class

class projectile(object):
   def __init__(self, x, y, dirx, diry, color):
       self.x = x
       self.y = y
       self.dirx = dirx
       self.diry = diry
       self.slash = pygame.image.load("round.png")
       self.slash = pygame.transform.scale(self.slash,(self.slash.get_width()//2,self.slash.get_height()//2))
       self.rect  = self.slash.get_rect()
       self.rect.topleft = ( self.x, self.y )
       self.speed = 18
       self.color = color
       self.hitbox = (self.x + -18, self.y, 46,60)



how my projectiles append


        if event.type == pygame.MOUSEBUTTONDOWN:           
                    
                    # this is for the bullets
            if len(bullets) < 3:
                if box1.health > 25:
                    mousex, mousey = pygame.mouse.get_pos()

                    playerman.isJump = True
                    start_x, start_y = playerman.x - 30, playerman.y  - 65
                    mouse_x, mouse_y = event.pos

                    dir_x, dir_y = mouse_x - start_x, mouse_y - start_y
                    distance = math.sqrt(dir_x**2 + dir_y**2)
                    if distance > 0:
                        new_bullet = projectile(start_x, start_y, dir_x/distance, dir_y/distance, (0,0,0))
                        bullets.append(new_bullet)
                

                # this is displaying the bullets for the player            
    for bullet in bullets[:]:
        bullet.move()
        if bullet.x < 0 or bullet.x > 900 or bullet.y < 0 or bullet.y > 900:
            bullets.pop(bullets.index(bullet))


    def draw(self,drawX,drawY):
 
        self.rect.topleft =  (drawX,drawY)
 
            # 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 = (190/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)

        if((angle > 90 or angle < -90) and self.gunDirection != "left"):
            self.gunDirection = "left"
            self.image = pygame.transform.flip(self.image, False, True)
        if((angle < 90 and angle > -90) and self.gunDirection != "right"):
            self.gunDirection = "right"
            self.image = pygame.transform.flip(self.image, False, True)





my full gun class

 
class handgun():
    def __init__(self,x,y,height,width,color):
        self.x = x
        self.y = y
        self.height = height
        self.width = width
        self.color = color
        self.rect = pygame.Rect(x,y,height,width)
 
 
        # LOL THESE IS THE HAND
        self.shootsright = pygame.image.load("hands.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.hitbox = (self.x + -18, self.y, 46,60)

 
        self.gunDirection = "right"
    def draw(self,drawX,drawY):
 
        self.rect.topleft =  (drawX,drawY)
 
            # 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 = (120/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)

        if((angle > 90 or angle < -90) and self.gunDirection != "left"):
            self.gunDirection = "left"
            self.image = pygame.transform.flip(self.image, False, True)
        if((angle < 90 and angle > -90) and self.gunDirection != "right"):
            self.gunDirection = "right"
            self.image = pygame.transform.flip(self.image, False, True)




    def lookAt( self, coordinate ):
            
        self.look_at_pos = coordinate
 
 
 
white = (255,255,255)
handgun1 = handgun(300,300,10,10,white)




how my images are blitted





```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)
 

I think what I am trying to say is how could I make my gun rotate at exactly at my mouse poisition without any problems

my full code script

Habib Ismail
  • 69
  • 5
  • 16

1 Answers1

10

It looks to me as if your bullets are originating at the players coordinates and not at the edge of the gun. You probably need to apply the same offset you used for the gun, to the projectile origin. Or just extract the top right and bottom right coordinates of the gun after rotation and set the projectiles origin to equal the average position.

As for why the gun does not seem to be pointing in the direction of the pointer, the coordinate origin is at the top left of the object and not the center. It would probably be easier to offset the position of the cursor object by half width and height. Otherwise you would need to do some additional trigonometry to adjust the offset based on the distance to the cursor.

Example

This is a pretty good example of finding the 2 points, but note that the other 2 points are mirrored. (this could be fixed but i didn't bother)

Adapted from - How can you rotate an image around an off center pivot in Pygame

And From - Rotate point about another point in degrees python

Online IDE - https://repl.it/@ikoursh/tracking

import pygame
import math
import time


def rotate(origin, point, angle):
    """
    Rotate a point counterclockwise by a given angle around a given origin.
    """
    angle = math.radians(angle)
    ox, oy = origin
    px, py = point

    qx = ox + math.cos(angle) * (px - ox) - math.sin(angle) * (py - oy)
    qy = oy + math.sin(angle) * (px - ox) + math.cos(angle) * (py - oy)
    return [qx, qy]


def blitRotate(surf, image, pos, originPos, angle):
    # calculate 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 = (
        round(pos[0] - originPos[0] + min_x - pivot_move[0]), round(pos[1] - originPos[1] - min_y + pivot_move[1]))

    box_rel = [[0, 0], [w, 0], [w, -h], [0, -h]]
    box_n_rotate = [rotate(originPos, p, -angle) for p in box_rel]  # crete a box with negative rotation
    for i in range(len(box_n_rotate)):
        box_n_rotate[i][0] += pos[0] - originPos[0]
        box_n_rotate[i][1] += pos[1] - originPos[1]

    for c in box_n_rotate[:2]:
        pygame.draw.circle(screen, (0, 255, 0), [round(c[i]) for i in range(len(c))], 5)

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

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


pygame.init()
size = (400, 400)
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()

image = pygame.image.load('boomerang64.png')
pivot = (48, 21)

angle, frame = 0, 0
done = False
while not done:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
    screen.fill(0)

    pos = (200 + math.cos(frame * 0.05) * 100, 200 + math.sin(frame * 0.05) * 50)
    blitRotate(screen, image, pos, pivot, angle)

    pygame.draw.line(screen, (0, 255, 0), (pos[0] - 20, pos[1]), (pos[0] + 20, pos[1]), 3)
    pygame.draw.line(screen, (0, 255, 0), (pos[0], pos[1] - 20), (pos[0], pos[1] + 20), 3)
    pygame.display.flip()
    frame += 1
    angle += 1
    # time.sleep(0.2)

pygame.quit()
Geo
  • 543
  • 5
  • 16
  • could you explain it a little more with code because I am having trouble understanding what your saying – Habib Ismail Aug 09 '20 at 23:33
  • @HabibIsmail The bullets originate from the center of the player body and NOT the gun tip. You need to specify the gun tip location. – Bryce Wayne Aug 16 '20 at 01:13