外星人入侵(python)
前言
代码来源《python编程从入门到实践》Eric Matthes 署 袁国忠 译
使用软件:PyCharm Community Editor 2022
目的:记录一下按照书上敲的代码
alien_invasion.py
游戏的一些初始化设置,调用已经封装好的函数方法,一个函数的调用实现一个游戏的部分。
import sys
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf
from pygame.sprite import Group
from alien import Alien
from game_stats import GameStatsdef run_game():# 初始化游戏并创建一个屏幕对象pygame.init()ai_settigns = Settings()# 里面是一个元组screen = pygame.display.set_mode((ai_settigns.screen_width, ai_settigns.screen_height))# 窗口尺寸,宽高# screen=pygame.display.set_mode((1200,800))# 窗口标题pygame.display.set_caption("Alien Invasion")#创建一个用于存储游戏统计信息的实例stats=GameStats(ai_settigns)# 设置背景色# bg_color=(230,230,230)# 创建一艘飞船、一个子弹编组和一个外星人编组ship = Ship(ai_settigns, screen)# 创建一个用于存储子弹的编组bullets = Group()# 创建一个外星人# alien=Alien(ai_settigns,screen)aliens = Group()# 创建外星人群gf.create_fleet(ai_settigns, screen, ship, aliens)# 开始游戏的主循环while True:gf.check_events(ai_settigns, screen, ship, bullets)if stats.game_active:ship.update()gf.update_bullets(ai_settigns, screen, ship, aliens, bullets)gf.update_aliens(ai_settigns,stats,screen,ship, aliens,bullets)# print(len(bullets))gf.update_screen(ai_settigns, screen, ship, aliens, bullets)# 监视键盘和鼠标事件# for event in pygame.event.get():# if event.type==pygame.QUIT:# sys.exit()# 每次循环都重绘屏幕# screen.fill(bg_color)# screen.fill(ai_settigns.gb_color)# ship.blitme()# 让最近绘制的屏幕可见# pygame.display.flip()run_game()
game_functions.py
游戏主体,具体功能的实现被封装在里面,按下按键、松开按键的响应,界面的更新、子弹的发射、外星人和飞船之间碰撞的检查等等。
import sys
import pygame
from bullet import Bullet
from alien import Alien
from time import sleepdef 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)# 按下键盘上的q键同样关闭游戏界面(需要是英文状态下)elif event.key == pygame.K_q:sys.exit()def check_keyup_events(event, ship):# 响应松开if event.key == pygame.K_RIGHT:ship.moving_right = Falseelif event.key == pygame.K_LEFT:ship.moving_left = Falsedef 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:# if event.key == pygame.K_RIGHT:# ship.moving_right = True# elif event.key == pygame.K_LEFT:# ship.moving_left = Truecheck_keydown_events(event, ai_settings, screen, ship, bullets)elif event.type == pygame.KEYUP:# if event.key == pygame.K_RIGHT:# ship.moving_right = False# elif event.key == pygame.K_LEFT:# ship.moving_left = Falsecheck_keyup_events(event, ship)def update_screen(ai_settings, screen, ship, aliens, bullets):# 更新屏幕上的图像,并切换到新屏幕# 每次循环时都重绘屏幕screen.fill(ai_settings.gb_color)# 在飞船和外星人后面重绘所有子弹for bullet in bullets.sprites():bullet.draw_bullet()ship.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_collision(ai_settings, screen, ship, aliens, bullets)def check_bullet_alien_collision(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 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)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_aliens_x(ai_settings, alien_width):# 计算每行可容纳多少个外星人available_space_x = ai_settings.screen_width - 2 * alien_widthnumber_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 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_rowsdef update_aliens(ai_settings, stats, screen, ship, aliens, bullets):# 检查是否有外星人位于屏幕边缘,更新外星人群中所有外星人的位置check_fleet_edges(ai_settings, aliens)aliens.update()# 检测外星人和飞船之间的碰撞if pygame.sprite.spritecollideany(ship, aliens):print("Ship hit!!!")ship_hit(ai_settings, stats, screen, ship, aliens, bullets)# 检查是否有外星人到达屏幕底端check_aliens_bottom(ai_settings, stats, screen, ship, aliens, bullets)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 ship_hit(ai_settings, stats, screen, ship, aliens, bullets):# 响应被外星人撞到的飞船if stats.ships_left > 0:# 将ships_letf减1stats.ships_left -= 1# 清空外星人列表和子弹列表aliens.empty()bullets.empty()# 创建一群新的外星人,并将飞船放到屏幕底端中央create_fleet(ai_settings, screen, ship, aliens)ship.center_ship()# 暂停sleep(0.5)else:stats.game_active = 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
settings.py
游戏的一些初始化数据的储存,子弹的速度,大小,屏幕的大小等等。
class Settings():# 储存《外星人入侵》所设置的类def __init__(self):# 初始化游戏的设置# 屏幕设置self.screen_width = 1200self.screen_height = 800self.gb_color = (230, 230, 230)# 飞船设置# 位置self.ship_speed_factor = 1.5self.ship_limit = 3# 子弹设置(宽高,颜色)self.bullet_speed_factor = 1 # 速度self.bullet_width = 3 # 宽度self.bullet_height = 15 # 高度self.bullet_color = 60, 60, 60 # 颜色self.bullets_allowed = 3# 外星人设置self.alien_speed_factor = 1self.fleet_drop_speed = 10# fleet_direction为1表示向右移,为-1表示向左移self.fleet_direction = 1
ship.py
飞船的初始化信息(在屏幕上面显示的位置)和移动。
import pygameclass Ship():def __init__(self, ai_settings, screen):# 初始化飞船并设置其初始位置self.screen = screenself.ai_settings = ai_settings# 加载飞船图像并获取外接矩形self.image = pygame.image.load('images/ship.png')self.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 = Falseself.moving_left = Falsedef update(self):# 根据移动标志调整飞船的位置# 更新飞船的center值,而不是rect# if self.moving_right:# 增加不能越界的条件if self.moving_right and self.rect.right < self.screen_rect.right:# self.rect.centerx += 1self.center += self.ai_settings.ship_speed_factor# elif self.moving_left:if self.moving_left and self.rect.left > 0:# self.rect.centerx -= 1self.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
alien.py
外星人的初始信息(在屏幕上面显示的位置)和移动。
import pygame
from pygame.sprite import Spriteclass Alien(Sprite):# 表示单个外星人的类def __init__(self, ai_settings, screen):# 初始化外星人并设置起始位置super(Alien, self).__init__()self.screen = screenself.ai_settins = ai_settings# 加载外星人图像,并设置其rect属性self.image = pygame.image.load('images/alien.png')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_settins.alien_speed_factorself.x += (self.ai_settins.alien_speed_factor * self.ai_settins.fleet_direction)self.rect.x = self.xdef check_edges(self):# 如果外星人位于屏幕边缘,就返回Truescreen_rect = self.screen.get_rect()if self.rect.right >= screen_rect.right:return Trueelif self.rect.left <= 0:return True
bullet.py
子弹的显示和移动。
import 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)self.rect.centerx = ship.rect.centerxself.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)
game_stats.py
游戏是否结束,统计游戏运行期间的变化。
class GameStats():# 跟踪游戏的统计信息def __init__(self, ai_settings):# 初始化统计信息self.ai_settings = ai_settingsself.reset_stats()# 游戏刚启动时处于活动状态self.game_active=Truedef reset_stats(self):# 初始化在游戏运行期间可能变化的统计信息self.ships_left = self.ai_settings.ship_limit
我们的飞船和下面的飞船相撞或者撞到下面的墙都会输出:“Ship hit!!!”
图片可以自己去找,如果想修改图片可以运用电脑的“画图”工具来实现。
总结
主要是记录一下这个,毕竟敲了这么久了,不过还是要理解。
整个游戏的结构还是是否清晰的,游戏的流程储存在alien_invasion中,为了让程序的可读性更好,把功能封装成对应的函数,把这些函数全部储存到game_functions中,把游戏需要初始化的数据(子弹的大小,颜色,速度等等)全部储存到settings中,ship是对飞船的抽象表示,alien是对外星人的抽象表示,bullet是对子弹的抽象表示,最后用game_stats来记录整个游戏。
相关文章:

外星人入侵(python)
前言 代码来源《python编程从入门到实践》Eric Matthes 署 袁国忠 译 使用软件:PyCharm Community Editor 2022 目的:记录一下按照书上敲的代码 alien_invasion.py 游戏的一些初始化设置,调用已经封装好的函数方法,一个函数的…...

Unity中开发程序打包发布
添加ESC脚本 使用Unity打包发布的过程中,考虑到打开的程序会处于全屏界面,而此时我们又会有退出全屏的需求,因此需要添加ESC脚本,当我们单击ESC脚本的过程中,退出全屏模式。 在Assets/Scenes下,创建esc.cs…...

2024.2.1日总结
web的运行原理: 用户通过浏览器发送HTTP请求到服务器(网页操作)。web服务器接收到用户特定的HTTP请求,由web服务器请求信息移交给在web服务器中部署的javaweb应用程序(Java程序)。启动javaweb应用程序执行…...

LeetCode解法汇总2670. 找出不同元素数目差数组
目录链接: 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目: https://github.com/September26/java-algorithms 原题链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 描述: 给你一个下…...

STM32目录结构
之前一直头疼的32目录,比51复杂,又没有C规律,也不像python脚本文件关联不强,也不像工整的FPGA工程,编的时候到处放,爆出的错千奇百怪。短暂整理了一个,还是没有理得很轻。 startup_stm32f10x_m…...

算法专题:记忆搜索
参考练习习题总集 文章目录 前置知识练习习题87. 扰乱字符串97. 交错字符串375. 猜数字大小II403. 青蛙过河464. 我能赢吗494. 目标和552. 学生出勤记录II576. 出借的路径数 前置知识 没有什么特别知识,只有一些做题经验。要做这类型的题目,首先写出暴…...

【数据分享】1929-2023年全球站点的逐日最低气温数据(Shp\Excel\免费获取)
气象数据是在各项研究中都经常使用的数据,气象指标包括气温、风速、降水、湿度等指标,其中又以气温指标最为常用!说到气温数据,最详细的气温数据是具体到气象监测站点的气温数据! 之前我们分享过1929-2023年全球气象站…...

2024美赛数学建模D题思路+模型+代码+论文(持续更新)
2024美赛数学建模A题B题C题D题E题F题思路模型代码论文:开赛后第一时间更新,获取见文末名片 组队环节: 美赛最多是3个人参赛,一般的队伍都是由三人组成(当然如果你很大佬也可以一个人参赛),队伍…...

dubbo+sentinel最简集成实例
说明 在集成seata后,下面来集成sentinel进行服务链路追踪管理~ 背景 sample-front网关服务已配置好 集成 一、启动sentinel.jar 1、官网下载 选择1:在本地启动 nohup java -Dserver.port8082 -Dcsp.sentinel.dashboard.serverlocalhost:8082 -Dp…...

9.2爬楼梯(LC70-E)
算法: 多举几个例子,找规律: 爬到第一层楼梯有一种方法,爬到二层楼梯有两种方法。 那么第一层楼梯再跨两步就到第三层 ,第二层楼梯再跨一步就到第三层(时序)。 所以到第三层楼梯的状态可以由…...

Asp.net移除Server, X-Powered-By, 和X-AspNet-Version头
移除X-AspNet-Version很简单,只需要在Web.config中增加这个配置节: <httpRuntime enableVersionHeader"false" />移除Server在Global.asax文件总增加: //隐藏IIS版本 protected void Application_PreSendRequestHeaders() {HttpContext.Current.Res…...

reactnative 调用原生ui组件
reactnative 调用原生ui组件 1.该样例已textView,介绍。 新建MyTextViewManager 文件,继承SimpleViewManager。import android.graphics.Color; import andr…...

面试手写第五期
文章目录 一. 实现一个函数用来对 URL 的 querystring 进行编码二. 如何实现一个数组洗牌函数 shuffle三. 异步加法的几种方式四. 实现trim函数五. 求多个数组的交集六. 手写实现render函数七. 驼峰转- -转驼峰八. instanceof实现九. 组合问题十. 字符串分组 一. 实现一个函数用…...

【CSS】css选择器和css获取第n个元素(:nth-of-type(n)、:nth-child(n)、first-child和last-child)
:nth-of-type、:nth-child的区别 一、css选择器二、:nth-of-type、:nth-child的区别:nth-of-type(n):选择器匹配属于父元素的特定类型的第N个子元素:nth-child(n):选择器匹配属于其父元素的第 N 个子元素,不论元素的类型:first-child…...

解析Excel文件内容,按每列首行元素名打印出某个字符串的统计占比(超详细)
目录 1.示例: 1.1 实现代码1:列数为常量 运行结果: 1.2 实现代码2:列数为变量 运行结果: 1.示例: 开发需求:读取Excel文件,统计第3列到第5列中每列的"False"字段占…...

qt中遇到[Makfile.Debug:119:debug/app.res.o] Error 1的原因以及解决方法
当我们将项目已到本地qt环境中会出现下图的代码错误 解决方法:在主界面中,点击左边的项目栏,选择构建设置,看Shadow build下面的路径是否为中文,改成英文,或者直接将Shadow build这个 √ 去掉就行了,如图已…...

pytorch调用gpu训练的流程以及示例
首先需要确保系统上安装了CUDA支持的NVIDIA GPU和相应的驱动程序。 基本步骤如下 检查CUDA是否可用: 使用 torch.cuda.is_available() 来检查CUDA是否可用。 指定设备: 可以使用 torch.device(“cuda:0”) 来指定要使用的GPU。如果系统有多个GPU&…...

学习Android的第一天
目录 什么是 Android? Android 官网 Android 应用程序 Android 开发环境搭建 Android 平台架构 Android 应用程序组件 附件组件 Android 第一个程序 HelloWorld 什么是 Android? Android(发音为[ˈnˌdrɔɪd],非官方中文…...

回归预测 | Matlab实现CPO-LSTM【24年新算法】冠豪猪优化长短期记忆神经网络多变量回归预测
回归预测 | Matlab实现CPO-LSTM【24年新算法】冠豪猪优化长短期记忆神经网络多变量回归预测 目录 回归预测 | Matlab实现CPO-LSTM【24年新算法】冠豪猪优化长短期记忆神经网络多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现CPO-LSTM【24年新算…...

Typora导出html文件图片自动转换成base64
Typora导出html文件图片自动转换成base64 一、出现问题二、解决方案三、编码实现3.1.创建Java项目3.2.代码3.3.打包成Jar包 四、如何使用endl 一、出现问题 typora 导出 html 的时候必须带有原图片,不方便交流学习,文件太多显得冗余,只有将图…...

『C++成长记』string使用指南
🔥博客主页:小王又困了 📚系列专栏:C 🌟人之为学,不日近则日退 ❤️感谢大家点赞👍收藏⭐评论✍️ 目录 一、string类介绍 二、string类的常用接口说明 📒2.1string类对象的常…...

硬件连通性测试:构建数字世界的无形基石
在当今数字化的时代,硬件设备的连通性对于系统的正常运行至关重要。硬件连通性测试作为确保设备协同工作的关键步骤,扮演着构建数字世界的无形基石的角色。本文将深入探讨硬件连通性测试的意义、方法以及在现代科技生态系统中的重要性。 1. 硬件连通性测…...

mysql的安装与卸载
mysql的安装 mysql 8.0的安装步骤: 1. 从mysql官网上下载mysql安装软件 https://www.mysql.com/ 2. 双击msi文件进行安装 3. 选择安装的类型 选择server only可以远程访问数据库 4. 选择服务并安装 5. 安装中,安装完成后直接next 6. 进入mysql的配置 …...

假期作业 2.2
第一章 命名空间 一.选择题 1、编写C程序一般需经过的几个步骤依次是( B ) A. 编辑、调试、编译、连接 B. 编辑、编译、连接、运行 C. 编译、调试、编辑、连接 D. 编译、编辑、连接、运行 2、所谓数据封装就是将一组数据和与这组数…...

运维SRE-02 正则表达式、grep
1.特殊符号补充 1.1位置相关的特殊符号 . 当前目录 .. 当前目录的上级目录 ~ 当前用户家目录 / 根目录 cd - 返回上次所在目录1.2熟练掌握 # 注释符号,root命令提示符 | 管道符号.1.3了解其他特殊符号 $ 取值(取出变量的值),普通用户的提示符 ! % ^ & * (){} [] ; ? \…...

【SpringCloud】使用OpenFeign进行微服务化改造
目录 一、需求与背景二、OpenFeign 远程调用技术原理三、项目代码演示3.1 引入依赖3.2 实现OpenFeign注解修饰接口3.3 指定 OpenFeign 远程调用接口的扫描路径 四、OpenFeign 在日志中打印Request和Response五、OpenFeign 客户端超时配置六、使用 OpenFeign 实现服务降级6.1 实…...

DRV8313和L298N都是电机驱动,一个是驱动三相FOC无刷直流电机的,一个是驱动有刷电机,使stm32控制无刷电机简单入门知识
DRV8313和L298N都是电机驱动器,但它们之间存在一些关键的区别: DRV83131: 由德州仪器(TI)制造。 具有集成的场效应晶体管(FET)。 最大电压为65V。 峰值电流为3A。 适用于三相电机驱动。 L298N…...

React16源码: React中event事件系统初始化源码实现
event 事件系统初始化 1 )概述 react事件系统比较的复杂,它是基于dom的事件系统在dom事件系统上面进行了一个深度的封装它里面的很多实现逻辑都是自由的一套在初始化 react-dom 的源码的时候,会为react的事件系统注入 reactdom 相关的一些插…...

Qt6入门教程 15:QRadioButton
目录 一.简介 二.常用接口 三.实战演练 1.径向渐变 2.QSS贴图 3.开关效果 4.非互斥 一.简介 QRadioButton控件提供了一个带有文本标签的单选按钮。 QRadioButton是一个可以切换选中(checked)或未选中(unchecked)状态的选项…...

Json序列化和反序列化 笔记
跟着施磊老师学C 下载:GitHub - nlohmann/json: JSON for Modern C 在single_include/nlohmann里头有一个json.hpp,把它放到我们的项目中就可以了 #include "json.hpp" using json nlohmann::json;#include <iostream> #include <…...