背单词小游戏,要有多界面交互,界面整洁、美观,可调节游戏等级难度,可配置游戏信息。
有游戏分数,游戏时间,动画特效,背景音乐,不同游戏等级的历史最高分记录。
拼写成功的英文单词显示中文意思。支持长按回删键[backspace],快速删除单词字母。
多种游戏困难等级让玩家可以侧重提高打字速度、或者练习英语单词。
完整程序代码下载地址:Python背单词记单词小程序源代码
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Description: { 背单词小游戏主入口模块 }
"""
import os
import sys
import time
import json
import traceback
import Game_View
from Game_View import *
from Game_Sprite import *def center_pos():"""设置游戏窗口相对电脑屏幕居中"""game_x = (Game_Info.SCREEN_X - Game_Info.SCREEN_RECT.width) / 2game_y = (Game_Info.SCREEN_Y - Game_Info.SCREEN_RECT.height) / 2os.environ['SDL_VIDEO_WINDOW_POS'] = "%d, %d" % (game_x, game_y)def random_music():"""随机播放背景音乐"""# 判断是否是静音模式print(Game_View.GameStartWin.voice_flag())try:pygame.mixer.init()pygame.mixer.music.load(random.choice(Game_Info.GAME_MUSICS))pygame.mixer.music.play(loops=0)except Exception as e:print("无法加载音频,请检查电脑配置" + str(e))print(traceback.format_exc())if not Game_View.GameStartWin.voice_flag():pygame.mixer_music.set_volume(0)class TypingGame(object):"""打字小游戏主类"""spell_ok = False # 用于标识单词拼写成功game_pause_flag = False # 游戏暂停标志game_over_flag = False # 游戏结束标志game_quit_flag = False # 游戏退出标志game_total_blood = Game_Info.GAME_BLOOD_RECT.width # 游戏总能量(血条)# 游戏等级对照字典game_level_dict = {1: {"word_fall_speed": 0.3, "level_text": "简单", "level_color": "green"},2: {"word_fall_speed": 0.5, "level_text": "上手", "level_color": "blue"},3: {"word_fall_speed": 1.0, "level_text": "中等", "level_color": "orange"},4: {"word_fall_speed": 1.5, "level_text": "困难", "level_color": "red"},5: {"word_fall_speed": 2.0, "level_text": "魔鬼", "level_color": "purple"}}@staticmethoddef game_init():"""游戏初始化"""pygame.init()# 初始化游戏字体pygame.font.init()# 设置游戏标题和图标pygame.display.set_caption(Game_Info.GAME_NAME)pygame.display.set_icon(pygame.image.load(Game_Info.GAME_ICON_32))@staticmethoddef set_game_event():"""设置游戏事件"""# 设置创建单词的定时器pygame.time.set_timer(Game_Info.CREATE_WORD_EVENT, Game_Info.CREATE_WORD_INTERVAL)# 设置游戏音乐结束事件try:pygame.mixer.music.set_endevent(Game_Info.MUSIC_END_EVENT)except Exception as e:print("无法设置音乐结束事件\t" + str(e))print(traceback.format_exc())@staticmethoddef load_words() -> dict:"""加载英语单词return:{"CET4": [{"eng_word": "a","cn_comment": "art.一(个);每一(个)"},...]}"""with open(Game_Info.GAME_WORD_JSON, "r", encoding="utf-8") as file:word_json = file.read()word_dict = json.loads(word_json)return word_dictdef __init__(self):self.words = self.load_words().get("CET4")self.game_conf = GameConfig() # 游戏配置信息self.game_default_voice = 20 # 游戏默认音量self.use_time = 0 # 记录游戏使用的时间self.total_score = 0 # 记录游戏拼写成功了多少个单词self.word_content = "" # 记录键盘输入的单词self.backspace_count = 0 # 回删键按下的次数# 预先创建动画对象self.animates = [Animation(self) for _ in range(5)]# 游戏初始血条值self.game_blood = int(self.game_conf.game_init_blood) * 10self.game_clock = pygame.time.Clock()self.screen = pygame.display.set_mode(Game_Info.SCREEN_RECT.size)self.game_init()self.set_game_event() # 设置游戏事件self.__create_sprite() # 创建游戏精灵def __create_sprite(self):"""创建精灵和精灵组"""# 背景精灵back_sprite = ImageSprite(Game_Info.GAME_BACKGROUND)# 根据游戏屏幕的大小适配背景图(可能会导致背景图变形)back_sprite.transform_scale(back_sprite.image,(Game_Info.SCREEN_RECT.width, Game_Info.SCREEN_RECT.height))self.back_group = pygame.sprite.Group(back_sprite)# 英文单词显示框input_rect_sprite = ImageSprite(Game_Info.INPUT_BACKGROUND)# 缩放图片input_rect_sprite.transform_scale(input_rect_sprite.image,(Game_Info.INPUT_RECT_WIDTH, Game_Info.INPUT_RECT_HEIGHT))# 水平居中显示input_rect_sprite.hor_center(Game_Info.SCREEN_RECT)self.input_rect_group = pygame.sprite.Group(input_rect_sprite)# 创建“游戏设置”图片self.game_set_sprite = ImageSprite(Game_Info.GAME_SET_PINK)set_x = Game_Info.SCREEN_RECT.width - self.game_set_sprite.rect.width - 10set_y = Game_Info.SCREEN_RECT.height - self.game_set_sprite.rect.height - 10self.game_set_sprite.set_pos(set_x, set_y)self.game_set_sprite_group = pygame.sprite.Group(self.game_set_sprite)# 拼写的单词spell_word_sprite = SpellSprite("",size=26,color=pygame.color.Color(self.game_conf.spell_ok_color))spell_word_sprite.hor_center(Game_Info.SCREEN_RECT)spell_word_sprite.set_pos(spell_word_sprite.rect.x, 40)self.spell_word_group = pygame.sprite.Group(spell_word_sprite)# 创建单词精灵组self.word_group = pygame.sprite.Group()self.__random_generate_word(Game_Info.GENERATE_WORD_NUM)# 创建显示游戏时间精灵time_sprite = TextSprite(text="Time: 0", size=28, color=Game_Info.BLUE)time_sprite.set_pos(5, 0)self.time_group = pygame.sprite.Group(time_sprite)# 游戏分数self.score_sprite = TextSprite("Score: 0", size=30, color=Game_Info.BLUE)self.score_sprite.set_pos(Game_Info.SCREEN_RECT.width - self.score_sprite.rect.width - 20, 3)self.score_group = pygame.sprite.Group(self.score_sprite)# 游戏结束精灵(组)self.__game_over_sprite()def __game_over_sprite(self):"""创建游戏结束的精灵(组)"""self.game_over_group = pygame.sprite.Group()game_over_sprite = TextSprite("Game Over", 100, Game_Info.BLUE)game_over_sprite.rect.y = (Game_Info.SCREEN_RECT.height - game_over_sprite.rect.height - 400) / 2game_over_sprite.hor_center(Game_Info.SCREEN_RECT)game_level_text = self.game_level_dict[int(self.game_conf.game_level)]["level_text"]game_level_color = pygame.color.Color(self.game_level_dict[int(self.game_conf.game_level)]["level_color"])self.game_level_sprite = TextSprite(u"游戏等级: " + game_level_text, 50, game_level_color)self.game_level_sprite.rect.y = game_over_sprite.rect.y + 100 + 50self.game_level_sprite.hor_center(Game_Info.SCREEN_RECT)self.game_score_sprite = TextSprite(u"游戏分数: ", 50, Game_Info.BLUE)self.game_score_sprite.rect.y = game_over_sprite.rect.y + 200 + 50self.game_score_sprite.hor_center(Game_Info.SCREEN_RECT)self.highest_sprite = TextSprite(u"历史最高: ", 50, Game_Info.BLUE)self.highest_sprite.rect.y = game_over_sprite.rect.y + 300 + 50self.highest_sprite.hor_center(Game_Info.SCREEN_RECT)self.quit_sprite = TextSprite(u"退出", 50, Game_Info.BLUE)self.quit_sprite.set_pos(game_over_sprite.rect.x - self.quit_sprite.rect.width,game_over_sprite.rect.y + 400 + 10)self.reset_sprite = TextSprite(u"重 玩", 50, Game_Info.BLUE)self.reset_sprite.set_pos(game_over_sprite.rect.x + game_over_sprite.rect.width,game_over_sprite.rect.y + 400 + 10)self.game_over_group.add(game_over_sprite,self.game_level_sprite,self.game_score_sprite,self.highest_sprite,self.quit_sprite, self.reset_sprite)def __update_sprite(self):"""更新精灵"""self.back_group.update()self.back_group.draw(self.screen)self.game_set_sprite_group.update()self.game_set_sprite_group.draw(self.screen)self.input_rect_group.update()self.input_rect_group.draw(self.screen)# 计算游戏使用时间if not self.game_pause_flag and not self.game_over_flag:self.use_time += 0.1display_time = "Time: " + str(self.use_time / 6)self.time_group.update(display_time[:12])self.time_group.draw(self.screen)self.score_sprite.set_pos(Game_Info.SCREEN_RECT.width - self.score_sprite.rect.width - 20, 3)self.score_group.update("Score: " + str(self.total_score))self.score_group.draw(self.screen)# 判断是否游戏结束if self.game_over_flag:self.__game_over()game_level_text = self.game_level_dict[int(self.game_conf.game_level)]["level_text"]self.game_level_sprite.update("游戏等级: " + str(game_level_text))self.game_over_group.draw(self.screen)else:if not self.game_pause_flag:self.word_group.update(self)self.word_group.draw(self.screen)spell_ok_color = pygame.Color(self.game_conf.spell_ok_color)self.spell_word_group.update(self.word_content, spell_ok_color)self.spell_word_group.draw(self.screen)# 更新游戏能量条if 0 <= self.game_blood <= self.game_total_blood:self.__draw_game_blood()# 单词精灵拼写成功动画for animate in self.animates:if animate.visible:animate.draw()def start_game(self):"""打字游戏开启"""# 随机播放背景音乐random_music()# 利用多线程完成游戏持续掉血drop_blood_t = threading.Thread(target=self.__drop_blood)drop_blood_t.start()while True:# 是否设置成静音if not Game_View.GameStartWin.voice_flag():pygame.mixer_music.set_volume(0)else:pygame.mixer_music.set_volume(self.game_default_voice)# 设置游戏刷新帧率self.game_clock.tick(Game_Info.FRAME_PRE_SEC)# 判断游戏结束if self.game_blood < 0:TypingGame.game_over_flag = Trueelse:self.__animate_action()self.__check_spell_word()self.__update_sprite()self.__event_handle()pygame.display.update()def __event_handle(self):"""游戏事件监听"""# 遍历所有事件for event in pygame.event.get():try:if pygame.mixer.music.get_endevent() == Game_Info.MUSIC_END_EVENT and \not pygame.mixer.music.get_busy():# 如果music播放结束且没有音乐在播放就随机下一首print("下一首")random_music()except:pass# 如果单击关闭窗口,则退出if event.type == pygame.QUIT and not self.game_pause_flag:pygame.quit()TypingGame.game_quit_flag = Truesys.exit()# 创建单词事件elif event.type == Game_Info.CREATE_WORD_EVENT:if not self.game_over_flag and not self.game_pause_flag:# 游戏结束或者暂停就停止生成单词了self.__random_generate_word(word_num=3)# 鼠标移动事件elif event.type == pygame.MOUSEMOTION:x, y = event.pos # 获取屏幕坐标位置if self.__is_on_set(x, y):self.game_set_sprite.image = pygame.image.load(Game_Info.GAME_SET_BLUE)else:self.game_set_sprite.image = pygame.image.load(Game_Info.GAME_SET_PINK)# 游戏结束鼠标悬浮在确定按钮上变色if self.quit_sprite.rect.x <= x <= self.quit_sprite.rect.x + self.quit_sprite.rect.width and \self.quit_sprite.rect.y <= y <= self.quit_sprite.rect.y + self.quit_sprite.rect.height:self.quit_sprite.color = Game_Info.PINKself.quit_sprite.update(self.quit_sprite.text)else:self.quit_sprite.color = Game_Info.BLUEself.quit_sprite.update(self.quit_sprite.text)# 游戏结束鼠标悬浮在重玩按钮上变色if self.reset_sprite.rect.x <= x <= self.reset_sprite.rect.x + self.reset_sprite.rect.width and \self.reset_sprite.rect.y <= y <= self.reset_sprite.rect.y + self.reset_sprite.rect.height:self.reset_sprite.color = Game_Info.PINKself.reset_sprite.update(self.reset_sprite.text)else:self.reset_sprite.color = Game_Info.BLUEself.reset_sprite.update(self.reset_sprite.text)# 鼠标点击事件elif event.type == pygame.MOUSEBUTTONDOWN:x, y = event.pos # 获取屏幕坐标位置# 点击游戏设置if self.__is_on_set(x, y):# 判断游戏是否暂停if not self.game_pause_flag:TypingGame.game_pause_flag = True# 游戏结束鼠标点击退出按钮if self.quit_sprite.rect.x <= x <= self.quit_sprite.rect.x + self.quit_sprite.rect.width and \self.quit_sprite.rect.y <= y <= self.quit_sprite.rect.y + self.quit_sprite.rect.height:pygame.quit()TypingGame.game_quit_flag = Truesys.exit()# 游戏结束鼠标点击重玩按钮if self.reset_sprite.rect.x <= x <= self.reset_sprite.rect.x + self.reset_sprite.rect.width and \self.reset_sprite.rect.y <= y <= self.reset_sprite.rect.y + self.reset_sprite.rect.height:self.__reset_game()# 键盘事件elif event.type == pygame.KEYDOWN and not self.game_over_flag and not self.game_pause_flag:# 英文单引号的ASCII值是39、-是45、.是46# print(event.key)if (pygame.K_a <= event.key <= pygame.K_z) or event.key in (39, 45, 46):if self.spell_ok:# 如果单词拼写成功再按下键盘时清空内容self.word_content = ""self.spell_ok = False# 控制单词长度if len(self.word_content) < 40:# 记录键盘输入的字符self.word_content += pygame.key.name(event.key)else:print("Word to long")print(self.word_content)if event.key == pygame.K_BACKSPACE:self.__delete_words()elif event.type == pygame.KEYUP:self.backspace_count = 0# 实现长按backspace连续回删# 使用键盘提供的方法获取键盘按键 - 按键元组keys_pressed = pygame.key.get_pressed()# 判断元组中对应的按键索引值 1if keys_pressed[pygame.K_BACKSPACE]:self.backspace_count += 1if self.backspace_count > 20:self.__delete_words()def __is_on_set(self, x, y):"""检查是否在设置图片上:param x,y 鼠标的位置"""img_set_x = self.game_set_sprite.rect.ximg_set_y = self.game_set_sprite.rect.yimg_set_w = self.game_set_sprite.rect.widthimg_set_h = self.game_set_sprite.rect.heightif (img_set_x <= x <= img_set_x + img_set_w) and \(img_set_y <= y <= img_set_y + img_set_h):return Trueelse:return Falsedef __delete_words(self):"""单词回删"""if self.word_content != "":self.word_content = self.word_content[:-1]print(self.word_content + "---" + str(len(self.word_content)))if self.spell_ok:# 如果单词拼写成功再按下键盘回删键时清空内容self.word_content = ""self.spell_ok = Falsedef __random_generate_word(self, word_num=5):"""随机生成单词精灵:param word_num:精灵数量 默认5:return:"""count = 0while len(self.word_group.sprites()) <= 30:index = random.randint(0, len(self.words) - 1)eng_word = self.words[index]["eng_word"]cn_comment = self.words[index]["cn_comment"]# print(eng_word + "----" + cn_comment)word_sprite = WordSprite(eng_word,cn_comment,speed=self.game_level_dict[int(self.game_conf.game_level)]['word_fall_speed'],size=int(self.game_conf.word_size),color=pygame.color.Color(str(self.game_conf.word_normal_color)))# 单词位置随机word_sprite.random_pos()# 检查新单词精灵是否与单词精灵组中的精灵碰撞(重叠)words = pygame.sprite.spritecollide(word_sprite, self.word_group, False,)is_collide = pygame.sprite.spritecollideany(word_sprite, self.word_group)print("碰撞", is_collide)# 碰撞(释放内存重新随机生成单词精灵)if len(words) > 0:word_sprite.kill()print("重叠")continueelse:self.word_group.add(word_sprite)count += 1if count >= word_num:breakdef __game_over(self):"""游戏结束"""self.game_score_sprite.hor_center(Game_Info.SCREEN_RECT)self.highest_sprite.hor_center(Game_Info.SCREEN_RECT)self.game_score_sprite.update("游戏分数: %s" % self.total_score)"""history_score_dict{'level_0': "{'score': None,'use_time': None,'create_time': None}",'level_1': "{'score': None,'use_time': None,'create_time': None}",'level_2': "{...}",...}"""# 显示历史最高highest_score_str = self.game_conf.history_score_dict['level_' + str(int(self.game_conf.game_level))]highest_score_dict = eval(highest_score_str)highest_score = highest_score_dict['score']if highest_score is None or int(self.total_score) > int(highest_score):# 更新历史记录highest_score = self.total_scorehighest_score_dict['score'] = str(self.total_score)highest_score_dict['use_time'] = str(self.use_time)[:5] + 's'highest_score_dict['create_time'] = str(time.strftime("%Y-%m-%d %H:%M"))self.game_conf.set_highest_score(str(highest_score_dict), 'level_' + str(int(self.game_conf.game_level)))else:highest_score = highest_score_dict['score']self.highest_sprite.update("历史最高: %s" % highest_score)def __check_spell_word(self):"""检查拼写单词是否正确"""word_sprites = self.word_group.sprites()for word_sprite in word_sprites:# 判断单词内容是否相同if self.word_content.lower() == word_sprite.text.lower():# 判断血条是否超过总血条数if self.game_blood < self.game_total_blood:self.game_blood += 10self.total_score += 1self.spell_ok = Trueself.word_content = self.word_content + "\t" + str(word_sprite.cn_comment)word_sprite.kill()# 从预先创建完毕的动画中取出一个动画对象for animate in self.animates:if not animate.visible:# 设置动画位置animate.set_pos(word_sprite.rect.x, word_sprite.rect.y)# 动画对象状态设置为Trueanimate.visible = Truebreakdef __draw_game_blood(self, color=Game_Info.GREEN):"""绘制游戏能量"""if self.game_blood <= 3 * 10:color = Game_Info.REDif self.game_blood >= 25 * 10:color = Game_Info.BLUEif self.game_total_blood - 30 <= self.game_blood <= self.game_total_blood:color = Game_Info.ORANGE# 绘制游戏能量pygame.draw.rect(self.screen, color,pygame.Rect(Game_Info.GAME_BLOOD_RECT.x + 2,Game_Info.GAME_BLOOD_RECT.y,self.game_blood,Game_Info.GAME_BLOOD_RECT.height))pygame.draw.rect(self.screen, Game_Info.WHITE, Game_Info.GAME_BLOOD_RECT, 2)def __drop_blood(self):"""持续掉血"""# if not self.game_pause_flag:# if int(self.use_time) > 0 and (int(self.use_time) / 6) % 2 == 0:# self.game_blood -= 0.5while not self.game_over_flag:if self.game_pause_flag:self.game_clock.tick(60)else:# 根据不同游戏等级掉血self.game_clock.tick(int(self.game_conf.game_level))self.game_blood -= 1def __animate_action(self):"""开启单词拼写成功动画"""for animate in self.animates:if animate.visible:animate.action()def __reset_game(self):"""游戏重玩"""del self # 释放内存pygame.quit()pygame.init()random_music()TypingGame.game_over_flag = FalseTypingGame.game_quit_flag = FalseTypingGame().start_game()def main():center_pos()# 启动游戏开始界面GameStartWin(title="Word Sprite").run()if __name__ == '__main__':main()
完整程序代码下载地址:Python背单词记单词小程序源代码