[Python] 纯文本查看 复制代码
import pygame
import random
import math
import sys
import os
from pygame.locals import *
folder_name = os.path.dirname(__file__)
bg_music = os.path.join(folder_name, '丛林.ogg')
# 初始化Pygame
pygame.init()
pygame.mixer.init()
pygame.mixer.music.load(bg_music)
pygame.mixer.music.play(-1)
# 游戏窗口设置
WIDTH, HEIGHT = 1000, 700
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Let's Type")
# 颜色定义
BACKGROUND = (10, 10, 30) # 深蓝色背景
STAR_COLORS = [
(255, 255, 200), # 亮黄色
(200, 220, 255), # 淡蓝色
(255, 220, 180), # 淡橙色
(220, 255, 220), # 淡绿色
]
TEXT_COLOR = (240, 240, 255) # 亮白色
CORRECT_COLOR = (100, 255, 150) # 绿色
INCORRECT_COLOR = (255, 100, 100) # 红色
INPUT_COLOR = (255, 255, 200) # 黄色
STATS_COLOR = (180, 220, 255) # 淡蓝色
PROGRESS_COLOR = (100, 200, 255) # 蓝色
HINT_COLOR = (200, 200, 255) # 淡紫色
BUTTON_COLORS = {
"normal": (60, 100, 180),
"hover": (80, 140, 220),
"pressed": (40, 80, 160)
}
# 常用300个英文单词(初中水平)及其中文释义
WORD_LIST = [
("the", "这个"), ("be", "是"), ("and", "和"), ("of", "...的"), ("a", "一个"),
("to", "到"), ("in", "在...里"), ("have", "有"), ("it", "它"),
("that", "那个"), ("for", "为了"), ("you", "你"), ("he", "他"), ("with", "和...一起"),
("on", "在...上"), ("do", "做"), ("say", "说"), ("this", "这个"), ("they", "他们"),
("at", "在"), ("but", "但是"), ("we", "我们"), ("his", "他的"), ("from", "从"),
("not", "不"), ("by", "被"), ("she", "她"), ("or", "或者"), ("as", "如同"),
("what", "什么"), ("go", "去"), ("their", "他们的"), ("can", "能"), ("who", "谁"),
("get", "得到"), ("if", "如果"), ("would", "将"), ("her", "她的"), ("all", "所有"),
("my", "我的"), ("make", "制作"), ("about", "关于"), ("know", "知道"), ("will", "将"),
("up", "向上"), ("one", "一个"), ("time", "时间"), ("there", "那里"), ("year", "年"),
("so", "所以"), ("think", "想"), ("when", "当...时"), ("which", "哪一个"), ("them", "他们"),
("some", "一些"), ("me", "我"), ("people", "人们"), ("take", "拿"), ("out", "出去"),
("into", "进入"), ("just", "刚刚"), ("see", "看见"), ("him", "他"), ("your", "你的"),
("come", "来"), ("could", "能够"), ("now", "现在"), ("than", "比"), ("like", "喜欢"),
("other", "其他"), ("how", "如何"), ("then", "然后"), ("its", "它的"), ("our", "我们的"),
("two", "两个"), ("more", "更多"), ("these", "这些"), ("want", "想要"), ("way", "方式"),
("look", "看"), ("first", "第一"), ("also", "也"), ("new", "新的"), ("because", "因为"),
("day", "天"), ("use", "使用"), ("man", "男人"), ("find", "找到"), ("water", "水"),
("been", "曾经"), ("call", "呼叫"), ("oil", "油"), ("now", "现在"), ("find", "发现"),
("long", "长的"), ("down", "向下"), ("day", "白天"), ("did", "做了"), ("get", "得到"),
("come", "来"), ("made", "制造了"), ("may", "可能"), ("part", "部分"), ("over", "超过"),
("new", "新的"), ("sound", "声音"), ("take", "拿"), ("only", "只有"), ("little", "小的"),
("work", "工作"), ("know", "知道"), ("place", "地方"), ("year", "年"), ("live", "生活"),
("me", "我"), ("back", "后面"), ("give", "给"), ("most", "大多数"), ("very", "非常"),
("after", "之后"), ("thing", "事情"), ("our", "我们的"), ("just", "只是"), ("name", "名字"),
("good", "好的"), ("sentence", "句子"), ("man", "男人"), ("think", "认为"), ("say", "说"),
("great", "伟大的"), ("where", "哪里"), ("help", "帮助"), ("through", "通过"), ("much", "很多"),
("before", "之前"), ("line", "线"), ("right", "正确"), ("too", "也"), ("mean", "意思"),
("old", "老的"), ("any", "任何"), ("same", "相同的"), ("tell", "告诉"), ("boy", "男孩"),
("follow", "跟随"), ("came", "来了"), ("want", "想要"), ("show", "展示"), ("around", "周围"),
("form", "形式"), ("three", "三"), ("small", "小的"), ("set", "设置"), ("put", "放"),
("end", "结束"), ("does", "做"), ("another", "另一个"), ("well", "好"), ("large", "大的"),
("must", "必须"), ("big", "大的"), ("even", "甚至"), ("such", "这样的"), ("turn", "转"),
("here", "这里"), ("why", "为什么"), ("ask", "问"), ("went", "去了"), ("men", "男人们"),
("read", "读"), ("need", "需要"), ("land", "土地"), ("different", "不同的"), ("home", "家"),
("us", "我们"), ("move", "移动"), ("try", "尝试"), ("kind", "种类"), ("hand", "手"),
("picture", "图片"), ("again", "再次"), ("change", "改变"), ("off", "离开"), ("play", "玩"),
("spell", "拼写"), ("air", "空气"), ("away", "离开"), ("animal", "动物"), ("house", "房子"),
("point", "点"), ("page", "页面"), ("letter", "信"), ("mother", "母亲"), ("answer", "答案"),
("found", "发现"), ("study", "学习"), ("still", "仍然"), ("learn", "学习"), ("should", "应该"),
("world", "世界"), ("high", "高的"), ("every", "每个"), ("near", "近的"),
("add", "添加"), ("food", "食物"), ("between", "之间"), ("own", "自己的"), ("below", "下面"),
("country", "国家"), ("plant", "植物"), ("last", "最后的"), ("school", "学校"), ("father", "父亲"),
("keep", "保持"), ("tree", "树"), ("never", "从不"), ("start", "开始"), ("city", "城市"),
("earth", "地球"), ("eye", "眼睛"), ("light", "光"), ("thought", "思想"), ("head", "头"),
("under", "下面"), ("story", "故事"), ("saw", "看见"), ("left", "左边"),
("few", "很少"), ("while", "当...时"), ("along", "沿着"), ("might", "可能"), ("close", "关闭"),
("something", "某事"), ("seem", "似乎"), ("next", "下一个"), ("hard", "困难的"), ("open", "打开"),
("example", "例子"), ("begin", "开始"), ("life", "生活"), ("always", "总是"), ("those", "那些"),
("both", "两者"), ("paper", "纸"), ("together", "一起"), ("got", "得到"), ("group", "组"),
("often", "经常"), ("run", "跑"), ("important", "重要的"), ("until", "直到"), ("children", "孩子们"),
("side", "边"), ("feet", "脚"), ("car", "汽车"), ("mile", "英里"), ("night", "夜晚"),
("walk", "走"), ("white", "白色"), ("sea", "海洋"), ("began", "开始"), ("grow", "生长"),
("took", "拿了"), ("river", "河流"), ("four", "四"), ("carry", "携带"), ("state", "州"),
("once", "一次"), ("book", "书"), ("hear", "听到"), ("stop", "停止"), ("without", "没有"),
("second", "第二"), ("later", "后来"), ("miss", "想念"), ("idea", "想法"), ("enough", "足够的"),
("eat", "吃"), ("face", "脸"), ("watch", "观看"), ("far", "远的"),
("really", "真的"), ("almost", "几乎"), ("let", "让"), ("above", "上面"), ("girl", "女孩"),
("sometimes", "有时"), ("mountain", "山"), ("cut", "切"), ("young", "年轻的"), ("talk", "谈话"),
("soon", "很快"), ("list", "列表"), ("song", "歌曲"), ("being", "存在"), ("leave", "离开"),
("family", "家庭"), ("body", "身体"), ("music", "音乐"), ("color", "颜色"),
("stand", "站"), ("sun", "太阳"), ("questions", "问题"), ("fish", "鱼"), ("area", "区域"),
("mark", "标记"), ("dog", "狗"), ("horse", "马"), ("birds", "鸟"), ("problem", "问题"),
("complete", "完成"), ("room", "房间"), ("knew", "知道"), ("since", "自从"), ("ever", "曾经"),
("piece", "片"), ("told", "告诉"), ("usually", "通常"), ("friends", "朋友"),
("easy", "容易的"), ("heard", "听到"), ("order", "顺序"), ("red", "红色"), ("door", "门"),
("sure", "确定"), ("become", "成为"), ("top", "顶部"), ("ship", "船"), ("across", "穿过"),
("today", "今天"), ("during", "在...期间"), ("short", "短的"), ("better", "更好的"), ("best", "最好的"),
("however", "然而"), ("low", "低的"), ("hours", "小时"), ("black", "黑色"), ("products", "产品"),
("happened", "发生"), ("whole", "整个"), ("measure", "测量"), ("remember", "记住"), ("early", "早的"),
("waves", "波浪"), ("reached", "到达"), ("listen", "听"), ("wind", "风"), ("rock", "岩石"),
("space", "空间"), ("covered", "覆盖"), ("fast", "快的"), ("several", "几个"), ("hold", "握住"),
("himself", "他自己"), ("toward", "朝向"), ("five", "五"), ("step", "步骤"), ("morning", "早晨"),
("passed", "经过"), ("vowel", "元音"), ("true", "真的"), ("hundred", "百"), ("against", "反对"),
("pattern", "模式"), ("numeral", "数字"), ("table", "桌子"), ("north", "北"), ("slowly", "慢慢地"),
("money", "钱"), ("map", "地图"), ("farm", "农场"), ("pulled", "拉"), ("draw", "画"),
("voice", "声音"), ("seen", "看见"), ("cold", "冷的"), ("cried", "哭"), ("plan", "计划"),
("notice", "注意"), ("south", "南"), ("sing", "唱"), ("war", "战争"), ("ground", "地面"),
("fall", "秋天"), ("king", "国王"), ("town", "城镇"), ("unit", "单元"),
("figure", "数字"), ("certain", "确定的"), ("field", "田野"), ("travel", "旅行"), ("wood", "木材"),
("fire", "火"), ("upon", "在...上"), ("done", "完成"), ("road", "道路"),
("half", "一半"), ("ten", "十"), ("fly", "飞"), ("gave", "给"), ("box", "盒子"),
("finally", "最后"), ("wait", "等待"), ("correct", "正确的"), ("oh", "哦"), ("quickly", "快速地"),
("person", "人"), ("became", "成为"), ("shown", "展示"), ("minutes", "分钟"), ("strong", "强壮的"),
("verb", "动词"), ("stars", "星星"), ("front", "前面"), ("feel", "感觉"), ("fact", "事实"),
("inches", "英寸"), ("street", "街道"), ("decided", "决定"), ("contain", "包含"), ("course", "课程"),
("surface", "表面"), ("produce", "生产"), ("building", "建筑"), ("ocean", "海洋"), ("class", "班级"),
("note", "笔记"), ("nothing", "没有东西"), ("rest", "休息"), ("carefully", "小心地"), ("scientists", "科学家"),
("inside", "里面"), ("wheels", "轮子"), ("stay", "停留"), ("green", "绿色"), ("known", "知道"),
("island", "岛屿"), ("week", "周"), ("less", "更少"), ("machine", "机器"), ("base", "基础"),
("ago", "以前"), ("stood", "站"), ("plane", "飞机"), ("system", "系统"), ("behind", "后面"),
("ran", "跑"), ("round", "圆的"), ("boat", "船"), ("game", "游戏"), ("force", "力量"),
("brought", "带来"), ("understand", "理解"), ("warm", "温暖的"), ("common", "常见的"), ("bring", "带来"),
("explain", "解释"), ("dry", "干的"), ("though", "虽然"), ("language", "语言"), ("shape", "形状"),
("deep", "深的"), ("thousands", "成千上万"), ("yes", "是的"), ("clear", "清楚的"), ("equation", "方程"),
("yet", "尚未"), ("government", "政府"), ("filled", "填满"), ("heat", "热"), ("full", "满的"),
("hot", "热的"), ("check", "检查"), ("object", "物体"), ("am", "是"), ("rule", "规则"),
("among", "在...中"), ("noun", "名词"), ("power", "力量"), ("cannot", "不能"), ("able", "能够"),
("six", "六"), ("size", "大小"), ("dark", "黑暗的"), ("ball", "球"), ("material", "材料"),
("special", "特殊的"), ("heavy", "重的"), ("fine", "好的"), ("pair", "一对"), ("circle", "圆圈"),
("include", "包括"), ("built", "建造"), ("matter", "物质"), ("square", "正方形"),
("syllables", "音节"), ("perhaps", "也许"), ("bill", "账单"), ("felt", "感觉"), ("suddenly", "突然"),
("test", "测试"), ("direction", "方向"), ("center", "中心"), ("farmers", "农民"), ("ready", "准备好的"),
("anything", "任何东西"), ("divided", "分开"), ("general", "一般的"), ("energy", "能量"), ("subject", "主题"),
("moon", "月亮"), ("region", "地区"), ("return", "返回"), ("believe", "相信"),
("dance", "跳舞"), ("members", "成员"), ("picked", "捡起"), ("simple", "简单的"), ("cells", "细胞"),
("paint", "油漆"), ("mind", "思想"), ("love", "爱"), ("cause", "原因"), ("rain", "雨"),
("exercise", "锻炼"), ("eggs", "蛋"), ("train", "火车"), ("blue", "蓝色"), ("wish", "希望"),
("drop", "掉落"), ("developed", "发展"), ("window", "窗口"), ("difference", "不同"), ("distance", "距离"),
("heart", "心"), ("sit", "坐"), ("sum", "总和"), ("summer", "夏天"), ("wall", "墙"),
("forest", "森林"), ("probably", "可能"), ("legs", "腿"), ("sat", "坐"), ("main", "主要的"),
("winter", "冬天"), ("wide", "宽的"), ("written", "写的"), ("length", "长度"), ("reason", "原因"),
("kept", "保持"), ("interest", "兴趣"), ("arms", "手臂"), ("brother", "兄弟"), ("race", "种族"),
("present", "现在"), ("beautiful", "美丽的"), ("store", "商店"), ("job", "工作"), ("edge", "边缘"),
("past", "过去"), ("sign", "标志"), ("record", "记录"), ("finished", "完成"), ("discovered", "发现"),
("wild", "野生的"), ("happy", "快乐的"), ("beside", "在旁边"), ("gone", "去了"), ("sky", "天空"),
("glass", "玻璃"), ("million", "百万"), ("west", "西"), ("lay", "躺"), ("weather", "天气"),
("root", "根"), ("instruments", "乐器"), ("meet", "见面"), ("third", "第三"), ("months", "月"),
("paragraph", "段落"), ("raised", "举起"), ("represent", "代表"), ("soft", "软的"), ("whether", "是否"),
("clothes", "衣服"), ("flowers", "花"), ("shall", "将"), ("teacher", "老师"), ("held", "握住"),
("describe", "描述"), ("drive", "驾驶"), ("cross", "穿过"), ("speak", "说话"), ("solve", "解决"),
("appear", "出现"), ("metal", "金属"), ("son", "儿子"), ("either", "要么"), ("ice", "冰"),
("sleep", "睡觉"), ("village", "村庄"), ("factors", "因素"), ("result", "结果"), ("jumped", "跳"),
("snow", "雪"), ("ride", "骑"), ("care", "关心"), ("floor", "地板"), ("hill", "山"),
("pushed", "推"), ("baby", "婴儿"), ("buy", "买"), ("century", "世纪"), ("outside", "外面"),
("everything", "每件事"), ("tall", "高的"), ("already", "已经"), ("instead", "代替"), ("phrase", "短语"),
("soil", "土壤"), ("bed", "床"), ("copy", "复制"), ("free", "自由的"), ("hope", "希望"),
("spring", "春天"), ("case", "案例"), ("laughed", "笑"), ("nation", "国家"), ("quite", "相当"),
("type", "类型"), ("themselves", "他们自己"), ("temperature", "温度"), ("bright", "明亮的"), ("lead", "领导"),
("everyone", "每个人"), ("method", "方法"), ("section", "部分"), ("lake", "湖"), ("consonant", "辅音"),
("within", "在...内"), ("dictionary", "字典"), ("hair", "头发"), ("age", "年龄"), ("amount", "数量"),
("scale", "规模"), ("pounds", "磅"), ("although", "虽然"), ("per", "每"), ("broken", "破碎的"),
("moment", "时刻"), ("tiny", "微小的"), ("possible", "可能的"), ("gold", "金"), ("milk", "牛奶"),
("quiet", "安静的"), ("natural", "自然的"), ("lot", "很多"), ("stone", "石头"), ("act", "行动"),
("build", "建造"), ("middle", "中间"), ("speed", "速度"), ("count", "数"), ("cat", "猫"),
("someone", "某人"), ("sail", "帆"), ("rolled", "滚动"), ("bear", "熊"), ("wonder", "想知道"),
("smiled", "微笑"), ("angle", "角度"), ("fraction", "分数"), ("Africa", "非洲"), ("killed", "杀"),
("melody", "旋律"), ("bottom", "底部"), ("trip", "旅行"), ("hole", "洞"), ("poor", "贫穷的"),
("fight", "战斗"), ("surprise", "惊讶"), ("died", "死"),
("beat", "打"), ("exactly", "确切地"), ("remain", "保持"), ("dress", "衣服"), ("iron", "铁"),
("fingers", "手指"), ("row", "行"), ("least", "最少的"), ("catch", "抓住"),
("climbed", "爬"), ("wrote", "写"), ("shouted", "喊"), ("continued", "继续"), ("itself", "它自己"),
("plains", "平原"), ("gas", "气体"), ("burning", "燃烧"), ("design", "设计"),
("joined", "加入"), ("foot", "脚"), ("law", "法律"), ("ears", "耳朵"), ("grass", "草"),
("grew", "生长"), ("skin", "皮肤"), ("valley", "山谷"), ("cents", "分"),
("key", "钥匙"), ("president", "总统"), ("brown", "棕色"), ("trouble", "麻烦"), ("cool", "酷的"),
("cloud", "云"), ("lost", "丢失"), ("sent", "发送"), ("symbols", "符号"), ("wear", "穿"),
("bad", "坏的"), ("save", "保存"), ("experiment", "实验"), ("engine", "引擎"), ("alone", "独自"),
("drawing", "绘画"), ("east", "东"), ("pay", "支付"), ("single", "单一的"), ("touch", "触摸"),
("information", "信息"), ("express", "表达"), ("mouth", "嘴"), ("yard", "院子"), ("equal", "等于"),
("decimal", "小数"), ("yourself", "你自己"), ("control", "控制"), ("practice", "练习"), ("report", "报告"),
("straight", "直的"), ("rise", "上升"), ("statement", "陈述"), ("stick", "棍子"), ("party", "派对"),
("seeds", "种子"), ("suppose", "假设"), ("woman", "女人"), ("coast", "海岸"), ("bank", "银行"),
("period", "时期"), ("wire", "电线"), ("choose", "选择"), ("clean", "干净的"), ("visit", "访问"),
("bit", "一点"), ("whose", "谁的"), ("received", "收到"), ("garden", "花园"), ("please", "请"),
("strange", "奇怪的"), ("caught", "抓住"), ("fell", "掉落"), ("team", "团队"),
("captain", "队长"), ("direct", "直接的"), ("ring", "戒指"), ("serve", "服务"), ("child", "孩子"),
("desert", "沙漠"), ("increase", "增加"), ("history", "历史"), ("cost", "成本"), ("maybe", "也许"),
("business", "商业"), ("separate", "分开"), ("break", "打破"), ("uncle", "叔叔"), ("hunting", "狩猎"),
("flow", "流动"), ("lady", "女士"), ("students", "学生们"), ("human", "人类"), ("art", "艺术"),
("feeling", "感觉"), ("supply", "供应"), ("corner", "角落"), ("electric", "电的"), ("insects", "昆虫"),
("crops", "庄稼"), ("tone", "音调"), ("hit", "打"), ("sand", "沙"), ("doctor", "医生"),
("provide", "提供"), ("thus", "因此"), ("cook", "烹饪"), ("bones", "骨头"),
("tail", "尾巴"), ("board", "板"), ("modern", "现代的"), ("compound", "化合物"), ("mine", "我的"),
("fit", "适合"), ("addition", "添加"), ("belong", "属于"), ("safe", "安全的"),
("soldiers", "士兵们"), ("guess", "猜测"), ("silent", "安静的"), ("trade", "贸易"), ("rather", "宁愿"),
("compare", "比较"), ("crowd", "人群"), ("poem", "诗歌"), ("enjoy", "享受"), ("elements", "元素"),
("indicate", "指示"), ("except", "除了"), ("expect", "期望"), ("flat", "平的"), ("seven", "七"),
("interesting", "有趣的"), ("sense", "感觉"), ("string", "弦"), ("blow", "吹"), ("famous", "著名的"),
("value", "价值")
]
# 尝试加载中文字体
def load_font(font_path, size):
try:
if os.path.exists(font_path):
return pygame.font.Font(font_path, size)
except:
pass
return None
# 常见的中文字体路径
chinese_font_paths = [
"C:/Windows/Fonts/simsun.ttc", # 宋体
"C:/Windows/Fonts/simhei.ttf", # 黑体
"C:/Windows/Fonts/msyh.ttc", # 微软雅黑
"C:/Windows/Fonts/msyhbd.ttc", # 微软雅黑粗体
"/System/Library/Fonts/PingFang.ttc", # macOS 苹方字体
"/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf", # Linux
]
# 加载字体
font_large = None
font_medium = None
font_small = None
font_tiny = None
font_word = None
font_input = None
# 尝试加载中文字体
for font_path in chinese_font_paths:
if font_large is None:
font_large = load_font(font_path, 64)
if font_medium is None:
font_medium = load_font(font_path, 48)
if font_small is None:
font_small = load_font(font_path, 36)
if font_tiny is None:
font_tiny = load_font(font_path, 24)
if font_word is None:
font_word = load_font(font_path, 72)
if font_input is None:
font_input = load_font(font_path, 56)
# 如果都加载成功了就退出循环
if all([font_large, font_medium, font_small, font_tiny, font_word, font_input]):
break
# 如果中文字体加载失败,回退到默认字体
if font_large is None:
print("警告:未找到中文字体,将使用默认字体(中文可能显示为方框)")
try:
font_large = pygame.font.Font(None, 64)
font_medium = pygame.font.Font(None, 48)
font_small = pygame.font.Font(None, 36)
font_tiny = pygame.font.Font(None, 24)
font_word = pygame.font.Font(None, 72)
font_input = pygame.font.Font(None, 56)
except:
font_large = pygame.font.SysFont(None, 64)
font_medium = pygame.font.SysFont(None, 48)
font_small = pygame.font.SysFont(None, 36)
font_tiny = pygame.font.SysFont(None, 24)
font_word = pygame.font.SysFont(None, 72)
font_input = pygame.font.SysFont(None, 56)
# 星星类
class Star:
def __init__(self):
self.x = random.randint(0, WIDTH)
self.y = random.randint(0, HEIGHT)
self.size = random.uniform(1.0, 3.0)
self.color = random.choice(STAR_COLORS)
self.speed = random.uniform(0.1, 0.5)
self.twinkle_speed = random.uniform(0.01, 0.05)
self.twinkle = random.random() * math.pi * 2
self.original_brightness = random.uniform(0.6, 1.0)
self.current_color = self.color
def update(self):
# 星星闪烁效果
self.twinkle += self.twinkle_speed
brightness = self.original_brightness + 0.2 * math.sin(self.twinkle)
# 确保亮度在0-1之间
brightness = max(0.2, min(1.0, brightness))
# 计算当前颜色
self.current_color = (
int(self.color[0] * brightness),
int(self.color[1] * brightness),
int(self.color[2] * brightness)
)
# 确保颜色值在0-255之间
self.current_color = (
max(0, min(255, self.current_color[0])),
max(0, min(255, self.current_color[1])),
max(0, min(255, self.current_color[2]))
)
# 星星缓慢移动
self.y -= self.speed
if self.y < 0:
self.y = HEIGHT
self.x = random.randint(0, WIDTH)
def draw(self, surface):
pygame.draw.circle(surface, self.current_color, (int(self.x), int(self.y)), int(self.size))
# 流星类
class ShootingStar:
def __init__(self):
self.reset()
def reset(self):
self.x = random.randint(WIDTH // 2, WIDTH)
self.y = random.randint(0, HEIGHT // 4)
self.length = random.randint(20, 60)
self.speed = random.uniform(8, 15)
self.angle = random.uniform(2.8, 3.5) # 弧度
self.active = True
self.trail = []
self.max_trail = 10
def update(self):
if not self.active:
if random.random() < 0.005: # 随机生成新流星
self.reset()
return
# 更新位置
self.x -= self.speed * math.cos(self.angle)
self.y += self.speed * math.sin(self.angle)
# 记录轨迹
self.trail.append((self.x, self.y))
if len(self.trail) > self.max_trail:
self.trail.pop(0)
# 检查是否飞出屏幕
if self.x < 0 or self.y > HEIGHT:
self.active = False
def draw(self, surface):
if not self.active and not self.trail:
return
# 绘制流星轨迹
for i, (trail_x, trail_y) in enumerate(self.trail):
alpha = int(255 * (i / len(self.trail)))
if alpha > 0: # 只绘制可见的轨迹
# 创建一个临时Surface用于绘制半透明圆
s = pygame.Surface((6, 6), pygame.SRCALPHA)
color_with_alpha = (255, 255, 255, alpha)
pygame.draw.circle(s, color_with_alpha, (3, 3), 3)
surface.blit(s, (trail_x - 3, trail_y - 3))
# 绘制流星头部
if self.active:
pygame.draw.circle(surface, (255, 255, 255), (int(self.x), int(self.y)), 2)
# 按钮类
class Button:
def __init__(self, x, y, width, height, text, action):
self.rect = pygame.Rect(x, y, width, height)
self.text = text
self.action = action
self.color = BUTTON_COLORS["normal"]
self.hovered = False
self.pressed = False
self.radius = 15
def draw(self, surface):
# 绘制按钮背景
color = BUTTON_COLORS["pressed"] if self.pressed else (BUTTON_COLORS["hover"] if self.hovered else BUTTON_COLORS["normal"])
pygame.draw.rect(surface, color, self.rect, border_radius=self.radius)
pygame.draw.rect(surface, (255, 255, 255), self.rect, 2, border_radius=self.radius)
# 绘制按钮文字
text_surf = font_medium.render(self.text, True, TEXT_COLOR)
text_rect = text_surf.get_rect(center=self.rect.center)
surface.blit(text_surf, text_rect)
def check_hover(self, pos):
self.hovered = self.rect.collidepoint(pos)
return self.hovered
def handle_event(self, event):
if event.type == MOUSEBUTTONDOWN and event.button == 1:
if self.hovered:
self.pressed = True
return True
elif event.type == MOUSEBUTTONUP and event.button == 1:
if self.pressed and self.hovered:
self.action()
self.pressed = False
return False
# 游戏主类
class TypingGame:
def __init__(self):
self.reset_game()
self.stars = [Star() for _ in range(150)] # 减少星星数量以提高性能
self.shooting_stars = [ShootingStar() for _ in range(2)] # 减少流星数量
self.buttons = []
self.create_buttons()
self.game_state = "menu" # menu, playing, game_over
def reset_game(self):
self.current_word_idx = 0
self.user_input = ""
self.correct_count = 0
self.incorrect_count = 0
self.total_time = 0
self.start_time = pygame.time.get_ticks()
self.last_word_time = pygame.time.get_ticks()
self.word_times = []
self.accuracy = 100.0
self.current_words = []
self.shuffle_words()
self.get_new_word()
def shuffle_words(self):
# 随机选择30个单词进行练习
self.current_words = random.sample(WORD_LIST, 30)
def get_new_word(self):
if self.current_word_idx < len(self.current_words):
self.current_word, self.current_meaning = self.current_words[self.current_word_idx]
self.user_input = ""
self.last_word_time = pygame.time.get_ticks()
else:
self.game_over()
def game_over(self):
self.game_state = "game_over"
if self.correct_count + self.incorrect_count > 0:
self.accuracy = (self.correct_count / (self.correct_count + self.incorrect_count)) * 100
def create_buttons(self):
button_width, button_height = 200, 60
center_x = WIDTH // 2
self.buttons = [
Button(center_x - button_width // 2, HEIGHT // 2, button_width, button_height, "开始游戏", self.start_game),
Button(center_x - button_width // 2, HEIGHT // 2 + 100, button_width, button_height, "重新开始", self.restart_game),
Button(center_x - button_width // 2, HEIGHT // 2 + 200, button_width, button_height, "退出游戏", self.quit_game)
]
def start_game(self):
self.reset_game()
self.game_state = "playing"
def restart_game(self):
self.start_game()
def quit_game(self):
pygame.quit()
sys.exit()
def handle_input(self, event):
if self.game_state != "playing":
for button in self.buttons:
button.handle_event(event)
return
if event.type == KEYDOWN:
if event.key == K_RETURN: # 回车键提交
self.check_word()
elif event.key == K_BACKSPACE: # 退格键
self.user_input = self.user_input[:-1]
elif event.key == K_ESCAPE: # ESC键返回菜单
self.game_state = "menu"
else: # 普通字符输入
char = event.unicode
if char.isalpha(): # 只接受字母
self.user_input += char.lower()
def check_word(self):
if not self.user_input:
return
current_time = pygame.time.get_ticks()
time_taken = (current_time - self.last_word_time) / 1000.0
self.word_times.append(time_taken)
if self.user_input == self.current_word:
self.correct_count += 1
else:
self.incorrect_count += 1
self.current_word_idx += 1
self.get_new_word()
def update(self):
# 更新星星
for star in self.stars:
star.update()
# 更新流星
for star in self.shooting_stars:
star.update()
# 更新游戏时间
if self.game_state == "playing":
self.total_time = (pygame.time.get_ticks() - self.start_time) / 1000.0
# 计算准确率
total = self.correct_count + self.incorrect_count
if total > 0:
self.accuracy = (self.correct_count / total) * 100
def draw_background(self, surface):
# 绘制深蓝色背景
surface.fill(BACKGROUND)
# 绘制星星
for star in self.stars:
star.draw(surface)
# 绘制流星
for shooting_star in self.shooting_stars:
shooting_star.draw(surface)
# 绘制标题装饰
title = "Let's Type"
title_surf = font_large.render(title, True, TEXT_COLOR)
title_shadow = font_large.render(title, True, (50, 50, 100))
# 绘制阴影效果
surface.blit(title_shadow, (WIDTH//2 - title_surf.get_width()//2 + 3, 53))
surface.blit(title_surf, (WIDTH//2 - title_surf.get_width()//2, 50))
# 绘制装饰线
line_y = 120
pygame.draw.line(surface, (100, 150, 255), (WIDTH//2 - 180, line_y), (WIDTH//2 + 180, line_y), 2)
# 绘制星星装饰
for i in range(5):
x = WIDTH//2 - 100 + i * 50
pygame.draw.polygon(surface, (255, 255, 200), [
(x, line_y - 10),
(x + 5, line_y - 15),
(x + 10, line_y - 10),
(x + 5, line_y - 5)
])
def draw_menu(self, surface):
# 绘制游戏说明
instructions = [
"游戏说明:",
"1. 输入显示的英文单词",
"2. 按Enter键提交",
"3. 按ESC键返回菜单",
"4. 练习300个最常用英文单词"
]
for i, line in enumerate(instructions):
text_surf = font_small.render(line, True, TEXT_COLOR)
surface.blit(text_surf, (WIDTH//2 - text_surf.get_width()//2, 150 + i * 40))
# 绘制按钮
for button in self.buttons[:1]: # 只显示开始游戏按钮
button.draw(surface)
def draw_game(self, surface):
# 绘制进度显示
progress_bg = pygame.Rect(50, 150, WIDTH - 100, 20)
progress_width = (WIDTH - 100) * (self.current_word_idx / max(len(self.current_words), 1))
progress_fg = pygame.Rect(50, 150, progress_width, 20)
pygame.draw.rect(surface, (50, 50, 100), progress_bg, border_radius=10)
pygame.draw.rect(surface, PROGRESS_COLOR, progress_fg, border_radius=10)
progress_text = f"进度: {self.current_word_idx}/{len(self.current_words)}"
text_surf = font_small.render(progress_text, True, TEXT_COLOR)
surface.blit(text_surf, (WIDTH//2 - text_surf.get_width()//2, 120))
# 绘制当前单词
word_surf = font_word.render(self.current_word, True, TEXT_COLOR)
word_x = WIDTH//2 - word_surf.get_width()//2
word_y = 200
surface.blit(word_surf, (word_x, word_y))
# 绘制中文释义
meaning_surf = font_medium.render(f"中文: {self.current_meaning}", True, HINT_COLOR)
surface.blit(meaning_surf, (WIDTH//2 - meaning_surf.get_width()//2, 300))
# 绘制输入框
input_bg = pygame.Rect(WIDTH//2 - 300, 380, 600, 80)
pygame.draw.rect(surface, (30, 30, 60), input_bg, border_radius=15)
pygame.draw.rect(surface, INPUT_COLOR, input_bg, 3, border_radius=15)
input_surf = font_input.render(self.user_input, True, INPUT_COLOR)
cursor_x = WIDTH//2 - input_surf.get_width()//2
# 绘制输入文本
surface.blit(input_surf, (cursor_x, 400))
# 绘制闪烁的光标
if pygame.time.get_ticks() % 1000 < 500:
cursor_pos = cursor_x + input_surf.get_width() + 5
pygame.draw.line(surface, INPUT_COLOR, (cursor_pos, 400), (cursor_pos, 440), 3)
# 绘制提示
hint_text = "输入单词后按Enter键提交,按ESC返回菜单"
hint_surf = font_tiny.render(hint_text, True, HINT_COLOR)
surface.blit(hint_surf, (WIDTH//2 - hint_surf.get_width()//2, 480))
# 绘制统计数据
stats_y = 520
stats = [
f"正确: {self.correct_count}",
f"错误: {self.incorrect_count}",
f"准确率: {self.accuracy:.1f}%",
f"用时: {self.total_time:.1f}秒"
]
for i, stat in enumerate(stats):
stat_surf = font_tiny.render(stat, True, STATS_COLOR)
surface.blit(stat_surf, (100 + i * 220, stats_y))
# 如果已经输入了一些字符,在单词上方显示比对
if self.user_input:
for i, (user_char, correct_char) in enumerate(zip(self.user_input, self.current_word)):
if i >= len(self.current_word):
break
# 计算每个字符的位置
char_color = CORRECT_COLOR if user_char == correct_char else INCORRECT_COLOR
# 渲染字符
char_surf = font_word.render(user_char, True, char_color)
# 计算这个字符在完整单词中的位置
# 首先获取从单词开始到这个字符的子字符串
partial_word = self.current_word[:i]
partial_surf = font_word.render(partial_word, True, TEXT_COLOR)
# 计算这个字符的x坐标
char_x = word_x + partial_surf.get_width()
# 在单词上方绘制用户输入的这个字符
# surface.blit(char_surf, (char_x, word_y - 40))
# 在单词原本的位置绘制用户输入的这个字符
surface.blit(char_surf, (char_x, word_y))
# 可选:在字符下方绘制下划线
if user_char != correct_char:
underline_y = word_y - 10
pygame.draw.line(surface, INCORRECT_COLOR,
(char_x, underline_y),
(char_x + char_surf.get_width(), underline_y), 2)
def draw_game_over(self, surface):
# 绘制游戏结束界面
game_over_text = "练习完成!"
text_surf = font_large.render(game_over_text, True, TEXT_COLOR)
surface.blit(text_surf, (WIDTH//2 - text_surf.get_width()//2, 200))
# 绘制最终统计
stats = [
f"正确单词: {self.correct_count}",
f"错误单词: {self.incorrect_count}",
f"最终准确率: {self.accuracy:.1f}%",
f"总用时: {self.total_time:.1f}秒"
]
if self.word_times:
avg_time = sum(self.word_times) / len(self.word_times)
stats.append(f"平均每个单词: {avg_time:.2f}秒")
wpm = (self.correct_count / self.total_time * 60) if self.total_time > 0 else 0
stats.append(f"打字速度: {wpm:.1f} WPM")
for i, stat in enumerate(stats):
stat_surf = font_medium.render(stat, True, STATS_COLOR)
surface.blit(stat_surf, (WIDTH//2 - stat_surf.get_width()//2, 280 + i * 50))
# 绘制按钮
for button in self.buttons[1:]: # 显示重新开始和退出按钮
button.draw(surface)
def draw(self, surface):
# 绘制背景
self.draw_background(surface)
# 根据游戏状态绘制不同界面
if self.game_state == "menu":
self.draw_menu(surface)
elif self.game_state == "playing":
self.draw_game(surface)
elif self.game_state == "game_over":
self.draw_game_over(surface)
# 绘制版本信息
version_text = "英文打字练习 - by xhlbudd@52pojie"
version_surf = font_tiny.render(version_text, True, HINT_COLOR)
surface.blit(version_surf, (WIDTH//2 - version_surf.get_width()//2, HEIGHT - 30))
# 主游戏循环
def main():
game = TypingGame()
clock = pygame.time.Clock()
running = True
while running:
mouse_pos = pygame.mouse.get_pos()
# 处理事件
for event in pygame.event.get():
if event.type == QUIT:
running = False
elif event.type == KEYDOWN and event.key == K_ESCAPE:
if game.game_state == "playing":
game.game_state = "menu"
else:
running = False
else:
game.handle_input(event)
# 更新按钮状态
for button in game.buttons:
button.check_hover(mouse_pos)
# 更新游戏状态
game.update()
# 绘制
game.draw(screen)
# 更新显示
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit()
if __name__ == "__main__":
main()