I've seen many posts about different ways to implement a simple camera that works in a 2D side scroller game. My way of handling this is by making an object that offsets the position of everything as long as the player is centered in the screen and not at the ends of the screen.
This works absolutely fine, but I want to think bigger.
So, I wondered how I could add "smooth camera movement" where the player isn't just stuck in the middle of the screen all the time, but the camera is actually following the player. In search of an answer, I found examples that work only in Java. I was unsure of how to add this feature in pygame though. If you think you could explain to me how this could be implemented, that would be of great help.
Just in case you don't know what I mean by "smooth camera movement", you can skim through this video to kinda get the idea of what I'm talking about. Any tips or starting points you can give me will be very helpful as I've already mentioned.
You can do this with vectors. I just use a vector as the camera here and make it follow the player. First subtract the camera
from the player.pos
to get another vector (called heading
here) which points from the camera to the player. Then scale this vector to the desired speed (a fraction of the length) and use it as the velocity of the camera.
from random import randrange
import pygame as pg
from pygame.math import Vector2
class Player(pg.sprite.Sprite):
def __init__(self, pos, *groups):
super().__init__(*groups)
self.image = pg.Surface((30, 30))
self.image.fill(pg.Color('dodgerblue1'))
self.rect = self.image.get_rect(center=pos)
self.pos = Vector2(pos)
self.vel = Vector2(0, 0)
def handle_event(self, event):
if event.type == pg.KEYDOWN:
if event.key == pg.K_d:
self.vel.x = 5
elif event.key == pg.K_a:
self.vel.x = -5
elif event.key == pg.K_w:
self.vel.y = -5
elif event.key == pg.K_s:
self.vel.y = 5
elif event.type == pg.KEYUP:
if event.key == pg.K_d and self.vel.x > 0:
self.vel.x = 0
elif event.key == pg.K_a and self.vel.x < 0:
self.vel.x = 0
elif event.key == pg.K_w:
self.vel.y = 0
elif event.key == pg.K_s:
self.vel.y = 0
def update(self):
# Move the player.
self.pos += self.vel
self.rect.center = self.pos
def main():
pg.init()
screen = pg.display.set_mode((800, 600))
clock = pg.time.Clock()
all_sprites = pg.sprite.Group()
camera = Vector2(400, 300)
player = Player((400, 300), all_sprites)
background_rects = [pg.Rect(randrange(-3000, 3001), randrange(-3000, 3001), 20, 20)
for _ in range(500)]
while True:
for event in pg.event.get():
if event.type == pg.QUIT:
return
player.handle_event(event)
all_sprites.update()
# A vector that points from the camera to the player.
heading = player.pos - camera
# Follow the player with the camera.
# Move the camera by a fraction of the heading vector's length.
camera += heading * 0.05
# The actual offset that we have to add to the positions of the objects.
offset = -camera + Vector2(400, 300) # + 400, 300 to center the player.
screen.fill((30, 30, 30))
# Blit all objects and add the offset to their positions.
for background_rect in background_rects:
topleft = background_rect.topleft + offset
pg.draw.rect(screen, (200, 50, 70), (topleft, background_rect.size))
screen.blit(player.image, player.rect.topleft+offset)
pg.display.flip()
clock.tick(60)
if __name__ == '__main__':
main()
pg.quit()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.