python学习之飞机大战
2019-03-07 19:37
295 查看
框图
主函数
监视键盘、鼠标
子弹检测
飞机检测
显示
主程序
import pygame from settings import Settings from ship import Ship import game_functions as gf from pygame.sprite import Group from game_stats import GameStats from button import Button from scoreboard import Scoreboard def run_game(): # 初始化背景设置 pygame.init() ai_settings = Settings() screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height)) # 创建显示窗口 pygame.display.set_caption("Alien Invasion") # 创建Plya按钮 play_button = Button(ai_settings,screen,"Play") # 创建一个用于存储游戏统计信息的实例 stats = GameStats(ai_settings) sb = Scoreboard(ai_settings,screen,stats) # 创建一艘飞机 ship = Ship(ai_settings,screen) # 创建一个用于存储子弹的编组 bullets = Group() aliens = Group() # 创建外星人群 gf.create_fleet(ai_settings,screen,ship,aliens) while True: # 监视键盘和鼠标事件 gf.check_events(ai_settings,screen,stats,sb,play_button,ship,aliens,bullets) if stats.game_active: gf.update_bullets(ai_settings,screen,stats,sb,ship,aliens,bullets) gf.update_aliens(ai_settings,stats,screen,sb,ship,aliens,bullets) gf.update_screen(ai_settings,screen,stats,sb,ship,aliens,bullets,play_button) run_game()
功能模块
import sys import pygame from time import sleep from bullet import Bullet from alien import Alien def check_keydown_events(event,ai_settings,screen,ship,bullets): if event.key == pygame.K_RIGHT: ship.moving_right = True elif event.key == pygame.K_LEFT: ship.moving_left = True elif event.key == pygame.K_UP: ship.moving_up = True elif event.key == pygame.K_DOWN: ship.moving_down = True elif event.key == pygame.K_SPACE: # 创建一个子弹 fire_bullet(ai_settings,screen,ship,bullets) def fire_bullet(ai_settings,screen,ship,bullets): if len(bullets) < ai_settings.bullets_allowed: new_bullet = Bullet(ai_settings,screen,ship) bullets.add(new_bullet) def check_keyup_events(event,ship): if event.key == pygame.K_RIGHT: ship.moving_right = False elif event.key == pygame.K_LEFT: ship.moving_left = False elif event.key == pygame.K_UP: ship.moving_up = False elif event.key == pygame.K_DOWN: ship.moving_down = False def check_events(ai_settings,screen,stats,sb,play_button,ship,aliens,bullets): for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == pygame.KEYDOWN: check_keydown_events(event,ai_settings,screen,ship,bullets) elif event.type == pygame.KEYUP: check_keyup_events(event,ship) elif event.type == pygame.MOUSEBUTTONDOWN: # 获取鼠标点击的坐标 mouse_x,mouse_y = pygame.mouse.get_pos() # 检测这个坐标是否在play按钮内 check_play_button(ai_settings,screen,stats,sb,play_button,ship,aliens,bullets,mouse_x,mouse_y) def check_play_button(ai_settings,screen,stats,sb,play_button,ship,aliens,bullets,mouse_x,mouse_y): button_clicked = play_button.rect.collidepoint(mouse_x,mouse_y) # 如果在内那并且是非活跃就执行下面的语句 if button_clicked and not stats.game_active: # 重置速度 ai_settings.initialize_dynamic_settings() # 隐藏光标 pygame.mouse.set_visible(False) # 重置飞机的条数和得分 stats.reset_stats() stats.game_active = True # 重置记分牌图像 sb.prep_score() sb.prep_high_score() sb.prep_level() sb.prep_ships() # 清空子弹和外星人 aliens.empty() bullets.empty() # 创建一群外星人 create_fleet(ai_settings, screen, ship, aliens) ship.center_ship() def check_fleet_edges(ai_settings,aliens): # 有外星人到达边缘时采取相应的措施,遍历每个外星人 for alien in aliens.sprites(): if alien.check_edges(): change_fleet_direction(ai_settings,aliens) break def change_fleet_direction(ai_settings,aliens): for alien in aliens.sprites(): alien.rect.y += ai_settings.fleet_drop_speed ai_settings.fleet_direction *= -1 def ship_hit(ai_settings,stats,screen,sb,ship,aliens,bullets): if stats.ships_left > 0: # 飞机的数量减一 stats.ships_left -= 1 sb.prep_ships() # 清空外星人和子弹 aliens.empty() bullets.empty() # 创建一群新的外星人,将飞机放在屏幕低端中央 create_fleet(ai_settings,screen,ship,aliens) ship.center_ship() # 暂停1s sleep(1) else: stats.game_active = False pygame.mouse.set_visible(True) def check_aliens_bottom(ai_settings,stats,screen,sb,ship,aliens,bullets): screen_rect = screen.get_rect() for alien in aliens.sprites(): if alien.rect.bottom >= screen_rect.bottom: ship_hit(ai_settings,stats,screen,sb,ship,aliens,bullets) break; def update_aliens(ai_settings,stats,screen,sb,ship,aliens,bullets): check_fleet_edges(ai_settings,aliens) # 对编组aliens调用方法update(),这将自动对每个外星人调用方法update() aliens.update() # 检测外星人和飞船之间的碰撞 # 方法spritecollideany()接受两个实参:一个精灵和一个编组。它检查编组是否 # 有成员与精灵发生了碰撞,并在找到与精灵发生了碰撞的成员后就停止遍历编组。在这里, # 它遍历编组aliens,并返回它找到的第一个与飞机发生了碰撞的外星人 # 如果没有发生碰撞,spritecollideany()将返回None # 如果找到了与飞机发生碰撞的外星人, 它就返回这个外星人 if pygame.sprite.spritecollideany(ship,aliens): ship_hit(ai_settings, stats, screen, sb, ship, aliens, bullets) check_aliens_bottom(ai_settings,stats,screen,sb,ship,aliens,bullets) def update_screen(ai_settings, screen, stats, sb, ship, aliens, bullets,play_button): # 背景色填充屏幕 screen.fill(ai_settings.bg_color) ship.update() # 调试用到,会影响运行速度 #print(len(bullets)) # 在飞机和外星人创建之后重绘子弹 for bullet in bullets.sprites(): bullet.draw_bullet() # 绘制飞机 ship.blitme() # 编组调用draw()时,Pygame自动绘制编组的每个元素,绘制位置由元素的属性rect决定。 # 在这里,aliens.draw(screen)在屏幕上绘制编组中的每个外星人。 aliens.draw(screen) # 显示得分 sb.show_score() if not stats.game_active: play_button.draw_button() # 最近绘制的屏幕可见,不断更新屏幕,以显示元素的新位置,并在原来的位置隐藏元素, # 从而营造平滑移动的效果 pygame.display.flip() def update_bullets(ai_settings,screen,stats,sb,ship,aliens,bullets): # 对编组调用update()时,编组将自动对其中的每个精灵调用update() bullets.update() # 不应从列表或编组中删除条目(如果不这样做,那样会直接把bullets列表中的子弹删除,影响下 # 面的检测),因此必须遍历编组的副本 for bullet in bullets.copy(): if bullet.rect.bottom <= 0: bullets.remove(bullet) check_bullet_alien_collisions(ai_settings,screen,stats,sb,ship,aliens,bullets) def check_bullet_alien_collisions(ai_settings,screen,stats,sb,ship,aliens,bullets): # 每当有子弹和外星人的rect重叠时,groupcollide()就在它返回的字典中添加一个键-值对 # 两个实参True 告诉Pygame删除发生碰撞的子弹和外星人 # 第一个布尔实参设置为False,并让第二个布尔实参为True。这样被击中的外星人将消失,但所有 # 的子弹都始终有效,直到抵达屏幕顶端后消失 collisions = pygame.sprite.groupcollide(bullets,aliens,True,True) if collisions: # 外星人碰撞的子弹都是字典collisions中的一个键;而与每颗子弹相关的值都是一个列表, # 其中包含该子弹撞到的外星人 # 如果字典collisions 存在,我们就遍历其中的所有值。别忘了,每个值都是一个列表, # 包含被同一颗子弹击中的所有外星人。对于每个列表,都将一个外星人的点数乘以其中 # 包含的外星人数量,并将结果加入到当前得分中人 for ali in collisions.values(): stats.score += ai_settings.alien_points * len(ali) sb.prep_score() check_high_score(stats,sb) if len(aliens) == 0: bullets.empty() ai_settings.increase_speed() # 提高等级 stats.level += 1 sb.prep_level() create_fleet(ai_settings,screen,ship,aliens) # 计算一行容纳多少人 def get_number_aliens_x(ai_settings,alien_width): available_space_x = ai_settings.screen_width - 2 * alien_width # 为了不让外星人看起来拥挤,设置为整形 number_alines_x = int(available_space_x / (2 * alien_width)) return number_alines_x def get_unmber_rows(ai_settings,ship_height,alien_height): available_space_y = (ai_settings.screen_height - (7*alien_height)-ship_height) number_rows = int(available_space_y/(2*alien_height)) return number_rows def create_alien(ai_settings, screen, aliens,alien_number,row_number): alien = Alien(ai_settings,screen) alien_width = alien.rect.width alien.x = alien_width + 2 * alien_width * alien_number alien.rect.x = alien.x alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number aliens.add(alien) # 计算可以创建多少外星人 def create_fleet(ai_settings,screen,ship,aliens): alien = Alien(ai_settings,screen) # 计算一行可以容纳多少外星人 number_aliens_x = get_number_aliens_x(ai_settings,alien.rect.width) # number_rows = get_unmber_rows(ai_settings,ship.rect.height,alien.rect.height) # 创建一行外星人 # 一次次循环,增加x的值,使得外星人的横坐标不同,每个外星人的rect属性都不同 for row_number in range(number_rows): # 这里为了显示效果更佳,+1处理 for alien_number in range(number_aliens_x+1): create_alien(ai_settings, screen, aliens,alien_number,row_number) def check_high_score(stats,sb): if stats.score > stats.high_score: stats.high_score = stats.score sb.prep_high_score()
状态模块
class GameStats(): # 跟踪游戏的统计信息 def __init__(self,ai_settings): # 初始化统计信息 self.ai_settings = ai_settings self.reset_stats() # 游戏一开始处于非活跃状态 self.game_active = False #self.score = 0 # 最高得分 self.high_score = 0 def reset_stats(self): self.ships_left = self.ai_settings.ship_limit self.score = 0 self.level = 1
子弹模块
import pygame from pygame.sprite import Sprite # pygame.sprite.Sprite就是Pygame里面用来实现精灵的一个类,使用时,并不需要对它实例化, # 只需要继承他,然后按需写出自己的类就好了 # 精灵可以认为成是一个个小图片,一种可以在屏幕上移动的图形对象,并且可以与其他图形对象交互。 # 精灵图像可以是使用pygame绘制函数绘制的图像,也可以是原来就有的图像文件 class Bullet(Sprite): def __init__(self,ai_settings,screen,ship): # 思考一下这里为什么没有参数??? super(Bullet,self).__init__() self.screen = screen # 在(0,0)处创建一个子弹的属性rect self.rect = pygame.Rect(0,0, ai_settings.bullet_width, ai_settings.bullet_height) # 设置子弹的位置 self.rect.centerx = ship.rect.centerx self.rect.top = ship.rect.top # 子弹位置,子弹x坐标不变,y向上运动 self.y = float(self.rect.y) self.color = ai_settings.bullet_color self.speed_factor = ai_settings.bullet_speed_factor def update(self): self.y -= self.speed_factor self.rect.y = self.y def draw_bullet(self): # 在屏幕上绘制子弹 pygame.draw.rect(self.screen,self.color,self.rect)
按钮模块
import pygame.ftfont class Button(): def __init__(self,ai_settings,screen,msg): self.screen = screen self.screen_rect = screen.get_rect() self.width,self.height = 100,50 self.button_color = (0,255,0) self.text_color = (255,255,255) # 指定使用什么字体来渲染文本,48是文本字号 self.font = pygame.font.SysFont(None,48) # 先创建一个按钮的rect对象,然后指定位置(居中) self.rect = pygame.Rect(0,0,self.width,self.height) self.rect.center = self.screen_rect.center # 显示的字符串渲染为图像来处理文本 self.prep_msg(msg) def prep_msg(self,msg): # 将msg渲染为图像,并使其在按钮上居中 # font.render()将存储在msg中的文本转换为图像,然后将该图像存储在msg_image中 self.msg_image = self.font.render(msg,True,self.text_color,self.button_color) self.msg_image_rect = self.msg_image.get_rect() self.msg_image_rect.center = self.rect.center def draw_button(self): # 绘制表示按钮的矩形 self.screen.fill(self.button_color,self.rect) # 传递一幅图像以及与该图像相关联的rect 对象, 从而在屏幕上绘制文本图像 self.screen.blit(self.msg_image,self.msg_image_rect)
外星人模块
import pygame from pygame.sprite import Sprite class Alien(Sprite): def __init__(self,ai_settings,screen): super(Alien,self).__init__() self.screen = screen self.ai_settings = ai_settings # 加载外星人,获取属性 self.image = pygame.image.load('images/alien.bmp') self.rect = self.image.get_rect() # 外星人在屏幕左上角 self.rect.x = self.rect.width self.rect.y = self.rect.height self.x = float(self.rect.x) def blitme(self): # 指定位置绘制外星人 self.screen.blit(self.image,self.rect) def update(self): # 这里的rect.x是一个int类型的数据 self.x += (self.ai_settings.alien_speed_factor * self.ai_settings.fleet_direction) self.rect.x = self.x def check_edges(self): screen_rect = self.screen.get_rect() if self.rect.right >= screen_rect.right: return True elif self.rect.left <= 0: return True
飞机模块
import pygame from pygame.sprite import Sprite # 让Ship继承Sprite ,以便能够创建飞船编组 class Ship(Sprite): def __init__(self,ai_settings,screen): super(Ship,self).__init__() # 初始化飞机并设置其初始位置 self.screen = screen self.ai_settings = ai_settings # 加载飞机图像 self.image = pygame.image.load('images/ship.bmp') # 获取飞机和屏幕的属性 self.rect = self.image.get_rect() self.screen_rect = screen.get_rect() # 将新飞机放在屏幕底部中央 # 游戏元素与屏幕边缘对齐,可使用属性top、bottom、left或right,要调整游戏元素的水平或垂直位置,可使用属性x和y self.rect.centerx = self.screen_rect.centerx self.rect.bottom = self.screen_rect.bottom self.center = float(self.rect.centerx) self.bottom = float(self.rect.bottom) #移动标志 self.moving_right = False self.moving_left = False self.moving_up = False self.moving_down = False def update(self): if self.moving_right and self.rect.right < self.screen_rect.right: self.center += self.ai_settings.ship_speed_factor if self.moving_left and self.rect.left > 0: self.center -= self.ai_settings.ship_speed_factor if self.moving_down and self.rect.bottom < self.screen_rect.bottom: self.bottom += self.ai_settings.ship_speed_factor if self.moving_up and self.rect.top > 0: self.bottom -= self.ai_settings.ship_speed_factor self.rect.centerx = self.center self.rect.bottom = self.bottom def blitme(self): # 指定位置绘制飞船 self.screen.blit(self.image,self.rect) # 设置在屏幕底中央 def center_ship(self): self.center = self.screen_rect.centerx self.bottom = self.screen_rect.bottom
相关设置模块
class Settings(): def __init__(self): # 设置屏幕大小 self.screen_width = 1200 self.screen_height = 700 # 设置背景颜色 self.bg_color = (230,230,230) # 飞机数量 self.ship_limit = 3 # 子弹设置 self.bullet_width = 4 self.bullet_height = 15 self.bullet_color = 60,60,60 # 限制子弹的数量 self.bullets_allowed = 7 # 外星人向下速度设置 self.fleet_drop_speed = 6 # 以什么样的速度加快游戏节奏 self.speedup_scale = 1.1 self.score_scale = 1.5 self.initialize_dynamic_settings() def initialize_dynamic_settings(self): # 速度设置 self.ship_speed_factor = 1.5 self.bullet_speed_factor = 3 self.alien_speed_factor = 1 # 1为向右,-1为向左 self.fleet_direction = 1 # 记分 self.alien_points = 50 def increase_speed(self): self.ship_speed_factor *= self.speedup_scale self.bullet_speed_factor *= self.speedup_scale self.alien_speed_factor *= self.speedup_scale # 增加记分的底数 self.alien_points = int(self.alien_points * self.score_scale) print(self.alien_points)
运行:
开始阶段:
运行阶段:
相关文章推荐
- 【零基础入门学习Python笔记007】了不起的分支和循环1:打飞机框架
- python语言实现飞机大战
- Python3项目实战:飞机大战
- unity学习之飞机大战制作 关键点(六) 子弹与敌机之间的碰撞
- 学习Python就业有哪些方向?附加视频教程(python3从入门到进阶(面向对象),实战(爬虫,飞机游戏,GUI)视频教程)
- unity学习之飞机大战制作 关键点(三) 设置子弹的生成和移动
- unity学习之飞机大战制作 关键点(MAX) 成品小游戏飞机大战
- python pygame模块编写飞机大战
- python飞机大战,初步实现代码
- Python实现飞机大战
- Python项目案例介绍,炫酷飞机大战,内附源码文件领取
- Java学习笔记(九):多线程实现简陋的飞机大战
- unity学习之飞机大战制作 关键点(二)定义层级,以及设置主角动画
- unity学习之飞机大战制作 关键点(四) 设置敌机和奖励物品的生成和随机
- Python学习笔记(五)Python的切片和迭代
- Python 学习笔记
- Python-学习-import语句导入模块
- 分享2个Python的学习资源
- Python学习路线最好是哪个?
- Python学习 我和Python的第一次亲密接触(1)