Python 尝试在Pygame简单2D平台中为玩家设置屏幕中心

Python 尝试在Pygame简单2D平台中为玩家设置屏幕中心,python,pygame,camera,2d,Python,Pygame,Camera,2d,我正在Pygame中创建一个简单的2D平台。在这个项目中,我一直在尝试更多地使用类来进行良好的实践。我目前的问题是,我试图使屏幕在播放器上居中,但我找不到一种方法来实现这一点,我的代码目前设置的方式 此外,我计划稍后添加一种方法,使屏幕以较小的延迟跟随玩家,随着距离的增加,跟随速度加快。然而,让摄像机对准球员是我最关心的问题 当玩家向右移动时,我让所有的“平台矩形”以相同的速度向左移动。我尝试过不同的速度,将播放器设置为零速度,只需移动“PlatformRects”就可以了(在“player”类

我正在Pygame中创建一个简单的2D平台。在这个项目中,我一直在尝试更多地使用类来进行良好的实践。我目前的问题是,我试图使屏幕在播放器上居中,但我找不到一种方法来实现这一点,我的代码目前设置的方式

此外,我计划稍后添加一种方法,使屏幕以较小的延迟跟随玩家,随着距离的增加,跟随速度加快。然而,让摄像机对准球员是我最关心的问题

当玩家向右移动时,我让所有的“平台矩形”以相同的速度向左移动。我尝试过不同的速度,将播放器设置为零速度,只需移动“PlatformRects”就可以了(在“player”类的“update”funct中的代码中有相关注释)。我也尝试过让“平台矩形”的移动取决于玩家的位置,但我也无法让它工作

我将感谢任何帮助。这是我的代码(我删掉了很多不相关的代码,比如动画等等):

import pygame,sys,random
#---班级----------------------------------------#
类PlatformRect(pygame.sprite.sprite):
定义初始(self,x_pos,y_pos,size_x,size_y,path,players):
super()。\uuuu init\uuuuu()
self.x_pos=x_pos
self.y_pos=y_pos
self.size\u x=size\u x
self.size\u y=size\u y
self.players=玩家
self.can_jump1=无
如果路径==“null”:
self.image=pygame.Surface((self.size\ux,self.size\uy))
self.rect=self.image.get_rect(左上方=(self.x_pos,self.y_pos))
其他:
self.image=pygame.transform.scale(pygame.image.load(path.convert_alpha(),(size_x,size_y))
self.rect=self.image.get_rect(左上方=(self.x_pos,self.y_pos))
def碰撞检查(自检):
如果pygame.sprite.spritecollide(self,self.players,False):
碰撞桨=pygame.sprite.spritecollide(self,self.players,False)[0]。矩形
如果player.movement_y>0且abs(self.rect.top-collision_-paller.bottom)<10:#检查以确保碰撞的是正确的一侧
碰撞桨.bottom=self.rect.top
player.movement_y=0
self.can_jump1=真
elif player.movement_y<0且abs(self.rect.bottom-collision_-blade.top)<10且非abs(self.rect.right-collision_-blade.left)<10且非abs(self.rect.left-collision_-blade.right)<10:
碰撞桨.top=self.rect.bottom
player.movement_y*=-0.2
打印(“移动底部”)
elif player.movement_x<0且abs(self.rect.right-碰撞_桨.left)<10,而非abs(self.rect.bottom-碰撞_桨.top)<10:
碰撞桨左=自右
打印(“向左移动”)
elif player.movement_x>0且abs(self.rect.left-collision_-blade.right)小于10,而非abs(self.rect.bottom-collision_-blade.top)<10:
碰撞桨。右=自。直。左
打印(“向右移动”)
其他:
self.can_jump1=self.rect.top==self.players.sprites()[0].rect.bottom
def can_jump_check(自检):
返回自我can_跳线1
def更新(自我):
自碰撞检查()
self.rect.centerx-=player.movement_x#尝试让rect移动与播放器相同的距离,如果播放器向右移动2像素,rect向左移动2像素?
self.rect.centery-=0
职业玩家(pygame.sprite.sprite):
定义初始(自身、x位置、y位置、尺寸x、尺寸y、速度x、加速度y):
super()。\uuuu init\uuuuu()
self.x_pos=x_pos
self.y_pos=y_pos
self.size\u x=size\u x
self.size\u y=size\u y
self.speed\u x=速度
self.shift\u pressed=False
自加速_y=加速_y
self.movement_x=0
self.movement_y=0
self.image=pygame.Surface((self.size\ux,self.size\uy))
self.image.fill(“红色”)
self.rect=self.image.get_rect(中心=(self.x_pos,self.y_pos))
def屏幕_约束(自):
如果self.rect.bottom>=sresy:
self.rect.bottom=sresy
def更新(自我):

如果abs(self.movement_y)你应该像这样移动相机:

#开始时:设置摄像头
camera=pygame.math.Vector2((0,0))
#在主循环中:调整摄像机位置,使播放器居中
camera.x=player.x_pos-resx/2
camera.y=player.y_pos-resy/2
#在每个精灵类中:根据相机移动,而不是更改精灵位置
屏幕上的位置=(self.x\u pos-camera.x,self.y\u pos-camera.y)
  • 摄像机跟随播放器,并将其自身放置,使播放器位于屏幕中央
  • 每个精灵的位置永远不会改变,不断改变精灵的位置是一个非常糟糕的主意
  • 根据相机的不同,每个精灵都会在屏幕上绘制
要减少延迟,应仅在每个精灵可见时显示:

screen_rect=pygame.rect((0,0),(resx,resy))
sprite_rect=pygame.rect((self.x_pos-camera.x,self.y_pos-camera.y),sprite_image.get_size())
如果screen\u rect.collide rect(精灵\u rect):
#渲染(如果可见)

下面是我制作的游戏中移动背景的屏幕截图,使用相同的方法:

在这里,我移动相机更平稳。基本上,我使用这种方法:

speed=1
距离x=播放器x位置-camera.x
距离_y=player.y_pos-camera.y
camera.x=(camera.x*速度+距离x)/(速度+1)
camera.y=(camera.y*速度+距离_y)/(速度+1)
我会根据FPS改变速度。

你应该提供一份关于你尝试过什么和失败了什么的报告。但本质上,你需要的是像移动一样移动背景
import pygame, sys, random
#---Classes----------------------------------------#
class PlatformRect(pygame.sprite.Sprite):
    def __init__(self,x_pos,y_pos,size_x,size_y,path,players):
        super().__init__()
        self.x_pos = x_pos
        self.y_pos = y_pos
        self.size_x = size_x
        self.size_y = size_y
        self.players = players
        self.can_jump1 = None

        if path == "null":
            self.image = pygame.Surface((self.size_x,self.size_y))
            self.rect = self.image.get_rect(topleft = (self.x_pos,self.y_pos))
        else:
            self.image = pygame.transform.scale(pygame.image.load(path).convert_alpha(),(size_x,size_y))
            self.rect = self.image.get_rect(topleft = (self.x_pos,self.y_pos))

    def collision_check(self):
        if pygame.sprite.spritecollide(self,self.players,False): 
            collision_paddle = pygame.sprite.spritecollide(self,self.players,False)[0].rect
            if player.movement_y > 0 and abs(self.rect.top - collision_paddle.bottom) < 10: #load of checks to ensure the correct side is being collided 
                collision_paddle.bottom = self.rect.top 
                player.movement_y = 0
                self.can_jump1 = True
            elif player.movement_y < 0 and abs(self.rect.bottom - collision_paddle.top) < 10 and not abs(self.rect.right - collision_paddle.left) < 10 and not abs(self.rect.left - collision_paddle.right) < 10:
                collision_paddle.top = self.rect.bottom
                player.movement_y *= -0.2
                print("moving bottom")
            elif player.movement_x < 0 and abs(self.rect.right - collision_paddle.left) < 10 and not abs(self.rect.bottom - collision_paddle.top) < 10:
                collision_paddle.left = self.rect.right
                print("moving left")
            elif player.movement_x > 0 and abs(self.rect.left - collision_paddle.right) < 10 and not abs(self.rect.bottom - collision_paddle.top) < 10:
                collision_paddle.right = self.rect.left
                print("moving right")
        else:
            self.can_jump1 = self.rect.top == self.players.sprites()[0].rect.bottom  

    def can_jump_check(self):
        return self.can_jump1

    def update(self):
        self.collision_check()
        self.rect.centerx -= player.movement_x #trying to get rects to move the same distance as the player, if player moves 2 pixels right, rect moves 2 pixels left?
        self.rect.centery -= 0


class Player(pygame.sprite.Sprite):
    def __init__(self,x_pos,y_pos,size_x,size_y,speed_x,acceleration_y): 
        super().__init__()
        self.x_pos = x_pos
        self.y_pos = y_pos
        self.size_x = size_x
        self.size_y = size_y
        self.speed_x = speed_x
        self.shift_pressed = False
        self.acceleration_y = acceleration_y
        self.movement_x = 0 
        self.movement_y = 0
        
        self.image = pygame.Surface((self.size_x,self.size_y))
        self.image.fill("red")
        self.rect = self.image.get_rect(center = (self.x_pos,self.y_pos))

    def screen_constrain(self): 
        if self.rect.bottom >= sresy:
            self.rect.bottom = sresy

    def update(self):
        if abs(self.movement_y) <= 8: 
            self.movement_y += GRAVITY
        self.rect.centery += self.movement_y
        if self.shift_pressed == False:
            self.rect.centerx += self.movement_x #if set to 0, scrolling kindof works, although camera still scrolls even if player is stuck on block
        elif self.shift_pressed == True: 
            self.rect.centerx += 2*self.movement_x
        self.screen_constrain()

class GameManager:
    def __init__(self,player_group,platform_group):
        self.player_group = player_group
        self.platform_group = platform_group
        self.can_jump = True

    def run_game(self):
        #---drawing---#
        self.player_group.draw(screen)
        self.platform_group.draw(screen)

        #---updating---#
        self.player_group.update()
        self.platform_group.update()

    def game_checking(self):
        #---checking---#
        self.can_jump = any(p.can_jump_check() for p in self.platform_group)  
        return self.can_jump
        
#---Setup------------------------------------------#
#---constants-----#
global GRAVITY
GRAVITY = 0.25

#---Gamevariables-----#
can_jump = True
shift_pressed = False
music_playing = False

#---colour---#
bg_colour = (50,50,50)
white_colour = (255,255,255)
black_colour = (0,0,0)

#---res---#
resx = 900 
resy = 700
resx_moved = resx - 50
resy_moved = resy - 50
sresx = 850 #base surface size, to be scaled up to resx_moved and resy_moved
sresy = 650

#---game map---# 
game_map = [[0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0],
            [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1],
            [0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1],
            [0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1],
            [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
            [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
            [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
            [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
            [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]]

#---start window-----#
pygame.init()
clock = pygame.time.Clock()

screendisplay = pygame.display.set_mode((resx,resy))
screendisplay.fill(bg_colour)
pygame.display.set_caption("PlatformerGame") 

screen = pygame.Surface((sresx,sresy))
screen.fill(white_colour)

#---startgame-----#
player = Player(425,325,50,50,2,30)
player_group = pygame.sprite.GroupSingle() 
player_group.add(player) 

platform_list = []
y_gm = 0
for row in game_map:
    x_gm = 0
    for tile in row:
        if tile == 1:
            platform_list.append(PlatformRect(x_gm * 50, y_gm * 50, 50, 50, "null",player_group)) #sets platform at given positions and size
        x_gm += 1
    y_gm += 1
platform_group = pygame.sprite.Group() 
platform_group.add(platform_list) 

game_manager = GameManager(player_group,platform_group)

#---Loop--------------------------------------------#
while True:
    #---events-----#
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE: #emergency
                pygame.quit()
                sys.exit()

            if event.key == pygame.K_SPACE: 
                if can_jump == True:
                    player.movement_y = 0
                    player.movement_y -= player.acceleration_y * GRAVITY 

            if event.key == pygame.K_LSHIFT: #sprinting
                player.shift_pressed = True

            if event.key == pygame.K_a: 
                player.movement_x -= player.speed_x

            if event.key == pygame.K_d: 
                player.movement_x += player.speed_x

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_SPACE: 
                if player.movement_y < 0: 
                    player.movement_y = 0

            if event.key == pygame.K_a: 
                player.movement_x += player.speed_x

            if event.key == pygame.K_d: 
                player.movement_x -= player.speed_x

            if event.key == pygame.K_LSHIFT: 
                player.shift_pressed = False

    #---background---#
    surf = pygame.transform.scale(screen,(resx_moved,resy_moved)) #changes resolution
    screendisplay.blit(surf,(25,25))
    screen.fill(white_colour) 

    #---running---#
    game_manager.run_game()
    if not game_manager.game_checking() == True and player.rect.bottom < sresy: #checking if can_jump is true
        can_jump = False
    else:
        can_jump = True

    #---updating-----#
    pygame.display.update()
    clock.tick(120)