from typing import Type, Literal import pygame from module import WIDTH, HEIGHT, JUMP_FORCE, COLORS, PLAYER_SIZE, OPTIONS, BLOCK_SIZE from module.block import AirBlock, Block # 玩家类 class Player: def __init__(self, world: list[list[Block]]): self.x = 100 self.y = 100 self.velocity = 0 self.on_ground = False self.selected_block = AirBlock self.world = world def move(self, dx: float, dy: float): # 仅需检测玩家当前区块的上下左右的方块是否有碰撞体积 block_x_idx = int(self.x) // BLOCK_SIZE block_y_idx = int(self.y) // BLOCK_SIZE top_block = self.world[block_x_idx][block_y_idx - 1] if block_y_idx > 0 else None bottom_block = self.world[block_x_idx][block_y_idx + 1] if block_y_idx < HEIGHT // 20 - 1 else None left_block = self.world[block_x_idx - 1][block_y_idx] if block_x_idx > 0 else None right_block = self.world[block_x_idx + 1][block_y_idx] if block_x_idx < WIDTH // 20 - 1 else None # 无碰撞体积时加 dx dy 有碰撞体积时,限制其值 # 向下移动时且下面方块有碰撞体积,与上表面碰撞 if dy > 0 and bottom_block is not None and bottom_block.collision: if bottom_block.check_collision(self): new_y = bottom_block.get_collision_surface()[0] - 10 self.on_ground = True else: new_y = self.y + dy # 向上移动时且上面方块有碰撞体积,与下表面碰撞 elif dy < 0 and top_block is not None and top_block.collision: if top_block.check_collision(self): new_y = top_block.get_collision_surface()[2] + 10 else: new_y = self.y + dy else: new_y = self.y + dy # 右移动 if dx > 0 and right_block is not None and right_block.collision: if right_block.check_collision(self): new_x = right_block.get_collision_surface()[3] - 10 else: new_x = self.x + dx # 左移动 elif dx < 0 and left_block is not None and left_block.collision: if left_block.check_collision(self): new_x = left_block.get_collision_surface()[1] + 10 else: new_x = self.x + dx else: new_x = self.x + dx if 0 <= new_x < WIDTH and 0 <= new_y < HEIGHT: self.x = new_x self.y = new_y def jump(self): if self.on_ground: self.y += JUMP_FORCE self.on_ground = False def select_block(self, block: Type[Block]): self.selected_block = block def put_block(self, x: int, y: int, action: Literal['create', 'delete'] = 'create'): if action == 'create': self.world[x][y] = self.selected_block(x, y) elif action == 'delete': self.world[x][y] = AirBlock(x, y) else: pass def draw(self, screen: pygame.Surface): pygame.draw.circle(screen, COLORS["player"], (self.x, self.y), PLAYER_SIZE // 2) self.move(0, 0) # 绘制玩家所在区块颜色 if OPTIONS['debug']: block_x = int(self.x) // BLOCK_SIZE * BLOCK_SIZE block_y = int(self.y) // BLOCK_SIZE * BLOCK_SIZE rect = pygame.Rect(block_x, block_y, BLOCK_SIZE, BLOCK_SIZE) pygame.draw.rect(screen, '#ffd5004d', rect)