aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/pegasus/graphics.cpp99
-rw-r--r--engines/pegasus/graphics.h6
-rw-r--r--engines/pegasus/neighborhood/neighborhood.cpp7
3 files changed, 109 insertions, 3 deletions
diff --git a/engines/pegasus/graphics.cpp b/engines/pegasus/graphics.cpp
index 1e529d0e07..8b83ed7a32 100644
--- a/engines/pegasus/graphics.cpp
+++ b/engines/pegasus/graphics.cpp
@@ -212,5 +212,104 @@ void GraphicsManager::doFadeInSync(const TimeValue, const TimeValue, uint32) {
void GraphicsManager::markCursorAsDirty() {
_modifiedScreen = true;
}
+
+void GraphicsManager::newShakePoint(int32 index1, int32 index2, int32 maxRadius) {
+ int32 index3 = (index1 + index2) >> 1;
+
+ if (maxRadius == 0) {
+ _shakeOffsets[index3].x = ((_shakeOffsets[index1].x + _shakeOffsets[index2].x) >> 1);
+ _shakeOffsets[index3].y = ((_shakeOffsets[index1].y + _shakeOffsets[index2].y) >> 1);
+ } else {
+ double angle = (int32)(_vm->getRandomNumber(360 - 1) * 3.1415926535 / 180);
+ int32 radius = maxRadius;
+ _shakeOffsets[index3].x = (int32)(((_shakeOffsets[index1].x + _shakeOffsets[index2].x) >> 1) +
+ cos(angle) / 2 * radius);
+ _shakeOffsets[index3].y = (int32)(((_shakeOffsets[index1].y + _shakeOffsets[index2].y) >> 1) +
+ sin(angle) * radius);
+ }
+
+ if (index1 < index3 - 1)
+ newShakePoint(index1, index3, maxRadius * 2 / 3);
+
+ if (index3 < index2 - 1)
+ newShakePoint(index3, index2, maxRadius * 2 / 3);
+}
+
+void GraphicsManager::shakeTheWorld(TimeValue duration, TimeScale scale) {
+ if (duration == 0 || scale == 0)
+ return;
+
+ _shakeOffsets[0].x = 0;
+ _shakeOffsets[0].y = 0;
+ _shakeOffsets[(kMaxShakeOffsets - 1) / 4].x = 0;
+ _shakeOffsets[(kMaxShakeOffsets - 1) / 4].y = 0;
+ _shakeOffsets[(kMaxShakeOffsets - 1) / 2].x = 0;
+ _shakeOffsets[(kMaxShakeOffsets - 1) / 2].y = 0;
+ _shakeOffsets[(kMaxShakeOffsets - 1) * 3 / 4].x = 0;
+ _shakeOffsets[(kMaxShakeOffsets - 1) * 3 / 4].y = 0;
+ _shakeOffsets[kMaxShakeOffsets - 1].x = 0;
+ _shakeOffsets[kMaxShakeOffsets - 1].y = 0;
+
+ newShakePoint(0, (kMaxShakeOffsets - 1) / 4, 8);
+ newShakePoint((kMaxShakeOffsets - 1) / 4, (kMaxShakeOffsets - 1) / 2, 6);
+ newShakePoint((kMaxShakeOffsets - 1) / 2, (kMaxShakeOffsets - 1) * 3 / 4, 4);
+ newShakePoint((kMaxShakeOffsets - 1) * 3 / 4, kMaxShakeOffsets - 1, 3);
+
+ Common::Point lastOffset(0, 0);
+
+ // Convert to millis
+ duration = duration * 1000 / scale;
+
+ uint32 startTime = g_system->getMillis();
+
+ while (g_system->getMillis() < startTime + duration) {
+ Common::Point thisOffset = _shakeOffsets[(g_system->getMillis() - startTime) * (kMaxShakeOffsets - 1) / duration];
+ if (thisOffset != lastOffset) {
+ // Fill the screen with black
+ Graphics::Surface *screen = g_system->lockScreen();
+ screen->fillRect(Common::Rect(0, 0, 640, 480), g_system->getScreenFormat().RGBToColor(0, 0, 0));
+ g_system->unlockScreen();
+
+ // Calculate the src/dst offsets and the width/height
+ int32 srcOffsetX, dstOffsetX, width;
+
+ if (thisOffset.x > 0) {
+ srcOffsetX = 0;
+ dstOffsetX = thisOffset.x;
+ width = 640 - dstOffsetX;
+ } else {
+ srcOffsetX = -thisOffset.x;
+ dstOffsetX = 0;
+ width = 640 - srcOffsetX;
+ }
+
+ int32 srcOffsetY, dstOffsetY, height;
+
+ if (thisOffset.y > 0) {
+ srcOffsetY = 0;
+ dstOffsetY = thisOffset.y;
+ height = 480 - dstOffsetY;
+ } else {
+ srcOffsetY = -thisOffset.y;
+ dstOffsetY = 0;
+ height = 480 - srcOffsetY;
+ }
+
+ // Now copy to the screen
+ g_system->copyRectToScreen((byte *)_workArea.getBasePtr(srcOffsetX, srcOffsetY), _workArea.pitch,
+ dstOffsetX, dstOffsetY, width, height);
+ g_system->updateScreen();
+
+ lastOffset = thisOffset;
+ }
+
+ g_system->delayMillis(10);
+ }
+
+ if (lastOffset.x != 0 || lastOffset.y != 0) {
+ g_system->copyRectToScreen((byte *)_workArea.pixels, _workArea.pitch, 0, 0, 640, 480);
+ g_system->updateScreen();
+ }
+}
} // End of namespace Pegasus
diff --git a/engines/pegasus/graphics.h b/engines/pegasus/graphics.h
index e1b339843f..c68c2dec76 100644
--- a/engines/pegasus/graphics.h
+++ b/engines/pegasus/graphics.h
@@ -57,6 +57,7 @@ public:
Graphics::Surface *getWorkArea() { return &_workArea; }
void clearScreen();
DisplayElement *findDisplayElement(const tDisplayElementID id);
+ void shakeTheWorld(TimeValue time, TimeScale scale);
// These default to black
void doFadeOutSync(const TimeValue = kOneSecondPerThirtyTicks, const TimeScale = kThirtyTicksPerSecond, uint32 color = 0);
@@ -73,6 +74,11 @@ private:
tDisplayOrder _backLayer, _frontLayer;
DisplayElement *_firstDisplayElement, *_lastDisplayElement;
Graphics::Surface _workArea;
+
+ // Shake Shake Shake!
+ static const int kMaxShakeOffsets = 17;
+ Common::Point _shakeOffsets[kMaxShakeOffsets];
+ void newShakePoint(int32 index1, int32 index2, int32 maxRadius);
};
} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/neighborhood.cpp b/engines/pegasus/neighborhood/neighborhood.cpp
index f6da38692b..5d8f386d15 100644
--- a/engines/pegasus/neighborhood/neighborhood.cpp
+++ b/engines/pegasus/neighborhood/neighborhood.cpp
@@ -30,6 +30,7 @@
#include "pegasus/cursor.h"
#include "pegasus/energymonitor.h"
#include "pegasus/gamestate.h"
+#include "pegasus/graphics.h"
#include "pegasus/input.h"
#include "pegasus/interaction.h"
#include "pegasus/interface.h"
@@ -726,7 +727,8 @@ void Neighborhood::turnTo(const tDirectionConstant direction) {
if (g_map)
g_map->moveToMapLocation(GameState.getCurrentNeighborhood(), GameState.getCurrentRoom(), direction);
- _pushIn.copyToCurrentPort();
+ // FIXME: This isn't right. Crazy TGWorldSaver stuff
+ //_pushIn.copyToCurrentPort();
// Added 2/10/97. Shouldn't this be here? Shouldn't we set the current activation to
// always when turning to a new view?
@@ -1419,8 +1421,7 @@ void Neighborhood::newInteraction(const tInteractionID interactionID) {
}
void Neighborhood::bumpIntoWall() {
- // TODO
- warning("bump");
+ _vm->_gfx->shakeTheWorld(15, 30);
}
void Neighborhood::zoomUpOrBump() {