【日常点滴019】Python制作流浪气球游戏(导弹射击类)
Python制作流浪气球游戏(导弹射击类)
- 教学课程代码(分步教学版)
- 1、构建全局通用代码结构
- 2、构建气球精灵类
- 3、构建导弹精灵类
- 4、碰撞检测
- 5、构建游戏信息类 (最终完整代码)

教学课程代码(分步教学版)
实时同步文件:Python制作流浪气球游戏(射击类)
B站视频教学地址:浪淘三千
(代码和素材是完整的,对应视频也已更新完毕)
以下是静态样式展示:

1、构建全局通用代码结构
"""
本游戏制作了导弹拦截流浪气球的基本代码 有 音效、音乐、精灵、碰撞、轨迹计算 等知识的应用
当基础功能学会以后,可以教大家平面地图文件的绘制和使用 制作更丰富精彩的游戏场景
视频教学地址,会陆续更新 https://space.bilibili.com/455954948
欢迎积极交流更好的改进建议,一起升级游戏 (代码已同步 链接见视频评论区)
"""
import arcade# 常量 窗口大小和标题
SCREEN_WIDTH = 1200
SCREEN_HEIGHT = 600
SCREEN_TITLE = "Arcade 游戏教学 流浪气球"# arcade_game_202302 流浪气球Ⅰ 教学版
class LiuLangQiQiu(arcade.View):""" 视图程序,用于在窗体内展示. """def __init__(self):# 初始化父类的属性super().__init__()self.background_image = None# 鼠标的图片self.couser_pic = None# 游戏背景音乐self.background_sound = arcade.load_sound("../声音文件/忍者神龟背景音乐.mp3")# 在初始化时调用的一些准备工作代码self.set_up()def set_up(self):""" 进行一些游戏准备工作,让游戏主逻辑从这开始,以便于在有需要时重开游戏. """# 背景图片 当作精灵加载进来self.background_image = arcade.Sprite("../图片文件/世界卫星地图.png")# 播放并记录游戏背景音乐self.current_play = self.background_sound.play(volume=0.4, loop=True)# 设置精灵素材中心点的位置self.background_image.center_x = self.window.width // 3self.background_image.center_y = self.window.height // 2# 鼠标图片加载self.couser_pic = arcade.Sprite('../图片文件/瞄准.png', scale=0.2)# 画面渲染绘制def on_draw(self):""" 负责渲染画面 速率: 60帧/秒. """# 清除上一帧绘制的画面self.clear()# 绘制背景图片self.background_image.draw()# 绘制鼠标self.couser_pic.draw()# 控制每次刷新时的变化def on_update(self, delta_time: float):""" 负责逻辑变化 速率: 60帧/秒. """passdef on_mouse_press(self, x, y, button, modifiers):""" 监听鼠标点击事件. """mouse_buttons = {1: "左键", 2: "中键", 4: "右键"}print(f"当前点击的坐标是{x,y}")def on_mouse_release(self, x: float, y: float, button: int, modifiers: int):""" 监听鼠标释放事件. """passdef on_mouse_motion(self, x: float, y: float, dx: float, dy: float):""" 监听鼠标移动事件 """self.couser_pic.center_x = xself.couser_pic.center_y = ydef on_key_press(self,key, modifiers):"""监听键盘按键点击事件modifiers:None = 16,shift= 1(17) ctrl= 2(18) alt= 4(20) """print("---键盘按键按下了:--",key,"--修饰键编号的和是:---", modifiers)def on_key_release(self, key, modifiers):print("---键盘按键抬起了:--",key,"--剩余修饰键编号的和是:---", modifiers)def on_resize(self, width: int, height: int):# 重新设置精灵素材中心点的位置self.background_image.center_x = self.window.width // 2self.background_image.center_y = self.window.height // 2# 重新设置精灵素材宽度和高度self.background_image.width = self.window.widthself.background_image.height = self.window.heightdef main():# 设置窗体的宽、高、名字、是否支持缩放window = arcade.Window(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE, resizable=True)# 设置窗体的 logo 图标import pygletwindow.set_icon(pyglet.image.load('../图片文件/浪淘三千.png'))# 设置鼠标形状cursor = window.get_system_mouse_cursor(window.CURSOR_HAND)window.set_mouse_cursor(cursor)# 实例化定义的某个窗体start_view = LiuLangQiQiu()# 设置当前应该显示哪个窗体window.show_view(start_view)# 保持程序持续运行arcade.run()if __name__ == "__main__":main()
2、构建气球精灵类
"""
本游戏制作了导弹拦截流浪气球的基本代码 有 音效、音乐、精灵、碰撞、轨迹计算 等知识的应用
当基础功能学会以后,可以教大家平面地图文件的绘制和使用 制作更丰富精彩的游戏场景
视频教学地址,会陆续更新 https://space.bilibili.com/455954948
欢迎积极交流更好的改进建议,一起升级游戏 (代码已同步 链接见视频评论区)
"""
import arcade
import os,random# 常量 窗口大小和标题
SCREEN_WIDTH = 1200
SCREEN_HEIGHT = 600
SCREEN_TITLE = "Arcade 游戏教学 流浪气球"class QiQiu(arcade.Sprite):def __init__(self, filename, change_x, change_y, init_x, init_y):super(QiQiu, self).__init__(filename,hit_box_algorithm = "Simple")# 导弹精灵的飞行变化速度self.change_x = change_xself.change_y = change_y# 导弹精灵的初始中心点(init_x,init_y)self.center_x = init_xself.center_y = init_y# 记录气球单次持续垂直移动的距离self.total_change_y = 0# 是否被追踪 一旦被追踪则不再被别的导弹追踪self.is_tracked = False# 初始中心点不在界面左侧,则是从右向左飞行的,因为原始图片都朝向右侧,向左飞行的要水平翻转if self.center_x > 0:self.append_texture((arcade.load_texture(filename, mirrored=True)))# texture_right_forward = arcade.load_texture(filename, mirrored=True)self.set_texture(1)def update(self, window_height=800):self.total_change_y += self.change_y# 当单次垂直移动距离超过50就重新随机选择方向 这个数字通过自己测试调整得到if abs(self.total_change_y) > 50:# 随机改变气球纵向移动方向self.change_y *= random.choice([-1, 1])# 再次重新计算持续垂直移动的距离self.total_change_y = 0if self.center_y > window_height- self.height or self.center_y < self.height:self.change_y = 0self.total_change_y = 0self.center_x += self.change_xself.center_y += self.change_y# arcade_game_202302 流浪气球Ⅰ教学版
class LiuLangQiQiu(arcade.View):""" 视图程序,用于在窗体内展示. """def __init__(self):# 初始化父类的属性super().__init__()self.background_image = None# 气球类self.qi_qiu = Noneself.qi_qiu_list = None# 所有气球文件self.all_qi_qiu = None# 游戏背景音乐self.background_sound = arcade.load_sound("../声音文件/忍者神龟背景音乐.mp3")# 鼠标的图片self.couser_pic = None# 在初始化时调用的一些准备工作代码self.set_up()def set_up(self,init_qi_qiu_num=3):""" 进行一些游戏准备工作,让游戏主逻辑从这开始,以便于在有需要时重开游戏. """# 背景图片 当作精灵加载进来self.background_image = arcade.Sprite("../图片文件/世界卫星地图.png")# 播放并记录游戏背景音乐self.current_play = self.background_sound.play(volume=0.4, loop=True)# 气球精灵列表self.qi_qiu_list = arcade.SpriteList()# 获取文件夹中所有的飞艇图片self.all_qi_qiu = os.listdir("../图片文件/气球飞艇")print(self.all_qi_qiu)# 设置精灵素材中心点的位置self.background_image.center_x = self.window.width // 3self.background_image.center_y = self.window.height // 2# 初始状态时创建自定义个气球(默认3个)self.creat_qi_qiu(init_qi_qiu_num)self.couser_pic = arcade.Sprite('../图片文件/瞄准.png', scale=0.2)def creat_qi_qiu(self, num):"""创建气球"""for i in range(1, num+1):self.qi_qiu = QiQiu(filename=f"../图片文件/气球飞艇/{random.choice(self.all_qi_qiu)}",change_x=random.choice([0.5,0.5,1,2,2]), change_y=random.choice([1,2]),init_x=random.choice([-80, self.window.width + 200]),init_y=random.randint(200, self.window.height - num*50))self.qi_qiu.width = 60self.qi_qiu.height = 40# self.qi_qiu.scale = 0.5if self.qi_qiu.center_x > self.window.width//2:self.qi_qiu.change_x = -self.qi_qiu.change_xself.qi_qiu_list.append(self.qi_qiu)# 画面渲染绘制def on_draw(self):""" 负责渲染画面 速率: 60帧/秒. """# 清除上一帧绘制的画面self.clear()# 绘制背景图片self.background_image.draw()# 绘制气球精灵组self.qi_qiu_list.draw()# 绘制鼠标self.couser_pic.draw()# 控制每次刷新时的变化def on_update(self, delta_time: float):""" 负责逻辑变化 速率: 60帧/秒. """for qi_qiu_id, qi_qiu in enumerate(self.qi_qiu_list):# 气球移动qi_qiu.update(self.window.height)if qi_qiu.center_x not in range(-230, self.window.width+230):# 气球飞出屏幕一定距离后 则消失qi_qiu.remove_from_sprite_lists()# 再次创建气球self.creat_qi_qiu(1)def on_mouse_press(self, x, y, button, modifiers):""" 监听鼠标点击事件. """mouse_buttons = {1: "左键", 2: "中键", 4: "右键"}print(f"当前点击的坐标是{x,y}")def on_mouse_release(self, x: float, y: float, button: int, modifiers: int):""" 监听鼠标释放事件. """passdef on_mouse_motion(self, x: float, y: float, dx: float, dy: float):""" 监听鼠标移动事件 """self.couser_pic.center_x = xself.couser_pic.center_y = ydef on_key_press(self,key, modifiers):"""监听键盘按键点击事件modifiers:None = 16,shift= 1(17) ctrl= 2(18) alt= 4(20) """print("---键盘按键按下了:--",key,"--修饰键编号的和是:---", modifiers)def on_key_release(self, key, modifiers):print("---键盘按键抬起了:--",key,"--剩余修饰键编号的和是:---", modifiers)def on_resize(self, width: int, height: int):# 重新设置精灵素材中心点的位置self.background_image.center_x = self.window.width // 2self.background_image.center_y = self.window.height // 2# 重新设置精灵素材宽度和高度self.background_image.width = self.window.widthself.background_image.height = self.window.heightdef main():# 设置窗体的宽、高、名字、是否支持缩放window = arcade.Window(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE, resizable=True)# 设置窗体的 logo 图标import pygletwindow.set_icon(pyglet.image.load('../图片文件/浪淘三千.png'))# 设置鼠标形状cursor = window.get_system_mouse_cursor(window.CURSOR_HAND)window.set_mouse_cursor(cursor)# 实例化定义的某个窗体start_view = LiuLangQiQiu()# 设置当前应该显示哪个窗体window.show_view(start_view)# 保持程序持续运行arcade.run()if __name__ == "__main__":main()
3、构建导弹精灵类
"""
本游戏制作了导弹拦截流浪气球的基本代码 有 音效、音乐、精灵、碰撞、轨迹计算 等知识的应用
当基础功能学会以后,可以教大家平面地图文件的绘制和使用 制作更丰富精彩的游戏场景
视频教学地址,会陆续更新 https://space.bilibili.com/455954948
欢迎积极交流更好的改进建议,一起升级游戏 (代码已同步 链接见视频评论区)
"""
import arcade
import os,random,math# 常量 窗口大小和标题
SCREEN_WIDTH = 1200
SCREEN_HEIGHT = 600
SCREEN_TITLE = "Arcade 游戏教学 流浪气球"class QiQiu(arcade.Sprite):def __init__(self, filename, change_x, change_y, init_x, init_y):super(QiQiu, self).__init__(filename,hit_box_algorithm = "Simple")# 导弹精灵的飞行变化速度self.change_x = change_xself.change_y = change_y# 导弹精灵的初始中心点(init_x,init_y)self.center_x = init_xself.center_y = init_y# 记录气球单次持续垂直移动的距离self.total_change_y = 0# 是否被追踪 一旦被追踪则不再被别的导弹追踪self.is_tracked = False# 初始中心点不在界面左侧,则是从右向左飞行的,因为原始图片都朝向右侧,向左飞行的要水平翻转if self.center_x > 0:self.append_texture((arcade.load_texture(filename, mirrored=True)))# texture_right_forward = arcade.load_texture(filename, mirrored=True)self.set_texture(1)def update(self, window_height=800):self.total_change_y += self.change_y# 当单次垂直移动距离超过50就重新随机选择方向 这个数字通过自己测试调整得到if abs(self.total_change_y) > 50:# 随机改变气球纵向移动方向self.change_y *= random.choice([-1, 1])# 再次重新计算持续垂直移动的距离self.total_change_y = 0if self.center_y > window_height- self.height or self.center_y < self.height:self.change_y = 0self.total_change_y = 0self.center_x += self.change_xself.center_y += self.change_yclass DaoDan(arcade.Sprite):"""目前是设计成了自动搜寻目标 然后攻击的模式"""def __init__(self, filename, change_x, change_y, init_x, init_y, target_x=None, target_y=None):super(DaoDan, self).__init__(filename,hit_box_algorithm = "Simple")# self.load_animated_gif(filename)# 导弹精灵的飞行变化速度self.change_x = change_xself.change_y = change_yself.change_y_init = change_y# 记录导弹精灵的初始点self.init_x = init_xself.init_y = init_y# 导弹精灵的初始中心点(init_x,init_y)self.center_x = init_xself.center_y = init_y# 要追踪的目标self.target_x = target_xself.target_y = target_y# 导弹是否还在地面上(没有发射)self.is_on_ground = True# 是否正在追踪 初始是未开始追踪self.is_tracking = False# 导弹点火发射音效self.fire_sound = arcade.load_sound("../声音文件/火焰推进器.mp3")# 导弹爆炸音效self.explode_sound = arcade.load_sound("../声音文件/中距离爆炸.mp3")def track_target(self, target_x, target_y, change_angle=0.1):# 当被调用的时候,开始追踪目标气球# 计算导弹和气球飞艇之间的弧度值 Π = 3.14(弧度) = 180°(角度) 向左转角度要加 向右转角度要减target_radians_angle = math.atan2(target_y-self.center_y,target_x-self.center_x)# 将上一步计算出的弧度转换为角度值# 都要减去90 因为导弹的初始方向是向上的,所以有一个默认的90°角,减去后恢复到 0°再计算。target_degree_angle = math.degrees(target_radians_angle)-90# print(f"角度是:{target_degree_angle}")self.center_x += self.change_x if self.center_x < target_x else -self.change_xself.center_y += self.change_y if self.center_y < target_y else -self.change_yself.change_y = 0 if abs(self.center_y - target_y) < 5 else self.change_y_init# print("2222", self.center_y, target_y, self.change_y)if abs(target_degree_angle) in range(0,8):self.angle = 0elif abs(target_degree_angle) in range(172,188):self.angle = 180else:self.angle = target_degree_angle# 定义一个弹道导弹类 继承导弹基类 ,因为追踪逻辑不一样,所以需要重写其追踪方法
class DanDaoDaoDan(DaoDan):# def __init__(self):# super().__init__()def track_target(self):"""开始计算固定飞行轨迹 y = a(x-h)²+k h 和 k 为抛物线的顶点横纵坐标将鼠标点击的(self.target_x,self.target_y)点作为顶点,则有【抛物线函数 y = a(x-self.target_x)²+self.target_y 】将导弹的起点坐标带入上述方程 可以求出 a 值 于是就可以求出抛物线的函数式【抛物线函数 init_y = a(init_x-self.target_x)²+self.target_y 】a = (init_y - self.target_y)/(init_x-self.target_x)²"""# 如果开口向下,a小于0;开口向上,a大于0.a = (self.init_y - self.target_y)/(self.init_x-self.target_x)**2# print(f"a的值是:{a}")self.center_x += self.change_x# 将横坐标带入方程求纵坐标self.center_y = a*(int(self.center_x - self.target_x)**2)+self.target_y# print(f"{self.center_y} = {a}*({int(self.center_x - self.target_x)})**2+{self.target_y}")# 计算导弹和气球飞艇之间的弧度值 Π = 3.14(弧度) = 180°(角度)target_radians_angle = math.atan2(self.target_y-self.center_y,self.target_x-self.center_x)# 将上一步计算出的弧度转换为角度值# 都要减去90 因为导弹的初始方向是向上的,所以有一个默认的90°角,减去后恢复到 0°再计算。target_degree_angle = math.degrees(target_radians_angle)-90if (self.target_x-self.init_x)*(self.target_x-self.center_x) < 0:# 值小于0 的时候说明导弹飞行中已经超过了设定好的最高点target_degree_angle = target_degree_angle + 180# print(f"角度是:{target_degree_angle}")if abs(target_degree_angle) in range(0,8):self.angle = 0elif abs(target_degree_angle) in range(172,188):self.angle = 180else:self.angle = target_degree_angleclass BaoZhaYanWu(arcade.Sprite):def __init__(self):super(BaoZhaYanWu, self).__init__()# 初始中心点不在界面左侧,则是从右向左飞行的,因为原始图片都朝向右侧,向左飞行的要水平翻转all_explore_pic = os.listdir("../图片文件/images11")for pic_name in all_explore_pic:self.append_texture((arcade.load_texture(f"../图片文件/images11/{pic_name}")))# 记下一共有多少纹理图self.textures_num_len = len(all_explore_pic)self.texture_index_now = 0def update(self, texture_index: int = None):# 如果状态是 True 则开始计算绘制位置if self.texture_index_now < self.textures_num_len:self.set_texture(self.texture_index_now)self.texture_index_now += 1return Falseelse:# 收到为True的返回值时 销毁烟雾精灵return True# arcade_game_202302 流浪气球Ⅰ教学版
class LiuLangQiQiu(arcade.View):""" 视图程序,用于在窗体内展示. """def __init__(self):# 初始化父类的属性super().__init__()self.background_image = Noneself.dao_dan = None# 气球类self.qi_qiu = Noneself.qi_qiu_list = None# 导弹类self.dao_dan = Noneself.dao_dan_list = None# 弹道导弹类self.dan_dao_dao_dan = Noneself.dan_dao_dao_dan_list = None# 所有气球文件self.all_qi_qiu = None# 游戏背景音乐self.background_sound = arcade.load_sound("../声音文件/忍者神龟背景音乐.mp3")# 导弹发射车self.dao_dan_che_image = None# 爆炸烟雾self.explode_smoke = Noneself.explode_smoke_list = None# 鼠标的图片self.couser_pic = None# 在初始化时调用的一些准备工作代码self.set_up()def set_up(self,init_qi_qiu_num=3):""" 进行一些游戏准备工作,让游戏主逻辑从这开始,以便于在有需要时重开游戏. """# 背景图片 当作精灵加载进来self.background_image = arcade.Sprite("../图片文件/世界卫星地图.png")# 游戏背景音乐self.current_play = self.background_sound.play(volume=0.4, loop=True)# 气球精灵列表self.qi_qiu_list = arcade.SpriteList()# 导弹精灵列表self.dao_dan_list = arcade.SpriteList()# 弹道导弹精灵列表self.dan_dao_dao_dan_list = arcade.SpriteList()# 爆炸烟雾精灵self.explode_smoke_list = arcade.SpriteList()# 获取文件夹中所有的飞艇图片self.all_qi_qiu = os.listdir("../图片文件/气球飞艇")print(self.all_qi_qiu)# 设置精灵素材中心点的位置self.background_image.center_x = self.window.width // 3self.background_image.center_y = self.window.height // 2# 导弹发射车 在on_resize()里设置绘制位置self.dao_dan_che_image = arcade.Sprite("../图片文件/东风41.png")self.dao_dan_che_image.width = 70self.dao_dan_che_image.height = 70# 初始状态时创建自定义个气球(默认3个)self.creat_qi_qiu(init_qi_qiu_num)self.couser_pic = arcade.Sprite('../图片文件/瞄准.png', scale=0.2)def creat_qi_qiu(self, num):"""创建气球"""for i in range(1, num+1):self.qi_qiu = QiQiu(filename=f"../图片文件/气球飞艇/{random.choice(self.all_qi_qiu)}",change_x=random.choice([0.5,0.5,1,2,2]), change_y=random.choice([1,2]),init_x=random.choice([-80, self.window.width + 200]),init_y=random.randint(200, self.window.height - num*50))self.qi_qiu.width = 60self.qi_qiu.height = 40# self.qi_qiu.scale = 0.5if self.qi_qiu.center_x > self.window.width//2:self.qi_qiu.change_x = -self.qi_qiu.change_xself.qi_qiu_list.append(self.qi_qiu)def creat_zhui_zong_dao_dan(self):dao_dan = DaoDan("../图片文件/导弹.gif", change_x=4, change_y=3,init_x=self.window.width // 3, init_y=self.window.height // 2)self.dao_dan_list.append(dao_dan)dao_dan.fire_sound.play()def creat_dan_dao_dao_dan(self,x,y):# 弹道导弹 如果剩余的弹道弹数量大于0 就接受命令进行创建init_x = self.window.width // 3init_y = self.window.height // 2speed = 1 if abs(x - init_x) < 200 else 3# 如果目标点在右侧 则导弹向右飞行 横坐标变化为正数 否则为负数change_x = speed if x > self.window.width // 3 else - speeddan_dao_dao_dan = DanDaoDaoDan("../图片文件/弹道导弹.png", change_x=change_x, change_y=3,init_x=init_x, init_y=init_y,target_x=x, target_y=y)dan_dao_dao_dan.scale = 0.7self.dan_dao_dao_dan_list.append(dan_dao_dao_dan)dan_dao_dao_dan.fire_sound.play()def creat_yan_wu(self,center_x, center_y):yan_wu = BaoZhaYanWu()yan_wu.center_x = center_xyan_wu.center_y = center_yself.explode_smoke_list.append(yan_wu)# 画面渲染绘制def on_draw(self):""" 负责渲染画面 速率: 60帧/秒. """# 清除上一帧绘制的画面self.clear()# 绘制背景图片self.background_image.draw()# 导弹发射车self.dao_dan_che_image.draw()# 绘制气球精灵组self.qi_qiu_list.draw()# 绘制导弹精灵组self.dao_dan_list.draw()# 绘制弹道导弹精灵组self.dan_dao_dao_dan_list.draw()# 绘制爆炸烟雾self.explode_smoke_list.draw()# 绘制鼠标self.couser_pic.draw()# 控制每次刷新时的变化def on_update(self, delta_time: float):""" 负责逻辑变化 速率: 60帧/秒. """for qi_qiu_id, qi_qiu in enumerate(self.qi_qiu_list):# 处理气球和自动追踪导弹的移动qi_qiu.update(self.window.height)if qi_qiu_id <= len(self.dao_dan_list)-1:dao_dan = self.dao_dan_list[qi_qiu_id]dao_dan.track_target(qi_qiu.center_x, qi_qiu.center_y, change_angle=-0.5)# else:# print("请尽快发射导弹")if qi_qiu.center_x not in range(-230, self.window.width+230):# 气球飞出屏幕一定距离后 则消失qi_qiu.remove_from_sprite_lists()# 再次创建气球self.creat_qi_qiu(1)# 处理按下鼠标发射的弹道导弹for dan_dao_dao_dan in self.dan_dao_dao_dan_list:# 处理气球和弹道导弹的移动dan_dao_dao_dan.track_target()# 如果导弹飞出了屏幕 则销毁if dan_dao_dao_dan.center_x not in range(-230, self.window.width+230):dan_dao_dao_dan.remove_from_sprite_lists()def on_mouse_press(self, x, y, button, modifiers):""" 监听鼠标点击事件. """mouse_buttons = {1: "左键", 2: "中键", 4: "右键"}# print(f"当前点击的坐标是{x,y}")# 创建弹道导弹self.creat_dan_dao_dao_dan(x,y)def on_mouse_release(self, x: float, y: float, button: int, modifiers: int):""" 监听鼠标释放事件. """passdef on_mouse_motion(self, x: float, y: float, dx: float, dy: float):""" 监听鼠标移动事件 """self.couser_pic.center_x = xself.couser_pic.center_y = ydef on_key_press(self,key, modifiers):"""监听键盘按键点击事件modifiers:None = 16,shift= 1(17) ctrl= 2(18) alt= 4(20) """print("---键盘按键按下了:--",key,"--修饰键编号的和是:---", modifiers)if key == arcade.key.SPACE:self.creat_zhui_zong_dao_dan()def on_key_release(self, key, modifiers):print("---键盘按键抬起了:--",key,"--剩余修饰键编号的和是:---", modifiers)def on_resize(self, width: int, height: int):# 重新设置精灵素材中心点的位置self.background_image.center_x = self.window.width // 2self.background_image.center_y = self.window.height // 2# 重新设置精灵素材宽度和高度self.background_image.width = self.window.widthself.background_image.height = self.window.height# 设置导弹车精灵素材中心点的位置self.dao_dan_che_image.center_x = self.window.width // 3 - 30self.dao_dan_che_image.center_y = self.window.height // 2def main():# 设置窗体的宽、高、名字、是否支持缩放window = arcade.Window(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE, resizable=True)# 设置窗体的 logo 图标import pygletwindow.set_icon(pyglet.image.load('../图片文件/浪淘三千.png'))# 设置鼠标形状cursor = window.get_system_mouse_cursor(window.CURSOR_HAND)window.set_mouse_cursor(cursor)# 实例化定义的某个窗体start_view = LiuLangQiQiu()# 设置当前应该显示哪个窗体window.show_view(start_view)# 保持程序持续运行arcade.run()if __name__ == "__main__":main()
4、碰撞检测
"""
本游戏制作了导弹拦截流浪气球的基本代码 有 音效、音乐、精灵、碰撞、轨迹计算 等知识的应用
当基础功能学会以后,可以教大家平面地图文件的绘制和使用 制作更丰富精彩的游戏场景
视频教学地址,会陆续更新 https://space.bilibili.com/455954948
欢迎积极交流更好的改进建议,一起升级游戏 (代码已同步 链接见视频评论区)
"""
import arcade
import os,random,math# 常量 窗口大小和标题
SCREEN_WIDTH = 1200
SCREEN_HEIGHT = 600
SCREEN_TITLE = "Arcade 游戏教学 流浪气球"class QiQiu(arcade.Sprite):def __init__(self, filename, change_x, change_y, init_x, init_y):super(QiQiu, self).__init__(filename,hit_box_algorithm = "Simple")# 导弹精灵的飞行变化速度self.change_x = change_xself.change_y = change_y# 导弹精灵的初始中心点(init_x,init_y)self.center_x = init_xself.center_y = init_y# 记录气球单次持续垂直移动的距离self.total_change_y = 0# 是否被追踪 一旦被追踪则不再被别的导弹追踪self.is_tracked = False# 初始中心点不在界面左侧,则是从右向左飞行的,因为原始图片都朝向右侧,向左飞行的要水平翻转if self.center_x > 0:self.append_texture((arcade.load_texture(filename, mirrored=True)))# texture_right_forward = arcade.load_texture(filename, mirrored=True)self.set_texture(1)def update(self, window_height=800):self.total_change_y += self.change_y# 当单次垂直移动距离超过50就重新随机选择方向 这个数字通过自己测试调整得到if abs(self.total_change_y) > 50:# 随机改变气球纵向移动方向self.change_y *= random.choice([-1, 1])# 再次重新计算持续垂直移动的距离self.total_change_y = 0if self.center_y > window_height- self.height or self.center_y < self.height:self.change_y = 0self.total_change_y = 0self.center_x += self.change_xself.center_y += self.change_yclass DaoDan(arcade.Sprite):"""目前是设计成了自动搜寻目标 然后攻击的模式"""def __init__(self, filename, change_x, change_y, init_x, init_y, target_x=None, target_y=None):super(DaoDan, self).__init__(filename,hit_box_algorithm = "Simple")# self.load_animated_gif(filename)# 导弹精灵的飞行变化速度self.change_x = change_xself.change_y = change_yself.change_y_init = change_y# 记录导弹精灵的初始点self.init_x = init_xself.init_y = init_y# 导弹精灵的初始中心点(init_x,init_y)self.center_x = init_xself.center_y = init_y# 要追踪的目标self.target_x = target_xself.target_y = target_y# 导弹是否还在地面上(没有发射)self.is_on_ground = True# 是否正在追踪 初始是未开始追踪self.is_tracking = False# 导弹点火发射音效self.fire_sound = arcade.load_sound("../声音文件/火焰推进器.mp3")# 导弹爆炸音效self.explode_sound = arcade.load_sound("../声音文件/中距离爆炸.mp3")def track_target(self, target_x, target_y, change_angle=0.1):# 当被调用的时候,开始追踪目标气球# 计算导弹和气球飞艇之间的弧度值 Π = 3.14(弧度) = 180°(角度) 向左转角度要加 向右转角度要减target_radians_angle = math.atan2(target_y-self.center_y,target_x-self.center_x)# 将上一步计算出的弧度转换为角度值# 都要减去90 因为导弹的初始方向是向上的,所以有一个默认的90°角,减去后恢复到 0°再计算。target_degree_angle = math.degrees(target_radians_angle)-90# print(f"角度是:{target_degree_angle}")self.center_x += self.change_x if self.center_x < target_x else -self.change_xself.center_y += self.change_y if self.center_y < target_y else -self.change_yself.change_y = 0 if abs(self.center_y - target_y) < 5 else self.change_y_init# print("2222", self.center_y, target_y, self.change_y)if abs(target_degree_angle) in range(0,8):self.angle = 0elif abs(target_degree_angle) in range(172,188):self.angle = 180else:self.angle = target_degree_angle# 定义一个弹道导弹类 继承导弹基类 ,因为追踪逻辑不一样,所以需要重写其追踪方法
class DanDaoDaoDan(DaoDan):# def __init__(self):# super().__init__()def track_target(self):"""开始计算固定飞行轨迹 y = a(x-h)²+k h 和 k 为抛物线的顶点横纵坐标将鼠标点击的(self.target_x,self.target_y)点作为顶点,则有【抛物线函数 y = a(x-self.target_x)²+self.target_y 】将导弹的起点坐标带入上述方程 可以求出 a 值 于是就可以求出抛物线的函数式【抛物线函数 init_y = a(init_x-self.target_x)²+self.target_y 】a = (init_y - self.target_y)/(init_x-self.target_x)²"""# 如果开口向下,a小于0;开口向上,a大于0.a = (self.init_y - self.target_y)/(self.init_x-self.target_x)**2# print(f"a的值是:{a}")self.center_x += self.change_x# 将横坐标带入方程求纵坐标self.center_y = a*(int(self.center_x - self.target_x)**2)+self.target_y# print(f"{self.center_y} = {a}*({int(self.center_x - self.target_x)})**2+{self.target_y}")# 计算导弹和气球飞艇之间的弧度值 Π = 3.14(弧度) = 180°(角度)target_radians_angle = math.atan2(self.target_y-self.center_y,self.target_x-self.center_x)# 将上一步计算出的弧度转换为角度值# 都要减去90 因为导弹的初始方向是向上的,所以有一个默认的90°角,减去后恢复到 0°再计算。target_degree_angle = math.degrees(target_radians_angle)-90if (self.target_x-self.init_x)*(self.target_x-self.center_x) < 0:# 值小于0 的时候说明导弹飞行中已经超过了设定好的最高点target_degree_angle = target_degree_angle + 180# print(f"角度是:{target_degree_angle}")if abs(target_degree_angle) in range(0,8):self.angle = 0elif abs(target_degree_angle) in range(172,188):self.angle = 180else:self.angle = target_degree_angleclass BaoZhaYanWu(arcade.Sprite):def __init__(self):super(BaoZhaYanWu, self).__init__()# 初始中心点不在界面左侧,则是从右向左飞行的,因为原始图片都朝向右侧,向左飞行的要水平翻转all_explore_pic = os.listdir("../图片文件/images11")for pic_name in all_explore_pic:self.append_texture((arcade.load_texture(f"../图片文件/images11/{pic_name}")))# 记下一共有多少纹理图self.textures_num_len = len(all_explore_pic)self.texture_index_now = 0def update(self, texture_index: int = None):# 如果状态是 True 则开始计算绘制位置if self.texture_index_now < self.textures_num_len:self.set_texture(self.texture_index_now)self.texture_index_now += 1return Falseelse:# 收到为True的返回值时 销毁烟雾精灵return True# arcade_game_202302 流浪气球Ⅰ教学版
class LiuLangQiQiu(arcade.View):""" 视图程序,用于在窗体内展示. """def __init__(self):# 初始化父类的属性super().__init__()self.background_image = Noneself.dao_dan = None# 气球类self.qi_qiu = Noneself.qi_qiu_list = None# 导弹类self.dao_dan = Noneself.dao_dan_list = None# 弹道导弹类self.dan_dao_dao_dan = Noneself.dan_dao_dao_dan_list = None# 所有气球文件self.all_qi_qiu = None# 游戏背景音乐self.background_sound = arcade.load_sound("../声音文件/忍者神龟背景音乐.mp3")# 导弹发射车self.dao_dan_che_image = None# 爆炸烟雾self.explode_smoke = Noneself.explode_smoke_list = None# 为了有节奏的控制游戏刷新时个别元素的刷新速度 设置一个记录时间间隔变量self.interval_time = 0# 鼠标的图片self.couser_pic = None# 在初始化时调用的一些准备工作代码self.set_up()def set_up(self,init_qi_qiu_num=3):""" 进行一些游戏准备工作,让游戏主逻辑从这开始,以便于在有需要时重开游戏. """# 背景图片 当作精灵加载进来self.background_image = arcade.Sprite("../图片文件/世界卫星地图.png")# 游戏背景音乐self.current_play = self.background_sound.play(volume=0.4, loop=True)# 气球精灵列表self.qi_qiu_list = arcade.SpriteList()# 导弹精灵列表self.dao_dan_list = arcade.SpriteList()# 弹道导弹精灵列表self.dan_dao_dao_dan_list = arcade.SpriteList()# 爆炸烟雾精灵self.explode_smoke_list = arcade.SpriteList()# 获取文件夹中所有的飞艇图片self.all_qi_qiu = os.listdir("../图片文件/气球飞艇")print(self.all_qi_qiu)# 设置精灵素材中心点的位置self.background_image.center_x = self.window.width // 3self.background_image.center_y = self.window.height // 2# 导弹发射车 在on_resize()里设置绘制位置self.dao_dan_che_image = arcade.Sprite("../图片文件/东风41.png")self.dao_dan_che_image.width = 70self.dao_dan_che_image.height = 70# 初始状态时创建自定义个气球(默认3个)self.creat_qi_qiu(init_qi_qiu_num)self.couser_pic = arcade.Sprite('../图片文件/瞄准.png', scale=0.2)def creat_qi_qiu(self, num):"""创建气球"""for i in range(1, num+1):self.qi_qiu = QiQiu(filename=f"../图片文件/气球飞艇/{random.choice(self.all_qi_qiu)}",change_x=random.choice([0.5,0.5,1,2,2]), change_y=random.choice([1,2]),init_x=random.choice([-80, self.window.width + 200]),init_y=random.randint(200, self.window.height - num*50))self.qi_qiu.width = 60self.qi_qiu.height = 40# self.qi_qiu.scale = 0.5if self.qi_qiu.center_x > self.window.width//2:self.qi_qiu.change_x = -self.qi_qiu.change_xself.qi_qiu_list.append(self.qi_qiu)def creat_zhui_zong_dao_dan(self):dao_dan = DaoDan("../图片文件/导弹.gif", change_x=4, change_y=3,init_x=self.window.width // 3, init_y=self.window.height // 2)self.dao_dan_list.append(dao_dan)dao_dan.fire_sound.play()def creat_dan_dao_dao_dan(self,x,y):# 弹道导弹 如果剩余的弹道弹数量大于0 就接受命令进行创建init_x = self.window.width // 3init_y = self.window.height // 2speed = 1 if abs(x - init_x) < 200 else 3# 如果目标点在右侧 则导弹向右飞行 横坐标变化为正数 否则为负数change_x = speed if x > self.window.width // 3 else - speeddan_dao_dao_dan = DanDaoDaoDan("../图片文件/弹道导弹.png", change_x=change_x, change_y=3,init_x=init_x, init_y=init_y,target_x=x, target_y=y)dan_dao_dao_dan.scale = 0.7self.dan_dao_dao_dan_list.append(dan_dao_dao_dan)dan_dao_dao_dan.fire_sound.play()def creat_yan_wu(self,center_x, center_y):yan_wu = BaoZhaYanWu()yan_wu.center_x = center_xyan_wu.center_y = center_yself.explode_smoke_list.append(yan_wu)# 画面渲染绘制def on_draw(self):""" 负责渲染画面 速率: 60帧/秒. """# 清除上一帧绘制的画面self.clear()# 绘制背景图片self.background_image.draw()# 导弹发射车self.dao_dan_che_image.draw()# 绘制气球精灵组self.qi_qiu_list.draw()# 绘制导弹精灵组self.dao_dan_list.draw()# 绘制弹道导弹精灵组self.dan_dao_dao_dan_list.draw()# 绘制爆炸烟雾self.explode_smoke_list.draw()# 绘制鼠标self.couser_pic.draw()# 控制每次刷新时的变化def on_update(self, delta_time: float):""" 负责逻辑变化 速率: 60帧/秒. """for qi_qiu_id, qi_qiu in enumerate(self.qi_qiu_list):# 处理气球和自动追踪导弹的碰撞及逻辑qi_qiu.update(self.window.height)if qi_qiu_id <= len(self.dao_dan_list)-1:dao_dan = self.dao_dan_list[qi_qiu_id]dao_dan.track_target(qi_qiu.center_x, qi_qiu.center_y, change_angle=-0.5)# else:# print("请尽快发射导弹")collision = arcade.check_for_collision_with_list(qi_qiu, self.dao_dan_list)if len(collision) > 0:print(f"发生碰撞了,相撞的{qi_qiu_id}号导弹和气球都被移除")# 移除碰到的气球qi_qiu.remove_from_sprite_lists()# 创建气球self.creat_qi_qiu(1)# 移除碰到的追踪导弹for collision_obj in collision:collision_obj.remove_from_sprite_lists()collision_obj.explode_sound.play()# 创建烟雾 坐标为所碰撞气球的坐标self.creat_yan_wu(qi_qiu.center_x,qi_qiu.center_y)if qi_qiu.center_x not in range(-230, self.window.width+230):# 气球飞出屏幕一定距离后 则消失qi_qiu.remove_from_sprite_lists()# 再次创建气球self.creat_qi_qiu(1)# 处理按下鼠标发射的弹道导弹for dan_dao_dao_dan in self.dan_dao_dao_dan_list:# 处理气球和弹道导弹的碰撞及逻辑dan_dao_dao_dan.track_target()collision2 = arcade.check_for_collision_with_list(dan_dao_dao_dan, self.qi_qiu_list)for collision_obj2 in collision2:collision_obj2.remove_from_sprite_lists()dan_dao_dao_dan.remove_from_sprite_lists()dan_dao_dao_dan.explode_sound.play()# 创建气球self.creat_qi_qiu(1)# 创建烟雾self.creat_yan_wu(collision_obj2.center_x, collision_obj2.center_y)# 如果导弹飞出了屏幕 则销毁if dan_dao_dao_dan.center_x not in range(-230, self.window.width+230):dan_dao_dao_dan.remove_from_sprite_lists()# 烟雾的绘制for smoke in self.explode_smoke_list:self.interval_time += delta_timeif self.interval_time > 0.08:res = smoke.update()self.interval_time = 0if res:smoke.remove_from_sprite_lists()def on_mouse_press(self, x, y, button, modifiers):""" 监听鼠标点击事件. """mouse_buttons = {1: "左键", 2: "中键", 4: "右键"}# print(f"当前点击的坐标是{x,y}")# 创建弹道导弹self.creat_dan_dao_dao_dan(x,y)def on_mouse_release(self, x: float, y: float, button: int, modifiers: int):""" 监听鼠标释放事件. """passdef on_mouse_motion(self, x: float, y: float, dx: float, dy: float):""" 监听鼠标移动事件 """self.couser_pic.center_x = xself.couser_pic.center_y = ydef on_key_press(self,key, modifiers):"""监听键盘按键点击事件modifiers:None = 16,shift= 1(17) ctrl= 2(18) alt= 4(20) """print("---键盘按键按下了:--",key,"--修饰键编号的和是:---", modifiers)if key == arcade.key.SPACE:self.creat_zhui_zong_dao_dan()def on_key_release(self, key, modifiers):print("---键盘按键抬起了:--",key,"--剩余修饰键编号的和是:---", modifiers)def on_resize(self, width: int, height: int):# 重新设置精灵素材中心点的位置self.background_image.center_x = self.window.width // 2self.background_image.center_y = self.window.height // 2# 重新设置精灵素材宽度和高度self.background_image.width = self.window.widthself.background_image.height = self.window.height# 设置导弹车精灵素材中心点的位置self.dao_dan_che_image.center_x = self.window.width // 3 - 30self.dao_dan_che_image.center_y = self.window.height // 2def main():# 设置窗体的宽、高、名字、是否支持缩放window = arcade.Window(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE, resizable=True)# 设置窗体的 logo 图标import pygletwindow.set_icon(pyglet.image.load('../图片文件/浪淘三千.png'))# 设置鼠标形状cursor = window.get_system_mouse_cursor(window.CURSOR_HAND)window.set_mouse_cursor(cursor)# 实例化定义的某个窗体start_view = LiuLangQiQiu()# 设置当前应该显示哪个窗体window.show_view(start_view)# 保持程序持续运行arcade.run()if __name__ == "__main__":main()
5、构建游戏信息类 (最终完整代码)
"""
本游戏制作了导弹拦截流浪气球的基本代码 有 音效、音乐、精灵、碰撞、轨迹计算 等知识的应用
当基础功能学会以后,可以教大家平面地图文件的绘制和使用 制作更丰富精彩的游戏场景
视频教学地址,会陆续更新 https://space.bilibili.com/455954948
欢迎积极交流更好的改进建议,一起升级游戏 (代码已同步 链接见视频评论区)
"""
import arcade
import os,random,math# 常量 窗口大小和标题
SCREEN_WIDTH = 1200
SCREEN_HEIGHT = 600
SCREEN_TITLE = "Arcade 游戏教学 流浪气球"class QiQiu(arcade.Sprite):def __init__(self, filename, change_x, change_y, init_x, init_y):super(QiQiu, self).__init__(filename,hit_box_algorithm = "Simple")# 导弹精灵的飞行变化速度self.change_x = change_xself.change_y = change_y# 导弹精灵的初始中心点(init_x,init_y)self.center_x = init_xself.center_y = init_y# 记录气球单次持续垂直移动的距离self.total_change_y = 0# 是否被追踪 一旦被追踪则不再被别的导弹追踪self.is_tracked = False# 初始中心点不在界面左侧,则是从右向左飞行的,因为原始图片都朝向右侧,向左飞行的要水平翻转if self.center_x > 0:self.append_texture((arcade.load_texture(filename, mirrored=True)))# texture_right_forward = arcade.load_texture(filename, mirrored=True)self.set_texture(1)def update(self, window_height=800):self.total_change_y += self.change_y# 当单次垂直移动距离超过50就重新随机选择方向 这个数字通过自己测试调整得到if abs(self.total_change_y) > 50:# 随机改变气球纵向移动方向self.change_y *= random.choice([-1, 1])# 再次重新计算持续垂直移动的距离self.total_change_y = 0if self.center_y > window_height- self.height or self.center_y < self.height:self.change_y = 0self.total_change_y = 0self.center_x += self.change_xself.center_y += self.change_yclass DaoDan(arcade.Sprite):"""目前是设计成了自动搜寻目标 然后攻击的模式"""def __init__(self, filename, change_x, change_y, init_x, init_y, target_x=None, target_y=None):super(DaoDan, self).__init__(filename,hit_box_algorithm = "Simple")# self.load_animated_gif(filename)# 导弹精灵的飞行变化速度self.change_x = change_xself.change_y = change_yself.change_y_init = change_y# 记录导弹精灵的初始点self.init_x = init_xself.init_y = init_y# 导弹精灵的初始中心点(init_x,init_y)self.center_x = init_xself.center_y = init_y# 要追踪的目标self.target_x = target_xself.target_y = target_y# 导弹是否还在地面上(没有发射)self.is_on_ground = True# 是否正在追踪 初始是未开始追踪self.is_tracking = False# 导弹点火发射音效self.fire_sound = arcade.load_sound("../声音文件/火焰推进器.mp3")# 导弹爆炸音效self.explode_sound = arcade.load_sound("../声音文件/中距离爆炸.mp3")def track_target(self, target_x, target_y, change_angle=0.1):# 当被调用的时候,开始追踪目标气球# 计算导弹和气球飞艇之间的弧度值 Π = 3.14(弧度) = 180°(角度) 向左转角度要加 向右转角度要减target_radians_angle = math.atan2(target_y-self.center_y,target_x-self.center_x)# 将上一步计算出的弧度转换为角度值# 都要减去90 因为导弹的初始方向是向上的,所以有一个默认的90°角,减去后恢复到 0°再计算。target_degree_angle = math.degrees(target_radians_angle)-90# print(f"角度是:{target_degree_angle}")self.center_x += self.change_x if self.center_x < target_x else -self.change_xself.center_y += self.change_y if self.center_y < target_y else -self.change_yself.change_y = 0 if abs(self.center_y - target_y) < 5 else self.change_y_init# print("2222", self.center_y, target_y, self.change_y)if abs(target_degree_angle) in range(0,8):self.angle = 0elif abs(target_degree_angle) in range(172,188):self.angle = 180else:self.angle = target_degree_angle# 定义一个弹道导弹类 继承导弹基类 ,因为追踪逻辑不一样,所以需要重写其追踪方法
class DanDaoDaoDan(DaoDan):# def __init__(self):# super().__init__()def track_target(self):"""开始计算固定飞行轨迹 y = a(x-h)²+k h 和 k 为抛物线的顶点横纵坐标将鼠标点击的(self.target_x,self.target_y)点作为顶点,则有【抛物线函数 y = a(x-self.target_x)²+self.target_y 】将导弹的起点坐标带入上述方程 可以求出 a 值 于是就可以求出抛物线的函数式【抛物线函数 init_y = a(init_x-self.target_x)²+self.target_y 】a = (init_y - self.target_y)/(init_x-self.target_x)²"""# 如果开口向下,a小于0;开口向上,a大于0.a = (self.init_y - self.target_y)/(self.init_x-self.target_x)**2# print(f"a的值是:{a}")self.center_x += self.change_x# 将横坐标带入方程求纵坐标self.center_y = a*(int(self.center_x - self.target_x)**2)+self.target_y# print(f"{self.center_y} = {a}*({int(self.center_x - self.target_x)})**2+{self.target_y}")# 计算导弹和气球飞艇之间的弧度值 Π = 3.14(弧度) = 180°(角度)target_radians_angle = math.atan2(self.target_y-self.center_y,self.target_x-self.center_x)# 将上一步计算出的弧度转换为角度值# 都要减去90 因为导弹的初始方向是向上的,所以有一个默认的90°角,减去后恢复到 0°再计算。target_degree_angle = math.degrees(target_radians_angle)-90if (self.target_x-self.init_x)*(self.target_x-self.center_x) < 0:# 值小于0 的时候说明导弹飞行中已经超过了设定好的最高点target_degree_angle = target_degree_angle + 180# print(f"角度是:{target_degree_angle}")if abs(target_degree_angle) in range(0,8):self.angle = 0elif abs(target_degree_angle) in range(172,188):self.angle = 180else:self.angle = target_degree_angleclass BaoZhaYanWu(arcade.Sprite):def __init__(self):super(BaoZhaYanWu, self).__init__()# 初始中心点不在界面左侧,则是从右向左飞行的,因为原始图片都朝向右侧,向左飞行的要水平翻转all_explore_pic = os.listdir("../图片文件/images11")for pic_name in all_explore_pic:self.append_texture((arcade.load_texture(f"../图片文件/images11/{pic_name}")))# 记下一共有多少纹理图self.textures_num_len = len(all_explore_pic)self.texture_index_now = 0def update(self, texture_index: int = None):# 如果状态是 True 则开始计算绘制位置if self.texture_index_now < self.textures_num_len:self.set_texture(self.texture_index_now)self.texture_index_now += 1return Falseelse:# 收到为True的返回值时 销毁烟雾精灵return Trueclass InfoPanel:"""信息板 以后可以优化为游戏公共信息类"""def __init__(self):super(InfoPanel, self).__init__()self.game_info = {}self.set_up()def set_up(self,init_qi_qiu_num=0,game_limit_time=10,zhui_zong_dao_dan_num=10,dan_dao_dao_dan_num=20,difficulty_level=2):self.game_info.clear()self.game_info["game_status"] = True # 游戏状态(能玩和不能玩)self.game_info["game_pause"] = False # 游戏暂停状态self.game_info["player_score"] = 0 # 玩家分数self.game_info["player_use_time"] = 0 # 玩家用时self.game_info["game_limit_time"] = game_limit_time # 游戏限时 单位秒self.game_info["difficulty_level"] = difficulty_level # 游戏难度(平均几个弹道导弹 VS 一个气球)self.game_info["surplus_dan_dao_dao_dan_num"] = dan_dao_dao_dan_num # surplus:剩余 弹道导弹数量self.game_info["surplus_zhui_zong_dao_dan_num"] = zhui_zong_dao_dan_num # 剩余追踪弹的数量# 得分要求为 追踪导弹的数量个数 加上 弹道导弹数量个数的一半self.game_info["player_target_score"] = zhui_zong_dao_dan_num + dan_dao_dao_dan_num//max(1,difficulty_level) # 玩家目标分数self.game_info["init_qi_qiu_num"] = init_qi_qiu_num # 初始气球数量设置为self.game_info["surplus_qi_qiu_num"] = 0 # 剩余气球数量self.game_info["all_qi_qiu_num"] = 0 # 全部出现过的气球数量self.game_info["zhui_zong_dao_dan_pic"] = arcade.Sprite("../图片文件/导弹.gif")self.game_info["dan_dao_dao_dan_pic"] = arcade.Sprite("../图片文件/弹道导弹.png")# 游戏胜利图片self.game_info["game_win_pic"] = arcade.Sprite("../图片文件/win.png")# 游戏失败图片self.game_info["game_over_pic"] = arcade.Sprite("../图片文件/game_over.png")# 游戏暂停图片self.game_info["game_pause_pic"] = arcade.Sprite("../图片文件/游戏暂停.png")# 游戏胜利音乐self.game_info["game_win_sound"] = arcade.sound.load_sound("../声音文件/成功.mp3")# 游戏失败音乐self.game_info["game_over_sound_1"] = arcade.sound.load_sound("../声音文件/马里奥游戏结束.mp3")# 游戏失败嘲讽self.game_info["game_over_sound_2"] = arcade.sound.load_sound("../声音文件/马里奥哈哈嘲讽.mp3")# 游戏暂停音效self.game_info["game_pause_sound"] = arcade.sound.load_sound("../声音文件/暂停.mp3")# # 游戏暂停后重新开始音效# self.game_info["game_continue_sound"] = arcade.sound.load_sound("../声音文件/暂停后开始.mp3")def draw_game_info(self,x,y):# x: 屏幕宽度 y:屏幕高度font_size = 20# 第一行# 描述游戏信息的字符串self.game_info["game_info_txt"] = f"难度:{self.game_info['difficulty_level']} vs 1" \f" 得分:{self.game_info['player_score']} /{self.game_info['player_target_score']}"\f" 命中率:{self.game_info['player_score']}/{self.game_info['all_qi_qiu_num']}"\f" 计时:{self.game_info['player_use_time']}/{self.game_info['game_limit_time']}"arcade.Text(self.game_info["game_info_txt"], 10, y - font_size*2,color=arcade.color.SAE, font_size=font_size, width=x, font_name="站酷快乐体2016修订版",bold=True, align="left", anchor_x="left", multiline=False).draw()# 第二行# 绘制追踪导弹信息self.game_info["zhui_zong_dao_dan_pic"].width = font_size*2self.game_info["zhui_zong_dao_dan_pic"].height = font_size*2self.game_info["zhui_zong_dao_dan_pic"].center_x = 10 + font_size // 2self.game_info["zhui_zong_dao_dan_pic"].center_y = y - font_size * 3.5self.game_info["zhui_zong_dao_dan_pic"].draw()arcade.Text(f"X {self.game_info['surplus_zhui_zong_dao_dan_num']}", 10 + font_size*2 , y - font_size *4,color=arcade.color.SAE, font_size=font_size, width=x, font_name="站酷快乐体2016修订版",bold=True, align="left", anchor_x="left", multiline=True).draw()# 绘制弹道导弹信息 (第二行 追踪导弹后面的内容)self.game_info["dan_dao_dao_dan_pic"].width = font_size*2self.game_info["dan_dao_dao_dan_pic"].height = font_size*2self.game_info["dan_dao_dao_dan_pic"].center_x = 10 + font_size * 2 + 5*font_sizeself.game_info["dan_dao_dao_dan_pic"].center_y = y - font_size * 3.5self.game_info["dan_dao_dao_dan_pic"].draw()arcade.Text(f"X {self.game_info['surplus_dan_dao_dao_dan_num']}", 10 + font_size * 2 + 6*font_size, y - font_size *4,color=arcade.color.SAE, font_size=font_size, width=x, font_name="站酷快乐体2016修订版",bold=True, align="left", anchor_x="left", multiline=True).draw()# 游戏失败时持续执行if not self.game_info["game_status"] and self.game_info["player_use_time"] >= self.game_info["game_limit_time"]:self.game_info["game_over_pic"].center_x = x // 2self.game_info["game_over_pic"].center_y = y // 2self.game_info["game_over_pic"].draw()arcade.Text(f"~~按右侧 SHIFT 键重新开始~~", x//2,y//2 - 200,color=arcade.color.WHITE, font_size=font_size*2, width=x, font_name="站酷快乐体2016修订版",bold=True, align="left", anchor_x="center", multiline=False).draw()# 游戏胜利时持续执行if not self.game_info["game_status"] and (self.game_info["player_score"] >= self.game_info['player_target_score']):self.game_info["game_win_pic"].center_x = x // 2self.game_info["game_win_pic"].center_y = y // 2self.game_info["game_win_pic"].draw()# 触发游戏暂停时持续执行if self.game_info["game_status"] and self.game_info["game_pause"]:self.game_info["game_pause_pic"].center_x = x // 2self.game_info["game_pause_pic"].center_y = y // 2self.game_info["game_pause_pic"].draw()arcade.Text(f"~~按 Enter 键继续~~", x // 2, y // 2 - 200,color=arcade.color.WHITE, font_size=font_size*2, width=x, font_name="站酷快乐体2016修订版",bold=True, align="left", anchor_x="center", multiline=False).draw()def check_game_status(self, bgm):# 游戏失败时执行if self.game_info["game_status"] and self.game_info["player_use_time"] >= self.game_info["game_limit_time"]:self.game_info["game_status"] = Falsearcade.stop_sound(bgm)self.game_info["game_over_sound_1"].play()self.game_info["game_over_sound_2"].play()# 游戏胜利时执行if self.game_info["game_status"] and (self.game_info["player_score"] >= self.game_info['player_target_score']):self.game_info["game_status"] = Falsearcade.stop_sound(bgm)self.game_info["game_win_sound"].play()# 游戏暂停时执行if self.game_info["game_pause"]:return Falsereturn self.game_info["game_status"]# arcade_game_202302 流浪气球Ⅰ
class LiuLangQiQiu(arcade.View):""" 视图程序,用于在窗体内展示. """def __init__(self):# 初始化父类的属性super().__init__()self.background_image = Noneself.dao_dan = None# 气球类self.qi_qiu = Noneself.qi_qiu_list = None# 导弹类self.dao_dan = Noneself.dao_dan_list = None# 弹道导弹类self.dan_dao_dao_dan = Noneself.dan_dao_dao_dan_list = None# 所有气球文件self.all_qi_qiu = None# 游戏背景音乐self.background_sound = arcade.load_sound("../声音文件/忍者神龟背景音乐.mp3")# 导弹发射车self.dao_dan_che_image = None# 爆炸烟雾self.explode_smoke = Noneself.explode_smoke_list = None# 为了有节奏的控制游戏刷新时个别元素的刷新速度 设置一个记录时间间隔变量self.interval_time = 0# 游戏信息面板self.info_panel = None# 鼠标的图片self.couser_pic = None# 在初始化时调用的一些准备工作代码self.set_up()# 有规律的调用time_clock函数,每次调用间隔设置为1秒arcade.schedule(self.time_clock, 1)def set_up(self,init_qi_qiu_num = 5,zhui_zong_dao_dan_num = 20,dan_dao_dao_dan_num=30,difficulty_level=3):"difficulty_level:难度等级 代表平均至少用几个弹道导弹就击中一个气球 ,会以此来计算玩家的目标分数 数字越大越简单 最小是1"""" 进行一些游戏准备工作,让游戏主逻辑从这开始,以便于在有需要时重开游戏. """# 实例化游戏信息类self.info_panel = InfoPanel()self.info_panel.set_up(init_qi_qiu_num=init_qi_qiu_num,game_limit_time=zhui_zong_dao_dan_num * 1 + dan_dao_dao_dan_num*2,zhui_zong_dao_dan_num=zhui_zong_dao_dan_num, dan_dao_dao_dan_num=dan_dao_dao_dan_num,difficulty_level=difficulty_level)# 游戏背景音乐self.current_play = self.background_sound.play(volume=0.4, loop=True)# 气球精灵列表self.qi_qiu_list = arcade.SpriteList()# 导弹精灵列表self.dao_dan_list = arcade.SpriteList()# 弹道导弹精灵列表self.dan_dao_dao_dan_list = arcade.SpriteList()# 爆炸烟雾精灵self.explode_smoke_list = arcade.SpriteList()# 获取文件夹中所有的飞艇图片self.all_qi_qiu = os.listdir("../图片文件/气球飞艇")print(self.all_qi_qiu)# 背景图片 当作精灵加载进来self.background_image = arcade.Sprite("../图片文件/世界卫星地图.png")# 设置精灵素材中心点的位置self.background_image.center_x = self.window.width // 3self.background_image.center_y = self.window.height // 2# 导弹发射车 在on_resize()里设置绘制位置self.dao_dan_che_image = arcade.Sprite("../图片文件/东风41.png")self.dao_dan_che_image.width = 70self.dao_dan_che_image.height = 70# 初始状态时创建自定义个气球(默认3个)self.creat_qi_qiu(init_qi_qiu_num)self.couser_pic = arcade.Sprite('../图片文件/瞄准.png', scale=0.2)# 括号里的这个参数必须写,他是一个时间间隔,代表上次调用 到本次调用之间的时间差 不严格等于我们设置的1秒def time_clock(self, delta_time):# print(delta_time)# 因为我们要更改TIME_CLOCK的值,所以使用global 让函数可以改变这个全局变量if self.info_panel.game_info["game_status"] and not self.info_panel.game_info["game_pause"]:self.info_panel.game_info["player_use_time"] += 1def creat_qi_qiu(self, num):"""创建气球"""for i in range(1, num+1):self.qi_qiu = QiQiu(filename=f"../图片文件/气球飞艇/{random.choice(self.all_qi_qiu)}",change_x=random.choice([0.5,0.5,1,2,2]), change_y=random.choice([1,2]),init_x=random.choice([-80, self.window.width + 200]),init_y=random.randint(200, self.window.height - num*50))self.qi_qiu.width = 60self.qi_qiu.height = 40# self.qi_qiu.scale = 0.5if self.qi_qiu.center_x > self.window.width//2:self.qi_qiu.change_x = -self.qi_qiu.change_xself.qi_qiu_list.append(self.qi_qiu)# 每次创建过气球后 都将统计到游戏信息面板中self.info_panel.game_info["all_qi_qiu_num"] += numdef creat_zhui_zong_dao_dan(self):# 追踪导弹 如果剩余的追踪弹数量大于0 就接受命令进行创建if self.info_panel.game_info["surplus_zhui_zong_dao_dan_num"] > 0:dao_dan = DaoDan("../图片文件/导弹.gif", change_x=4, change_y=3,init_x=self.window.width // 3, init_y=self.window.height // 2)self.dao_dan_list.append(dao_dan)dao_dan.fire_sound.play()self.info_panel.game_info["surplus_zhui_zong_dao_dan_num"] -= 1def creat_dan_dao_dao_dan(self,x,y):# 弹道导弹 如果剩余的弹道弹数量大于0 就接受命令进行创建if self.info_panel.game_info["surplus_dan_dao_dao_dan_num"] > 0:init_x = self.window.width // 3init_y = self.window.height // 2speed = 1 if abs(x - init_x) < 200 else 3# 如果目标点在右侧 则导弹向右飞行 横坐标变化为正数 否则为负数change_x = speed if x > self.window.width // 3 else - speeddan_dao_dao_dan = DanDaoDaoDan("../图片文件/弹道导弹.png", change_x=change_x, change_y=3,init_x=init_x, init_y=init_y,target_x=x, target_y=y)dan_dao_dao_dan.scale = 0.7self.dan_dao_dao_dan_list.append(dan_dao_dao_dan)dan_dao_dao_dan.fire_sound.play()# 创建完毕后 剩余弹道导弹数量 -1self.info_panel.game_info["surplus_dan_dao_dao_dan_num"] -= 1def creat_yan_wu(self,center_x, center_y):yan_wu = BaoZhaYanWu()yan_wu.center_x = center_xyan_wu.center_y = center_yself.explode_smoke_list.append(yan_wu)# 画面渲染绘制def on_draw(self):""" 负责渲染画面 速率: 60帧/秒. """# 清除上一帧绘制的画面self.clear()# 绘制背景图片self.background_image.draw()# 导弹发射车self.dao_dan_che_image.draw()# 绘制气球精灵组self.qi_qiu_list.draw()# 绘制导弹精灵组self.dao_dan_list.draw()# 绘制弹道导弹精灵组self.dan_dao_dao_dan_list.draw()# 绘制爆炸烟雾self.explode_smoke_list.draw()# 绘制游戏信息self.info_panel.draw_game_info(self.window.width, self.window.height)# 绘制鼠标self.couser_pic.draw()# 控制每次刷新时的变化def on_update(self, delta_time: float):""" 负责逻辑变化 速率: 60帧/秒. """if self.info_panel.check_game_status(self.current_play):# 如果检测游戏的状态为True 则继续刷新 否则不再执行后续逻辑for qi_qiu_id, qi_qiu in enumerate(self.qi_qiu_list):# 处理气球和自动追踪导弹的碰撞及逻辑qi_qiu.update(self.window.height)if qi_qiu_id <= len(self.dao_dan_list)-1:dao_dan = self.dao_dan_list[qi_qiu_id]dao_dan.track_target(qi_qiu.center_x, qi_qiu.center_y, change_angle=-0.5)# else:# print("请尽快发射导弹")collision = arcade.check_for_collision_with_list(qi_qiu, self.dao_dan_list)if len(collision) > 0:print(f"发生碰撞了,相撞的{qi_qiu_id}号导弹和气球都被移除")# 移除碰到的气球qi_qiu.remove_from_sprite_lists()# 剩余气球数量 -1self.info_panel.game_info["surplus_qi_qiu_num"] -= 1# 玩家分数 +1self.info_panel.game_info["player_score"] += 1# 创建气球self.creat_qi_qiu(1)# 移除碰到的追踪导弹for collision_obj in collision:collision_obj.remove_from_sprite_lists()collision_obj.explode_sound.play()# 追踪导弹数量-1 因为在创建时候就减去了1 所以这里不再减# self.info_panel.game_info["surplus_zhui_zong_dao_dan_num"] -= 1# 创建烟雾 坐标为所碰撞气球的坐标self.creat_yan_wu(qi_qiu.center_x,qi_qiu.center_y)if qi_qiu.center_x not in range(-230, self.window.width+230):# 气球飞出屏幕一定距离后 则消失qi_qiu.remove_from_sprite_lists()# 剩余气球数量 -1self.info_panel.game_info["surplus_qi_qiu_num"] -= 1# 再次创建气球self.creat_qi_qiu(1)# 处理按下鼠标发射的弹道导弹for dan_dao_dao_dan in self.dan_dao_dao_dan_list:# 处理气球和弹道导弹的碰撞及逻辑dan_dao_dao_dan.track_target()collision2 = arcade.check_for_collision_with_list(dan_dao_dao_dan, self.qi_qiu_list)for collision_obj2 in collision2:collision_obj2.remove_from_sprite_lists()dan_dao_dao_dan.remove_from_sprite_lists()dan_dao_dao_dan.explode_sound.play()# 剩余气球数量 -1self.info_panel.game_info["surplus_qi_qiu_num"] -= 1# 玩家分数 +1self.info_panel.game_info["player_score"] += 1# 创建气球self.creat_qi_qiu(1)# 创建烟雾self.creat_yan_wu(collision_obj2.center_x, collision_obj2.center_y)# 如果导弹飞出了屏幕 则销毁if dan_dao_dao_dan.center_x not in range(-230, self.window.width+230):dan_dao_dao_dan.remove_from_sprite_lists()# 将原来创建气球的时机改为每当有一个气球消失 就创建一个 下面代码不再使用# if len(self.qi_qiu_list) <= 3:# self.creat_qi_qiu(3)for smoke in self.explode_smoke_list:self.interval_time += delta_timeif self.interval_time > 0.08:res = smoke.update()self.interval_time = 0if res:smoke.remove_from_sprite_lists()def on_mouse_press(self, x, y, button, modifiers):""" 监听鼠标点击事件. """mouse_buttons = {1: "左键", 2: "中键", 4: "右键"}# print(f"当前点击的坐标是{x,y}")if self.info_panel.game_info["game_status"] and not self.info_panel.game_info["game_pause"]:# 创建弹道导弹self.creat_dan_dao_dao_dan(x,y)def on_mouse_release(self, x: float, y: float, button: int, modifiers: int):""" 监听鼠标释放事件. """passdef on_mouse_motion(self, x: float, y: float, dx: float, dy: float):""" 监听鼠标移动事件 """self.couser_pic.center_x = xself.couser_pic.center_y = ydef on_key_press(self,key, modifiers):"""监听键盘按键点击事件modifiers:None = 16,shift= 1(17) ctrl= 2(18) alt= 4(20) """print("---键盘按键按下了:--",key,"--修饰键编号的和是:---", modifiers)if key == arcade.key.SPACE and self.info_panel.game_info["game_status"] \and not self.info_panel.game_info["game_pause"]:self.creat_zhui_zong_dao_dan()if key == arcade.key.RSHIFT and not self.info_panel.game_info["game_status"]:# 让游戏重新开始 并且重置屏幕大小为上一次的大小self.set_up()self.on_resize(self.window.width,self.window.height)def on_key_release(self, key, modifiers):print("---键盘按键抬起了:--",key,"--剩余修饰键编号的和是:---", modifiers)print("---键盘按下之前:--",self.info_panel.game_info["game_pause"])if key == arcade.key.ENTER and self.info_panel.game_info["game_status"]:self.info_panel.game_info["game_pause"] = not self.info_panel.game_info["game_pause"]self.info_panel.game_info["game_pause_sound"].play()print("---键盘按下之后:--", self.info_panel.game_info["game_pause"])def on_resize(self, width: int, height: int):# 重新设置精灵素材中心点的位置self.background_image.center_x = self.window.width // 2self.background_image.center_y = self.window.height // 2# 重新设置精灵素材宽度和高度self.background_image.width = self.window.widthself.background_image.height = self.window.height# 设置导弹车精灵素材中心点的位置self.dao_dan_che_image.center_x = self.window.width // 3 - 30self.dao_dan_che_image.center_y = self.window.height // 2for jing_ling in (self.dan_dao_dao_dan_list,self.dao_dan_list,self.qi_qiu_list):# 界面在玩耍时侯如果缩放,会使导弹和气球位置发生相对于地图的偏移passdef main():# 设置窗体的宽、高、名字、是否支持缩放window = arcade.Window(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE, resizable=True)# 设置窗体的 logo 图标import pygletwindow.set_icon(pyglet.image.load('../图片文件/浪淘三千.png'))# 设置鼠标形状cursor = window.get_system_mouse_cursor(window.CURSOR_HAND)window.set_mouse_cursor(cursor)# 实例化定义的某个窗体start_view = LiuLangQiQiu()# 设置当前应该显示哪个窗体window.show_view(start_view)# 保持程序持续运行arcade.run()if __name__ == "__main__":main()相关文章:
【日常点滴019】Python制作流浪气球游戏(导弹射击类)
Python制作流浪气球游戏(导弹射击类)教学课程代码(分步教学版)1、构建全局通用代码结构2、构建气球精灵类3、构建导弹精灵类4、碰撞检测5、构建游戏信息类 (最终完整代码)教学课程代码(分步教学…...
effective c++阅读之旅---条款29
为"异常安全"而努力是值得的! 什么是异常安全? 所谓的"异常安全",往往值得是函数接口的异常安全,它要求函数满足两个条件: 异常抛出时: 1、不泄露任何资源 2、不允许数据被破坏 异常安…...
Android system — 进程生命周期与ADJ
Android system — 进程oom_adj0. 引言1. 进程的生命周期1.1 Foreground process1.2 Visible process1.3 Service process1.4 Background process1.5 Empty process2. Lowmemorykiller2.1 ADJ级别2.2 进程state级别2.3 lmk策略2.4 如何查看应用oom_adj值3. 注意0. 引言 本文主要…...
vue3+ts+node个人博客系统(三)
一.主页顶部和中心面板布局 (1) 首先先去element-plus选择合适的布局el-container (2)在头部处编写相应的菜单栏el-menu,在这里要注意动态绑定路由的问题:default-active"$route.path"。将default-active设置为$route.path,el-me…...
Python第三方模块
♥️作者:小刘在C站 ♥️个人主页:小刘主页 ♥️每天分享云计算网络运维课堂笔记,努力不一定有收获,但一定会有收获加油!一起努力,共赴美好人生! ♥️夕阳下,是最美的绽放࿰…...
怎样查询PMP成绩?
【如何查询成绩】1、输入网址(PMI官网,不知道网址的私戳),点击 Log In如果忘记 PMI 的账号和密码了,怎么办?可以在你报名机构官网的个人中心的学习中心的我的报名处查看 PMI 的注册名和密码2、点击 Exam An…...
说说变量 __name__ 和它可能取到的一个值 __main__
结合 例子 弄懂 变量__name__ 和它的值’ main’这两个东西。 首先,明白两个定义, __name__是一个变量, __main__是个普通字符串,不是变量,但可以作为变量的值。 例子: 1.py 代码如下: if _…...
软考高级-信息系统管理师之整体管理(最新版)
整体管理 1、项目整体管理概述2、制定项目章程(选择,案例,论文)制定项目章程过程制定项目章程的依据1、协议2.项目工作说明书:3、商业论证4、事业环境因素包括,但不限于如下事项。5、组织过程资产:项目选择方法项目启动会议项目目标引导技术3、制订项目管理计划(选择)项目管…...
JVM学习篇垃圾收集器ParNewCMS与底层三色标记算法详解
1. 垃圾收集算法 2. 分代收集理论 当前虚拟机的垃圾收集都采用分代收集算法,这种算法没有什么新的思想,只是根据对象存活周期的不同将内存分为几块。一般将java堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法…...
基于FFmpeg和Screen Capturer Recorder实现屏幕和声音的录制
当我们看到一些精彩的视频画面,但无法下载时,可以通过录屏的方式将视频和音频录制下来。 这个时候我们需要安装采集视频和音频的工具screen-capture-recorder。 以下是在windows10环境下,基于FFmpeg和Screen Capturer Recorder实现屏幕和声音…...
猿人学14题详解
目测重点在于cookie:mz和m 获取mz.js: https://match.yuanrenxue.com/static/match/match14/m.js 获取设置m: https://match.yuanrenxue.com/api/match/14/m 一、还原16进制 const fs require(fs); const parser require(babel/parser); const gen…...
Allegro如何快速把推挤的走线变平滑操作指导
Allegro如何快速把推挤的走线变平滑操作指导 Allegro有个非常强大的功能,推挤命令,可以快速的让走线以不报DRC的形式避让目标 推挤后的效果如下图 但是走线不够平滑,如果每一段都去再推一下比较费时间,下面介绍allegro本身自带的优化类似走线的功能 具体操作如下 点击Rout…...
nginx基础学习
作为前端开发者,也很有必要了解一些运维部署知识。 nginx的作用有哪些? 负载平衡动静分离反向代理 何为反向代理? 反向代理即是,用户访问nginx服务器,nginx又将请求转发到真正服务器上,为什么用户不能直…...
【HDFS】FsDatasetImpl#recoverClose方法
recoverClose的目的recoverClose的过程recoverClose的调用点一、前言 HDFS客户端写文件时,如果某个datanode发生错误或者异常。客户端会把这个datanode从pipeline里踢除,然后进行pipiline recovery,用剩余datanodes去写或者满足一定的条件时补充新的datanode到pipeline中写…...
加油站会员管理小程序实战开发教程15 完结篇
这篇是本次实战课程的最后一篇,我们在上篇还有两个问题没解决。一个是会员卡类型显示不对,一个是不同的会员卡我们希望背景色显示不同。我们先处理一下这两个问题 1 显示会员卡类型 在列表上直接显示会员卡类型,目前显示的是数字,这个是因为枚举类型导致的。枚举类型在数…...
学习 Python 之 Pygame 开发坦克大战(五)
学习 Python 之 Pygame 开发坦克大战(五)坦克大战完善地图1. 创建砖墙2. 给砖墙增加子弹击中的碰撞效果3. 给砖墙添加坦克不能通过的碰撞效果4. 添加石墙5. 添加玩家基地6. 最终效果坦克大战完善地图 我的素材放到了百度网盘里,里面还有原版…...
【ROS】Windows系统安装ROS体验
大家平时玩ROS都是在Ubuntu系统上,那Windows系统可以安装吗,答案是:可以的!Windows为了发展自家的物联网生态,已经在Windows系统支持ROS了。 文章目录1.安装VS 20172.安装Chocolatey & Git3.安装ROS4.运行ROS例程1…...
第1讲-初步认识数据库系统(测试题总结)
一、测试题 数据库系统 包含 数据库管理系统 详细版: 数据库管理系统DBMS是数据管理软件,在用户和操作系统之间。 数据库系统DBS由数据库,数据库管理系统(及其应用开发工具)、应用程序和数据库管理员DBA组成的存储、管…...
进程-操作系统结构
进程-操作系统结构 中文仅本人理解,有错误请联系我。 操作系统为不同方面服务,有不同的设计角度。 为用户: 使用 为程序员:创造 程序员需要关注的就是system call接口的调度 file systems:ntfs,ext4 commu…...
【网络原理6】数据链路层协议——以太网
数据链路层负责的是相邻两个网络节点之间的数据以帧为单位进行传输。 具体关于数据链路层的介绍,已经在这一篇文章当中提到了。 初识网络:IP、端口、网络协议、TCP-IP五层模型_革凡成圣211的博客-CSDN博客TCP/IP五层协议详解https://blog.csdn.net/weix…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
