文章目录
- 1.效果展示
- 2. 《外星人入侵》源代码
- 2.1 image
- 2.2 alien_invasion.py
- 2.3 alien.py
- 2.4 bullet.py
- 2.5 button.py
- 2.6 game_stats.py
- 2.7 scoreboarf.py
- 2.8 settings.py
- 2.9 ship.py
最近学习的python第一个项目实战,《外星人入侵》,成功实现所有功能,给大家提供源代码
环境安装:python 3.7+ pygame
安装 pygame
pip install -- user pygame
或者
conda install --user pygame
1.效果展示
先展示效果,消灭外星人,有三条命,按Q是退出全屏,空格键是子弹,按下play键开始游戏,击败外星人飞船会有积分加,三条命之后需要点击play才能再次启动
2. 《外星人入侵》源代码
外星人入侵小游戏文件排版如下,先创建这几个.py文件
2.1 image
2.2 alien_invasion.py
import sys
from time import sleepimport pygamefrom settings import Settings
from ship import Ship
from bullet import Bullet
from alien import Alien
from game_stats import GameStats
from button import Button
from scoreboard import Scoreboardclass 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.sb = Scoreboard(self)self.ship =Ship(self)self.bullets = pygame.sprite.Group()self.aliens = pygame.sprite.Group()self._create_fleet()'''创建play按钮'''self.play_button = Button(self,"Play")# '''设置背景色'''# self.bg_color = (self.settings.bg_color) cuowudef _ship_hit(self):'''响应飞船被外星人撞到'''if self.stats.ships_left >0:'''将ship_left减1并更新记分牌'''self.stats.ships_left -= 1self.sb.prep_ships()'''清除余下的外星人和子弹'''self.aliens.empty()self.bullets.empty()'''创建一群新的外星人,并将飞船放到屏幕底端的中央'''self._create_fleet()self.ship.center_ship()'''暂停'''sleep(0.5)else:self.stats.game_active = Falsepygame.mouse.set_visible(True)def _create_fleet(self):'''创建外星人群''''''创建一个外星人并计算一行可容纳多少个外星人''''''外星人的间距为外星人宽度'''alien = Alien(self)alien_width, alien_height = alien.rect.sizeavailable_space_x = self.settings.screen_width - (2 * alien_width)number_aliens_x = available_space_x // (2 * alien_width )'''计算屏幕可容纳多少行外星人'''ship_height = self.ship.rect.heightavailable_space_y = (self.settings.screen_height -(3 * alien_height) - ship_height)number_rows = available_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.xalien.rect.y =alien.rect.height + 2 * alien.rect.height * row_numberself.aliens.add(alien)def run_game(self):'''开始游戏的主循环'''while True:'''监视键盘和鼠标事件'''self._check_events()if self.stats.game_active:'''调用飞船的方法'''self.ship.update()'''子弹更新'''self._update_bullets()'''让外星人移动'''self._update_aliens() #suojin+weizhi'''每次循环时都会重绘屏幕'''self._update_screen()def _check_fleet_edges(self):'''有外星人到达边缘时采取相应的措施'''for alien in self.aliens.sprites():if alien.check_edges():self._change_fleet_direction()breakdef _change_fleet_direction(self):'''将整群人外星人下一,并改变它们的方向'''for alien in self.aliens.sprites():alien.rect.y += self.settings.fleet_drop_speedself.settings.fleet_direction *= -1def _update_aliens(self):'''检测是否有外星人位于屏幕边缘,更新外星人群中所有外星人的位置'''self._check_fleet_edges()self.aliens.update()'''检测外星人和飞船之间的碰撞'''if pygame.sprite.spritecollideany(self.ship, self.aliens):self._ship_hit()'''检查是否有外星人到达了屏幕底端'''self._check_aliens_bottom() #suojindef _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)elif event.type == pygame.MOUSEBUTTONDOWN:mouse_pos = pygame.mouse.get_pos()self._check_play_button(mouse_pos)def _check_play_button(self,mouse_pos):'''在玩家单机play按钮时开始新游戏'''button_clicked = self.play_button.rect.collidepoint(mouse_pos)if button_clicked and not self.stats.game_active:'''重置游戏设置'''self.settings.initialize_dynamic_settings()'''重置游戏统计信息'''self.stats.reset_stats()self.stats.game_active = Trueself.sb.prep_score()self.sb.prep_level()self.sb.prep_ships()'''清空余下的外星人和子弹'''self.aliens.empty()self.bullets.empty()'''创建一群新的外星人并让飞船居中'''self._create_fleet()self.ship.center_ship()'''隐藏鼠标光标'''pygame.mouse.set_visible(False)def _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 _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_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 = Falsedef _fire_bullet(self):'''创建一颗子弹,并将其加入编组bullets中'''if len(self.bullets) < self.settings.bullets_allowed:new_bullet = Bullet(self)self.bullets.add(new_bullet)def _update_bullets(self):'''更新子弹的位置并删除消失的子弹''''''更新子弹的位置'''self.bullets.update()'''删除消失的子弹'''for bullet in self.bullets.copy():if bullet.rect.bottom <= 0:self.bullets.remove(bullet)self._check_bullet_alien_collisions()def _check_bullet_alien_collisions(self):'''检查是否有子弹击中了外星人如果是,就删除相应的子弹和外星人'''collisions = pygame.sprite.groupcollide(self.bullets, self.aliens, True,True)if collisions:for aliens in collisions.values():self.stats.score += self.settings.alien_points * len(aliens)self.sb.prep_score()self.sb.check_high_score()if not self.aliens:'''删除现有的子弹并新建一群外星人'''self.bullets.empty()self._create_fleet()self.settings.increase_speed()'''提高等级'''self.stats.level += 1self.sb.prep_level()def _update_screen(self):'''更新屏幕上的图像,并切换到新屏幕'''self.screen.fill(self.settings.bg_color)#loule settings.self.ship.blitme()for bullet in self.bullets.sprites():bullet.draw_bullet()self.aliens.draw(self.screen)'''显示得分'''self.sb.show_score()'''如果游戏处于非活动状态,就绘制Play按钮'''if not self.stats.game_active:self.play_button.draw_button()'''让最近绘制的屏幕可见'''pygame.display.flip()if __name__ == "__main__":'''创建游戏实例并运行游戏'''ai = AlienInvasion()ai.run_game()
2.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('image/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.x += self.settings.alien_speed向右移动外星人self.rect.x = self.x
2.4 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)def update(self):'''向上移动子弹''''''更新表示子弹位置的小数值'''self.y -= self.settings.bullet_speed'''更新表示子弹的rect的位置'''self.rect.y = self.ydef draw_bullet(self):'''在屏幕上绘制子弹'''pygame.draw.rect(self.screen, self.color, self.rect)
2.5 button.py
import pygame.fontclass Button:def __init__(self,ai_game,msg):'''初始化按钮的属性'''self.screen = ai_game.screenself.screen_rect = self.screen.get_rect()'''设置按钮的尺寸和其他属性'''self.width, self.height = 200,50self.button_color = (0,255,0)self.text_color =(255,255,255)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渲染为图像,并使其在按钮上居中'''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.centerdef draw_button(self):'''绘制一个用颜色填充的按钮,再绘制文本'''self.screen.fill(self.button_color, self.rect)self.screen.blit(self.msg_image,self.msg_image_rect)
2.6 game_stats.py
class GameStats:'''跟踪游戏的统计信息'''def __init__(self,ai_game):'''初始化统计信息'''self.settings = ai_game.settingsself.reset_stats()'''游戏刚启动时处于活动状态'''self.game_active = False'''任何情况下都不应该重置最高得分'''self.high_score = 0def reset_stats(self):'''初始化在游戏运行期间可能变化的统计信息'''self.ships_left = self.settings.ship_limitself.score = 0self.level = 1
2.7 scoreboarf.py
import pygame.font
from pygame.sprite import Group
from ship import Shipclass Scoreboard:'''显示得分信息的类'''def __init__(self,ai_game):'''初始化显示得分涉及的属性'''self.ai_game = ai_gameself.screen = ai_game.screenself.screen_rect = self.screen.get_rect()self.settings = ai_game.settingsself.stats = ai_game.stats'''显示得分信息时使用的字体设置'''self.text_color = (30,30,30)self.font = pygame.font.SysFont(None,48)'''准备包含最高得分和当前得分的图像'''self.prep_score()self.prep_ships()self.prep_high_score()self.prep_level()#cuowudef prep_ships(self):'''显示还剩下多少艘飞船'''self.ships = Group()for ship_number in range(self.stats.ships_left): #cuowuship =Ship(self.ai_game)ship.rect.x = 10 + ship_number * ship.rect.widthship.rect.y = 10self.ships.add(ship) #cuowudef prep_high_score(self):'''将最高得分转换为渲染的图像'''high_score =round(self.stats.high_score, -1)high_score_str = "{:,}".format(high_score)self.high_score_image = self.font.render(high_score_str,True,self.text_color,self.settings.bg_color)'''将最高得分放在屏幕顶部中央'''self.high_score_rect = self.high_score_image.get_rect()self.high_score_rect.centerx = self.screen_rect.centerxself.high_score_rect.top = self.score_rect.topdef prep_score(self):'''将得分转换成一副渲染的图像'''rounded_score = round(self.stats.score, -1)score_str ="{:,}".format(rounded_score)self.score_image =self.font.render(score_str,True,self.text_color,self.settings.bg_color)'''在屏幕右下显示得分'''self.score_rect =self.score_image.get_rect()self.score_rect.right = self.screen_rect.right - 20self.score_rect.top = 20def show_score(self):'''在屏幕上显示得分和等级和余下的飞船数'''self.screen.blit(self.score_image, self.score_rect)self.screen.blit(self.high_score_image, self.high_score_rect)self.screen.blit(self.level_image, self.level_rect )self.ships.draw(self.screen)def check_high_score(self):'''检查是否诞生了新的最高得分'''if self.stats.score > self.stats.high_score:self.stats.high_score = self.stats.scoreself.prep_high_score()def prep_level(self):'''将等级转化为渲染的图像'''level_str = str(self.stats.level)self.level_image = self.font.render(level_str,True,self.text_color, self.settings.bg_color)'''将等级放在得分下面'''self.level_rect = self.level_image.get_rect()self.level_rect.right = self.score_rect.rightself.level_rect.top = self.score_rect.bottom +10
2.8 settings.py
class Settings:'''存储游戏《外星人入侵》中所有设置的类'''def __init__(self):'''初始化游戏的静态设置''''''屏幕设置'''self.screen_width = 1200self.screen_height =800self.bg_color = (230,230,230)self.ship_limit = 3self.bullet_width = 3self.bullet_height = 15self.bullet_color = (60, 60, 60)self.bullets_allowed = 3 # 设置存储的最大子弹数为3self.fleet_drop_speed = 10'''加快游戏节奏的速度'''self.speedup_scale = 1.1self.score_scale = 1.5self.initialize_dynamic_settings()# '''设置飞船速度'''# self.ship_speed = 1.5# '''子弹设置'''# self.bullet_speed = 1.5# self.alien_speed = 1.0# '''fleet_direction为1表示向有意,-1表示向左移'''# self.fleet_direction = 1 cuowudef initialize_dynamic_settings(self):'''初始化随游戏进行而变化的设置'''self.ship_speed = 1.5self.bullet_speed =3.0self.alien_speed = 1.0'''fleet_direction为1表示向右,为-1表示向左'''self.fleet_direction = 1# '''计分'''self.alien_points = 50def increase_speed(self):'''提高速度设置和外星人分数'''self.ship_speed *= self.speedup_scaleself.bullet_speed *= self.speedup_scaleself.alien_speed *= self.speedup_scaleself.alien_points = int(self.alien_points * self.score_scale)# print(self.alien_points) cuowu
2.9 ship.py
import pygame
from pygame.sprite import Spriteclass Ship(Sprite):'''管理飞船的类'''def __init__(self,ai_game):'''初始化飞船并设置其初始化位置'''super().__init__()self.screen = ai_game.screen'''设置飞船速度'''self.settings = ai_game.settingsself.screen_rect = ai_game.screen.get_rect()'''加载飞船图像并获取其外接矩阵'''self.image = pygame.image.load('image/ship.bmp')self.rect = self.image.get_rect()'''对于每艘新飞船,都将其放在屏幕底部的中央'''self.rect.midbottom = self.screen_rect.midbottom'''在飞船的属性x中存储小数值'''self.x = float(self.rect.x)'''移动标志'''self.moving_right = Falseself.moving_left = Falsedef update(self):'''根据移动标志调整飞船的位置''''''更新飞船而不是rect对象的值'''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'''根据self.x更新rect对象'''self.rect.x = self.xdef blitme(self):'''在指定位置绘制飞船'''self.screen.blit(self.image, self.rect)def center_ship(self):'''让飞船在屏幕底端剧中'''self.rect.midbottom = self.screen_rect.midbottomself.x = float(self.rect.x)