2.5zflyingobject类
类型特性
class zFlyingObject : public zObject
{
public:
zFlyingObject(QWidget* parent = 0);
virtual void act();
int raw;
bool canFire = false;
};
每一个子弹有行属性和能否变成火豌豆属性。因为火焰豌豆和mush是不能变的
总共有四种子弹,蘑菇,豌豆,火焰豆,冰豆
mush受到距离的限制才会发射,且会有一个生存周期用timerfly表示,其他子弹子类都只需要一个speed属性,同时扩展一个QMovie对象绑定动画
mush和其他类型不一样,除了speed还有一个timerfly作为生存周期,其他是通过screen的contain来判断要不要设置alive为false的
class zMush : public zFlyingObject
{
public:
zMush(QWidget* parent = 0);
~zMush();
void act();
private:
QMovie* anim = new QMovie(":/FlyingObjects/rc/Mush.gif");
int speed;
int TimerFly;
};
1.1版本更新:没有解决的bug:冰豌豆变火焰豆(未实现)
1.2版本更新:没有解决的bug:僵尸断手(未实现)
1.3版本更新:没有解决的bug:僵尸被冻结后的变色
构造与析构
析构函数释放this->anim
构造函数设置动画播放,设置canFire属性,设置速度(蘑菇还要设置飞行生存时间)
zMush::zMush(QWidget* parent) : zFlyingObject(parent)
{
this->setMovie(anim);
anim->start();
this->show();
this->speed = 12;
this->canFire = false;
this->TimerFly = 22;
}
行没有初始化,需要在植物类里面初始化
act函数
void zMush::act()
{
this->raise();
this->TimerFly --;
if (this->TimerFly < 0)
{
this->alive = false;
}
if (!(this->scene->screen.contains(this->pos())))
{
this->alive = false;
}
this->move(this->x() + this->speed , this->y());
zZombie* zombie;
foreach (zombie, this->scene->Zombies)
{
if ((qAbs(zombie->x() - this->x() + zombie->offset + 60) < 20) && ((this->raw) == (zombie->raw)) && (this->alive))
{
this->alive = false;
zombie->hit(10);
return;
}
}
}
蘑菇和其他子弹不同的是有一个生存周期,除了scene对象的screen矩阵属性可以判断它是否生存以外,timerfly生存周期也可以,模拟蘑菇只能射出一段距离而不是全图,其实我也想过用格子的手段实现,但是明显timerfly更简单。如果生存情况确定了,就在每帧移动这个子弹,然后在scene的僵尸列表里里判断每一个僵尸的位置是否有满足,豌豆集中后会有击中效果,这个动画效果会被加入scene的动画列表对象里,冰豌豆还会除法冰冻(没有实现图片,实现了速度减少,利用多态实现对于普通,路障,撑杆跳的速度降低
zAnim* pea_anim = new zPeaHit(scene);
pea_anim->setGeometry(this->x() + 20, this->y(), 40, 40);
这个动画设置在子弹的后面一点显示
僵尸中点位置减去子弹位置加上一些偏移量的绝对值满足在一个区间内,即到达了僵尸的前后两个边缘;同时子弹和僵尸在同一行且子弹alive,设置子弹为alive,调用该僵尸的hit函数然后return避免攻击到了多个僵尸
注意这个hit,这里要设置true,因为群体伤害
void zFirePea::act()
{
this->raise();
if (!(this->scene->screen.contains(this->pos())))
{
this->alive = false;
}
this->move(this->x() + this->speed , this->y());
zZombie* zombie;
foreach (zombie, this->scene->Zombies)
{
if ((qAbs(zombie->x() - this->x() + zombie->offset + 60) < 20) && ((this->raw) == (zombie->raw)) && (this->alive))
{
this->alive = false;
zAnim* pea_anim = new zFire(scene);
pea_anim->setGeometry(this->x() + 20, this->y(), 40, 40);
this->scene->Anims.append(pea_anim);
zombie->hit(10);
zZombie* zombie_2;
foreach (zombie_2, this->scene->Zombies)
{
if ((qAbs(zombie_2->x() - this->x() + zombie_2->offset + 60) < 60) && ((this->raw) == (zombie_2->raw)))
{
zombie_2->hit(10, true);
}
}
return;
}
}
}
火焰豆还有群体伤害效果,在里面再次实现一个foreach循环,找到这个场景里的其他僵尸满足当前条件的,静音攻击,不用再播放特效了,所以放在里面,对于原来那个僵尸造成20点伤害x2,其他是10,范围扩大到60而不是20
这个偏移量的作用?
offset用于对可能拿着东西的僵尸设置位置偏移,这会影响到攻击情况,比如失去东西offset就会减少,跳跃僵尸起跳后offset会调整,比如这里我就会变大,使得需要更近能打到,失去护甲也可以增加offset
在 zCommonZombie
的 hit()
方法中:
this->xpos += this->offset;
作用:
- 当某些僵尸失去护甲(如 路障僵尸 或 铁桶僵尸)时,它们的
x
坐标 向右偏移offset
像素。 - 这样可以 模拟僵尸失去护甲后变瘦,使其在屏幕上位置有所调整,防止动画突兀。
调用hit函数
void zPoleZombie::hit(int damage, bool silence)
{
if (damage >= 200)
{
this->alive = false;
zAnim* death_anim = new zBurnDie(scene);
death_anim->setGeometry(this->x() - 20 + this->offset, this->y() + 25, 180, 150);
this->scene->Anims.append(death_anim);
return;
}
if (!(silence))
{
QSound::play(":/Sounds/rc/Pea.wav");
}
this->strength -= damage;
if (this->strength <= 0)
{
this->alive = false;
zAnim* death_anim = new zPoleZombieDie(scene);
death_anim->setGeometry(this->x() - 30, this->y(), 300, 200);
this->scene->Anims.append(death_anim);
zAnim* death_head = new zPoleZombieHead(scene);
death_head->setGeometry(this->x(), this->y() - 50, 300, 300);
this->scene->Anims.append(death_head);
}
}
如果僵尸死了,修改alive状态,设置一个掉头和一个死亡僵尸动画,脑袋的y轴下面一点,尸体的x轴左边一点
hit的silence有默认值,所以可以只传递一个参数,这个damage超过200的烧死特效对应樱桃炸弹和土豆雷,他们的伤害是1200