void KAsteroidsView::addRocks( int num ) { if ( !initialized ) return; for ( int i = 0; i < num; i++ ) { KRock *rock = new KRock( animation[ID_ROCK_LARGE], &field, ID_ROCK_LARGE, randInt(2), randInt(2) ? -1 : 1 ); double dx = (2.0 - randDouble()*4.0) * rockSpeed; double dy = (2.0 - randDouble()*4.0) * rockSpeed; rock->setVelocity( dx, dy ); rock->setFrame( randInt( rock->frameCount() ) ); if ( dx > 0 ) { if ( dy > 0 ) rock->setPos( 5, 5 ); else rock->setPos( 5, field.height() - 25 ); rock->setFrame( 0 ); } else { if ( dy > 0 ) rock->setPos( field.width() - 25, 5 ); else rock->setPos( field.width() - 25, field.height() - 25 ); rock->setFrame( 0 ); } rock->show(); rocks.append( rock ); } }
/*! \internal A static function that adds \a count new rocks to the scene. Called when a new game starts and when a new game level starts. */ void KRock::createRocks(int count) { for (int i=0; i<count; i++) { KRock* rock = new KMediumRock(); double dx = rockSpeed_; dx = qAbs(dx); double dy = dx; rock->setImage(randInt(ROCK_IMAGE_COUNT)); int j = randInt(4); switch (j) { case 0: rock->setPos(5,5); break; case 1: dy = -dy; rock->setPos(5,scene_->height() - 25); break; case 2: dx = -dx; rock->setPos(scene_->width() - 25,5); break; case 3: dx = -dx; dy = -dy; rock->setPos(scene_->width() - 25,scene_->height() - 25); break; default: dy = -dy; rock->setPos(5,5); break; } rock->setVelocity(dx,dy); rock->show(); } allRocksDestroyed_ = false; }
/*! \internal This function is called when a large rock or a medium rock is shattered by a missile. It is not called for small rocks. Destroy this rock because it was either hit by a missile fired by the ship, or it was hit by the ship itself while the ship's shield was up. If this rock is a large rock, remove it from the board and break it into 4 medium rocks. If this rock is a medium rock, remove it from the board and break it into four small rocks. An appropriate rockDestroyed signal is emitted so the game score can be updated. Additionally, a powerup might be created as a consequence of destroying the rock. */ void KRock::destroy() { if (isSmallRock()) return; /* Break large rocks into medium rocks and medium rocks into small rocks. */ if (isLargeRock()) view_->reportRockDestroyed(1); else if (isMediumRock()) view_->reportRockDestroyed(5); static double x_multiplier[4] = { 1.0, 1.0, -1.0, -1.0 }; static double y_multiplier[4] = { -1.0, 1.0, -1.0, 1.0 }; double dx = velocityX() + velocityX() * 0.1; double dy = velocityY() + velocityY() * 0.1; double maxRockSpeed = ROCK_SPEED_MULTIPLIER * rockSpeed_; if (dx > maxRockSpeed) dx = maxRockSpeed; else if (dx < -maxRockSpeed) dx = -maxRockSpeed; if (dy > maxRockSpeed) dy = maxRockSpeed; else if (dy < -maxRockSpeed) dy = -maxRockSpeed; /* When the old rock explodes, we create four new, smaller rocks in its place. If the old rock is a large one, create four medium size rocks. If the old rock is a medium one, create four small ones. If the old rock is already small, we don't create anything. We don't even get into this loop if the old rock is small. */ for (int i = 0; i < 4; i++) { double r = (rockSpeed_/2 - (randDouble() * rockSpeed_)) * 3.0; KRock* newRock = 0; if (isLargeRock()) newRock = new KMediumRock(); else newRock = new KSmallRock(); /* Each new rock is given an initial position which is offset from the old rock's last position by the width of one quadrant of the old rock's bounding box. Each of the new rocks is positioned in a different quadrant of the old rock's bounding box. */ qreal quadrant = newRock->boundingRect().width()/4; newRock->setPos(x() + (x_multiplier[i] * quadrant), y() + (y_multiplier[i] * quadrant)); newRock->setVelocity(dx + (x_multiplier[i] * rockSpeed_) + r, dy + (y_multiplier[i] * rockSpeed_) + r); newRock->setImage(randInt(ROCK_IMAGE_COUNT)); newRock->show(); } /* Note: This rock is actually deleted as the last statement of the caller. See KLargeRock::advance() and KMediumRock::advance(). */ }