pythonpygame

Trying to make a top down shooter on pygame and having trouble trying to figure out how to scroll the map when the player moves


I am currently trying to make a top down shooter game, but I am having a bit of trouble trying to figure out how to move the map when the character moves (Up, down, left, and right). I want the map to always fill the screen but when the character moves the map will move with it. I have looked online trying to find some solutions but having a hard time trying to implement it into my own program.

import pygame
pygame.display.set_caption("TEST")

clock = pygame.time.Clock()

class Player():

  def __init__(self,x,y):
    self.Image = pygame.image.load("myAvatar.png").convert()

    self.rect  = self.Image.get_rect(topleft = (x,y))

  def getX(self):
    return self.rect.x

  def getY(self):
    return self.rect.y

  def handle_keys(self,screenHeight,screenWidth):
      key = pygame.key.get_pressed()
      dist = 1 

      if key[pygame.K_DOWN]: 
          self.rect.y += dist
          if self.rect.y > screenHeight:
            self.rect.y = screenHeight
    
      elif key[pygame.K_UP]: 
          self.rect.y -= dist
          if self.rect.y < 0:
            self.rect.y = 0  
      if key[pygame.K_RIGHT]: 
          self.rect.x += dist
          if self.rect.x > screenWidth:
            self.rect.x = screenWidth
      elif key[pygame.K_LEFT]: 
          self.rect.x -= dist
          if self.rect.x < 0:
            self.rect.x = 0 

  def draw(self, game_window,screenX,screenY):
    self.Image = pygame.transform.scale(self.Image,(20,20))
    game_window.blit(self.Image, (screenX, screenY))


class Map():
  def __init__(self):
    self.Image = pygame.image.load("testbackground.jpg").convert()
    self.rect = self.Image.get_rect()
    self.rect.x = 0
    self.rect.y = 0

  def getX(self):
    return self.rect.x

  def getY(self):
    return self.rect.y

  def setX(self,newX):
    self.rect.x = newX
  
  def setY(self,newY):
    self.rect.y = newY

  def draw(self, game_window,screenX,screenY):
    self.Image = pygame.transform.scale(self.Image,(800,800))
    game_window.blit(self.Image,(screenX, screenY))


class Enemy():

  def __init__ (self,x,y):
    self.Image = pygame.image.load("WC.jpg").convert()
    self.rect  = self.Image.get_rect(topleft = (x,y))

  def draw(self, game_window):
    self.Image = pygame.transform.scale(self.Image,(20,20))
    game_window.blit(self.Image, (self.rect.x, self.rect.y))


pygame.init()

clock = pygame.time.Clock()
screenWidth = 400
screenHeight = 400
game_window = pygame.display.set_mode((screenWidth,screenHeight))
player = Player(200,200)
map = Map()
enemy = Enemy(250,250)
leave = False
while not leave:
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      pygame.quit() 
      running = False

  playerX = player.getX()
  playerY = player.getY()

  mapX = map.getX()
  mapY = map.getY()

  screenX = playerX - (screenWidth/2)
  if screenX < 0:
    screenX = 0
  if screenX > (mapX - screenWidth):
    screenX = (mapX - screenWidth)

  screenY = playerY - (screenHeight/2)
  if screenY < 0:
    screenY = 0
  if screenY > (mapY - screenHeight):
    screenY = (mapY - screenHeight)
  
  player.handle_keys(screenHeight,screenWidth)

  map.draw(game_window,screenX,screenY)
  enemy.draw(game_window)
  player.draw(game_window,screenX,screenY)
  pygame.display.update()
  pygame.display.flip()
  clock.tick(60)


pygame.quit()
quit()

Solution

  • You can move the camera like in this question:

    Basically, every sprite has a position, and is drawn on the screen like this:

    pos_on_the_screen = (posX - cameraX, posY - cameraY)
    

    Then, the camera follows the player like this:

    width, height = sceen_size
    camera_pos = (player.posX - width / 2, player.posY - height / 2)
    

    In this case, the player stays in the center of the screen.


    If you want the camera to follow the player, but you don't want the player to be constantly in the center (it could move a little bit, but not exit the screen), you can use this method:

    width, height = screen_size
    if cameraX - playerX > 2 * width / 3: # player exits to the right
        cameraX = playerX - 2 * width / 3
    elif cameraX - playerX < width / 3: # player exits to the left
        cameraX = playerX - width / 3
    if cameraY - playerY > 2 * height / 3: # player exits to the bottom
        cameraY = playerY - 2 * height / 3
    elif cameraY - playerY < height / 3: # player exits to the top
        cameraY = playerY - height / 3
    

    In this example, the player never goes out of this space:

    You can also use a more compact form:

    width, height = screen_size
    cameraX = min(max(cameraX, playerX - 2 * width / 3), playerX - width / 3)
    cameraY = min(max(cameraY, playerY - 2 * height / 3), playerY - height / 3)
    

    Example (link):