From 97cd5a7e6961be52d545e3c131a85cd90c582441 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 3 Jan 2015 03:19:14 -1000 Subject: XEEN: Split game interface code into it's own class --- engines/xeen/interface.cpp | 231 +++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/interface.h | 73 ++++++++++++++ engines/xeen/module.mk | 1 + engines/xeen/xeen.cpp | 204 +-------------------------------------- engines/xeen/xeen.h | 43 ++------- 5 files changed, 319 insertions(+), 233 deletions(-) create mode 100644 engines/xeen/interface.cpp create mode 100644 engines/xeen/interface.h diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp new file mode 100644 index 0000000000..cdb9204537 --- /dev/null +++ b/engines/xeen/interface.cpp @@ -0,0 +1,231 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "xeen/interface.h" +#include "xeen/resources.h" +#include "xeen/xeen.h" + +namespace Xeen { + +Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { + Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr); + _batUIFrame = 0; + _spotDoorsUIFrame = 0; + _dangerSenseUIFrame = 0; + _face1UIFrame = 0; + _face2UIFrame = 0; + _blessedUIFrame = 0; + _powerShieldUIFrame = 0; + _holyBonusUIFrame = 0; + _heroismUIFrame = 0; + _isEarlyGame = false; + _buttonsLoaded = false; + + loadSprites(); +} + +void Interface::loadSprites() { + _globalSprites.load("global.icn"); + _borderSprites.load("border.icn"); + _spellFxSprites.load("spellfx.icn"); + _fecpSprites.load("fecp.brd"); + _blessSprites.load("bless.icn"); +} + +void Interface::setup(bool soundPlayed) { + SpriteResource uiSprites("inn.icn"); + + // Get mappings to the active characters in the party + _vm->_party._activeParty.resize(_vm->_party._partyCount); + for (int i = 0; i < _vm->_party._partyCount; ++i) { + _vm->_party._activeParty[i] = &_vm->_roster[_vm->_party._partyMembers[i]]; + } + + _isEarlyGame = _vm->_party._minutes >= 300; + + if (_vm->_party._mazeId == 0) { + if (!soundPlayed) { + warning("TODO: loadSound?"); + } + + if (!_partyFaces[0]) { + // Xeen only uses 24 of possible 30 character slots + loadCharIcons(XEEN_TOTAL_CHARACTERS); + + for (int i = 0; i < _vm->_party._partyCount; ++i) + _partyFaces[i] = &_charFaces[_vm->_party._partyMembers[i]]; + } + + _vm->_mode = MODE_1; + Common::Array xeenSideChars; + + // Build up a list of characters on the same Xeen side being loaded + for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) { + PlayerStruct &player = _vm->_roster[i]; + if (player._name.empty() || player._xeenSide != _vm->_loadDarkSide) + continue; + + xeenSideChars.push_back(i); + } + + // Add in buttons for the UI + _buttonsLoaded = true; + addButton(Common::Rect(16, 100, 40, 120), 242, &uiSprites, true); + addButton(Common::Rect(52, 100, 76, 120), 243, &uiSprites, true); + addButton(Common::Rect(87, 100, 111, 120), 68, &uiSprites, true); + addButton(Common::Rect(122, 100, 146, 120), 82, &uiSprites, true); + addButton(Common::Rect(157, 100, 181, 120), 67, &uiSprites, true); + addButton(Common::Rect(192, 100, 216, 120), 88, &uiSprites, true); + addButton(Common::Rect(), 27, &uiSprites, false); + addButton(Common::Rect(16, 16, 48, 48), 49, &uiSprites, false); + addButton(Common::Rect(117, 16, 139, 48), 50, &uiSprites, false); + addButton(Common::Rect(16, 59, 48, 81), 51, &uiSprites, false); + addButton(Common::Rect(117, 59, 149, 81), 52, &uiSprites, false); + + setupBackground(); + } +} + +void Interface::loadCharIcons(int numChars) { + for (int i = 0; i < numChars; ++i) { + // Load new character resource + Common::String name = Common::String::format("char%02d.fac", i); + _charFaces[i].load(name); + } + + _dseFace.load("dse.fac"); +} + +void Interface::setupBackground() { + _vm->_screen->loadBackground("back.raw"); + assembleBorder(); +} + +void Interface::assembleBorder() { + Screen &screen = *_vm->_screen; + Window &gameWindow = screen._windows[28]; + + // Draw the outer frame + _globalSprites.draw(gameWindow, 0); + + // Draw the animating bat character used to show when levitate is active + _borderSprites.draw(screen, _vm->_party._levitateActive ? _batUIFrame + 16 : 16); + _batUIFrame = (_batUIFrame + 1) % 12; + + // Draw UI element to indicate whether can spot hidden doors + _borderSprites.draw(screen, + (_vm->_spotDoorsAllowed && _vm->_party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28, + Common::Point(194, 91)); + _spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12; + + // Draw UI element to indicate whether can sense danger + _borderSprites.draw(screen, + (_vm->_dangerSenseAllowed && _vm->_party.checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40, + Common::Point(107, 9)); + _dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12; + + // Handle the face UI elements for indicating clairvoyance status + _face1UIFrame = (_face1UIFrame + 1) % 4; + if (_vm->_face1State == 0) + _face1UIFrame += 4; + else if (_vm->_face1State == 2) + _face1UIFrame = 0; + + _face2UIFrame = (_face2UIFrame + 1) % 4 + 12; + if (_vm->_face2State == 0) + _face2UIFrame += 252; + else if (_vm->_face2State == 2) + _face2UIFrame = 0; + + if (!_vm->_party._clairvoyanceActive) { + _face1UIFrame = 0; + _face2UIFrame = 8; + } + + _borderSprites.draw(screen, _face1UIFrame, Common::Point(0, 32)); + _borderSprites.draw(screen, + screen._windows[10]._enabled || screen._windows[2]._enabled ? + 52 : _face2UIFrame, + Common::Point(215, 32)); + + // Draw resistence indicators + if (!screen._windows[10]._enabled && !screen._windows[2]._enabled + && screen._windows[38]._enabled) { + _fecpSprites.draw(screen, _vm->_party._fireResistence ? 1 : 0, + Common::Point(2, 2)); + _fecpSprites.draw(screen, _vm->_party._electricityResistence ? 3 : 2, + Common::Point(219, 2)); + _fecpSprites.draw(screen, _vm->_party._coldResistence ? 5 : 4, + Common::Point(2, 134)); + _fecpSprites.draw(screen, _vm->_party._poisonResistence ? 7 : 6, + Common::Point(219, 134)); + } else { + _fecpSprites.draw(screen, _vm->_party._fireResistence ? 9 : 8, + Common::Point(8, 8)); + _fecpSprites.draw(screen, _vm->_party._electricityResistence ? 10 : 11, + Common::Point(219, 8)); + _fecpSprites.draw(screen, _vm->_party._coldResistence ? 12 : 13, + Common::Point(8, 134)); + _fecpSprites.draw(screen, _vm->_party._poisonResistence ? 14 : 15, + Common::Point(219, 134)); + } + + // Draw UI element for blessed + _blessSprites.draw(screen, 16, Common::Point(33, 137)); + if (_vm->_party._blessedActive) { + _blessedUIFrame = (_blessedUIFrame + 1) % 4; + _blessSprites.draw(screen, _blessedUIFrame, Common::Point(33, 137)); + } + + // Draw UI element for power shield + if (_vm->_party._powerShieldActive) { + _powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4; + _blessSprites.draw(screen, _powerShieldUIFrame + 4, + Common::Point(55, 137)); + } + + // Draw UI element for holy bonus + if (_vm->_party._holyBonusActive) { + _holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4; + _blessSprites.draw(screen, _holyBonusUIFrame + 8, Common::Point(160, 137)); + } + + // Draw UI element for heroism + if (_vm->_party._heroismActive) { + _heroismUIFrame = (_heroismUIFrame + 1) % 4; + _blessSprites.draw(screen, _heroismUIFrame + 12, Common::Point(182, 137)); + } + + // Draw direction character if direction sense is active + if (_vm->_party.checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) { + const char *dirText = DIRECTION_TEXT[_vm->_party._mazeDirection]; + Common::String msg = Common::String::format( + "\002""08\003""c\013""139\011""116%c\014""d\001", *dirText); + screen._windows[0].writeString(msg); + } + + // Draw view frame + if (screen._windows[12]._enabled) + screen._windows[12].frame(); +} + +} // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h new file mode 100644 index 0000000000..565fe84273 --- /dev/null +++ b/engines/xeen/interface.h @@ -0,0 +1,73 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef XEEN_INTERFACE_H +#define XEEN_INTERFACE_H + +#include "common/scummsys.h" +#include "xeen/dialogs.h" +#include "xeen/party.h" + +namespace Xeen { + +class XeenEngine; + +class Interface: public ButtonContainer { +private: + XeenEngine *_vm; + SpriteResource _dseFace; + SpriteResource _globalSprites; + SpriteResource _borderSprites; + SpriteResource _spellFxSprites; + SpriteResource _fecpSprites; + SpriteResource _blessSprites; + SpriteResource _charFaces[TOTAL_CHARACTERS]; + SpriteResource *_partyFaces[MAX_ACTIVE_PARTY]; + + int _batUIFrame; + int _spotDoorsUIFrame; + int _dangerSenseUIFrame; + int _face1UIFrame; + int _face2UIFrame; + int _blessedUIFrame; + int _powerShieldUIFrame; + int _holyBonusUIFrame; + int _heroismUIFrame; + bool _isEarlyGame; + bool _buttonsLoaded; + + void loadSprites(); + + void loadCharIcons(int numChars); + + void assembleBorder(); + + void setupBackground(); +public: + Interface(XeenEngine *vm); + + void setup(bool soundPlayed); +}; + +} // End of namespace Xeen + +#endif /* XEEN_INTERFACE_H */ diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 752608a136..7f0caf7b10 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -11,6 +11,7 @@ MODULE_OBJS := \ events.o \ files.o \ font.o \ + interface.o \ items.o \ party.o \ resdata.o \ diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index ec98a5ffe8..1574871c25 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -35,36 +35,26 @@ namespace Xeen { XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) - : Engine(syst), ButtonContainer(), _gameDescription(gameDesc), _randomSource("Xeen") { + : Engine(syst), _gameDescription(gameDesc), _randomSource("Xeen") { _debugger = nullptr; _events = nullptr; + _interface = nullptr; _saves = nullptr; _screen = nullptr; _sound = nullptr; _eventData = nullptr; - Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr); - _isEarlyGame = false; _loadDarkSide = 1; - _buttonsLoaded = false; - _batUIFrame = 0; - _spotDoorsUIFrame = 0; _spotDoorsAllowed = false; - _dangerSenseUIFrame = 0; _dangerSenseAllowed = false; - _face1UIFrame = 0; _face1State = 0; - _face2UIFrame = 0; _face2State = 0; - _blessedUIFrame = 0; - _powerShieldUIFrame = 0; - _holyBonusUIFrame = 0; - _heroismUIFrame = 0; _noDirectionSense = false; } XeenEngine::~XeenEngine() { delete _debugger; delete _events; + delete _interface; delete _saves; delete _screen; delete _sound; @@ -82,6 +72,7 @@ void XeenEngine::initialize() { FileManager::init(this); _debugger = new Debugger(this); _events = new EventsManager(this); + _interface = new Interface(this); _saves = new SavesManager(this, _party, _roster); _screen = new Screen(this); _screen->setupWindows(); @@ -260,192 +251,7 @@ void XeenEngine::showMainMenu() { void XeenEngine::playGame() { _saves->reset(); - setupUI(true); -} - -/* - * Lots of stuff in this method. - * TODO: Consider renaming method when better understood - */ -void XeenEngine::setupUI(bool soundPlayed) { - SpriteResource uiSprites("inn.icn"); - _globalSprites.load("global.icn"); - _borderSprites.load("border.icn"); - _spellFxSprites.load("spellfx.icn"); - _fecpSprites.load("fecp.brd"); - _blessSprites.load("bless.icn"); - - // Get mappings to the active characters in the party - _party._activeParty.resize(_party._partyCount); - for (int i = 0; i < _party._partyCount; ++i) { - _party._activeParty[i] = &_roster[_party._partyMembers[i]]; - } - - _isEarlyGame = _party._minutes >= 300; - - if (_party._mazeId == 0) { - if (!soundPlayed) { - warning("TODO: loadSound?"); - } - - if (!_partyFaces[0]) { - // Xeen only uses 24 of possible 30 character slots - loadCharIcons(XEEN_TOTAL_CHARACTERS); - - for (int i = 0; i < _party._partyCount; ++i) - _partyFaces[i] = &_charFaces[_party._partyMembers[i]]; - } - - _mode = MODE_1; - Common::Array xeenSideChars; - - // Build up a list of characters on the same Xeen side being loaded - for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) { - PlayerStruct &player = _roster[i]; - if (player._name.empty() || player._xeenSide != _loadDarkSide) - continue; - - xeenSideChars.push_back(i); - } - - // Add in buttons for the UI - _buttonsLoaded = true; - addButton(Common::Rect(16, 100, 40, 120), 242, &uiSprites, true); - addButton(Common::Rect(52, 100, 76, 120), 243, &uiSprites, true); - addButton(Common::Rect(87, 100, 111, 120), 68, &uiSprites, true); - addButton(Common::Rect(122, 100, 146, 120), 82, &uiSprites, true); - addButton(Common::Rect(157, 100, 181, 120), 67, &uiSprites, true); - addButton(Common::Rect(192, 100, 216, 120), 88, &uiSprites, true); - addButton(Common::Rect(), 27, &uiSprites, false); - addButton(Common::Rect(16, 16, 48, 48), 49, &uiSprites, false); - addButton(Common::Rect(117, 16, 139, 48), 50, &uiSprites, false); - addButton(Common::Rect(16, 59, 48, 81), 51, &uiSprites, false); - addButton(Common::Rect(117, 59, 149, 81), 52, &uiSprites, false); - - setupGameBackground(); - } -} - -void XeenEngine::loadCharIcons(int numChars) { - for (int i = 0; i < numChars; ++i) { - // Load new character resource - Common::String name = Common::String::format("char%02d.fac", i); - _charFaces[i].load(name); - } - - _dseFace.load("dse.fac"); -} - -void XeenEngine::setupGameBackground() { - _screen->loadBackground("back.raw"); - assembleGameBorder(); -} - -void XeenEngine::assembleGameBorder() { - Window &gameWindow = _screen->_windows[28]; - - // Draw the outer frame - _globalSprites.draw(gameWindow, 0); - - // Draw the animating bat character used to show when levitate is active - _borderSprites.draw(*_screen, _party._levitateActive ? _batUIFrame + 16 : 16); - _batUIFrame = (_batUIFrame + 1) % 12; - - // Draw UI element to indicate whether can spot hidden doors - _borderSprites.draw(*_screen, - (_spotDoorsAllowed && _party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28, - Common::Point(194, 91)); - _spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12; - - // Draw UI element to indicate whether can sense danger - _borderSprites.draw(*_screen, - (_dangerSenseAllowed && _party.checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40, - Common::Point(107, 9)); - _dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12; - - // Handle the face UI elements for indicating clairvoyance status - _face1UIFrame = (_face1UIFrame + 1) % 4; - if (_face1State == 0) - _face1UIFrame += 4; - else if (_face1State == 2) - _face1UIFrame = 0; - - _face2UIFrame = (_face2UIFrame + 1) % 4 + 12; - if (_face2State == 0) - _face2UIFrame += 252; - else if (_face2State == 2) - _face2UIFrame = 0; - - if (!_party._clairvoyanceActive) { - _face1UIFrame = 0; - _face2UIFrame = 8; - } - - _borderSprites.draw(*_screen, _face1UIFrame, Common::Point(0, 32)); - _borderSprites.draw(*_screen, - _screen->_windows[10]._enabled || _screen->_windows[2]._enabled ? - 52 : _face2UIFrame, - Common::Point(215, 32)); - - // Draw resistence indicators - if (!_screen->_windows[10]._enabled && !_screen->_windows[2]._enabled - && _screen->_windows[38]._enabled) { - _fecpSprites.draw(*_screen, _party._fireResistence ? 1 : 0, - Common::Point(2, 2)); - _fecpSprites.draw(*_screen, _party._electricityResistence ? 3 : 2, - Common::Point(219, 2)); - _fecpSprites.draw(*_screen, _party._coldResistence ? 5 : 4, - Common::Point(2, 134)); - _fecpSprites.draw(*_screen, _party._poisonResistence ? 7 : 6, - Common::Point(219, 134)); - } else { - _fecpSprites.draw(*_screen, _party._fireResistence ? 9 : 8, - Common::Point(8, 8)); - _fecpSprites.draw(*_screen, _party._electricityResistence ? 10 : 11, - Common::Point(219, 8)); - _fecpSprites.draw(*_screen, _party._coldResistence ? 12 : 13, - Common::Point(8, 134)); - _fecpSprites.draw(*_screen, _party._poisonResistence ? 14 : 15, - Common::Point(219, 134)); - } - - // Draw UI element for blessed - _blessSprites.draw(*_screen, 16, Common::Point(33, 137)); - if (_party._blessedActive) { - _blessedUIFrame = (_blessedUIFrame + 1) % 4; - _blessSprites.draw(*_screen, _blessedUIFrame, Common::Point(33, 137)); - } - - // Draw UI element for power shield - if (_party._powerShieldActive) { - _powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4; - _blessSprites.draw(*_screen, _powerShieldUIFrame + 4, - Common::Point(55, 137)); - } - - // Draw UI element for holy bonus - if (_party._holyBonusActive) { - _holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4; - _blessSprites.draw(*_screen, _holyBonusUIFrame + 8, Common::Point(160, 137)); - } - - // Draw UI element for heroism - if (_party._heroismActive) { - _heroismUIFrame = (_heroismUIFrame + 1) % 4; - _blessSprites.draw(*_screen, _heroismUIFrame + 12, Common::Point(182, 137)); - } - - // Draw direction character if direction sense is active - if (_party.checkSkill(DIRECTION_SENSE) && !_noDirectionSense) { - const char *dirText = DIRECTION_TEXT[_party._mazeDirection]; - Common::String msg = Common::String::format( - "\002""08\003""c\013""139\011""116%c\014""d\001", *dirText); - _screen->_windows[0].writeString(msg); - } - - // Draw view frame - if (_screen->_windows[12]._enabled) - _screen->_windows[12].frame(); + _interface->setup(true); } } // End of namespace Xeen diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index c175048389..a549c15df4 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -34,6 +34,7 @@ #include "xeen/debugger.h" #include "xeen/dialogs.h" #include "xeen/events.h" +#include "xeen/interface.h" #include "xeen/party.h" #include "xeen/saves.h" #include "xeen/screen.h" @@ -77,48 +78,15 @@ struct XeenGameDescription; #define XEEN_SAVEGAME_VERSION 1 #define GAME_FRAME_TIME 50 -class XeenEngine : public Engine, public ButtonContainer { +class XeenEngine : public Engine { private: const XeenGameDescription *_gameDescription; Common::RandomSource _randomSource; int _loadSaveSlot; - bool _isEarlyGame; - int _loadDarkSide; - SpriteResource _charFaces[TOTAL_CHARACTERS]; - SpriteResource *_partyFaces[MAX_ACTIVE_PARTY]; - SpriteResource _dseFace; - SpriteResource _globalSprites; - SpriteResource _borderSprites; - SpriteResource _spellFxSprites; - SpriteResource _fecpSprites; - SpriteResource _blessSprites; - bool _buttonsLoaded; - int _batUIFrame; - int _spotDoorsUIFrame; - bool _spotDoorsAllowed; - int _dangerSenseUIFrame; - bool _dangerSenseAllowed; - int _face1UIFrame; - bool _face1State; - int _face2UIFrame; - bool _face2State; - int _blessedUIFrame; - int _powerShieldUIFrame; - int _holyBonusUIFrame; - int _heroismUIFrame; - bool _noDirectionSense; void showIntro(); void showMainMenu(); - - void setupUI(bool soundPlayed); - - void loadCharIcons(int numChars); - - void setupGameBackground(); - - void assembleGameBorder(); protected: /** * Play the game @@ -144,6 +112,7 @@ private: public: Debugger *_debugger; EventsManager *_events; + Interface *_interface; SavesManager *_saves; Screen *_screen; SoundManager *_sound; @@ -152,6 +121,12 @@ public: Common::SeekableReadStream *_eventData; Roster _roster; Party _party; + int _loadDarkSide; + bool _spotDoorsAllowed; + bool _dangerSenseAllowed; + int _face1State; + int _face2State; + bool _noDirectionSense; public: XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); virtual ~XeenEngine(); -- cgit v1.2.3