PEGASUS: Add the space junk stuff

This commit is contained in:
Matthew Hoops 2011-10-23 22:50:54 -04:00
parent 841f96868a
commit b3059e75e2
5 changed files with 424 additions and 4 deletions

View File

@ -63,6 +63,7 @@ MODULE_OBJS = \
neighborhood/mars/reactor.o \
neighborhood/mars/shuttleenergymeter.o \
neighborhood/mars/spacechase3d.o \
neighborhood/mars/spacejunk.o \
neighborhood/norad/norad.o \
neighborhood/norad/noradelevator.o \
neighborhood/norad/pressuredoor.o \

View File

@ -778,7 +778,7 @@ Mars::Mars(InputHandler *nextHandler, PegasusEngine *owner) : Neighborhood(nextH
_leftShuttleMovie(kNoDisplayElement), _rightShuttleMovie(kNoDisplayElement), _lowerLeftShuttleMovie(kNoDisplayElement),
_lowerRightShuttleMovie(kNoDisplayElement), _centerShuttleMovie(kNoDisplayElement),
_upperLeftShuttleMovie(kNoDisplayElement), _upperRightShuttleMovie(kNoDisplayElement),
_leftDamageShuttleMovie(kNoDisplayElement), _rightDamageShuttleMovie(kNoDisplayElement) {
_leftDamageShuttleMovie(kNoDisplayElement), _rightDamageShuttleMovie(kNoDisplayElement), _explosions(kNoDisplayElement) {
_noAirFuse.setFunctionPtr(&airStageExpiredFunction, this);
setIsItemTaken(kMarsCard);
setIsItemTaken(kAirMask);
@ -2991,6 +2991,8 @@ void Mars::receiveNotification(Notification *notification, const tNotificationFl
} else if ((flag & kTimeForCanyonChaseFlag) != 0) {
doCanyonChase();
} else if ((flag & kExplosionFinishedFlag) != 0) {
_explosions.stop();
_explosions.hide();
// TODO
} else if ((flag & kTimeToTransportFlag) != 0) {
// TODO
@ -3170,7 +3172,8 @@ void Mars::setSoundFXLevel(const uint16 level) {
if (_canyonChaseMovie.isMovieValid())
_canyonChaseMovie.setVolume(level);
// TODO: Explosions
if (_explosions.isMovieValid())
_explosions.setVolume(level);
}
void Mars::startMarsTimer(TimeValue time, TimeScale scale, MarsTimerCode code) {
@ -3181,7 +3184,10 @@ void Mars::startMarsTimer(TimeValue time, TimeScale scale, MarsTimerCode code) {
_utilityFuse.lightFuse();
}
void Mars::marsTimerExpired(MarsTimerEvent &event) {
void Mars::marsTimerExpired(MarsTimerEvent &event) {
Common::Rect r;
uint16 x, y;
switch (event.event) {
case kMarsLaunchTubeReached:
_lowerLeftShuttleMovie.setTime(kShuttleLowerLeftTubeTime);
@ -3205,7 +3211,38 @@ void Mars::marsTimerExpired(MarsTimerEvent &event) {
break;
case kMarsSpaceChaseFinished:
// Player failed to stop the robot in time...
// TODO
_interruptionFilter = kFilterNoInput;
_rightShuttleMovie.setTime(kShuttleRightTargetLockTime);
_rightShuttleMovie.redrawMovieWorld();
_upperRightShuttleMovie.show();
_upperRightShuttleMovie.setTime(kShuttleUpperRightLockedTime);
_upperRightShuttleMovie.redrawMovieWorld();
_rightShuttleMovie.setTime(kShuttleRightGravitonTime);
_rightShuttleMovie.redrawMovieWorld();
_upperRightShuttleMovie.setTime(kShuttleUpperRightArmedTime);
_upperRightShuttleMovie.redrawMovieWorld();
_vm->delayShell(3, 1);
x = _vm->getRandomNumber(19);
y = _vm->getRandomNumber(19);
r = Common::Rect(kShuttleWindowMidH - x, kShuttleWindowMidV - y,
kShuttleWindowMidH - x + 20, kShuttleWindowMidV - y + 20);
showBigExplosion(r, kShuttleAlienShipOrder);
while (_explosions.isRunning()) {
_vm->checkCallBacks();
_vm->refreshDisplay();
g_system->delayMillis(10);
}
throwAwayMarsShuttle();
reinstateMonocleInterface();
recallToTSAFailure();
break;
default:
break;
@ -3214,6 +3251,92 @@ void Mars::marsTimerExpired(MarsTimerEvent &event) {
_interruptionFilter = kFilterAllInput;
}
void Mars::throwAwayMarsShuttle() {
_shuttleInterface1.deallocateSurface();
_shuttleInterface1.stopDisplaying();
_shuttleInterface2.deallocateSurface();
_shuttleInterface2.stopDisplaying();
_shuttleInterface3.deallocateSurface();
_shuttleInterface3.stopDisplaying();
_shuttleInterface4.deallocateSurface();
_shuttleInterface4.stopDisplaying();
_spotSounds.disposeSound();
_canyonChaseMovie.releaseMovie();
_canyonChaseMovie.stopDisplaying();
_leftShuttleMovie.releaseMovie();
_leftShuttleMovie.stopDisplaying();
_rightShuttleMovie.releaseMovie();
_rightShuttleMovie.stopDisplaying();
_lowerLeftShuttleMovie.releaseMovie();
_lowerLeftShuttleMovie.stopDisplaying();
_lowerRightShuttleMovie.releaseMovie();
_lowerRightShuttleMovie.stopDisplaying();
_centerShuttleMovie.releaseMovie();
_centerShuttleMovie.stopDisplaying();
_upperLeftShuttleMovie.releaseMovie();
_upperLeftShuttleMovie.stopDisplaying();
_upperRightShuttleMovie.releaseMovie();
_upperRightShuttleMovie.stopDisplaying();
_leftDamageShuttleMovie.releaseMovie();
_leftDamageShuttleMovie.stopDisplaying();
_rightDamageShuttleMovie.releaseMovie();
_rightDamageShuttleMovie.stopDisplaying();
// TODO: Some more to do here
_explosions.releaseMovie();
_explosions.stopDisplaying();
loadLoopSound1("");
}
void Mars::showBigExplosion(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(kBigExplosionStart, kBigExplosionStop);
_explosions.setTime(kBigExplosionStart);
_explosionCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
_explosions.start();
}
}
void Mars::hitByJunk() {
_leftDamageShuttleMovie.setTime(_leftDamageShuttleMovie.getTime() - 40);
playSpotSoundSync(kMarsJunkCollisionIn, kMarsJunkCollisionOut);
if (_leftDamageShuttleMovie.getTime() == 0) {
die(kDeathRanIntoSpaceJunk);
} else {
TimeValue t = _leftDamageShuttleMovie.getTime() / 40;
if (t == 1)
playSpotSoundSync(kShuttleHullBreachIn, kShuttleHullBreachOut);
t = _leftShuttleMovie.getTime();
_leftShuttleMovie.setTime(kShuttleLeftDamagedTime);
_vm->delayShell(1, 3);
_leftShuttleMovie.setTime(t);
}
}
void Mars::setUpNextDropTime() {
// TODO
}
tAirQuality Mars::getAirQuality(const tRoomID room) {
if ((room >= kMars36 && room <= kMars39) || (room >= kMarsMaze004 && room <= kMarsMaze200))
return kAirQualityVacuum;

View File

@ -312,6 +312,10 @@ public:
void checkAirMask();
void showBigExplosion(const Common::Rect &, const tDisplayOrder);
void hitByJunk();
void setUpNextDropTime();
Common::String getBriefingMovie();
Common::String getEnvScanMovie();
uint getNumHints();
@ -406,6 +410,7 @@ protected:
void doCanyonChase(void);
void startMarsTimer(TimeValue, TimeScale, MarsTimerCode);
void marsTimerExpired(MarsTimerEvent &);
void throwAwayMarsShuttle();
// TODO: Space chase functions
@ -442,6 +447,8 @@ protected:
Movie _leftDamageShuttleMovie;
Movie _rightDamageShuttleMovie;
ShuttleEnergyMeter _shuttleEnergyMeter;
ScalingMovie _explosions;
NotificationCallBack _explosionCallBack;
// TODO: Space chase variables
};

View File

@ -0,0 +1,213 @@
/* 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/pegasus.h"
#include "pegasus/neighborhood/mars/spacejunk.h"
namespace Pegasus {
//const TimeValue kWeaponReboundTime = kTwoSeconds * kJunkTimeScale;
//const TimeValue kCollisionReboundTime = kOneSecond * kJunkTimeScale;
const tCoordType kMaxBounceSize = 90;
const tCoordType kBounceTargetHRange = 640 - kMaxBounceSize - 2;
const tCoordType kBounceTargetVRange = 480 - kMaxBounceSize - 2;
const float kJunkXTarget = 0;
const float kJunkYTarget = 0;
const float kJunkZTarget = kJunkMinDistance;
SpaceJunk *g_spaceJunk = 0;
SpaceJunk::SpaceJunk(const tDisplayElementID id) : ScalingMovie(id) {
_timer.setScale(kJunkTimeScale);
_bouncing = false;
g_spaceJunk = this;
}
SpaceJunk::~SpaceJunk() {
g_spaceJunk = 0;
}
void SpaceJunk::launchJunk(int16 whichJunk, tCoordType xOrigin, tCoordType yOrigin) {
_bouncing = false;
TimeValue startTime = whichJunk * 16 * 40;
TimeValue stopTime = startTime + 16 * 40;
_launchPoint = Point3D(convertScreenHToSpaceX(xOrigin, kJunkMaxDistance),
convertScreenVToSpaceY(yOrigin, kJunkMaxDistance), kJunkMaxDistance);
startIdling();
stop();
setFlags(0);
setSegment(startTime, stopTime);
setFlags(kLoopTimeBase);
setTime(startTime);
start();
show();
_timer.stop();
_timer.setSegment(0, kJunkTravelTime);
_timer.setTime(0);
// Force it to set up correctly from the get-go
useIdleTime();
_timer.start();
}
void SpaceJunk::setCenter(const tCoordType centerX, const tCoordType centerY) {
_center.x = centerX;
_center.y = centerY;
Common::Rect r;
getBounds(r);
r.moveTo(centerX - (r.width() >> 1), centerY - (r.height() >> 1));
setBounds(r);
}
void SpaceJunk::setScaleSize(const tCoordType size) {
Common::Rect r;
r.left = _center.x - (size >> 1);
r.top = _center.y - (size >> 1);
r.right = r.left + size;
r.bottom = r.top + size;
setBounds(r);
}
void SpaceJunk::useIdleTime() {
if (_bouncing) {
TimeValue time = _timer.getTime();
Common::Point pt;
pt.x = linearInterp(0, _bounceTime, time, _bounceStart.x, _bounceStop.x);
pt.y = linearInterp(0, _bounceTime, time, _bounceStart.y, _bounceStop.y);
tCoordType size = linearInterp(0, _bounceTime, time, _bounceSizeStart, _bounceSizeStop);
setCenter(pt.x, pt.y);
setScaleSize(size);
if (time == _bounceTime) {
stop();
stopIdling();
hide();
((Mars *)g_neighborhood)->setUpNextDropTime();
}
} else {
float t = (float)_timer.getTime() / kJunkTravelTime;
linearInterp(_launchPoint, kJunkXTarget, kJunkYTarget, kJunkZTarget, t, _junkPosition);
Common::Point pt2D;
project3DTo2D(_junkPosition, pt2D);
setCenter(pt2D.x, pt2D.y);
setScaleSize((int)(convertSpaceYToScreenV(_junkPosition.y - kJunkSize / 2, _junkPosition.z) -
convertSpaceYToScreenV(_junkPosition.y + kJunkSize / 2, _junkPosition.z)));
if (t == 1.0) {
rebound(kCollisionReboundTime);
((Mars *)g_neighborhood)->hitByJunk();
}
}
}
bool SpaceJunk::pointInJunk(const Common::Point &pt) {
Common::Rect r;
getBounds(r);
int dx = r.width() / 4;
int dy = r.height() / 4;
r.left += dx;
r.right -= dx;
r.top += dy;
r.top -= dy;
return r.contains(pt);
}
void SpaceJunk::rebound(const TimeValue reboundTime) {
Common::Rect bounds;
getBounds(bounds);
_bounceStart.x = (bounds.left + bounds.right) >> 1;
_bounceStart.y = (bounds.top + bounds.bottom) >> 1;
PegasusEngine *vm = (PegasusEngine *)g_engine;
switch (vm->getRandomNumber(3)) {
case 0:
_bounceStop.x = kMaxBounceSize / 2 + 1 + vm->getRandomNumber(kBounceTargetHRange - 1);
_bounceStop.y = kMaxBounceSize / 2 + 1;
break;
case 1:
_bounceStop.x = kMaxBounceSize / 2 + 1 + vm->getRandomNumber(kBounceTargetHRange - 1);
_bounceStop.y = 480 - kMaxBounceSize / 2 + 1;
break;
case 2:
_bounceStop.x = kMaxBounceSize / 2 + 1;
_bounceStop.y = kMaxBounceSize / 2 + 1 + vm->getRandomNumber(kBounceTargetVRange - 1);
break;
case 3:
_bounceStop.x = 640 - kMaxBounceSize / 2 + 1;
_bounceStop.y = kMaxBounceSize / 2 + 1 + vm->getRandomNumber(kBounceTargetVRange - 1);
break;
}
_bounceSizeStart = bounds.width();
_bounceSizeStop = MIN(_bounceSizeStart, kMaxBounceSize);
_timer.stop();
_timer.setSegment(0, reboundTime);
_bounceTime = reboundTime;
_timer.setTime(0);
_timer.start();
_bouncing = true;
}
void SpaceJunk::hitByEnergyBeam(Common::Point) {
rebound(kWeaponReboundTime);
setGlowing(true);
((PegasusEngine *)g_engine)->delayShell(1, 3);
setGlowing(false);
}
void SpaceJunk::hitByGravitonCannon(Common::Point impactPoint) {
stop();
stopIdling();
hide();
Common::Rect r;
getBounds(r);
r = Common::Rect::center(impactPoint.x, impactPoint.y, r.width(), r.height());
((Mars *)g_neighborhood)->showBigExplosion(r, kShuttleJunkOrder);
((Mars *)g_neighborhood)->setUpNextDropTime();
}
void SpaceJunk::getJunkPosition(Point3D &position) {
position = _junkPosition;
}
bool SpaceJunk::isJunkFlying() {
return isIdling();
}
} // End of namespace Pegasus

View File

@ -0,0 +1,76 @@
/* 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_SPACEJUNK_H
#define PEGASUS_NEIGHBORHOOD_MARS_SPACEJUNK_H
#include "pegasus/neighborhood/mars/spacechase3d.h"
namespace Pegasus {
const tCoordType kJunkMaxScreenSize = 250;
const float kJunkSize = convertScreenVToSpaceY(kShuttleWindowMidV - kJunkMaxScreenSize / 2, kJunkMinDistance) -
convertScreenVToSpaceY(kShuttleWindowMidV + kJunkMaxScreenSize / 2, kJunkMinDistance);
class SpaceJunk : public ScalingMovie, public Idler {
public:
SpaceJunk(const tDisplayElementID);
virtual ~SpaceJunk();
void setCenter(const tCoordType, const tCoordType);
void setScaleSize(const tCoordType);
void useIdleTime();
void launchJunk(int16, tCoordType, tCoordType);
void getJunkPosition(Point3D &);
bool isJunkFlying();
bool pointInJunk(const Common::Point &);
void hitByEnergyBeam(Common::Point impactPoint);
void hitByGravitonCannon(Common::Point impactPoint);
bool junkFlying() { return _timer.isRunning(); }
protected:
void rebound(const TimeValue);
TimeBase _timer;
Point3D _launchPoint, _junkPosition;
Common::Point _center;
bool _bouncing;
Common::Point _bounceStart, _bounceStop;
tCoordType _bounceSizeStart, _bounceSizeStop;
TimeValue _bounceTime;
};
extern SpaceJunk *g_spaceJunk;
} // End of namespace Pegasus
#endif