4

I am working on a very rough topdown 2d adventure game after skimming around the pygame documentation. However, I have hit a bit of a roadblock after not being able to find anything on a camera system and found that most tutorials for a camera are 5+ years old and don't seem to work anymore. Can anybody help me build a camera?

This is my main executed script

import sys, pygame
from PlayerObject import Player

pygame.init()

screen_height = 180
screen_width = 320
map_height = 1080
map_width = 1920

num_objects = 5

screen = pygame.display.set_mode((screen_width, screen_height))
player_image = pygame.image.load('models/hero.bmp').convert()
background = pygame.image.load('models/lobby.bmp').convert()
screen.blit(background, (0, 0))
objects = []

# randomly generates 5 entities with the 1st one being the controlled character
for i in range(num_objects):
    o = Player(player_image, random.randint(0, screen_width), random.randint(0, screen_height), 10)
    objects.append(o)

while 1:

    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        screen.blit(background, objects[0].pos, objects[0].pos)
        objects[0].move_left()
        screen.blit(objects[0].image, objects[0].pos)
    if keys[pygame.K_RIGHT]:
        screen.blit(background, objects[0].pos, objects[0].pos)
        objects[0].move_right()
        screen.blit(objects[0].image, objects[0].pos)
    if keys[pygame.K_UP]:
        screen.blit(background, objects[0].pos, objects[0].pos)
        objects[0].move_up()
        screen.blit(objects[0].image, objects[0].pos)
    if keys[pygame.K_DOWN]:
        screen.blit(background, objects[0].pos, objects[0].pos)
        objects[0].move_down()
        screen.blit(objects[0].image, objects[0].pos)
        screen.blit(background)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    for o in objects:
        screen.blit(background, o.pos, o.pos)
    for num in range(num_objects - 1):
        objects[num + 1].rand_move()
    for o in objects:
        screen.blit(o.image, o.pos)

    pygame.display.update()
    pygame.time.delay(100)

This is my Player class

import random

map_height = 180
map_width = 320

class Player:
    def __init__(self, image, width, height, speed):
        self.speed = speed
        self.image = image
        self.pos = image.get_rect().move(width, height)
        self.image = image

    def set_speed(self, speed):
        self.speed = speed

    def rand_move(self):
        x = random.randint(-self.speed, self.speed)
        y = random.randint(-self.speed, self.speed)
        self.pos = self.pos.move(x, y)

        # keeps player in boundaries
        if self.pos.left < 0:
            self.pos.left = 0
        if self.pos.right > map_width:
            self.pos.right = map_width
        if self.pos.top < 0:
            self.pos.top = 0
        if self.pos.bottom > map_height:
            self.pos.bottom = map_height

    def move_left(self):
        speed = self.speed
        self.pos = self.pos.move(-speed, 0)
        if self.pos.left < 0:
            self.pos.left = 0

    def move_right(self):
        speed = self.speed
        self.pos = self.pos.move(speed, 0)
        if self.pos.right > map_width:
            self.pos.right = map_width

    def move_up(self):
        speed = self.speed
        self.pos = self.pos.move(0, -speed)
        if self.pos.top < 0:
            self.pos.top = 0

    def move_down(self):
        speed = self.speed
        self.pos = self.pos.move(0, speed)
        if self.pos.bottom > map_height:
            self.pos.bottom = map_height
Rabbid76
  • 202,892
  • 27
  • 131
  • 174

1 Answers1

2

Your basic misunderstanding, is that you try to draw the background at the position of an object, then you move the object and blit it finally on its new position. That all is not necessary.
In common the entire scene is drawn in each frame in the main application loop. It is sufficient to draw the background to the entire window and blit each object on top of it. Note, you do not see the changes of the window surface immediately. The changes become visible, when the display is updated by pygame.display.update() or pygame.display.flip():

The main application loop has to:

e.g.:

while 1:

    # handle events
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    # update objects (depends on input events and frames)
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        objects[0].move_left()    
    if keys[pygame.K_RIGHT]:
        objects[0].move_right()
    if keys[pygame.K_UP]:
        objects[0].move_up()
    if keys[pygame.K_DOWN]:
        objects[0].move_down()

    for num in range(num_objects - 1):
        objects[num + 1].rand_move()

    # draw background
    screen.blit(background, (0, 0))

    # draw scene
    for o in objects:
        screen.blit(o.image, o.pos)

    # update dispaly
    pygame.display.update()
    pygame.time.delay(100)

Minimal example: repl.it/@Rabbid76/PyGame-MinimalApplicationLoop

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • First off, thank you so much for responding! I think I understand blitting a little bit better after reading your comments and fiddling around with the code you gave as an example. Speaking of which, I changed the screen.blit(background, (0,0) to screen.blit(background, (-L+speed, -T+speed) where L and T are the rect positions of my characte and speed is how far the character moves each frame. This simulates a camera but it appears that the character reaches the edge of the screen before the map ends. I have tried messing with it but nothing seems to work, do you have any suggestions? Thanks!! – AsianTemptation Feb 26 '20 at 06:28
  • @AsianTemptation *"but it appears that the character reaches the edge of the screen before the map ends."* I have no idea what you mean. Is that a new question? – Rabbid76 Feb 26 '20 at 07:26
  • Well, my original question was on how to build a workable camera and I have built a very rough one where the character moves faster than the map underneath him is updated. I don't know how to describe it but it seems that he is moving relative to the screen window and I'm not sure how to keep him centered. – AsianTemptation Feb 26 '20 at 23:43
  • @AsianTemptation Your question is to broad. Please read [How do I ask a good question?](https://stackoverflow.com/help/how-to-ask) and [How to create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve). I recommend to show hat you have tried so far and to [Ask a public question](https://stackoverflow.com/questions/ask) again. – Rabbid76 Feb 27 '20 at 07:37