/*! \internal If the ship has any braking force available, release the brakes, ie stop applying the breaks. Also, if the ship is braking, stop the ship movement, and stop its rotation. I don't know if this is actually correct, but this is how it was programmed when I ported it to Qtopia 4.2. */ void KShip::stopBraking() { if (brakeForce()) { if (isBraking()) { stopEngine(); stopRotation(); } releaseBrakes(); } }
void toggleBrake() { if(isBraking()) { m_brake->Set(m_brake->kForward); m_bIsBraking = false; } else { m_brake->Set(m_brake->kReverse); m_bIsBraking = true; } }
/*! The advance function does quite a lot for the ship sprite. In \a phase 0, if the ship is marked dead, just return. If not, move the ship using its current position and velocity. Then get the list of all collisions with the ship and run through the list. If the ship collides with a rock, then if the shield is up, destroy the rock. If the shiled is down (normal), mark the ship dead and return. If the ship collides with a powerup, then if the shield is up, mark the powerup destroyed. If the shield is not up, apply the powerup to the ship. In phase 1, if the ship is marked dead, explode the ship, delete it, and return. Otherwise, handle ship rotation, breaking, ship velocity, an teleporting. also update the image if the ship is rotating, and the exhaust image, if the engine is on. If the shiled is up, handle its image and age. Finally, in phase one, handle the firing of the missiles. \internal */ void KShip::advance(int phase) { if (phase == 0) { if (dying()) markDead(); if (isDead() || teleport_) return; KSprite::advance(phase); QList<QGraphicsItem*> hits = ship_->collidingItems(); QList<QGraphicsItem*>::Iterator i; for (i=hits.begin(); i!=hits.end(); ++i) { if ((*i)->type() <= ID_Base) continue; KSprite* sprite = (KSprite*)(*i); if (sprite->isRock()) { if (shield_->isUp()) { /* The ship hit a rock with the shield up. The rock is marked for death, which will cause it to break up or just disappear in in phase 1. The shield's strength is reduced by an amount commensurate with the rock size. If the strength goes to 0, the shield will be dropped in phase 1. */ sprite->markDead(); int s = 1; if (sprite->isLargeRock()) s = 3; else if (sprite->isMediumRock()) s = 2; int pl = s * (SHIELD_HIT_COST - (shield_->strength()*2)); shield_->reduceStrength(s); reducePowerLevel(pl); } else { /* The ship hit a rock with the shield down. Mark the ship dead and return. The ship will be exploded in phase 1. */ view_->setCanPause(false); markDead(); shield_->markDead(); return; } } else if (sprite->isPowerup()) { if (shield_->isUp()) { sprite->markDead(); } else { /* The ship hit a powerup with the shield down. Mark the powerup for apply. It will be applied to the ship in phase 1, if the ship survives. Also mark the powerup dead, ie consumed. */ sprite->markApply(); sprite->markDead(); return; } } else if (powerLevel() <= EMPTY_SHIP_POWER_LEVEL) { ship_->markDead(); shield_->markDead(); } } } else { // phase 1 if (isDead() || dying()) { explode(); // shatters the ship into spinning fragments. delete this; return; } if (rotateSlow_) rotateSlow_--; if (rotateLeft_) { angleIndex_ -= rotateSlow_ ? 1 : rotationRate_; if (angleIndex_ < 0) angleIndex_ = SHIP_STEPS-1; angle_ = angleIndex_ * PI_X_2 / SHIP_STEPS; cosangle_ = cos(angle_); sinangle_ = sin(angle_); } if (rotateRight_) { angleIndex_ += rotateSlow_ ? 1 : rotationRate_; if (angleIndex_ >= SHIP_STEPS) angleIndex_ = 0; angle_ = angleIndex_ * PI_X_2 / SHIP_STEPS; cosangle_ = cos(angle_); sinangle_ = sin(angle_); } if (isBraking()) { stopEngine(); stopRotation(); if ((fabs(dx_) < 2.5) && (fabs(dy_) < 2.5)) { dx_ = 0.0; dy_ = 0.0; setVelocity(dx_,dy_); releaseBrakes(); } else { double motionAngle = atan2(-dy_,-dx_); if (angle_ > M_PI) angle_ -= PI_X_2; double angleDiff = angle_ - motionAngle; if (angleDiff > M_PI) angleDiff = PI_X_2 - angleDiff; else if (angleDiff < -M_PI) angleDiff = PI_X_2 + angleDiff; double fdiff = fabs(angleDiff); if (fdiff > 0.08) { if (angleDiff > 0) rotateLeft_ = true; else if (angleDiff < 0) rotateRight_ = true; if (fdiff > 0.6) rotationRate_ = brakeForce() + 1; else if (fdiff > 0.4) rotationRate_ = 2; else rotationRate_ = 1; if (rotationRate_ > 5) rotationRate_ = 5; } else if ((fabs(dx_)>1) || (fabs(dy_)>1)) { startEngine(); // we'll make braking a bit faster dx_ += cosangle_/6 * (brakeForce() - 1); dy_ += sinangle_/6 * (brakeForce() - 1); reducePowerLevel(BRAKE_ON_COST); KExhaust::add(ship_->x() + 10 - cosangle_*11, ship_->y() + 10 - sinangle_*11, dx_-cosangle_, dy_-sinangle_, brakeForce()+1); } } } else if (engineIsOn()) { /* The ship has a terminal velocity, but trying to go faster still uses fuel (can go faster diagonally - don't care). */ double thrustx = cosangle_/8; double thrusty = sinangle_/8; if (fabs(dx_ + thrustx) < MAX_SHIP_SPEED) dx_ += thrustx; if (fabs(dy_ + thrusty) < MAX_SHIP_SPEED) dy_ += thrusty; setVelocity(dx_,dy_); reducePowerLevel(5); KExhaust::add(x() + 10 - cosangle_*10, y() + 10 - sinangle_*10, dx_-cosangle_, dy_-sinangle_, 3); } setImage(angleIndex_ >> 1); if (teleport_) { int ra = rand() % 10; if(ra == 0) ra += rand() % 20; int xra = ra * 60 + ((rand() % 20) * (rand() % 20)); int yra = ra * 50 - ((rand() % 20) * (rand() % 20)); setPos(xra,yra); teleport_ = false; if (teleportCount_ > 0) { --teleportCount_; view_->markVitalsChanged(); } wrap(); } if (shield_->isUp()) { /* The shield's position always depends on the ship's position. */ static int sf = 0; sf++; if (sf % 2) shield_->advanceImage(); shield_->setPos(x()-5,y()-5); shield_->show(); } if (isShooting()) { int maxMissiles = firePower_ + 2; if (canShoot() && (KMissile::missiles() < maxMissiles)) { KMissile* missile = new KMissile(); missile->setMaximumAge(12); missile->setPos(11 + x() + cosangle_ * 11, 11 + y() + sinangle_ * 11); missile->setVelocity(dx_ + cosangle_ * MISSILE_SPEED, dy_ + sinangle_ * MISSILE_SPEED); missile->show(); reducePowerLevel(1); view_->reportMissileFired(); int delay = 5 - firePower_; if (delay < 0) delay = 0; delayShooting(delay); // delay firing next missile. } decrementNextShotDelay(); } } }