I have been trying to make the bullets come out from a specific point on my ship (a pixel ship, where I have drawn a "cannon"). It works when the ship is in a specific angle, but as soon as the player rotate the ship, the bullets start appearing further and further away from the cannon.
I have been trying to work out the math behind fixing this, but cannot for the life of me figure it out. I have tried playing with offset values within the Bullet class, adding it to the blit_rotate_center function as arguments for the x and y values. Everything I do seem to make it worse.
new_image = pygame.transform.rotate(image, angle)
rotated_image = pygame.mask.from_surface(new_image)
new_rect = rotated_image.get_rect(center = image.get_rect(topleft = top_left).center)
win.blit(rotated_image.to_surface(unsetcolor=(0, 0, 0, 0), setcolor= (255, 255, 255,)), new_rect.topleft)
win.blit(new_image, new_rect.topleft)
return new_rect
class PlayerShip:
def __init__(self):
self.img = assets.SPACE_SHIP_1
self.max_vel = 3
self.vel = 0
self.acceleration = 0.01
self.rotation_vel = 0.0
self.rotation_max_vel = 0.6
self.rotation_acc = 0.01
self.angle = 270
self.x = 400
self.y = 400
self.drag = 0.004
self.rotation_drag = 0.0025
self.vertical = 0
self.horizontal = 0
self.cooldown = 240
self.max_cooldown = 240
self.rect = self.img.get_rect()
# Weapons data
self.salvo = 3
def rotate(self, left = False, right = False):
if left:
self.rotation_vel += self.rotation_acc
if self.rotation_vel > self.rotation_max_vel:
self.rotation_vel = self.rotation_max_vel
elif right:
self.rotation_vel -= self.rotation_acc
if self.rotation_vel < self.rotation_max_vel - self.rotation_max_vel * 2:
self.rotation_vel = self.rotation_max_vel - self.rotation_max_vel * 2
def draw(self, win):
self.rect = blit_rotate_center(win, self.img, (self.x, self.y), self.angle)
self.angle += self.rotation_vel
# Moving the player according to angle
radians = math.radians(self.angle)
self.vertical = math.cos(radians) * self.vel
self.horizontal = math.sin(radians) * self.vel
self.y -= self.vertical
self.x -= self.horizontal
self.reduce_speed()
#Updating the cooldown
self.cooldown -= 1
if self.cooldown <= 0:
self.cooldown = 0
def key_input(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
self.rotate(left = True)
if keys[pygame.K_d]:
self.rotate(right = True)
if keys[pygame.K_w]:
self.move_forward()
if keys[pygame.K_s]:
self.move_backward()
def move_forward(self):
self.img = assets.SPACE_SHIP_1_THRUST
self.vel = min(self.vel + self.acceleration, self.max_vel)
def move_backward(self):
self.vel = min(self.vel - self.acceleration, self.max_vel)
if self.vel < self.max_vel - self.max_vel * 2:
self.vel = self.max_vel - self.max_vel * 2
def reduce_speed(self):
if self.vel < 0:
self.vel += self.drag
elif self.vel > 0:
self.vel -= self.drag
if self.rotation_vel < 0:
self.rotation_vel += self.rotation_drag
elif self.rotation_vel > 0:
self.rotation_vel -= self.rotation_drag
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y, player_angle, player_rect):
self.speed = 10
self.angle = player_angle
self.image = assets.BULLET_1
ship_center_x = player_rect[0] + player_rect[2] // 2
ship_center_y = player_rect[1] + player_rect[3] // 2
self.x = ship_center_x
self.y = ship_center_y
self.rect = self.image.get_rect()
radians = math.radians(self.angle - 90)
self.vertical = math.cos(radians) * self.speed
self.horizontal = math.sin(radians) * self.speed
self.x_offset = self.vertical
self.y_offset = self.horizontal
def draw(self, win):
blit_rotate_center(win, self.image, (self.x - self.x_offset, self.y - self.y_offset), self.angle)
radians = math.radians(self.angle - 90)
self.vertical = math.cos(radians) * self.speed
self.horizontal = math.sin(radians) * self.speed
self.y -= self.vertical
self.x -= self.horizontal