0

I am trying currently to program a functioning camera that follows the player, and stops whenever the player gets close enough to the border that the outside would appear.

Most of everything works fine except for the collision with the right and bottom parts of the screen.

The code for the collision part is as follows:

for sprite in self.sprites():
    rectPosition = sprite.rect.topleft - self.offset
            
    if self.offset.x < self.mapRect.x:
        self.offset.x = 0
        rectPosition = sprite.rect.topleft - self.offset
    if self.offset.y < self.mapRect.y:
        self.offset.y = 0
        rectPosition = sprite.rect.topleft - self.offset

    if self.offset.x > self.mapRect.w:
        self.offset.x = 0
        rectPosition = sprite.rect.topleft - self.offset
    if self.offset.y > self.mapRect.h:
        self.offset.y = 0
        rectPosition = sprite.rect.topleft - self.offset

    screen.blit( sprite.image, rectPosition)

The collisions for the top and left sides of the screen work fine, but the right and bottom ones don't seem to work correctly. If the player moves enough off screen (seems about half the screen's supposed length) to either of the faulty sides, it does trigger a collision, but it still doesn't work as intended i believe because the camera position seems to be reset to (0,0)

I've tried different attributes for the mapRect (w, h, right, bottom) and conditions (offset.y < mapRect.height instead of >) but the most that will happen, is that it sets the camera position to (0,0) as well, otherwise nothing will change. Also tried manually setting the width and height values in the condition instead of getting them from the map Rect.

The game screen is first blited to a Surface before being blited to the actual game screen, so that the contents in the screen are resizable. I've of course changed it to draw everything in the game screen to see if anything changes but no luck.

What can i do to fix this so that it will work as intended?

If needed, the rest of the game code is below:

import pygame

pygame.init()
screen_SIZE = width, height = 768, 648
screen = pygame.display.set_mode(screen_SIZE)



class Background(pygame.sprite.Sprite):
    def __init__(self, group):
        super().__init__(group)
        self.image = pygame.Surface((1152,972))
        self.rect = pygame.Rect(0,0,1152,972)
        pygame.draw.rect(self.image, 'red', self.rect)
        #big red rectangle
class Background_Center(pygame.sprite.Sprite):
    def __init__(self, group):
        super().__init__(group)
        self.image = pygame.Surface((200,200))
        self.rect = pygame.Rect(576,486,200,200)
        pygame.draw.rect(self.image, 'black', self.rect)
        #big square in the middle
class Player(pygame.sprite.Sprite):
    def __init__(self, group):
        super().__init__(group)
        self.image = pygame.Surface((64, 64))
        self.rect = pygame.Rect(400, 800, 64, 64)
        pygame.draw.rect(self.image, 'white', self.rect)
        #movement
        self.direction = pygame.math.Vector2()
        self.speed = 5

    def input(self):
        key = pygame.key.get_pressed()
        #keys
        if key[pygame.K_UP]:
            self.direction.y = -1
        elif key[pygame.K_DOWN]: 
            self.direction.y = 1
        else:
            self.direction.y = 0
        if key[pygame.K_RIGHT]:
            self.direction.x = 1
        elif key[pygame.K_LEFT]:
            self.direction.x = -1
        else:
            self.direction.x = 0
    def move(self):
        self.rect.x += self.direction.x * self.speed
        self.rect.y += self.direction.y * self.speed

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

class camera_group(pygame.sprite.Group):
    def __init__(self):
        super().__init__()
        self.display = screen

        self.offset = pygame.math.Vector2()
        self.half_w = self.display.get_size()[0] // 2
        self.half_h = self.display.get_size()[0] // 2

    def custom_draw(self, target, map):
        rectPosition = []
        self.mapRect = map.rect
        self.offset.x = target.rect.centerx - self.half_w
        self.offset.y = target.rect.centery - self.half_h

        for sprite in self.sprites():
            rectPosition = sprite.rect.topleft - self.offset
            
            if self.offset.x < self.mapRect.x:
                self.offset.x = 0
                rectPosition = sprite.rect.topleft - self.offset
            if self.offset.y < self.mapRect.y:
                self.offset.y = 0
                rectPosition = sprite.rect.topleft - self.offset

            if self.offset.x > self.mapRect.w:
                self.offset.x = 0
                rectPosition = sprite.rect.topleft - self.offset
            if self.offset.y > self.mapRect.h:
                self.offset.y = 0
                rectPosition = sprite.rect.topleft - self.offset

            screen.blit( sprite.image, rectPosition)
            
camera = camera_group()
map = Background(camera)
map_center = Background_Center(camera)
player = Player(camera)

clock = pygame.time.Clock()
while True:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()
    screen.fill('white')
    camera.update()
    camera.custom_draw(player, map)

    pygame.display.update()

Alv-Rod
  • 1
  • 2

0 Answers0