在这个项目中,要实现在屏幕左上角添加一个外星人,然后根据这个外星人的边距和屏幕尺寸来计算屏幕上可容纳多少个外星人,据此创建一系列外星人,使其填满尺寸屏幕上半部分;

之后要实现让外星人向两边和下方移动直到被外星人全部击落、有外星人撞到飞船或者有外星人抵达屏幕底端,在将全部外星人击落、有外星人撞到飞船或者有外星人抵达屏幕底端后,屏幕上将再出现一群外星人;

为了避免无休止地重复游戏而乏味无趣,可限制玩家可用的飞船数量,当飞船数量用完之后,游戏结束。

下面展示代码:

1.alien_invasion.py

import sys
import pygame
from time import sleepfrom settings import Settings
from ship import Ship
from bullet import Bullet
from alien import Alien
from game_stats import GameStatsclass AlienInvasion:""" 管理游戏资源和行为的类 """def __init__(self):""" 初始化游戏并创建游戏资源 """pygame.init()self.settings = Settings()self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)self.settings.screen_width = self.screen.get_rect().widthself.settings.screen_height = self.screen.get_rect().heightpygame.display.set_caption("Alien Invasion")# 创建一个用于存储游戏统计信息的实例self.stats = GameStats(self)self.ship = Ship(self)self.bullets = pygame.sprite.Group()self.aliens = pygame.sprite.Group()self._create_fleet()def run_game(self):""" 开始游戏的主循环 """while True:self._check_events()if self.stats.game_active:self.ship.update()self._update_bullets()self._update_aliens()self._update_screen()def _update_bullets(self):""" 更新子弹的位置并删除消失的子弹 """# 更新子弹的位置self.bullets.update()# 删除消失的子弹for bullet in self.bullets.copy():if bullet.rect.bottom <= 0:# ######## 此处有改动# if bullet.rect.right >= self.ship.screen_rect.right:self.bullets.remove(bullet)self._check_bullet_alien_collisions()def _check_bullet_alien_collisions(self):""" 响应子弹和外星人碰撞 """# 删除发生碰撞的子弹和外星人pygame.sprite.groupcollide(self.bullets, self.aliens, True, True)'''函数sprite.groupcollide()将一个编组中每个元素的rect同另一个编组中每个元素的rect及进行比较。'''if not self.aliens:# 删除现有的所有子弹并新建一群外星人self.bullets.empty()self._create_fleet()def _update_aliens(self):"""检查是否有外星人位于屏幕边缘,并更新外星人群中所有外星人的位置"""self._check_fleet_edges()self.aliens.update()# 检测外星人和飞船之间的碰撞if pygame.sprite.spritecollideany(self.ship, self.aliens):print("Ship hit!!!")self._ship_hit()# 检查是否有外星人到达了屏幕底端self._check_aliens_bottom()def _ship_hit(self):""" 响应飞船被外星人撞到 """if self.stats.ships_left > 0:# 将ships_left减1self.stats.ships_left -= 1# 清空余下的外星人和子弹self.aliens.empty()self.bullets.empty()# 创建一群新的外星人,并将飞船放到屏幕底端的中央self._create_fleet()self.ship.center_ship()# 暂停sleep(0.5)else:self.stats.game_active = Falsedef _check_events(self):""" 响应按键和鼠标事件 """for event in pygame.event.get():if event.type == pygame.QUIT:sys.exit()elif event.type == pygame.KEYDOWN:  # 按下键self._check_keydown_events(event)elif event.type == pygame.KEYUP:  # 松开键self._check_keyup_events(event)def _check_keydown_events(self, event):""" 响应按键 """if event.key == pygame.K_RIGHT:  # 按下的键是右箭头键# 向右移动飞船self.ship.moving_right = Trueelif event.key == pygame.K_LEFT:  # 按下的键是左箭头键# 向左移动飞船self.ship.moving_left = Trueelif event.key == pygame.K_UP:# 向上移动飞船self.ship.moving_up = Trueelif event.key == pygame.K_DOWN:# 向下移动飞船self.ship.moving_down = Trueelif event.key == pygame.K_q:sys.exit()elif event.key == pygame.K_SPACE:self._fire_bullet()def _check_keyup_events(self, event):""" 响应松开 """if event.key == pygame.K_RIGHT:  # 松开的键是右箭头键self.ship.moving_right = Falseelif event.key == pygame.K_LEFT:  # 松开的键是左箭头键self.ship.moving_left = Falseelif event.key == pygame.K_UP:  # 松开的键是上箭头键self.ship.moving_up = Falseelif event.key == pygame.K_DOWN:  # 松开的键是下箭头键self.ship.moving_down = Falsedef _fire_bullet(self):""" 创建一颗子弹,并将其加入编组bullets中 """if len(self.bullets) < self.settings.bullets_allowed:new_bullet = Bullet(self)self.bullets.add(new_bullet)def _create_fleet(self):""" 创建外星人群 """# 创建一个外星人并计算一行可容纳多少个外星人# 外星人的间距为外星人宽度alien = Alien(self)alien_width, alien_height = alien.rect.sizeavailiable_space_x = self.settings.screen_width - (2 * alien_width)number_aliens_x = availiable_space_x // (2 * alien_width) + 1# 计算屏幕可容纳多少行外星人ship_height = self.ship.rect.heightavailiable_space_y = (self.settings.screen_height - (3 * alien_height) - ship_height)number_rows = availiable_space_y // (2 * alien_height)# 创建外星人群for row_number in range(number_rows):for alien_number in range(number_aliens_x):self._create_alien(alien_number, row_number)def _create_alien(self, alien_number, row_number):""" 创建一个外星人并将其加入到当前行 """alien = Alien(self)alien_width, alien_height = alien.rect.sizealien.x = alien_width + 2 * alien_width * alien_numberalien.rect.x = alien.x# 这里很重要!!!# 如果写作:# alien.rect.x = alien_width + 2 * alien_width * alien_number# 屏幕只会出现一列外星人# 原因是(alien_width + 2 * alien_width * alien_number)# 是计算当前外星人在当前行的位置,然后使用外星人的属性x来设置其rect的位置,这是创建外星人行列的过程,并不能展示外星人移动过程# alien是类Alien()的实例,在Alien()中alien.x在一直变化,利用函数_update_aliens()更新,以此来展示外星人左右移动alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_numberself.aliens.add(alien)def _check_fleet_edges(self):""" 外星人到达边缘时采取相应的措施 """for alien in self.aliens.sprites():if alien.check_edges():self._change_fleet_firection()breakdef _check_aliens_bottom(self):""" 检查是否有外星人到达了屏幕底端 """screen_rect = self.screen.get_rect()for alien in self.aliens.sprites():if alien.rect.bottom >= screen_rect.bottom:# 像飞船被撞到一样处理self._ship_hit()breakdef _change_fleet_firection(self):""" 将整群外星人下移,并改变它们方向 """for alien in self.aliens.sprites():alien.rect.y += self.settings.fleet_drop_speedself.settings.fleet_direction *= -1def _update_screen(self):""" 更新屏幕上的图像,并切换到新屏幕 """self.screen.fill(self.settings.bg_color)self.ship.blitme()for bullet in self.bullets.sprites():bullet.draw_bullet()self.aliens.draw(self.screen)pygame.display.flip()if __name__ == '__main__':# 创建游戏实例并运行游戏ai = AlienInvasion()ai.run_game()

2.settings.py

class Settings:""" 存储游戏《外星人入侵》中所有设置的类 """def __init__(self):""" 初始化游戏的设置 """# 屏幕设置self.screen_width = 1500self.screen_height = 800self.bg_color = (227, 227, 227)# 飞船设置self.ship_speed = 1.5  # 速度:每次循环将移动1.5像素self.ship_limit = 3  # 飞船数量限制# 子弹设置self.bullet_speed = 3.0self.bullet_width = 3self.bullet_height = 15self.bullet_color = (60, 60, 60)  # 子弹颜色self.bullets_allowed = 10  # 允许在屏幕中的子弹数量# 外星人设置self.alien_speed = 1.0self.fleet_drop_speed = 10# fleet_direction为1表示右移,为-1表示左移self.fleet_direction = 1

3.alien.py

import pygame
from pygame.sprite import Spriteclass Alien(Sprite):""" 表示单个外星人的类 """def __init__(self, ai_game):""" 初始化外星人并设置其起始位置 """super().__init__()self.screen = ai_game.screenself.settings = ai_game.settings# 加载外星人图像并设置其rect属性self.image = pygame.image.load('images/alien.bmp')self.rect = self.image.get_rect()# 每个外星人最初都在屏幕左上角附近self.rect.x = self.rect.widthself.rect.y = self.rect.height# 存储外星人的精确水平位置self.x = float(self.rect.x)def check_edges(self):""" 如果外星人位于屏幕边缘,就返回True """screen_rect = self.screen.get_rect()if self.rect.right >= screen_rect.right or self.rect.left <= 0:return Truedef update(self):""" 向左或向右移动外星人 """self.x += (self.settings.alien_speed * self.settings.fleet_direction)self.rect.x = self.x

4.ship.py

import pygameclass Ship:""" 管理飞船的类 """def __init__(self, ai_game):""" 初始化飞船并设置其初始位置 """self.screen = ai_game.screenself.settings = ai_game.settingsself.screen_rect = ai_game.screen.get_rect()# 加载飞船图像并获取其外接矩形self.image = pygame.image.load('images/ship.bmp')self.rect = self.image.get_rect()# 对于每艘新飞船,都将其放在屏幕底部的中央self.rect.midbottom = self.screen_rect.midbottom# # 使飞船出现在屏幕中央而不是屏幕底部的中央# self.rect.center = self.screen_rect.center# # 使飞船出现在屏幕左侧# self.rect.midleft = self.screen_rect.midleft# 在飞船的属性x中储存小数值self.x = float(self.rect.x)self.y = float(self.rect.y)# 移动标志self.moving_right = Falseself.moving_left = Falseself.moving_up = Falseself.moving_down = Falsedef update(self):""" 根据移动标志调整飞船的位置 """# 更新飞船而不是rect对象的x值if self.moving_right and self.rect.right < self.screen_rect.right:self.x += self.settings.ship_speedif self.moving_left and self.rect.left > 0:self.x -= self.settings.ship_speed# 更新飞船而不是rect对象的y值if self.moving_down and self.rect.bottom < self.screen_rect.bottom:self.y += self.settings.ship_speedif self.moving_up and self.rect.top > 0:self.y -= self.settings.ship_speed# 根据self.x更新rect对象self.rect.x = self.x# 根据self.y更新rect对象self.rect.y = self.ydef center_ship(self):""" 让飞船在屏幕低端居中 """self.rect.midbottom = self.screen_rect.midbottomself.x = float(self.rect.x)def blitme(self):""" 在指定位置绘制飞船 """self.screen.blit(self.image, self.rect)

5.bullet.py

import pygame
from pygame.sprite import Spriteclass Bullet(Sprite):""" 管理飞船所发射子弹的类 """def __init__(self, ai_game):""" 在飞船当前位置创建一个子弹位置 """super().__init__()self.screen = ai_game.screenself.settings = ai_game.settingsself.color = self.settings.bullet_color# 在(0,0)处创建一个表示子弹的矩形,再设置正确的位置self.rect = pygame.Rect(0, 0, self.settings.bullet_width, self.settings.bullet_height)self.rect.midtop = ai_game.ship.rect.midtop# 储存用小数表示的子弹位置self.y = float(self.rect.y)# self.x = float(self.rect.x)def update(self):""" 向上移动子弹 """# 更新表示子弹位置的小数值self.y -= self.settings.bullet_speed# 更新表示子弹的rect的位置self.rect.y = self.y# def update(self):#     """ 向右移动子弹 """#     # 更新表示子弹位置的小数值#     self.x += self.settings.bullet_speed#     # 更新表示子弹的rect的位置#     self.rect.x = self.xdef draw_bullet(self):""" 在屏幕上绘制子弹 """pygame.draw.rect(self.screen, self.color, self.rect)

6.game_stats.py

class GameStats:""" 跟踪游戏的统计信息 """def __init__(self, ai_game):""" 初始化统计信息 """self.settings = ai_game.settingsself.reset_stats()# 游戏刚启动时处于活动状态self.game_active = Truedef reset_stats(self):""" 初始化在游戏运行期间可能变化的统计信息 """self.ships_left = self.settings.ship_limit

《Python编程:从入门到实践》第13章:外星人来了相关推荐

  1. Python编程从入门到实践第五章部分习题

    Python编程从入门到实践第五章部分习题 5-8 5-9` names = ['admin','zhang','li','zhao','song'] for name in names:if nam ...

  2. Python编程:从入门到实践 第三章--函数

    Python编程:从入门到实践 第三章-函数 语法 就还是需要先记一下函数定义的语法: def Test(num):num = 12 如上,def func_name(factors): # code ...

  3. 读书笔记——《Python编程从入门到实践》第二章

    读书笔记--<Python编程从入门到实践>第二章 读书笔记--<Python编程从入门到实践>第二章 变量 如何使用变量 如何规范变量命名 字符串 字符串是什么 如何修改字符 ...

  4. python编程从入门到实践 第18章Django入门 2022年最新

    说明:这篇文章只是记录自己自学本书的一个痕迹,日后来看作为一个念想.至于做为公开,是希望对一些同样跟我一样的朋友有一点点帮助,当然我本人就是小白,帮助可能也不大哈哈. 这篇文章记录了<pytho ...

  5. Python编程 从入门到实践——第1章 起步

    第一章 起步 1.1 搭建编程环境 1.1.1 Python版本 1.1.2 运行Python代码片段 1.1.3 Sublime Text简介 1.2 在不同操作系统中搭建Python编程环境 1. ...

  6. Python编程从入门到实践 -----第4章、操作列表(课后习题答案)

    4-1 比萨:想出至少三种你喜欢的比萨,将其名称储存在一个列表中,在使用循环将每种比萨名称都打印出来. 修改这个for循环,使其打印包含比萨名称的句子,而不是仅仅是比萨的名称,对于每种比萨,都显示一行 ...

  7. Python编程从入门到实践 -----第3章、列表简介(课后习题答案)

    3-1 姓名: 将一些朋友的姓名存储在一个列表中,并将其命名为names .依次访问该列表中的每个元素,从而将每个朋友的姓名都打印出来. names = ['chen', 'x', 'l']print ...

  8. Python编程-从入门到实践第15章课后习题详解

    第15章 使用Plotly模拟掷骰子--课后习题答案 练习15-6 #掷两个D8 from plotly.graph_objs import Bar,Layout from plotly import ...

  9. Python编程:从入门到实践-第七章:用户输入和while循环(语法)

    #7-1 汽车租赁:编写一个程序,询问用户要租赁什么样的汽车,并打印一条消息,如"Let me see if I can find you a Subaru". ''' print ...

  10. 记录——python编程从入门到实践十二章练习题

    12-1.12-2.12-3 main.py import sysimport pygamefrom homura import Ho from sets import Settings import ...

最新文章

  1. Jconsole配置与连接
  2. 31 | 套路篇:磁盘 I/O 性能优化的几个思路
  3. 学习Java编程,英语对我们来说有多重要?
  4. outlook2010客户端无法预览及保存word,excel问题
  5. 链栈和递归实现迷宫算法
  6. JavaSE08:详解多线程(超详细)
  7. 微波遥感SNAP(三)——检测地表沉降(1)自动化处理(Graph Builder)
  8. paip.提升效率--输入框不能粘贴的问题
  9. 树莓派引脚介绍与GPIO的初步认识与应用
  10. mysql中tab键作用_MySQL小技巧-mysql命令 tab键数据表名、字段名补全功能
  11. 关于校企合作的一些想法和思路
  12. 数学建模常用算法—层次分析法(AHP)
  13. 【ARM】嵌入式 ARM Linux 下移植 USB 蓝牙、交叉编译 bluez 各种版本
  14. 公司网盘间的风云变幻PK赛
  15. 中台战略-第五章、中台建设方法论
  16. 数据仓库卸数(网银系统数据库)
  17. 看完这篇iOS面试题,一天3offer!!!
  18. php网站整合ck播放器,帝国cms整合CKplayer播放器代码教程
  19. C语言学习笔记(浙大翁恺版)第一周
  20. Python实现头像换脸(AI换脸)

热门文章

  1. Floyd算法实现公交地铁站点之间的最短路径规划
  2. Unity水管 管道流水资源
  3. multipartfile获取数据_MultipartFile实现文件上传
  4. java入门之控制台输入人数成绩计算及格率(将成绩存入数组)与打印九九乘法表
  5. 系统网络“人肉”监控
  6. python怎么将字符串逆序_python中如何把一个字符串顺序逆序反转的几种方法?
  7. css绝对定位有什么用,css中的绝对定位是什么意思
  8. VS2019 配色_设计师必看|这10个网站可以帮你更快做好配色
  9. openssl在多平台和多语言之间进行RSA加解密注意事项
  10. 天气预报-微信小程序-源码