Pygame相机偏移致玩家矩形错位 求解决方案
相机偏移导致玩家矩形定位错误问题
问题描述
相机偏移设置后,玩家角色的红色基础矩形无法正确显示在角色上方,仅黄色旋转矩形位置正常。将偏移值设为0时,两个矩形都能正确贴合角色,但相机跟随功能失效。需要实现两个矩形都准确覆盖角色的效果。
可复现代码
from sys import exit import math import pygame pygame.init() # 窗口设置 WIDTH = 1280 HEIGHT = 720 FPS = 60 screen = pygame.display.set_mode((WIDTH,HEIGHT)) pygame.display.set_caption('Zombie Game') clock = pygame.time.Clock() # 加载资源 background = pygame.image.load('background/gamemap4.png').convert() class Player(pygame.sprite.Sprite): def __init__(self, pos): super().__init__() self.image = pygame.image.load('handgun/move/survivor-move_handgun_0.png').convert_alpha() self.image = pygame.transform.rotozoom(self.image, 0, 0.35) self.base_player_image = self.image self.pos = pos self.base_player_rect = self.base_player_image.get_rect(center = pos) self.rect = self.base_player_rect.copy() self.player_speed = 10 self.shoot = False def player_turning(self): self.mouse_coords = pygame.mouse.get_pos() self.x_change_mouse_player = (self.mouse_coords[0] - (WIDTH // 2)) self.y_change_mouse_player = (self.mouse_coords[1] - (HEIGHT // 2)) self.angle = int(math.degrees(math.atan2(self.y_change_mouse_player, self.x_change_mouse_player))) self.angle = (self.angle + 360) % 360 self.image = pygame.transform.rotate(self.base_player_image, -self.angle) self.rect = self.image.get_rect(center=self.base_player_rect.center) def player_input(self, shoot_key_up): self.velocity_x = 0 self.velocity_y = 0 keys = pygame.key.get_pressed() if keys[pygame.K_w]: self.velocity_y = -self.player_speed if keys[pygame.K_s]: self.velocity_y = self.player_speed if keys[pygame.K_d]: self.velocity_x = self.player_speed if keys[pygame.K_a]: self.velocity_x = -self.player_speed if self.velocity_x != 0 and self.velocity_y != 0: # 斜向移动时减速 self.velocity_x /= math.sqrt(2) self.velocity_y /= math.sqrt(2) self.shoot = keys[pygame.K_SPACE] if shoot_key_up: self.shoot = False def move(self): self.base_player_rect.centerx += self.velocity_x self.base_player_rect.centery += self.velocity_y def update(self, camera_offset, shoot_key_up): # 应用相机偏移后绘制矩形 base_rect_screen = self.base_player_rect.move(-camera_offset.x, -camera_offset.y) pygame.draw.rect(screen, 'red', base_rect_screen, width=2) rect_screen = self.rect.move(-camera_offset.x, -camera_offset.y) pygame.draw.rect(screen, 'yellow', rect_screen, width=2) self.player_turning() self.player_input(shoot_key_up) self.move() class Camera(pygame.sprite.Group): def __init__(self): super().__init__() self.offset = pygame.math.Vector2() self.floor_rect = background.get_rect(topleft = (0,0)) def custom_draw(self): # 计算相机偏移,以玩家基础位置为中心 self.offset.x = player.base_player_rect.centerx - (WIDTH // 2) self.offset.y = player.base_player_rect.centery - (HEIGHT // 2) # 绘制背景 floor_offset_pos = self.floor_rect.topleft - self.offset screen.blit(background, floor_offset_pos) for sprite in all_sprites_group: offset_pos = sprite.rect.topleft - self.offset screen.blit(sprite.image, offset_pos) # 精灵组 all_sprites_group = pygame.sprite.Group() obstacles_group = pygame.sprite.Group() player = Player((900,900)) all_sprites_group.add(player) camera = Camera() while True: shoot_key_up = False for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit() if event.type == pygame.KEYUP: if event.key == pygame.K_SPACE: shoot_key_up = True camera.custom_draw() all_sprites_group.update(camera.offset, shoot_key_up) pygame.display.update() clock.tick(FPS)
解决方案
问题根源
base_player_rect存储的是角色在世界空间的坐标,当前直接绘制它时未应用相机偏移,导致红色矩形停留在世界坐标位置,而角色图像已通过相机转换到屏幕空间,因此出现错位。
修复步骤
- 恢复相机偏移计算:在Camera类的
custom_draw方法中,基于玩家的base_player_rect计算偏移,确保相机以角色基础位置为中心。 - 矩形绘制时应用偏移:在Player的
update方法中,将世界空间的矩形坐标通过move(-camera_offset.x, -camera_offset.y)转换为屏幕空间坐标后再绘制。 - 修复输入事件问题:将SPACE键的KEYUP事件移到主循环处理,避免Player类直接访问主循环的event变量导致报错。
替代方案(统一绘制逻辑到Camera类)
如果希望统一管理绘制逻辑,可把矩形绘制移到Camera的custom_draw中:
def custom_draw(self): self.offset.x = player.base_player_rect.centerx - (WIDTH // 2) self.offset.y = player.base_player_rect.centery - (HEIGHT // 2) # 绘制背景 floor_offset_pos = self.floor_rect.topleft - self.offset screen.blit(background, floor_offset_pos) for sprite in all_sprites_group: offset_pos = sprite.rect.topleft - self.offset screen.blit(sprite.image, offset_pos) # 绘制红色基础矩形 base_rect_screen = sprite.base_player_rect.move(-self.offset.x, -self.offset.y) pygame.draw.rect(screen, 'red', base_rect_screen, width=2) # 绘制黄色旋转矩形 rect_screen = sprite.rect.move(-self.offset.x, -self.offset.y) pygame.draw.rect(screen, 'yellow', rect_screen, width=2)
同时注释掉Player类update方法中的绘制代码。
内容的提问来源于stack exchange,提问作者juba1029
相关产品推荐
相关产品推荐

