aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph-Eugene Winzer2017-07-25 02:11:00 +0200
committerThierry Crozat2018-01-23 00:29:34 +0000
commit0462bd0184edf230b92e6513eb4f6ca0804ec73f (patch)
tree340fa6da4737d9d31aa702b5665001dd89f2a641
parent97ef7cbe871791a48dbcaf3d0b983ff85afe3640 (diff)
downloadscummvm-rg350-0462bd0184edf230b92e6513eb4f6ca0804ec73f.tar.gz
scummvm-rg350-0462bd0184edf230b92e6513eb4f6ca0804ec73f.tar.bz2
scummvm-rg350-0462bd0184edf230b92e6513eb4f6ca0804ec73f.zip
SUPERNOVA: Implements animation
The original game's time was stored in 55ms ticks but we just run on milliseconds. setAnimationTimer() sets the ticks the currrent room's animation() function will not be called.
-rw-r--r--engines/supernova/state.cpp187
-rw-r--r--engines/supernova/state.h5
-rw-r--r--engines/supernova/supernova.cpp12
3 files changed, 129 insertions, 75 deletions
diff --git a/engines/supernova/state.cpp b/engines/supernova/state.cpp
index 8ee7cd51b4..9066ac400a 100644
--- a/engines/supernova/state.cpp
+++ b/engines/supernova/state.cpp
@@ -118,11 +118,9 @@ void GuiElement::setHighlight(bool isHighlighted) {
}
-static const char *timeToString(int t) {
- // TODO: Does ScummVM emulate PIT timings for DOS?
-
- static char s[9];
- strcpy(s," 0:00:00");
+static Common::String timeToString(int t) {
+ char s[9] = " 0:00:00";
+ t /= 1000;
s[7] = t % 10 + '0';
t /= 10;
s[6] = t % 6 + '0';
@@ -134,9 +132,9 @@ static const char *timeToString(int t) {
s[1] = t % 10 + '0';
t /= 10;
if (t)
- s[0] = t+48;
+ s[0] = t + '0';
- return(s);
+ return Common::String(s);
}
GameManager::GameManager(SupernovaEngine *vm) {
@@ -197,8 +195,40 @@ GameManager::GameManager(SupernovaEngine *vm) {
Object::setObjectNull(_inputObject[1]);
_inputVerb = ACTION_WALK;
_processInput = false;
+ _guiEnabled = true;
+ _animationEnabled = true;
_mouseField = -1;
_inventoryScroll = 0;
+ _timer1 = 0;
+ _animationTimer = 0;
+
+ _state.time = 14200;
+ _state.timeSleep = 0;
+ _state.timeStarting = 50400000;
+ _state.timeAlarm = 25200000;
+ _state.timeAlarmSystem = _state.timeAlarm + _state.timeStarting;
+ _state.eventTime = 0xffffffff;
+ _state.shipEnergy = 2135;
+ _state.landingModuleEnergy = 923;
+ _state.greatF = 0;
+ _state.timeRobot = 0;
+ _state.money = 0;
+ _state.coins = 0;
+ _state.shoes = 0;
+ _state.nameSeen = 0;
+ _state.destination = 255;
+ _state.benOverlay = 0;
+ _state.language = 0;
+ _state.corridorSearch = false;
+ _state.alarmOn = false;
+ _state.terminalStripConnected = false;
+ _state.terminalStripWire = false;
+ _state.cableConnected = false;
+ _state.powerOff = false;
+ _state.cockpitSeen = false;
+ _state.airlockSeen = false;
+ _state.holdSeen = false;
+ _state.dream = false;
initGui();
}
@@ -218,7 +248,6 @@ void GameManager::initGui() {
x += width + 2;
}
- // Inventory + Inventory Arrows
for (int i = 0; i < ARRAYSIZE(_guiInventory); ++i) {
int x = 136 * (i % 2);
int y = 161 + 10 * (i / 2);
@@ -226,12 +255,9 @@ void GameManager::initGui() {
_guiInventory[i].setSize(x, y, x + 135, y + 9);
_guiInventory[i].setColor(kColorWhite25, kColorDarkRed, kColorWhite35, kColorRed);
}
-
- // Minimap
-
- // Status (?)
}
+
void GameManager::processInput(Common::KeyState &state) {
switch (state.keycode) {
case Common::KEYCODE_F1:
@@ -267,27 +293,28 @@ void GameManager::resetInputState() {
Object::setObjectNull(_inputObject[1]);
_inputVerb = ACTION_WALK;
_processInput = false;
+ _mouseClicked = false;
+ _key = 0;
+ _mouseClickType = Common::EVENT_MOUSEMOVE;
- processInput(Common::EVENT_MOUSEMOVE, _mouseX, _mouseY);
+ processInput();
}
-void GameManager::processInput(Common::EventType eventType, int x, int y) {
- _mouseClickType = eventType;
- _mouseX = x;
- _mouseY = y;
-
+void GameManager::processInput() {
if (_mouseClickType == Common::EVENT_LBUTTONUP) {
_vm->removeMessage();
if (((_mouseField >= 0) && (_mouseField < 256)) ||
((_mouseField >= 512) && (_mouseField < 768))) {
if (_inputVerb == ACTION_GIVE || _inputVerb == ACTION_USE) {
- // TODO: There are cases where here is no second object needed
- // for example, putting on the space suit
- if (Object::isNullObject(_inputObject[0]))
+ if (Object::isNullObject(_inputObject[0])) {
_inputObject[0] = _currentInputObject;
- else
+ if (!_inputObject[0]->hasProperty(COMBINABLE))
+ _processInput = true;
+ } else {
_inputObject[1] = _currentInputObject;
+ _processInput = true;
+ }
} else {
_inputObject[0] = _currentInputObject;
if (!Object::isNullObject(_currentInputObject))
@@ -296,12 +323,11 @@ void GameManager::processInput(Common::EventType eventType, int x, int y) {
} else if (_mouseField >= 256 && _mouseField < 512) {
resetInputState();
_inputVerb = static_cast<Action>(_mouseField - 256);
- drawStatus();
} else if (_mouseField == 768) {
- if (_inventoryScroll >= 0)
- --_inventoryScroll;
+ if (_inventoryScroll >= 2)
+ _inventoryScroll -= 2;
} else if (_mouseField == 769) {
- ++_inventoryScroll;
+ _inventoryScroll += 2;
}
} else if (_mouseClickType == Common::EVENT_RBUTTONUP) {
_vm->removeMessage();
@@ -334,40 +360,40 @@ void GameManager::processInput(Common::EventType eventType, int x, int y) {
int click = -1;
/* command row? */
- if ((y >= _guiCommandButton[0].top) && (y <= _guiCommandButton[0].bottom)) {
+ if ((_mouseY >= _guiCommandButton[0].top) && (_mouseY <= _guiCommandButton[0].bottom)) {
field = 9;
- while (x < _guiCommandButton[field].left - 1)
+ while (_mouseX < _guiCommandButton[field].left - 1)
field--;
field += 256;
}
/* exit box? */
- else if ((x >= 283) && (x <= 317) && (y >= 163) && (y <= 197)) {
- field = _exitList[(x - 283) / 7 + 5 * ((y - 163) / 7)];
+ else if ((_mouseX >= 283) && (_mouseX <= 317) && (_mouseY >= 163) && (_mouseY <= 197)) {
+ field = _exitList[(_mouseX - 283) / 7 + 5 * ((_mouseY - 163) / 7)];
}
/* inventory box */
- else if ((y >= 161) && (x <= 270)) {
- field = (x + 1) / 136 + ((y - 161) / 10) * 2;
+ else if ((_mouseY >= 161) && (_mouseX <= 270)) {
+ field = (_mouseX + 1) / 136 + ((_mouseY - 161) / 10) * 2;
if (field + _inventoryScroll < _inventory.getSize())
field += 512;
else
field = -1;
}
/* inventory arrows */
- else if ((y >= 161) && (x >= 271) && (x < 279)) {
- if (y > 180)
+ else if ((_mouseY >= 161) && (_mouseX >= 271) && (_mouseX < 279)) {
+ if (_mouseY > 180)
field = 769;
else
field = 768;
}
/* normal item */
else {
- for (int i = 0; (_currentRoom->getObject(i)->_name[0] != '\0') && (field == -1); i++) {
+ for (int i = 0; (_currentRoom->getObject(i)->_name[0] != '\0') && (field == -1) && i < kMaxObject; i++) {
click = _currentRoom->getObject(i)->_click;
if (click != 255) {
MSNImageDecoder::ClickField *clickField = _vm->_currentImage->_clickField;
do {
- if ((x >= clickField[click].x1) && (x <= clickField[click].x2) &&
- (y >= clickField[click].y1) && (y <= clickField[click].y2))
+ if ((_mouseX >= clickField[click].x1) && (_mouseX <= clickField[click].x2) &&
+ (_mouseY >= clickField[click].y1) && (_mouseY <= clickField[click].y2))
field = i;
click = clickField[click].next;
@@ -402,7 +428,7 @@ void GameManager::processInput(Common::EventType eventType, int x, int y) {
}
}
- drawStatus();
+// drawStatus();
}
}
@@ -515,6 +541,7 @@ void GameManager::mouseInput() {
void GameManager::mouseInput2() {
// STUB
+ // If animation off and timer expired, skip room animation
}
void GameManager::mouseInput3() {
@@ -564,6 +591,12 @@ void GameManager::setAnimationTimer(int ticks) {
_animationTimer = g_system->getMillis() + (55 * ticks);
}
+void GameManager::handleTime() {
+ _state.time = g_system->getMillis();
+ if (_animationTimer <= _state.time)
+ _animationTimer = 0;
+}
+
void GameManager::screenShake() {
// STUB
}
@@ -605,11 +638,11 @@ void GameManager::drawMapExits() {
}
void GameManager::animationOff() {
- // STUB
+ _animationEnabled = false;
}
void GameManager::animationOn() {
- // STUB
+ _animationEnabled = true;
}
void GameManager::edit(char *text, int x, int y, int length) {
@@ -622,8 +655,8 @@ void GameManager::loadOverlayStart() {
void GameManager::drawStatus() {
int index = static_cast<int>(_inputVerb);
- _vm->renderBox(0, 140, 320, 9, HGR_BEF_ANZ);
- _vm->renderText(guiStatusCommand_DE[index], 1, 141, COL_BEF_ANZ);
+ _vm->renderBox(0, 140, 320, 9, kColorWhite25);
+ _vm->renderText(guiStatusCommand_DE[index], 1, 141, kColorDarkGreen);
if (Object::isNullObject(_inputObject[0])) {
_vm->renderText(_currentInputObject->_name);
@@ -642,7 +675,7 @@ void GameManager::drawStatus() {
}
void GameManager::openLocker(const Room *room, Object *obj, Object *lock, int section) {
- _vm->renderImage(room->getFileNumber(), section);
+ drawImage(section);
obj->setProperty(OPENED);
lock->_click = 255;
int i = obj->_click;
@@ -651,7 +684,16 @@ void GameManager::openLocker(const Room *room, Object *obj, Object *lock, int se
}
void GameManager::closeLocker(const Room *room, Object *obj, Object *lock, int section) {
- // STUB
+ if (!obj->hasProperty(OPENED)) {
+ _vm->renderMessage("Das ist schon geschlossen.");
+ } else {
+ drawImage(invertSection(section));
+ obj->disableProperty(OPENED);
+ lock->_click = lock->_click2;
+ int i = obj->_click;
+ obj->_click = obj->_click2;
+ obj->_click2 = i;
+ }
}
int GameManager::invertSection(int section) {
@@ -741,8 +783,8 @@ bool GameManager::genericInteract(Action verb, Object &obj1, Object &obj2) {
"Es ist eine Uhr mit extra|lautem Wecker. "
"Sie hat einen|Knopf zum Verstellen der Alarmzeit.|"
"Uhrzeit: %s Alarmzeit: %s",
- timeToString(_vm->getDOSTicks() - _state.timeStarting),
- timeToString(_state.timeAlarm)).c_str());
+ timeToString(_state.time + _state.timeStarting).c_str(),
+ timeToString(_state.timeAlarm).c_str()).c_str());
} else if ((verb == ACTION_PRESS) && (obj1._id == WATCH)) {
char *min;
int hours, minutes;
@@ -930,26 +972,7 @@ bool GameManager::genericInteract(Action verb, Object &obj1, Object &obj2) {
return true;
}
-void GameManager::executeRoom() {
- if (!_vm->_messageDisplayed)
- _vm->renderRoom(*_currentRoom);
- drawMapExits();
- drawInventory();
- drawStatus();
- drawCommandBox();
-
- animationOn();
- roomBrightness();
- if (_vm->_brightness == 0)
- _vm->paletteFadeIn();
- else
- _vm->paletteBrightness();
- if (!_currentRoom->hasSeen())
- _currentRoom->onEntrance();
-
- if (_vm->_messageDisplayed || !_processInput)
- return;
-
+void GameManager::handleInput() {
bool validCommand = genericInteract(_inputVerb, *_inputObject[0], *_inputObject[1]);
if (!validCommand)
validCommand = _currentRoom->interact(_inputVerb, *_inputObject[0], *_inputObject[1]);
@@ -1039,17 +1062,35 @@ void GameManager::executeRoom() {
// This is not possible.
_vm->renderMessage("Das geht nicht.");
}
+ }
+}
- if (_newOverlay) {
- loadOverlayStart();
- _newOverlay = false;
- }
- if (_newRoom) {
- _newRoom = false;
+void GameManager::executeRoom() {
+ if (_guiEnabled) {
+ if (!_vm->_messageDisplayed) {
+ g_system->fillScreen(kColorBlack);
+ _vm->renderRoom(*_currentRoom);
}
+ drawMapExits();
+ drawInventory();
+ drawStatus();
+ drawCommandBox();
+ }
+ roomBrightness();
+ if (_vm->_brightness == 0)
+ _vm->paletteFadeIn();
+ else
+ _vm->paletteBrightness();
+ if (!_currentRoom->hasSeen())
+ _currentRoom->onEntrance();
+
+ if (!_guiEnabled || !_processInput || _vm->_messageDisplayed) {
+
+ } else {
+ handleInput();
+ resetInputState();
}
- resetInputState();
}
}
diff --git a/engines/supernova/state.h b/engines/supernova/state.h
index 79b8a8e70d..ced1de6533 100644
--- a/engines/supernova/state.h
+++ b/engines/supernova/state.h
@@ -99,7 +99,7 @@ public:
GameManager(SupernovaEngine *vm);
void processInput(Common::KeyState &state);
- void processInput(Common::EventType eventType, int x, int y);
+ void processInput();
void executeRoom();
SupernovaEngine *_vm;
@@ -116,6 +116,7 @@ public:
int _status;
bool _processInput;
bool _guiEnabled;
+ bool _animationEnabled;
Action _inputVerb;
Object *_currentInputObject;
Object *_inputObject[2];
@@ -169,6 +170,8 @@ public:
void drawImage(int section);
void changeRoom(RoomID id);
void resetInputState();
+ void handleInput();
+ void handleTime();
void setAnimationTimer(int ticks);
};
diff --git a/engines/supernova/supernova.cpp b/engines/supernova/supernova.cpp
index b5e674d46a..e1293c452d 100644
--- a/engines/supernova/supernova.cpp
+++ b/engines/supernova/supernova.cpp
@@ -167,6 +167,11 @@ int SupernovaEngine::getDOSTicks() {
}
void SupernovaEngine::updateEvents() {
+ _gm->handleTime();
+ if (_gm->_animationEnabled && _gm->_animationTimer == 0)
+ _gm->_currentRoom->animation();
+
+ _gm->_mouseClicked = false;
while (g_system->getEventManager()->pollEvent(_event)) {
switch (_event.type) {
case Common::EVENT_QUIT:
@@ -193,8 +198,13 @@ void SupernovaEngine::updateEvents() {
// fallthrough
case Common::EVENT_RBUTTONUP:
// fallthrough
+ _gm->_mouseClicked = true;
case Common::EVENT_MOUSEMOVE:
- _gm->processInput(_event.type, _event.mouse.x, _event.mouse.y);
+ _gm->_mouseClickType = _event.type;
+ _gm->_mouseX = _event.mouse.x;
+ _gm->_mouseY = _event.mouse.y;
+ if (_gm->_guiEnabled)
+ _gm->processInput();
break;
default: