赞
踩
修正了原书中由于版本等问题无法跑通的部分语句
附带代码中关键语法介绍
class Settings(): """存储所有设置的类""" def __init__(self): """初始化游戏的设置""" # 屏幕设置 self.screen_width = 800 self.screen_height = 600 self.bg_color = (230, 230, 230) # 飞船设置 self.ship_limit = 3 # 子弹设置 self.bullet_width = 300 self.bullet_height = 15 self.bullet_color = 60, 60, 60 self.bullet_allowed = 1 # 外星人设置 self.fleet_drop_speed = 10 # 以什么速度加快游戏节奏 self.speedup_scale = 1.1 self.score_scale = 1.5 self.initialize_dynamic_settings() def initialize_dynamic_settings(self): self.ship_speed_factor = 1.5 self.bullet_speed_factor = 1 self.alien_speed_factor = 1 # fleet_direction1表示右移,-1左移 self.fleet_direction = 1 self.alien_points = 50 def increase_speed(self): self.ship_speed_factor *= self.speedup_scale self.bullet_speed_factor *= self.speedup_scale self.alien_speed_factor *= self.speedup_scale self.alien_points = int(self.alien_points * self.speedup_scale)
import sys import pygame import game_functions as gf from pygame.sprite import Group from game_stats import GameStats from button import Button from scoreboard import Scoreboard from settings import Settings from ship import Ship def 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") # 创建play按钮 play_button = Button(ai_settings, screen, "Play") # 创建存储游戏统计信息的实例 stats = GameStats(ai_settings) sb = Scoreboard(ai_settings, screen, stats) # 设置背景颜色 bg_color = (ai_settings.bg_color) # 创建一艘飞船 ship = Ship(screen, ai_settings) # 创建一个用于存储子弹的编组 bullets = Group() # 创建外星人编组 aliens = Group() # 创建外星人群 gf.create_fleet(ai_settings, screen, aliens, ship) # 开始游戏主循环 while True: # 监听键盘鼠标事件 gf.check_events(ship=ship, ai_settings=ai_settings, screen=screen, bullets=bullets, stats=stats, play_button=play_button, aliens=aliens, sb=sb) if stats.game_active: ship.update() # 更新子弹 gf.update_bullets(bullets, aliens, ai_settings, screen, ship, stats, sb) gf.update_aliens(ai_settings=ai_settings, stats=stats, screen=screen, ship=ship, aliens=aliens, bullets=bullets, sb=sb) gf.update_screen(ai_settings, screen, ship, bullets, aliens, stats, play_button, sb) run_game()
import pygame from pygame.sprite import Sprite class Alien(Sprite): """表示单个外星人的类""" def __init__(self, ai_settings, screen): """初始化外星人并设置起始位置""" super(Alien, self).__init__() self.screen = screen self.ai_settings = ai_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 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.x def check_edges(self): """如果外星人接触边缘,返回True""" screen_rect = self.screen.get_rect() if self.rect.right >= screen_rect.right: return True elif self.rect.left <= 0: return True
import pygame from pygame.sprite import Sprite class 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.centerx self.rect.top = ship.rect.top # 存储用小数表示的子弹位置 self.y = float(self.rect.y) self.color = ai_settings.bullet_color self.speed_factor = ai_settings.bullet_speed_factor def update(self): """向上移动子弹""" # 更新表示子弹位置的小数值 self.y -= self.speed_factor # 更新表示子弹的rect位置 self.rect.y = self.y def draw_bullet(self): """在屏幕上绘制子弹""" pygame.draw.rect(self.screen, self.color, self.rect)
import pygame from settings import Settings from pygame.sprite import Sprite class Ship(Sprite): def __init__(self, screen, ai_settings): """初始化飞船并设置其初始位置""" super(Ship, self).__init__() self.screen = screen self.ai_settings = ai_settings # 加载飞船图像,获取外接矩形 self.image = pygame.image.load('images/ship.bmp') self.rect = self.image.get_rect() self.screen_rect = screen.get_rect() # 将每艘新飞船放在屏幕底部中央 self.rect.centerx = self.screen_rect.centerx self.rect.bottom = self.screen_rect.bottom self.moving_right = False self.moving_left = False self.center = float(self.rect.centerx) def update(self): """根据移动标志调整飞船位置""" if self.moving_right and self.rect.right < self.screen_rect.right: self.center += self.ai_settings.ship_speed_factor if self.moving_left and self.rect.left > self.screen_rect.left: self.center -= self.ai_settings.ship_speed_factor self.rect.centerx = self.center def blitme(self): """在指定位置绘制飞船""" self.screen.blit(self.image, self.rect) def center_ship(self): """飞船居中""" self.center = self.screen_rect.centerx
import pygame.font class Button(): def __init__(self, ai_settings, screen, msg): """初始化按钮属性""" self.screen = screen self.screen_rect = screen.get_rect() # 设置按钮的尺寸和其他属性 self.width, self.height = 200, 50 self.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.center def draw_button(self): # 绘制一个用颜色填充的按钮,再绘制文本 self.screen.fill(self.button_color, self.rect) self.screen.blit(self.msg_image, self.msg_image_rect)
class GameStats(): """跟踪游戏的统计信息""" def __init__(self, ai_settings): """初始化统计信息""" self.ai_settings = ai_settings self.reset_stats() self.game_active = False self.high_score = 0 def reset_stats(self): """初始化在游戏运行中可能变化的统计信息""" self.ships_left = self.ai_settings.ship_limit self.score = 0 self.level = 1
import pygame.font from pygame.sprite import Group from ship import Ship class Scoreboard(): """显示得分信息""" def __init__(self, ai_settings, screen, stats): """初始化显示得分涉及的属性""" self.screen = screen self.screen_rect = screen.get_rect() self.ai_settings = ai_settings self.stats = stats # 显示得分的字体 self.text_color = (30, 30, 30) self.font = pygame.font.SysFont(None, 48) # 准备初始得分图像 self.prep_score() self.prep_high_score() self.prep_level() self.prep_ships() def prep_score(self): """将得分转换为图像""" rounded_score = int(round(self.stats.score, -1)) score_str = "{:,}".format(rounded_score) self.score_image = self.font.render(score_str, True, self.text_color, self.ai_settings.bg_color) self.score_rect = self.score_image.get_rect() self.score_rect.right = self.screen_rect.right - 20 self.score_rect.top = 20 def 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 prep_high_score(self): """将最高得分变成图像""" high_score = int(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.ai_settings.bg_color) # 将最高得分放在屏幕顶部中央 self.high_score_rect = self.high_score_image.get_rect() self.high_score_rect.centerx = self.screen_rect.centerx self.high_score_rect.top = self.score_rect.top def prep_level(self): self.level_image = self.font.render(str(self.stats.level), True, self.text_color, self.ai_settings.bg_color) self.level_rect = self.level_image.get_rect() self.level_rect.right = self.score_rect.right self.level_rect.top = self.score_rect.bottom + 10 def prep_ships(self): """显示余下飞船""" self.ships = Group() for ship_number in range(self.stats.ships_left): ship = Ship(self.screen, self.ai_settings) ship.rect.x = 10 + ship_number * ship.rect.width ship.rect.y = 10 self.ships.add(ship)
import sys import pygame from bullet import Bullet from alien import Alien from time import sleep def check_keydown_events(event, ship, ai_settings, screen, bullets): """响应按下""" if event.key == pygame.K_d: ship.moving_right = True elif event.key == pygame.K_a: ship.moving_left = True elif event.key == pygame.K_SPACE: fire_bullet(ai_settings, screen, ship, bullets) elif event.key == pygame.K_q: sys.exit() def check_keyup_events(event, ship, ai_settings, screen, bullets): """响应松开""" if event.key == pygame.K_d: ship.moving_right = False elif event.key == pygame.K_a: ship.moving_left = False def check_events(ship, ai_settings, screen, aliens, bullets, stats, play_button, sb): """响应键盘鼠标事件""" for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == pygame.KEYDOWN: check_keydown_events(event, ship, ai_settings, screen, bullets) elif event.type == pygame.KEYUP: check_keyup_events(event, ship, ai_settings, screen, bullets) elif event.type == pygame.MOUSEBUTTONDOWN: mouse_x, mouse_y = pygame.mouse.get_pos() check_play_button(ai_settings, screen, stats, play_button, ship, aliens, bullets, mouse_x, mouse_y, sb) def check_play_button(ai_settings, screen, stats, play_button, ship, aliens, bullets, mouse_x, mouse_y, sb): """玩家点击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() create_fleet(ai_settings=ai_settings, screen=screen, ship=ship, aliens=aliens) ship.center_ship() def update_screen(ai_settings, screen, ship, bullets, aliens, stats, play_button, sb): """更新屏幕上的图像,切换到新屏幕""" # 每次循环重绘屏幕 screen.fill(ai_settings.bg_color) # 在飞船和外星人后面绘制所有子弹 for bullet in bullets.sprites(): bullet.draw_bullet() ship.blitme() aliens.draw(screen) # 显示得分 sb.show_score() # 如果游戏非活动,显示按钮 if not stats.game_active: play_button.draw_button() # 让最近绘制的屏幕可见 pygame.display.flip() def update_bullets(bullets, aliens, ai_settings, screen, ship, stats, sb): """更新子弹位置,删除已消失子弹""" # 更新子弹位置 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, stats, sb) def check_bullet_alien_collision(ai_settings, screen, ship, aliens, bullets, stats, sb): """响应子弹和外星人的碰撞""" collisions = pygame.sprite.groupcollide(bullets, aliens, True, True) if collisions: for aliens in collisions.values(): stats.score += ai_settings.alien_points * len(aliens) sb.prep_score() check_high_score(stats, sb) if len(aliens) == 0: bullets.empty() ai_settings.increase_speed() stats.level += 1 sb.prep_level() create_fleet(ai_settings, screen, aliens, ship) def fire_bullet(ai_settings, screen, ship, bullets): """如果没有达到限制就发射一颗子弹""" if len(bullets) < ai_settings.bullet_allowed: new_bullet = Bullet(ai_settings, screen, ship) bullets.add(new_bullet) def create_fleet(ai_settings, screen, aliens, ship): """创建外星人群""" alien = Alien(ai_settings, screen) alien_width = alien.rect.width number_alien_x = get_number_aliens_x(ai_settings, alien_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_alien_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_width number_alien_x = int(available_space_x / (2 * alien_width)) return number_alien_x def create_alien(ai_settings, screen, aliens, alien_number, row_number): """创建一个外星人并放在当前行""" alien = Alien(ai_settings, screen) alien_width = alien.rect.width alien.x = alien_width + 2 * alien_width * alien_number alien.rect.x = alien.x alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number aliens.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_rows def update_aliens(ai_settings, stats, screen, ship, aliens, bullets, sb): """更新外星人群中所有外星人位置""" check_fleet_edges(ai_settings=ai_settings, aliens=aliens) aliens.update() if pygame.sprite.spritecollideany(ship, aliens): ship_hit(ai_settings=ai_settings, stats=stats, screen=screen, ship=ship, aliens=aliens, bullets=bullets, sb=sb) check_aliens_bottom(ai_settings=ai_settings, stats=stats, screen=screen, ship=ship, aliens=aliens, bullets=bullets, sb=sb) def check_fleet_edges(ai_settings, aliens): """外星人到达边缘时采取措施""" for alien in aliens.sprites(): if alien.check_edges(): change_fleet_direction(ai_settings, aliens) break def change_fleet_direction(ai_settings, aliens): """将整群外星人下移,改变方向""" for alien in aliens.sprites(): alien.rect.y += ai_settings.fleet_drop_speed ai_settings.fleet_direction *= -1 def ship_hit(ai_settings, stats, screen, ship, aliens, bullets, sb): """响应外星人撞到飞船""" if stats.ships_left > 0: stats.ships_left -= 1 sb.prep_ships() aliens.empty() bullets.empty() create_fleet(ai_settings, screen, aliens, ship) ship.center_ship() sleep(0.5) else: stats.game_active = False pygame.mouse.set_visible(True) def check_aliens_bottom(ai_settings, stats, screen, ship, aliens, bullets, sb): """检查外星人到达屏幕底端""" 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, sb) def check_high_score(stats, sb): """检查是否出现最高分""" if stats.score > stats.high_score: stats.high_score = stats.score sb.prep_high_score()
pygame.sprite.Group
A container class to hold and manage multiple Sprite objects.
empty
()remove all Sprites
empty() -> None
Removes all Sprites from this Group.
clear
()draw a background over the Sprites
clear(Surface_dest, background) -> None
Erases the Sprites used in the last Group.draw()
call. The destination Surface is cleared by filling the drawn Sprite positions with the background.
The background is usually a Surface image the same dimensions as the destination Surface. However, it can also be a callback function that takes two arguments; the destination Surface and an area to clear. The background callback function will be called several times each clear.
Here is an example callback that will clear the Sprites with solid red:
def clear_callback(surf, rect):
color = 255, 0, 0
surf.fill(color, rect)
draw
()blit the Sprite images
draw(Surface) -> None
Draws the contained Sprites to the Surface argument. This uses the Sprite.image
attribute for the source surface, and Sprite.rect
for the position.
The Group does not keep sprites in any order, so the draw order is arbitrary.
update
()call the update method on contained Sprites
update(*args, **kwargs) -> None
Calls the update()
method on all Sprites in the Group. The base Sprite class has an update method that takes any number of arguments and does nothing. The arguments passed to Group.update()
will be passed to each Sprite.
There is no way to get the return value from the Sprite.update()
methods.
has
()test if a Group contains Sprites
has(*sprites) -> bool
Return True if the Group contains all of the given sprites. This is similar to using the “in” operator on the Group (“if sprite in group: …”), which tests if a single Sprite belongs to a Group.
Each sprite argument can also be a iterator containing Sprites.
remove
()remove Sprites from the Group
remove(*sprites) -> None
Remove any number of Sprites from the Group. This will only remove Sprites that are already members of the Group.
Each sprite argument can also be a iterator containing Sprites.
add
()add Sprites to this Group
add(*sprites) -> None
Add any number of Sprites to this Group. This will only add Sprites that are not already members of the Group.
Each sprite argument can also be a iterator containing Sprites.
copy
()duplicate the Group
copy() -> Group
Creates a new Group with all the same Sprites as the original. If you have subclassed Group, the new object will have the same (sub-)class as the original. This only works if the derived class’s constructor takes the same arguments as the Group class’s.
sprites
()list of the Sprites this Group contains
sprites() -> sprite_list
Return a list of all the Sprites this group contains. You can also get an iterator from the group, but you cannot iterate over a Group while modifying it.
pygame.sprite.groupcollide
()Find all sprites that collide between two groups.
groupcollide(group1, group2, dokill1, dokill2, collided = None) -> Sprite_dict
This will find collisions between all the Sprites in two groups. Collision is determined by comparing the Sprite.rect
attribute of each Sprite or by using the collided function if it is not None.
Every Sprite inside group1 is added to the return dictionary. The value for each item is the list of Sprites in group2 that intersect.
If either dokill argument is True, the colliding Sprites will be removed from their respective Group.
The collided argument is a callback function used to calculate if two sprites are colliding. It should take two sprites as values and return a bool value indicating if they are colliding. If collided is not passed, then all sprites must have a “rect” value, which is a rectangle of the sprite area, which will be used to calculate the collision.
>>>"{} {}".format("hello", "world") # 不设置指定位置,按默认顺序
'hello world'
>>> "{0} {1}".format("hello", "world") # 设置指定位置
'hello world'
>>> "{1} {0} {1}".format("hello", "world") # 设置指定位置
'world hello world'
#!/usr/bin/python # -*- coding: UTF-8 -*- print("网站名:{name}, 地址 {url}".format(name="菜鸟教程", url="www.runoob.com")) # 通过字典设置参数 site = {"name": "菜鸟教程", "url": "www.runoob.com"} print("网站名:{name}, 地址 {url}".format(**site)) # 通过列表索引设置参数 my_list = ['菜鸟教程', 'www.runoob.com'] print("网站名:{0[0]}, 地址 {0[1]}".format(my_list)) # "0" 是必须的 网站名:菜鸟教程, 地址 www.runoob.com 网站名:菜鸟教程, 地址 www.runoob.com 网站名:菜鸟教程, 地址 www.runoob.com
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class AssignValue(object):
def __init__(self, value):
self.value = value
my_value = AssignValue(6)
print('value 为: {0.value}'.format(my_value)) # "0" 是可选的
value 为: 6
数字 | 格式 | 输出 | 描述 |
---|---|---|---|
3.1415926 | {:.2f} | 3.14 | 保留小数点后两位 |
3.1415926 | {:+.2f} | +3.14 | 带符号保留小数点后两位 |
-1 | {:+.2f} | -1.00 | 带符号保留小数点后两位 |
2.71828 | {:.0f} | 3 | 不带小数 |
5 | {:0>2d} | 05 | 数字补零 (填充左边, 宽度为2) |
5 | {:x<4d} | 5xxx | 数字补x (填充右边, 宽度为4) |
10 | {:x<4d} | 10xx | 数字补x (填充右边, 宽度为4) |
1000000 | {:,} | 1,000,000 | 以逗号分隔的数字格式 |
0.25 | {:.2%} | 25.00% | 百分比格式 |
1000000000 | {:.2e} | 1.00e+09 | 指数记法 |
13 | {:>10d} | 13 | 右对齐 (默认, 宽度为10) |
13 | {:<10d} | 13 | 左对齐 (宽度为10) |
13 | {:^10d} | 13 | 中间对齐 (宽度为10) |
11 | ‘{:b}’.format(11) | 1011 | 进制 |
11 | ‘{:d}’.format(11) | 11 | 进制 |
11 | ‘{ 声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/121635 推荐阅读 相关标签 Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。 |