This repository has been archived on 2025-02-14. You can view files and clone it, but cannot push or open issues or pull requests.
LXCsGame/module/player.py

102 lines
3.8 KiB
Python

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, block_y_idx = self.get_pixel_idx()
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
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):
self.move(0, 0)
# 重力检测
block_x_idx, block_y_idx = self.get_pixel_idx()
bottom_block = self.world[block_x_idx][block_y_idx + 1] if block_y_idx < HEIGHT // 20 - 1 else None
if bottom_block and bottom_block.collision and bottom_block.check_collision(self):
self.on_ground = True
else:
self.on_ground = False
pygame.draw.circle(screen, COLORS["player"], (self.x, self.y), PLAYER_SIZE // 2)
if OPTIONS['debug']:
block_x = block_x_idx * BLOCK_SIZE
block_y = block_y_idx * BLOCK_SIZE
# 绘制玩家所在区块颜色
rect = pygame.Rect(block_x, block_y, BLOCK_SIZE, BLOCK_SIZE)
pygame.draw.rect(screen, '#ffd5004d', rect)
def get_pixel_idx(self) -> tuple[int, int]:
return int(self.x) // BLOCK_SIZE, int(self.y) // BLOCK_SIZE