简体   繁体   中英

How would I go about creating smooth camera movement in pygame?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM