PINK: basic walk, left click and seqTimer implementation

This commit is contained in:
whiterandrek 2018-04-05 08:15:14 +03:00 committed by Eugene Sandulenko
parent 4b7c75607a
commit cad72b1532
36 changed files with 681 additions and 87 deletions

View File

@ -68,7 +68,7 @@ void CursorMgr::setCursor(Common::String &cursorName, Common::Point point) {
else if (cursorName == "ExitRight"){
index = kExitRightCursor;
}
else if (cursorName == "ExitForward")
else if (cursorName == "ExitForward" || cursorName == "ExitUp")
index = kExitForwardCursor;
else assert(0);
setCursor(index, point);

View File

@ -42,10 +42,11 @@ void Director::draw() {
void Director::drawSprite(ActionCEL *sprite) {
CelDecoder *decoder = sprite->getDecoder();
const Graphics::Surface *surface;
if (decoder->needsUpdate())
surface = decoder->decodeNextFrame();
else surface = decoder->getCurrentFrame();
if (decoder->needsUpdate()) {
surface = decoder->decodeNextFrame();
}
else surface = decoder->getCurrentFrame();
if (!showBounds) {
Graphics::Surface *screen = _system->lockScreen();
@ -116,7 +117,7 @@ void Director::clear() {
}
Actor *Director::getActorByPoint(Common::Point point) {
for (int i = _sprites.size() - 1; i > 0; --i) {
for (int i = _sprites.size() - 1; i >= 0; --i) {
CelDecoder *decoder = _sprites[i]->getDecoder();
const Graphics::Surface *frame = decoder->getCurrentFrame();
Common::Rect &rect = decoder->getRectangle();

View File

@ -42,6 +42,7 @@ MODULE_OBJS = \
objects/sequences/sequencer.o \
objects/walk/walk_mgr.o \
objects/walk/walk_location.o \
objects/walk/walk_shortest_path.o \
# This module can be built as a plugin
ifeq ($(ENABLE_PINK), DYNAMIC_PLUGIN)

View File

@ -48,6 +48,8 @@ void ActionStill::onStart() {
for (int i = 0; i < _startFrame; ++i) {
_decoder->decodeNextFrame();
}
_decoder->stop();
_actor->endAction();
}
} // End of namespace Pink

View File

@ -22,6 +22,7 @@
#include "walk_action.h"
#include <engines/pink/archive.h>
#include "pink/cel_decoder.h"
namespace Pink {
@ -36,4 +37,8 @@ void WalkAction::toConsole() {
_name.c_str(), _fileName.c_str(), _toCalcFramePositions);
}
void WalkAction::onStart() {
_decoder->start();
}
} // End of namespace Pink

View File

@ -33,6 +33,9 @@ public:
virtual void toConsole();
protected:
void onStart() override;
private:
bool _toCalcFramePositions;
};

View File

@ -71,16 +71,20 @@ LeadActor::State LeadActor::getState() const {
void LeadActor::update() {
switch (_state) {
case kReady:
_sequencer->update();
//fall-through intended
_cursorMgr->update();
break;
case kMoving:
_walkMgr->update();
_cursorMgr->update();
break;
case kInDialog1:
case kInDialog2:
_sequencer->update();
if (!_sequencer->_context){
_state = _nextState;
_nextState = kUnk_Loading;
}
break;
case kInventory:
@ -136,7 +140,8 @@ void LeadActor::onKeyboardButtonClick(Common::KeyCode code) {
void LeadActor::start(bool isHandler) {
if (isHandler && _state != kPlayingVideo){
_state = kReady;
_state = kInDialog1;
_nextState = kReady;
}
updateCursor({0,0});
}
@ -177,17 +182,19 @@ void LeadActor::onLeftButtonClick(Common::Point point) {
case kReady:
case kMoving: {
Actor *actor = _page->getGame()->getDirector()->getActorByPoint(point);
if (this == actor){
// inventory is not implemented
return;
}
_recipient = (SupportingActor*) actor;
if (actor->isClickable() &&
((SupportingActor*) actor)->isLeftClickHandlers())
_recipient->isLeftClickHandlers()){
_state = kMoving;
_nextState = kInDialog1;
_walkMgr->start(_walkMgr->findLocation(_recipient->getLocation()));
}
break;
}
case kPDA:
@ -207,6 +214,27 @@ void LeadActor::onMouseOver(Common::Point point, CursorMgr *mgr) {
else Actor::onMouseOver(point, mgr);
}
void LeadActor::onWalkEnd() {
State oldNextState = _nextState;
_state = kReady;
_nextState = kUnk_Loading;
if (_recipient && oldNextState == kInDialog1){
// if use click not impl
sendLeftClickMessage(_recipient);
}
}
bool LeadActor::sendUseClickMessage(SupportingActor *actor) {
return false;
}
bool LeadActor::sendLeftClickMessage(SupportingActor *actor) {
actor->onLeftClickMessage();
_nextState = _state != kPlayingVideo ? kReady : kPlayingVideo;
_state = kInDialog1;
return false;
}
void ParlSqPink::toConsole() {
debug("ParlSqPink: _name = %s", _name.c_str());
for (int i = 0; i < _actions.size(); ++i) {

View File

@ -27,12 +27,15 @@
#include <common/rect.h>
#include "actor.h"
namespace Pink {
class CursorMgr;
class WalkMgr;
class Sequencer;
class SupportingActor;
class LeadActor : public Actor {
public:
enum State {
@ -62,14 +65,22 @@ public:
void onKeyboardButtonClick(Common::KeyCode code);
void onLeftButtonClick(Common::Point point);
void onMouseMove(Common::Point point);
void onWalkEnd();
virtual void onMouseOver(Common::Point point, CursorMgr *mgr);
private:
void updateCursor(Common::Point point);
bool sendUseClickMessage(SupportingActor *actor);
bool sendLeftClickMessage(SupportingActor *actor);
State _state;
State _nextState;
SupportingActor *_recipient;
CursorMgr *_cursorMgr;
WalkMgr *_walkMgr;
Sequencer *_sequencer;

View File

@ -57,4 +57,20 @@ bool SupportingActor::isLeftClickHandlers() {
return _handlerMgr.isLeftClickHandler(this);
}
void SupportingActor::onTimerMessage() {
_handlerMgr.onTimerMessage(this);
}
bool SupportingActor::onLeftClickMessage() {
return _handlerMgr.onLeftClickMessage(this);
}
bool SupportingActor::onUseClickMessage() {
return _handlerMgr.onUseClickMessage(this);
}
const Common::String &SupportingActor::getLocation() const {
return _location;
}
} // End of namespace Pink

View File

@ -38,6 +38,13 @@ public:
virtual bool isClickable() { return 1; }
bool isLeftClickHandlers();
void onTimerMessage();
bool onLeftClickMessage();
bool onUseClickMessage();
const Common::String &getLocation() const;
private:
HandlerMgr _handlerMgr;
Common::String _location;

View File

@ -46,13 +46,13 @@ bool Handler::isSuitable(Actor *actor) {
return true;
}
void Handler::executeSideEffects(LeadActor *actor) {
void Handler::executeSideEffects(Actor *actor) {
for (int i = 0; i < _sideEffects.size(); ++i) {
_sideEffects[i]->execute(actor);
}
}
void Handler::onMessage(LeadActor *actor) {
void Handler::handle(Actor *actor) {
executeSideEffects(actor);
}
@ -70,8 +70,8 @@ void HandlerSequences::deserialize(Archive &archive) {
archive >> _sequences;
}
void HandlerSequences::onMessage(LeadActor *actor) {
Handler::onMessage(actor);
void HandlerSequences::handle(Actor *actor) {
Handler::handle(actor);
Sequencer *sequencer = actor->getSequencer();
assert(!_sequences.empty());
@ -84,10 +84,10 @@ void HandlerSequences::onMessage(LeadActor *actor) {
assert(sequence);
sequencer->authorSequence(sequence, 0);
handle(sequence);
execute(sequence);
}
void HandlerStartPage::handle(Sequence *sequence) {
void HandlerStartPage::execute(Sequence *sequence) {
sequence->_unk = 1;
}
@ -152,7 +152,7 @@ void HandlerUseClick::toConsole() {
}
}
void HandlerUseClick::handle(Sequence *sequence) {
void HandlerUseClick::execute(Sequence *sequence) {
}

View File

@ -39,11 +39,11 @@ class Handler : public Object {
public:
~Handler();
virtual void deserialize(Archive &archive);
virtual void onMessage(LeadActor *actor);
virtual void handle(Actor *actor);
bool isSuitable(Actor *actor);
protected:
void executeSideEffects(LeadActor *actor);
void executeSideEffects(Actor *actor);
Common::Array<Condition*> _conditions;
Common::Array<SideEffect*> _sideEffects;
@ -54,10 +54,10 @@ class Sequence;
class HandlerSequences : public Handler {
public:
virtual void deserialize(Archive &archive);
virtual void onMessage(LeadActor *actor);
virtual void handle(Actor *actor);
protected:
virtual void handle(Sequence *sequence) = 0;
virtual void execute(Sequence *sequence) = 0;
Common::StringArray _sequences;
};
@ -67,7 +67,7 @@ public:
virtual void toConsole();
private:
virtual void handle(Sequence *sequence);
virtual void execute(Sequence *sequence);
};
class HandlerLeftClick : public HandlerSequences {
@ -75,7 +75,7 @@ public:
virtual void toConsole();
private:
virtual void handle(Sequence *sequence) {}
virtual void execute(Sequence *sequence) {}
};
class HandlerUseClick : public HandlerSequences {
@ -84,7 +84,7 @@ public:
virtual void toConsole();
private:
virtual void handle(Sequence *sequence);
virtual void execute(Sequence *sequence);
Common::String _inventoryItem;
Common::String _recepient;

View File

@ -36,4 +36,55 @@ bool HandlerMgr::isLeftClickHandler(Actor *actor) {
return false;
}
void HandlerMgr::onTimerMessage(Actor *actor) {
Handler *handler = findSuitableHandlerTimer(actor);
if (handler)
handler->handle(actor);
}
bool HandlerMgr::onLeftClickMessage(Actor *actor) {
Handler *handler = findSuitableHandlerLeftClick(actor);
if (handler) {
handler->handle(actor);
return 1;
}
return 0;
}
bool HandlerMgr::onUseClickMessage(Actor *actor) {
Handler *handler = findSuitableHandlerUseClick(actor);
if (handler) {
handler->handle(actor);
return 1;
}
return 0;
}
Handler *HandlerMgr::findSuitableHandlerTimer(Actor *actor) {
for (int i = 0; i < _timerHandlers.size(); ++i) {
if (_timerHandlers[i]->isSuitable(actor))
return _timerHandlers[i];
}
return nullptr;
}
Handler *HandlerMgr::findSuitableHandlerLeftClick(Actor *actor) {
for (int i = 0; i < _leftClickHandlers.size(); ++i) {
if (_leftClickHandlers[i]->isSuitable(actor))
return _leftClickHandlers[i];
}
return nullptr;
}
Handler *HandlerMgr::findSuitableHandlerUseClick(Actor *actor) {
for (int i = 0; i < _useClickHandlers.size(); ++i) {
if (_useClickHandlers[i]->isSuitable(actor))
return _useClickHandlers[i];
}
return nullptr;
}
}

View File

@ -28,6 +28,7 @@
namespace Pink {
class Handler;
class HandlerLeftClick;
class HandlerUseClick;
class HandlerTimer;
@ -41,7 +42,15 @@ public:
bool isLeftClickHandler(Actor *actor);
void onTimerMessage(Actor *actor);
bool onLeftClickMessage(Actor *actor);
bool onUseClickMessage(Actor *actor);
private:
Handler *findSuitableHandlerTimer(Actor *actor);
Handler *findSuitableHandlerLeftClick(Actor *actor);
Handler *findSuitableHandlerUseClick(Actor *actor);
Common::Array<HandlerLeftClick*> _leftClickHandlers;
Common::Array<HandlerUseClick*> _useClickHandlers;
Common::Array<HandlerTimer*> _timerHandlers;

View File

@ -59,8 +59,8 @@ void HandlerTimerActions::toConsole() {
}
}
void HandlerTimerActions::onMessage(LeadActor *actor) {
Handler::onMessage(actor);
void HandlerTimerActions::handle(Actor *actor) {
Handler::handle(actor);
assert(_actions.size());
if (!actor->isPlaying()){
Common::RandomSource &rnd = actor->getPage()->getGame()->getRnd();
@ -72,7 +72,7 @@ void HandlerTimerActions::onMessage(LeadActor *actor) {
}
void HandlerTimerSequences::handle(Sequence *sequence) {
void HandlerTimerSequences::execute(Sequence *sequence) {
debug("HandlerTimerSequences function is not implemented");
}

View File

@ -42,7 +42,7 @@ class HandlerTimerActions : public HandlerTimer {
public:
virtual void toConsole();
virtual void deserialize(Archive &archive);
virtual void onMessage(LeadActor *actor);
virtual void handle(Actor *actor);
private:
Common::StringArray _actions;
@ -53,7 +53,7 @@ class HandlerTimerSequences : public HandlerSequences { //originally it was inhe
public:
virtual void toConsole();
protected:
virtual void handle(Sequence *sequence); // very big and hard function
virtual void execute(Sequence *sequence); // very big and hard function
};
} // End of namespace Pink

View File

@ -65,7 +65,9 @@ void Module::changePage(const Common::String &pageName) {
//_page->clear
page->init(kLoadingNewGame);
_page = page;
_page->init(kLoadingNewGame);
}
GamePage *Module::findPage(const Common::String &pageName) const {

View File

@ -83,7 +83,7 @@ void GamePage::init(bool isLoadingSave) {
bool GamePage::initHandler() {
for (uint i = 0; i < _handlers.size(); ++i) {
if (_handlers[i]->isSuitable(_leadActor)){
_handlers[i]->onMessage(_leadActor);
_handlers[i]->handle(_leadActor);
return true;
}
}

View File

@ -71,4 +71,8 @@ Page::~Page() {
}
}
LeadActor *Page::getLeadActor() {
return _leadActor;
}
} // End of namespace Pink

View File

@ -39,11 +39,13 @@ public:
~Page();
void load(Archive &archive);
Actor *findActor(Common::String &name);
Sound* loadSound(Common::String &fileName);
Sound *loadSound(Common::String &fileName);
CelDecoder *loadCel(Common::String &fileName);
virtual void toConsole();
LeadActor *getLeadActor();
protected:
void init();
Common::Array<Actor*> _actors;

View File

@ -24,11 +24,14 @@
#include <engines/pink/archive.h>
#include "./sequencer.h"
#include <common/debug.h>
#include <engines/pink/objects/actors/supporting_actor.h>
#include "pink/objects/pages/game_page.h"
#include "pink/pink.h"
namespace Pink {
SeqTimer::SeqTimer()
: _unk(0) {
: _updatesToMessage(0) {
}
@ -43,4 +46,21 @@ void SeqTimer::toConsole() {
debug("\tSeqTimer: _actor=%s _period=%u _range=%u", _actor.c_str(), _period, _range);
}
void SeqTimer::update() {
Common::RandomSource &random =_sequencer->_page->getGame()->getRnd();
if (_updatesToMessage--)
return;
calculateUpdatesCount();
SupportingActor *actor = static_cast<SupportingActor*>(_sequencer->_page->findActor(_actor));
if (!_sequencer->findSequenceActorState(actor->getName())){
actor->onTimerMessage();
}
}
void SeqTimer::calculateUpdatesCount() {
Common::RandomSource &random =_sequencer->_page->getGame()->getRnd();
_updatesToMessage = _range ? _period + random.getRandomNumber(_range) : _period;
}
} // End of namespace Pink

View File

@ -35,12 +35,16 @@ public:
virtual void deserialize(Archive &archive);
virtual void toConsole();
virtual void update();
private:
void calculateUpdatesCount();
Common::String _actor;
Sequencer *_sequencer;
int _period;
int _range;
int _unk;
Sequencer *_sequencer;
int _updatesToMessage;
};
} // End of namespace Pink

View File

@ -119,7 +119,7 @@ void Sequence::restart() {
void Sequence::skipToLastSubSequence() {
if (_unk && _context->getNextItemIndex() < _items.size()){
int i = _items.size() - 1;
while(i >= 0 && !_items[i--]->isLeader());
while(i >= 0 && !_items[--i]->isLeader());
assert(i >= 0);
_context->setNextItemIndex(i);
_context->clearActionsFromActorStates();

View File

@ -58,14 +58,10 @@ bool SequenceItem::execute(int index, Sequence *sequence, bool unk2) {
}
actor->setAction(action, unk2);
Common::Array<SequenceActorState> &states = sequence->_context->_states;
for (int i = 0; i < sequence->_context->_states.size(); ++i) {
if (states[i]._actorName == _actor){
states[i]._index = index;
sequence->_context->_actor = isLeader() ? actor : sequence->_context->_actor;
break;
}
}
SequenceActorState *state = sequence->_sequencer->findSequenceActorState(_actor);
state->_index = index;
sequence->_context->_actor = isLeader() ? actor : sequence->_context->_actor;
return true;
}
@ -97,13 +93,8 @@ uint32 SequenceItemLeaderAudio::getSample() {
}
bool SequenceItemDefaultAction::execute(int index, Sequence *sequence, bool unk2) {
Common::Array<SequenceActorState> &actorStates = sequence->_context->_states;
for (int i = 0; i < actorStates.size(); ++i) {
if (actorStates[i]._actorName == _actor){
actorStates[i]._actionName = _action;
break;
}
}
SequenceActorState *state = sequence->_sequencer->findSequenceActorState(_actor);
state->_actionName = _action;
return true;
}

View File

@ -27,11 +27,14 @@
#include "sequence_context.h"
#include "pink/objects/actors/actor.h"
#include "engines/pink/archive.h"
#include "pink/objects/pages/game_page.h"
#include "pink/pink.h"
#include "pink/objects/sequences/seq_timer.h"
namespace Pink {
Sequencer::Sequencer(GamePage *page)
: _context(nullptr), _page(page)
: _context(nullptr), _page(page), _time(0)
{}
Sequencer::~Sequencer() {
@ -70,11 +73,15 @@ void Sequencer::toConsole() {
for (int i = 0; i < _sequences.size(); ++i) {
_sequences[i]->toConsole();
}
for (int i = 0; i < _timers.size(); ++i) {
_timers[i]->toConsole();
}
}
void Sequencer::update() {
if (_context)
_context->_sequence->update();
updateTimers();
}
void Sequencer::removeContext(SequenceContext *context) {
@ -95,4 +102,28 @@ void Sequencer::skipToLastSubSequence() {
_context->getSequence()->skipToLastSubSequence();
}
void Sequencer::updateTimers() {
uint time = _page->getGame()->getTotalPlayTime();
if (time - _time <= 0x64) {
return;
}
_time = time;
for (int i = 0; i < _timers.size(); ++i) {
_timers[i]->update();
}
}
SequenceActorState *Sequencer::findSequenceActorState(const Common::String &name) {
if (!_context)
return nullptr;
for (int i = 0; i < _context->_states.size(); ++i) {
if (_context->_states[i].getActor() == name)
return &_context->_states[i];
}
return nullptr;
}
} // End of namespace Pink

View File

@ -33,6 +33,7 @@ class Sequence;
class SequenceContext;
class GamePage;
class SeqTimer;
class SequenceActorState;
class Sequencer : public Object {
public:
@ -43,6 +44,8 @@ public:
virtual void deserialize(Archive &archive);
Sequence* findSequence(const Common::String &name);
SequenceActorState *findSequenceActorState(const Common::String &name);
void authorSequence(Sequence *sequence, bool unk);
void removeContext(SequenceContext *context);
@ -54,13 +57,15 @@ public:
void skipToLastSubSequence();
public:
void updateTimers();
SequenceContext *_context;
// context array
Common::Array<Sequence*> _sequences;
Common::String _currentSequenceName;
Common::Array<SeqTimer*> _timers;
GamePage *_page;
int unk;
uint _time;
};
} // End of namespace Pink

View File

@ -36,8 +36,8 @@ void SideEffectExit::deserialize(Archive &archive) {
archive >> _nextModule >> _nextPage;
}
void SideEffectExit::execute(LeadActor *actor) {
actor->setNextExecutors(_nextModule, _nextPage);
void SideEffectExit::execute(Actor *actor) {
actor->getPage()->getLeadActor()->setNextExecutors(_nextModule, _nextPage);
}
void SideEffectExit::toConsole() {
@ -48,10 +48,11 @@ void SideEffectLocation::deserialize(Archive &archive) {
archive >> _location;
}
void SideEffectLocation::execute(LeadActor *actor) {
void SideEffectLocation::execute(Actor *actor) {
WalkMgr *mgr = actor->getPage()->getWalkMgr();
WalkLocation *location = mgr->findLocation(_location);
//TODO end this method
assert(location);
mgr->setCurrentWayPoint(location);
}
void SideEffectLocation::toConsole() {
@ -62,8 +63,10 @@ void SideEffectInventoryItemOwner::deserialize(Archive &archive) {
archive >> _item >> _owner;
}
void SideEffectInventoryItemOwner::execute(LeadActor *actor) {
//TODO
void SideEffectInventoryItemOwner::execute(Actor *actor) {
InventoryMgr *mgr = actor->getPage()->getModule()->getInventoryMgr();
InventoryItem *item = mgr->findInventoryItem(_item);
mgr->setItemOwner(_item, item);
}
void SideEffectInventoryItemOwner::toConsole() {
@ -74,7 +77,7 @@ void SideEffectVariable::deserialize(Pink::Archive &archive) {
archive >> _name >> _value;
}
void SideEffectGameVariable::execute(LeadActor *actor) {
void SideEffectGameVariable::execute(Actor *actor) {
actor->getPage()->getGame()->setVariable(_name, _value);
}
@ -82,7 +85,7 @@ void SideEffectGameVariable::toConsole() {
debug("\t\tSideEffectGameVariable: _name=%s, _value=%s", _name.c_str(), _value.c_str());
}
void SideEffectModuleVariable::execute(LeadActor *actor) {
void SideEffectModuleVariable::execute(Actor *actor) {
actor->getPage()->getModule()->setVariable(_name, _value);
}
@ -90,7 +93,7 @@ void SideEffectModuleVariable::toConsole() {
debug("\t\tSideEffectModuleVariable: _name=%s, _value=%s", _name.c_str(), _value.c_str());
}
void SideEffectPageVariable::execute(LeadActor *actor) {
void SideEffectPageVariable::execute(Actor *actor) {
actor->getPage()->setVariable(_name, _value);
}
@ -102,7 +105,7 @@ void SideEffectRandomPageVariable::deserialize(Archive &archive) {
archive >> _name >> _values;
}
void SideEffectRandomPageVariable::execute(LeadActor *actor) {
void SideEffectRandomPageVariable::execute(Actor *actor) {
assert(!_values.empty());
Common::RandomSource &rnd = actor->getPage()->getGame()->getRnd();

View File

@ -28,19 +28,19 @@
namespace Pink {
class LeadActor;
class Actor;
class SideEffect : public Object {
public:
virtual void deserialize(Archive &archive) = 0;
virtual void execute(LeadActor *actor) = 0;
virtual void execute(Actor *actor) = 0;
};
class SideEffectExit : public SideEffect {
public:
virtual void deserialize(Archive &archive);
virtual void toConsole();
virtual void execute(LeadActor *actor);
virtual void execute(Actor *actor);
private:
Common::String _nextModule;
@ -50,7 +50,7 @@ private:
class SideEffectLocation : public SideEffect {
public:
virtual void deserialize(Archive &archive);
virtual void execute(LeadActor *actor);
virtual void execute(Actor *actor);
virtual void toConsole();
private:
@ -60,7 +60,7 @@ private:
class SideEffectInventoryItemOwner : public SideEffect {
public:
virtual void deserialize(Archive &archive);
virtual void execute(LeadActor *actor);
virtual void execute(Actor *actor);
virtual void toConsole();
private:
@ -71,7 +71,7 @@ private:
class SideEffectVariable : public SideEffect {
public:
virtual void deserialize(Archive &archive);
virtual void execute(LeadActor *actor) = 0;
virtual void execute(Actor *actor) = 0;
protected:
Common::String _name;
@ -81,19 +81,19 @@ protected:
class SideEffectGameVariable : public SideEffectVariable {
public:
virtual void toConsole();
virtual void execute(LeadActor *actor);
virtual void execute(Actor *actor);
};
class SideEffectModuleVariable : public SideEffectVariable {
public:
virtual void toConsole();
virtual void execute(LeadActor *actor);
virtual void execute(Actor *actor);
};
class SideEffectPageVariable : public SideEffectVariable {
public:
virtual void toConsole();
virtual void execute(LeadActor *actor);
virtual void execute(Actor *actor);
};
class SideEffectRandomPageVariable : public SideEffect
@ -101,7 +101,7 @@ class SideEffectRandomPageVariable : public SideEffect
public:
virtual void deserialize(Archive &archive);
virtual void toConsole();
virtual void execute(LeadActor *actor);
virtual void execute(Actor *actor);
private:
Common::String _name;

View File

@ -20,10 +20,23 @@
*
*/
#include <common/debug.h>
#include "walk_location.h"
#include "engines/pink/archive.h"
void Pink::WalkLocation::deserialize(Pink::Archive &archive) {
namespace Pink {
void WalkLocation::deserialize(Pink::Archive &archive) {
NamedObject::deserialize(archive);
archive >> _neighbors;
}
void WalkLocation::toConsole() {
debug("\tWalkLocation: _name =%s", _name.c_str());
debug("\tNeighbors:");
for (int i = 0; i < _neighbors.size(); ++i) {
debug("\t\t%s", _neighbors[i].c_str());
}
}
} // End of namespace Pink;

View File

@ -33,6 +33,8 @@ class WalkLocation : public NamedObject {
public:
virtual void deserialize(Archive &archive);
void toConsole() override;
Common::StringArray &getNeigbors() { return _neighbors;}
private:
Common::StringArray _neighbors;
};

View File

@ -1,20 +1,153 @@
//
// Created by andrei on 3/17/18.
//
/* 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 "walk_mgr.h"
#include "walk_location.h"
#include "engines/pink/objects/actions/walk_action.h"
#include "engines/pink/objects/actors/lead_actor.h"
#include "engines/pink/archive.h"
#include "pink/cel_decoder.h"
namespace Pink {
void Pink::WalkMgr::deserialize(Pink::Archive &archive) {
_leadActor = static_cast<LeadActor*>(archive.readObject());
WalkMgr::WalkMgr()
: _isWalking(false), _leadActor(nullptr)
{
}
void WalkMgr::deserialize(Pink::Archive &archive) {
_leadActor = static_cast<LeadActor *>(archive.readObject());
archive >> _locations;
}
Pink::WalkLocation *Pink::WalkMgr::findLocation(Common::String &name) {
return *Common::find_if(_locations.begin(), _locations.end(), [&name] (WalkLocation *location) {
WalkLocation *WalkMgr::findLocation(const Common::String &name) {
auto it = Common::find_if(_locations.begin(), _locations.end(), [&name](WalkLocation *location) {
return location->getName() == name;
});
if (it == _locations.end())
return nullptr;
return *it;
}
void WalkMgr::toConsole() {
debug("WalkMgr:");
for (int i = 0; i < _locations.size(); ++i) {
_locations[i]->toConsole();
}
}
void WalkMgr::start(WalkLocation *destination) {
if (_isWalking)
return;
if (_current.name.empty()) {
_current.name = _locations[0]->getName();
_current.coord = getLocationCoordinates(_locations[0]->getName());
}
_destination = destination;
if (_current.name == _destination->getName()) {
end();
}
else {
_isWalking = true;
WalkLocation *currentLocation = findLocation(_current.name);
WalkShortestPath path(this);
WalkLocation *nextLocation = path.next(currentLocation, _destination);
initNextWayPoint(nextLocation);
_leadActor->setAction(getWalkAction(), 0);
}
}
void WalkMgr::initNextWayPoint(WalkLocation *location) {
_next.name = location->getName();
_next.coord = getLocationCoordinates(location->getName());
}
WalkAction *WalkMgr::getWalkAction() {
Common::String walkActionName;
if (_current.coord.z == _next.coord.z){
if (_next.coord.x > _current.coord.x){
walkActionName = Common::String::format("%dRight", _current.coord.z);
}
else walkActionName = Common::String::format("%dLeft", _next.coord.z);
}
else walkActionName = Common::String::format("%dTo%d", _current.coord.z, _next.coord.z);
Action *action = _leadActor->findAction(walkActionName);
return static_cast<WalkAction*>(action);
}
double WalkMgr::getLengthBetweenLocations(WalkLocation *first, WalkLocation *second) {
Coordinates firstCoord = getLocationCoordinates(first->getName());
Coordinates secondCoord = getLocationCoordinates(second->getName());
return sqrt((secondCoord.x - firstCoord.x) * (secondCoord.x - firstCoord.x) +
(secondCoord.y - firstCoord.y) * (secondCoord.y - firstCoord.y));
}
WalkMgr::Coordinates WalkMgr::getLocationCoordinates(const Common::String &locationName) {
Coordinates coords;
ActionCEL *action = static_cast<ActionCEL*>(_leadActor->findAction(locationName));
action->start(0);
CelDecoder *decoder = action->getDecoder();
coords.x = decoder->getX() + decoder->getWidth() / 2;
coords.y = decoder->getY() + decoder->getHeight() / 2;
coords.z = action->getZ();
action->end();
return coords;
}
void WalkMgr::setCurrentWayPoint(WalkLocation *location) {
_current.name = location->getName();
_current.coord = getLocationCoordinates(_current.name);
}
void WalkMgr::update() {
if (_leadActor->isPlaying())
return;
WalkShortestPath path(this);
_current = _next;
WalkLocation *next = path.next(findLocation(_current.name), _destination);
if (next){
initNextWayPoint(next);
_leadActor->setAction(getWalkAction(), 0);
}
else end();
}
void WalkMgr::end() {
_isWalking = false;
_leadActor->onWalkEnd();
}
} // End of namespace Pink

View File

@ -25,20 +25,49 @@
#include <common/array.h>
#include "engines/pink/objects/object.h"
#include "walk_shortest_path.h"
namespace Pink {
class WalkLocation;
class LeadActor;
class WalkAction;
class WalkMgr : public Object {
public:
WalkMgr();
virtual void deserialize(Archive &archive);
WalkLocation *findLocation(Common::String &name);
void toConsole() override;
WalkLocation *findLocation(const Common::String &name);
void start(WalkLocation *destination);
void update();
double getLengthBetweenLocations(WalkLocation *first, WalkLocation *second);
void setCurrentWayPoint(WalkLocation *location);
private:
struct Coordinates {
int x;
int y;
int z;
};
struct WayPoint {
Common::String name;
Coordinates coord;
};
Coordinates getLocationCoordinates(const Common::String &locationName);
void end();
void initNextWayPoint(WalkLocation *location);
WalkAction *getWalkAction();
LeadActor *_leadActor;
WalkLocation *_destination;
Common::Array<WalkLocation*> _locations;
WayPoint _current;
WayPoint _next;
bool _isWalking;
};
} // End of namespace Pink

View File

@ -0,0 +1,159 @@
/* 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 "walk_shortest_path.h"
#include "walk_mgr.h"
#include "walk_location.h"
namespace Pink {
WalkShortestPath::WalkShortestPath(WalkMgr *manager)
: _manager(manager)
{}
WalkLocation *WalkShortestPath::next(WalkLocation *start, WalkLocation *destination) {
if (start == destination)
return nullptr;
add(start, 0.0, 0);
while (build() != destination);
return getNearestNeighbor(destination);
}
void WalkShortestPath::add(WalkLocation *wl, double val, WalkLocation *nearest) {
_locations.push_back(wl);
_visited.push_back(wl);
_weight.push_back(val);
_nearestNeigbor.push_back(nearest);
}
WalkLocation *WalkShortestPath::build() {
WalkLocation *nearest = nullptr;
WalkLocation *location = nullptr;
double len = -1.0;
addLocationsToVisit();
for (int i = 0; i < _toVisit.size(); ++i) {
double curLen = getLengthToNearestNeigbor(_toVisit[i]);
if (curLen < 0) {
remove(_toVisit[i]);
continue;
}
curLen += getWeight(_toVisit[i]);
if (len < 0.0 || len > curLen) {
len = curLen;
location = _toVisit[i];
nearest = getNearestNeighbor(_toVisit[i]);
if (!nearest)
nearest = findNearestNeighbor(_toVisit[i]);
}
}
WalkLocation *neighbor = findNearestNeighbor(location);
if (neighbor)
add(neighbor, len, nearest);
return neighbor;
}
WalkLocation *WalkShortestPath::getNearestNeighbor(WalkLocation *location) {
for(int i = 0; i < _visited.size(); ++i){
if (_visited[i] == location)
return _nearestNeigbor[i];
}
return nullptr;
}
void WalkShortestPath::addLocationsToVisit() {
_toVisit.resize(_locations.size());
for (int i = 0; i < _locations.size(); ++i) {
_toVisit[i] = _locations[i];
}
}
double WalkShortestPath::getLengthToNearestNeigbor(WalkLocation *location) {
double minLength = -1.0;
auto &neighbors = location->getNeigbors();
for (int i = 0; i < neighbors.size(); ++i) {
WalkLocation *neighbor = _manager->findLocation(neighbors[i]);
if (!isLocationVisited(neighbor)){
double length = _manager->getLengthBetweenLocations(location, neighbor);
if (minLength >= 0.0) {
if (length < minLength)
minLength = length;
}
else minLength = length;
}
}
return minLength;
}
WalkLocation *WalkShortestPath::findNearestNeighbor(WalkLocation *location) {
double minLength = -1.0;
WalkLocation *nearest = nullptr;
auto neighbors = location->getNeigbors();
for (int i = 0; i < neighbors.size(); ++i) {
WalkLocation *neighbor = _manager->findLocation(neighbors[i]);
if (!isLocationVisited(neighbor)){
double length = _manager->getLengthBetweenLocations(location, neighbor);
if (minLength >= 0.0) {
if (length < minLength) {
nearest = neighbor;
minLength = length;
}
}
else {
nearest = neighbor;
minLength = length;
}
}
}
return nearest;
}
double WalkShortestPath::getWeight(WalkLocation *location) {
for (int i = 0; i < _locations.size(); ++i) {
if (_locations[i] == location)
return _weight[i];
}
return 0.0;
}
bool WalkShortestPath::isLocationVisited(WalkLocation *location) {
for (int i = 0; i < _visited.size(); ++i) {
if (_visited[i] == location)
return 1;
}
return 0;
}
void WalkShortestPath::remove(WalkLocation *location) {
for (int i = 0; i < _locations.size(); ++i) {
if (_locations[i] == location){
_locations.remove_at(i);
_weight.remove_at(i);
}
}
}
} // End of namespace Pink

View File

@ -0,0 +1,61 @@
/* 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 PINK_WALK_SHORTEST_PATH_H
#define PINK_WALK_SHORTEST_PATH_H
#include <common/array.h>
namespace Pink {
class WalkLocation;
class WalkMgr;
class WalkShortestPath {
public:
WalkShortestPath(WalkMgr *manager);
WalkLocation *next(WalkLocation *start, WalkLocation *destination);
private:
void add(WalkLocation *wl, double val, WalkLocation *nearest);
void remove(WalkLocation *location);
WalkLocation *build();
WalkLocation *getNearestNeighbor(WalkLocation *location);
WalkLocation *findNearestNeighbor(WalkLocation *location);
double getLengthToNearestNeigbor(WalkLocation *location);
double getWeight(WalkLocation *location);
void addLocationsToVisit();
bool isLocationVisited(WalkLocation *location);
WalkMgr *_manager;
Common::Array<WalkLocation*> _locations;
Common::Array<WalkLocation*> _toVisit;
Common::Array<double> _weight;
Common::Array<WalkLocation*> _visited;
Common::Array<WalkLocation*> _nearestNeigbor;
};
} // End of namespace Pink
#endif

View File

@ -30,6 +30,7 @@
#include <graphics/surface.h>
#include <graphics/cursorman.h>
#include <common/winexe_pe.h>
#include <common/config-manager.h>
namespace Pink {

View File

@ -68,7 +68,7 @@ void Sound::play(Audio::Mixer::SoundType type, int volume, bool isLoop) {
}
else audioStream = wavStream;
_mixer->playStream(type, &_handle , audioStream, -1 , Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::YES);
_mixer->playStream(type, &_handle , audioStream, -1 , 50, 0, DisposeAfterUse::YES);
}
void Sound::setBalance(int8 balance) {