mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-24 19:45:07 +00:00
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.
This commit is contained in:
parent
28a3faa178
commit
6a32516490
@ -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;
|
||||
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 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;
|
||||
}
|
||||
|
||||
} 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;
|
||||
}
|
||||
|
||||
if (!_buttonValue && Common::Rect(8, 8, 224, 135).contains(pt)) {
|
||||
_buttonValue = 1;
|
||||
return true;
|
||||
}
|
||||
} 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) {
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
bool isKeyPending() const;
|
||||
/**
|
||||
* Adds a mouse button event to the queue
|
||||
*/
|
||||
void addEvent(bool leftButton, bool rightButton);
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user