aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorjohndoe1232014-04-15 19:35:51 +0200
committerEugene Sandulenko2018-07-20 06:43:33 +0000
commit44c566b51e661ef5751b947aed071660cc628547 (patch)
tree4267df6ff7e71347826ae5283279e1789147c58d /engines
parent60600191a07fe8e7f4945b5dab63b5b374111ed4 (diff)
downloadscummvm-rg350-44c566b51e661ef5751b947aed071660cc628547.tar.gz
scummvm-rg350-44c566b51e661ef5751b947aed071660cc628547.tar.bz2
scummvm-rg350-44c566b51e661ef5751b947aed071660cc628547.zip
ILLUSIONS: Add screen shaking effect
Diffstat (limited to 'engines')
-rw-r--r--engines/illusions/illusions.h6
-rw-r--r--engines/illusions/illusions_bbdou.h6
-rw-r--r--engines/illusions/illusions_duckman.cpp81
-rw-r--r--engines/illusions/illusions_duckman.h34
-rw-r--r--engines/illusions/screen.cpp46
-rw-r--r--engines/illusions/screen.h5
-rw-r--r--engines/illusions/scriptopcodes_duckman.cpp6
-rw-r--r--engines/illusions/updatefunctions.cpp3
8 files changed, 150 insertions, 37 deletions
diff --git a/engines/illusions/illusions.h b/engines/illusions/illusions.h
index ae7b4af7b1..7ea49fd5ca 100644
--- a/engines/illusions/illusions.h
+++ b/engines/illusions/illusions.h
@@ -68,6 +68,7 @@ class Screen;
class ScreenText;
class ScriptOpcodes;
class ScriptResource;
+class ScriptStack;
class Sequence;
class SpecialCode;
class TalkItems;
@@ -113,10 +114,15 @@ public:
SpecialCode *_specialCode;
ThreadList *_threads;
+ uint32 _nextTempThreadId;
+ bool _doScriptThreadInit;
+ ScriptStack *_stack;
ScriptResource *_scriptResource;
Fader *_fader;
+ int _pauseCtr;
+
int _resGetCtr;
uint32 _resGetTime;
bool _unpauseControlActorFlag;
diff --git a/engines/illusions/illusions_bbdou.h b/engines/illusions/illusions_bbdou.h
index ea46fb949a..fccfb59bf5 100644
--- a/engines/illusions/illusions_bbdou.h
+++ b/engines/illusions/illusions_bbdou.h
@@ -98,12 +98,6 @@ public:
uint32 _theThreadId;
uint32 _globalSceneId;
- int _pauseCtr;
- ScriptStack *_stack;
- bool _doScriptThreadInit;
-
- uint32 _nextTempThreadId;
-
void initUpdateFunctions();
int updateScript(uint flags);
diff --git a/engines/illusions/illusions_duckman.cpp b/engines/illusions/illusions_duckman.cpp
index f9d0360792..48db89d26a 100644
--- a/engines/illusions/illusions_duckman.cpp
+++ b/engines/illusions/illusions_duckman.cpp
@@ -200,6 +200,56 @@ int IllusionsEngine_Duckman::updateScript(uint flags) {
return 1;
}
+void IllusionsEngine_Duckman::startScreenShaker(uint pointsCount, uint32 duration, const ScreenShakerPoint *points, uint32 threadId) {
+ _screenShaker = new ScreenShaker();
+ _screenShaker->_pointsIndex = 0;
+ _screenShaker->_pointsCount = pointsCount;
+ _screenShaker->_finished = false;
+ _screenShaker->_duration = duration;
+ _screenShaker->_nextTime = duration + getCurrentTime();
+ _screenShaker->_points = points;
+ _screenShaker->_notifyThreadId = threadId;
+ _updateFunctions->add(71, getCurrentScene(), new Common::Functor1Mem<uint, int, IllusionsEngine_Duckman>
+ (this, &IllusionsEngine_Duckman::updateScreenShaker));
+}
+
+int IllusionsEngine_Duckman::updateScreenShaker(uint flags) {
+ if (_pauseCtr > 0 || getCurrentScene() == 0x10038) {
+ _screenShaker->_nextTime = getCurrentTime();
+ return 1;
+ }
+
+ if (flags & 1)
+ _screenShaker->_finished = true;
+
+ if (!_screenShaker->_finished) {
+ if (getCurrentTime() >= _screenShaker->_nextTime) {
+ ++_screenShaker->_pointsIndex;
+ if (_screenShaker->_pointsIndex <= _screenShaker->_pointsCount) {
+ ScreenShakerPoint shakePt = _screenShaker->_points[_screenShaker->_pointsIndex - 1];
+ if (shakePt.x == (int16)0x8000) {
+ // Loop
+ _screenShaker->_pointsIndex = 1;
+ shakePt = _screenShaker->_points[_screenShaker->_pointsIndex - 1];
+ }
+ _screenShaker->_nextTime = getCurrentTime() + _screenShaker->_duration;
+ _screen->setScreenOffset(Common::Point(shakePt.x, shakePt.y));
+ } else
+ _screenShaker->_finished = true;
+ }
+ }
+
+ if (_screenShaker->_finished) {
+ notifyThreadId(_screenShaker->_notifyThreadId);
+ delete _screenShaker;
+ _screenShaker = 0;
+ _screen->setScreenOffset(Common::Point(0, 0));
+ return 2;
+ }
+
+ return 1;
+}
+
void IllusionsEngine_Duckman::startFader(int duration, int minValue, int maxValue, int firstIndex, int lastIndex, uint32 threadId) {
_fader->_active = true;
_fader->_currValue = minValue;
@@ -553,13 +603,6 @@ void IllusionsEngine_Duckman::newScriptThread(uint32 threadId, uint32 callingThr
ScriptThread *scriptThread = new ScriptThread(this, threadId, callingThreadId, notifyFlags,
scriptCodeIp, 0, 0, 0);
_threads->startThread(scriptThread);
- if (_pauseCtr > 0)
- scriptThread->pause();
- if (_doScriptThreadInit) {
- int updateResult = kTSRun;
- while (scriptThread->_pauseCtr <= 0 && updateResult != kTSTerminate && updateResult != kTSYield)
- updateResult = scriptThread->update();
- }
}
uint32 IllusionsEngine_Duckman::newTimerThread(uint32 duration, uint32 callingThreadId, bool isAbortable) {
@@ -980,7 +1023,6 @@ void IllusionsEngine_Duckman::updateDialogState() {
_controls->destroyDialogItems();
Control *control = _dict->getObjectControl(0x40148);
_controls->destroyControl(control);
- debug("_cursor._notifyThreadId30: %08X", _cursor._notifyThreadId30);
notifyThreadId(_cursor._notifyThreadId30);
_cursor._notifyThreadId30 = 0;
_cursor._gameState = 2;
@@ -1139,6 +1181,7 @@ typedef Common::Functor1Mem<OpCall&, void, IllusionsEngine_Duckman> SpecialCodeF
#define SPECIAL(id, func) _specialCodeMap[id] = new SpecialCodeFunctionDM(this, &IllusionsEngine_Duckman::func);
void IllusionsEngine_Duckman::initSpecialCode() {
+ SPECIAL(0x00160001, spcStartScreenShaker);
SPECIAL(0x00160002, spcSetCursorHandMode);
SPECIAL(0x00160005, spcOpenInventory);
SPECIAL(0x00160007, spcPutBackInventoryItem);
@@ -1148,6 +1191,8 @@ void IllusionsEngine_Duckman::initSpecialCode() {
SPECIAL(0x0016001C, spcSetCursorInventoryMode);
}
+#undef SPECIAL
+
void IllusionsEngine_Duckman::runSpecialCode(uint32 specialCodeId, OpCall &opCall) {
SpecialCodeMapIterator it = _specialCodeMap.find(specialCodeId);
if (it != _specialCodeMap.end()) {
@@ -1158,6 +1203,26 @@ void IllusionsEngine_Duckman::runSpecialCode(uint32 specialCodeId, OpCall &opCal
}
}
+static const ScreenShakerPoint kShakerPoints0[] = {
+ {0, -2}, {0, -4}, {0, -3}, {0, -1}, {0, 1}
+};
+
+static const ScreenShakeEffect kShakerEffect0 = {
+ 6, 5, kShakerPoints0
+};
+
+static const ScreenShakeEffect *kShakerEffects = {
+ &kShakerEffect0
+};
+
+void IllusionsEngine_Duckman::spcStartScreenShaker(OpCall &opCall) {
+ // TODO Add more effects
+ ARG_BYTE(effect);
+ debug("### effect: %d", effect);
+ const ScreenShakeEffect *shakerEffect = &kShakerEffects[effect];
+ startScreenShaker(shakerEffect->_pointsCount, shakerEffect->_duration, shakerEffect->_points, opCall._threadId);
+}
+
void IllusionsEngine_Duckman::spcSetCursorHandMode(OpCall &opCall) {
ARG_BYTE(mode);
setCursorHandMode(mode);
diff --git a/engines/illusions/illusions_duckman.h b/engines/illusions/illusions_duckman.h
index ca48bc676b..da3036f348 100644
--- a/engines/illusions/illusions_duckman.h
+++ b/engines/illusions/illusions_duckman.h
@@ -71,6 +71,26 @@ struct DMInventoryItem {
: _objectId(objectId), _propertyId(propertyId) {}
};
+struct ScreenShakerPoint {
+ int16 x, y;
+};
+
+struct ScreenShakeEffect {
+ uint32 _duration;
+ uint _pointsCount;
+ const ScreenShakerPoint *_points;
+};
+
+struct ScreenShaker {
+ uint _pointsIndex;
+ uint _pointsCount;
+ bool _finished;
+ uint32 _duration;
+ uint32 _nextTime;
+ uint32 _notifyThreadId;
+ const ScreenShakerPoint *_points;
+};
+
struct OpCall;
typedef Common::Functor1<OpCall&, void> SpecialCodeFunction;
@@ -91,12 +111,6 @@ public:
uint32 _theThreadId;
uint32 _globalSceneId;
- int _pauseCtr;
- ScriptStack *_stack;
- bool _doScriptThreadInit;
-
- uint32 _nextTempThreadId;
-
uint _activeScenesCount;
uint32 _activeScenes[6];
@@ -108,11 +122,16 @@ public:
Common::Array<DMInventorySlot> _inventorySlots;
Common::Array<DMInventoryItem> _inventoyItems;
+ ScreenShaker *_screenShaker;
+
SpecialCodeMap _specialCodeMap;
void initUpdateFunctions();
int updateScript(uint flags);
-
+
+ void startScreenShaker(uint pointsCount, uint32 duration, const ScreenShakerPoint *points, uint32 threadId);
+ int updateScreenShaker(uint flags);
+
void startFader(int duration, int minValue, int maxValue, int firstIndex, int lastIndex, uint32 threadId);
void setDefaultTextCoords();
@@ -200,6 +219,7 @@ public:
// Special code
void initSpecialCode();
void runSpecialCode(uint32 specialCodeId, OpCall &opCall);
+ void spcStartScreenShaker(OpCall &opCall);
void spcSetCursorHandMode(OpCall &opCall);
void spcOpenInventory(OpCall &opCall);
void spcPutBackInventoryItem(OpCall &opCall);
diff --git a/engines/illusions/screen.cpp b/engines/illusions/screen.cpp
index 2ac1a44eaf..cd5ca683df 100644
--- a/engines/illusions/screen.cpp
+++ b/engines/illusions/screen.cpp
@@ -178,15 +178,12 @@ bool SpriteDrawQueue::calcItemRect(SpriteDrawQueueItem *item, Common::Rect &srcR
dstRect.right = item->_drawPosition.x + item->_scale * (item->_dimensions._width - item->_controlPosition.x) / 100;
dstRect.bottom = item->_drawPosition.y + item->_scale * (item->_dimensions._height - item->_controlPosition.y) / 100;
- /* CHECKME This seems to be unused basically and only called from debug code
- Left here just in case...
- if (gfx_seemsAlways0) {
- dstRect.left += screenOffsetPt.x;
- dstRect.right = screenOffsetPt.x + dstRect.right;
- dstRect.top = screenOffsetPt.y + dstRect.top;
- dstRect.bottom = screenOffsetPt.y + dstRect.bottom;
+ if (_screen->_isScreenOffsetActive) {
+ dstRect.left += _screen->_screenOffsetPt.x;
+ dstRect.right += _screen->_screenOffsetPt.x;
+ dstRect.top += _screen->_screenOffsetPt.y;
+ dstRect.bottom += _screen->_screenOffsetPt.y;
}
- */
// Check if the sprite is on-screen
if (dstRect.left >= _screen->getScreenWidth() || dstRect.right <= 0 || dstRect.top >= _screen->getScreenHeight() || dstRect.bottom <= 0)
@@ -238,6 +235,7 @@ Screen::Screen(IllusionsEngine *vm, int16 width, int16 height, int bpp)
memset(_mainPalette, 0, sizeof(_mainPalette));
_isFaderActive = false;
+ _isScreenOffsetActive = false;
}
@@ -267,6 +265,15 @@ void Screen::setDisplayOn(bool isOn) {
// TODO Clear screen when off
}
+void Screen::setScreenOffset(Common::Point offsPt) {
+ if (offsPt.x != 0 || offsPt.y != 0) {
+ _isScreenOffsetActive = true;
+ _screenOffsetPt = offsPt;
+ } else {
+ _isScreenOffsetActive = false;
+ }
+}
+
uint16 Screen::getColorKey2() {
return _colorKey2;
}
@@ -275,11 +282,33 @@ void Screen::updateSprites() {
_decompressQueue->decompressAll();
// NOTE Skipped doShiftBrightness and related as it seems to be unused
_drawQueue->drawAll();
+ if (_isScreenOffsetActive)
+ clearScreenOffsetAreas();
if (!_displayOn) // TODO Check if a video is playing then don't do it
_backSurface->fillRect(Common::Rect(_backSurface->w, _backSurface->h), 0);
g_system->copyRectToScreen((byte*)_backSurface->getBasePtr(0, 0), _backSurface->pitch, 0, 0, _backSurface->w, _backSurface->h);
}
+void Screen::clearScreenOffsetAreas() {
+ int16 x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+ if (_screenOffsetPt.x < 0) {
+ x1 = _backSurface->w + _screenOffsetPt.x;
+ x2 = _backSurface->w;
+ } else if (_screenOffsetPt.x > 0) {
+ x1 = 0;
+ x2 = _screenOffsetPt.x;
+ }
+ if (_screenOffsetPt.y < 0) {
+ y1 = _backSurface->h + _screenOffsetPt.y;
+ y2 = _backSurface->h;
+ } else if (_screenOffsetPt.y > 0) {
+ y1 = 0;
+ y2 = _screenOffsetPt.y;
+ }
+ _backSurface->fillRect(Common::Rect(0, y1, _backSurface->w, y2), 0);
+ _backSurface->fillRect(Common::Rect(x1, 0, x2, _backSurface->h), 0);
+}
+
void Screen::decompressSprite(SpriteDecompressQueueItem *item) {
switch (_backSurface->format.bytesPerPixel) {
case 1:
@@ -337,7 +366,6 @@ void Screen::getPalette(byte *colors) {
}
void Screen::shiftPalette(int16 fromIndex, int16 toIndex) {
- //debug("shiftPalette(%d, %d)", fromIndex, toIndex);
byte r, g, b;
if (toIndex > fromIndex) {
r = _mainPalette[3 * toIndex + 0];
diff --git a/engines/illusions/screen.h b/engines/illusions/screen.h
index 15a703c46c..1eef207513 100644
--- a/engines/illusions/screen.h
+++ b/engines/illusions/screen.h
@@ -121,8 +121,10 @@ public:
Graphics::Surface *allocSurface(SurfInfo &surfInfo);
bool isDisplayOn();
void setDisplayOn(bool isOn);
+ void setScreenOffset(Common::Point offsPt);
uint16 getColorKey2();
void updateSprites();
+ void clearScreenOffsetAreas();
void decompressSprite(SpriteDecompressQueueItem *item);
void drawSurface(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect, int16 scale, uint32 flags);
void setPalette(byte *colors, uint start, uint count);
@@ -153,6 +155,9 @@ public:
byte _faderPalette[768];
int _newFaderValue, _firstFaderIndex, _lastFaderIndex;
+ bool _isScreenOffsetActive;
+ Common::Point _screenOffsetPt;
+
void setSystemPalette(byte *palette);
void buildColorTransTbl();
diff --git a/engines/illusions/scriptopcodes_duckman.cpp b/engines/illusions/scriptopcodes_duckman.cpp
index 3b90e0c5e3..1caf3b8bca 100644
--- a/engines/illusions/scriptopcodes_duckman.cpp
+++ b/engines/illusions/scriptopcodes_duckman.cpp
@@ -244,7 +244,7 @@ void ScriptOpcodes_Duckman::opEnterScene18(ScriptThread *scriptThread, OpCall &o
//static uint dsceneId = 0, dthreadId = 0;
//static uint dsceneId = 0x00010008, dthreadId = 0x00020029;//Beginning in Jac
-//static uint dsceneId = 0x00010012, dthreadId = 0x0002009D;//Paramount
+static uint dsceneId = 0x00010012, dthreadId = 0x0002009D;//Paramount
//static uint dsceneId = 0x00010039, dthreadId = 0x00020089;//Map
//static uint dsceneId = 0x00010033, dthreadId = 0x000201A4;//Chinese
//static uint dsceneId = 0x00010020, dthreadId = 0x00020112;//Xmas
@@ -253,7 +253,7 @@ void ScriptOpcodes_Duckman::opEnterScene18(ScriptThread *scriptThread, OpCall &o
//static uint dsceneId = 0x0001004B, dthreadId = 0x0002029B;
//static uint dsceneId = 0x00010021, dthreadId = 0x00020113;
//static uint dsceneId = 0x0001000A, dthreadId = 0x00020043;//Home front
-static uint dsceneId = 0x0001000E, dthreadId = 0x0002007C;
+//static uint dsceneId = 0x0001000E, dthreadId = 0x0002007C;
void ScriptOpcodes_Duckman::opChangeScene(ScriptThread *scriptThread, OpCall &opCall) {
ARG_SKIP(2);
@@ -547,8 +547,6 @@ void ScriptOpcodes_Duckman::opRunSpecialCode(ScriptThread *scriptThread, OpCall
ARG_SKIP(2);
ARG_UINT32(specialCodeId);
_vm->runSpecialCode(specialCodeId, opCall);
- //DEBUG Resume calling thread, later done by the special code
- _vm->notifyThreadId(opCall._threadId);
}
void ScriptOpcodes_Duckman::opStartSound(ScriptThread *scriptThread, OpCall &opCall) {
diff --git a/engines/illusions/updatefunctions.cpp b/engines/illusions/updatefunctions.cpp
index e0cc775eb9..6e6cf52ae7 100644
--- a/engines/illusions/updatefunctions.cpp
+++ b/engines/illusions/updatefunctions.cpp
@@ -49,12 +49,10 @@ void UpdateFunctions::add(int priority, uint32 tag, UpdateFunctionCallback *call
}
void UpdateFunctions::update() {
-
// Avoid running updates multiple times in the current time slice
while (_lastTimerUpdateTime == getCurrentTime())
g_system->delayMillis(10); // CHECKME Timer resolution
_lastTimerUpdateTime = getCurrentTime();
-
UpdateFunctionListIterator it = _updateFunctions.begin();
while (it != _updateFunctions.end()) {
int r = (*it)->run();
@@ -70,7 +68,6 @@ void UpdateFunctions::update() {
break;
}
}
-
}
void UpdateFunctions::terminateByScene(uint32 sceneId) {