目录
前言
一、13-1星星
二、13-2更逼真的星星
三、13-3雨滴
四、13-4连绵细雨
五、13-5?侧面射击2
六、13-6游戏结束
总结
前言
这里是Python从入门到实践的练习答案,本人也是初学python,在这里把我的答案记录下来。如果有错误或者可以改进的地方欢迎在评论区留言。另外,所有代码均按照书上方式重构,便于阅读和理解。
后两题的答案是根据12章答案改进而来,感兴趣的uu们可以去专栏里找找看。
另外注意相对路径问题。
一、13-1星星
在网上找的图片 没找到合适大小的( 尺寸小就美观一些
图片命名为 star.png
?新建star.py
import pygame
from pygame.sprite import Sprite
class Star(Sprite):
"""表示单个星星的类"""
def __init__(self, ai_game):
"""初始化星星"""
super().__init__()
self.screen = ai_game
#加载星星图像并设置其rect
self.image = pygame.image.load('star.png')
self.rect = self.image.get_rect()
#每个星星一开始都在屏幕左上角附近
self.rect.x = self.rect.width - 50
self.rect.y = self.rect.height - 50
#储存星星的精确位置
self.x = float(self.rect.x)
self.y = float(self.rect.y)
新建sky.py
import sys
import pygame
from star import Star
class Sky:
"""管理天空的类"""
def __init__(self):
"""初始化界面"""
pygame.init()
self.screen = pygame.display.set_mode((1000, 800))
self.screen_rect = self.screen.get_rect()
pygame.display.set_caption("Star Sky")
self.stars = pygame.sprite.Group()
self._create_fleet()
def _create_fleet(self):
"""创建星云"""
#计算一行可以容纳多少星星
star = Star(self)
star_width = star.rect.width
available_space_x = self.screen_rect.width - 100
number_stars_x = available_space_x // (star_width * 2)
for row_number in range(3):
#创建一行星星
for star_number in range(number_stars_x):
#创建一个星星并加入当前行
self._create_star(star_number, row_number)
def _create_star(self, star_number, row_number):
#创建一个星星
star = Star(self)
star_width = star.rect.width
star_height = star.rect.height
star.x = 50 + star_width * star_number * 2
star.rect.x = star.x
star.y = 50 + star_height * row_number * 2
star.rect.y = star.y
self.stars.add(star)
def _update_screen(self):
"""绘制屏幕"""
self.screen.fill((0, 190, 230))
self.stars.draw(self.screen)
pygame.display.flip()
def run_game(self):
"""主循环"""
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
self._update_screen()
if __name__ == "__main__":
ai = Sky()
ai.run_game()
?结果是这样的 星星小点就好了(
二、13-2更逼真的星星
只需对 sky.py 做少许修改
import sys
import pygame
from star import Star
from random import randint
class Sky:
"""管理天空的类"""
def __init__(self):
"""初始化界面"""
pygame.init()
self.screen = pygame.display.set_mode((1000, 800))
self.screen_rect = self.screen.get_rect()
pygame.display.set_caption("Star Sky")
self.stars = pygame.sprite.Group()
self._create_fleet()
def _create_fleet(self):
"""创建星云"""
#计算一行可以容纳多少星星
star = Star(self)
star_width = star.rect.width
available_space_x = self.screen_rect.width - 100
number_stars_x = available_space_x // (star_width * 2)
for row_number in range(3):
#创建一行星星
for star_number in range(number_stars_x):
#创建一个星星并加入当前行
star_number = randint(0, number_stars_x)
self._create_star(star_number, row_number)
def _create_star(self, star_number, row_number):
#创建一个星星
star = Star(self)
star_width = star.rect.width
star_height = star.rect.height
star.x = 50 + star_width * star_number * 2
star.rect.x = star.x
star.y = 50 + star_height * row_number * 2
star.rect.y = star.y
if star.rect.right < self.screen_rect.right:
self.stars.add(star)
def _update_screen(self):
"""绘制屏幕"""
self.screen.fill((0, 190, 230))
self.stars.draw(self.screen)
pygame.display.flip()
def run_game(self):
"""主循环"""
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
self._update_screen()
if __name__ == "__main__":
ai = Sky()
ai.run_game()
结果是这样的:
三、13-3雨滴
雨滴和星星差不多,这里直接修改 star.py 将星星都换成雨滴就行
将背景改为白色
在 raindrop.py里直接设置速度,就不新建settings.py文件专门储存设置了
另外稍微修改raindrop.py
?raindrop.py
import pygame
from pygame.sprite import Sprite
class Raindrop(Sprite):
"""表示单个雨滴的类"""
def __init__(self, ai_game):
"""初始化雨滴"""
super().__init__()
self.screen = ai_game
#加载雨滴图像并设置其rect
self.image = pygame.image.load('raindrop.png')
self.rect = self.image.get_rect()
#每个雨滴一开始都在屏幕左上角附近
self.rect.x = self.rect.width - 50
self.rect.y = self.rect.height - 50
#储存雨滴的精确位置
self.x = float(self.rect.x)
self.y = float(self.rect.y)
#雨滴下降速度
self.speed = 0.3
def update(self):
"""向下移动雨滴"""
self.y += self.speed
self.rect.y = self.y
sky.py
import sys
import pygame
from raindrop import Raindrop
class Sky:
"""管理天空的类"""
def __init__(self):
"""初始化界面"""
pygame.init()
self.screen = pygame.display.set_mode((1000, 800))
self.screen_rect = self.screen.get_rect()
pygame.display.set_caption("Star Sky")
self.raindrops = pygame.sprite.Group()
self._create_fleet()
def _create_fleet(self):
"""创建大雨"""
#计算一行可以容纳多少雨滴
raindrop = Raindrop(self)
raindrop_width = raindrop.rect.width
available_space_x = self.screen_rect.width - 100
number_raindrop_x = available_space_x // (raindrop_width * 2)
for row_number in range(3):
#创建一行雨滴
for raindrop_number in range(number_raindrop_x):
#创建一个雨滴并加入当前行
self._create_raindrop(raindrop_number, row_number)
def _create_raindrop(self, raindrop_number, row_number):
#创建一个雨滴
raindrop = Raindrop(self)
raindrop_width = raindrop.rect.width
raindrop_height = raindrop.rect.height
raindrop.x = 50 + raindrop_width * raindrop_number * 2
raindrop.rect.x = raindrop.x
raindrop.y = 50 + raindrop_height * row_number * 2
raindrop.rect.y = raindrop.y
self.raindrops.add(raindrop)
def _update_raindrops(self):
"""更新所有雨滴的位置"""
self.raindrops.update()
def _update_screen(self):
"""绘制屏幕"""
self.screen.fill((255, 255, 255))
self.raindrops.draw(self.screen)
pygame.display.flip()
def run_game(self):
"""主循环"""
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
self._update_raindrops()
self._update_screen()
if __name__ == "__main__":
ai = Sky()
ai.run_game()
结果是这样的:
四、13-4连绵细雨
修改 raindrop.py
import pygame
from pygame.sprite import Sprite
class Raindrop(Sprite):
"""表示单个雨滴的类"""
def __init__(self, ai_game):
"""初始化雨滴"""
super().__init__()
self.screen = ai_game.screen
#加载雨滴图像并设置其rect
self.image = pygame.image.load('raindrop.png')
self.rect = self.image.get_rect()
#每个雨滴一开始都在屏幕左上角附近
self.rect.x = self.rect.width - 50
self.rect.y = self.rect.height - 50
#储存雨滴的精确位置
self.x = float(self.rect.x)
self.y = float(self.rect.y)
#雨滴下降速度
self.speed = 0.3
def update(self):
"""向下移动雨滴"""
self.y += self.speed
self.rect.y = self.y
def check_edge(self):
"""如果位于屏幕边缘则返回 True"""
screen_rect = self.screen.get_rect()
if self.rect.bottom > screen_rect.bottom:
return True
sky.py
import sys
import pygame
from raindrop import Raindrop
class Sky:
"""管理天空的类"""
def __init__(self):
"""初始化界面"""
pygame.init()
self.screen = pygame.display.set_mode((1000, 800))
self.screen_rect = self.screen.get_rect()
pygame.display.set_caption("Star Sky")
self.raindrops = pygame.sprite.Group()
self._create_fleet()
def _create_fleet(self):
"""创建星云"""
#计算一行可以容纳多少星星
raindrop = Raindrop(self)
raindrop_width = raindrop.rect.width
available_space_x = self.screen_rect.width - 100
number_raindrop_x = available_space_x // (raindrop_width * 2)
for row_number in range(3):
#创建一行星星
for raindrop_number in range(number_raindrop_x):
#创建一个星星并加入当前行
self._create_raindrop(raindrop_number, row_number)
def _create_raindrop(self, raindrop_number, row_number):
#创建一个星星
raindrop = Raindrop(self)
raindrop_width = raindrop.rect.width
raindrop_height = raindrop.rect.height
raindrop.x = 50 + raindrop_width * raindrop_number * 2
raindrop.rect.x = raindrop.x
raindrop.y = 50 + raindrop_height * row_number * 2
raindrop.rect.y = raindrop.y
self.raindrops.add(raindrop)
def _check_rain_edge(self):
"""有雨滴到达边缘时采取相应的措施"""
for raindrop in self.raindrops.sprites():
if raindrop.check_edge():
raindrop.y = 0
def _update_raindrops(self):
"""更新所有雨滴的位置"""
self.raindrops.update()
def _update_screen(self):
"""绘制屏幕"""
self.screen.fill((255, 255, 255))
self.raindrops.draw(self.screen)
pygame.display.flip()
def run_game(self):
"""主循环"""
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
self._check_rain_edge()
self._update_raindrops()
self._update_screen()
if __name__ == "__main__":
ai = Sky()
ai.run_game()
?结果是这样的
五、13-5?侧面射击2
外星人图片放在这里啦
命名为 enemy1.png
?遗漏的外星人到达边缘以后不会消失,只是看不见
长时间这样运行肯定不好
所以有一个额外任务:删除到达边缘的外星人
?settings.py
class Settings:
"""储存游戏《外星人入侵》中所有设置的类"""
def __init__(self):
"""初始化游戏的设置"""
# 屏幕设置
self.screen_width = 1000
self.screen_height = 600
self.bg_color = (0, 200, 255)
#飞船设置
self.ship_speed = 0.5
#子弹设置
self.bullet_speed = 1.0
self.bullet_width = 5
self.bullet_hight = 15
self.bullet_color = (60, 60, 60)
#外星人设置
self.alien_speed = 0.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.screen_rect = self.screen.get_rect()
self.settings = ai_game.settings
#加载外星人图像并设置其 rect 属性
self.image = pygame.image.load('enemy1.png')
self.rect = self.image.get_rect()
#每个外星人都在屏幕右上角附近
self.rect.right = self.screen_rect.right
self.rect.y = 30
#储存外星人的精确位置
self.x = float(self.rect.x)
def update(self):
"""更新外星人的位置"""
self.x -= self.settings.alien_speed
self.rect.x = self.x
def check_edge(self):
"""如果外星人到达边缘就返回 True """
if self.rect.left < 0:
return True
?mygame1.0.py
import sys
import pygame
from settings import Settings
from ship import Ship
from bullet import Bullet
from alien import Alien
from random import randint
class MyGame:
"""管理游戏资源和行为的类"""
def __init__(self):
"""初始化游戏并创建游戏资源"""
pygame.init()
self.settings = Settings()
self.screen = pygame.display.set_mode(
(self.settings.screen_width, self.settings.screen_height))
pygame.display.set_caption("MyGame 1.0")
self.ship = Ship(self)
self.bullets = pygame.sprite.Group()
self.aliens = pygame.sprite.Group()
def _check_fleet_edge(self):
"""到达边缘时对外星人的处理"""
for alien in self.aliens.sprites():
if alien.check_edge():
self.aliens.remove(alien)
def _create_fleet(self):
"""创建外星人舰队"""
if 200 == randint(1, 300):
for alien_num in range(8):
if 8 == randint(0, 20):
num = randint(0, 7)
alien = Alien(self)
alien.y = 30 + num * (alien.rect.height + 10)
alien.rect.y = alien.y
self.aliens.add(alien)
def _update_screen(self):
"""更新屏幕上的图像,并切换到新图像"""
self.screen.fill(self.settings.bg_color)
self.ship.blitme()
for bullet in self.bullets.sprites():
bullet.draw_bullet()
self._check_fleet_edge()
self.aliens.draw(self.screen)
# 让最近绘制的屏幕可见
pygame.display.flip()
def _update_bullets(self):
"""更新子弹的位置并删除消失的子弹"""
self.bullets.update()
# 删除消失的子弹
for bullet in self.bullets.copy():
if bullet.rect.x > self.settings.screen_width:
self.bullets.remove(bullet)
#子弹和外星人碰撞
collisions = pygame.sprite.groupcollide(
self.bullets, self.aliens, True, True)
def _fire_bullet(self):
"""创建一颗子弹,并将其加入编组bullets中"""
new_bullet = Bullet(self)
self.bullets.add(new_bullet)
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_UP:
# 向上移动角色
self.ship.moving_up = True
elif event.key == pygame.K_DOWN:
# 向下移动角色
self.ship.moving_down = True
elif event.key == pygame.K_q:
#按 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 run_game(self):
""""开始游戏的主循环"""
while True:
self._create_fleet()
self._check_events()
self.ship.update()
self._update_bullets()
self.aliens.update()
self._update_screen()
if __name__ == '__main__':
ai = MyGame()
ai.run_game()
来看看结果吧:
六、13-6游戏结束
我的游戏规则:
玩家有三艘飞船,与外星人碰撞会损失一艘并停顿0.5秒,没有飞船时游戏结束
外星人飞出屏幕不会损失飞船
增加了一点设置
settings.py
class Settings:
"""储存游戏《外星人入侵》中所有设置的类"""
def __init__(self):
"""初始化游戏的设置"""
# 屏幕设置
self.screen_width = 1000
self.screen_height = 600
self.bg_color = (0, 200, 255)
#飞船设置
self.ship_speed = 0.5
self.ship_limit = 3
#子弹设置
self.bullet_speed = 0.75
self.bullet_width = 5
self.bullet_hight = 15
self.bullet_color = (60, 60, 60)
#外星人设置
self.alien_speed = 0.3
?新建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.ship_left = self.settings.ship_limit
mygame1.0.py
import sys
import pygame
from settings import Settings
from ship import Ship
from bullet import Bullet
from alien import Alien
from random import randint
from game_stats import GameStats
from time import sleep
class MyGame:
"""管理游戏资源和行为的类"""
def __init__(self):
"""初始化游戏并创建游戏资源"""
pygame.init()
self.settings = Settings()
self.screen = pygame.display.set_mode(
(self.settings.screen_width, self.settings.screen_height))
pygame.display.set_caption("MyGame 1.0")
# 创建一个用于游戏储存的统计信息的实例
self.stats = GameStats(self)
self.ship = Ship(self)
self.bullets = pygame.sprite.Group()
self.aliens = pygame.sprite.Group()
def _check_fleet_edge(self):
"""到达边缘时对外星人的处理"""
for alien in self.aliens.sprites():
if alien.check_edge():
self.aliens.remove(alien)
def _create_fleet(self):
"""创建外星人舰队"""
if 100 == randint(1, 250):
for alien_num in range(8):
if 8 == randint(0, 20):
num = randint(0, 7)
alien = Alien(self)
alien.y = 30 + num * (alien.rect.height + 10)
alien.rect.y = alien.y
self.aliens.add(alien)
def _update_screen(self):
"""更新屏幕上的图像,并切换到新图像"""
self.screen.fill(self.settings.bg_color)
self.ship.blitme()
for bullet in self.bullets.sprites():
bullet.draw_bullet()
self._check_fleet_edge()
self.aliens.draw(self.screen)
# 让最近绘制的屏幕可见
pygame.display.flip()
def _update_bullets(self):
"""更新子弹的位置并删除消失的子弹"""
self.bullets.update()
# 删除消失的子弹
for bullet in self.bullets.copy():
if bullet.rect.x > self.settings.screen_width:
self.bullets.remove(bullet)
#子弹和外星人碰撞
collisions = pygame.sprite.groupcollide(
self.bullets, self.aliens, True, True)
def _update_aliens(self):
"""更新外星人的类"""
self._create_fleet()
self.aliens.update()
#检测飞船和外星人的碰撞
if pygame.sprite.spritecollideany(self.ship, self.aliens):
if self.stats.ship_left > 0:
self.stats.ship_left -= 1
#暂停
sleep(0.5)
#清空余下的外星人和子弹
self.aliens.empty()
self.bullets.empty()
else:
self.stats.game_active = False
def _fire_bullet(self):
"""创建一颗子弹,并将其加入编组bullets中"""
new_bullet = Bullet(self)
self.bullets.add(new_bullet)
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_UP:
# 向上移动角色
self.ship.moving_up = True
elif event.key == pygame.K_DOWN:
# 向下移动角色
self.ship.moving_down = True
elif event.key == pygame.K_q:
#按 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 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()
if __name__ == '__main__':
ai = MyGame()
ai.run_game()
结果跟上一题看不出差别
但是测试撞击、结束是成功的
接下来做记分系统
先对游戏画面做点优化
换掉子弹和背景
图片放在这里 背景命名为 background.png 子弹命名为 bullet0.png
?为了便于管理,新建一个image文件夹存放照片
这次改动较大,我把所有文件都贴一下 目录如下图所示
?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.screen_rect = self.screen.get_rect()
self.settings = ai_game.settings
#加载外星人图像并设置其 rect 属性
self.image = pygame.image.load('image/enemy1.png')
self.rect = self.image.get_rect()
#每个外星人都在屏幕右上角附近
self.rect.right = self.screen_rect.right
self.rect.y = 30
#储存外星人的精确位置
self.x = float(self.rect.x)
def update(self):
"""更新外星人的位置"""
self.x -= self.settings.alien_speed
self.rect.x = self.x
def check_edge(self):
"""如果外星人到达边缘就返回 True """
if self.rect.left < 0:
return True
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
#在(0,0)处创建一个表示子弹的矩形,再设置正确的位置
self.buImg = pygame.image.load('image/bullet0.png')
self.rect = self.buImg.get_rect()
self.rect.midleft = ai_game.ship.rect.midleft
self.rect.x = ai_game.ship.rect.right
#使用小数表示的子弹的位置
self.x = float(self.rect.x)
def draw_bullet(self):
"""在屏幕上绘制子弹"""
self.screen.blit(self.buImg, (self.rect.x, self.rect.y))
def update(self):
"""向右移动子弹"""
#更新表示子弹位置的小数值
self.x += self.settings.bullet_speed
#更新表示 rect 的位置
self.rect.x = self.x
gamestats.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.ship_left = self.settings.ship_limit
self.score = 0
?mygame1.0.py
import sys
import pygame
from settings import Settings
from ship import Ship
from bullet import Bullet
from alien import Alien
from random import randint
from game_stats import GameStats
from time import sleep
from scoreboard import Scoreboard
class MyGame:
"""管理游戏资源和行为的类"""
def __init__(self):
"""初始化游戏并创建游戏资源"""
pygame.init()
self.settings = Settings()
self.screen = pygame.display.set_mode(
(self.settings.screen_width, self.settings.screen_height))
pygame.display.set_caption("MyGame 1.0")
# 创建一个用于游戏储存的统计信息的实例
self.stats = GameStats(self)
self.sb = Scoreboard(self)
self.ship = Ship(self)
self.bullets = pygame.sprite.Group()
self.aliens = pygame.sprite.Group()
def _check_fleet_edge(self):
"""到达边缘时对外星人的处理"""
for alien in self.aliens.sprites():
if alien.check_edge():
self.aliens.remove(alien)
def _check_bullet_alien_collision(self):
#子弹和外星人碰撞
collisions = pygame.sprite.groupcollide(
self.bullets, self.aliens, True, True)
if collisions:
self.stats.score += self.settings.alien_points
self.sb.prep_score()
def _create_fleet(self):
"""创建外星人舰队"""
if 1 == randint(1, 15):
for alien_num in range(8):
if 8 == randint(0, 20):
num = randint(0, 5)
alien = Alien(self)
alien.y = 30 + num * (alien.rect.height + 10)
alien.rect.y = alien.y
self.aliens.add(alien)
def _update_screen(self):
"""更新屏幕上的图像,并切换到新图像"""
bmImg = pygame.image.load('image/background.png')
self.screen.blit(bmImg, (0, 0))
self.sb.show_score()
self.ship.blitme()
for bullet in self.bullets.sprites():
bullet.draw_bullet()
self._check_fleet_edge()
self.aliens.draw(self.screen)
# 让最近绘制的屏幕可见
pygame.display.flip()
def _update_bullets(self):
"""更新子弹的位置并删除消失的子弹"""
self.bullets.update()
# 删除消失的子弹
for bullet in self.bullets.copy():
if bullet.rect.x > self.settings.screen_width:
self.bullets.remove(bullet)
self._check_bullet_alien_collision()
def _update_aliens(self):
"""更新外星人的类"""
self._create_fleet()
self.aliens.update()
#检测飞船和外星人的碰撞
if pygame.sprite.spritecollideany(self.ship, self.aliens):
if self.stats.ship_left > 0:
#暂停
sleep(0.5)
self.stats.ship_left -= 1
self.sb.prep_ships()
#清空余下的外星人和子弹
self.aliens.empty()
self.bullets.empty()
else:
self.stats.game_active = False
def _fire_bullet(self):
"""创建一颗子弹,并将其加入编组bullets中"""
new_bullet = Bullet(self)
self.bullets.add(new_bullet)
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_UP:
# 向上移动角色
self.ship.moving_up = True
elif event.key == pygame.K_DOWN:
# 向下移动角色
self.ship.moving_down = True
elif event.key == pygame.K_q:
#按 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 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()
if __name__ == '__main__':
ai = MyGame()
ai.run_game()
?scoreboard.py
import pygame.font
class Scoreboard:
"""显示得分信息的类"""
def __init__(self, ai_game):
"""初始化显示得分涉及的属性"""
self.ai_game = ai_game
self.screen = ai_game.screen
self.screen_rect = self.screen.get_rect()
self.stats = ai_game.stats
self.settings = ai_game.settings
#显示得分信息时使用的字体设置
self.color = (251, 255, 242)
self.font = pygame.font.SysFont("./STCAIYUN.ttf", 33)
#准备初始得分图像
self.prep_score()
self.prep_ships()
def prep_ships(self):
"""显示还余下多少飞船"""
ship_left_str = str(self.stats.ship_left)
self.ship_left_image = self.font.render("LEFT: " + ship_left_str,
True, self.color)
self.ship_left_rect = self.ship_left_image.get_rect()
self.ship_left_rect.top, self.ship_left_rect.right = 10, 700
def prep_score(self):
"""将得分转换为一幅渲染的图像"""
rounded_score = round(self.stats.score, -1)
score_str = "{:,}".format(rounded_score)
self.score_image = self.font.render("SCORE: " + score_str,
True, self.color)
self.score_rect = self.score_image.get_rect()
self.score_rect.bottom, self.score_rect.right = 480, 700
def show_score(self):
"""在屏幕上显示得分"""
self.screen.blit(self.score_image, self.score_rect)
self.screen.blit(self.ship_left_image, self.ship_left_rect)
?settings.py
class Settings:
"""储存游戏《外星人入侵》中所有设置的类"""
def __init__(self):
"""初始化游戏的设置"""
# 屏幕设置
self.screen_width = 700
self.screen_height = 480
#飞船设置
self.ship_speed = 4.0
self.ship_limit = 3
#子弹设置
self.bullet_speed = 5.0
# def initialize_dynamic_settings(self):
"""游戏动态数据"""
#飞船设置
self.ship_left = 3
#外星人设置
self.alien_speed = 2.0
self.alien_points = 50
ship.py
import pygame
from pygame.sprite import Sprite
class Ship(Sprite):
"""管理角色的类"""
def __init__(self, ai_game):
"""初始化角色并设置其初始位置"""
super().__init__()
self.screen = ai_game.screen
self.settings = ai_game.settings
self.screen_rect = ai_game.screen.get_rect()
#加载角色图像并获取其外接矩形
self.image = pygame.image.load('image/me.png')
self.rect = self.image.get_rect()
#绘制到屏幕中央
self.rect.midleft = self.screen_rect.midleft
# 在飞船的属性 x,y 中储存小数值
self.y = float(self.rect.y)
#移动标志
self.moving_up = False
self.moving_down = False
def update(self):
"""根据移动标志调整角色的位置"""
#更新角色而不是rect对象的y值
if self.moving_up and self.rect.top > 0:
self.y += -1 * self.settings.ship_speed
elif self.moving_down and self.rect.bottom < self.screen_rect.bottom:
self.y += self.settings.ship_speed
#更新rect对象
self.rect.y = self.y
def blitme(self):
"""在指定的位置绘制飞船"""
self.screen.blit(self.image, self.rect)
?来看看结果吧:
总结
学习pygame能让我们对如何管理一个项目有一个初认识,这对于初学者来说绝对是难得的体验,希望大家都能从中体会编程的乐趣。
看完了记得点个赞~?
|