aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2018-04-07 11:02:09 -0400
committerPaul Gilbert2018-04-07 11:02:09 -0400
commit6a3251649010e0488046c5c994b600b5c831a209 (patch)
tree6d26cdd40c3604d001397d952f04d88de82c594e
parent28a3faa1785293df6aa94917c3e846e2f8e6258e (diff)
downloadscummvm-rg350-6a3251649010e0488046c5c994b600b5c831a209.tar.gz
scummvm-rg350-6a3251649010e0488046c5c994b600b5c831a209.tar.bz2
scummvm-rg350-6a3251649010e0488046c5c994b600b5c831a209.zip
XEEN: Cache mouse clicks as well as keyboard in EventsManager
This allows the well open door/gate, shoot at enemies, then close to work with the mouse as well as the keyboard. The pending event queue has also been limited to 5 pending events. Trust me, you don't want to spent time spamming Shoot at a high level monster that can't reach you, only for when it's killed to have to wait several minutes whilst your party keeps shooting.
-rw-r--r--engines/xeen/dialogs/dialogs.cpp78
-rw-r--r--engines/xeen/dialogs/dialogs_input.cpp9
-rw-r--r--engines/xeen/events.cpp52
-rw-r--r--engines/xeen/events.h58
-rw-r--r--engines/xeen/interface.cpp6
-rw-r--r--engines/xeen/scripts.cpp4
-rw-r--r--engines/xeen/worldofxeen/worldofxeen_menu.cpp8
7 files changed, 132 insertions, 83 deletions
diff --git a/engines/xeen/dialogs/dialogs.cpp b/engines/xeen/dialogs/dialogs.cpp
index f404996b56..1b99ec6978 100644
--- a/engines/xeen/dialogs/dialogs.cpp
+++ b/engines/xeen/dialogs/dialogs.cpp
@@ -66,51 +66,55 @@ bool ButtonContainer::checkEvents(XeenEngine *vm) {
EventsManager &events = *vm->_events;
Party &party = *vm->_party;
Windows &windows = *_vm->_windows;
+ PendingEvent event;
+ const Common::Rect WAIT_BOUNDS(8, 8, 224, 140);
_buttonValue = 0;
- if (events._leftButton) {
- Common::Point pt = events._mousePos;
-
- // Check for party member glyphs being clicked
- Common::Rect r(0, 0, 32, 32);
- for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
- r.moveTo(Res.CHAR_FACES_X[idx], 150);
- if (r.contains(pt)) {
- _buttonValue = Common::KEYCODE_F1 + idx;
- break;
+ if (events.getEvent(event)) {
+ if (event._leftButton) {
+ Common::Point pt = events._mousePos;
+
+ // Check for party member glyphs being clicked
+ Common::Rect r(0, 0, 32, 32);
+ for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+ r.moveTo(Res.CHAR_FACES_X[idx], 150);
+ if (r.contains(pt)) {
+ _buttonValue = Common::KEYCODE_F1 + idx;
+ break;
+ }
}
- }
- // Check whether any button is selected
- for (uint i = 0; i < _buttons.size(); ++i) {
- if (_buttons[i]._bounds.contains(pt)) {
- events.debounceMouse();
+ // Check whether any button is selected
+ for (uint i = 0; i < _buttons.size(); ++i) {
+ if (_buttons[i]._bounds.contains(pt)) {
+ events.debounceMouse();
- _buttonValue = _buttons[i]._value;
- break;
+ _buttonValue = _buttons[i]._value;
+ break;
+ }
+ }
+
+ if (!_buttonValue && WAIT_BOUNDS.contains(pt)) {
+ _buttonValue = Common::KEYCODE_SPACE;
+ return true;
}
- }
- if (!_buttonValue && Common::Rect(8, 8, 224, 135).contains(pt)) {
- _buttonValue = 1;
- return true;
+ } else if (event.isKeyboard()) {
+ const Common::KeyCode &keycode = event._keyState.keycode;
+
+ if (keycode == Common::KEYCODE_KP8)
+ _buttonValue = Common::KEYCODE_UP;
+ else if (keycode == Common::KEYCODE_KP2)
+ _buttonValue = Common::KEYCODE_DOWN;
+ else if (keycode == Common::KEYCODE_KP_ENTER)
+ _buttonValue = Common::KEYCODE_RETURN;
+ else if (keycode != Common::KEYCODE_LCTRL && keycode != Common::KEYCODE_RCTRL
+ && keycode != Common::KEYCODE_LALT && keycode != Common::KEYCODE_RALT)
+ _buttonValue = keycode;
+
+ if (_buttonValue)
+ _buttonValue |= (event._keyState.flags & ~Common::KBD_STICKY) << 16;
}
- } else if (events.isKeyPending()) {
- Common::KeyState keyState;
- events.getKey(keyState);
-
- if (keyState.keycode == Common::KEYCODE_KP8)
- _buttonValue = Common::KEYCODE_UP;
- else if (keyState.keycode == Common::KEYCODE_KP2)
- _buttonValue = Common::KEYCODE_DOWN;
- else if (keyState.keycode == Common::KEYCODE_KP_ENTER)
- _buttonValue = Common::KEYCODE_RETURN;
- else if (keyState.keycode != Common::KEYCODE_LCTRL && keyState.keycode != Common::KEYCODE_RCTRL
- && keyState.keycode != Common::KEYCODE_LALT && keyState.keycode != Common::KEYCODE_RALT)
- _buttonValue = keyState.keycode;
-
- if (_buttonValue)
- _buttonValue |= (keyState.flags & ~Common::KBD_STICKY) << 16;
}
if (_buttonValue) {
diff --git a/engines/xeen/dialogs/dialogs_input.cpp b/engines/xeen/dialogs/dialogs_input.cpp
index b259908fe0..214aa28e5c 100644
--- a/engines/xeen/dialogs/dialogs_input.cpp
+++ b/engines/xeen/dialogs/dialogs_input.cpp
@@ -86,7 +86,7 @@ Common::KeyState Input::waitForKey(const Common::String &msg) {
bool flag = !_vm->_startupWindowActive && !windows[25]._enabled
&& _vm->_mode != MODE_FF && _vm->_mode != MODE_17;
- Common::KeyState ks;
+ PendingEvent pe;
while (!_vm->shouldExit()) {
events.updateGameCounter();
@@ -100,11 +100,8 @@ Common::KeyState Input::waitForKey(const Common::String &msg) {
windows[3].update();
events.wait(1);
-
- if (events.isKeyPending()) {
- events.getKey(ks);
+ if (events.getEvent(pe) && pe.isKeyboard())
break;
- }
}
_window->writeString("");
@@ -113,7 +110,7 @@ Common::KeyState Input::waitForKey(const Common::String &msg) {
intf._tillMove = oldTillMove;
intf._upDoorText = oldUpDoorText;
- return ks;
+ return pe._keyState;
}
void Input::animateCursor() {
diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp
index 6ceef4406b..7a0a5127cc 100644
--- a/engines/xeen/events.cpp
+++ b/engines/xeen/events.cpp
@@ -33,7 +33,7 @@ namespace Xeen {
EventsManager::EventsManager(XeenEngine *vm) : _vm(vm), _playTime(0),
_frameCounter(0), _priorFrameCounterTime(0), _gameCounter(0),
- _leftButton(false), _rightButton(false), _sprites("mouse.icn") {
+ _mousePressed(false), _sprites("mouse.icn") {
Common::fill(&_gameCounters[0], &_gameCounters[6], 0);
}
@@ -80,24 +80,23 @@ void EventsManager::pollEvents() {
_vm->_debugger->attach();
_vm->_debugger->onFrame();
} else {
- _keys.push(event.kbd);
+ addEvent(event.kbd);
}
break;
case Common::EVENT_MOUSEMOVE:
_mousePos = event.mouse;
break;
case Common::EVENT_LBUTTONDOWN:
- _leftButton = true;
- return;
- case Common::EVENT_LBUTTONUP:
- _leftButton = false;
+ _mousePressed = true;
+ addEvent(true, false);
return;
case Common::EVENT_RBUTTONDOWN:
- _rightButton = true;
- return;
+ _mousePressed = true;
+ addEvent(false, true);
+ case Common::EVENT_LBUTTONUP:
case Common::EVENT_RBUTTONUP:
- _rightButton = false;
- break;
+ _mousePressed = false;
+ return;
default:
break;
}
@@ -110,31 +109,38 @@ void EventsManager::pollEventsAndWait() {
}
void EventsManager::clearEvents() {
- _keys.clear();
- _leftButton = _rightButton = false;
-
+ _pendingEvents.clear();
+ _mousePressed = false;
}
void EventsManager::debounceMouse() {
- while (_leftButton && !_vm->shouldExit()) {
+ while (_mousePressed && !_vm->shouldExit()) {
pollEventsAndWait();
}
}
-bool EventsManager::getKey(Common::KeyState &key) {
- if (_keys.empty()) {
+
+void EventsManager::addEvent(const Common::KeyState &keyState) {
+ if (_pendingEvents.size() < MAX_PENDING_EVENTS)
+ _pendingEvents.push(PendingEvent(keyState));
+}
+
+void EventsManager::addEvent(bool leftButton, bool rightButton) {
+ if (_pendingEvents.size() < MAX_PENDING_EVENTS)
+ _pendingEvents.push(PendingEvent(leftButton, rightButton));
+}
+
+
+bool EventsManager::getEvent(PendingEvent &pe) {
+ if (_pendingEvents.empty()) {
return false;
} else {
- key = _keys.pop();
+ pe = _pendingEvents.pop();
return true;
}
}
-bool EventsManager::isKeyPending() const {
- return !_keys.empty();
-}
-
bool EventsManager::isKeyMousePressed() {
- bool result = _leftButton || _rightButton || isKeyPending();
+ bool result = isEventPending();
debounceMouse();
clearEvents();
@@ -144,7 +150,7 @@ bool EventsManager::isKeyMousePressed() {
bool EventsManager::wait(uint numFrames, bool interruptable) {
while (!_vm->shouldExit() && timeElapsed() < numFrames) {
pollEventsAndWait();
- if (interruptable && (_leftButton || _rightButton || isKeyPending()))
+ if (interruptable && isEventPending())
return true;
}
diff --git a/engines/xeen/events.h b/engines/xeen/events.h
index 0ef2c3a9e7..80ce83aacb 100644
--- a/engines/xeen/events.h
+++ b/engines/xeen/events.h
@@ -32,9 +32,30 @@ namespace Xeen {
#define GAME_FRAME_RATE (1000 / 50)
#define GAME_FRAME_TIME 50
+#define MAX_PENDING_EVENTS 5
class XeenEngine;
+struct PendingEvent {
+ Common::KeyState _keyState;
+ bool _leftButton;
+ bool _rightButton;
+
+ PendingEvent() : _leftButton(false), _rightButton(false) {}
+ PendingEvent(const Common::KeyState &keyState) : _keyState(keyState), _leftButton(false), _rightButton(false) {}
+ PendingEvent(bool leftButton, bool rightButton) : _leftButton(leftButton), _rightButton(rightButton) {}
+
+ /**
+ * Returns true if a keyboard event is pending
+ */
+ bool isKeyboard() const { return _keyState.keycode != Common::KEYCODE_INVALID; }
+
+ /**
+ * Returns ture if a mouse button event is pending
+ */
+ bool isMouse() const { return _leftButton || _rightButton; }
+};
+
class EventsManager {
private:
XeenEngine *_vm;
@@ -43,19 +64,18 @@ private:
uint32 _gameCounter;
uint32 _gameCounters[6];
uint32 _playTime;
- Common::Queue<Common::KeyState> _keys;
+ Common::Queue<PendingEvent> _pendingEvents;
SpriteResource _sprites;
+ bool _mousePressed;
/**
* Handles moving to the next game frame
*/
void nextFrame();
public:
- bool _leftButton, _rightButton;
Common::Point _mousePos;
public:
EventsManager(XeenEngine *vm);
-
~EventsManager();
/*
@@ -78,17 +98,45 @@ public:
*/
bool isCursorVisible();
+ /**
+ * Polls the ScummVM backend for any pending events
+ */
void pollEvents();
+ /**
+ * Polls for events, and wait a slight delay. This ensures the game doesn't use up 100% of the CPU
+ */
void pollEventsAndWait();
+ /**
+ * Clears all pending events
+ */
void clearEvents();
+ /**
+ * Waits for a mouse press to be released
+ */
void debounceMouse();
- bool getKey(Common::KeyState &key);
+ /**
+ * Adds a keyboard event to the queue
+ */
+ void addEvent(const Common::KeyState &keyState);
+
+ /**
+ * Adds a mouse button event to the queue
+ */
+ void addEvent(bool leftButton, bool rightButton);
- bool isKeyPending() const;
+ /**
+ * Returns the next pending key/mouse press, if any
+ */
+ bool getEvent(PendingEvent &pe);
+
+ /**
+ * Returns true if a key or mouse event is pending
+ */
+ bool isEventPending() const { return !_pendingEvents.empty(); }
/**
* Returns true if a key or mouse press is pending
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 8e52aae7ae..88b33c4164 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -262,7 +262,6 @@ void Interface::perform() {
Party &party = *_vm->_party;
Scripts &scripts = *_vm->_scripts;
Sound &sound = *_vm->_sound;
- const Common::Rect WAIT_BOUNDS(8, 8, 224, 140);
do {
// Draw the next frame
@@ -276,10 +275,7 @@ void Interface::perform() {
if (g_vm->shouldExit() || g_vm->isLoadPending() || party._dead)
return;
- if (events._leftButton && WAIT_BOUNDS.contains(events._mousePos))
- _buttonValue = Common::KEYCODE_SPACE;
- else
- checkEvents(g_vm);
+ checkEvents(g_vm);
} while (!_buttonValue && events.timeElapsed() < 1);
} while (!_buttonValue);
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 92204fc5ac..7d36b83f34 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -214,7 +214,7 @@ int Scripts::checkEvents() {
MazeObject &selectedObj = map._mobData._objects[intf._objNumber];
if (selectedObj._spriteId == (ccNum ? 15 : 16)) {
- for (uint idx = 0; idx < MIN((int)map._mobData._objects.size(), 16); ++idx) {
+ for (int idx = 0; idx < MIN((int)map._mobData._objects.size(), 16); ++idx) {
MazeObject &obj = map._mobData._objects[idx];
if (obj._spriteId == (ccNum ? 62 : 57)) {
selectedObj._id = idx;
@@ -223,7 +223,7 @@ int Scripts::checkEvents() {
}
}
} else if (selectedObj._spriteId == 73) {
- for (uint idx = 0; idx < MIN((int)map._mobData._objects.size(), 16); ++idx) {
+ for (int idx = 0; idx < MIN((int)map._mobData._objects.size(), 16); ++idx) {
MazeObject &obj = map._mobData._objects[idx];
if (obj._spriteId == 119) {
selectedObj._id = idx;
diff --git a/engines/xeen/worldofxeen/worldofxeen_menu.cpp b/engines/xeen/worldofxeen/worldofxeen_menu.cpp
index 8356794ef7..a4a4b0277b 100644
--- a/engines/xeen/worldofxeen/worldofxeen_menu.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen_menu.cpp
@@ -110,11 +110,9 @@ void MainMenuContainer::execute() {
} else {
// No active dialog. If Escape pressed, exit game entirely. Otherwise,
// open up the main menu dialog
- if (events.isKeyPending()) {
- Common::KeyState key;
- if (events.getKey(key) && key.keycode == Common::KEYCODE_ESCAPE)
- g_vm->_gameMode = GMODE_QUIT;
- }
+ PendingEvent pe;
+ if (events.getEvent(pe) && pe._keyState.keycode == Common::KEYCODE_ESCAPE)
+ g_vm->_gameMode = GMODE_QUIT;
events.clearEvents();
showMenuDialog();