You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegames/kspaceduel/mainview.cpp

1053 lines
32 KiB

#include "mainview.h"
#include <math.h>
#include <qbitmap.h>
#include <qfile.h>
#include <qvbox.h>
#include <kapplication.h>
#include <kaction.h>
#include <klocale.h>
#include <kstandarddirs.h>
#include <kglobalsettings.h>
#include <kconfig.h>
#include <kiconloader.h>
#include "ai.h"
#include "options.h"
KToggleAction *MyMainView::pauseAction = 0;
MyMainView::MyMainView(QWidget *parent)
:QWidget(parent),
field(DEF_WIDTH,DEF_HEIGHT),
view(&field,this)
{
int i,p;
setMinimumSize(600,400);
random.setSeed(0);
QPixmap backgr(locate("appdata", MV_BACKGROUND));
field.setBackgroundPixmap(backgr);
view.setResizePolicy(QScrollView::AutoOne);
view.setHScrollBarMode(QScrollView::AlwaysOff);
view.setVScrollBarMode(QScrollView::AlwaysOff);
for(p=0;p<2;p++)
{
for(i=0;i<PlayerKeyNum;i++)
playerKeyPressed[p][i]=false;
bulletShot[p]=false;
minePut[p]=false;
}
QString tmp = KGlobal::dirs()->findResourceDir("appdata", (QString)MV_BACKGROUND);
QCanvasPixmapArray *sunsequence
= loadOldPixmapSequence( tmp + MV_SUN_PPM, tmp + MV_SUN_PBM );
sun=new SunSprite(sunsequence, &field);
sun->move(width()/2-1,height()/2-1);
sun->show();
explosionsequence = loadOldPixmapSequence( tmp + MV_EXPLOSION_PPM,
tmp + MV_EXPLOSION_PBM, 31 );
mineexplosionsequence = loadOldPixmapSequence(tmp + MV_MINEEX_PPM,
tmp + MV_MINEEX_PBM, 18 );
shipsequence[0] = loadOldPixmapSequence( tmp + MV_SHIP1_PPM,
tmp + MV_SHIP1_PBM, ROTNUM );
shipsequence[1] = loadOldPixmapSequence( tmp + MV_SHIP2_PPM,
tmp + MV_SHIP2_PBM, ROTNUM);
ship[0]=new ShipSprite(shipsequence[0],&field,0);
ship[1]=new ShipSprite(shipsequence[1],&field,1);
bulletsequence[0] = loadOldPixmapSequence( tmp + MV_BULLET1_PPM,
tmp + MV_BULLET1_PBM );
bulletsequence[1] = loadOldPixmapSequence( tmp + MV_BULLET2_PPM,
tmp + MV_BULLET2_PBM );
minesequence[0] = loadOldPixmapSequence( tmp + MV_MINE1_PPM,
tmp + MV_MINE1_PBM, 2);
minesequence[1] = loadOldPixmapSequence( tmp + MV_MINE2_PPM,
tmp + MV_MINE2_PBM, 2);
powerupsequence[PowerupSprite::PowerupMine]
= loadOldPixmapSequence( tmp + MV_POWERMINE_PPM, tmp + MV_POWERMINE_PBM );
powerupsequence[PowerupSprite::PowerupBullet]
= loadOldPixmapSequence( tmp + MV_POWERBULLET_PPM, tmp + MV_POWERBULLET_PBM );
powerupsequence[PowerupSprite::PowerupShield]
= loadOldPixmapSequence( tmp + MV_POWERSHIELD_PPM, tmp + MV_POWERSHIELD_PBM );
powerupsequence[PowerupSprite::PowerupEnergy]
= loadOldPixmapSequence( tmp + MV_POWERENERGY_PPM, tmp + MV_POWERENERGY_PBM );
for(i=0;i<2;i++)
{
// ship[i]->setBoundsAction(QwRealMobileSprite::Wrap);
ship[i]->hide();
bullets[i]=new QPtrList<BulletSprite>;
bullets[i]->setAutoDelete(true);
mines[i]=new QPtrList<MineSprite>;
mines[i]->setAutoDelete(true);
}
explosions.setAutoDelete(true);
powerups.setAutoDelete(true);
waitForStart=false;
textSprite=0;
readConfig();
}
MyMainView::~MyMainView()
{
killTimers();
writeConfig();
}
void MyMainView::setActionCollection(KActionCollection *a)
{
actionCollection = a;
}
void MyMainView::readConfig()
{
KConfig *cfg = kapp->config();
int i;
cfg->setGroup("Game");
customConfig.gamespeed=cfg->readDoubleNumEntry("gamespeed",
predefinedConfig[0].gamespeed);
customConfig.gravity=
cfg->readDoubleNumEntry("gravity",predefinedConfig[0].gravity);
customConfig.acc=
cfg->readDoubleNumEntry("acceleration",predefinedConfig[0].acc);
customConfig.bulletDamage=
cfg->readUnsignedNumEntry("bulletDamage",predefinedConfig[0].bulletDamage);
customConfig.bulletLifeTime=
cfg->readDoubleNumEntry("bulletLifeTime",predefinedConfig[0].bulletLifeTime);
customConfig.bulletReloadTime=
cfg->readDoubleNumEntry("bulletReloadTime",predefinedConfig[0].bulletReloadTime);
customConfig.mineDamage=
cfg->readUnsignedNumEntry("mineDamage",predefinedConfig[0].mineDamage);
customConfig.shipDamage=
cfg->readUnsignedNumEntry("shipDamage",predefinedConfig[0].shipDamage);
customConfig.maxBullets=
cfg->readUnsignedNumEntry("maxBullets",predefinedConfig[0].maxBullets);
customConfig.maxMines=
cfg->readUnsignedNumEntry("maxMines",predefinedConfig[0].maxMines);
customConfig.mineReloadTime=
cfg->readDoubleNumEntry("mineReloadTime",predefinedConfig[0].mineReloadTime);
customConfig.rotationSpeed=
cfg->readDoubleNumEntry("rotationSpeed",predefinedConfig[0].rotationSpeed);
customConfig.shotSpeed=
cfg->readDoubleNumEntry("shotSpeed",predefinedConfig[0].shotSpeed);
customConfig.energyNeed=
cfg->readDoubleNumEntry("accEnergyNeed",predefinedConfig[0].energyNeed);
customConfig.rotationEnergyNeed=
cfg->readDoubleNumEntry("rotationEnergyNeed",predefinedConfig[0].rotationEnergyNeed);
customConfig.sunEnergy=
cfg->readDoubleNumEntry("sunEnergy",predefinedConfig[0].sunEnergy);
customConfig.mineActivateTime=
cfg->readDoubleNumEntry("mineActivateTime",predefinedConfig[0].mineActivateTime);
customConfig.mineFuel=
cfg->readDoubleNumEntry("mineFuel",predefinedConfig[0].mineFuel);
customConfig.shotEnergyNeed=
cfg->readDoubleNumEntry("shotEnergyNeed",predefinedConfig[0].shotEnergyNeed);
customConfig.mineEnergyNeed=
cfg->readDoubleNumEntry("mineEnergyNeed",predefinedConfig[0].mineEnergyNeed);
customConfig.startPosX=
cfg->readDoubleNumEntry("startPosX",predefinedConfig[0].startPosX);
customConfig.startPosY=
cfg->readDoubleNumEntry("startPosY",predefinedConfig[0].startPosY);
customConfig.startVelX=
cfg->readDoubleNumEntry("startVelX",predefinedConfig[0].startVelX);
customConfig.startVelY=
cfg->readDoubleNumEntry("startVelY",predefinedConfig[0].startVelY);
customConfig.powerupLifeTime=
cfg->readDoubleNumEntry("powerupLifeTime",predefinedConfig[0].powerupLifeTime);
customConfig.powerupRefreshTime=
cfg->readDoubleNumEntry("powerupRefreshTime",predefinedConfig[0].powerupRefreshTime);
customConfig.powerupShieldAmount=
cfg->readUnsignedNumEntry("powerupShieldAmount",
predefinedConfig[0].powerupShieldAmount);
customConfig.powerupEnergyAmount=
cfg->readDoubleNumEntry("powerupEnergyAmount",
predefinedConfig[0].powerupEnergyAmount);
if(Options::lastConfig() < predefinedConfigNum)
config=modifyConfig(predefinedConfig[Options::lastConfig()]);
else
config=modifyConfig(customConfig);
for(i=0;i<2;i++)
ai[i]=new Ai(i,ship,bullets,mines,&config);
}
void MyMainView::writeConfig()
{
KConfig *cfg;
cfg=KApplication::kApplication()->config();
cfg->setGroup("Game");
cfg->writeEntry("gravity",customConfig.gravity);
cfg->writeEntry("acceleration",customConfig.acc);
cfg->writeEntry("bulletDamage",customConfig.bulletDamage);
cfg->writeEntry("bulletLifeTime",customConfig.bulletLifeTime);
cfg->writeEntry("bulletReloadTime",customConfig.bulletReloadTime);
cfg->writeEntry("mineDamage",customConfig.mineDamage);
cfg->writeEntry("shipDamage",customConfig.shipDamage);
cfg->writeEntry("maxBullets",customConfig.maxBullets);
cfg->writeEntry("maxMines",customConfig.maxMines);
cfg->writeEntry("rotationSpeed",customConfig.rotationSpeed);
cfg->writeEntry("shotSpeed",customConfig.shotSpeed);
cfg->writeEntry("accEnergyNeed",customConfig.energyNeed);
cfg->writeEntry("rotationEnergyNeed",customConfig.rotationEnergyNeed);
cfg->writeEntry("sunEnergy",customConfig.sunEnergy);
cfg->writeEntry("mineActivateTime",customConfig.mineActivateTime);
cfg->writeEntry("mineReloadTime",customConfig.mineReloadTime);
cfg->writeEntry("mineFuel",customConfig.mineFuel);
cfg->writeEntry("shotEnergyNeed",customConfig.shotEnergyNeed);
cfg->writeEntry("mineEnergyNeed",customConfig.mineEnergyNeed);
cfg->writeEntry("startPosX",customConfig.startPosX);
cfg->writeEntry("startPosY",customConfig.startPosY);
cfg->writeEntry("startVelX",customConfig.startVelX);
cfg->writeEntry("startVelY",customConfig.startVelY);
cfg->writeEntry("powerupLifeTime",customConfig.powerupLifeTime);
cfg->writeEntry("powerupRefreshTime",customConfig.powerupRefreshTime);
cfg->writeEntry("powerupShieldAmount",customConfig.powerupShieldAmount);
cfg->writeEntry("powerupEnergyAmount",customConfig.powerupEnergyAmount);
}
SConfig MyMainView::modifyConfig(SConfig conf)
{
SConfig newConfig=conf;
newConfig.gamespeed*=Options::refreshTime()/33.0;
newConfig.acc*=newConfig.gamespeed;
newConfig.rotationSpeed*=newConfig.gamespeed*M_PI/ROTNUM*4;
newConfig.energyNeed*=newConfig.gamespeed;
newConfig.rotationEnergyNeed*=newConfig.gamespeed;
newConfig.mineActivateTime*=newConfig.gamespeed;
return newConfig;
}
void MyMainView::keyPressEvent(QKeyEvent *ev)
{
if((gameEnd<=0.0)&&(gameEnd>-2.0))
{
/*
if(key==options.functionKey[FunctionKeyStart])
newRound();
*/
}
else if(waitForStart)
{
/*
if((key==options.functionKey[FunctionKeyStart])
&& (!functionKeyPressed[FunctionKeyStart]))
{
functionKeyPressed[FunctionKeyStart]=true;
resume();
}
*/
}
else
{
KKey key(ev);
bool accept=true;
if(actionCollection->action("P1KeyLeft")->shortcut().contains(key))
playerKeyPressed[0][PlayerKeyLeft]=true;
else if(actionCollection->action("P2KeyLeft")->shortcut().contains(key))
playerKeyPressed[1][PlayerKeyLeft]=true;
else if(actionCollection->action("P1KeyRight")->shortcut().contains(key))
playerKeyPressed[0][PlayerKeyRight]=true;
else if(actionCollection->action("P2KeyRight")->shortcut().contains(key))
playerKeyPressed[1][PlayerKeyRight]=true;
else if(actionCollection->action("P1KeyAcc")->shortcut().contains(key))
playerKeyPressed[0][PlayerKeyAcc]=true;
else if(actionCollection->action("P2KeyAcc")->shortcut().contains(key))
playerKeyPressed[1][PlayerKeyAcc]=true;
else if(actionCollection->action("P1Shot")->shortcut().contains(key))
playerKeyPressed[0][PlayerKeyShot]=true;
else if(actionCollection->action("P2Shot")->shortcut().contains(key))
playerKeyPressed[1][PlayerKeyShot]=true;
else if(actionCollection->action("P1Mine")->shortcut().contains(key))
playerKeyPressed[0][PlayerKeyMine]=true;
else if(actionCollection->action("P2Mine")->shortcut().contains(key))
playerKeyPressed[1][PlayerKeyMine]=true;
else
accept = false;
/*
if((key==options.functionKey[FunctionKeyStart])
&& (!functionKeyPressed[FunctionKeyStart]))
{
functionKeyPressed[FunctionKeyStart]=true;
pause();
}
*/
if(!accept)
ev->ignore();
}
}
void MyMainView::keyReleaseEvent(QKeyEvent *ev)
{
KKey key(ev);
bool accept=true;
if(actionCollection->action("P1KeyLeft")->shortcut().contains(key))
playerKeyPressed[0][PlayerKeyLeft]=false;
else if(actionCollection->action("P2KeyLeft")->shortcut().contains(key))
playerKeyPressed[1][PlayerKeyLeft]=false;
else if(actionCollection->action("P1KeyRight")->shortcut().contains(key))
playerKeyPressed[0][PlayerKeyRight]=false;
else if(actionCollection->action("P2KeyRight")->shortcut().contains(key))
playerKeyPressed[1][PlayerKeyRight]=false;
else if(actionCollection->action("P1KeyAcc")->shortcut().contains(key))
playerKeyPressed[0][PlayerKeyAcc]=false;
else if(actionCollection->action("P2KeyAcc")->shortcut().contains(key))
playerKeyPressed[1][PlayerKeyAcc]=false;
else if(actionCollection->action("P1Shot")->shortcut().contains(key))
playerKeyPressed[0][PlayerKeyShot]=false;
else if(actionCollection->action("P2Shot")->shortcut().contains(key))
playerKeyPressed[1][PlayerKeyShot]=false;
else if(actionCollection->action("P1Mine")->shortcut().contains(key))
playerKeyPressed[0][PlayerKeyMine]=false;
else if(actionCollection->action("P2Mine")->shortcut().contains(key))
playerKeyPressed[1][PlayerKeyMine]=false;
else
accept = false;
if(!accept)
ev->ignore();
}
void MyMainView::pause()
{
if( !waitForStart )
{
pauseAction->setChecked( true );
waitForStart=true;
killTimers();
emit setStatusText(i18n(" paused "), IDS_PAUSE);
}
}
void MyMainView::resume()
{
waitForStart=false;
timerID=startTimer(Options::refreshTime());
emit(setStatusText("",IDS_PAUSE));
emit(setStatusText("",IDS_MAIN));
}
void MyMainView::start( )
{
if( ( gameEnd <= 0.0 ) && ( gameEnd > -2.0 ) )
{
newRound( );
}
else if( waitForStart )
{
waitForStart = false;
timerID=startTimer(Options::refreshTime());
emit(setStatusText("",IDS_PAUSE));
emit(setStatusText("",IDS_MAIN));
pauseAction->setEnabled( true );
pauseAction->setChecked( false );
}
}
void MyMainView::stop()
{
pauseAction->setEnabled( false );
pauseAction->setChecked( false );
killTimers();
waitForStart = true;
}
void MyMainView::togglePause( )
{
if( waitForStart )
resume( );
else
pause( );
}
void MyMainView::resizeEvent(QResizeEvent *event)
{
double mx,my;
MineSprite *mine;
BulletSprite *bullet;
PowerupSprite *powerup;
int i,current;
mx=(event->size().width()-event->oldSize().width())/2.0;
my=(event->size().height()-event->oldSize().height())/2.0;
QWidget::resizeEvent(event);
view.resize(width(),height());
field.resize(width(),height());
// printf("%d %d\n",field.width(),field.height());
sun->move(width()/2-1,height()/2-1);
for(i=0;i<2;i++)
{
// ship[i]->adoptSpritefieldBounds();
ship[i]->moveBy(mx,my);
current=mines[i]->at();
for(mine=mines[i]->first();mine;mine=mines[i]->next())
{
// mine->adoptSpritefieldBounds();
mine->moveBy(mx,my);
}
if(current>=0)
mines[i]->at(current);
current=bullets[i]->at();
for(bullet=bullets[i]->first();bullet;bullet=bullets[i]->next())
{
// bullet->adoptSpritefieldBounds();
bullet->moveBy(mx,my);
}
if(current>=0)
bullets[i]->at(current);
}
if(textSprite)
textSprite->moveBy((int)mx,(int)my);
current=powerups.at();
for(powerup=powerups.first();powerup;powerup=powerups.next())
powerup->moveBy(mx,my);
if(current>=0)
powerups.at(current);
}
void MyMainView::newRound()
{
double mx,my;
int i;
timeToNextPowerup=random.getDouble() * config.powerupRefreshTime;
powerups.clear();
killTimers();
mx=width()/2.0;
my=height()/2.0;
ship[0]->move(mx+config.startPosX,my+config.startPosY);
ship[0]->setRotation(0.0);
ship[0]->setFrame(0);
ship[1]->move(mx-config.startPosX,my-config.startPosY);
ship[1]->setRotation(M_PI);
ship[1]->setFrame(ROTNUM/2);
ship[0]->setVelocity(config.startVelX,config.startVelY);
ship[1]->setVelocity(-config.startVelX,-config.startVelY);
for(i=0;i<2;i++)
{
ship[i]->show();
ship[i]->setEnergy(99.9);
ship[i]->setHitPoints(Options::startHitPoints(i));
ship[i]->stop(false);
ship[i]->setExplosion(-1);
emit(energy(i,(int)ship[i]->getEnergy()));
emit(hitPoints(i,ship[i]->getHitPoints()));
bulletShot[i]=false;
bullets[i]->clear();
mines[i]->clear();
ship[i]->mine(0.0);
ship[i]->bullet(0.0);
ship[i]->setBulletPowerups(0);
ship[i]->setMinePowerups(0);
ai[i]->newRound();
}
explosions.clear();
gameEnd=-10.0;
for(i=0;i<PlayerKeyNum;i++)
{
playerKeyPressed[0][i]=false;
playerKeyPressed[1][i]=false;
}
if(textSprite)
{
textSprite->hide();
delete textSprite;
textSprite=0;
}
field.update();
QString str = i18n("Press %1 to start")
.arg(KShortcut(GAME_START_SHORTCUT).toString());
emit(setStatusText(str,IDS_MAIN));
emit( setStatusText( "", IDS_PAUSE ) );
stop( );
}
void MyMainView::newGame()
{
int i;
for(i=0;i<2;i++)
{
ship[i]->setWins(0);
emit(wins(i,0));
}
newRound();
}
void MyMainView::timerEvent(QTimerEvent *event)
{
unsigned w;
int i;
bool stopped = false;
if(event->timerId()==timerID)
{
killTimers();
if(gameEnd>0.0)
{
gameEnd-=1.0;
if(gameEnd<=0.0)
{
stopped = true;
if(textSprite)
{
textSprite->hide();
delete textSprite;
textSprite=0;
}
textSprite=new QCanvasText(&field);
textSprite->move(width()/2,height()/2-90);
textSprite->setTextFlags(AlignCenter);
textSprite->setColor(qRgb(255,160,0));
textSprite->setFont(QFont(KGlobalSettings::generalFont().family(),14));
textSprite->show( );
if(ship[0]->getHitPoints()==0)
{
if(ship[1]->getHitPoints()==0)
textSprite->setText(i18n("draw round"));
else
{
textSprite->setText(i18n("blue player won the round"));
w=ship[1]->getWins()+1;
ship[1]->setWins(w);
emit(wins(1,w));
}
}
else
{
textSprite->setText(i18n("red player won the round"));
w=ship[0]->getWins()+1;
ship[0]->setWins(w);
emit(wins(0,w));
}
QString str = i18n("Press %1 for new round")
.arg(KShortcut(GAME_START_SHORTCUT).toString());
emit(setStatusText(str,IDS_MAIN));
stop( );
}
}
if( !stopped )
{
for(i=0;i<2;i++)
if(Options::playerIsAi(i)&&(ship[i]->getHitPoints()>0))
ai[i]->think();
moveMines();
moveBullets();
moveExplosions();
moveShips();
calculatePowerups();
collisions();
timerID=startTimer(Options::refreshTime());
}
field.update();
}
}
void MyMainView::moveShips()
{
int i,nf,olde;
double nx,ny,en,nr;
BulletSprite *bullet;
MineSprite *mine;
for(i=0;i<2;i++)
{
bool playerIsAi = Options::playerIsAi(i);
olde=(int)ship[i]->getEnergy();
if(ship[i]->getHitPoints()==0)
{
ship[i]->forward(config.gamespeed);
ship[i]->calculateGravityAndEnergy(config.gravity,config.sunEnergy,
config.gamespeed);
}
else
{
ship[i]->calculateGravityAndEnergy(config.gravity,config.sunEnergy,
config.gamespeed);
if(!playerIsAi&&playerKeyPressed[i][PlayerKeyRight]
|| playerIsAi&&ai[i]->rotateRight())
ship[i]->rotateRight(config.rotationEnergyNeed,
config.rotationSpeed);
if(!playerIsAi&&playerKeyPressed[i][PlayerKeyLeft]
|| playerIsAi&&ai[i]->rotateLeft())
ship[i]->rotateLeft(config.rotationEnergyNeed,
config.rotationSpeed);
en=ship[i]->getEnergy();
nr=ship[i]->getRotation();
nf=ship[i]->frame();
nx=cos(nr);
ny=sin(nr);
if((!playerIsAi&&playerKeyPressed[i][PlayerKeyAcc]
|| playerIsAi&&ai[i]->accelerate())
&&(en>config.energyNeed))
{
en-=config.energyNeed;
ship[i]->setVelocity(ship[i]->xVelocity()+nx*config.acc,
ship[i]->yVelocity()-ny*config.acc);
}
if(en>99.9)
en=99.9;
ship[i]->forward(config.gamespeed);
//Bullets and Mines
if(!playerIsAi&&playerKeyPressed[i][PlayerKeyShot]
||playerIsAi&&ai[i]->shootBullet())
{
if((en>config.shotEnergyNeed) && (!ship[i]->reloadsBullet()))
{
if(bullets[i]->count() <
(config.maxBullets+ship[i]->getBulletPowerups()))
{
ship[i]->bullet(config.bulletReloadTime);
en-=config.shotEnergyNeed;
bullet=new BulletSprite(bulletsequence[i],&field,i,
config.bulletLifeTime);
bullet->move(ship[i]->x()+nx*SHOTDIST,
ship[i]->y()-ny*SHOTDIST);
bullet->setVelocity(ship[i]->xVelocity()+nx*config.shotSpeed,
ship[i]->yVelocity()-ny*config.shotSpeed);
// bullet->setBoundsAction(QwRealMobileSprite::Wrap);
bullet->show();
bullets[i]->append(bullet);
}
}
}
if(!Options::playerIsAi(i)&&playerKeyPressed[i][PlayerKeyMine]
|| Options::playerIsAi(i)&&ai[i]->layMine())
{
if((en>config.mineEnergyNeed) && (!ship[i]->reloadsMine()))
{
if(mines[i]->count() <
(config.maxMines+ship[i]->getMinePowerups()))
{
ship[i]->mine(config.mineReloadTime);
en-=config.mineEnergyNeed;
mine=new MineSprite(minesequence[i],&field,i,
config.mineActivateTime,config.mineFuel);
mine->move(ship[i]->x(),ship[i]->y());
mine->setVelocity(0,0);
//mine->setBoundsAction(QwRealMobileSprite::Wrap);
mine->show();
mines[i]->append(mine);
}
}
}
ship[i]->setEnergy(en);
if(olde!=(int)en)
emit(energy(i,(int)en));
}
}
}
void MyMainView::moveMines()
{
MineSprite* mine;
int p;
for(p=0;p<2;p++)
{
mine=mines[p]->first();
while(mine)
{
mine->calculateGravity(config.gravity,config.gamespeed);
mine->forward(config.gamespeed);
if(mine->over())
{
mine->hide();
mines[p]->remove();
mine=mines[p]->current();
}
else
mine=mines[p]->next();
}
}
}
void MyMainView::moveBullets()
{
int i;
BulletSprite *sp;
for(i=0;i<2;i++)
{
sp=bullets[i]->first();
while(sp)
{
sp->calculateGravity(config.gravity,config.gamespeed);
sp->forward(config.gamespeed);
if(sp->timeOut())
{
sp->hide();
bullets[i]->removeRef(sp);
sp=bullets[i]->current();
}
else
sp=bullets[i]->next();
}
}
}
void MyMainView::moveExplosions()
{
ExplosionSprite *ex;
ex=explosions.first();
while(ex)
{
ex->forward(config.gamespeed);
if(ex->isOver())
{
explosions.removeRef(ex);
ex=explosions.current();
}
else
ex=explosions.next();
}
}
void MyMainView::calculatePowerups()
{
PowerupSprite *sp;
int type,x,y;
sp=powerups.first();
while(sp)
{
sp->setLifetime(sp->getLifetime()-config.gamespeed);
if(sp->getLifetime()<0)
{
powerups.removeRef(sp);
sp=powerups.current();
}
else
sp=powerups.next();
}
timeToNextPowerup-=config.gamespeed;
if(timeToNextPowerup<0)
{
timeToNextPowerup= random.getDouble() * config.powerupRefreshTime;
type= random.getLong(PowerupSprite::PowerupNum);
sp=new PowerupSprite(powerupsequence[type],&field,type,
config.powerupLifeTime);
do
{
x = random.getLong(width()-40)+20;
y = random.getLong(height()-40)+20;
}
while(((x-width()/2)*(x-width()/2)+(y-height()/2)*(y-height()/2))<(50*50));
sp->move(x,y);
powerups.append(sp);
sp->show();
}
}
void MyMainView::collisions()
{
int pl,hp,op,oldhp[2],ohp;
QCanvasItemList unexact;
QCanvasItem *sprite;
BulletSprite *bullet;
MineSprite *mine;
ExplosionSprite *expl;
ShipSprite *s;
PowerupSprite *power;
QCanvasItemList hitlist;
double ndx[2],ndy[2];
double en;
QCanvasItemList::Iterator it;
for(pl=0;pl<2;pl++)
{
if(!ship[pl]->isStopped())
{
unexact.clear();
unexact=ship[pl]->collisions(false);
oldhp[pl]=hp=ship[pl]->getHitPoints();
hitlist.clear();
for(it=unexact.begin(); it != unexact.end(); ++it)
{
sprite = (*it);
if((sprite->rtti()!=S_EXPLOSION)
&& !((sprite->rtti()!=S_SUN)&&(ship[pl]->getHitPoints()==0)))
if(ship[pl]->collidesWith(sprite))
if(!hitlist.contains(sprite))
hitlist.append(sprite);
}
for(it=hitlist.begin(); it != hitlist.end(); ++it)
{
sprite = (*it);
switch(sprite->rtti())
{
case S_SUN:
hp=0;
ship[pl]->stop();
break;
case S_BULLET:
bullet=(BulletSprite *)sprite;
bullet->hide();
bullets[bullet->getPlayerNumber()]->removeRef(bullet);
hp-=config.bulletDamage;
break;
case S_SHIP:
s=(ShipSprite*)sprite;
ohp=s->getHitPoints();
if(ohp>0)
{
s->setHitPoints(ohp-hp-config.shipDamage);
emit(hitPoints(s->getPlayerNumber(),s->getHitPoints()));
ndx[0]=((1-EPSILON)*ship[0]->xVelocity()+(1+EPSILON)*ship[1]->xVelocity())/2.0;
ndy[0]=((1-EPSILON)*ship[0]->yVelocity()+(1+EPSILON)*ship[1]->yVelocity())/2.0;
ndx[1]=((1-EPSILON)*ship[1]->xVelocity()+(1+EPSILON)*ship[0]->xVelocity())/2.0;
ndy[1]=((1-EPSILON)*ship[1]->yVelocity()+(1+EPSILON)*ship[0]->yVelocity())/2.0;
ship[0]->setVelocity(ndx[0],ndy[0]);
ship[1]->setVelocity(ndx[1],ndy[1]);
hp-=ohp+config.shipDamage;
}
break;
case S_MINE:
mine=(MineSprite *)sprite;
if(mine->isActive()&& !mine->explodes())
{
mine->explode(mineexplosionsequence);
ndx[0]=(ship[pl]->xVelocity()+0.3*mine->xVelocity())/1.3;
ndy[0]=(ship[pl]->yVelocity()+0.3*mine->yVelocity())/1.3;
ship[pl]->setVelocity(ndx[0],ndy[0]);
mine->setVelocity(ndx[0],ndy[0]);
hp-=config.mineDamage;
}
break;
case S_POWERUP:
power=(PowerupSprite *)sprite;
switch(power->getType())
{
case PowerupSprite::PowerupShield:
hp+=config.powerupShieldAmount;
break;
case PowerupSprite::PowerupEnergy:
en=ship[pl]->getEnergy()+config.powerupEnergyAmount;
if(en>99)
en=99;
ship[pl]->setEnergy(en);
break;
case PowerupSprite::PowerupMine:
ship[pl]->setMinePowerups(
ship[pl]->getMinePowerups()+1);
break;
case PowerupSprite::PowerupBullet:
ship[pl]->setBulletPowerups(
ship[pl]->getMinePowerups()+1);
break;
}
power->hide();
powerups.removeRef(power);
break;
}
}
if(hp>99)
hp=99;
ship[pl]->setHitPoints(hp);
}
for(mine=mines[pl]->first();mine;mine=mines[pl]->next())
{
if(!mine->explodes())
{
unexact.clear();
unexact=mine->collisions(false);
hitlist.clear();
for( it=unexact.begin(); it != unexact.end(); ++it )
{
sprite = (*it);
if(sprite->rtti()==S_BULLET)
if(mine->collidesWith(sprite))
if(!hitlist.contains(sprite))
hitlist.append(sprite);
}
if(hitlist.count()>0)
{
mine->explode(mineexplosionsequence);
for(it=hitlist.begin(); it != hitlist.end(); ++it)
{
bullet=(BulletSprite*)(*it);
bullets[bullet->getPlayerNumber()]->removeRef(bullet);
}
}
}
}
}
hitlist.clear();
unexact.clear();
unexact=sun->collisions(false);
for( it = unexact.begin(); it != unexact.end(); ++it)
{
sprite=(*it);
switch(sprite->rtti())
{
case S_BULLET:
if(sun->collidesWith(sprite))
if(!hitlist.contains(sprite))
hitlist.append(sprite);
break;
case S_MINE:
if(!((MobileSprite*)sprite)->isStopped())
if(sun->collidesWith(sprite))
if(!hitlist.contains(sprite))
hitlist.append(sprite);
break;
}
}
for(it=hitlist.begin(); it != hitlist.end(); ++it)
{
sprite=(*it);
switch(sprite->rtti())
{
case S_BULLET:
bullet=(BulletSprite *)sprite;
bullet->hide();
bullets[bullet->getPlayerNumber()]->removeRef(bullet);
break;
case S_MINE:
mine=(MineSprite*)sprite;
mine->stop();
if(!mine->explodes())
mine->explode(mineexplosionsequence);
break;
}
}
for(pl=0;pl<2;pl++)
{
hp=ship[pl]->getHitPoints();
if(hp!=oldhp[pl])
emit(hitPoints(pl,hp));
if((hp==0)&&(ship[pl]->getExplosion()<0))
{
op=(pl+1)%2;
ship[pl]->setExplosion((int)(EXPLOSION_TIME/config.gamespeed));
expl=new ExplosionSprite(explosionsequence,&field,ship[pl]);
expl->show();
explosions.append(expl);
gameEnd=Options::timeAfterKill()/config.gamespeed;
}
}
}
void MyMainView::gameSetup()
{
if(!waitForStart)
pause();
if (KConfigDialog::showDialog("settings"))
return;
SettingsDialog *settings=new SettingsDialog(&customConfig,this,"settings");
connect(settings, SIGNAL(settingsUpdated()),this,SLOT(closeSettings()));
settings->show();
}
void MyMainView::closeSettings(){
if(Options::lastConfig()<predefinedConfigNum)
config=modifyConfig(predefinedConfig[Options::lastConfig()]);
else
config=modifyConfig(customConfig);
}
QCanvasPixmapArray* MyMainView::loadOldPixmapSequence(const QString& datapattern,
const QString& maskpattern, int framecount)
{
int image;
QPtrList<QPixmap> pixmaplist;
QPtrList<QPoint> pointlist;
QString dataname, maskname;
QPixmap *pix;
QBitmap *bitmap;
int hotx=0, hoty=0;
QPoint *point;
for( image=0; image < framecount; image++ )
{
// #### Why is this a QString??
dataname.sprintf( datapattern.ascii(), image );
maskname.sprintf( maskpattern.ascii(), image );
QFile file(dataname);
if( file.open( IO_ReadOnly ) )
{
char line[128];
file.readLine( line, 128 ); // Skip "P6"/"P3" line
file.readLine( line, 128 );
while ( line[0] == '#' )
{
// Comment line - see if it has additional parameters
if ( 0 == strncmp( line,"# HOTSPOT ", 10 ) )
sscanf( line+10, "%d %d", &hotx, &hoty);
file.readLine( line, 128 );
}
point = new QPoint( hotx, hoty );
pointlist.append( point );
}
pix = new QPixmap( dataname );
bitmap = new QBitmap( maskname );
pix->setMask( *bitmap );
pixmaplist.append( pix );
}
QCanvasPixmapArray* newarray = new QCanvasPixmapArray( pixmaplist, pointlist );
return newarray;
}
#include "mainview.moc"