MM: MM1: Implementing animated location display

This commit is contained in:
Paul Gilbert 2023-02-26 11:45:38 -08:00
parent f1ba389a87
commit 6a15e3bb1e
9 changed files with 115 additions and 11 deletions

View File

@ -45,13 +45,11 @@ namespace ViewsEnh {
struct Dialogs {
private:
// Unenhanced views
Views::Characters _characters;
Views::CreateCharacters _createCharacters;
Views::Locations::Inn _inn;
Views::Protect _protect;
Views::Title _title;
// Views::ViewCharacter _viewCharacter;
ViewsEnh::Locations::Market _market;
ViewsEnh::Locations::Temple _temple;
ViewsEnh::Spells::CastSpell _castSpell;

View File

@ -53,10 +53,8 @@ bool Game::msgUnfocus(const UnfocusMessage &msg) {
}
void Game::draw() {
if (_needsRedraw) {
Graphics::ManagedSurface s = getSurface();
s.blitFrom(_bg);
}
Graphics::ManagedSurface s = getSurface();
s.blitFrom(_bg);
UIElement::draw();
}

View File

@ -51,7 +51,7 @@ public:
bool msgGame(const GameMessage &msg) override;
};
} // namespace Views
} // namespace ViewsEnh
} // namespace MM1
} // namespace MM

View File

@ -25,12 +25,76 @@ namespace MM {
namespace MM1 {
namespace ViewsEnh {
void GameView::draw() {
Views::GameView::draw();
}
#define TICKS_PER_FRAME 4
struct LocationEntry {
const char *const _prefix;
uint _count;
};
static const LocationEntry LOCATIONS[3] = {
{ "", 0 },
{ "", 0 },
{ "tmpl", 4 }
};
bool GameView::msgGame(const GameMessage &msg) {
return Views::GameView::msgGame(msg);
if (msg._name == "LOCATION") {
showLocation(msg._value);
} else if (msg._name == "LOCATION_DRAW") {
UIElement *view = g_events->findView("Game");
view->draw();
} else {
return Views::GameView::msgGame(msg);
}
return true;
}
void GameView::showLocation(int locationId) {
if (locationId == -1) {
_backgrounds.clear();
_frameCount = 0;
_locationId = -1;
} else {
assert(LOCATIONS[locationId]._prefix);
_locationId = locationId;
_frameIndex = _timerCtr = 0;
_frameCount = LOCATIONS[locationId]._count * 8;
_backgrounds.resize(LOCATIONS[locationId]._count);
for (uint i = 0; i < _backgrounds.size(); ++i) {
Common::String name = Common::String::format("%s%d.twn",
LOCATIONS[locationId]._prefix, i + 1);
_backgrounds[i].load(name);
}
}
}
void GameView::draw() {
if (_locationId == -1) {
Views::GameView::draw();
} else {
Graphics::ManagedSurface s = getSurface();
_backgrounds[_frameIndex / 8].draw(&s, _frameIndex % 8,
Common::Point(0, 0));
}
}
bool GameView::tick() {
if (_locationId != -1) {
if (++_timerCtr >= TICKS_PER_FRAME) {
_timerCtr = 0;
_frameIndex = (_frameIndex + 1) % _frameCount;
}
redraw();
}
return true;
}
} // namespace ViewsEnh

View File

@ -23,18 +23,32 @@
#define MM1_VIEWS_ENH_GAME_VIEW_H
#include "mm/mm1/views/game_view.h"
#include "mm/shared/xeen/sprites.h"
namespace MM {
namespace MM1 {
namespace ViewsEnh {
class GameView : public Views::GameView {
private:
int _locationId = -1;
Common::Array<Shared::Xeen::SpriteResource> _backgrounds;
uint _frameIndex = 0, _frameCount = 0;
uint _timerCtr = 0;
/**
* Start location animation
*/
void showLocation(int locationId);
public:
GameView(UIElement *owner) : Views::GameView(owner) {}
virtual ~GameView() {}
void draw() override;
bool msgGame(const GameMessage &msg) override;
bool tick() override;
void update();
};
} // namespace ViewsEnh

View File

@ -66,6 +66,19 @@ void Location::backpackFull() {
displayMessage(STRING["dialogs.misc.backpack_full"]);
}
void Location::draw() {
send("View", GameMessage("LOCATION_DRAW"));
PartyView::draw();
}
bool Location::tick() {
// Locations have animated game backgrounds, so pass on tick
// to the game view to let it update
g_events->findView("View")->tick();
redraw();
return true;
}
} // namespace Locations
} // namespace ViewsEnh
} // namespace MM1

View File

@ -69,6 +69,16 @@ public:
* Leave the location, turning around
*/
void leave();
/**
* Draw the location
*/
void draw();
/**
* Tick handler
*/
bool tick();
};
} // namespace Locations

View File

@ -42,6 +42,12 @@ bool Temple::msgFocus(const FocusMessage &msg) {
return true;
}
bool Temple::msgUnfocus(const UnfocusMessage &msg) {
send("View", GameMessage("LOCATION", -1));
(void)Location::msgUnfocus(msg);
return true;
}
void Temple::draw() {
Location::draw();

View File

@ -47,6 +47,7 @@ public:
Temple();
bool msgFocus(const FocusMessage &msg) override;
bool msgUnfocus(const UnfocusMessage &msg) override;
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;