After several hours of complete utter chaos, I still haven't found a solution to rotating a sprite to face the mouse position. I've implemented several examples from other post, the links are below, but none of them seem to be effective. Any help with my problem, would be very appreciated :)
Original Code:
class Player(pygame.sprite.Sprite):
def __init__(self, game, x, y):
pygame.sprite.Sprite.__init__(self)
self.game = game
sprite_sheet = Spritesheet("Sprites/ships_spritesheet.png")
image = sprite_sheet.get_image(204, 115, 66, 113)
self.image = pygame.transform.flip(image, False, True)
self.orig_img = self.image
self.rect = self.image.get_rect()
self.pos = vec(x, y)
self.vel = vec(0, 0)
self.health = PLAYER_HEALTH
def update(self):
self.rotate()
self.pos += self.vel
self.rect.x = self.pos.x
self.collide_with_tiles(self.game.obstacle_list, "x")
self.rect.y = self.pos.y
self.collide_with_tiles(self.game.obstacle_list, "y")
def rotate(self):
mouse_x, mouse_y = pygame.mouse.get_pos()
rel_x, rel_y = mouse_x - self.rect.x, mouse_y - self.rect.y
angle = (180 / math.pi) * -math.atan2(rel_y, rel_x)
self.image = pygame.transform.rotate(self.orig_img, int(angle))
self.rect = self.image.get_rect(center=self.pos)
New Code:
class Player(pygame.sprite.Sprite):
def __init__(self, game, pos):
pygame.sprite.Sprite.__init__(self)
self.game = game
sprite_sheet = Spritesheet("Sprites/ships_spritesheet.png")
image = sprite_sheet.get_image(204, 115, 66, 113)
self.image = pygame.transform.flip(image, False, True)
self.orig_img = self.image
self.rect = self.image.get_rect(center=pos)
self.pos = vec(pos)
self.vel = vec(0, 0)
self.health = PLAYER_HEALTH
def update(self):
self.rotate()
self.pos += self.vel
self.rect.centerx = self.pos.x
#self.rect.x = self.pos.x
self.collide_with_tiles(self.game.obstacle_list, "x")
self.rect.centery = self.pos.y
#self.rect.y = self.pos.y
self.collide_with_tiles(self.game.obstacle_list, "y")
self.vel = vec(0, 0)
def rotate(self):
mouse_pos = pygame.mouse.get_pos()
rel_x, rel_y = mouse_pos - self.pos
angle = -math.degrees(math.atan2(rel_y, rel_x))
self.image = pygame.transform.rotate(self.orig_img, angle)
self.rect = self.image.get_rect(center=self.rect.center)
def collide_with_tiles(self, group, dir):
if dir == "x":
hits = pygame.sprite.spritecollide(self, group, False)
if hits:
if self.vel.x > 0:
self.rect.right = hits[0].rect.left
if self.vel.x < 0:
self.rect.left = hits[0].rect.right
self.pos.x = self.rect.centerx
if dir == "y":
hits = pygame.sprite.spritecollide(self, group, False)
if hits:
if self.vel.y > 0:
self.rect.bottom = hits[0].rect.top
if self.vel.y < 0:
self.rect.top = hits[0].rect.bottom
self.pos.y = self.rect.centery
My Game Class
import pygame, pytmx, sys, os
from Settings import *
from Obstacle import *
from Player import *
from Camera import *
from TiledMap import *
from MainMenu import *
from PauseMenu import *
from OptionsMenu import *
from HUD import *
class Game:
def __init__(self):
pygame.init()
pygame.mixer.init()
os.environ['SDL_VIDEO_CENTERED'] = '1'
pygame.display.set_caption(GAME_TITLE)
self.window = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
self.clock = pygame.time.Clock()
self.click_sound = pygame.mixer.Sound("Sounds/click1.ogg")
self.main_menu = MainMenu(self, self.window)
self.obstacle_list = pygame.sprite.Group()
self.island_boundary_list = pygame.sprite.Group()
self.pause_menu = PauseMenu(self.window)
self.options_menu = OptionsMenu(self.window)
self.hud = HUD()
self.display_pause_menu = False
self.display_options_menu = False
self.display_main_menu = True
def get_map(self):
map_dir = TiledMap("Sprites/Maps/map_01.tmx")
self.map = map_dir.generate_map()
self.map_rect = self.map.get_rect()
for tile_obj in map_dir.tmxdata.objects:
if tile_obj.name == "Obstacle":
obstacle = Obstacle(self, tile_obj.x, tile_obj.y, 64, 64)
self.obstacle_list.add(obstacle)
if tile_obj.name == "PLAYER":
self.player = Player(self, (tile_obj.x, tile_obj.y))
def game_loop(self):
self.get_map()
self.camera = Camera(5120, 5120)
while True:
self.clock.tick(FPS)
self.game_events()
if not self.display_pause_menu and not self.display_options_menu and not self.display_main_menu:
self.update_game()
self.draw_game()
def game_events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.run_game = False
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_p and not self.display_options_menu:
self.display_pause_menu = not self.display_pause_menu
if event.key == pygame.K_o and not self.display_pause_menu:
self.display_options_menu = not self.display_options_menu
if event.type == pygame.MOUSEBUTTONDOWN and self.display_main_menu:
x, y = event.pos
self.click_sound.play()
if self.main_menu.play_button.collidepoint(x, y):
self.display_main_menu = False
if self.main_menu.credits_button.collidepoint(x, y):
pass
if self.main_menu.exit_button.collidepoint(x, y):
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN and self.display_pause_menu:
x, y = event.pos
self.click_sound.play()
if self.pause_menu.pause_resume_button.collidepoint(x, y) or self.pause_menu.pause_x_button.collidepoint(x, y):
self.display_pause_menu = False
if self.pause_menu.pause_options_button.collidepoint(x, y):
self.display_pause_menu = False
self.display_options_menu = True
if self.pause_menu.pause_quit_button.collidepoint(x, y):
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN and self.display_options_menu:
x, y = event.pos
self.click_sound.play()
if self.options_menu.options_x_button.collidepoint(x, y):
self.display_options_menu = False
if self.options_menu.options_reset_button.collidepoint(x, y):
#reset options to original options if modified
pass
if self.options_menu.options_home_button.collidepoint(x, y):
self.display_options_menu = False
self.display_main_menu = True
if self.options_menu.options_ok_button.collidepoint(x, y):
#save settings
self.display_options_menu = False
mouse_x, mouse_y = pygame.mouse.get_pos()
if mouse_x > self.main_menu.play_button.x and mouse_x < self.main_menu.play_button.x + self.main_menu.play_button.width and mouse_y > self.main_menu.play_button.y and mouse_y < self.main_menu.play_button.y + self.main_menu.play_button.height:
self.main_menu.img_id = 1
elif mouse_x > self.main_menu.credits_button.x and mouse_x < self.main_menu.credits_button.x + self.main_menu.credits_button.width and mouse_y > self.main_menu.credits_button.y and mouse_y < self.main_menu.credits_button.y + self.main_menu.credits_button.height:
self.main_menu.img_id = 2
elif mouse_x > self.main_menu.exit_button.x and mouse_x < self.main_menu.exit_button.x + self.main_menu.exit_button.width and mouse_y > self.main_menu.exit_button.y and mouse_y < self.main_menu.exit_button.y + self.main_menu.exit_button.height:
self.main_menu.img_id = 3
else:
self.main_menu.img_id = 0
if mouse_x > self.pause_menu.pause_resume_button.x and mouse_x < self.pause_menu.pause_resume_button.x + self.pause_menu.pause_resume_button.width and mouse_y > self.pause_menu.pause_resume_button.y and mouse_y < self.pause_menu.pause_resume_button.y + self.pause_menu.pause_resume_button.height:
self.pause_menu.img_id = 1
elif mouse_x > self.pause_menu.pause_x_button.x and mouse_x < self.pause_menu.pause_x_button.x + self.pause_menu.pause_x_button.width and mouse_y > self.pause_menu.pause_x_button.y and mouse_y < self.pause_menu.pause_x_button.y + self.pause_menu.pause_x_button.height:
self.pause_menu.img_id = 2
elif mouse_x > self.pause_menu.pause_options_button.x and mouse_x < self.pause_menu.pause_options_button.x + self.pause_menu.pause_options_button.width and mouse_y > self.pause_menu.pause_options_button.y and mouse_y < self.pause_menu.pause_options_button.y + self.pause_menu.pause_options_button.height:
self.pause_menu.img_id = 3
elif mouse_x > self.pause_menu.pause_quit_button.x and mouse_x < self.pause_menu.pause_quit_button.x + self.pause_menu.pause_quit_button.width and mouse_y > self.pause_menu.pause_quit_button.y and mouse_y < self.pause_menu.pause_quit_button.y + self.pause_menu.pause_quit_button.height:
self.pause_menu.img_id = 4
else:
self.pause_menu.img_id = 0
if mouse_x > self.options_menu.options_x_button.x and mouse_x < self.options_menu.options_x_button.x + self.options_menu.options_x_button.width and mouse_y > self.options_menu.options_x_button.y and mouse_y < self.options_menu.options_x_button.y + self.options_menu.options_x_button.height:
self.options_menu.img_id = 1
elif mouse_x > self.options_menu.options_reset_button.x and mouse_x < self.options_menu.options_reset_button.x + self.options_menu.options_reset_button.width and mouse_y > self.options_menu.options_reset_button.y and mouse_y < self.options_menu.options_reset_button.y + self.options_menu.options_reset_button.height:
self.options_menu.img_id = 2
elif mouse_x > self.options_menu.options_home_button.x and mouse_x < self.options_menu.options_home_button.x + self.options_menu.options_home_button.width and mouse_y > self.options_menu.options_home_button.y and mouse_y < self.options_menu.options_home_button.y + self.options_menu.options_home_button.height:
self.options_menu.img_id = 3
elif mouse_x > self.options_menu.options_ok_button.x and mouse_x < self.options_menu.options_ok_button.x + self.options_menu.options_ok_button.width and mouse_y > self.options_menu.options_ok_button.y and mouse_y < self.options_menu.options_ok_button.y + self.options_menu.options_ok_button.height:
self.options_menu.img_id = 4
else:
self.options_menu.img_id = 0
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
self.player.vel.x = PLAYER_SPEED
if keys[pygame.K_LEFT] or keys[pygame.K_a]:
self.player.vel.x = -PLAYER_SPEED
if keys[pygame.K_UP] or keys[pygame.K_w]:
self.player.vel.y = -PLAYER_SPEED
if keys[pygame.K_DOWN] or keys[pygame.K_s]:
self.player.vel.y = PLAYER_SPEED
def update_game(self):
self.player.update()
self.camera.update(self.player)
if self.player.rect.x <= 0:
self.player.rect.x = 0
if self.player.rect.right >= 5120:
self.player.rect.right = 5120
if self.player.rect.y <= 0:
self.player.rect.y = 0
if self.player.rect.bottom >= 5120:
self.player.rect.bottom = 5120
def draw_game(self):
self.window.blit(self.map, self.camera.apply_rect(self.map_rect))
self.window.blit(self.player.image, self.camera.apply(self.player))
self.hud.draw_health(self.window, 10, 10, self.player.health / PLAYER_HEALTH)
if self.display_main_menu:
self.main_menu.draw()
if self.display_pause_menu:
self.pause_menu.draw()
if self.display_options_menu:
self.options_menu.draw()
pygame.display.flip()
def main():
g = Game()
g.game_loop()
if __name__ == "__main__":
main()
Camera class
import pygame
from Settings import *
class Camera:
def __init__(self, width, height):
self.camera = pygame.Rect(0, 0, width, height)
self.width = width
self.height = height
def apply(self, target):
return target.rect.move(self.camera.topleft)
def apply_rect(self, rect):
return rect.move(self.camera.topleft)
def update(self, target):
x = -target.rect.centerx + int(WINDOW_WIDTH/2)
y = -target.rect.centery + int(WINDOW_HEIGHT/2)
x = min(0, x)
y = min(0, y)
x = max(-(self.width - WINDOW_WIDTH), x)
y = max(-(self.height - WINDOW_HEIGHT), y)
self.camera = pygame.Rect(x, y, self.width, self.height)