《Python编程从入门到实践》第13章外星人来了
在这个项目中,要实现在屏幕左上角添加一个外星人,然后根据这个外星人的边距和屏幕尺寸来计算屏幕上可容纳多少个外星人,据此创建一系列外星人,使其填满尺寸屏幕上半部分;
之后要实现让外星人向两边和下方移动直到被外星人全部击落、有外星人撞到飞船或者有外星人抵达屏幕底端,在将全部外星人击落、有外星人撞到飞船或者有外星人抵达屏幕底端后,屏幕上将再出现一群外星人;
为了避免无休止地重复游戏而乏味无趣,可限制玩家可用的飞船数量,当飞船数量用完之后,游戏结束。
下面展示代码:
1.alien_invasion.py
-
import sys
-
import pygame
-
from time import sleep
-
-
from settings import Settings
-
from ship import Ship
-
from bullet import Bullet
-
from alien import Alien
-
from game_stats import GameStats
-
-
-
class 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().width
-
self.settings.screen_height = self.screen.get_rect().height
-
pygame.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减1
-
self.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 = False
-
-
def _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 = True
-
elif event.key == pygame.K_LEFT: # 按下的键是左箭头键
-
# 向左移动飞船
-
self.ship.moving_left = True
-
elif event.key == pygame.K_UP:
-
# 向上移动飞船
-
self.ship.moving_up = True
-
elif event.key == pygame.K_DOWN:
-
# 向下移动飞船
-
self.ship.moving_down = True
-
elif 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 = False
-
elif event.key == pygame.K_LEFT: # 松开的键是左箭头键
-
self.ship.moving_left = False
-
elif event.key == pygame.K_UP: # 松开的键是上箭头键
-
self.ship.moving_up = False
-
elif event.key == pygame.K_DOWN: # 松开的键是下箭头键
-
self.ship.moving_down = False
-
-
def _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.size
-
availiable_space_x = self.settings.screen_width - (2 * alien_width)
-
number_aliens_x = availiable_space_x // (2 * alien_width) 1
-
-
# 计算屏幕可容纳多少行外星人
-
ship_height = self.ship.rect.height
-
availiable_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.size
-
alien.x = alien_width 2 * alien_width * alien_number
-
alien.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_number
-
self.aliens.add(alien)
-
-
def _check_fleet_edges(self):
-
""" 外星人到达边缘时采取相应的措施 """
-
for alien in self.aliens.sprites():
-
if alien.check_edges():
-
self._change_fleet_firection()
-
break
-
-
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()
-
break
-
-
def _change_fleet_firection(self):
-
""" 将整群外星人下移,并改变它们方向 """
-
for alien in self.aliens.sprites():
-
alien.rect.y = self.settings.fleet_drop_speed
-
self.settings.fleet_direction *= -1
-
-
def _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 = 1500
-
self.screen_height = 800
-
self.bg_color = (227, 227, 227)
-
-
# 飞船设置
-
self.ship_speed = 1.5 # 速度:每次循环将移动1.5像素
-
self.ship_limit = 3 # 飞船数量限制
-
-
# 子弹设置
-
self.bullet_speed = 3.0
-
self.bullet_width = 3
-
self.bullet_height = 15
-
self.bullet_color = (60, 60, 60) # 子弹颜色
-
self.bullets_allowed = 10 # 允许在屏幕中的子弹数量
-
-
# 外星人设置
-
self.alien_speed = 1.0
-
self.fleet_drop_speed = 10
-
# fleet_direction为1表示右移,为-1表示左移
-
self.fleet_direction = 1
3.alien.py
-
import pygame
-
from pygame.sprite import Sprite
-
-
-
class Alien(Sprite):
-
""" 表示单个外星人的类 """
-
-
def __init__(self, ai_game):
-
""" 初始化外星人并设置其起始位置 """
-
super().__init__()
-
self.screen = ai_game.screen
-
self.settings = ai_game.settings
-
-
# 加载外星人图像并设置其rect属性
-
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 check_edges(self):
-
""" 如果外星人位于屏幕边缘,就返回True """
-
screen_rect = self.screen.get_rect()
-
if self.rect.right >= screen_rect.right or self.rect.left <= 0:
-
return True
-
-
def update(self):
-
""" 向左或向右移动外星人 """
-
self.x = (self.settings.alien_speed * self.settings.fleet_direction)
-
self.rect.x = self.x
4.ship.py
-
import pygame
-
-
-
class Ship:
-
""" 管理飞船的类 """
-
-
def __init__(self, ai_game):
-
""" 初始化飞船并设置其初始位置 """
-
self.screen = ai_game.screen
-
self.settings = ai_game.settings
-
self.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 = False
-
self.moving_left = False
-
self.moving_up = False
-
self.moving_down = False
-
-
def update(self):
-
""" 根据移动标志调整飞船的位置 """
-
# 更新飞船而不是rect对象的x值
-
if self.moving_right and self.rect.right < self.screen_rect.right:
-
self.x = self.settings.ship_speed
-
if 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_speed
-
if 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.y
-
-
def center_ship(self):
-
""" 让飞船在屏幕低端居中 """
-
self.rect.midbottom = self.screen_rect.midbottom
-
self.x = float(self.rect.x)
-
-
def blitme(self):
-
""" 在指定位置绘制飞船 """
-
self.screen.blit(self.image, self.rect)
5.bullet.py
-
import pygame
-
from pygame.sprite import Sprite
-
-
-
class Bullet(Sprite):
-
""" 管理飞船所发射子弹的类 """
-
-
def __init__(self, ai_game):
-
""" 在飞船当前位置创建一个子弹位置 """
-
super().__init__()
-
self.screen = ai_game.screen
-
self.settings = ai_game.settings
-
self.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.x
-
-
def 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.settings
-
self.reset_stats()
-
-
# 游戏刚启动时处于活动状态
-
self.game_active = True
-
-
def reset_stats(self):
-
""" 初始化在游戏运行期间可能变化的统计信息 """
-
self.ships_left = self.settings.ship_limit
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhihaeeh
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
excel下划线不显示怎么办
PHP中文网 06-23 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel图片置于文字下方的方法
PHP中文网 06-27 -
微信运动停用后别人还能看到步数吗
PHP中文网 07-22