Filipek
Filipek

Reputation: 11

Pygame 2D tiled game, moving camera. Character moving faster than camera

I had a problem with creating camera in pygame, I assumed code below should work but our player is moving faster than camera and is going out of the window. Somebody know what's the issue?

import pygame, sys

class Player(pygame.sprite.Sprite):
    def __init__(self, pos, group):
        super().__init__(group)
        self.image = pygame.image.load('./chatacters/players/player_one.png').convert_alpha()
        self.rect = self.image.get_rect(center=(640, 360))
        self.direction = pygame.math.Vector2()
        self.speed = 5

    # key inputs
    def input(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_UP]:
            self.direction.y = -1
        elif keys[pygame.K_DOWN]:
            self.direction.y = 1
        else:
            self.direction.y = 0

        if keys[pygame.K_LEFT]:
            self.direction.x = -1
        elif keys[pygame.K_RIGHT]:
            self.direction.x = 1
        else:
            self.direction.x = 0

    # Moving using inputs
    def move(self, speed):
        if self.direction.magnitude() != 0:
            self.direction = self.direction.normalize()

        self.rect.center += self.direction * speed

    # updating drawing
    def update(self):
        self.input()
        self.move(self.speed)


class Camera(pygame.sprite.Group):
    def __init__(self):
        super().__init__()
        self.display_surface = pygame.display.get_surface()
        self.offset = pygame.math.Vector2()
        self.half_w = self.display_surface.get_size()[0] // 2
        self.half_h = self.display_surface.get_size()[1] // 2

        self.map = pygame.image.load('./map/level_data/level.png').convert_alpha()
        self.rect = self.map.get_rect(topleft=(0, 0))

    def custom_draw(self, player):
        self.offset.x = player.rect.centerx - self.half_w
        self.offset.y = player.rect.centery - self.half_h

        ground_offset = self.rect.topleft - self.offset
        self.display_surface.blit(self.map, ground_offset)


class Game():
    def __init__(self):
        # Settings
        self.WIDTH = 1280
        self.HEIGHT = 720
        self.FPS = 60

        pygame.init()
        pygame.display.set_caption('BetterFortinite')


        self.screen = pygame.display.set_mode((self.WIDTH, self.HEIGHT))
        self.clock = pygame.time.Clock()
        self.camera_group = Camera()
        self.player = Player((100, 200), self.camera_group)



    def game(self):
        while True:
            self.clock.tick(self.FPS)
            self.screen.fill('black')
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()

            # self.screen.fill("WHITE")

            self.camera_group.custom_draw(self.player)
            self.player.move(5)
            self.player.update()
            self.camera_group.draw(self.screen)
            # self.camera_group.update()
            pygame.display.update()




if __name__ in '__main__':
    game = Game()
    game.game()

I'm taking the center position of player rect minus half of the width size. Same with height and setting with it my offset. Then I'm setting my ground_offset as cords of topleft screen rect minus offset. What is wrong with this formula?

Upvotes: 0

Views: 121

Answers (1)

The_spider
The_spider

Reputation: 1255

The problem is not with your formula, but with the code itsself. In the main game loop, you have:

self.player.move(5)
self.player.update()

While Player.update contains:

def update(self):
    self.input()
    self.move(self.speed)

As you can see, player.move is called twice. This means that the player is moved twice as much as intended and thus twice as fast as the camera, causing both to move at a different speed.

The solution to this problem would be to remove one of the calls of Player.move. I would remove the one in the main game loop as it uses a hardcoded value rather than the Player.speed constant, but it doesn't really matter which one you remove.

Upvotes: 1

Related Questions