- 臧启航 的博客
Python2D我的世界
- @ 2025-4-20 22:44:06
警告:有严重卡顿,电脑配置不好的别玩,小心别把电脑搞坏了
目前有很多BUG,BUG后续将会一一修复,并完善游戏
import pygame
import random
# 初始化 Pygame
pygame.init()
# 定义常量
WIDTH, HEIGHT = 800, 600
TILE_SIZE = 20
PLAYER_SIZE = TILE_SIZE
GRAVITY = 0.5
JUMP_POWER = 10
PLAYER_SPEED = 5
WORLD_WIDTH = 10000
MONSTER_SPEED = 2
MONSTER_DETECT_RANGE = 200
GHAST_SPEED = 1
GHAST_FIREBALL_SPEED = 3
ENDER_DRAGON_SPEED = 3
ENDER_DRAGON_DETECT_RANGE = 300
VILLAGER_SPEED = 1
ENDERMEN_SPEED = 2
INVENTORY_ROWS = 3
INVENTORY_COLS = 10
HOTBAR_SIZE = 9
HOTBAR_Y = HEIGHT - TILE_SIZE - 10
STACK_SIZE = 64
# 创建游戏窗口
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("2D Minecraft")
# 定义颜色
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRASS_COLOR = (0, 128, 0)
DIRT_COLOR = (139, 69, 19)
STONE_COLOR = (128, 128, 128)
SAND_COLOR = (244, 164, 96)
MONSTER_COLOR = (255, 0, 0)
OBSIDIAN_COLOR = (50, 50, 50)
PORTAL_COLOR = (128, 0, 128)
END_STONE_COLOR = (144, 144, 144)
END_PORTAL_COLOR = (0, 255, 255)
GHAST_COLOR = (255, 255, 200)
FIREBALL_COLOR = (255, 165, 0)
ENDER_DRAGON_COLOR = (128, 0, 0)
NETHER_BRICK_COLOR = (128, 0, 0)
OBSIDIAN_PILLAR_COLOR = (64, 0, 64)
VILLAGE_WOOD_COLOR = (139, 69, 19)
VILLAGE_ROOF_COLOR = (160, 82, 45)
TEMPLE_COLOR = (255, 215, 0)
VILLAGER_COLOR = (0, 255, 0)
ENDERMEN_COLOR = (0, 0, 255)
INVENTORY_BACKGROUND_COLOR = (50, 50, 50)
INVENTORY_SLOT_COLOR = (100, 100, 100)
SELECTED_SLOT_COLOR = (200, 200, 200)
DRAG_COLOR = (200, 200, 200, 128)
# 生物群系类型
BIOME_PLAINS = 0
BIOME_DESERT = 1
# 维度
OVERWORLD = 0
NETHER = 1
END = 2
current_dimension = OVERWORLD
# 生成随机地形
def generate_terrain():
terrain = []
biome_changes = [i for i in range(0, WORLD_WIDTH, random.randint(200, 500))]
current_biome = random.choice([BIOME_PLAINS, BIOME_DESERT])
biome_index = 0
base_height = HEIGHT // TILE_SIZE - 5
for x in range(WORLD_WIDTH):
if x in biome_changes:
current_biome = random.choice([BIOME_PLAINS, BIOME_DESERT])
biome_index += 1
if current_biome == BIOME_PLAINS:
height = base_height + random.randint(-2, 2)
surface_color = GRASS_COLOR
underground_color = DIRT_COLOR
elif current_biome == BIOME_DESERT:
height = base_height + random.randint(-1, 1)
surface_color = SAND_COLOR
underground_color = SAND_COLOR
for y in range(height, HEIGHT // TILE_SIZE):
if y == height:
terrain.append((x, y, surface_color))
elif y < height + 3:
terrain.append((x, y, underground_color))
else:
terrain.append((x, y, STONE_COLOR))
return terrain
# 初始化地形
terrain = generate_terrain()
# 初始化末地要塞
end_fortresses = []
for _ in range(3):
fortress_x = random.randint(0, WORLD_WIDTH - 10)
fortress_y = HEIGHT // TILE_SIZE - 10
end_fortresses.append([fortress_x, fortress_y])
# 初始化下界堡垒
nether_fortresses = []
for _ in range(2):
fortress_x = random.randint(0, WORLD_WIDTH - 15)
fortress_y = HEIGHT // TILE_SIZE - 15
nether_fortresses.append([fortress_x, fortress_y])
# 初始化末地黑曜石柱
obsidian_pillars = []
for _ in range(4):
pillar_x = random.randint(0, WORLD_WIDTH - 3)
pillar_y = HEIGHT // TILE_SIZE - 20
obsidian_pillars.append([pillar_x, pillar_y])
# 初始化主世界村庄
villages = []
for _ in range(2):
village_x = random.randint(0, WORLD_WIDTH - 10)
village_y = HEIGHT // TILE_SIZE - 10
villages.append([village_x, village_y])
# 初始化主世界神庙
temples = []
for _ in range(1):
temple_x = random.randint(0, WORLD_WIDTH - 8)
temple_y = HEIGHT // TILE_SIZE - 12
temples.append([temple_x, temple_y])
# 初始化玩家
player_x = WIDTH // 2 - PLAYER_SIZE // 2
player_y = 0
player_vel_y = 0
# 初始化怪物
monsters = []
for _ in range(5):
monster_x = random.randint(0, WORLD_WIDTH * TILE_SIZE - TILE_SIZE)
monster_y = 0
monster_vel_y = 0
monsters.append([monster_x, monster_y, monster_vel_y])
# 初始化恶魂
ghasts = []
ghast_fireballs = []
# 初始化末影龙
ender_dragon = None
if random.random() < 0.5:
ender_dragon_x = random.randint(0, WORLD_WIDTH * TILE_SIZE - TILE_SIZE)
ender_dragon_y = 0
ender_dragon_vel_y = 0
ender_dragon = [ender_dragon_x, ender_dragon_y, ender_dragon_vel_y]
# 初始化村民
villagers = []
for _ in range(3):
villager_x = random.randint(0, WORLD_WIDTH * TILE_SIZE - TILE_SIZE)
villager_y = 0
villager_vel_y = 0
villagers.append([villager_x, villager_y, villager_vel_y])
# 初始化末影人
endermen = []
if random.random() < 0.5:
enderman_x = random.randint(0, WORLD_WIDTH * TILE_SIZE - TILE_SIZE)
enderman_y = 0
enderman_vel_y = 0
endermen.append([enderman_x, enderman_y, enderman_vel_y])
# 初始化库存和快捷栏
inventory = [[None] * INVENTORY_COLS for _ in range(INVENTORY_ROWS)]
hotbar = [None] * HOTBAR_SIZE
selected_hotbar_slot = 0
inventory_open = False
dragging = False
dragged_item = None
dragged_quantity = 0
# 传送门相关
portal_blocks = []
portal_active = False
end_portal_blocks = []
end_portal_active = False
# 检查是否是传送门框架的一部分
def check_portal_frame(x, y):
for dx in [-1, 0, 1, 2, 3]:
for dy in [-1, 0, 1, 2, 3, 4]:
found = False
for tile in terrain:
tile_x, tile_y, color = tile
if tile_x == x + dx and tile_y == y + dy and color == OBSIDIAN_COLOR:
found = True
break
if not found:
return False
return True
# 获取传送门的方块
def get_portal_blocks(x, y):
blocks = []
for dx in range(1, 3):
for dy in range(1, 4):
blocks.append((x + dx, y + dy))
return blocks
# 检查传送门是否激活
def check_portal_activation():
# 简单示例:假设在传送门框架内放置特定方块激活
for block in portal_blocks:
block_x, block_y = block
for tile in terrain:
tile_x, tile_y, color = tile
if tile_x == block_x and tile_y == block_y and color != OBSIDIAN_COLOR:
return True
return False
# 检查是否是末地传送门框架的一部分
def check_end_portal_frame(x, y):
# 简单示例,假设末地传送门框架是 3x3
for dx in [-1, 0, 1]:
for dy in [-1, 0, 1]:
found = False
for tile in terrain:
tile_x, tile_y, color = tile
if tile_x == x + dx and tile_y == y + dy and color == END_STONE_COLOR:
found = True
break
if not found:
return False
return True
# 获取末地传送门的方块
def get_end_portal_blocks(x, y):
blocks = []
for dx in range(1):
for dy in range(1):
blocks.append((x + dx, y + dy))
return blocks
# 检查末地传送门是否激活
def check_end_portal_activation():
# 简单示例:假设在末地传送门框架内放置特定方块激活
for block in end_portal_blocks:
block_x, block_y = block
for tile in terrain:
tile_x, tile_y, color = tile
if tile_x == block_x and tile_y == block_y and color != END_STONE_COLOR:
return True
return False
# 游戏主循环
running = True
clock = pygame.time.Clock()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
on_ground = False
for tile in terrain:
tile_x, tile_y, _ = tile
tile_rect = pygame.Rect(tile_x * TILE_SIZE, tile_y * TILE_SIZE, TILE_SIZE, TILE_SIZE)
player_rect = pygame.Rect(player_x, player_y + PLAYER_SIZE, PLAYER_SIZE, 1)
if player_rect.colliderect(tile_rect):
on_ground = True
break
if on_ground:
player_vel_y = -JUMP_POWER
if event.key == pygame.K_e:
inventory_open = not inventory_open
if event.key in [pygame.K_1, pygame.K_2, pygame.K_3, pygame.K_4, pygame.K_5, pygame.K_6, pygame.K_7, pygame.K_8, pygame.K_9]:
selected_hotbar_slot = event.key - pygame.K_1
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = event.pos
if inventory_open:
inventory_x = (WIDTH - INVENTORY_COLS * TILE_SIZE) // 2
inventory_y = (HEIGHT - INVENTORY_ROWS * TILE_SIZE) // 2
for row in range(INVENTORY_ROWS):
for col in range(INVENTORY_COLS):
slot_x = inventory_x + col * TILE_SIZE
slot_y = inventory_y + row * TILE_SIZE
slot_rect = pygame.Rect(slot_x, slot_y, TILE_SIZE, TILE_SIZE)
if slot_rect.collidepoint(mouse_x, mouse_y):
if inventory[row][col] is not None:
dragging = True
dragged_item = inventory[row][col][0]
dragged_quantity = inventory[row][col][1]
inventory[row][col] = None
hotbar_x = (WIDTH - HOTBAR_SIZE * TILE_SIZE) // 2
for i in range(HOTBAR_SIZE):
slot_x = hotbar_x + i * TILE_SIZE
slot_y = HOTBAR_Y
slot_rect = pygame.Rect(slot_x, slot_y, TILE_SIZE, TILE_SIZE)
if slot_rect.collidepoint(mouse_x, mouse_y):
if hotbar[i] is not None:
dragging = True
dragged_item = hotbar[i][0]
dragged_quantity = hotbar[i][1]
hotbar[i] = None
if event.button == 1:
tile_x = (mouse_x + (player_x - WIDTH // 2 + PLAYER_SIZE // 2)) // TILE_SIZE
tile_y = mouse_y // TILE_SIZE
# 破坏方块
for tile in terrain[:]:
if tile[0] == tile_x and tile[1] == tile_y:
terrain.remove(tile)
block_color = tile[2]
# 尝试堆叠物品到库存
added = False
for row in range(INVENTORY_ROWS):
for col in range(INVENTORY_COLS):
if inventory[row][col] is not None and inventory[row][col][0] == block_color and inventory[row][col][1] < STACK_SIZE:
inventory[row][col] = (block_color, inventory[row][col][1] + 1)
added = True
break
if added:
break
if not added:
for row in range(INVENTORY_ROWS):
for col in range(INVENTORY_COLS):
if inventory[row][col] is None:
inventory[row][col] = (block_color, 1)
break
if added:
break
if (tile_x, tile_y) in portal_blocks:
portal_blocks.remove((tile_x, tile_y))
portal_active = False
if (tile_x, tile_y) in end_portal_blocks:
end_portal_blocks.remove((tile_x, tile_y))
end_portal_active = False
elif event.button == 3:
# 放置方块
if hotbar[selected_hotbar_slot] is not None:
new_tile = (tile_x, tile_y, hotbar[selected_hotbar_slot][0])
terrain.append(new_tile)
hotbar[selected_hotbar_slot] = (hotbar[selected_hotbar_slot][0], hotbar[selected_hotbar_slot][1] - 1)
if hotbar[selected_hotbar_slot][1] == 0:
hotbar[selected_hotbar_slot] = None
if check_portal_frame(tile_x, tile_y):
portal_blocks = get_portal_blocks(tile_x, tile_y)
if check_portal_activation():
portal_active = True
if current_dimension == OVERWORLD:
current_dimension = NETHER
elif current_dimension == NETHER:
current_dimension = OVERWORLD
if check_end_portal_frame(tile_x, tile_y):
end_portal_blocks = get_end_portal_blocks(tile_x, tile_y)
if check_end_portal_activation():
end_portal_active = True
if current_dimension != END:
current_dimension = END
else:
current_dimension = OVERWORLD
if event.type == pygame.MOUSEBUTTONUP:
if dragging:
mouse_x, mouse_y = event.pos
if inventory_open:
inventory_x = (WIDTH - INVENTORY_COLS * TILE_SIZE) // 2
inventory_y = (HEIGHT - INVENTORY_ROWS * TILE_SIZE) // 2
for row in range(INVENTORY_ROWS):
for col in range(INVENTORY_COLS):
slot_x = inventory_x + col * TILE_SIZE
slot_y = inventory_y + row * TILE_SIZE
slot_rect = pygame.Rect(slot_x, slot_y, TILE_SIZE, TILE_SIZE)
if slot_rect.collidepoint(mouse_x, mouse_y):
if inventory[row][col] is not None and inventory[row][col][0] == dragged_item:
new_quantity = min(STACK_SIZE, inventory[row][col][1] + dragged_quantity)
inventory[row][col] = (dragged_item, new_quantity)
dragged_quantity -= new_quantity - inventory[row][col][1]
elif inventory[row][col] is None:
inventory[row][col] = (dragged_item, dragged_quantity)
dragged_quantity = 0
hotbar_x = (WIDTH - HOTBAR_SIZE * TILE_SIZE) // 2
for i in range(HOTBAR_SIZE):
slot_x = hotbar_x + i * TILE_SIZE
slot_y = HOTBAR_Y
slot_rect = pygame.Rect(slot_x, slot_y, TILE_SIZE, TILE_SIZE)
if slot_rect.collidepoint(mouse_x, mouse_y):
if hotbar[i] is not None and hotbar[i][0] == dragged_item:
new_quantity = min(STACK_SIZE, hotbar[i][1] + dragged_quantity)
hotbar[i] = (dragged_item, new_quantity)
dragged_quantity -= new_quantity - hotbar[i][1]
elif hotbar[i] is None:
hotbar[i] = (dragged_item, dragged_quantity)
dragged_quantity = 0
if dragged_quantity > 0:
# 尝试放回原位置
for row in range(INVENTORY_ROWS):
for col in range(INVENTORY_COLS):
if inventory[row][col] is not None and inventory[row][col][0] == dragged_item:
new_quantity = min(STACK_SIZE, inventory[row][col][1] + dragged_quantity)
inventory[row][col] = (dragged_item, new_quantity)
dragged_quantity -= new_quantity - inventory[row][col][1]
for i in range(HOTBAR_SIZE):
if hotbar[i] is not None and hotbar[i][0] == dragged_item:
new_quantity = min(STACK_SIZE, hotbar[i][1] + dragged_quantity)
hotbar[i] = (dragged_item, new_quantity)
dragged_quantity -= new_quantity - hotbar[i][1]
dragging = False
dragged_item = None
dragged_quantity = 0
keys = pygame.key.get_pressed()
if keys[pygame.K_a] and player_x > PLAYER_SPEED:
player_x -= PLAYER_SPEED
if keys[pygame.K_d] and player_x < (WORLD_WIDTH * TILE_SIZE - PLAYER_SIZE - PLAYER_SPEED):
player_x += PLAYER_SPEED
# 重力模拟 - 玩家
player_vel_y += GRAVITY
player_y += player_vel_y
# 碰撞检测 - 玩家
for tile in terrain:
tile_x, tile_y, _ = tile
tile_rect = pygame.Rect(tile_x * TILE_SIZE, tile_y * TILE_SIZE, TILE_SIZE, TILE_SIZE)
player_rect = pygame.Rect(player_x, player_y, PLAYER_SIZE, PLAYER_SIZE)
if player_rect.colliderect(tile_rect):
if player_vel_y > 0:
player_y = tile_y * TILE_SIZE - PLAYER_SIZE
player_vel_y = 0
# 怪物移动
for monster in monsters:
monster_x, monster_y, monster_vel_y = monster
# 重力模拟 - 怪物
monster_vel_y += GRAVITY
monster_y += monster_vel_y
# 碰撞检测 - 怪物
for tile in terrain:
tile_x, tile_y, _ = tile
tile_rect = pygame.Rect(tile_x * TILE_SIZE, tile_y * TILE_SIZE, TILE_SIZE, TILE_SIZE)
monster_rect = pygame.Rect(monster_x, monster_y, TILE_SIZE, TILE_SIZE)
if monster_rect.colliderect(tile_rect):
if monster_vel_y > 0:
monster_y = tile_y * TILE_SIZE - TILE_SIZE
monster_vel_y = 0
# 怪物 AI
distance_to_player = abs(monster_x - player_x)
if distance_to_player < MONSTER_DETECT_RANGE:
if monster_x < player_x:
monster_x += MONSTER_SPEED
elif monster_x > player_x:
monster_x -= MONSTER_SPEED
else:
# 随机移动
random_move = random.randint(-1, 1)
monster_x += random_move * MONSTER_SPEED
monster[0] = monster_x
monster[1] = monster_y
monster[2] = monster_vel_y
# 恶魂相关
if current_dimension == NETHER:
if len(ghasts) < 3 and random.random() < 0.01:
ghast_x = random.randint(0, WORLD_WIDTH * TILE_SIZE - TILE_SIZE)
ghast_y = random.randint(0, HEIGHT - TILE_SIZE)
ghasts.append([ghast_x, ghast_y])
for ghast in ghasts:
ghast_x, ghast_y = ghast
if random.random() < 0.01:
fireball_x = ghast_x
fireball_y = ghast_y
fireball_dx = 0
if player_x > ghast_x:
fireball_dx = GHAST_FIREBALL_SPEED
elif player_x < ghast_x:
fireball_dx = -GHAST_FIREBALL_SPEED
ghast_fireballs.append([fireball_x, fireball_y, fireball_dx])
random_move_x = random.randint(-1, 1) * GHAST_SPEED
random_move_y = random.randint(-1, 1) * GHAST_SPEED
ghast[0] = ghast_x + random_move_x
ghast[1] = ghast_y + random_move_y
for fireball in ghast_fireballs[:]:
fireball_x, fireball_y, fireball_dx = fireball
fireball_x += fireball_dx
fireball[0] = fireball_x
if fireball_x < 0 or fireball_x > WORLD_WIDTH * TILE_SIZE:
ghast_fireballs.remove(fireball)
# 末影龙相关
if current_dimension == END and ender_dragon:
ender_dragon_x, ender_dragon_y, ender_dragon_vel_y = ender_dragon
distance_to_player = abs(ender_dragon_x - player_x)
if distance_to_player < ENDER_DRAGON_DETECT_RANGE:
if ender_dragon_x < player_x:
ender_dragon_x += ENDER_DRAGON_SPEED
elif ender_dragon_x > player_x:
ender_dragon_x -= ENDER_DRAGON_SPEED
ender_dragon_vel_y += GRAVITY
ender_dragon_y += ender_dragon_vel_y
for tile in terrain:
tile_x, tile_y, _ = tile
tile_rect = pygame.Rect(tile_x * TILE_SIZE, tile_y * TILE_SIZE, TILE_SIZE, TILE_SIZE)
dragon_rect = pygame.Rect(ender_dragon_x, ender_dragon_y, TILE_SIZE * 2, TILE_SIZE * 2)
if dragon_rect.colliderect(tile_rect):
if ender_dragon_vel_y > 0:
ender_dragon_y = tile_y * TILE_SIZE - TILE_SIZE * 2
ender_dragon_vel_y = 0
ender_dragon[0] = ender_dragon_x
ender_dragon[1] = ender_dragon_y
ender_dragon[2] = ender_dragon_vel_y
# 村民移动
for villager in villagers:
villager_x, villager_y, villager_vel_y = villager
# 重力模拟 - 村民
villager_vel_y += GRAVITY
villager_y += villager_vel_y
# 碰撞检测 - 村民
for tile in terrain:
tile_x, tile_y, _ = tile
tile_rect = pygame.Rect(tile_x * TILE_SIZE, tile_y * TILE_SIZE, TILE_SIZE, TILE_SIZE)
villager_rect = pygame.Rect(villager_x, villager_y, TILE_SIZE, TILE_SIZE)
if villager_rect.colliderect(tile_rect):
if villager_vel_y > 0:
villager_y = tile_y * TILE_SIZE - TILE_SIZE
villager_vel_y = 0
# 村民随机移动
random_move = random.randint(-1, 1)
villager_x += random_move * VILLAGER_SPEED
villager[0] = villager_x
villager[1] = villager_y
villager[2] = villager_vel_y
# 末影人移动
for enderman in endermen:
enderman_x, enderman_y, enderman_vel_y = enderman
# 重力模拟 - 末影人
enderman_vel_y += GRAVITY
enderman_y += enderman_vel_y
# 碰撞检测 - 末影人
for tile in terrain:
tile_x, tile_y, _ = tile
tile_rect = pygame.Rect(tile_x * TILE_SIZE, tile_y * TILE_SIZE, TILE_SIZE, TILE_SIZE)
enderman_rect = pygame.Rect(enderman_x, enderman_y, TILE_SIZE, TILE_SIZE)
if enderman_rect.colliderect(tile_rect):
if enderman_vel_y > 0:
enderman_y = tile_y * TILE_SIZE - TILE_SIZE
enderman_vel_y = 0
# 末影人 AI
distance_to_player = abs(enderman_x - player_x)
if distance_to_player < ENDER_DRAGON_DETECT_RANGE:
if enderman_x < player_x:
enderman_x += ENDERMEN_SPEED
elif enderman_x > player_x:
enderman_x -= ENDERMEN_SPEED
enderman[0] = enderman_x
enderman[1] = enderman_y
enderman[2] = enderman_vel_y
# 确保玩家在视角正中间
camera_x = player_x - WIDTH // 2 + PLAYER_SIZE // 2
# 绘制背景
screen.fill(WHITE)
# 绘制地形
for tile in terrain:
tile_x, tile_y, color = tile
tile_rect = pygame.Rect((tile_x * TILE_SIZE - camera_x, tile_y * TILE_SIZE), (TILE_SIZE, TILE_SIZE))
if 0 <= tile_rect.x < WIDTH and 0 <= tile_rect.y < HEIGHT:
pygame.draw.rect(screen, color, tile_rect)
# 绘制末地要塞
for fortress in end_fortresses:
fortress_x, fortress_y = fortress
for dx in range(10):
for dy in range(10):
fortress_rect = pygame.Rect((fortress_x + dx) * TILE_SIZE - camera_x, (fortress_y + dy) * TILE_SIZE, TILE_SIZE, TILE_SIZE)
if 0 <= fortress_rect.x < WIDTH and 0 <= fortress_rect.y < HEIGHT:
pygame.draw.rect(screen, END_STONE_COLOR, fortress_rect)
# 绘制下界堡垒
for fortress in nether_fortresses:
fortress_x, fortress_y = fortress
for dx in range(15):
for dy in range(15):
fortress_rect = pygame.Rect((fortress_x + dx) * TILE_SIZE - camera_x, (fortress_y + dy) * TILE_SIZE, TILE_SIZE, TILE_SIZE)
if 0 <= fortress_rect.x < WIDTH and 0 <= fortress_rect.y < HEIGHT:
pygame.draw.rect(screen, NETHER_BRICK_COLOR, fortress_rect)
# 绘制末地黑曜石柱
for pillar in obsidian_pillars:
pillar_x, pillar_y = pillar
for dx in range(3):
for dy in range(20):
pillar_rect = pygame.Rect((pillar_x + dx) * TILE_SIZE - camera_x, (pillar_y + dy) * TILE_SIZE, TILE_SIZE, TILE_SIZE)
if 0 <= pillar_rect.x < WIDTH and 0 <= pillar_rect.y < HEIGHT:
pygame.draw.rect(screen, OBSIDIAN_PILLAR_COLOR, pillar_rect)
# 绘制主世界村庄
for village in villages:
village_x, village_y = village
# 绘制房屋主体
for dx in range(8):
for dy in range(5):
village_rect = pygame.Rect((village_x + dx) * TILE_SIZE - camera_x, (village_y + dy) * TILE_SIZE, TILE_SIZE, TILE_SIZE)
if 0 <= village_rect.x < WIDTH and 0 <= village_rect.y < HEIGHT:
pygame.draw.rect(screen, VILLAGE_WOOD_COLOR, village_rect)
# 绘制屋顶
for dx in range(10):
for dy in range(3):
if dy <= dx and dy <= 9 - dx:
roof_rect = pygame.Rect((village_x + dx - 1) * TILE_SIZE - camera_x, (village_y - dy - 1) * TILE_SIZE, TILE_SIZE, TILE_SIZE)
if 0 <= roof_rect.x < WIDTH and 0 <= roof_rect.y < HEIGHT:
pygame.draw.rect(screen, VILLAGE_ROOF_COLOR, roof_rect)
# 绘制主世界神庙
for temple in temples:
temple_x, temple_y = temple
for dx in range(8):
for dy in range(12):
temple_rect = pygame.Rect((temple_x + dx) * TILE_SIZE - camera_x, (temple_y + dy) * TILE_SIZE, TILE_SIZE, TILE_SIZE)
if 0 <= temple_rect.x < WIDTH and 0 <= temple_rect.y < HEIGHT:
pygame.draw.rect(screen, TEMPLE_COLOR, temple_rect)
# 绘制玩家
player_rect = pygame.Rect((player_x - camera_x, player_y), (PLAYER_SIZE, PLAYER_SIZE))
pygame.draw.rect(screen, BLACK, player_rect)
# 绘制怪物
for monster in monsters:
monster_x, monster_y, _ = monster
monster_rect = pygame.Rect((monster_x - camera_x, monster_y), (TILE_SIZE, TILE_SIZE))
if 0 <= monster_rect.x < WIDTH and 0 <= monster_rect.y < HEIGHT:
pygame.draw.rect(screen, MONSTER_COLOR, monster_rect)
# 绘制恶魂
for ghast in ghasts:
ghast_x, ghast_y = ghast
ghast_rect = pygame.Rect((ghast_x - camera_x, ghast_y), (TILE_SIZE, TILE_SIZE))
if 0 <= ghast_rect.x < WIDTH and 0 <= ghast_rect.y < HEIGHT:
pygame.draw.rect(screen, GHAST_COLOR, ghast_rect)
# 绘制恶魂火球
for fireball in ghast_fireballs:
fireball_x, fireball_y, _ = fireball
fireball_rect = pygame.Rect((fireball_x - camera_x, fireball_y), (TILE_SIZE // 2, TILE_SIZE // 2))
if 0 <= fireball_rect.x < WIDTH and 0 <= fireball_rect.y < HEIGHT:
pygame.draw.rect(screen, FIREBALL_COLOR, fireball_rect)
# 绘制末影龙
if ender_dragon and current_dimension == END:
ender_dragon_x, ender_dragon_y, _ = ender_dragon
ender_dragon_rect = pygame.Rect((ender_dragon_x - camera_x, ender_dragon_y), (TILE_SIZE * 2, TILE_SIZE * 2))
if 0 <= ender_dragon_rect.x < WIDTH and 0 <= ender_dragon_rect.y < HEIGHT:
pygame.draw.rect(screen, ENDER_DRAGON_COLOR, ender_dragon_rect)
# 绘制村民
for villager in villagers:
villager_x, villager_y, _ = villager
villager_rect = pygame.Rect((villager_x - camera_x, villager_y), (TILE_SIZE, TILE_SIZE))
if 0 <= villager_rect.x < WIDTH and 0 <= villager_rect.y < HEIGHT:
pygame.draw.rect(screen, VILLAGER_COLOR, villager_rect)
# 绘制末影人
for enderman in endermen:
enderman_x, enderman_y, _ = enderman
enderman_rect = pygame.Rect((enderman_x - camera_x, enderman_y), (TILE_SIZE, TILE_SIZE))
if 0 <= enderman_rect.x < WIDTH and 0 <= enderman_rect.y < HEIGHT:
pygame.draw.rect(screen, ENDERMEN_COLOR, enderman_rect)
# 绘制快捷栏
for i in range(HOTBAR_SIZE):
slot_x = (WIDTH - HOTBAR_SIZE * TILE_SIZE) // 2 + i * TILE_SIZE
slot_y = HOTBAR_Y
slot_rect = pygame.Rect(slot_x, slot_y, TILE_SIZE, TILE_SIZE)
if i == selected_hotbar_slot:
pygame.draw.rect(screen, SELECTED_SLOT_COLOR, slot_rect)
else:
pygame.draw.rect(screen, INVENTORY_SLOT_COLOR, slot_rect)
if hotbar[i] is not None:
item_rect = pygame.Rect(slot_x + 2, slot_y + 2, TILE_SIZE - 4, TILE_SIZE - 4)
pygame.draw.rect(screen, hotbar[i][0], item_rect)
font = pygame.font.Font(None, 20)
text = font.render(str(hotbar[i][1]), True, WHITE)
screen.blit(text, (slot_x + TILE_SIZE - text.get_width() - 2, slot_y + TILE_SIZE - text.get_height() - 2))
# 绘制库存
if inventory_open:
inventory_x = (WIDTH - INVENTORY_COLS * TILE_SIZE) // 2
inventory_y = (HEIGHT - INVENTORY_ROWS * TILE_SIZE) // 2
inventory_bg_rect = pygame.Rect(inventory_x - 10, inventory_y - 10, INVENTORY_COLS * TILE_SIZE + 20, INVENTORY_ROWS * TILE_SIZE + 20)
pygame.draw.rect(screen, INVENTORY_BACKGROUND_COLOR, inventory_bg_rect)
for row in range(INVENTORY_ROWS):
for col in range(INVENTORY_COLS):
slot_x = inventory_x + col * TILE_SIZE
slot_y = inventory_y + row * TILE_SIZE
slot_rect = pygame.Rect(slot_x, slot_y, TILE_SIZE, TILE_SIZE)
pygame.draw.rect(screen, INVENTORY_SLOT_COLOR, slot_rect)
if inventory[row][col] is not None:
item_rect = pygame.Rect(slot_x + 2, slot_y + 2, TILE_SIZE - 4, TILE_SIZE - 4)
pygame.draw.rect(screen, inventory[row][col][0], item_rect)
font = pygame.font.Font(None, 20)
text = font.render(str(inventory[row][col][1]), True, WHITE)
screen.blit(text, (slot_x + TILE_SIZE - text.get_width() - 2, slot_y + TILE_SIZE - text.get_height() - 2))
# 绘制拖动物品
if dragging:
mouse_x, mouse_y = pygame.mouse.get_pos()
drag_rect = pygame.Rect(mouse_x - TILE_SIZE // 2, mouse_y - TILE_SIZE // 2, TILE_SIZE, TILE_SIZE)
s = pygame.Surface((TILE_SIZE, TILE_SIZE))
s.set_alpha(128)
s.fill(DRAG_COLOR)
screen.blit(s, (mouse_x - TILE_SIZE // 2, mouse_y - TILE_SIZE // 2))
item_rect = pygame.Rect(mouse_x - TILE_SIZE // 2 + 2, mouse_y - TILE_SIZE // 2 + 2, TILE_SIZE - 4, TILE_SIZE - 4)
pygame.draw.rect(screen, dragged_item, item_rect)
font = pygame.font.Font(None, 20)
text = font.render(str(dragged_quantity), True, WHITE)
screen.blit(text, (mouse_x - text.get_width() // 2, mouse_y - text.get_height() // 2))
# 绘制传送门
if portal_active:
for block in portal_blocks:
block_x, block_y = block
portal_rect = pygame.Rect((block_x * TILE_SIZE - camera_x, block_y * TILE_SIZE), (TILE_SIZE, TILE_SIZE))
pygame.draw.rect(screen, PORTAL_COLOR, portal_rect)
if end_portal_active:
for block in end_portal_blocks:
block_x, block_y = block
end_portal_rect = pygame.Rect((block_x * TILE_SIZE - camera_x, block_y * TILE_SIZE), (TILE_SIZE, TILE_SIZE))
pygame.draw.rect(screen, END_PORTAL_COLOR, end_portal_rect)
# 更新显示
pygame.display.flip()
# 控制帧率
clock.tick(60)
# 退出 Pygame
pygame.quit()