网站价格表,网站建设中如何发布信息推广,做网站php的作用,安徽六安有什么特产一、整体介绍#xff1a;
1.1 前言#xff1a;
游戏代码基于Python制作经典游戏案例-水果忍者做出一些改动#xff0c;优化并增加了一些功能。作为自己Python阶段学习的结束作品#xff0c;文章最后有源码链接。
1.2 Python主要知识#xff1a;
#xff08;1#xf…一、整体介绍
1.1 前言
游戏代码基于Python制作经典游戏案例-水果忍者做出一些改动优化并增加了一些功能。作为自己Python阶段学习的结束作品文章最后有源码链接。
1.2 Python主要知识
1面向对象编程
类的定义与实例化、封装、继承使用 pygame.sprite.Sprite 作为基类
2模块与库
导入标准库time, math, random、导入第三方库 pygame
3事件处理
事件监听pygame.event.get() 处理用户输入和游戏事件、响应事件根据不同事件如关闭窗口、定时器事件执行相应操作
4图形绘制
图像加载 pygame.image.load() 加载图像、图像绘制blit() 方法将图像绘制到窗口上、图像旋转 pygame.transform.rotate() 旋转图像
5随机数生成
6计时与帧率控制
使用 pygame.time.Clock() 控制游戏的帧率
7文件操作
使用 open() 读取和写入文本文件保存和读取最佳分数、逐行读取文件内容并解析数据
8碰撞检测
9Sprite 和 Group
使用 pygame.sprite.Sprite 创建精灵如水果、刀光、背景、使用 pygame.sprite.Group 管理和更新多个精灵方便批量处理
10数学运算
使用三角函数math.sin() 和 math.cos()计算水果的抛出轨迹
11音频处理
使用 pygame.mixer 播放背景音乐和音效增强游戏体验
12逻辑控制
13字体与文本渲染
使用 pygame.font.Font() 创建字体对象并使用 render() 方法渲染文本以显示分数和信息
14参数传递与返回值 1.3 游戏素材 二、完善功能
1优化游戏参数
例如首页旋转圆环速度水果上抛高度等使游戏体验更加平滑。
2禅宗模式倒计时
禅宗模式在游戏右上方增加了时间倒计时的图形化界面。 3增加额外音效
由于pygame同时播放音乐会有覆盖现象。即后播放音乐会覆盖之前播放音乐导致原版游戏结束bgm.play_over被bgm.play_menu覆盖播放不出来。使用独立线程对代码要求较高取巧利用睡眠time.sleep。玩家切到炸弹结束游戏暂停0.3s画面而不是原版的突然重新开始。
4游戏历史最高分数
利用IO流逐行读取txt文件和原版分数一样的window.blit函数绘制在游戏界面不过分数的更新要在结束程序后会执行。 Bug
游戏的局部和实例变量较多有些资源可能会被程序占用而无法释放。目前主要bug在游戏碰撞检测的时候偶尔会出现分数停止更新的情况。本人才疏学浅至今没有有效解决希望大佬们多多包涵最好能够帮助解决完善游戏。
三、代码设计
import time
import math
import random
import pygame
from pygame.constants import *pygame.init() 背景图片
class Background(pygame.sprite.Sprite):def __init__(self, window, x, y, image_path):pygame.sprite.Sprite.__init__(self)self.window windowself.image pygame.image.load(image_path)self.rect self.image.get_rect()self.rect.x xself.rect.y ydef update(self):self.window.blit(self.image, self.rect) 被抛出的水果类
class ThrowFruit(pygame.sprite.Sprite):def __init__(self, window, image_path, speed, turn_angel, flag):pygame.sprite.Sprite.__init__(self)# 游戏窗口self.window window# 导入水果图像并获取其矩形区域self.image pygame.image.load(image_path)self.rect self.image.get_rect()# 水果抛出时x坐标取随机数self.rect.x random.randint(0, Manager.WIDTH - 10)# 水果初始y坐标self.rect.y Manager.HEIGHT# 抛出时速度self.speed speed# 旋转速度self.turn_angel turn_angel# 水果抛出时与窗口下水平线的夹角弧度因为要用到随机函数, 所以取整数 使用时除以100self.throw_angel 157# 水果抛出后所经历的时间, 初始化为0self.fruit_t 0# 旋转的总角度self.v_angel 0# 水果抛出时的初速度self.v0 6# 水果标记self.flag flagdef update(self): 水果运动状态更新 # 在弧度制中一个完整的圆周对应的角度是360度对应的弧度是2π即360度 2π弧度。# 因此可以通过以下公式将角度转换为弧度 弧度 角度 × π / 180# 当角度为90度时根据上述公式可以计算出对应的弧度为 90度 × π / 180 0.5π 1.57约# 如果水果的初始X坐标位于窗口左边区域, 取抛出时弧度在70度至90度之间if self.rect.x Manager.WIDTH / 2:self.throw_angel random.randint(140, 157)# 如果水果的初始X坐标位于窗口右侧区域, 取抛出时弧度在90度至110度之间elif self.rect.x Manager.WIDTH / 2:self.throw_angel random.randint(157, 175)# 水果旋转后的新图像new_fruit pygame.transform.rotate(self.image, self.v_angel)self.window.blit(new_fruit, (self.rect.x self.rect.width / 2 - new_fruit.get_width() / 2,self.rect.y self.rect.height / 2 - new_fruit.get_height() / 2))# 如果水果落出屏幕没有被切经典模式 X 加一并销毁水果对象if self.rect.y Manager.HEIGHT self.rect.height:if self.flag ! 5:Manager.classic_miss 1self.kill()# 水果抛出后的运动时水平匀速运动以及竖直向上的变速运动到达最高点时下落, 所以可以判断水果做的是斜上抛运动# 可以利用重力加速度来求出每隔一段时间水果运动后的y坐标# 公式: v0 * t * sin(α) - g * t^2 / 2self.rect.y - self.v0 * self.fruit_t * math.sin(self.throw_angel / 100) - (Manager.G *self.fruit_t ** 2 / 10) / 2# 计算水果在水平方向的匀速运动位移之后的X坐标# 公式: v0 * t * cos(α)self.rect.x self.v0 * self.fruit_t * math.cos(self.throw_angel / 100)# 累加经过的时间self.fruit_t 0.1# 累加旋转总角度self.v_angel self.turn_angel 水果切片类
class HalfFruit(pygame.sprite.Sprite):def __init__(self, window, image_path, x, y, turn_angel, v_angel, v0):pygame.sprite.Sprite.__init__(self)self.window windowself.image pygame.image.load(image_path)self.rect self.image.get_rect()self.rect.x xself.rect.y yself.turn_angel turn_angelself.fruit_t 0self.v_angel v_angelself.v0 v0def update(self): 水果运动状态更新 # 水果旋转后的新图像new_fruit pygame.transform.rotate(self.image, self.v_angel)# 将旋转后的新图像贴入游戏窗口, 注意, 旋转后的图像尺寸以及像素都不一样了(尺寸变大了), 所以坐标需要进行适当处理# 在原先图片矩形的中心位置绘制self.window.blit(new_fruit, (self.rect.x self.rect.width / 2 - new_fruit.get_width() / 2,self.rect.y self.rect.height / 2 - new_fruit.get_height() / 2))if self.rect.y Manager.HEIGHT:self.kill()self.rect.y Manager.G * self.fruit_t ** 2 / 2self.rect.x self.v0 * self.fruit_tself.fruit_t 0.01self.v_angel self.turn_angel 水果刀光类
class Knife(object):def __init__(self, window):self.window windowself.apple_flash pygame.image.load(./images/apple_flash.png)self.banana_flash pygame.image.load(./images/banana_flash.png)self.peach_flash pygame.image.load(./images/peach_flash.png)self.watermelon_flash pygame.image.load(./images/watermelon_flash.png)self.strawberry_flash pygame.image.load(./images/strawberry_flash.png)def show_apple_flash(self, x, y):self.window.blit(self.apple_flash, (x, y))def show_banana_flash(self, x, y):self.window.blit(self.banana_flash, (x, y))def show_peach_flash(self, x, y):self.window.blit(self.peach_flash, (x, y))def show_watermelon_flash(self, x, y):self.window.blit(self.watermelon_flash, (x, y))def show_strawberry_flash(self, x, y):self.window.blit(self.strawberry_flash, (x, y)) 模式选项类
class OptionMode(pygame.sprite.Sprite):def __init__(self, window, x, y, image_path, turn_angel, flag):pygame.sprite.Sprite.__init__(self)self.window windowself.image pygame.image.load(image_path)self.rect self.image.get_rect()self.rect.x xself.rect.y yself.turn_angel turn_angelself.v_angel 0self.flag flagdef update(self):new_image pygame.transform.rotate(self.image, -self.v_angel)self.window.blit(new_image, (self.rect.x self.rect.width / 2 - new_image.get_width() / 2,self.rect.y self.rect.height / 2 - new_image.get_height() / 2))self.v_angel self.turn_angel 游戏音乐类
class Bgm(object):def __init__(self):pygame.mixer.init()def play_menu(self):pygame.mixer.music.load(./sound/menu.mp3)pygame.mixer.music.play(-1, 0)def play_classic(self):pygame.mixer.music.load(./sound/start.mp3)pygame.mixer.music.play(1, 0)def play_throw(self):pygame.mixer.music.load(./sound/throw.mp3)pygame.mixer.music.play(1, 0)def play_splatter(self):pygame.mixer.music.load(./sound/splatter.mp3)pygame.mixer.music.play(1, 0)def play_over(self):pygame.mixer.music.load(./sound/over.mp3)pygame.mixer.music.play(1, 0)def play_boom(self):pygame.mixer.music.load(./sound/boom.mp3)pygame.mixer.music.play(1, 0) 游戏逻辑类
class Manager(object):# 窗口尺寸WIDTH 640HEIGHT 480# 游戏中的定时器常量THROWFRUITTIME pygame.USEREVENTpygame.time.set_timer(THROWFRUITTIME, 3000)# 根据窗口大小选取随机整数重力加速度, 水果下落更有层次感使用时除以10G random.randint(19, 21)# 经典模式miss掉的水果数classic_miss 0# 打开文本文件with open(best.txt, r) as file:# 逐行读取文件内容for line in file:if zen_mode in line:zen_best int(line.split(:)[-1].strip())if classic_mode in line:classic_best int(line.split(:)[-1].strip())def __init__(self):# 生成游戏窗口self.window pygame.display.set_mode((Manager.WIDTH, Manager.HEIGHT))self.window_icon pygame.image.load(./images/score.png)pygame.display.set_icon(self.window_icon)pygame.display.set_caption(FruitNinja)# 创建游戏中用到的的精灵组self.background_list pygame.sprite.Group()self.circle_option pygame.sprite.Group()self.option_fruit_list pygame.sprite.Group()self.fruit_half_list pygame.sprite.Group()self.throw_fruit_list pygame.sprite.Group()# 导入背景图像并添加入背景精灵组self.background Background(self.window, 0, 0, ./images/background.jpg)self.home_mask Background(self.window, 0, 0, ./images/home-mask.png)self.logo Background(self.window, 20, 10, ./images/logo.png)self.ninja Background(self.window, Manager.WIDTH - 320, 45, ./images/ninja.png)self.home_desc Background(self.window, 20, 135, ./images/home-desc.png)self.zen_new Background(self.window, 175, 215, ./images/new.png)self.background_list.add(self.background)self.background_list.add(self.home_mask)self.background_list.add(self.logo)self.background_list.add(self.ninja)self.background_list.add(self.home_desc)self.background_list.add(self.zen_new)# 创建旋转的圈并添加进精灵组self.dojo OptionMode(self.window, Manager.WIDTH - 600, Manager.HEIGHT - 250,./images/dojo.png, 1, None)self.new_game OptionMode(self.window, Manager.WIDTH - 405, Manager.HEIGHT - 250,./images/new-game.png, 1, None)self.game_quit OptionMode(self.window, Manager.WIDTH - 160, Manager.HEIGHT - 150,./images/quit.png, -1, None)self.circle_option.add(self.dojo)self.circle_option.add(self.new_game)self.circle_option.add(self.game_quit)# 创建主菜单界面旋转的水果并添加进精灵组self.home_peach OptionMode(self.window, Manager.WIDTH - 600 self.dojo.rect.width / 2 - 31,Manager.HEIGHT - 250 self.dojo.rect.height / 2 - 59 / 2,./images/peach.png, -1, option_peach)self.home_watermelon OptionMode(self.window, Manager.WIDTH - 405 self.new_game.rect.width / 2 - 49,Manager.HEIGHT - 250 self.new_game.rect.height / 2 - 85 / 2,./images/watermelon.png, -1, option_watermelon)self.home_boom OptionMode(self.window, Manager.WIDTH - 160 self.game_quit.rect.width / 2 - 66 / 2,Manager.HEIGHT - 150 self.game_quit.rect.height / 2 - 68 / 2,./images/boom.png, 1, option_boom)self.option_fruit_list.add(self.home_peach)self.option_fruit_list.add(self.home_watermelon)self.option_fruit_list.add(self.home_boom)# 设置定时器self.clock pygame.time.Clock()# 模式标记self.mode_flag 0# 音效self.bgm Bgm()# 刀光self.knife Knife(self.window)# 游戏分数self.classic_score 0self.zen_score 0def create_fruit(self): 创建水果 if self.mode_flag 1:boom_prob random.randint(4, 6)if boom_prob 5:self.bgm.play_throw()boom ThrowFruit(self.window, ./images/boom.png, None, 5, 5)self.throw_fruit_list.add(boom)fruit_image_path [./images/apple.png, ./images/banana.png, ./images/peach.png,./images/watermelon.png, ./images/strawberry.png]fruit_number random.randint(1, 4)for n in range(fruit_number):rand_fruit_index random.randint(0, len(fruit_image_path) - 1)self.bgm.play_throw()fruit ThrowFruit(self.window, fruit_image_path[rand_fruit_index], None, 5,rand_fruit_index)self.throw_fruit_list.add(fruit)def create_fruit_half(self, fruit_flag, fruit_x, fruit_y, turn_angel, v_angel):if fruit_flag option_peach: 禅宗模式的桃子被切开 fruit_left HalfFruit(self.window, ./images/peach-1.png, fruit_x - 50,fruit_y, turn_angel, v_angel, -5)fruit_right HalfFruit(self.window, ./images/peach-2.png, fruit_x 50,fruit_y, -turn_angel, v_angel, 5)self.fruit_half_list.add(fruit_left)self.fruit_half_list.add(fruit_right)if fruit_flag option_watermelon: 经典模式西瓜被切开 fruit_left HalfFruit(self.window, ./images/watermelon-1.png, fruit_x - 50,fruit_y, turn_angel, v_angel, -5)fruit_right HalfFruit(self.window, ./images/watermelon-2.png, fruit_x 50,fruit_y, -turn_angel, v_angel, 5)self.fruit_half_list.add(fruit_left)self.fruit_half_list.add(fruit_right)if fruit_flag 0: 苹果被切开 fruit_left HalfFruit(self.window, ./images/apple-1.png, fruit_x - 50,fruit_y, turn_angel, v_angel, -5)fruit_right HalfFruit(self.window, ./images/apple-2.png, fruit_x 50,fruit_y, -turn_angel, v_angel, 5)self.fruit_half_list.add(fruit_left)self.fruit_half_list.add(fruit_right)if fruit_flag 1: 香蕉被切开 fruit_left HalfFruit(self.window, ./images/banana-1.png, fruit_x - 50,fruit_y, turn_angel, v_angel, -5)fruit_right HalfFruit(self.window, ./images/banana-2.png, fruit_x 50,fruit_y, -turn_angel, v_angel, 5)self.fruit_half_list.add(fruit_left)self.fruit_half_list.add(fruit_right)if fruit_flag 2: 梨被切开 fruit_left HalfFruit(self.window, ./images/peach-1.png, fruit_x - 50,fruit_y, turn_angel, v_angel, -5)fruit_right HalfFruit(self.window, ./images/peach-2.png, fruit_x 50,fruit_y, -turn_angel, v_angel, 5)self.fruit_half_list.add(fruit_left)self.fruit_half_list.add(fruit_right)if fruit_flag 3: 西瓜被切开 fruit_left HalfFruit(self.window, ./images/watermelon-1.png, fruit_x - 50,fruit_y, turn_angel, v_angel, -5)fruit_right HalfFruit(self.window, ./images/watermelon-2.png, fruit_x 50,fruit_y, -turn_angel, v_angel, 5)self.fruit_half_list.add(fruit_left)self.fruit_half_list.add(fruit_right)if fruit_flag 4: 草莓被切开 fruit_left HalfFruit(self.window, ./images/strawberry-1.png, fruit_x - 50,fruit_y, turn_angel, v_angel, -5)fruit_right HalfFruit(self.window, ./images/strawberry-2.png, fruit_x 50,fruit_y, -turn_angel, v_angel, 5)self.fruit_half_list.add(fruit_left)self.fruit_half_list.add(fruit_right)def impact_check(self): 碰撞检测 for item in self.option_fruit_list: 主页的模式选择 mouse_pos pygame.mouse.get_pos()if mouse_pos[0] item.rect.left and mouse_pos[0] item.rect.right \and mouse_pos[1] item.rect.top and mouse_pos[1] item.rect.bottom:self.bgm.play_splatter()self.create_fruit_half(item.flag, item.rect.x, item.rect.y, item.turn_angel, item.v_angel)self.option_fruit_list.remove_internal(item)if item.flag option_peach:self.mode_flag 1return 1elif item.flag option_watermelon:self.mode_flag 2return 2elif item.flag option_boom:return 0for item in self.throw_fruit_list: 游戏开始后判断水果是否被切到 mouse_pos pygame.mouse.get_pos()if mouse_pos[0] item.rect.left and mouse_pos[0] item.rect.right \and mouse_pos[1] item.rect.top and mouse_pos[1] item.rect.bottom:if item.flag 0:self.knife.show_apple_flash(item.rect.x, item.rect.y)if item.flag 1:self.knife.show_banana_flash(item.rect.x, item.rect.y)if item.flag 2:self.knife.show_peach_flash(item.rect.x, item.rect.y)if item.flag 3:self.knife.show_watermelon_flash(item.rect.x, item.rect.y)if item.flag 4:self.knife.show_strawberry_flash(item.rect.x, item.rect.y)if self.mode_flag 1:self.zen_score 2if self.mode_flag 2:self.classic_score 2if item.flag ! 5:self.bgm.play_splatter()self.create_fruit_half(item.flag, item.rect.x, item.rect.y, item.turn_angel, item.v_angel)self.throw_fruit_list.remove_internal(item)if item.flag 5:self.bgm.play_boom()time.sleep(0.4)return 3def check_key(self): 监听事件 for event in pygame.event.get():if event.type QUIT:pygame.quit()exit()elif event.type Manager.THROWFRUITTIME and self.mode_flag 1:self.create_fruit()elif event.type Manager.THROWFRUITTIME and self.mode_flag 2:self.create_fruit()def zen_mode(self): 禅宗模式 self.bgm.play_classic()score_image Background(self.window, 10, 5, ./images/score.png)text pygame.font.Font(./images/simhei.ttf, 30) # 设置分数显示的字体best pygame.font.Font(./images/simhei.ttf, 20) # 设置历史最好分数显示的字体# 禅宗模式游戏时间record_time 3600while True:# 设置游戏帧率self.clock.tick(60)self.check_key()self.background_list.sprites()[0].update()score_image.update()text_score text.render(%d % self.zen_score, 1, (255, 213, 156))self.window.blit(text_score, (50, 8))best_score best.render(BEST %d % self.zen_best, 1, (255, 179, 78))self.window.blit(best_score, (10, 40))game_time text.render(Time:%d % (record_time / 60), 1, (178, 34, 34))self.window.blit(game_time, (510, 12))temp_flag self.impact_check()self.throw_fruit_list.update()self.fruit_half_list.update()pygame.display.update()record_time - 1# 禅宗模式更新最高历史记录if record_time 0 or temp_flag 3:if self.zen_score self.zen_best:file_path best.txtwith open(file_path, r) as file:content file.read()content content.replace(str(self.zen_best), str(self.zen_score))with open(file_path, w) as file:file.write(content)returndef classic_mode(self): 经典模式 pygame.font.init()self.bgm.play_classic()score_image Background(self.window, 10, 5, ./images/score.png)text pygame.font.Font(./images/simhei.ttf, 30) # 设置分数显示的字体best pygame.font.Font(./images/simhei.ttf, 20) # 设置历史最好分数显示的字体x_nums pygame.sprite.Group()miss_times pygame.sprite.Group()xxx Background(self.window, Manager.WIDTH - 30, 5, ./images/xxx.png)xx Background(self.window, Manager.WIDTH - 60, 5, ./images/xx.png)x Background(self.window, Manager.WIDTH - 90, 5, ./images/x.png)x_nums.add(xxx)x_nums.add(xx)x_nums.add(x)while True:# 设置游戏帧率self.clock.tick(60)pygame.display.update()self.check_key()self.background_list.sprites()[0].update()score_image.update()text_score text.render(%d % self.classic_score, 1, (255, 213, 156))self.window.blit(text_score, (50, 8))best_score best.render(BEST %d % self.classic_best, 1, (255, 179, 78))self.window.blit(best_score, (10, 40))x_nums.update()miss_times.update()temp_flag self.impact_check()if temp_flag 3:# 经典模式炸弹结束游戏更新历史最高记录if self.classic_score self.classic_best:file_path best.txtwith open(file_path, r) as file:content file.read()content content.replace(str(self.classic_best), str(self.classic_score))with open(file_path, w) as file:file.write(content)self.bgm.play_boom()time.sleep(0.4)returnself.throw_fruit_list.update()self.fruit_half_list.update()if Manager.classic_miss 1:xf Background(self.window, Manager.WIDTH - 90, 5, ./images/xf.png)miss_times.add(xf)elif Manager.classic_miss 2:xf Background(self.window, Manager.WIDTH - 90, 5, ./images/xf.png)miss_times.add(xf)xxf Background(self.window, Manager.WIDTH - 60, 5, ./images/xxf.png)miss_times.add(xxf)elif Manager.classic_miss 3:# 经典模式正常结束更新历史最高记录if self.classic_score self.classic_best:file_path best.txtwith open(file_path, r) as file:content file.read()content content.replace(str(self.classic_best), str(self.classic_score))with open(file_path, w) as file:file.write(content)self.bgm.play_over()time.sleep(0.4)Manager.classic_miss 0returndef main(self): 主页 self.bgm.play_menu()while True:# 设置游戏帧率self.clock.tick(60)self.background_list.update()self.circle_option.update()self.option_fruit_list.update()self.fruit_half_list.update()temp_flag self.impact_check()pygame.display.update()if temp_flag 1:self.zen_mode()self.__init__()self.bgm.play_over()self.bgm.play_menu()if temp_flag 2:self.classic_mode()self.__init__()self.bgm.play_over()self.bgm.play_menu()elif temp_flag 0:self.bgm.play_over()time.sleep(0.3)pygame.quit()exit()elif temp_flag 3:self.__init__()self.bgm.play_menu()self.check_key()if __name__ __main__:manager Manager()manager.main()源码 链接https://pan.baidu.com/s/11YM7GzqzFz1QkcGbJHnDCQ 提取码daz5