Reputation: 75
I am trying to make a spaceship move towards the mouse pointer, rotating to follow the pointer if it moves around. Currently, the rotation works fine and the linear movement works fine, but for some reason if the ship rotates and moves simultaneously, it sort of shakes in place while rotating and doesn't move forward any more. Here is a gif of my problem for clarification. Below I have the relevant code.
EDIT: I just posted the entire class to hopefully make things less confusing.
class player():
def __init__(self, x_position, y_position, length, height):
self.x = x_position
self.y = y_position
self.l = length
self.h = height
self.player_ship = pygame.transform.scale(ships[0], (128, 128))
self.angle = 0
def draw(self, win):
cx, cy = pygame.mouse.get_pos()
img_copy = pygame.transform.rotate(self.player_ship, math.atan2(self.x - cx, self.y - cy)*57.2957795)
win.blit(img_copy, (self.x - int(img_copy.get_width() / 2), self.y - int(img_copy.get_height() / 2)))
def move(self, speed):
cx, cy = pygame.mouse.get_pos()
self.angle = math.atan2(cx - self.x, cy - self.y)*57.2957795
movement_x = math.cos(self.angle) * speed
movement_y = math.sin(self.angle) * speed
self.x -= movement_x
self.y += movement_y
I read somewhere that I should not store my location as integers but I'm not completely sure how else to track location. I greatly appreciate any tips or pointer anyone has to offer.
Upvotes: 4
Views: 1748
Reputation: 210909
The issue is caused by the code which rotates the sprite.
Rotate the image, and get a pygame.Rect
of the coated image. Set the center of the rectangle by the position of the object. Use the rectangle to blit the image.
See How do I rotate an image around its center using Pygame?.
img_copy = pygame.transform.rotate(self.player_ship, self.angle)
rotated_rect = img_copy.get_rect(center = (round(self.x), round(self.y)))
To rotate the image it is sufficient to compute the unit direction vector [See Unit vector.)] from the current position to the mouse position. Scale the vector by the speed and add it to the position:
cx, cy = pygame.mouse.get_pos()
dx, dy = cx - self.x, cy - self.y
if abs(dx) > 0 or abs(dy) > 0:
dist = math.hypot(dx, dy)
self.x += min(dist, speed) * dx/dist
self.y += min(dist, speed) * dy/dist
See the example
class player():
def __init__(self, x_position, y_position, length, height):
self.x = x_position
self.y = y_position
self.l = length
self.h = height
self.player_ship = pygame.transform.scale(ships[0], (128, 128))
self.angle = 0
def draw(self, win):
cx, cy = pygame.mouse.get_pos()
dx, dy = cx - self.x, cy - self.y
if abs(dx) > 0 or abs(dy) > 0:
self.angle = math.atan2(-dx, -dy)*57.2957795
img_copy = pygame.transform.rotate(self.player_ship, self.angle)
rotated_rect = img_copy.get_rect(center = (round(self.x), round(self.y)))
win.blit(img_copy, rotated_rect)
def move(self, speed):
cx, cy = pygame.mouse.get_pos()
dx, dy = cx - self.x, cy - self.y
if abs(dx) > 0 or abs(dy) > 0:
dist = math.hypot(dx, dy)
self.x += min(dist, speed) * dx/dist
self.y += min(dist, speed) * dy/dist
Upvotes: 2