pygame编写飞机大战(8)-碰撞检测
来源:互联网 发布:美即黑面膜怎么样 知乎 编辑:程序博客网 时间:2024/05/22 06:24
当英雄飞机发射的子弹击中敌人的飞机,那么敌人飞机和子弹都应该马上消失。根据我们的设计,子弹只需要设置visible属性为False即可,而敌人飞机只需要重新设置下初始位置,飞行速度即可。
我们子弹和飞机都维护了一个矩形,rect(x, y, width, height), 其中x和y是矩形在窗口上的坐标,碰撞检测我们只需要循环遍历每一颗已经发射的子弹,也就是visible为True的子弹和每一个敌人飞机的矩形是否相交,如果相交,说明子弹击中了敌机,我们对应做行为就可以了。
我们现在在GameScene类的detect_conlision函数内做矩形是否相交的检测,这里我们还是比较简单,我们只判断子弹是否和敌人飞机相交,至于英雄飞机和敌人飞机是否相撞,实现思路一样,请大家自行尝试。
# 碰撞检测 def detect_conlision(self): # 检测英雄子弹是否和敌机碰撞 for bullet in self.hero.bullets: # 如果子弹不可见,说明子弹处于闲置状态,直接continue if not bullet.visible: continue for enemy in self.enemy_list: # 判断子弹的矩形和飞机的矩形是否相交 if pygame.Rect.colliderect(bullet.rect, enemy.rect): # 子弹设置为不可见 bullet.visible = False # 敌人飞机重新设置位置和速度 enemy.set_pos(random.randint(0, self.size[1] - enemy.rect[2] - 20), 0) enemy.speed = random.randint(2, 5) break
完成程序代码为:
import pygameimport random# 子弹class Bullet(object): # 初始化子弹 def __init__(self, scene, enemy=False): # 子弹移动速度 self.speed = 2 # 是否是敌人子弹 self.is_enemy = enemy # 子弹资源 if self.is_enemy: # 加载敌人子弹图片 self.image = pygame.image.load("./res/bullet_1.png") # 设置子弹移动方向 self.speed = self.speed else: # 加载英雄子弹图片 self.image = pygame.image.load("./res/bullet_11.png") # 设置子弹移动方向 self.speed = -self.speed # 子弹是否可见 self.visible = False # 持有主场景对象 self.main_scene = scene # 获得子弹矩形(x, y, width, height) self.rect = self.image.get_rect() # 设置子弹位置 def set_pos(self, x, y): self.rect[0] = x self.rect[1] = y # 设置子弹速度 def set_speed(self, speed): if self.is_enemy: self.speed = speed else: self.speed = -speed # 子弹移动 def action(self): if not self.visible: return # 假设飞机矩形为plane_rect(10, 20, 200, 300) # plane_rect.move_ip(10, 20), 那么结果是plane_rect(20, 40, 200, 300) # 也就是原矩形x和y坐标加上move_ip函数x和y坐标,就是当前矩形新位置 self.rect.move_ip(0, self.speed) # 如果子弹超出场景范围,则设置为不可见 if self.rect[1] < 0 or self.rect[1] > self.main_scene.size[1]: self.visible = False # 绘制子弹 def draw(self): if not self.visible: return self.main_scene.scene.blit(self.image, (self.rect[0], self.rect[1]))# 地图class GameBackground(object): # 初始化地图 def __init__(self, scene): # 加载相同张图片资源,做交替实现地图滚动 self.image1 = pygame.image.load("res/img_bg_level_3.jpg") self.image2 = pygame.image.load("res/img_bg_level_3.jpg") # 保存场景对象 self.main_scene = scene # 辅助移动地图 self.y1 = 0 self.y2 = -self.main_scene.size[1] # 计算地图图片绘制坐标 def action(self): self.y1 = self.y1 + 1 self.y2 = self.y2 + 1 if self.y1 >= self.main_scene.size[1]: self.y1 = 0 if self.y2 >= 0: self.y2 = -self.main_scene.size[1] # 绘制地图的两张图片 def draw(self): self.main_scene.scene.blit(self.image1, (0, self.y1)) self.main_scene.scene.blit(self.image2, (0, self.y2))# 飞机class HeroPlane(object): # 飞机初始化 def __init__(self, scene): # 加载飞机资源 self.image = pygame.image.load("./res/hero2.png") # 缓存主场景对象 self.main_scene = scene # 飞机矩形 self.rect = self.image.get_rect() # 矩形起始点 self.rect[0] = self.main_scene.size[0] / 2 - self.rect[2] / 2 self.rect[1] = self.main_scene.size[1] - self.rect[3] * 2 # 飞机子弹列表 self.bullets = [Bullet(self.main_scene) for _ in range(1, 30)] # 获得飞机 self.mImage = pygame.image.load("./res/bullet_11.png")矩形 def rect(self): return self.rect # 发子弹 def shot(self): # 每次发射三颗子弹 wait_for_shot = [] # 从子弹列表取出3颗目前尚未发射的子弹 # 如果子弹的visible为false,说明子弹尚未发射 for bullet in self.bullets: # 如果子弹不可见,说明子弹闲置状态 if not bullet.visible: wait_for_shot.append(bullet) if len(wait_for_shot) >= 3: break # 子弹发射位置,从posx位置开始 向右排列三颗子弹 posx = self.rect[0] - 15 # 依次设置选择子弹的初始位置,并将其设置为发射状态、移动速度 for bullet in wait_for_shot: bullet.visible = True posx = posx + 30 bullet.set_speed(4) bullet.set_pos(posx + 5, self.rect[1] - self.rect[3] / 2) # 飞机动作 def action(self, x, y): self.rect[0] = x - self.rect[2] / 2 self.rect[1] = y - self.rect[3] / 2 # 飞机绘制 def draw(self): self.main_scene.scene.blit( self.image, (self.rect[0], self.rect[1]))# 敌人飞机class EnemyPlane(object): # 初始化敌人飞机 def __init__(self, scene): # 加载飞机资源 self.image = pygame.image.load("./res/img-plane_1.png") # 缓存主场景对象 self.main_scene = scene # 飞机矩形 self.rect = self.image.get_rect() # 子弹列表 self.bullet = Bullet(self.main_scene, True) # 飞机速度 self.speed = 2 # 获得飞机矩形 def rect(self): return self.rect # 设置飞机位置 def set_pos(self, x, y): self.rect[0] = x self.rect[1] = y # 飞机动作 def action(self): # 子弹每次移动向上移动self.speed速度 self.rect.move_ip(0, self.speed) # 如果飞机移动出屏幕则将飞机设置为不可见状态 if self.rect[1] > self.main_scene.size[1]: # 当飞机飞出屏幕,重新设置飞机的初始位置,移动速度 # 随机产生x坐标,纵坐标使用为0 self.set_pos(random.randint(0, self.main_scene.size[1] - self.rect[2] - 20), 0) # 随机设置飞机移动速度 self.speed = random.randint(2, 5) # 绘制飞机 def draw(self): self.main_scene.scene.blit(self.image, (self.rect[0], self.rect[1]))# 主场景class MainScene(object): # 初始化主场景 def __init__(self): # 场景尺寸 self.size = (512, 768) # 场景对象 self.scene = pygame.display.set_mode([self.size[0], self.size[1]]) # 设置标题 pygame.display.set_caption("飞机大战-v1.0") # 地图对象 self.map = GameBackground(self) # 英雄对象 self.hero = HeroPlane(self) # 创建多个敌机 self.enemy_list = [EnemyPlane(self) for _ in range(3)] # 绘制 def draw_elements(self): # 绘制地图 self.map.draw() # 绘制英雄飞机 self.hero.draw() # 依次绘制英雄飞机每一颗发射出去的子弹 for bullet in self.hero.bullets: if bullet.visible: bullet.draw() # 绘制敌人飞机和飞机子弹 for plane in self.enemy_list: plane.draw() # 动作 def action_elements(self): # 计算坐标地图 self.map.action() # 依次计算英雄飞机每一颗发射子弹的坐标 for bullet in self.hero.bullets: if bullet.visible: bullet.action() # 计算敌人飞机和其飞机子弹 for plane in self.enemy_list: plane.action() # 处理事件 def handle_event(self): # 如果玩家点击右上角的X按钮,则关闭窗口 event_list = pygame.event.get() # 遍历事件列表 for event in event_list: # 如果判断用户点击了X按钮,则结束程序 if event.type == pygame.QUIT: pygame.quit() exit() # 判断事件类型是否是键盘按下事件 if event.type == pygame.KEYDOWN: # 如果是键盘按下,再判断玩家按下的是不是j键 if event.key == pygame.K_j: self.hero.shot() # 判断是否发生了鼠标拖动事件 if event.type == pygame.MOUSEMOTION: # 获得鼠标点击三个按钮的点击情况(1,0,0) # 如果第一个参数为1,表示左键被按下 # 如果第二个参数为1,表示滚轮被按下 # 如果第三个参数为1,表示右键被按下 buttons = pygame.mouse.get_pressed() # 我们只处理左键被按下的情况 if buttons[0]: # 获得拖动鼠标的拖动位置 position = pygame.mouse.get_pos() # 飞机跟随坐标移动 # print(position) self.hero.action(position[0], position[1]) # 碰撞检测 def detect_conlision(self): # 检测英雄子弹是否和敌机碰撞 for bullet in self.hero.bullets: # 如果子弹不可见,说明子弹处于闲置状态,直接continue if not bullet.visible: continue for enemy in self.enemy_list: # 判断子弹的矩形和飞机的矩形是否相交 if pygame.Rect.colliderect(bullet.rect, enemy.rect): # 子弹设置为不可见 bullet.visible = False # 敌人飞机重新设置位置和速度 enemy.set_pos(random.randint(0, self.size[1] - enemy.rect[2] - 20), 0) enemy.speed = random.randint(2, 5) break # 主循环,主要处理各种事件 def run_scene(self): while True: # 计算元素坐标 self.action_elements() # 绘制元素图片 self.draw_elements() # 处理事件 self.handle_event() # 碰撞检测 self.detect_conlision() # 刷新显示 pygame.display.update()# 入口函数if __name__ == "__main__": # 创建主场景 mainScene = MainScene() # 开始游戏 mainScene.run_scene()显示结果:
阅读全文
0 0
- pygame编写飞机大战(8)-碰撞检测
- pygame编写飞机大战(1)-准备
- pygame编写飞机大战(4)-滚动地图
- pygame编写飞机大战(5)-子弹类
- pygame编写飞机大战(2)-pygame快速入门
- pygame编写飞机大战(6)-英雄飞机类
- pygame编写飞机大战(7)-敌人飞机类
- pygame编写飞机大战(3)-搭建游戏流程
- pygame编写飞机大战(9)-播放爆炸动画
- 飞机大战之六:敌机爆炸(碰撞检测)
- unity之飞机大战和碰撞检测、射线
- 飞机大战开发04子弹与敌机的碰撞检测
- quick-cocos2d-x 飞机大战(打飞机)小demo教程------碰撞检测以及胜负
- Python:用Pygame实现飞机大战小游戏
- 【cocos2d-x入门实战】微信飞机大战之九:碰撞检测
- 【cocos2d-x入门实战】微信飞机大战之九:碰撞检测
- [cocos2d-x][游戏开发]通过cocos2d-x实现简易飞机大战 08.游戏界面 碰撞检测
- Cocos2d-x 3.2 lua飞机大战开发实例(二)敌机类的封装,以及碰撞检测的实现
- 二分查找,你真的懂吗
- 欢迎使用CSDN-markdown编辑器
- 图像识别
- python 多并发竞争微信token刷新问题的解决方案
- JAVA 时间日期
- pygame编写飞机大战(8)-碰撞检测
- sizeof 函数
- 编写多线程并发的测试类
- nginx 499 status
- 科比-一个烙印在篮球上的传奇
- [SDOI2009]学校食堂Dining 洛谷p2157
- 软件测试-接口测试(怎样设计接口测试用例)
- 剑指offer之九---矩形覆盖
- Servlet基础