diff options
-rw-r--r-- | engines/pegasus/module.mk | 1 | ||||
-rwxr-xr-x | engines/pegasus/movie.h | 2 | ||||
-rwxr-xr-x | engines/pegasus/neighborhood/mars/mars.cpp | 73 | ||||
-rwxr-xr-x | engines/pegasus/neighborhood/mars/mars.h | 4 | ||||
-rwxr-xr-x | engines/pegasus/neighborhood/mars/robotship.cpp | 269 | ||||
-rwxr-xr-x | engines/pegasus/neighborhood/mars/robotship.h | 86 | ||||
-rwxr-xr-x | engines/pegasus/neighborhood/mars/spacechase3d.cpp | 16 |
7 files changed, 447 insertions, 4 deletions
diff --git a/engines/pegasus/module.mk b/engines/pegasus/module.mk index aca065ad97..034ccaa9d5 100644 --- a/engines/pegasus/module.mk +++ b/engines/pegasus/module.mk @@ -61,6 +61,7 @@ MODULE_OBJS = \ neighborhood/mars/mars.o \ neighborhood/mars/planetmover.o \ neighborhood/mars/reactor.o \ + neighborhood/mars/robotship.o \ neighborhood/mars/shuttleenergymeter.o \ neighborhood/mars/spacechase3d.o \ neighborhood/mars/spacejunk.o \ diff --git a/engines/pegasus/movie.h b/engines/pegasus/movie.h index b248cc19d4..db7b640ba8 100755 --- a/engines/pegasus/movie.h +++ b/engines/pegasus/movie.h @@ -84,7 +84,7 @@ public: void setBounds(const Common::Rect &); - void setGlowing(const bool); + void setGlowing(const bool glowing) { _glowing = glowing; } protected: bool _glowing; diff --git a/engines/pegasus/neighborhood/mars/mars.cpp b/engines/pegasus/neighborhood/mars/mars.cpp index b5564bb88a..b6b9211554 100755 --- a/engines/pegasus/neighborhood/mars/mars.cpp +++ b/engines/pegasus/neighborhood/mars/mars.cpp @@ -2993,7 +2993,19 @@ void Mars::receiveNotification(Notification *notification, const tNotificationFl } else if ((flag & kExplosionFinishedFlag) != 0) { _explosions.stop(); _explosions.hide(); - // TODO + if (g_robotShip->isDead()) { + GameState.setMarsFinished(true); + _centerShuttleMovie.hide(); + _upperRightShuttleMovie.show(); + _upperRightShuttleMovie.setTime(kShuttleUpperRightTargetDestroyedTime); + _upperRightShuttleMovie.redrawMovieWorld(); + _rightDamageShuttleMovie.hide(); + playMovieSegment(&_rightShuttleMovie, kShuttleRightDestroyedStart, kShuttleRightDestroyedStop); + playSpotSoundSync(kShuttleDestroyedIn, kShuttleDestroyedOut); + throwAwayMarsShuttle(); + reinstateMonocleInterface(); + recallToTSASuccess(); + } } else if ((flag & kTimeToTransportFlag) != 0) { // TODO } @@ -3285,7 +3297,8 @@ void Mars::throwAwayMarsShuttle() { _rightDamageShuttleMovie.stopDisplaying(); // TODO: Some more to do here - + _shuttleEnergyMeter.disposeShuttleEnergyMeter(); + _robotShip.cleanUpRobotShip(); _explosions.releaseMovie(); _explosions.stopDisplaying(); @@ -3314,6 +3327,28 @@ void Mars::showBigExplosion(const Common::Rect &r, const tDisplayOrder order) { } } +void Mars::showLittleExplosion(const Common::Rect &r, const tDisplayOrder order) { + if (_explosions.isMovieValid()) { + _explosions.setDisplayOrder(order); + + Common::Rect r2 = r; + int dx = r.width() / 2; + int dy = r.height() / 2; + r2.left -= dx; + r2.right += dx; + r2.top -= dy; + r2.bottom += dy; + _explosions.setBounds(r2); + + _explosions.show(); + _explosions.stop(); + _explosions.setSegment(kLittleExplosionStart, kLittleExplosionStop); + _explosions.setTime(kLittleExplosionStart); + _explosionCallBack.scheduleCallBack(kTriggerAtStop, 0, 0); + _explosions.start(); + } +} + void Mars::hitByJunk() { _leftDamageShuttleMovie.setTime(_leftDamageShuttleMovie.getTime() - 40); playSpotSoundSync(kMarsJunkCollisionIn, kMarsJunkCollisionOut); @@ -3334,7 +3369,39 @@ void Mars::hitByJunk() { } void Mars::setUpNextDropTime() { - // TODO + _robotShip.setUpNextDropTime(); +} + +void Mars::decreaseRobotShuttleEnergy(const int delta, Common::Point impactPoint) { + _rightDamageShuttleMovie.setTime(_rightDamageShuttleMovie.getTime() - 40 * delta); + _rightDamageShuttleMovie.redrawMovieWorld(); + + if (_rightDamageShuttleMovie.getTime() == 0) { + Common::Rect r; + _robotShip.getShuttleBounds(r); + int size = MAX(r.width(), r.height()); + r = Common::Rect::center(impactPoint.x, impactPoint.y, size, size); + _robotShip.killRobotShip(); + showBigExplosion(r, kShuttleRobotShipOrder); + } else if (delta > 1) { + Common::Rect r; + _robotShip.getShuttleBounds(r); + int size = MIN(r.width(), r.height()); + r = Common::Rect::center(impactPoint.x, impactPoint.y, size, size); + showLittleExplosion(r, kShuttleWeaponBackOrder); + TimeValue t = _rightShuttleMovie.getTime(); + _rightShuttleMovie.setTime(kShuttleRightDamagedTime); + _rightShuttleMovie.redrawMovieWorld(); + _vm->delayShell(1, 3); + _rightShuttleMovie.setTime(t); + _rightShuttleMovie.redrawMovieWorld(); + } + + if (_rightDamageShuttleMovie.getTime() <= 40) { + GameState.setScoringStoppedRobotsShuttle(); + if (!GameState.getMarsHitRobotWithCannon()) + GameState.setScoringMarsGandhi(); + } } tAirQuality Mars::getAirQuality(const tRoomID room) { diff --git a/engines/pegasus/neighborhood/mars/mars.h b/engines/pegasus/neighborhood/mars/mars.h index f2d7b336e9..8e199d1bc1 100755 --- a/engines/pegasus/neighborhood/mars/mars.h +++ b/engines/pegasus/neighborhood/mars/mars.h @@ -28,6 +28,7 @@ #include "pegasus/neighborhood/neighborhood.h" #include "pegasus/neighborhood/mars/reactor.h" +#include "pegasus/neighborhood/mars/robotship.h" #include "pegasus/neighborhood/mars/shuttleenergymeter.h" namespace Pegasus { @@ -313,7 +314,9 @@ public: void checkAirMask(); void showBigExplosion(const Common::Rect &, const tDisplayOrder); + void showLittleExplosion(const Common::Rect &, const tDisplayOrder); void hitByJunk(); + void decreaseRobotShuttleEnergy(const int, Common::Point impactPoint); void setUpNextDropTime(); Common::String getBriefingMovie(); @@ -447,6 +450,7 @@ protected: Movie _leftDamageShuttleMovie; Movie _rightDamageShuttleMovie; ShuttleEnergyMeter _shuttleEnergyMeter; + RobotShip _robotShip; ScalingMovie _explosions; NotificationCallBack _explosionCallBack; diff --git a/engines/pegasus/neighborhood/mars/robotship.cpp b/engines/pegasus/neighborhood/mars/robotship.cpp new file mode 100755 index 0000000000..279bdd8365 --- /dev/null +++ b/engines/pegasus/neighborhood/mars/robotship.cpp @@ -0,0 +1,269 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * Additional copyright for this file: + * Copyright (C) 1995-1997 Presto Studios, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "pegasus/gamestate.h" +#include "pegasus/pegasus.h" +#include "pegasus/neighborhood/mars/hermite.h" +#include "pegasus/neighborhood/mars/mars.h" +#include "pegasus/neighborhood/mars/robotship.h" +#include "pegasus/neighborhood/mars/spacechase3d.h" +#include "pegasus/neighborhood/mars/spacejunk.h" + +namespace Pegasus { + +const TimeScale kRovingScale = kTractorBeamScale; +const TimeValue kRovingTime = kSixSeconds * kRovingScale; +const TimeValue kRovingSlop = kThreeSeconds * kRovingScale; + +const int kNumSpriteColumns = 15; +const int kNumSpriteRows = 16; + +const tCoordType kInitialLocationLeft = kShuttleWindowLeft - 50; +const tCoordType kInitialLocationTop = kShuttleWindowTop - 50; +const tCoordType kInitialLocationWidth = kShuttleWindowWidth + 100; +const tCoordType kInitialLocationHeight = kShuttleWindowHeight + 100; + +const tCoordType kVelocityVectorLength = 100; +const tCoordType kVelocityVectorSlop = 50; + +const tCoordType kRovingLeft = kShuttleWindowLeft + 20; +const tCoordType kRovingTop = kShuttleWindowTop + 20; +const tCoordType kRovingWidth = kShuttleWindowMidH - kRovingLeft; +const tCoordType kRovingHeight = kShuttleWindowMidV - kRovingTop; + +RobotShip* g_robotShip = 0; + +void timeToDropJunkFunction(FunctionPtr *, void *robotShip) { + ((RobotShip *)robotShip)->timeToDropJunk(); +} + +RobotShip::RobotShip() : _spritesMovie(kNoDisplayElement) { + g_robotShip = this; + _shipRange = Common::Rect(kShuttleWindowLeft, kShuttleWindowTop, kShuttleWindowLeft + kShuttleWindowWidth, + kShuttleWindowTop + kShuttleWindowHeight); + setScale(kRovingScale); + _currentLocation.x = 0; + _currentLocation.y = 0; + _snaring = false; + _dropJunkFuse.setFunctionPtr(&timeToDropJunkFunction, (void *)this); +} + +RobotShip::~RobotShip() { + g_robotShip = 0; +} + +void RobotShip::initRobotShip() { + _spritesMovie.initFromMovieFile("Images/Mars/Ship.movie", true); + _spritesMovie.setDisplayOrder(kShuttleRobotShipOrder); + _spritesMovie.moveElementTo(kPlanetStartLeft, kPlanetStartTop); + _spritesMovie.startDisplaying(); + _spritesMovie.show(); + + Common::Rect r; + _spritesMovie.getBounds(r); + _shipWidth = r.width(); + _shipHeight = r.height(); + _dead = false; +} + +void RobotShip::cleanUpRobotShip() { + _dropJunkFuse.stopFuse(); + _spritesMovie.stopDisplaying(); + _spritesMovie.releaseMovie(); +} + +void RobotShip::startMoving() { + if (((PegasusEngine *)g_engine)->getRandomBit()) { + _p4.x = kInitialLocationLeft + ((PegasusEngine *)g_engine)->getRandomNumber(kInitialLocationWidth - 1); + if (((PegasusEngine *)g_engine)->getRandomBit()) + _p4.y = kInitialLocationTop; + else + _p4.y = kInitialLocationTop + kInitialLocationHeight; + } else { + _p4.y = kInitialLocationTop + ((PegasusEngine *)g_engine)->getRandomNumber(kInitialLocationHeight - 1); + if (((PegasusEngine *)g_engine)->getRandomBit()) + _p4.x = kInitialLocationLeft; + else + _p4.x = kInitialLocationLeft + kInitialLocationWidth; + } + + makeVelocityVector(_p4.x, _p4.y, kShuttleWindowLeft + kShuttleWindowWidth / 2, + kShuttleWindowTop + kShuttleWindowHeight / 2, _r4); + newDestination(); + setUpNextDropTime(); +} + +void RobotShip::killRobotShip() { + cleanUpRobotShip(); + _dead = true; +} + +void RobotShip::setUpNextDropTime() { + if (!isSnared()) { + _dropJunkFuse.primeFuse(kJunkDropBaseTime + ((PegasusEngine *)g_engine)->getRandomNumber(kJunkDropSlopTime)); + _dropJunkFuse.lightFuse(); + } +} + +void RobotShip::timeToDropJunk() { + if (g_spaceJunk) { + tCoordType x, y; + _spritesMovie.getCenter(x, y); + g_spaceJunk->launchJunk(((PegasusEngine *)g_engine)->getRandomNumber(24), x, y); + } +} + +void RobotShip::newDestination() { + _p1 = _p4; + _r1 = _r4; + + _p4.x = kRovingLeft + ((PegasusEngine *)g_engine)->getRandomNumber(kRovingWidth - 1); + _p4.y = kRovingTop + ((PegasusEngine *)g_engine)->getRandomNumber(kRovingHeight - 1); + + if (((PegasusEngine *)g_engine)->getRandomNumber(7) < 6) { + if (!sameSign(_p4.x - kShuttleWindowMidH, kShuttleWindowMidH - _p1.x)) { + if (sign(_p4.x - kShuttleWindowMidH) > 0) + _p4.x -= kRovingWidth; + else + _p4.x += kRovingWidth; + } + } + + if (((PegasusEngine *)g_engine)->getRandomNumber(7) < 6) { + if (!sameSign(_p4.y - kShuttleWindowMidV, kShuttleWindowMidV - _p1.y)) { + if (sign(_p4.y - kShuttleWindowMidV) > 0) + _p4.y -= kRovingHeight; + else + _p4.y += kRovingHeight; + } + } + + makeVelocityVector(_p4.x, _p4.y, kShuttleWindowLeft + kShuttleWindowWidth / 2, + kShuttleWindowTop + kShuttleWindowHeight / 2, _r4); + stop(); + _duration = kRovingTime + ((PegasusEngine *)g_engine)->getRandomNumber(kRovingSlop - 1); + setSegment(0, _duration); + setTime(0); + start(); +} + +void RobotShip::moveRobotTo(tCoordType x, tCoordType y) { + _currentLocation.x = x; + _currentLocation.y = y; + + if (_spritesMovie.isMovieValid()) { + _spritesMovie.moveElementTo(x - (_shipWidth >> 1), y - (_shipHeight >> 1)); + + if (x < _shipRange.left) + x = 0; + else if (x > _shipRange.right - 1) + x = _shipRange.width() - 1; + else + x -= _shipRange.left; + + if (y < _shipRange.top) + y = 0; + else if (y > _shipRange.bottom - 1) + y = _shipRange.height() - 1; + else + y -= _shipRange.top; + + x = kNumSpriteColumns * x / _shipRange.width(); + y = kNumSpriteRows * y / _shipRange.height(); + + _spritesMovie.setTime(40 * (x + y * kNumSpriteColumns)); + } +} + +bool RobotShip::pointInShuttle(Common::Point &pt) { + Common::Rect r; + _spritesMovie.getBounds(r); + + int dx = r.width() / 4; + int dy = r.height() / 6; + + r.left += dx; + r.right -= dx; + r.top += dy; + r.bottom -= dy; + + return r.contains(pt); +} + +void RobotShip::hitByEnergyBeam(Common::Point impactPoint) { + ((Mars *)g_neighborhood)->decreaseRobotShuttleEnergy(1, impactPoint); + setGlowing(true); + ((PegasusEngine *)g_engine)->delayShell(1, 3); + setGlowing(false); +} + +void RobotShip::hitByGravitonCannon(Common::Point impactPoint) { + GameState.setMarsHitRobotWithCannon(true); + ((Mars *)g_neighborhood)->decreaseRobotShuttleEnergy(6, impactPoint); +} + +void RobotShip::snareByTractorBeam() { + _dropJunkFuse.stopFuse(); + stop(); + + Common::Point currentV; + dHermite(_p1, _p4, _r1, _r4, _lastTime, _duration, currentV); + + _p1 = _currentLocation; + _r1 = currentV; + _p4.x = kShuttleWindowMidH; + _p4.y = kShuttleWindowMidV; + _r4.x = 0; + _r4.y = 0; + _duration = kTractorBeamTime; + _snaring = true; + setSegment(0, _duration); + setTime(0); + start(); +} + +void RobotShip::timeChanged(const TimeValue) { + Common::Point newLocation; + hermite(_p1, _p4, _r1, _r4, _lastTime, _duration, newLocation); + moveRobotTo(newLocation.x, newLocation.y); + + if (_lastTime == _duration) { + if (_snaring) + stop(); + else + newDestination(); + } +} + +void RobotShip::makeVelocityVector(tCoordType x1, tCoordType y1, tCoordType x2, tCoordType y2, Common::Point &vector) { + tCoordType length = ((PegasusEngine *)g_engine)->getRandomNumber(kVelocityVectorSlop - 1) + kVelocityVectorLength; + vector.x = x2 - x1; + vector.y = y2 - y1; + float oldLength = sqrt(vector.x * vector.x + vector.y * vector.y); + vector.x = (int)(vector.x * length / oldLength); + vector.y = (int)(vector.y * length / oldLength); +} + +} // End of namespace Pegasus diff --git a/engines/pegasus/neighborhood/mars/robotship.h b/engines/pegasus/neighborhood/mars/robotship.h new file mode 100755 index 0000000000..7c6d996566 --- /dev/null +++ b/engines/pegasus/neighborhood/mars/robotship.h @@ -0,0 +1,86 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * Additional copyright for this file: + * Copyright (C) 1995-1997 Presto Studios, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef PEGASUS_NEIGHBORHOOD_MARS_ROBOTSHIP_H +#define PEGASUS_NEIGHBORHOOD_MARS_ROBOTSHIP_H + +#include "pegasus/movie.h" + +namespace Pegasus { + +const tCoordType kShuttleMovieWidth = 114; +const tCoordType kShuttleMovieHeight = 42; + +class RobotShip : IdlerTimeBase { +friend void timeToDropJunkFunction(FunctionPtr *, void *); + +public: + RobotShip(); + virtual ~RobotShip(); + + void initRobotShip(); + void cleanUpRobotShip(); + + void startMoving(); + + void killRobotShip(); + + bool pointInShuttle(Common::Point&); + + void hitByEnergyBeam(Common::Point impactPoint); + void hitByGravitonCannon(Common::Point impactPoint); + + void getShuttleBounds(Common::Rect &r) { _spritesMovie.getBounds(r); } + + void setGlowing(const bool glowing) { _spritesMovie.setGlowing(glowing); } + + void snareByTractorBeam(); + bool isSnared() { return _snaring && getTime() == _duration; } + + bool isDead() { return _dead; } + + void setUpNextDropTime(); + +protected: + void newDestination(); + void moveRobotTo(tCoordType, tCoordType); + void timeToDropJunk(); + virtual void timeChanged(const TimeValue); + void makeVelocityVector(tCoordType, tCoordType, tCoordType, tCoordType, Common::Point &); + + GlowingMovie _spritesMovie; + Common::Rect _shipRange; + int _shipWidth, _shipHeight; + Common::Point _p1, _p4, _r1, _r4, _currentLocation; + FuseFunction _dropJunkFuse; + TimeValue _duration; + bool _snaring, _dead; +}; + +extern RobotShip *g_robotShip; + +} // End of namespace Pegasus + +#endif diff --git a/engines/pegasus/neighborhood/mars/spacechase3d.cpp b/engines/pegasus/neighborhood/mars/spacechase3d.cpp index a15898f573..05f8233763 100755 --- a/engines/pegasus/neighborhood/mars/spacechase3d.cpp +++ b/engines/pegasus/neighborhood/mars/spacechase3d.cpp @@ -87,4 +87,20 @@ float linearInterp(const float arg1, const float arg2, const float t) { return arg1 + (arg2 - arg1) * t; } +bool isNegative(int a) { + return a < 0; +} + +bool isPositive(int a) { + return a > 0; +} + +int sign(int a) { + return isNegative(a) ? -1 : isPositive(a) ? 1 : 0; +} + +bool sameSign(int a, int b) { + return sign(a) == sign(b); +} + } // End of namespace Pegasus |