简体   繁体   English

如何在pygame中创建流畅的相机运动?

[英]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. 我已经看过许多关于在2D侧滚动游戏中实现简单相机的不同方法的文章。 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. 为了寻找答案,我找到了仅在Java中有效的示例。 I was unsure of how to add this feature in pygame though. 我不确定如何在pygame中添加此功能。 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. 首先从player.pos减去camera ,以获得另一个从相机指向播放器的向量(此处为heading )。 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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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