.\Zelda-with-Python\Code\Debug.py
# 导入pygame和os模块
import pygame
import os
# 设置当前工作目录为项目所在的目录,用于导入文件(特别是图片)
os.chdir(os.path.dirname(os.path.abspath(__file__)))
# 初始化pygame
pygame.init()
# 创建字体对象,用于在屏幕上显示调试信息
font = pygame.font.Font(None, 30)
# 定义一个函数用于在屏幕上显示调试信息
def debug(info, y = 10, x = 10):
# 获取当前显示的表面
display_surface = pygame.display.get_surface()
# 创建一个包含调试信息的表面
debug_surf = font.render(str(info), True, "White")
# 获取调试信息表面的矩形
debug_rect = debug_surf.get_rect(topleft = (x, y))
# 在屏幕上绘制一个黑色矩形
pygame.draw.rect(display_surface, "Black", debug_rect)
# 在屏幕上显示调试信息
display_surface.blit(debug_surf, debug_rect)
.\Zelda-with-Python\Code\Enemy.py
# 导入 pygame 模块
import pygame
# 从 Settings 模块中导入所有内容
from Settings import *
# 从 Entity 模块中导入 Entity 类
from Entity import Entity
# 从 Support 模块中导入所有内容
from Support import *
# 导入 os 模块
import os
# 将当前工作目录更改为 Main.py 文件所在的目录
os.chdir(os.path.dirname(os.path.abspath(__file__)))
.\Zelda-with-Python\Code\Entity.py
# 从 cmath 模块中导入 rect 函数
from cmath import rect
# 导入 pygame 模块
import pygame
# 从 math 模块中导入 sin 函数
from math import sin
# 导入 os 模块
import os
# 这是用于文件(特别是图片)导入的代码(这行代码将目录更改为项目保存的位置)
os.chdir(os.path.dirname(os.path.abspath(__file__)))
# 创建实体类,继承自 pygame.sprite.Sprite 类
class Entity(pygame.sprite.Sprite):
# 初始化方法
def __init__(self, groups):
# 调用父类的初始化方法
super().__init__(groups)
# 设置帧索引初始值为 0
self.frame_index = 0
# 设置动画速度为 0.15
self.animation_speed = 0.15
# 创建一个方向向量
self.direction = pygame.math.Vector2()
# 移动方法
def move(self, speed):
# 如果方向向量的大小不为 0,则将其归一化
if self.direction.magnitude() != 0:
self.direction = self.direction.normalize()
# 根据方向向量的值移动碰撞框
self.hitbox.x += self.direction.x * speed
self.collision("Horizontal")
self.hitbox.y += self.direction.y * speed
self.collision("Vertical")
self.rect.center = self.hitbox.center
# 碰撞检测方法
def collision(self, direction):
# 如果是水平方向的碰撞检测
if direction == "Horizontal":
# 遍历障碍物精灵组中的精灵
for sprite in self.obstacle_sprites:
# 如果碰撞框发生碰撞
if sprite.hitbox.colliderect(self.hitbox):
# 根据移动方向调整碰撞框的位置
if self.direction.x > 0: # 向右移动
self.hitbox.right = sprite.hitbox.left
if self.direction.x < 0: # 向左移动
self.hitbox.left = sprite.hitbox.right
# 如果是垂直方向的碰撞检测
if direction == "Vertical":
# 遍历障碍物精灵组中的精灵
for sprite in self.obstacle_sprites:
# 如果碰撞框发生碰撞
if sprite.hitbox.colliderect(self.hitbox):
# 根据移动方向调整碰撞框的位置
if self.direction.y > 0: # 向下移动
self.hitbox.bottom = sprite.hitbox.top
if self.direction.y < 0: # 向上移动
self.hitbox.top = sprite.hitbox.bottom
# 返回正弦波值的方法
def wave_value(self):
# 获取当前时间的正弦值
value = sin(pygame.time.get_ticks())
# 如果值大于等于 0,则返回 255,否则返回 0
if value >= 0:
return 255
else:
return 0
.\Zelda-with-Python\Code\Level.py
# 导入pygame模块
import pygame
# 从Settings模块中导入所有内容
from Settings import *
# 从Tile模块中导入Tile类
from Tile import Tile
# 从Player模块中导入Player类
from Player import Player
# 从Debug模块中导入debug函数
from Debug import debug
# 从Support模块中导入所有内容
from Support import *
# 从random模块中导入choice和randint函数
from random import choice, randint
# 从Weapon模块中导入Weapon类
from Weapon import Weapon
# 从UI模块中导入UI类
from UI import UI
# 从Enemy模块中导入Enemy类
from Enemy import Enemy
# 从Particles模块中导入AnimationPlayer类
from Particles import AnimationPlayer
# 从Magic模块中导入MagicPlayer类
from Magic import MagicPlayer
# 从Upgrade模块中导入Upgrade类
from Upgrade import Upgrade
# 导入os模块
import os
# 用于文件(特别是图片)导入的代码(这行代码将目录更改为项目保存的位置)
os.chdir(os.path.dirname(os.path.abspath(__file__)))
# 创建YSortCameraGroup类,继承自pygame.sprite.Group类
class YSortCameraGroup(pygame.sprite.Group):
def __init__(self):
# 通用设置
super().__init__()
self.display_surface = pygame.display.get_surface()
self.half_width = self.display_surface.get_size()[0] // 2
self.half_height = self.display_surface.get_size()[1] // 2
self.offset = pygame.math.Vector2()
# 创建地板
self.floor_surf = pygame.image.load("../Graphics/Tilemap/Ground.png").convert()
self.floor_rect = self.floor_surf.get_rect(topleft = (0, 0))
# 自定义绘制方法
def custom_draw(self, player):
# 获取偏移量
self.offset.x = player.rect.centerx - self.half_width
self.offset.y = player.rect.centery - self.half_height
# 绘制地板
floor_offset_pos = self.floor_rect.topleft - self.offset
self.display_surface.blit(self.floor_surf, floor_offset_pos)
# 对精灵进行排序绘制
for sprite in sorted(self.sprites(), key = lambda sprite: sprite.rect.centery):
offset_pos = sprite.rect.topleft - self.offset
self.display_surface.blit(sprite.image, offset_pos)
# 更新敌人位置
def enemy_update(self, player):
enemy_sprites = [sprite for sprite in self.sprites() if hasattr(sprite, "sprite_type") and sprite.sprite_type == "enemy"]
for enemy in enemy_sprites:
enemy.enemy_update(player)
.\Zelda-with-Python\Code\Magic.py
# 导入pygame模块
import pygame
# 从Settings模块中导入所有内容
from Settings import *
# 从random模块中导入randint函数
from random import randint
# 导入os模块
import os
# 这是用于文件(特别是图像)导入的(这一行将目录更改为项目保存的位置)
os.chdir(os.path.dirname(os.path.abspath(__file__)))
# 创建魔法玩家类
class MagicPlayer:
def __init__(self, animation_player):
# 初始化动画播放器
self.animation_player = animation_player
# 初始化声音字典
self.sounds = {
"heal": pygame.mixer.Sound("../Audio/Heal.wav"),
"flame": pygame.mixer.Sound("../Audio/Fire.wav")
}
# 治愈方法
def heal(self, player, strength, cost, groups):
# 如果玩家能量大于等于治愈消耗
if player.energy >= cost:
# 播放治愈声音
self.sounds["heal"].play()
# 增加玩家生命值
player.health += strength
# 减少玩家能量
player.energy -= cost
# 如果玩家生命值大于等于最大生命值
if player.health >= player.stats["health"]:
player.health = player.stats["health"]
# 创建光环粒子效果
self.animation_player.create_particles("aura", player.rect.center, groups)
# 创建治愈粒子效果
self.animation_player.create_particles("heal", player.rect.center + pygame.math.Vector2(0, -60), groups)
# 火焰方法
def flame(self, player, cost, groups):
# 如果玩家能量大于等于火焰消耗
if player.energy >= cost:
# 减少玩家能量
player.energy -= cost
# 播放火焰声音
self.sounds["flame"].play()
# 根据玩家状态确定火焰方向
if player.status.split("_")[0] == "right": direction = pygame.math.Vector2(1, 0)
elif player.status.split("_")[0] == "left": direction = pygame.math.Vector2(-1, 0)
elif player.status.split("_")[0] == "up": direction = pygame.math.Vector2(0, -1)
else: direction = pygame.math.Vector2(0, 1)
# 创建火焰粒子效果
for i in range(1, 6):
if direction.x: # 水平
offset_x = (direction.x * i) * TILESIZE
x = player.rect.centerx + offset_x + randint(-TILESIZE // 3, TILESIZE // 3)
y = player.rect.centery + randint(-TILESIZE // 3, TILESIZE // 3)
self.animation_player.create_particles("flame", (x, y), groups)
else: # 垂直
offset_y = (direction.y * i) * TILESIZE
x = player.rect.centerx + randint(-TILESIZE // 3, TILESIZE // 3)
y = player.rect.centery + offset_y + randint(-TILESIZE // 3, TILESIZE // 3)
self.animation_player.create_particles("flame", (x, y), groups)
.\Zelda-with-Python\Code\Main.py
# 导入pygame和sys模块
import pygame, sys
# 从Settings模块中导入所有内容
from Settings import *
# 从Level模块中导入Level类
from Level import Level
# 导入os模块
import os
# 更改工作目录到项目所在的目录
os.chdir(os.path.dirname(os.path.abspath(__file__))
# 创建游戏屏幕并调用一些类
class Game:
def __init__(self):
# 初始化pygame
pygame.init()
# 创建屏幕并设置宽度和高度
self.screen = pygame.display.set_mode((WIDTH, HEIGTH))
# 设置窗口标题
pygame.display.set_caption("Zelda with Python")
# 加载游戏图标
pygame_icon = pygame.image.load("../Graphics/Test/Player.png")
pygame.display.set_icon(pygame_icon)
# 创建时钟对象
self.clock = pygame.time.Clock()
# 创建Level对象
self.level = Level()
# 加载音乐
main_sound = pygame.mixer.Sound("../Audio/Main.ogg")
main_sound.set_volume(0.5)
main_sound.play(loops = -1)
# 游戏运行循环
def run(self):
while True:
# 处理事件
for event in pygame.event.get():
# 如果事件类型为退出,则退出游戏
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# 如果按下键盘上的m键,则切换菜单状态
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_m:
self.level.toggle_menu()
# 填充屏幕颜色
self.screen.fill(WATER_COLOR)
# 运行关卡
self.level.run()
# 更新屏幕
pygame.display.update()
# 控制帧率
self.clock.tick(FPS)
# 如果该文件被直接运行,则创建Game对象并运行游戏
if __name__ == "__main__":
game = Game()
game.run()
.\Zelda-with-Python\Code\Particles.py
# 导入pygame模块
import pygame
# 从Support模块中导入import_folder函数
from Support import import_folder
# 从random模块中导入choice函数
from random import choice
# 导入os模块
import os
# 改变当前工作目录到脚本所在目录
os.chdir(os.path.dirname(os.path.abspath(__file__)))
# 定义动画播放器类
class AnimationPlayer:
def __init__(self):
# 定义frames属性,包含不同动画类型的帧
self.frames = {
# Magic
"flame": import_folder("../Graphics/Particles/Flame/Frames"),
"aura": import_folder("../Graphics/Particles/Aura"),
"heal": import_folder("../Graphics/Particles/Heal/Frames"),
# Attacks
"claw": import_folder("../Graphics/Particles/Claw"),
"slash": import_folder("../Graphics/Particles/Slash"),
"sparkle": import_folder("../Graphics/Particles/Sparkle"),
"leaf_attack": import_folder("../Graphics/Particles/leaf_attack"),
"thunder": import_folder("../Graphics/Particles/Thunder"),
# Monster Deaths
"squid": import_folder("../Graphics/Particles/smoke_orange"),
"raccoon": import_folder("../Graphics/Particles/Raccoon"),
"spirit": import_folder("../Graphics/Particles/Nova"),
"bamboo": import_folder("../Graphics/Particles/Bamboo"),
# Leafs
"leaf":(
import_folder("../Graphics/Particles/Leaf1"),
import_folder("../Graphics/Particles/Leaf2"),
import_folder("../Graphics/Particles/Leaf3"),
import_folder("../Graphics/Particles/Leaf4"),
import_folder("../Graphics/Particles/Leaf5"),
import_folder("../Graphics/Particles/Leaf6"),
self.reflect_images(import_folder("../Graphics/Particles/Leaf1")),
self.reflect_images(import_folder("../Graphics/Particles/Leaf2")),
self.reflect_images(import_folder("../Graphics/Particles/Leaf3")),
self.reflect_images(import_folder("../Graphics/Particles/Leaf4")),
self.reflect_images(import_folder("../Graphics/Particles/Leaf5")),
self.reflect_images(import_folder("../Graphics/Particles/Leaf6"))
)
}
# 反转图像
def reflect_images(self, frames):
new_frames = []
for frame in frames:
flipped_frame = pygame.transform.flip(frame, True, False)
new_frames.append(flipped_frame)
return new_frames
# 创建草粒子效果
def create_grass_particles(self, pos, groups):
animation_frames = choice(self.frames["leaf"])
ParticleEffect(pos, animation_frames, groups)
# 创建粒子效果
def create_particles(self, animation_type, pos, groups):
animation_frames = self.frames[animation_type]
ParticleEffect(pos, animation_frames, groups)
# 粒子效果类
class ParticleEffect(pygame.sprite.Sprite):
def __init__(self, pos, animation_frames, groups):
super().__init__(groups)
self.sprite_type = "magic"
self.frame_index = 0
self.animation_speed = 0.15
self.frames = animation_frames
self.image = self.frames[self.frame_index]
self.rect = self.image.get_rect(center = pos)
# 动画
def animate(self):
self.frame_index += self.animation_speed
if self.frame_index >= len(self.frames):
self.kill()
else:
self.image = self.frames[int(self.frame_index)]
# 更新
def update(self):
self.animate()
.\Zelda-with-Python\Code\Player.py
# 导入 pygame 模块
import pygame
# 从 Support 模块中导入 import_folder 函数
from Support import import_folder
# 从 Settings 模块中导入所有内容
from Settings import *
# 从 Entity 模块中导入 Entity 类
from Entity import Entity
# 导入 os 和 sys 模块
import os, sys
# 将当前工作目录更改为 Main.py 文件所在的目录
# 这是为了在 Main.py 中进行文件导入时的路径设置
os.chdir(os.path.dirname(os.path.abspath(__file__)))
.\Zelda-with-Python\Code\Settings.py
# 导入 os 模块
import os
# 更改当前工作目录为当前文件所在目录
os.chdir(os.path.dirname(os.path.abspath(__file__)))
# 游戏设置
WIDTH = 1280 # 游戏窗口宽度
HEIGTH = 720 # 游戏窗口高度
FPS = 60 # 游戏帧率
TILESIZE = 64 # 地图瓦片大小
HITBOX_OFFSET = { # 不同对象的碰撞框偏移量
"player": -26,
"object": -40,
"grass": -10,
"invisible": 0
}
# 用户界面设置
BAR_HEIGHT = 20 # 柱状图高度
HEALTH_BAR_WIDTH = 200 # 生命值柱状图宽度
ENERGY_BAR_WIDTH = 140 # 能量值柱状图宽度
ITEM_BOX_SIZE = 80 # 物品框大小
UI_FONT = "../Graphics/Font/Joystix.ttf" # 用户界面字体
UI_FONT_SIZE = 18 # 用户界面字体大小
# 通用颜色
WATER_COLOR = "#71ddee" # 水的颜色
UI_BG_COLOR = "#222222" # 用户界面背景颜色
UI_BORDER_COLOR = "#111111" # 用户界面边框颜色
TEXT_COLOR = "#EEEEEE" # 文本颜色
# 用户界面颜色
HEALTH_COLOR = "Red" # 生命值颜色
ENERGY_COLOR = "Blue" # 能量值颜色
UI_BORDER_COLOR_ACTIVE = "Gold" # 用户界面激活时的边框颜色
# 升级菜单
TEXT_COLOR_SELECTED = "#111111" # 选中文本颜色
BAR_COLOR = "#EEEEEE" # 柱状图颜色
BAR_COLOR_SELECTED = "#111111" # 选中柱状图颜色
UPGRADE_BG_COLOR_SELECTED = "#EEEEEE" # 选中升级菜单背景颜色
# 武器
weapon_data = {
"sword": {"cooldown": 100, "damage": 15, "graphic": "../Graphics/Weapons/Sword/Full.png"}, # 剑的冷却时间、伤害和图像路径
"lance": {"cooldown": 400, "damage": 30, "graphic": "../Graphics/Weapons/Lance/Full.png"}, # 枪的冷却时间、伤害和图像路径
"axe": {"cooldown": 300, "damage": 20, "graphic": "../Graphics/Weapons/Axe/Full.png"}, # 斧头的冷却时间、伤害和图像路径
"rapier": {"cooldown": 50, "damage": 8, "graphic": "../Graphics/Weapons/Rapier/Full.png"}, # 细剑的冷却时间、伤害和图像路径
"sai": {"cooldown": 80, "damage": 10, "graphic": "../Graphics/Weapons/Sai/Full.png"} # 菜刀的冷却时间、伤害和图像路径
}
# 魔法
magic_data = {
"flame": {"strength": 5, "cost": 20, "graphic": "../Graphics/Particles/Flame/Fire.png"}, # 火焰的强度、消耗和图像路径
"heal": {"strength": 20, "cost": 10, "graphic": "../Graphics/Particles/Heal/Heal.png"} # 治疗的强度、消耗和图像路径
}
# 敌人
monster_data = {
"squid": {"health": 100, "exp": 180, "damage": 20, "attack_type": "slash", "attack_sound": "../Audio/Attack/Slash.wav", "speed": 3, "resistance": 3, "attack_radius": 80, "notice_radius": 360}, # 鱿鱼的生命值、经验值、伤害等信息
"raccoon": {"health": 300, "exp": 300, "damage": 40, "attack_type": "claw", "attack_sound": "../Audio/Attack/Claw.wav", "speed": 2, "resistance": 3, "attack_radius": 120, "notice_radius": 400}, # 浣熊的生命值、经验值、伤害等信息
"spirit": {"health": 100, "exp": 200, "damage": 8, "attack_type": "thunder", "attack_sound": "../Audio/Attack/Fireball.wav", "speed": 4, "resistance": 3, "attack_radius": 60, "notice_radius": 350}, # 精灵的生命值、经验值、伤害等信息
"bamboo": {"health": 70, "exp": 150, "damage": 6, "attack_type": "leaf_attack", "attack_sound": "../Audio/Attack/Slash.wav", "speed": 3, "resistance": 3, "attack_radius": 50, "notice_radius": 300} # 竹子的生命值、经验值、伤害等信息
}
.\Zelda-with-Python\Code\Support.py
# 从csv模块中导入reader函数
from csv import reader
# 导入os模块
import os
# 从os模块中导入walk函数
from os import walk
# 导入pygame模块
# 用于将CSV文件导入Python以及其他相关操作
# 这是用于文件(特别是图片)导入的代码(这行将目录更改为项目保存的位置)
os.chdir(os.path.dirname(os.path.abspath(__file__)))
def import_csv_layout(path):
# 创建一个空的地形地图列表
terrain_map = []
# 打开指定路径的文件
with open(path) as level_map:
# 使用CSV reader函数读取文件,以逗号为分隔符
layout = reader(level_map, delimiter = ",")
# 遍历CSV文件的每一行
for row in layout:
# 将每一行转换为列表,并添加到地形地图列表中
terrain_map.append(list(row))
# 返回地形地图列表
return terrain_map
def import_folder(path):
# 创建一个空的表面列表
surface_list = []
# 遍历指定路径下的所有文件和子目录
for _, __, img_files in walk(path):
# 遍历每个图片文件
for image in img_files:
# 拼接完整的文件路径
full_path = path + "/" + image
# 加载图片并转换为alpha通道
image_surf = pygame.image.load(full_path).convert_alpha()
# 将图片表面添加到表面列表中
surface_list.append(image_surf)
# 返回表面列表
return surface_list
.\Zelda-with-Python\Code\Tile.py
# 导入pygame模块
import pygame
# 从Settings模块中导入所有内容
from Settings import *
# 导入os模块
import os
# 将当前工作目录更改为Main.py所在的目录
os.chdir(os.path.dirname(os.path.abspath(__file__)))
# 创建Tile类,继承自pygame.sprite.Sprite类
class Tile(pygame.sprite.Sprite):
# 初始化方法,接受位置、组、精灵类型和表面作为参数
def __init__(self, pos, groups, sprite_type, surface = pygame.Surface((TILESIZE, TILESIZE))):
# 调用父类的初始化方法
super().__init__(groups)
# 设置精灵类型
self.sprite_type = sprite_type
# 根据精灵类型获取y轴偏移量
y_offset = HITBOX_OFFSET[sprite_type]
# 设置精灵的图像
self.image = surface
# 根据精灵类型设置精灵的矩形位置
if sprite_type == "object":
self.rect = self.image.get_rect(topleft = (pos[0], pos[1] - TILESIZE))
else:
self.rect = self.image.get_rect(topleft = pos)
# 设置精灵的碰撞框
self.hitbox = self.rect.inflate(0, y_offset)
.\Zelda-with-Python\Code\UI.py
# 导入pygame模块
import pygame
# 从Settings模块中导入所有内容
from Settings import *
# 导入os模块
import os
# 改变当前工作目录到项目所在的目录
os.chdir(os.path.dirname(os.path.abspath(__file__)))
# 创建UI类
class UI:
def __init__(self):
# General
# 获取显示表面
self.display_surface = pygame.display.get_surface()
# 创建字体对象
self.font = pygame.font.Font(UI_FONT, UI_FONT_SIZE)
# Bar Setup
# 创建血条矩形对象
self.health_bar_rect = pygame.Rect(10, 10, HEALTH_BAR_WIDTH, BAR_HEIGHT)
# 创建能量条矩形对象
self.energy_bar_rect = pygame.Rect(10, 34, ENERGY_BAR_WIDTH, BAR_HEIGHT)
# Convert Weapon Dictionary
# 将武器字典中的图像转换为pygame图像对象
self.weapon_graphics = []
for weapon in weapon_data.values():
path = weapon["graphic"]
weapon = pygame.image.load(path).convert_alpha()
self.weapon_graphics.append(weapon)
# Convert Magic Dictionary
# 将魔法字典中的图像转换为pygame图像对象
self.magic_graphics = []
for magic in magic_data.values():
magic = pygame.image.load(magic["graphic"]).convert_alpha()
self.magic_graphics.append(magic)
# 显示条形图
def show_bar(self, current, max_amount, bg_rect, color):
# 绘制背景
pygame.draw.rect(self.display_surface, UI_BG_COLOR, bg_rect)
# 将状态转换为像素
ratio = current / max_amount
current_width = bg_rect.width * ratio
current_rect = bg_rect.copy()
current_rect.width = current_width
# 绘制条形图
pygame.draw.rect(self.display_surface, color, current_rect)
pygame.draw.rect(self.display_surface, UI_BORDER_COLOR, bg_rect, 3)
# 显示经验值
def show_exp(self, exp):
text_surf = self.font.render(str(int(exp)), False, TEXT_COLOR)
x = self.display_surface.get_size()[0] - 20
y = self.display_surface.get_size()[1] - 20
text_rect = text_surf.get_rect(bottomright = (x, y))
pygame.draw.rect(self.display_surface, UI_BG_COLOR, text_rect.inflate(20, 20))
self.display_surface.blit(text_surf, text_rect)
pygame.draw.rect(self.display_surface, UI_BORDER_COLOR, text_rect.inflate(20, 20), 3)
# 选择框
def selection_box(self, left, top, has_switched):
bg_rect = pygame.Rect(left, top, ITEM_BOX_SIZE, ITEM_BOX_SIZE)
pygame.draw.rect(self.display_surface, UI_BG_COLOR, bg_rect)
if has_switched:
pygame.draw.rect(self.display_surface, UI_BORDER_COLOR_ACTIVE, bg_rect, 3)
else:
pygame.draw.rect(self.display_surface, UI_BORDER_COLOR, bg_rect, 3)
return bg_rect
# 武器叠加
def weapon_overlay(self, weapon_index, has_switched):
bg_rect = self.selection_box(10, 630, has_switched) # 武器框
weapon_surf = self.weapon_graphics[weapon_index]
weapon_rect = weapon_surf.get_rect(center = bg_rect.center)
self.display_surface.blit(weapon_surf, weapon_rect)
# 魔法叠加
def magic_overlay(self, magic_index, has_switched):
bg_rect = self.selection_box(100, 630, has_switched) # 魔法框
magic_surf = self.magic_graphics[magic_index]
magic_rect = magic_surf.get_rect(center = bg_rect.center)
self.display_surface.blit(magic_surf, magic_rect)
# 显示
def display(self, player):
self.show_bar(player.health, player.stats["health"], self.health_bar_rect, HEALTH_COLOR)
self.show_bar(player.energy, player.stats["energy"], self.energy_bar_rect, ENERGY_COLOR)
self.show_exp(player.exp)
self.weapon_overlay(player.weapon_index, not player.can_switch_weapon)
self.magic_overlay(player.magic_index, not player.can_switch_magic)
.\Zelda-with-Python\Code\Upgrade.py
# 导入必要的模块
import imp # 引入模块
from traceback import print_tb # 从模块中引入特定函数
import pygame # 导入pygame模块
from Settings import * # 从Settings模块中导入所有内容
import os # 导入os模块
# 更改工作目录到项目所在的目录
os.chdir(os.path.dirname(os.path.abspath(__file__))
# 定义Upgrade类
class Upgrade:
def __init__(self, player):
# 通用设置
self.display_surface = pygame.display.get_surface() # 获取显示表面
self.player = player # 设置玩家对象
self.attribute_nr = len(player.stats) # 获取玩家属性数量
self.attribute_names = list(player.stats.keys()) # 获取玩家属性名称列表
self.max_values = list(player.max_stats.values()) # 获取玩家最大属性值列表
self.font = pygame.font.Font(UI_FONT, UI_FONT_SIZE) # 设置字体
# 创建物品
self.height = self.display_surface.get_size()[1] * 0.8 # 设置高度
self.width = self.display_surface.get_size()[0] // 6 # 设置宽度
self.create_items() # 创建物品
# 选择系统
self.selection_index = 0 # 初始化选择索引
self.selection_time = None # 初始化选择时间
self.can_move = True # 初始化可移动状态
# 输入处理
def input(self):
keys = pygame.key.get_pressed() # 获取按键状态
if self.can_move:
if keys[pygame.K_RIGHT] and self.selection_index < self.attribute_nr - 1: # 如果按下右键且选择索引小于属性数量减1
self.selection_index += 1 # 选择索引加1
self.can_move = False # 设置为不可移动
self.selection_time = pygame.time.get_ticks() # 获取当前时间
elif keys[pygame.K_LEFT] and self.selection_index >= 1: # 如果按下左键且选择索引大于等于1
self.selection_index -= 1 # 选择索引减1
self.can_move = False # 设置为不可移动
self.selection_time = pygame.time.get_ticks() # 获取当前时间
if keys[pygame.K_SPACE]: # 如果按下空格键
self.can_move = False # 设置为不可移动
self.selection_time = pygame.time.get_ticks() # 获取当前时间
self.item_list[self.selection_index].trigger(self.player) # 触发物品效果
# 选择冷却
def selection_cooldown(self):
if not self.can_move: # 如果可以移动
current_time = pygame.time.get_ticks() # 获取当前时间
if current_time - self.selection_time >= 300: # 如果当前时间减去选择时间大于等于300
self.can_move = True # 设置为可移动
# 创建物品
def create_items(self):
self.item_list = [] # 初始化物品列表
for item, index in enumerate(range(self.attribute_nr)): # 遍历属性数量
# 水平位置
full_width = self.display_surface.get_size()[0] # 获取显示表面宽度
increment = full_width // self.attribute_nr # 计算增量
left = (item * increment) + (increment - self.width) // 2 # 计算左边距
# 垂直位置
top = self.display_surface.get_size()[1] * 0.1 # 计算顶部距离
# 创建对象
item = Item(left, top, self.width, self.height, index, self.font) # 创建物品对象
self.item_list.append(item) # 将物品对象添加到列表中
# 显示
def display(self):
self.input() # 处理输入
self.selection_cooldown() # 处理选择冷却
for index, item in enumerate(self.item_list): # 遍历物品列表
# 获取属性
name = self.attribute_names[index] # 获取属性名称
value = self.player.get_value_by_index(index) # 获取属性值
max_value = self.max_values[index] # 获取最大属性值
cost = self.player.get_cost_by_index(index) # 获取花费
item.display(self.display_surface, self.selection_index, name, value, max_value, cost) # 显示物品
# 物品类
class Item:
def __init__(self, l, t, w, h, index, font):
self.rect = pygame.Rect(l, t, w, h) # 设置矩形
self.index = index # 设置索引
self.font = font # 设置字体
# 显示名称
def display_names(self, surface, name, cost, selected):
color = TEXT_COLOR_SELECTED if selected else TEXT_COLOR # 根据选择状态设置颜色
# 标题
title_surf = self.font.render(name, False, color) # 渲染标题
title_rect = title_surf.get_rect(midtop=self.rect.midtop + pygame.math.Vector2(0, 20)) # 设置标题位置
# 花费
cost_surf = self.font.render(f"{int(cost)}", False, color) # 渲染花费
cost_rect = cost_surf.get_rect(midbottom=self.rect.midbottom - pygame.math.Vector2(0, 20)) # 设置花费位置
# 绘制
surface.blit(title_surf, title_rect) # 绘制标题
surface.blit(cost_surf, cost_rect) # 绘制花费
# 显示进度条
def display_bar(self, surface, value, max_value, selected):
# 绘制设置
top = self.rect.midtop + pygame.math.Vector2(0, 60) # 设置顶部位置
bottom = self.rect.midbottom - pygame.math.Vector2(0, 60) # 设置底部位置
color = BAR_COLOR_SELECTED if selected else BAR_COLOR # 根据选择状态设置颜色
# 进度条设置
full_height = bottom[1] - top[1] # 计算总高度
relative_number = (value / max_value) * full_height # 计算相对数值
value_rect = pygame.Rect(top[0] - 15, bottom[1] - relative_number, 30, 10) # 设置数值矩形
# 绘制元素
pygame.draw.line(surface, color, top, bottom, 5) # 绘制线条
pygame.draw.rect(surface, color, value_rect) # 绘制矩形
# 触发效果
def trigger(self, player):
upgrade_attribute = list(player.stats.keys())[self.index] # 获取升级属性
if player.exp >= player.upgrade_cost[upgrade_attribute] and player.stats[upgrade_attribute] < player.max_stats[upgrade_attribute]: # 如果玩家经验大于等于升级花费且属性小于最大属性
player.exp -= player.upgrade_cost[upgrade_attribute] # 减去升级花费
player.stats[upgrade_attribute] *= 1.2 # 属性增加20%
player.upgrade_cost[upgrade_attribute] *= 1.4 # 升级花费增加40%
if player.stats[upgrade_attribute] > player.max_stats[upgrade_attribute]: # 如果属性大于最大属性
player.stats[upgrade_attribute] = player.max_stats[upgrade_attribute] # 将属性设置为最大属性
# 显示
def display(self, surface, selection_num, name, value, max_value, cost):
if self.index == selection_num: # 如果索引等于选择索引
pygame.draw.rect(surface, UPGRADE_BG_COLOR_SELECTED, self.rect) # 绘制选中背景
pygame.draw.rect(surface, UI_BORDER_COLOR, self.rect, 4) # 绘制边框
else:
pygame.draw.rect(surface, UI_BG_COLOR, self.rect) # 绘制背景
pygame.draw.rect(surface, UI_BORDER_COLOR, self.rect, 4) # 绘制边框
self.display_names(surface, name, cost, self.index == selection_num) # 显示名称
self.display_bar(surface, value, max_value, self.index == selection_num) # 显示进度条
.\Zelda-with-Python\Code\Weapon.py
# 导入必要的模块
import os
import pygame
# 这是用于导入文件(特别是图片)的部分(这一行将目录更改为项目保存的位置)
os.chdir(os.path.dirname(os.path.abspath(__file__)))
# 创建武器类,继承自 pygame.sprite.Sprite 类
class Weapon(pygame.sprite.Sprite):
def __init__(self, player, groups):
super().__init__(groups)
self.sprite_type = "weapon"
# 获取玩家的状态(方向)
direction = player.status.split("_")[0]
# 图形
full_path = f"../Graphics/Weapons/{player.weapon}/{direction}.png"
# 加载武器图片并转换为透明度格式
self.image = pygame.image.load(full_path).convert_alpha()
# 放置
if direction == "right":
# 如果方向向右,则将武器放置在玩家矩形的右侧中间位置
self.rect = self.image.get_rect(midleft = player.rect.midright + pygame.math.Vector2(0, 16))
elif direction == "left":
# 如果方向向左,则将武器放置在玩家矩形的左侧中间位置
self.rect = self.image.get_rect(midright = player.rect.midleft + pygame.math.Vector2(0, 16))
elif direction == "down":
# 如果方向向下,则将武器放置在玩家矩形的底部中间位置
self.rect = self.image.get_rect(midtop = player.rect.midbottom + pygame.math.Vector2(-10, 0))
else:
# 如果方向向上,则将武器放置在玩家矩形的顶部中间位置
self.rect = self.image.get_rect(midbottom = player.rect.midtop + pygame.math.Vector2(-10, 0))
标签:os,self,player,源码,pygame,import,解析,PyZelda,rect
From: https://www.cnblogs.com/apachecn/p/18015785