Python编程:《外星人入侵》

Pygame是一组功能强大而有趣的的模块,可以用于管理图形、动画乃至声音,让你 能够更轻松地开发复杂的游戏。

《外星人入侵》游戏简介:

在游戏《外星人入侵》中, 玩家控制着一艘最初出现在屏幕底部中央的飞船。玩家可以使用箭头左右移动飞船,还可以使用空格键进行射击。游戏开始时,一群外星人出现在天空中,他们在屏幕中向下移动。玩家的任务时射杀这些外星人。玩家将所有外星人都消灭干净后,将出现一群新的外星人,他们移动的速度更快。只要有外星人撞到了玩家的飞船或到达了屏幕底部,玩家就损失一艘飞船。玩家损失三艘飞船后,游戏结束。

1.1 安装Pygame

本人的系统是macOS Monterey,要安装Pygame依赖的有些包,需要Home-brew。为安装Pygame依赖的库,请执行下面的命令:

(base) liuxiaowei@MacBook-Air ~ % brew install hg sdl sdl_image sdl_ttf

如果还想启用较高级的功能,如在游戏中包含声音, 可安装下面两个额外的库:

(base) liuxiaowei@MacBook-Air ~ % brew install sdl_mixer_portmidi

使用下面的命令来安装Pygame(如果你运行的是Python2.7, 请将pip3替换为pip ):

(base) liuxiaowei@MacBook-Air ~ % pip3 install --user hg+http://bitbucker.org/pygame/pygame

启动一个Python终端会话, 并导入Pygame以检查安装是否成功(如果你运行的是Python2.7, 请将python3替换为python):

(base) liuxiaowei@MacBook-Air ~ % python3
>>>import pygame

1.2开始游戏项目

游戏UML图如下所示:

1.2.1 创建alien_invasion.py

实现如下功能:

  • 创建Pygame窗口以及响应用户输入
  • 设置背景颜色
  • 创建一个用于存储游戏统计信息的实例
  • 创建一艘飞船,一个子弹编组和一个外星人编组
  • 创建外星人群
  • 监视键盘和鼠标事件

源码如下:

import pygamefrom settings import Settingsfrom ship import Shipimport game_functions as gf from pygame.sprite import Group from alien import Alienfrom scoreboard import Scoreboardfrom game_stats import GameStatsdef 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")# 创建一个用于存储游戏统计信息的实例stats = GameStats(ai_settings)# 创建一艘飞船,一个子弹编组和一个外星人编组ship = Ship(ai_settings, screen)bullets = Group()aliens = Group()# 创建一艘飞船ship = Ship(ai_settings, screen)#创建一个用于存储子弹的编组bullets = Group()# 创建外星人群gf.create_fleet(ai_settings, screen,  ship, aliens)# 创建存储游戏统计信息的实例,并创建记分牌# stats = GameStats(ai_settings)# sb = Scoreboard(ai_settings, screen, stats)# 开始游戏的主循环while True:gf.check_events(ai_settings, screen, ship, bullets)if stats.game_active:ship.update()gf.update_bullets(ai_settings, screen, ship, aliens, bullets)gf.update_aliens(ai_settings, stats, screen, ship, aliens, bullets)# bullets.update()# gf.update_aliens(ai_settings, ship,  aliens)gf.update_screen(ai_settings, screen, ship, aliens, bullets)# 在飞船和外星人后面重绘所有的子弹for bullet in bullets:bullet.draw_bullet()# 监视键盘和鼠标事件for event in pygame.event.get():if event.type == pygame.QUIT:sys.exit()# 每次循环时都重绘屏幕screen.fill(ai_settings.bg_color)ship.blitme()# 让最近绘制的屏幕可见pygame.display.flip()run_game()

1.2.2 创建settings.py

实现功能如下:

  • 创建名为Settings的类,用于将所有设置存储在一个地方

程序源码如下:

class Settings():"""存储《外星人入侵》的所有设置的类"""def __init__(self):"""初始化游戏的设置"""# 屏幕设置self.screen_width = 1200self.screen_height = 800self.bg_color = (230, 230, 230)# 飞船的设置self.ship_speed_factor = 1.5self.ship_limit = 3# 子弹设置self.bullet_speed_factor = 12self.bullet_width = 3self.bullet_height = 12self.bullet_color = 60, 60, 60self.bullets_allowed = 30000# 外星人设置self.alien_speed_factor =  1self.fleet_drop_speed = 10# fleet_direction为1表示向右转,为-1表示向左转self.fleet_direction = 1#以什么样的速度加快游戏节奏self.speedup_scale = 1.1# 加快游戏节奏的速度self.score_scale = 1.5self.initialize_dynamic_settings()def initialize_dynamic_settings(self):"""初始化随游戏进行而变化的设置"""self.ship_speed_factor = 1.5self.bullet_speed_factor = 3self.alien_speed_factor = 1# fleet_direction为1表示向右; 为-1表示向左self.fleet_direction = 1# 记分self.alien_points = 50def increase_speed(self):"""提高速度设置"""self.ship_speed_factor *= self.speedup_scaleself.bullet_speed_factor *= self.speedup_scaleself.alien_speed_factor *= self.speedup_scaleself.alien_points = int(self.alien_points * self.score_scale)print(self.alien_points)

1.2.3创建ship.py

实现功能如下:

  • 负责管理飞船的大部分行为

源码如下:

"""
处理图像用矩形代替游戏图像元素,矩形是简单的几何形状
"""
import pygame
from pygame.sprite import Spriteclass Ship(Sprite):"""初始化飞船并设置初始位置"""def __init__(self, ai_settings, screen):"""初始化飞船,并设置其起始位置"""super(Ship, self).__init__()self.screen = screenself.ai_settings = ai_settings# 加载飞船图像并获取其外接矩形, load返回surfaceself.image = pygame.image.load('images/ship.bmp')# rect是rectangle缩写, get_rect()获取相应的surface属性rectself.rect = self.image.get_rect()self.screen_rect = screen.get_rect()# 将每艘新飞船放在屏幕底部中央self.rect.centerx = self.screen_rect.centerxself.rect.bottom = self.screen_rect.bottom# 在飞船的属性center中存储小数值self.center = float(self.rect.centerx)# 移动标志self.moving_right = False self.moving_left = Falsedef update(self):"""根据移动标志调整飞船的位置"""# 更新飞船的center值,而不是rectif self.moving_right and self.rect.right < self.screen_rect.right:self.center += self.ai_settings.ship_speed_factorif self.moving_left and self.rect.left > 0:self.center -= self.ai_settings.ship_speed_factor# 根据self.center更新rect对象self.rect.centerx = self.centerdef blitme(self):"""在指定位置绘制飞船"""self.screen.blit(self.image, self.rect)def center_ship(self):"""让飞船在屏幕上居中"""self.center = self.screen_rect.centerx

1.2.4 创建game_functions.py

实现功能如下:

  • 游戏事件管理

程序源码如下:

from asyncio import events
# from fcntl import F_SEAL_SEAL
import imp
from re import A
import sys
from zoneinfo import available_timezonesfrom time import sleepimport pygamefrom settings import Settingsfrom ship import Ship from bullet import Bulletfrom alien import Aliendef check_events(ai_settings, screen,  ship, 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_keydown_events(event, ai_settings, screen, ship, bullets)elif event.type == pygame.MOUSEBUTTONDOWN:mouse_x, mouse_y = pygame.mouse.get_pos()check_play_button(ai_settings, screen, stats, sb, play_button, ship, aliens, bullets, mouse_x, mouse_y)def check_keydown_events(event, ai_settings, screen, ship, bullets):"""响应按键"""if event.key == pygame.K_RIGHT:ship.moving_right = Trueelif event.key == pygame.K_LEFT:ship.moving_left = Trueelif event.key == pygame.K_SPACE:fire_bullet(ai_settings, screen, ship, bullets)# 创建一颗子弹,并将其加入到编组bullets中if len(bullets) < ai_settings.bullets_allowed:new_bullet = Bullet(ai_settings, screen, ship)bullets.add(new_bullet)# 如果按q键,退出elif event.key == pygame.K_q:sys.exit()def check_keyup_events(event, ai_settings, screen, ship, bullets):"""响应松开"""if event.key == pygame.K_RIGHT:ship.moving_right = Falseelif event.key == pygame.K_LEFT:ship.moving_left = Falsedef check_aliens_bottom(ai_settings, stats, screen, 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, ship, aliens, bullets)break# 检测子弹和外星人之间的碰撞
def check_bullet_alien_collisions(ai_settings, screen, ship, aliens, bullets):"""响应子弹和外星人发生碰撞"""# 删除发生碰撞的子弹和外星人collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)if len(aliens) == 0:# 删除现有的所有子弹, 并创建一个新的外星人群bullets.empty()create_fleet(ai_settings, screen, ship, aliens)if len(aliens) == 0:# 如果整群外星人都被消灭,就提高一个等级bullets.empty()ai_settings.increase_speed()# 提高等级stats.level += 1sb.prep_level()create_fleet(ai_settings, screen, ship, aliens)def check_play_button(ai_settings, screen, stats, sb, play_button, ship, aliens, bullets, mouse_x, mouse_y):"""在玩家单击Play按钮时开始游戏"""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()def check_high_score(stats, sb):"""检查是否诞生了新的最高分"""if stats.score > stats.high_score:stats.high_score = stats.score  sb.prep_high_score()def check_fleet_edges(ai_settings, aliens):"""有外星人到达边缘时采取相应的措施"""for alien in aliens.sprites():if alien.check_edges():change_fleet_direction(ai_settings, aliens)breakdef change_fleet_direction(ai_settings, aliens):"""将整群外星人下移, 并改变它们的方向"""for alien in aliens.sprites():alien.rect.y += ai_settings.fleet_drop_speedai_settings.fleet_direction *= -1def update_aliens(ai_settings, stats, screen, ship, aliens, bullets):"""检查是否有外星人位于屏幕边缘,并更新整群外星人的位置"""check_fleet_edges(ai_settings, aliens)aliens.update()# 检测外星人和飞船之间的碰撞if pygame.sprite.spritecollideany(ship, aliens):ship_hit(ai_settings, stats, screen, ship, aliens, bullets)print("Ship hit!!!")# 检测是否有外星人到达屏幕底端check_aliens_bottom(ai_settings, stats, screen, ship, aliens, bullets)def update_screen(ai_settings, screen, ship, aliens, bullets):"""更新屏幕上的图案,并切换到新屏幕"""# 每次循环时都重绘屏幕screen.fill(ai_settings.bg_color)# 在飞船和外星人后面重绘所有子弹for bullet in bullets.sprites():bullet.draw_bullet()ship.blitme()# alien.blitme()aliens.draw(screen)# 让最近绘制的屏幕可见pygame.display.flip()def update_bullets(ai_settings, screen, ship, aliens, bullets):"""更新子弹的位置,并删除已消失的子弹"""# 更新子弹的位置bullets.update()# 删除已消失的子弹for bullet in bullets.copy():if bullet.rect.bottom <= 0:bullets.remove(bullet)check_bullet_alien_collisions(ai_settings, screen, ship, aliens, bullets)# 检查是否有子弹击中了外星人# 如果是这样,就删除相应的子弹和外星人collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)if len(aliens) == 0:#删除现有的子弹并新建一群外星人bullets.empty()create_fleet(ai_settings, screen, ship, aliens)def ship_hit(ai_settings, stats, screen, ship, aliens, bullets):"""响应被外星人撞到的飞船"""# 将ships_left减1stats.ships_left -= 1# 清空外星人列表和子弹列表aliens.empty()bullets.empty()# 创建一群新的外星人,并将飞船放到屏幕底端中央create_fleet(ai_settings, screen, ship, aliens)ship.center_ship()# 暂停sleep(0.5)if stats.ships_left > 0:# 将ships_left减1stats.ships_left -= 1# 更新记分牌# sb.prep_ships()else:stats.game_active = Falsedef 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 get_number_aliens_x(ai_settings, alien_width):"""计算每行可容纳多少个外星人"""# 屏幕的宽度减掉2个外星人的宽度,因为两侧各空出一个外星人available_space_x = ai_settings.screen_width - 2 * alien_width# 外星人和空格间距是相等的, 所以除以2number_aliens_x = int(available_space_x / (2 * alien_width))return number_aliens_xdef create_alien(ai_settings, screen, aliens, alien_number, row_number):"""创建一个外星人并将其放在当前行"""alien = Alien(ai_settings, screen)alien_width = alien.rect.widthalien.x = alien_width + 2 * alien_width * alien_numberalien.rect.x = alien.xalien.rect.y = alien.rect.height + 2 * alien.rect.height * row_numberaliens.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_number_rows(ai_settings, ship.rect.height, alien.rect.height)# 创建外星人群for row_number in range(number_rows):# 创建第一行外星人for alien_number in range(number_aliens_x):# 创建一个外星人并将其加入当前行create_alien(ai_settings, screen, aliens, alien_number, row_number)def get_number_rows(ai_settings, ship_height, alien_height):"""计算屏幕可容纳多少行外星人"""available_space_y = (ai_settings.screen_height - (3 * alien_height) - ship_height)number_rows = int(available_space_y / (2 * alien_height))return number_rows

1.2.5 创建bullet.py

实现功能如下:

  • 射击功能,按空格键时发射子弹(小矩形)

源码如下:

# Sprite:小妖怪,调皮鬼
import impimport pygame
from pygame.sprite import Spriteclass Bullet(Sprite):"""一个对飞船发射的子弹进行管理的类"""def __init__(self, ai_settings, screen, ship):"""在飞船所处的位置创建一个子弹对象"""super(Bullet, self).__init__()self.screen = screen# 在(0,0)处创建一个表示子弹的矩形,再设置正确的位置self.rect = pygame.Rect(0, 0, ai_settings.bullet_width,ai_settings.bullet_height)# x代表坐标,centerx代表中心的x坐标, 子弹的矩形中心x坐标等于飞船的矩形中心x坐标self.rect.centerx = ship.rect.centerx# 子弹的顶在飞船的矩形顶self.rect.top = ship.rect.top# 存储用小数表示的子弹位置self.y = float(self.rect.y)self.color = ai_settings.bullet_colorself.speed_factor = ai_settings.bullet_speed_factordef update(self):"""向上移动子弹"""# 更新表示子弹位置的小数值self.y -= self.speed_factor# 更新表示子弹的rect的位置self.rect.y = self.ydef draw_bullet(self):"""在屏幕上绘制子弹"""pygame.draw.rect(self.screen, self.color, self.rect)

1.2.6创建alien.py

实现功能如下:

  • 创建名为Alien类,实现外星人具备的功能模块

源码如下:

import pygame
from pygame.sprite import Spriteclass Alien(Sprite):"""表示单个外星人的类"""def __init__(self, ai_settings, screen):"""初始化外星人并设置其起始位置"""super(Alien, self).__init__()self.screen = screenself.ai_settings = ai_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 blitme(self):"""在指定位置绘制外星人"""self.screen.blit(self.image, self.rect)def update(self):"""向左或向右移动外星人"""self.x += (self.ai_settings.alien_speed_factor * self.ai_settings.fleet_direction)self.rect.x = self.xdef check_edges(self):"""如果外星人位于屏幕边缘, 就返回True"""screen_rect = self.screen.get_rect()if self.rect.right >= screen_rect.right:return Trueelif self.rect.left <= 0:return True

1.2.7创建game_stats.py

实现如下功能:

  • 标志游戏状态

源码如下:

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

游戏运行画面如下:

Python编程:《外星人入侵》相关推荐

  1. Python基础十五:面向对象编程四:高级特性

    Python基础十五:面向对象编程四:高级特性 Python基础系列内容为学习廖雪峰老师Python3教程的记录,廖雪峰老师官网地址:廖雪峰Python3教程 Author:yooongchun Em ...

  2. 学习python第十五天,面对对象

    学习python第十五天,面对对象 面对对象又叫劝退对象,要么劝退你的对象,要么python劝退你,hhhh 开玩笑,但是这块知识点确实比较难 面向对象编 面向对象编程 指令式编程---->面向 ...

  3. python灰度图片格式_[Python图像处理] 十五.图像的灰度线性变换

    [Python图像处理] 十五.图像的灰度线性变换 发布时间:2019-03-28 00:08, 浏览次数:619 , 标签: Python 该系列文章是讲解Python OpenCV图像处理知识,前 ...

  4. Dave Python 练习十五 -- 面向对象编程

    #encoding=utf-8 ### *************** 面向对象编程 ******************** #*********** Part 1: 面向对象编程 ******** ...

  5. 零基础该如何系统地自学Python编程?五个阶段带你从小白到大佬

    对于零基础学习或是已经学完基础不知道下一步该干什么的朋友,可以看看这篇缓解迷茫.今天分享下如何系统地自学Python规划目标,有一个学习目标在去行动. 有了目标,怎么行动呢?建议采用视频+书籍的方式进 ...

  6. python北京理工大学推荐的书-2020最新的学Python编程的五本必读好书

    我从海量Python图书中精挑细选了5本Python完整技术栈相关的书籍.读书,只读好书,经典好书,这5本就是! 提前说一句,可能对大部分人来说,买实体书不现实,因为我是一名python开发工程师,所 ...

  7. 无字天书之Python第十五页(Excel表格操作)

    博客内容 传送门 正文读 正文写 到此Python基础就此结束- 传送门 无字天书之Python第一页 无字天书之Python第二页 无字天书之Python第三页 无字天书之Python第四页 无字天 ...

  8. Python 第十五天 串讲

    Python: 弱类型的.解释型的高级编程语言 特点:简单.优雅.明确 变量:程序运行过程中产生的中间值,供给后面的程序使用. 变量的命名规范: 1.由数字.字母.下划线组成 2.不能以数字开头,更不 ...

  9. 面向对象编程(十五)——抽象类和接口

    一.抽象(abstract)类 抽象类,说白了就是包含抽象方法的类.那什么是抽象方法?抽象方法是一种特殊的方法:抽象方法只有声明,而没有具体的实现.抽象方法说白了就是只有方法的声明,没有方法体. 抽象 ...

  10. [Python人工智能] 十五.无监督学习Autoencoder原理及聚类可视化案例详解

    从本专栏开始,作者正式研究Python深度学习.神经网络及人工智能相关知识.前一篇文章详细讲解了循环神经网络LSTM RNN如何实现回归预测,通过sin曲线拟合实现如下图所示效果.本篇文章将分享无监督 ...

最新文章

  1. SmartForms 小技巧
  2. 交换机发生网络通信故障问题时该怎么办?
  3. 2014年ENVI/IDL遥感应用与开发培训班-11月重庆站 開始报名了
  4. (转)CocosCreator零基础制作游戏《极限跳跃》二、制作游戏开始场景
  5. 学习日报 day02 java的语法骨架 myeclipse编辑java代码
  6. Linux进程管理:上帝视角看进程调度
  7. linux7编译mysql5.7安装,CentOS 7.4 使用源码包编译安装MySQL 5.7.20
  8. vue获取input焦点事件_vue获取input焦点,弹框后自动获取input焦点
  9. java三星题之_JAVA三星题之playing a TicTacToe game
  10. html 中电话号码的使用
  11. Visual Basic 概述
  12. 网络授时设备(NTP时钟服务器)助力智能交通管控平台
  13. Linux教程+操作系统教程 -- 大全
  14. 长ping域名带时间戳
  15. 继美国后新加坡电信运营商遭DDoS攻击 部分用户断网
  16. java解析HL7协议报文工具 HAPI(SpringBoot版本)
  17. python web py入门(4)-从数据库读取数据显示到网页
  18. 《区块链助力粤港澳大湾区一体化发展报告(2022)》发布
  19. 官网电子安全证书端口即将到期!新型诈骗短信!
  20. 各种SQL子查询实例

热门文章

  1. 什么是Spring Profiles以及如何使用
  2. 已解决‘pyhton‘不是内部或外部命令,也不是可运行的程序或批处理文件。
  3. 计算机新的未来之路华文彩云字体,大学计算机基础教学大纲(72学时版)
  4. 升级的脉脉,正在以招聘业务铺开商业化版图
  5. 6个办公软件,产品运营必须下载
  6. NetApp Ontap系统降级(重新安装)流程
  7. Unity3D3个录屏插件PC,Android,IOS都有
  8. 使用Electron打造跨平台桌面应用
  9. mysql中的count(1)、count(*)、count(id)哪个更快?
  10. echarts图表截图保存成word文件的方法