前言
之前的游戏都是正常的外星人,这次我们添加了不一样的种类:
- 击中得分*10的高得分外星人
- 击中获得一个大子弹的外星人,大子弹的宽度更大,并且击中敌人不会消失,不计入总子弹数
- 获得了一个盾牌的外星人,能抵御一次子弹攻击
当然了,为了提高可玩性,特殊外星人的左右移动速度是正常的1.5倍,下落距离是正常的2倍,并且另外特殊外星人出现的概率较低。
尝试贴图——失败
最开始是准备直接在外星人的图片上贴一个单词上去,因为实在是懒得自己做图片,还需要重新拆出来几个分组,但是在我往上贴图的过程中,却变成了这样:
直接把之前的图片挡住了。
经过测试,单词的效果和之前的外星人相同,能触发事件,所以结案了:
孩子的外星人图片被单词图片顶掉了
单词部分:
def write(self):
#设置字号颜色
self.text_color = (0x49,0xa7,0xda)
self.font = pygame.font.SysFont(None,48)
#设置文字
if self.if_bullet:
self.msg = "buttle"
elif self.if_more:
self.msg = "more"
#制作文字并做成方框
self.image =self.font.render(self.msg,True,self.text_color,(0x23,0xd7,0x31))
self.image_rect = self.image.get_rect()
#只是实现了暂时的对齐,后面还需要调整
self.image_rect.centerx = self.rect.centerx
self.image_rect.centery = self.rect.centery
可以看到我根本没写blit,但是就能显示,最后找到了aliens.draw()方法
aliens是存放了我所有外星人精灵(sprite)的编组(group),这个方法相当于是对每一个对象都调用了一次blit方法,那么就是说明我的alien图片被替换掉了……
无语子。
特殊外星人事件处理——失败
本来想着文字就文字吧,因为网上的文本显示都是这样的,使用render做成一个图片,然后贴上去。
所以我想的是在check_bullet_alien_collisions函数中处理,因为该函数本身就是处理外星人和子弹碰撞的事件。
然后,运行直接报错,说list对象没有if_more属性,然后我尝试打印了一下collisions:
完犊子。
这里再提一下pygame.sprite.groupcollide函数:
输入两个精灵的编组,判断元素是否相交,并对相交的一对进行处理,并返回一个字典。
我之前以为字典的内容其实就是相交的精灵对象,然后一打印,居然是这玩意,心态炸了。
定稿
我的思路是这样的,我们已知的冲突函数是没法把删除调的内容找出来,然后判断是哪种外星人,所以我们就干脆对每一种外星人都创建一个编组,缺点就是需要将之前的处理外星人事件函数任务几乎翻了四倍。
对于每一种,我都给出了一个专门的图像,放个图给大家乐一乐:
(不过还是要注意一点,外星人图片的大小是相同的,所以不影响后期的计算行数列数)
有植物大战僵尸文字版那味了(狗头
首先是在setting.py中添加了这样的设置:
self.special_speed_factor = 1.5 #特殊外星人的左右移动速度为正常1.5倍
self.special_score_facteor = 10 #特殊外星人得分为十倍
然后我们在alien_invasion.py中创建了一万个编组:
添加了特殊外星人,就需要记录我们拥有了多少颗大子弹,这里我将记录变量添加到stats中,和得分等数据一起:
(因为游戏开始大子弹数量也需要清零,所以将其放在方法中,方便以后调用)
因为还需要我们在屏幕上显示我们当前拥有的大子弹数目,所以我选择在显示飞船(声明)个数的下方、和等级齐平的位置显示,这就需要修改我们的记分牌:
学着等级的样子,我添加了更新大子弹个数的函数:
def prep_big_bullet(self):
"""渲染大子弹的个数,数字形式"""
self.bullet_img = self.font.render(str(self.stats.big_bullet),True,self.text_color,self.ai_settings.bg_color)
# 将个数放在飞船下面
self.bullet_rect = self.bullet_img.get_rect()
self.bullet_rect.left = self.screen_rect.left
self.bullet_rect.bottom = self.level_rect.bottom
同时在渲染和初始化函数中进行了添加:
最后记得在修改了stats.big_bullet之后,调一下prep_big_bullet进行刷新就好了,不然是不会改变的。
上述部分都是边角,或者是可以直接copy魔改的部分,下面的事件处理和外星人类修改才是大头。
外星人类的修改
之前本来想创建子类的,但是后面想了一下,我们只需要创建一个通用外星人,然后放在不同的编组中,就能对应不同的外星人。
说干就干。
首先我们添加了三个特殊外星人标识:
因为不同的外星人对应着不同的图像,所以我们还不能直接加载,我选择创建了一个方法:
(只需要记得给完标识符就调用方法即可,不给标识符就会出错)
def loading(self):
# 加载外星人图像,并设置rect属性
if self.if_bullet:
self.image = pygame.image.load('./alien/image/alien_bullet.bmp')
elif self.if_more:
self.image = pygame.image.load('./alien/image/alien_more.bmp')
elif self.if_shield:
self.image = pygame.image.load('./alien/image/alien_shield.bmp')
else:
self.image = pygame.image.load('./alien/image/alien.bmp')
self.rect = self.image.get_rect()
# 开始每一个外星人都在屏幕的左上角
self.rect.x = self.rect.width
self.rect.y = self.rect.height
# 用来存储准确的位置,用其更新rect.x
self.x = float(self.rect.x)
随后,在update方法中,添加了对不同种类的外星人有不同的左右移动速度(调用ai_setting)
成果长这样:
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
# 移动方向,1表示向右,-1向左
self.fleet_direction = 1
# 特殊外星人
self.if_bullet = False
self.if_more = False
self.if_shield = False
def loading(self):
# 加载外星人图像,并设置rect属性
if self.if_bullet:
self.image = pygame.image.load('./alien/image/alien_bullet.bmp')
elif self.if_more:
self.image = pygame.image.load('./alien/image/alien_more.bmp')
elif self.if_shield:
self.image = pygame.image.load('./alien/image/alien_shield.bmp')
else:
self.image = pygame.image.load('./alien/image/alien.bmp')
self.rect