简体   繁体   English

pygame - 为什么玩家的移动速度比相机快?

[英]pygame - Why player move faster than camera?

I am learning pygame.我正在学习pygame。 I wanted to make the camera follows the player so that the player is in the middle of the screen all the time.我想让相机跟随玩家,让玩家一直在屏幕中间。 Even though I move the camera about the same vector, the player moves much faster and runs off the screen.即使我将相机移动到相同的向量,玩家移动得更快并跑出屏幕。 Thanks in advance for any attempts to help.在此先感谢您提供帮助的任何尝试。 I am posting the whole code, but the problem probably lies in one of the functions: player.move(), level.move_camera() or level.render().我发布了整个代码,但问题可能在于其中一个函数:player.move()、level.move_camera() 或 level.render()。

import pygame
from pygame.math import Vector2


#####SETTINGS#####
HEIGHT = 1080
WIDTH = 1920
TICKRATE = 60
BLOCK_SIZE = 60
GRAVITY = 18
##################


class Level():
   def __init__(self, file):
       self.file = file
       self.blocks = [] # list of tills
       self.map = self.load_from_file()
       self.camera_position = Vector2(WIDTH / 2, 0)

   # loading map
   def load_from_file(self):
       map = []
       file = open(self.file + '.txt', 'r')
       data = file.read()
       file.close()
       data = data.split('\n')
       for x in data:
           map.append(list(x))
       return map

   def move_camera(self, player):
       self.camera_position.x += player.shift.x
   
   def render(self, screen):
       self.blocks = []
       y = 0
       for row in self.map:
           x = 0
           for block in row:
               if block != '0':
                   self.blocks.append(pygame.Rect(x * BLOCK_SIZE - self.camera_position.x, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))
                   if block == '1':
                       pygame.draw.rect(screen, (56,24,0), (x * BLOCK_SIZE - self.camera_position.x, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))
                   elif block == '2':
                       pygame.draw.rect(screen, (18,115,81), (x * BLOCK_SIZE - self.camera_position.x, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))
               x += 1
           y += 1


class Player():
   def __init__(self, x, y, color):
       self.position = Vector2(x, y)
       self.shift = Vector2(0, 0)
       self.jump = Vector2(0, 0)
       self.color = color
       self.rect = pygame.Rect(x, y, BLOCK_SIZE, BLOCK_SIZE)
       self.go_left = False
       self.go_right = False
       self.go_up = False
       self.collisions = {'left' : False, 'right' : False, 'top' : False, 'bottom' : False}

   # moving the player object
   def move(self, level):
       self.shift = Vector2(0, GRAVITY)
       self.position.y = int(self.position.y)

       # left / right section
       if self.go_left:
           self.go_left = False
           self.collisions = test_collisions(pygame.Rect(self.position.x - 1, self.position.y, BLOCK_SIZE, BLOCK_SIZE), level.blocks)
           if not self.collisions['left']:
               self.shift += Vector2(-10, 0)
       if self.go_right:
           self.go_right = False
           self.collisions = test_collisions(pygame.Rect(self.position.x + 1, self.position.y, BLOCK_SIZE, BLOCK_SIZE), level.blocks)
           if not self.collisions['right']:
               self.shift += Vector2(10, 0)

       # gravity section
       self.collisions = test_collisions(pygame.Rect(self.position.x, self.position.y + GRAVITY, BLOCK_SIZE, BLOCK_SIZE), level.blocks)
       if self.collisions['bottom']: 
           self.shift -= Vector2(0, GRAVITY)
           if self.position.y % BLOCK_SIZE > 0:
               self.position.y += BLOCK_SIZE - (self.position.y % BLOCK_SIZE)
           
       # jump section
       if self.go_up:
           self.go_up = False
           self.collisions = test_collisions(pygame.Rect(self.position.x, self.position.y + GRAVITY, BLOCK_SIZE, BLOCK_SIZE), level.blocks)
           if self.collisions['bottom']:
               self.jump = Vector2(0, -80)
       self.collisions = test_collisions(pygame.Rect(self.position.x, self.position.y - 1, BLOCK_SIZE, BLOCK_SIZE), level.blocks)
       if self.jump.y > GRAVITY or self.collisions['top']:
           self.jump = Vector2(0, 0)
       else: 
           self.jump *= 0.9
           self.shift += self.jump
           
       # new position
       self.position += self.shift
       self.rect = pygame.Rect(self.position.x, self.position.y, BLOCK_SIZE, BLOCK_SIZE)

   # checking if player is death
   def check_death(self):
       if self.position.y > HEIGHT:
           new_game()

   # render player
   def render(self, screen):
       pygame.draw.rect(screen, self.color, self.rect)


# render section
def render(screen, player, level):
   screen.fill((49, 113, 181))
   level.render(screen)
   player.render(screen)
   pygame.display.update()


# keyboard handling
def handle_events(player):
   for event in pygame.event.get():
       if event.type == pygame.QUIT or event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
           run = False
           pygame.quit()
   keys = pygame.key.get_pressed()
   if keys[pygame.K_a] or keys[pygame.K_LEFT]:
       player.go_left = True
   if keys[pygame.K_d] or keys[pygame.K_RIGHT]:
       player.go_right = True
   if keys[pygame.K_w] or keys[pygame.K_UP] or keys[pygame.K_SPACE]:
       player.go_up = True


# test direction of collison (rects have to overlap) 
def test_collisions(object, rects):
   collisions = {'left' : False, 'right' : False, 'top' : False, 'bottom' : False}
   for rect in rects:
       if object.colliderect(rect):
           if object.x <= rect.x:
               collisions['right'] = True
           if object.x >= rect.x:
               collisions['left'] = True
           if object.y >= rect.y:
               collisions['top'] = True
           if object.y <= rect.y:
               collisions['bottom'] = True
   return(collisions)


# game loop
def main_loop(run, screen, level, player):
   clock = pygame.time.Clock()
   while run:
       clock.tick(TICKRATE)
       handle_events(player)
       player.move(level)
       player.check_death()
       level.move_camera(player)
       render(screen, player, level)


# init new game
def new_game():
   run = True
   screen = pygame.display.set_mode((WIDTH, HEIGHT))
   level = Level('assets/level_two')
   level.camera_position = Vector2(0, 0)
   player = Player(WIDTH / 2, 0, (255,255,0))
   main_loop(run, screen, level, player)


# launch new game on start
if __name__ == "__main__":
   new_game()

You are not taking into account the players movement on itself, you only apply it to the blocks.您没有考虑玩家本身的运动,您只将其应用于块。 For it to always be in the centre, create a direction vector towards the centre from the player and add that to the player position like this:为了让它始终位于中心,创建一个从玩家朝向中心的方向向量,并将其添加到玩家位置,如下所示:

class Player():
    #...
    def move(self, level):
        #...
        #either this
        self.position.x += ((WIDTH / 2) - self.position.x)
        #or if you want a camera following with a delay effect
        delay = 5
        self.position.x += ((WIDTH / 2) - self.position.x) / delay

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

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