Example #1
0
/*!
  \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;
		}
	}
Example #3
0
/*!
  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();
	}
    }
}