1

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

  1. Pygame Making A Sprite Face The Mouse

  2. https://ubuntuforums.org/showthread.php?t=1823825

  3. https://gamedev.stackexchange.com/questions/132163/how-can-i-make-the-player-look-to-the-mouse-direction-pygame-2d

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)
  • FYI, the player rotates somewhat, but doesn't seem to follow the mouse and or doesn't keep up with the mouse movement. – 18 Triston Lehmann Jul 07 '17 at 00:28
  • if you only scroll the mouse in a continues single direction are they rotating in circles? –  Jul 07 '17 at 00:39
  • Can you elaborate more, I didn't quite understand what you said. – 18 Triston Lehmann Jul 07 '17 at 00:43
  • So if you drag your mouse from left to right only, pick it up and put it down on the left and keep dragging right.. does the character rotate 360 degrees? –  Jul 07 '17 at 00:44
  • When I drag my mouse in a full 360 degree motion either clockwise or counter clock wise the sprite properly rotates. But once I drag my mouse in a single direction, the player image doesn't properly rotate, and all the chaos emerges. – 18 Triston Lehmann Jul 07 '17 at 00:51
  • The rotate function rotates an image by a set amount, so I think what's going on is that when you move the mouse you're passing that function values and it keeps rotating in relation to itself rather than trying to face the mouse. what you want instead is to set some sort of rotation value based on the mouse, not to rotate it by x or y degrees based on mouse movement. –  Jul 07 '17 at 01:46
  • You should add the original code example again and create a separate paragraph for the modified example. – skrx Jul 07 '17 at 04:08

1 Answers1

1

Use the center points self.rect.centerx and self.rect.centery or just self.rect.center and self.pos instead of self.rect.x self.rect.y (the topleft coordinates).

Here's the complete example that I used to test your code:

import math
import pygame
from pygame.math import Vector2


class Player(pygame.sprite.Sprite):
    def __init__(self, pos):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((50, 30), pygame.SRCALPHA)
        pygame.draw.polygon(
            self.image,
            pygame.Color('dodgerblue1'),
            ((0, 0), (50, 15), (0, 30)))
        self.rect = self.image.get_rect(center=pos)
        self.orig_img = self.image
        self.pos = Vector2(pos)
        self.vel = Vector2(0, 0)

    def update(self):
        self.rotate()
        self.pos += self.vel
        self.rect.centerx = self.pos.x
        self.rect.centery = self.pos.y

    def rotate(self):
        mouse_pos = pygame.mouse.get_pos()
        # Calculate the vector to the mouse position by subtracting
        # the self.pos vector from the mouse_pos.
        rel_x, rel_y = mouse_pos - self.pos
        # Use math.atan2 to get the angle in radians and convert it to degrees.
        angle = -math.degrees(math.atan2(rel_y, rel_x))
        # Rotate the image.
        self.image = pygame.transform.rotozoom(self.orig_img, angle, 1)
        # Update the rect and keep the center at the old position.
        self.rect = self.image.get_rect(center=self.rect.center)


def main():
    screen = pygame.display.set_mode((640, 480))
    clock = pygame.time.Clock()
    sprite_group = pygame.sprite.Group()
    player = Player((300, 200))
    sprite_group.add(player)

    done = False

    while not done:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True

        sprite_group.update()
        screen.fill((30, 30, 30))
        sprite_group.draw(screen)

        pygame.display.flip()
        clock.tick(30)


if __name__ == '__main__':
    pygame.init()
    main()
    pygame.quit()

Edit3: In this example I use another pygame.Rect (called hitbox) to handle the collisions with the walls. The rect of the player can't be used for the collision detection, because it changes its size with each rotation what causes jumps if the player touches a wall. I'm using Rect.colliderect because spritecollide uses the rect not the hitbox, but you could also pass a custom collided callback function to spritecollide. (The red and green rects show the player.rect and player.hitbox.)

import math
import pygame
from pygame.math import Vector2 as vec


class Player(pygame.sprite.Sprite):
    def __init__(self, x, y, walls):
        pygame.sprite.Sprite.__init__(self)
        self.walls = walls
        self.image = pygame.Surface((50, 30), pygame.SRCALPHA)
        pygame.draw.polygon(
            self.image,
            pygame.Color('dodgerblue1'),
            ((0, 0), (50, 15), (0, 30)))
        self.rect = self.image.get_rect(center=(x, y))
        self.hitbox = pygame.Rect(x, y, 50, 50)
        self.orig_img = self.image
        self.pos = vec(x, y)
        self.vel = vec(0, 0)

    def update(self):
        self.rotate()
        self.pos += self.vel
        self.hitbox.centerx = self.pos.x
        self.collide_with_tiles(self.walls, "x")
        self.hitbox.centery = self.pos.y
        self.collide_with_tiles(self.walls, "y")
        self.rect.center = self.pos

    def rotate(self):
        rel_x, rel_y = pygame.mouse.get_pos() - self.pos
        angle = -math.degrees(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)

    def collide_with_tiles(self, group, dir):
        if dir == "x":
             for wall in self.walls:
                 if self.hitbox.colliderect(wall.rect):
                     if self.vel.x > 0:
                         self.hitbox.right = wall.rect.left
                     if self.vel.x < 0:
                         self.hitbox.left = wall.rect.right
                     self.vel.x = 0
                     self.pos.x = self.hitbox.centerx

        if dir == "y":
            for wall in self.walls:
                if self.hitbox.colliderect(wall.rect):
                    if self.vel.y > 0:
                        self.hitbox.bottom = wall.rect.top
                    if self.vel.y < 0:
                        self.hitbox.top = wall.rect.bottom
                    self.vel.y = 0
                    self.pos.y = self.hitbox.centery


class Wall(pygame.sprite.Sprite):
    def __init__(self, x, y, w, h):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((w, h))
        self.image.fill(pygame.Color('sienna1'))
        self.rect = self.image.get_rect(topleft=(x, y))


def main():
    screen = pygame.display.set_mode((640, 480))
    clock = pygame.time.Clock()

    sprite_group = pygame.sprite.Group()
    walls = pygame.sprite.Group()

    wall = Wall(100, 200, 300, 30)
    walls.add(wall)
    sprite_group.add(wall)

    player = Player(300, 400, walls)
    sprite_group.add(player)

    done = False

    while not done:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_w:
                    player.vel.y = -3
                elif event.key == pygame.K_s:
                    player.vel.y = 3
                elif event.key == pygame.K_a:
                    player.vel.x = -3
                elif event.key == pygame.K_d:
                    player.vel.x = 3
            elif event.type == pygame.KEYUP:
                player.vel = vec(0, 0)

        sprite_group.update()
        screen.fill((30, 30, 30))
        sprite_group.draw(screen)
        pygame.draw.rect(screen, (200, 30, 30), player.rect, 2)
        pygame.draw.rect(screen, (0, 200, 30), player.hitbox, 2)

        pygame.display.flip()
        clock.tick(30)


if __name__ == '__main__':
    pygame.init()
    main()
    pygame.quit()

Edit4: To include the camera in the calculation, give the Player the camera as an attribute and in the rotate method just change this line:

rel_x, rel_y = pg.mouse.get_pos() - vec(self.camera.apply(self).center)
skrx
  • 19,980
  • 5
  • 34
  • 48
  • As much as I wanted this to work, this solution seems ineffective. The rotation is still working improperly :( – 18 Triston Lehmann Jul 07 '17 at 03:10
  • Then you have to provide a complete example which I can test, because something else (that is not included in your post) seems to be wrong. – skrx Jul 07 '17 at 03:14
  • Okay I'll provide more from the Player class. – 18 Triston Lehmann Jul 07 '17 at 03:15
  • Check out this complete example. – skrx Jul 07 '17 at 03:20
  • I suspect the error might lie in my collide_with_tiles function perhaps. Idk i'm really clueless at this point. – 18 Triston Lehmann Jul 07 '17 at 03:21
  • As far as I can tell, everything matches up, except for the collide_with_tile function, let me try the program without this function. – 18 Triston Lehmann Jul 07 '17 at 03:25
  • Yes, it looks like the `collide_with_tiles` method causes the bug, but only if the player collides with a wall. – skrx Jul 07 '17 at 03:39
  • So far its effective at following the mouse in a full 360 degree angle, but once I move the sprite and try to rotate the sprite to face the way the mouse is, that's were all the problems arise. – 18 Triston Lehmann Jul 07 '17 at 03:40
  • Try adding some basic movement like moving right, left, up, and down and then try testing the script to see if the player rotates to face the mouse. – 18 Triston Lehmann Jul 07 '17 at 03:43
  • Yes, it rotates correctly, except if the player touches a wall. I've posted a modified `collide_with_tiles` method that should work better, but there's still a problem because the rect of the player changes every time it rotates. Edit: Actually I think it's better to use the `pos` not the `rect.center` to set the position. I'll change the method again. – skrx Jul 07 '17 at 03:57
  • This is getting a bit difficult. Because of the changing size of the player.rect, the collision with the walls gets buggy. Maybe the player needs another rect which we can use for the collision detection (the changing rect would just be used for the blitting). – skrx Jul 07 '17 at 04:12
  • Idk what the problem is but every time I change my mouses position, the player's rotation doesn't follow. I must've really screwed up. – 18 Triston Lehmann Jul 07 '17 at 04:21
  • Yeah, sounds like you've got another problem. :) Try to post a complete example that I can just copy, paste and run. – skrx Jul 07 '17 at 04:23
  • K I'm crafting an example up right now, where do you want me to post it. – 18 Triston Lehmann Jul 07 '17 at 04:32
  • Just add it to the question. We'll clean up later. ;) – skrx Jul 07 '17 at 04:35
  • There you go, I coded this in about 7 minutes so, I hope it works. I hope this helps you identify my error for my actual game. – 18 Triston Lehmann Jul 07 '17 at 04:54
  • I've also added another example with walls and a second rect which is used for the collision detection. – skrx Jul 07 '17 at 05:02
  • Well, your going over and beyond, which is very appreciated :) – 18 Triston Lehmann Jul 07 '17 at 05:06
  • I've just checked out your *"Fast paced Example:"* and it seems to work correctly. – skrx Jul 07 '17 at 05:08
  • Sorry for not replying for a while, I'm still trying to figure out whats wrong. Your help has been very appreciated though, Thank you!!!! – 18 Triston Lehmann Jul 07 '17 at 05:38
  • I could help, but I'm still waiting for the complete (bugged) example. ;) Maybe you still use `rect.x` `rect.y` somewhere instead of `rect.centerx`. – skrx Jul 07 '17 at 05:42
  • I can the Game class, and the player class because that's most likely the place where the problem lies. – 18 Triston Lehmann Jul 07 '17 at 05:47
  • Okay I posted the Game class which is the only other place, I believe the bug would be, so I hope this helps. Sorry for taking up so much of your time over my pathetic error :( – 18 Triston Lehmann Jul 07 '17 at 06:01
  • I was actually hoping for a [minimal, complete and verifiable example](https://stackoverflow.com/help/mcve), but I'll take a look at it anyway. We should really clean up the question later. – skrx Jul 07 '17 at 06:49
  • Ya, I'm sorry about that. I totally agree its pretty long. Which is why I didn't' want to post it. – 18 Triston Lehmann Jul 07 '17 at 07:00
  • I couldn't run your game, but I'm relatively sure that your camera causes your problems. You somehow have to include the camera offset in your calculations. – skrx Jul 07 '17 at 07:49
  • Sorry for not responding for so long. Well anyway I can provide the Camera class if that's were the error is occurring. – 18 Triston Lehmann Jul 07 '17 at 15:53
  • Yes, that would probably help. I'll check it out tomorrow. – skrx Jul 07 '17 at 16:02