Files
aliendefender/splashes.cpp
blizer 894e55bb41 added morphs, fix some bugs, new images
added onAlienInRadius trigger
but it not work right((
2011-08-21 22:22:02 +04:00

348 lines
12 KiB
C++

#include "splashes.h"
#include <cmath>
Splashes::Splashes(Game_Data *gd, QObject *parent) :
QObject(parent)
{
gameData = gd;
nextId = 1;
}
void Splashes::addSplash(int player, srcSplashType *src, QPointF pos, QPointF dest, int aim)
{
SplashType spl;
spl.id = nextId;
spl.towerId = QPoint(-1,-1);
spl.srcTow = 0;
spl.PlayerId = player;
spl.AlienId = 0;
spl.pos = pos;
spl.destination = dest;
spl.AlienId = aim;
spl.angle = 180.0f*(- std::atan2(spl.pos.x() - spl.destination.x(),spl.pos.y() - spl.destination.y()))/M_PI;
spl.life = 0;
spl.src = src;
addSplash(&spl);
}
void Splashes::addSplash(const TowerType &tower)
{
SplashType spl;
spl.src = &(tower.src->splashes[0]);
spl.id = nextId;
spl.towerId = tower.pos;
spl.PlayerId = tower.PlayerId;
spl.AlienId = tower.aim;
spl.srcTow = tower.src;
spl.pos = QPointF(tower.pos);
if (gameData->aliens->curAliens.contains(spl.AlienId))
spl.destination = gameData->aliens->curAliens.value(spl.AlienId).pos+QPointF(0.5,0.5);
else {qCritical("aim alien not exists(!)");return;}
spl.angle = 180.0f*(- std::atan2(spl.pos.x() - spl.destination.x(),spl.pos.y() - spl.destination.y()))/M_PI;
spl.life = 0;
addSplash(&spl);
}
void Splashes::addSplash(srcTowerType *srctower, int id, QPointF pos, QPointF dest, int aim, QPoint towerId)
{
SplashType spl;
if (srctower != 0)
spl.src = &(srctower->splashes[id]);
else spl.src = &(gameData->srcSplashes[id]);
spl.id = nextId;
spl.towerId = towerId;
spl.PlayerId = srctower->PlayerId;
spl.AlienId = aim;
spl.pos = pos;
spl.destination = dest;
spl.angle = 180.0f*(- std::atan2(spl.pos.x() - spl.destination.x(),spl.pos.y() - spl.destination.y()))/M_PI;
spl.life = 0;
spl.srcTow = srctower;
addSplash(&spl);
}
void Splashes::addSplash(SplashType * spl)
{
srcTriggerType * trig;
for(int i=0; i<spl->src->triggerIndexes.size(); i++)
{
TriggerOnDest tod;
TriggerOnAlien toa;
TriggerOnTimer tot;
if (spl->srcTow != 0)
trig = &(spl->srcTow->triggers[spl->src->triggerIndexes.at(i)]);
else {qDebug("no parent tower"); trig = &(gameData->srcTriggers[spl->src->triggerIndexes.at(i)]);}
switch (trig->type)
{
case srcTriggerType::onDestination :
tod.src = trig;
spl->trigsOnDest.append(tod);
break;
case srcTriggerType::onAlienInRadius :
toa.src = trig;
spl->trigsOnAlien.append(toa);
break;
case srcTriggerType::onTimer :
tot.src = trig;
tot.timer = 0;
spl->trigsOnTimer.append(tot);
break;
}
}
spl->item = new ADItem(spl->id, ADItem::Splash, spl->src->images);
spl->item->setPos(spl->pos*cellSize);
spl->item->setRotation(spl->angle);
spl->item->setZValue(spl->src->ZValue);
spl->item->setCompositionMode(spl->src->compositionMode);
scene->addItem(spl->item);
gameData->curSplashes.insert(spl->id,*spl);
nextId++;
}
void Splashes::update()
{
QHash<int,int> deadIndexes;
for (QHash<int, SplashType>::iterator
spl = gameData->curSplashes.begin();
spl != gameData->curSplashes.end(); ++spl)
{
spl->life++;
if (spl->life > spl->src->lifetime)
deadIndexes.insert(spl->id,spl->id);
if (!spl->trigsOnTimer.isEmpty())
doTriggerOnTimer(spl,&deadIndexes);
if (!spl->trigsOnAlien.isEmpty())
doTriggerOnAlien(spl,&deadIndexes);
float arctg;
float speed = spl->src->speed;
float speed2 = speed*speed;
bool keep = spl->src->keepOnAlien;
if (spl->src->keepOnAlien)
{
if (gameData->aliens->curAliens.contains(spl->AlienId))
{
spl->pos = gameData->aliens->curAliens[spl->AlienId].pos;
spl->angle = gameData->aliens->curAliens[spl->AlienId].angle;
} else deadIndexes.insert(spl->id,spl->id);
} else {
if (spl->src->autoControl && spl->AlienId != -1)
{
bool badAl = false;
if (gameData->aliens->curAliens.contains(spl->AlienId))
{
spl->destination = gameData->aliens->curAliens.value(spl->AlienId).pos+QPointF(0.5,0.5);
} else {
badAl = true;
spl->AlienId = -1;
keep = false;
}
if (distance2(spl->pos, spl->destination) < speed2)
{
if (badAl)
deadIndexes.insert(spl->id,spl->id);
spl->pos = spl->destination;
doTriggerOnDest(spl,&deadIndexes,badAl);
}
arctg = std::atan2(spl->pos.x() - spl->destination.x(), spl->pos.y() - spl->destination.y());
spl->angle = 180.0f*(-arctg)/M_PI;
} else {
if (!gameData->map->rect().contains(spl->pos.toPoint()))
deadIndexes.insert(spl->id,spl->id);
if (!spl->trigsOnDest.isEmpty())
{
if (distance2(spl->pos, spl->destination) < speed2)
{
spl->pos = spl->destination;
doTriggerOnDest(spl,&deadIndexes,true);
}
}
arctg = -spl->angle*M_PI/180.f;
}
spl->pos.rx() -= speed*std::sin(arctg);
spl->pos.ry() -= speed*std::cos(arctg);
}
/// TODO: smooth splash rotate
spl->item->setPos(spl->pos*cellSize);
spl->item->setRotation(spl->angle);
spl->item->next(spl->src->animSpeed);
}
for (QHash<int,int>::iterator j = deadIndexes.begin();
j != deadIndexes.end(); ++j)
delSplash(*j);
for (QHash<int,DeadAlienIndex>::iterator j = dead.begin();
j != dead.end(); ++j)
emit killAlien(j->player,j->id);
dead.clear();
}
void Splashes::delSplash(int Id)
{
scene->removeItem(gameData->curSplashes[Id].item);
delete gameData->curSplashes[Id].item;
gameData->curSplashes.remove(Id);
}
/// FIXME : correct onTrigTimer()
void Splashes::doTriggerOnTimer(QHash<int, SplashType>::iterator
spl, QHash<int,int> *deadIndexes)
{
for(QList<TriggerOnTimer>::iterator i = spl->trigsOnTimer.begin();
i != spl->trigsOnTimer.end(); ++i)
{
srcTriggerType * strig = i->src;
i->timer++;
if (i->timer >= strig->timer)
{
/// TODO : add damage and other effects
float dmg = strig->damage;
float rad = strig->radius;
if (dmg > 0)
{
float hh;
if (!(rad > 0))
{
if (gameData->aliens->curAliens.contains(spl->AlienId))
{
hh = gameData->aliens->curAliens[spl->AlienId].health -= dmg;
if (hh <= 0) dead.insert(spl->AlienId, DeadAlienIndex(spl->AlienId, spl->PlayerId));
}
} else {
for (QHash<int, AlienType>::iterator
a = gameData->aliens->curAliens.begin();
a != gameData->aliens->curAliens.end(); ++a)
{
if (distance2(spl->pos, a->pos) < rad*rad)
{
hh = a->health -= dmg;
if (hh <= 0) dead.insert(a->id, DeadAlienIndex(a->id, spl->PlayerId));
}
}
}
}
i->timer = 0;
if (strig->delParent) deadIndexes->insert(spl->id,spl->id);
if (strig->count > 0 && strig->childId > 0)
{
int aim;
switch(strig->childAim)
{
/// TODO : othet aim types
case srcTriggerType::parentAim : aim = spl->AlienId; break;
case srcTriggerType::noAim : aim = -1; break;
default : aim = -1;
}
for (int j=0; j<strig->count; ++j)
{
/// TODO: randomRadiusPos
addSplash(spl->srcTow, strig->childId, spl->pos, spl->destination, aim, spl->towerId);
}
}
}
}
}
void Splashes::doTriggerOnDest(QHash<int, SplashType>::iterator
spl, QHash<int,int> *deadIndexes,
bool badAl)
{
foreach(TriggerOnDest t, spl->trigsOnDest)
{
/// TODO: different aims for childs
if (t.src->delParent) deadIndexes->insert(spl->id,spl->id);
int aim;
switch(t.src->childAim)
{
case srcTriggerType::parentAim :
aim = spl->AlienId;
break;
/// TODO : other aim types
case srcTriggerType::nearestAlien :
case srcTriggerType::noAim :
default : aim = -1;
}
if (t.src->count > 0 && t.src->childId > 0)
{
for (int j=0; j<t.src->count; ++j)
{
/// TODO: randomRadiusPos
addSplash(spl->srcTow,t.src->childId,
spl->pos,spl->destination,aim,spl->towerId);
}
}
float dmg = t.src->damage;
float rad = t.src->radius;
if (dmg > 0)
{
float hh;
if (!(rad > 0))
{
if (!badAl)
{
hh = gameData->aliens->curAliens[spl->AlienId].health -= dmg;
if (hh <= 0) dead.insert(spl->AlienId, DeadAlienIndex(spl->AlienId, spl->PlayerId));
}
} else {
for (QHash<int, AlienType>::iterator
i = gameData->aliens->curAliens.begin();
i != gameData->aliens->curAliens.end(); ++i)
{
if (distance2(spl->pos, i->pos) < rad*rad)
{
hh = i->health -= dmg;
if (hh <= 0) dead.insert(i->id, DeadAlienIndex(i->id, spl->PlayerId));
}
}
}
}
}
}
void Splashes::doTriggerOnAlien(QHash<int, SplashType>::iterator spl, QHash<int, int> *deadIndexes)
{
foreach(TriggerOnAlien t, spl->trigsOnAlien)
{
/// TODO: different aims for childs
if (t.src->delParent) deadIndexes->insert(spl->id,spl->id);
float dmg = t.src->damage;
float rad = t.src->radius;
if (dmg > 0 && rad > 0)
{
float hh;
for (QHash<int, AlienType>::iterator
i = gameData->aliens->curAliens.begin();
i != gameData->aliens->curAliens.end(); ++i)
{
if (distance2(spl->pos, i->pos) < rad*rad)
{
hh = i->health -= dmg;
if (hh <= 0) dead.insert(i->id, DeadAlienIndex(i->id, spl->PlayerId));
if (t.src->count > 0 && t.src->childId > 0)
{
if (!t.triggerAliens.contains(i->id))
{
for (int j=0; j<t.src->count; ++j)
{
/// TODO: randomRadiusPos
addSplash(spl->srcTow,t.src->childId,
spl->pos,i->pos,i->id,spl->towerId);
}
t.triggerAliens.append(i->id);
}
}
}
}
}
}
}