fix collision detection issue

This commit is contained in:
Jeffrey Hsu 2025-01-31 21:17:10 +08:00
parent 3cb2bf4b74
commit 6670715bf2
3 changed files with 60 additions and 18 deletions

20
main.py
View File

@ -1,7 +1,7 @@
import pygame import pygame
from module import WIDTH, HEIGHT, BLOCK_SIZE, PLAYER_SPEED, GRAVITY, COLORS from module import WIDTH, HEIGHT, BLOCK_SIZE, PLAYER_SPEED, GRAVITY, COLORS
from module.block import AirBlock, GrassBlock, StoneBlock, SandBlock, WaterBlock from module.block import GrassBlock, StoneBlock, SandBlock, WaterBlock
from module.player import Player from module.player import Player
from module.utils import generate_terrain from module.utils import generate_terrain
@ -11,7 +11,7 @@ screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock() clock = pygame.time.Clock()
world = generate_terrain() world = generate_terrain()
player = Player() player = Player(world)
# 游戏循环 # 游戏循环
running = True running = True
@ -28,18 +28,18 @@ while running:
block = world[bx][by] block = world[bx][by]
if event.button == 1: # 左键放置方块 if event.button == 1: # 左键放置方块
if block.id == "air": if block.id == "air":
world[bx][by] = player.selected_block(bx, by) player.put_block(bx, by)
elif event.button == 3: # 右键拆除方块 elif event.button == 3: # 右键拆除方块
world[bx][by] = AirBlock(bx, by) player.put_block(bx, by, 'delete')
elif event.type == pygame.KEYDOWN: elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_1: if event.key == pygame.K_1:
player.selected_block = GrassBlock player.select_block(GrassBlock)
elif event.key == pygame.K_2: elif event.key == pygame.K_2:
player.selected_block = StoneBlock player.select_block(StoneBlock)
elif event.key == pygame.K_3: elif event.key == pygame.K_3:
player.selected_block = SandBlock player.select_block(SandBlock)
elif event.key == pygame.K_4: elif event.key == pygame.K_4:
player.selected_block = WaterBlock player.select_block(WaterBlock)
# 玩家移动 # 玩家移动
keys = pygame.key.get_pressed() keys = pygame.key.get_pressed()
@ -67,7 +67,9 @@ while running:
screen.fill(COLORS["air"]) screen.fill(COLORS["air"])
for row in world: for row in world:
for block in row: for block in row:
if block.id != "air": if block.id == "air":
continue
rect = pygame.Rect(block.x * BLOCK_SIZE, block.y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE) rect = pygame.Rect(block.x * BLOCK_SIZE, block.y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
pygame.draw.rect(screen, block.color, rect) pygame.draw.rect(screen, block.color, rect)

View File

@ -11,6 +11,12 @@ class Block:
self.x = x self.x = x
self.y = y self.y = y
def get_screen_x(self):
return self.x * 20
def get_screen_y(self):
return self.y * 20
class GrassBlock(Block): class GrassBlock(Block):
id = 'grass' id = 'grass'

View File

@ -1,19 +1,42 @@
from typing import Type, Literal
from module import WIDTH, HEIGHT, JUMP_FORCE from module import WIDTH, HEIGHT, JUMP_FORCE
from module.block import AirBlock from module.block import AirBlock, Block
# 玩家类 # 玩家类
class Player: class Player:
def __init__(self): def __init__(self, world: list[list[Block]]):
self.x = WIDTH // 2 self.x = 100
self.y = HEIGHT // 2 self.y = 100
self.velocity = 0 self.velocity = 0
self.on_ground = False self.on_ground = False
self.selected_block = AirBlock self.selected_block = AirBlock
self.world = world
def move(self, dx, dy): def move(self, dx, dy):
world_position = {'x': int(self.x) // 20, 'y': int(self.y) // 20}
# TODONeed to judgment x and y in order not to raise Index Out Of Range Error
top_block = self.world[world_position['x']][world_position['y'] - 1]
button_block = self.world[world_position['x']][world_position['y'] + 1]
left_block = self.world[world_position['x'] - 1][world_position['y']]
right_block = self.world[world_position['x'] + 1][world_position['y']]
if dx < 0 and left_block.collision:
new_x = left_block.get_screen_x() + 30
elif dx > 0 and right_block.collision:
new_x = right_block.get_screen_x() - 10
else:
new_x = self.x + dx new_x = self.x + dx
if dy < 0 and top_block.collision:
new_y = top_block.get_screen_y() + 30
elif dy > 0 and button_block.collision:
new_y = button_block.get_screen_y() - 10
else:
new_y = self.y + dy new_y = self.y + dy
if 0 <= new_x < WIDTH and 0 <= new_y < HEIGHT: if 0 <= new_x < WIDTH and 0 <= new_y < HEIGHT:
self.x = new_x self.x = new_x
self.y = new_y self.y = new_y
@ -22,3 +45,14 @@ class Player:
if self.on_ground: if self.on_ground:
self.velocity = JUMP_FORCE self.velocity = JUMP_FORCE
self.on_ground = False 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