Initial commit
This commit is contained in:
102
engines/crab/animation/AnimationEffect.h
Normal file
102
engines/crab/animation/AnimationEffect.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRAB_ANIMATIONEFFECT_H
|
||||
#define CRAB_ANIMATIONEFFECT_H
|
||||
|
||||
#include "crab/loaders.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
namespace pyrodactyl {
|
||||
namespace anim {
|
||||
// Types of fade effects
|
||||
enum FadeType {
|
||||
FADE_NONE,
|
||||
FADE_IN,
|
||||
FADE_OUT
|
||||
};
|
||||
|
||||
// Sometimes we need to stop drawing the game for proper fade effects
|
||||
// Use DRAW_STOP to stop drawing the game until DRAW_START is called. DRAW_SAME doesn't change anything
|
||||
enum DrawType {
|
||||
DRAW_SAME,
|
||||
DRAW_STOP,
|
||||
DRAW_START
|
||||
};
|
||||
|
||||
struct AnimationEffect {
|
||||
// What sort of effect do we apply to the image
|
||||
FadeType _type;
|
||||
|
||||
// The duration of the effect relative to the start of this animation
|
||||
uint32 _start, _finish;
|
||||
|
||||
// Warning: the only way to start drawing the game again is having another animation event with DRAW_START
|
||||
DrawType _drawGame;
|
||||
|
||||
AnimationEffect() {
|
||||
_type = FADE_NONE;
|
||||
_drawGame = DRAW_SAME;
|
||||
_start = 0;
|
||||
_finish = 0;
|
||||
}
|
||||
|
||||
AnimationEffect(rapidxml::xml_node<char> *node) : AnimationEffect() {
|
||||
if (nodeValid("effect", node)) {
|
||||
rapidxml::xml_node<char> *effnode = node->first_node("effect");
|
||||
loadNum(_start, "start", effnode);
|
||||
loadNum(_finish, "finish", effnode);
|
||||
|
||||
Common::String str;
|
||||
loadStr(str, "type", effnode);
|
||||
if (str == "fade_in")
|
||||
_type = FADE_IN;
|
||||
else if (str == "fade_out")
|
||||
_type = FADE_OUT;
|
||||
else
|
||||
_type = FADE_NONE;
|
||||
|
||||
loadStr(str, "game_draw", effnode);
|
||||
if (str == "start")
|
||||
_drawGame = DRAW_START;
|
||||
else if (str == "stop")
|
||||
_drawGame = DRAW_STOP;
|
||||
else
|
||||
_drawGame = DRAW_SAME;
|
||||
}
|
||||
}
|
||||
};
|
||||
} // End of namespace anim
|
||||
} // End of namespace pyrodactyl
|
||||
|
||||
} // End of namespace Crab
|
||||
|
||||
#endif // CRAB_ANIMATIONEFFECT_H
|
||||
106
engines/crab/animation/AnimationFrame.cpp
Normal file
106
engines/crab/animation/AnimationFrame.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "crab/crab.h"
|
||||
#include "crab/animation/AnimationFrame.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
using namespace pyrodactyl::image;
|
||||
using namespace pyrodactyl::anim;
|
||||
|
||||
AnimationFrame::AnimationFrame(rapidxml::xml_node<char> *node) : AnimationFrame() {
|
||||
_eff = AnimationEffect(node);
|
||||
Vector2i::load(node);
|
||||
loadImgKey(_img, "img", node);
|
||||
loadNum(_start, "start", node);
|
||||
loadNum(_finish, "finish", node);
|
||||
loadColor(_col, node);
|
||||
|
||||
if (nodeValid("text", node, false))
|
||||
_text.load(node->first_node("text"));
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
void AnimationFrame::reset() {
|
||||
switch (_eff._type) {
|
||||
case FADE_IN:
|
||||
_col.a = 0;
|
||||
break;
|
||||
case FADE_OUT:
|
||||
_col.a = 255;
|
||||
break;
|
||||
default:
|
||||
_col.a = 255;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationFrame::draw(const uint32 ×tamp) {
|
||||
warning("STUB: AnimationFrame::draw()");
|
||||
|
||||
#if 0
|
||||
// Only draw the frame in the specified duration
|
||||
if (timestamp >= start && timestamp <= finish) {
|
||||
// Fill the screen with the color indicated
|
||||
SDL_SetRenderDrawBlendMode(gRenderer, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetRenderDrawColor(gRenderer, col.r, col.g, col.b, col.a);
|
||||
SDL_RenderFillRect(gRenderer, NULL);
|
||||
|
||||
g_engine->_imageManager->draw(x, y, img);
|
||||
text.draw();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
DrawType AnimationFrame::internalEvents(const uint32 ×tamp) {
|
||||
|
||||
// Vary alpha according to the effect values in the variation time frame
|
||||
if (timestamp >= _eff._start && timestamp <= _eff._finish) {
|
||||
// These equations courtesy of linear algebra
|
||||
switch (_eff._type) {
|
||||
case FADE_IN:
|
||||
_col.a = (255 * (timestamp - _eff._start)) / (_eff._finish - _eff._start);
|
||||
break;
|
||||
case FADE_OUT:
|
||||
_col.a = (255 * (_eff._finish - timestamp)) / (_eff._finish - _eff._start);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return _eff._drawGame;
|
||||
}
|
||||
|
||||
return DRAW_SAME;
|
||||
}
|
||||
|
||||
} // End of namespace Crab
|
||||
81
engines/crab/animation/AnimationFrame.h
Normal file
81
engines/crab/animation/AnimationFrame.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRAB_ANIMATIONFRAME_H
|
||||
#define CRAB_ANIMATIONFRAME_H
|
||||
|
||||
#include "crab/animation/AnimationEffect.h"
|
||||
#include "crab/image/ImageManager.h"
|
||||
#include "crab/text/TextManager.h"
|
||||
#include "crab/ui/HoverInfo.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
namespace pyrodactyl {
|
||||
namespace anim {
|
||||
|
||||
struct AnimationFrame : public Vector2i {
|
||||
// The image drawn in this frame
|
||||
ImageKey _img;
|
||||
|
||||
// This is the time in we draw the frame milliseconds relative to the start of the entire animation
|
||||
uint32 _start, _finish;
|
||||
|
||||
// The effect applied to the image
|
||||
AnimationEffect _eff;
|
||||
|
||||
// In case we want to display any words during the animation
|
||||
pyrodactyl::ui::HoverInfo _text;
|
||||
|
||||
// The color drawn on the screen
|
||||
Color _col;
|
||||
|
||||
AnimationFrame() {
|
||||
_img = 0;
|
||||
_start = 0;
|
||||
_finish = 0;
|
||||
_col.r = 0;
|
||||
_col.g = 0;
|
||||
_col.b = 0;
|
||||
_col.a = 255;
|
||||
}
|
||||
|
||||
AnimationFrame(rapidxml::xml_node<char> *node);
|
||||
|
||||
void reset();
|
||||
void draw(const uint32 ×tamp);
|
||||
DrawType internalEvents(const uint32 ×tamp);
|
||||
};
|
||||
} // End of namespace anim
|
||||
} // End of namespace pyrodactyl
|
||||
|
||||
} // End of namespace Crab
|
||||
|
||||
#endif // CRAB_ANIMATIONFRAME_H
|
||||
133
engines/crab/animation/PopUp.cpp
Normal file
133
engines/crab/animation/PopUp.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "crab/ScreenSettings.h"
|
||||
#include "crab/animation/PopUp.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
using namespace pyrodactyl::anim;
|
||||
using namespace pyrodactyl::event;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Load from xml
|
||||
//------------------------------------------------------------------------
|
||||
void PopUp::load(rapidxml::xml_node<char> *node) {
|
||||
_duration.load(node, "duration", false);
|
||||
_delay.load(node, "delay");
|
||||
loadStr(_text, "text", node);
|
||||
loadNum(_next, "next", node);
|
||||
|
||||
bool end = false;
|
||||
loadBool(end, "end", node, false);
|
||||
if (end)
|
||||
_next = -1;
|
||||
|
||||
_visible.load(node);
|
||||
|
||||
_effect.clear();
|
||||
for (rapidxml::xml_node<char> *n = node->first_node("effect"); n != nullptr; n = n->next_sibling("effect")) {
|
||||
Effect e;
|
||||
e.load(n);
|
||||
_effect.push_back(e);
|
||||
}
|
||||
}
|
||||
|
||||
void PopUpCollection::load(rapidxml::xml_node<char> *node) {
|
||||
loadBool(_loop, "loop", node);
|
||||
for (auto n = node->first_node("dialog"); n != nullptr; n = n->next_sibling("dialog"))
|
||||
_element.push_back(n);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Internal events
|
||||
//------------------------------------------------------------------------
|
||||
bool PopUp::internalEvents(pyrodactyl::event::Info &info, const Common::String &playerId,
|
||||
Common::Array<EventResult> &result, Common::Array<EventSeqInfo> &endSeq) {
|
||||
if (_visible.evaluate(info) || _startedShow) {
|
||||
if (_delay.targetReached()) {
|
||||
if (_duration.targetReached(g_engine->_screenSettings->_textSpeed)) {
|
||||
_show = false;
|
||||
|
||||
for (auto &i : _effect)
|
||||
i.execute(info, playerId, result, endSeq);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
_startedShow = true;
|
||||
_show = true;
|
||||
}
|
||||
} else
|
||||
_show = false;
|
||||
} else
|
||||
_show = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void PopUpCollection::internalEvents(pyrodactyl::event::Info &info, const Common::String &playerId,
|
||||
Common::Array<EventResult> &result, Common::Array<EventSeqInfo> &endSeq) {
|
||||
if (_cur >= 0 && (uint)_cur < _element.size()) {
|
||||
if (_element[_cur].internalEvents(info, playerId, result, endSeq)) {
|
||||
if (_element[_cur]._next <= 0 || (uint)_element[_cur]._next >= _element.size()) {
|
||||
// This means that this popup is the "end" node, we must loop back to start or end this
|
||||
if (_loop) {
|
||||
_cur = 0;
|
||||
_element[_cur].reset();
|
||||
} else
|
||||
_cur = -1;
|
||||
} else {
|
||||
_cur = _element[_cur]._next;
|
||||
_element[_cur].reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Draw functions
|
||||
//------------------------------------------------------------------------
|
||||
void PopUp::draw(const int &x, const int &y, pyrodactyl::ui::ParagraphData &pop, const Rect &camera) {
|
||||
if (_show) {
|
||||
if (x + pop.x < camera.w / 3)
|
||||
g_engine->_textManager->draw(x + pop.x, y + pop.y, _text, pop._col, pop._font, ALIGN_LEFT, pop._line.x, pop._line.y, true);
|
||||
else if (x + pop.x > (2 * camera.w) / 3)
|
||||
g_engine->_textManager->draw(x + pop.x, y + pop.y, _text, pop._col, pop._font, ALIGN_RIGHT, pop._line.x, pop._line.y, true);
|
||||
else
|
||||
g_engine->_textManager->draw(x + pop.x, y + pop.y, _text, pop._col, pop._font, ALIGN_CENTER, pop._line.x, pop._line.y, true);
|
||||
}
|
||||
}
|
||||
|
||||
void PopUpCollection::draw(const int &x, const int &y, pyrodactyl::ui::ParagraphData &pop, const Rect &camera) {
|
||||
if (_cur >= 0 && (uint)_cur < _element.size())
|
||||
_element[_cur].draw(x, y, pop, camera);
|
||||
}
|
||||
|
||||
} // End of namespace Crab
|
||||
127
engines/crab/animation/PopUp.h
Normal file
127
engines/crab/animation/PopUp.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRAB_POPUP_H
|
||||
#define CRAB_POPUP_H
|
||||
|
||||
#include "crab/timer.h"
|
||||
#include "crab/event/effect.h"
|
||||
#include "crab/event/triggerset.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
namespace pyrodactyl {
|
||||
namespace anim {
|
||||
struct PopUp {
|
||||
// The total time the popup stays on the screen
|
||||
Timer _duration;
|
||||
|
||||
// The time we wait before showing the trigger for the first time
|
||||
Timer _delay;
|
||||
|
||||
// Should we draw this or not? (Decided by internal events)
|
||||
bool _show;
|
||||
|
||||
// Popups with "talk key pressed" condition need to be shown once the key is pressed
|
||||
bool _startedShow;
|
||||
|
||||
// Triggers for when you only want to display this in certain conditions
|
||||
pyrodactyl::event::TriggerSet _visible;
|
||||
|
||||
// Effects for changing variables and other related stuff
|
||||
Common::Array<pyrodactyl::event::Effect> _effect;
|
||||
|
||||
// The text displayed
|
||||
Common::String _text;
|
||||
|
||||
// The next popup we should go to, negative values means the end
|
||||
int _next;
|
||||
|
||||
PopUp() {
|
||||
_next = -1;
|
||||
reset();
|
||||
}
|
||||
|
||||
PopUp(rapidxml::xml_node<char> *node) : PopUp() {
|
||||
load(node);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
_show = false;
|
||||
_startedShow = false;
|
||||
_delay.stop();
|
||||
_duration.stop();
|
||||
}
|
||||
|
||||
void load(rapidxml::xml_node<char> *node);
|
||||
void draw(const int &x, const int &y, pyrodactyl::ui::ParagraphData &pop, const Rect &camera);
|
||||
|
||||
// return true if we should proceed to next event, false otherwise
|
||||
bool internalEvents(pyrodactyl::event::Info &info, const Common::String &playerId,
|
||||
Common::Array<pyrodactyl::event::EventResult> &result, Common::Array<pyrodactyl::event::EventSeqInfo> &endSeq);
|
||||
};
|
||||
|
||||
struct PopUpCollection {
|
||||
// Collection of environmental dialog
|
||||
Common::Array<PopUp> _element;
|
||||
|
||||
// The current dialog being played
|
||||
int _cur;
|
||||
|
||||
// true if dialog needs to loop, false otherwise
|
||||
bool _loop;
|
||||
|
||||
PopUpCollection() {
|
||||
_cur = 0;
|
||||
_loop = true;
|
||||
}
|
||||
|
||||
// Return true if any of the popup dialog is visible, false otherwise
|
||||
bool show() {
|
||||
for (auto &i : _element)
|
||||
if (i._show)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void load(rapidxml::xml_node<char> *node);
|
||||
|
||||
void internalEvents(pyrodactyl::event::Info &info, const Common::String &playerId,
|
||||
Common::Array<pyrodactyl::event::EventResult> &result, Common::Array<pyrodactyl::event::EventSeqInfo> &endSeq);
|
||||
|
||||
void draw(const int &x, const int &y, pyrodactyl::ui::ParagraphData &pop, const Rect &camera);
|
||||
};
|
||||
} // End of namespace anim
|
||||
} // End of namespace pyrodactyl
|
||||
|
||||
} // End of namespace Crab
|
||||
|
||||
#endif // CRAB_POPUP_H
|
||||
66
engines/crab/animation/animation.cpp
Normal file
66
engines/crab/animation/animation.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "crab/animation/animation.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
using namespace pyrodactyl::image;
|
||||
using namespace pyrodactyl::anim;
|
||||
|
||||
Animation::Animation(rapidxml::xml_node<char> *node) {
|
||||
loadNum(_length, "length", node);
|
||||
for (auto n = node->first_node("frame"); n != nullptr; n = n->next_sibling("frame"))
|
||||
_frame.push_back(n);
|
||||
}
|
||||
|
||||
void Animation::draw() {
|
||||
uint32 timestamp = _timer.ticks();
|
||||
for (auto &frame : _frame)
|
||||
frame.draw(timestamp);
|
||||
}
|
||||
|
||||
bool Animation::internalEvents(DrawType &gameDraw) {
|
||||
uint32 timestamp = _timer.ticks();
|
||||
for (auto &frame : _frame) {
|
||||
DrawType result = frame.internalEvents(timestamp);
|
||||
// if (result != DRAW_SAME)
|
||||
gameDraw = result;
|
||||
}
|
||||
|
||||
return _timer.ticks() >= _length;
|
||||
}
|
||||
|
||||
void Animation::reset() {
|
||||
for (auto &frame : _frame)
|
||||
frame.reset();
|
||||
}
|
||||
|
||||
} // End of namespace Crab
|
||||
73
engines/crab/animation/animation.h
Normal file
73
engines/crab/animation/animation.h
Normal file
@@ -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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRAB_ANIMATION_H
|
||||
#define CRAB_ANIMATION_H
|
||||
|
||||
#include "crab/timer.h"
|
||||
#include "crab/animation/AnimationEffect.h"
|
||||
#include "crab/animation/AnimationFrame.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
namespace pyrodactyl {
|
||||
namespace anim {
|
||||
class Animation {
|
||||
// All the frames are updated simultaneously rather than sequentially
|
||||
Common::Array<AnimationFrame> _frame;
|
||||
|
||||
// Length of the entire animation in milliseconds
|
||||
uint32 _length;
|
||||
|
||||
// Keep track of the time
|
||||
Timer _timer;
|
||||
|
||||
public:
|
||||
Animation() {
|
||||
_length = 0;
|
||||
}
|
||||
|
||||
Animation(rapidxml::xml_node<char> *node);
|
||||
|
||||
void draw();
|
||||
void reset();
|
||||
|
||||
bool internalEvents(DrawType &gameDraw);
|
||||
void start() {
|
||||
reset();
|
||||
_timer.start();
|
||||
}
|
||||
};
|
||||
} // End of namespace anim
|
||||
} // End of namespace pyrodactyl
|
||||
|
||||
} // End of namespace Crab
|
||||
|
||||
#endif // CRAB__ANIMATION_H
|
||||
109
engines/crab/animation/animframe.cpp
Normal file
109
engines/crab/animation/animframe.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "crab/animation/animframe.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
using namespace pyrodactyl::anim;
|
||||
|
||||
void AnimFrame::load(rapidxml::xml_node<char> *node, const Rect &VBOX, const uint32 &rep, const int &AX, const int &AY) {
|
||||
_clip.load(node);
|
||||
|
||||
if (rep == 0)
|
||||
loadNum(_repeat, "repeat", node);
|
||||
else
|
||||
_repeat = rep;
|
||||
|
||||
if (AX == 0.0f && AY == 0.0f) {
|
||||
if (nodeValid("anchor", node, false))
|
||||
_anchor.load(node->first_node("anchor"));
|
||||
} else {
|
||||
_anchor.x = AX;
|
||||
_anchor.y = AY;
|
||||
}
|
||||
|
||||
if (VBOX.w == 0 || VBOX.h == 0) {
|
||||
if (nodeValid("box_v", node))
|
||||
_boxV.load(node->first_node("box_v"));
|
||||
} else
|
||||
_boxV = VBOX;
|
||||
}
|
||||
|
||||
void AnimationFrames::load(rapidxml::xml_node<char> *node) {
|
||||
loadTextureFlipType(_flip, node);
|
||||
|
||||
if (!loadNum(_repeat, "repeat", node, false))
|
||||
_repeat = 0;
|
||||
|
||||
loadBool(_random, "random", node, false);
|
||||
|
||||
if (nodeValid("anchor", node, false))
|
||||
_anchor.load(node->first_node("anchor"));
|
||||
|
||||
if (nodeValid("box_v", node))
|
||||
_boxV.load(node->first_node("box_v"));
|
||||
|
||||
if (nodeValid("shadow", node)) {
|
||||
_shadow.load(node->first_node("shadow"));
|
||||
_shadow._valid = true;
|
||||
}
|
||||
|
||||
if (nodeValid("frames", node)) {
|
||||
_frame.clear();
|
||||
rapidxml::xml_node<char> *framenode = node->first_node("frames");
|
||||
for (auto n = framenode->first_node("frame"); n != nullptr; n = n->next_sibling("frame")) {
|
||||
AnimFrame af;
|
||||
af.load(n, _boxV, _repeat, _anchor.x, _anchor.y);
|
||||
_frame.push_back(af);
|
||||
}
|
||||
}
|
||||
|
||||
if (_random)
|
||||
_currentClip = g_engine->getRandomNumber(_frame.size() - 1);
|
||||
else
|
||||
_currentClip = 0;
|
||||
}
|
||||
|
||||
bool AnimationFrames::updateClip() {
|
||||
if (_currentClip < _frame.size()) {
|
||||
_currentClip = (_currentClip + 1) % _frame.size();
|
||||
return true;
|
||||
} else
|
||||
_currentClip = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const AnimFrame &AnimationFrames::currentFrame() {
|
||||
return _frame[_currentClip];
|
||||
}
|
||||
|
||||
} // End of namespace Crab
|
||||
113
engines/crab/animation/animframe.h
Normal file
113
engines/crab/animation/animframe.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRAB_ANIMFRAME_H
|
||||
#define CRAB_ANIMFRAME_H
|
||||
|
||||
#include "crab/Rectangle.h"
|
||||
#include "crab/vectors.h"
|
||||
#include "crab/animation/shadow.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
namespace pyrodactyl {
|
||||
namespace anim {
|
||||
struct AnimFrame {
|
||||
// Portion of sprite to show
|
||||
Rect _clip;
|
||||
|
||||
// The duration for which the frame must be repeated on screen
|
||||
uint32 _repeat;
|
||||
|
||||
// The anchor point of the frame
|
||||
Vector2i _anchor;
|
||||
|
||||
// The vulnerable hit box for this frame
|
||||
Rect _boxV;
|
||||
|
||||
AnimFrame() {
|
||||
_repeat = 0;
|
||||
}
|
||||
|
||||
void load(rapidxml::xml_node<char> *node, const Rect &VBOX,
|
||||
const uint32 &REP = 0, const int &AX = 0, const int &AY = 0);
|
||||
};
|
||||
|
||||
class AnimationFrames {
|
||||
// The global vulnerable hit box for all the frames
|
||||
// If the W or H of this is 0, then use individual frame values
|
||||
Rect _boxV;
|
||||
|
||||
public:
|
||||
// The frames for the animation
|
||||
Common::Array<AnimFrame> _frame;
|
||||
|
||||
// The currentClip
|
||||
uint _currentClip;
|
||||
|
||||
// Should we flip the images in the frame rectangle?
|
||||
TextureFlipType _flip;
|
||||
|
||||
// The global repeat value for all the frames
|
||||
// If this is 0, then use individual frame values
|
||||
uint32 _repeat;
|
||||
|
||||
// The global anchor value for all the frames
|
||||
// If this is 0, then use individual frame values
|
||||
Vector2i _anchor;
|
||||
|
||||
// true if animation starts at a random frame
|
||||
// used for idle animations so that every sprite doesn't animate in sync
|
||||
bool _random;
|
||||
|
||||
// Does this set of animation frames need a specific shadow offset?
|
||||
ShadowOffset _shadow;
|
||||
|
||||
AnimationFrames() {
|
||||
reset();
|
||||
_flip = FLIP_NONE;
|
||||
_repeat = 0;
|
||||
_random = false;
|
||||
}
|
||||
void reset() {
|
||||
_currentClip = 0;
|
||||
}
|
||||
|
||||
void load(rapidxml::xml_node<char> *node);
|
||||
|
||||
bool updateClip();
|
||||
const AnimFrame ¤tFrame();
|
||||
};
|
||||
} // End of namespace anim
|
||||
} // End of namespace pyrodactyl
|
||||
|
||||
} // End of namespace Crab
|
||||
|
||||
#endif // CRAB_ANIMFRAME_H
|
||||
89
engines/crab/animation/animset.cpp
Normal file
89
engines/crab/animation/animset.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "crab/XMLDoc.h"
|
||||
#include "crab/animation/animset.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
using namespace pyrodactyl::anim;
|
||||
|
||||
void AnimSet::load(const Common::Path &filename) {
|
||||
XMLDoc conf(filename);
|
||||
if (conf.ready()) {
|
||||
rapidxml::xml_node<char> *node = conf.doc()->first_node();
|
||||
if (nodeValid(node)) {
|
||||
_fight.load(node);
|
||||
_walk.load(node);
|
||||
|
||||
if (nodeValid("bounds", node))
|
||||
_bounds.load(node->first_node("bounds"));
|
||||
|
||||
if (nodeValid("shadow", node))
|
||||
_shadow.load(node->first_node("shadow"));
|
||||
|
||||
if (nodeValid("focus", node))
|
||||
_focus.load(node->first_node("focus"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextureFlipType AnimSet::flip(const Direction &dir) {
|
||||
TextureFlipType ret;
|
||||
if (_fight.flip(ret, dir))
|
||||
return ret;
|
||||
|
||||
return _walk.flip(dir);
|
||||
}
|
||||
|
||||
const ShadowOffset &AnimSet::shadow(const Direction &dir) {
|
||||
if (_fight.validMove())
|
||||
return _fight.shadow(dir);
|
||||
|
||||
return _walk.shadow(dir);
|
||||
}
|
||||
|
||||
int AnimSet::anchorX(const Direction &dir) {
|
||||
FightAnimFrame faf;
|
||||
if (_fight.curFrame(faf, dir))
|
||||
return faf._anchor.x;
|
||||
|
||||
return _walk.anchorX(dir);
|
||||
}
|
||||
|
||||
int AnimSet::anchorY(const Direction &dir) {
|
||||
FightAnimFrame faf;
|
||||
if (_fight.curFrame(faf, dir))
|
||||
return faf._anchor.y;
|
||||
|
||||
return _walk.anchorY(dir);
|
||||
}
|
||||
|
||||
} // End of namespace Crab
|
||||
74
engines/crab/animation/animset.h
Normal file
74
engines/crab/animation/animset.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRAB_ANIMSET_H
|
||||
#define CRAB_ANIMSET_H
|
||||
|
||||
#include "crab/animation/fightmoves.h"
|
||||
#include "crab/animation/shadow.h"
|
||||
#include "crab/animation/walkframes.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
namespace pyrodactyl {
|
||||
namespace anim {
|
||||
// Container for all the possible animations an object can have
|
||||
struct AnimSet {
|
||||
// The frames relevant to fighting moves
|
||||
FightMoves _fight;
|
||||
|
||||
// The frames relevant to walking animations
|
||||
WalkFrames _walk;
|
||||
|
||||
// The bounding box of the character used for level collision
|
||||
Rect _bounds;
|
||||
|
||||
// The sprite shadow
|
||||
ShadowData _shadow;
|
||||
|
||||
// The camera focus point
|
||||
Vector2i _focus;
|
||||
|
||||
AnimSet() {}
|
||||
|
||||
void load(const Common::Path &filename);
|
||||
|
||||
TextureFlipType flip(const Direction &dir);
|
||||
const ShadowOffset &shadow(const Direction &dir);
|
||||
|
||||
int anchorX(const Direction &dir);
|
||||
int anchorY(const Direction &dir);
|
||||
};
|
||||
} // End of namespace anim
|
||||
} // End of namespace pyrodactyl
|
||||
|
||||
} // End of namespace Crab
|
||||
|
||||
#endif // CRAB_ANIMSET_H
|
||||
86
engines/crab/animation/fightanim.cpp
Normal file
86
engines/crab/animation/fightanim.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "crab/animation/fightanim.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
using namespace pyrodactyl::anim;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Load a single frame of a fighting move
|
||||
//------------------------------------------------------------------------
|
||||
void FightAnimFrame::load(rapidxml::xml_node<char> *node, const Rect &VBOX, const uint32 &rep, const int &AX, const int &AY) {
|
||||
AnimFrame::load(node, VBOX, rep, AX, AY);
|
||||
|
||||
if (nodeValid("box_d", node, false))
|
||||
_boxD.load(node->first_node("box_d"));
|
||||
|
||||
if (nodeValid("shift", node, false))
|
||||
_delta.load(node->first_node("shift"));
|
||||
|
||||
if (!loadNum(_state, "state", node, false))
|
||||
_state = 0;
|
||||
|
||||
loadBool(_branch, "branch", node, false);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Load a fighting move
|
||||
//------------------------------------------------------------------------
|
||||
void FightAnimFrames::load(rapidxml::xml_node<char> *node) {
|
||||
loadTextureFlipType(_flip, node);
|
||||
|
||||
if (!loadNum(_repeat, "repeat", node, false))
|
||||
_repeat = 0;
|
||||
|
||||
if (nodeValid("anchor", node, false))
|
||||
_anchor.load(node->first_node("anchor"));
|
||||
|
||||
if (nodeValid("box_v", node))
|
||||
_boxV.load(node->first_node("box_v"));
|
||||
|
||||
if (nodeValid("shadow", node)) {
|
||||
_shadow.load(node->first_node("shadow"));
|
||||
_shadow._valid = true;
|
||||
}
|
||||
|
||||
if (nodeValid("frames", node)) {
|
||||
_frame.clear();
|
||||
rapidxml::xml_node<char> *framenode = node->first_node("frames");
|
||||
for (auto n = framenode->first_node("frame"); n != nullptr; n = n->next_sibling("frame")) {
|
||||
FightAnimFrame faf;
|
||||
faf.load(n, _boxV, _repeat, _anchor.x, _anchor.y);
|
||||
_frame.push_back(faf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Crab
|
||||
110
engines/crab/animation/fightanim.h
Normal file
110
engines/crab/animation/fightanim.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRAB_FIGHTANIM_H
|
||||
#define CRAB_FIGHTANIM_H
|
||||
|
||||
#include "crab/ai/moveeffect.h"
|
||||
#include "crab/animation/fm_ai_data.h"
|
||||
#include "crab/input/fightinput.h"
|
||||
#include "crab/event/triggerset.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
namespace pyrodactyl {
|
||||
namespace anim {
|
||||
// A single frame of a fighting move
|
||||
struct FightAnimFrame : public AnimFrame {
|
||||
// The hit box of the player WITH RESPECT TO the sprite bounding box
|
||||
//boxV is the vulnerable hit box, boxD is the damage hit box
|
||||
Rect _boxD;
|
||||
|
||||
// The displacement in the position caused by the frame
|
||||
Vector2i _delta;
|
||||
|
||||
// The sprite state for the duration of the frame
|
||||
uint _state;
|
||||
|
||||
// Can we cancel/branch to another move from this frame?
|
||||
bool _branch;
|
||||
|
||||
FightAnimFrame() {
|
||||
_state = 0;
|
||||
_branch = false;
|
||||
}
|
||||
|
||||
void load(rapidxml::xml_node<char> *node, const Rect &VBOX,
|
||||
const uint32 &REP = 0, const int &AX = 0, const int &AY = 0);
|
||||
};
|
||||
|
||||
// All data related to a single fighting move in a single direction
|
||||
class FightAnimFrames {
|
||||
// The global vulnerable hit box for all the frames
|
||||
// If the W or H of this is 0, then use individual frame values
|
||||
Rect _boxV;
|
||||
|
||||
public:
|
||||
// The individual frames for each direction
|
||||
Common::Array<FightAnimFrame> _frame;
|
||||
|
||||
// The currentClip
|
||||
uint _currentClip;
|
||||
|
||||
// Should we flip the images in the frame rectangle?
|
||||
TextureFlipType _flip;
|
||||
|
||||
// The amount of time in milliseconds each animation frame needs to be on screen
|
||||
// If this is zero then use the value in each individual frame
|
||||
uint32 _repeat;
|
||||
|
||||
// The global anchor value for all the frames
|
||||
// If this is 0, then use individual frame values
|
||||
Vector2i _anchor;
|
||||
|
||||
// Does this set of animation frames need a specific shadow offset?
|
||||
ShadowOffset _shadow;
|
||||
|
||||
FightAnimFrames() {
|
||||
reset();
|
||||
_flip = FLIP_NONE;
|
||||
_repeat = 0;
|
||||
}
|
||||
void reset() {
|
||||
_currentClip = 0;
|
||||
}
|
||||
|
||||
void load(rapidxml::xml_node<char> *node);
|
||||
};
|
||||
} // End of namespace anim
|
||||
} // End of namespace pyrodactyl
|
||||
|
||||
} // End of namespace Crab
|
||||
|
||||
#endif // CRAB_FIGHTANIM_H
|
||||
56
engines/crab/animation/fightmove.cpp
Normal file
56
engines/crab/animation/fightmove.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "crab/animation/fightmove.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
using namespace pyrodactyl::anim;
|
||||
|
||||
void FightMove::load(rapidxml::xml_node<char> *node) {
|
||||
_frames[DIRECTION_DOWN].load(node->first_node("down"));
|
||||
_frames[DIRECTION_UP].load(node->first_node("up"));
|
||||
_frames[DIRECTION_LEFT].load(node->first_node("left"));
|
||||
_frames[DIRECTION_RIGHT].load(node->first_node("right"));
|
||||
|
||||
if (nodeValid("input", node))
|
||||
_input.load(node->first_node("input"));
|
||||
|
||||
if (nodeValid("unlock", node, false))
|
||||
_unlock.load(node->first_node("unlock"));
|
||||
|
||||
if (nodeValid("effect", node))
|
||||
_eff.load(node->first_node("effect"));
|
||||
|
||||
if (nodeValid("ai", node, false))
|
||||
_ai.load(node->first_node("ai"));
|
||||
}
|
||||
|
||||
} // End of namespace Crab
|
||||
67
engines/crab/animation/fightmove.h
Normal file
67
engines/crab/animation/fightmove.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRAB_FIGHTMOVE_H
|
||||
#define CRAB_FIGHTMOVE_H
|
||||
|
||||
#include "crab/animation/fightanim.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
namespace pyrodactyl {
|
||||
namespace anim {
|
||||
// All info for a single fighting move in all four directions
|
||||
struct FightMove {
|
||||
// Frames for all four directions
|
||||
FightAnimFrames _frames[DIRECTION_TOTAL];
|
||||
|
||||
// The input required
|
||||
pyrodactyl::input::FightInput _input;
|
||||
|
||||
// The conditions to unlock this move for player use
|
||||
pyrodactyl::event::TriggerSet _unlock;
|
||||
|
||||
// The effects of this move - hurt animation, sound effect and so on
|
||||
FightMoveEffect _eff;
|
||||
|
||||
// The data needed by an AI sprite to execute this move
|
||||
FightMoveAIData _ai;
|
||||
|
||||
FightMove() {}
|
||||
~FightMove() {}
|
||||
|
||||
void load(rapidxml::xml_node<char> *node);
|
||||
};
|
||||
} // End of namespace anim
|
||||
} // End of namespace pyrodactyl
|
||||
|
||||
} // End of namespace Crab
|
||||
|
||||
#endif // CRAB_FIGHTMOVE_H
|
||||
201
engines/crab/animation/fightmoves.cpp
Normal file
201
engines/crab/animation/fightmoves.cpp
Normal file
@@ -0,0 +1,201 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "crab/animation/fightmoves.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
using namespace pyrodactyl::anim;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//------------------------------------------------------------------------
|
||||
FightMoves::FightMoves() {
|
||||
_cur = -1;
|
||||
_next = -1;
|
||||
_start = false;
|
||||
|
||||
_frameCur = 0;
|
||||
_frameTotal = 0;
|
||||
|
||||
_move.clear();
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Load from file
|
||||
//------------------------------------------------------------------------
|
||||
void FightMoves::load(rapidxml::xml_node<char> *node) {
|
||||
for (auto n = node->first_node("move"); n != nullptr; n = n->next_sibling("move")) {
|
||||
FightMove fm;
|
||||
fm.load(n);
|
||||
_move.push_back(fm);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Return current or next move
|
||||
//------------------------------------------------------------------------
|
||||
bool FightMoves::curMove(FightMove &fm) {
|
||||
if (_cur >= 0 && (uint)_cur < _move.size()) {
|
||||
fm = _move[_cur];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FightMoves::nextMove(FightMove &fm) {
|
||||
if (_next >= 0 && (uint)_next < _move.size()) {
|
||||
fm = _move[_next];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Get the current frame of the sprite
|
||||
//------------------------------------------------------------------------
|
||||
bool FightMoves::curFrame(FightAnimFrame &faf, const Direction &d) {
|
||||
// Check validity of current move
|
||||
if (_cur >= 0 && (uint)_cur < _move.size()) {
|
||||
// Check validity of current frame
|
||||
if (_frameCur < _frameTotal && _frameCur < _move[_cur]._frames[d]._frame.size()) {
|
||||
faf = _move[_cur]._frames[d]._frame[_frameCur];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Update frame
|
||||
//------------------------------------------------------------------------
|
||||
FrameUpdateResult FightMoves::updateFrame(const Direction &d) {
|
||||
// Check validity of current move
|
||||
if (_cur >= 0 && (uint)_cur < _move.size()) {
|
||||
// Check validity of current frame
|
||||
if (_frameCur < _frameTotal && _frameCur < _move[_cur]._frames[d]._frame.size()) {
|
||||
// Has the current frame finished playing?
|
||||
// OR Is this the first frame of the move?
|
||||
if (_timer.ticks() >= _move[_cur]._frames[d]._frame[_frameCur]._repeat || _start) {
|
||||
_frameCur++;
|
||||
_timer.start();
|
||||
_start = false;
|
||||
|
||||
return FUR_SUCCESS;
|
||||
} else
|
||||
return FUR_WAIT;
|
||||
}
|
||||
}
|
||||
|
||||
return FUR_FAIL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Find a move corresponding to the input and sprite state
|
||||
//------------------------------------------------------------------------
|
||||
uint FightMoves::findMove(const pyrodactyl::input::FightAnimationType &type, const int &state) {
|
||||
uint pos = 0;
|
||||
for (auto i = _move.begin(); i != _move.end(); ++i, ++pos)
|
||||
if (i->_input._type == type && i->_input._state == (uint)state)
|
||||
return pos;
|
||||
|
||||
pos = 0;
|
||||
for (auto i = _move.begin(); i != _move.end(); ++i, ++pos)
|
||||
if (i->_input._type == type && i->_input._state == SPRITE_STATE_OVERRIDE)
|
||||
return pos;
|
||||
|
||||
return SPRITE_STATE_OVERRIDE;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Function for AI
|
||||
//------------------------------------------------------------------------
|
||||
void FightMoves::listAttackMoves(Common::Array<uint> &list) {
|
||||
list.clear();
|
||||
uint pos = 0;
|
||||
for (auto i = _move.begin(); i != _move.end(); ++i, ++pos)
|
||||
if (i->_ai._type == MOVE_ATTACK)
|
||||
list.push_back(pos);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Force update to a new move
|
||||
//------------------------------------------------------------------------
|
||||
bool FightMoves::forceUpdate(const uint &index, pyrodactyl::input::FightInput &input, const Direction &d) {
|
||||
_frameCur = 0;
|
||||
_cur = index;
|
||||
|
||||
if ((uint)_cur < _move.size()) {
|
||||
if (_move[_cur]._unlock.result()) {
|
||||
_frameTotal = _move[_cur]._frames[d]._frame.size();
|
||||
if (_frameTotal > 0) {
|
||||
input = _move[_cur]._input;
|
||||
input._state = _move[_cur]._frames[d]._frame[0]._state;
|
||||
} else
|
||||
input.reset();
|
||||
|
||||
_timer.start();
|
||||
_start = true;
|
||||
g_engine->_musicManager->playEffect(_move[_cur]._eff._activate, 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
_cur = 0;
|
||||
_frameTotal = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Set unlock status
|
||||
//------------------------------------------------------------------------
|
||||
void FightMoves::evaluate(pyrodactyl::event::Info &info) {
|
||||
for (auto &i : _move)
|
||||
i._unlock.evaluate(info);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Find which style to flip the texture in
|
||||
//------------------------------------------------------------------------
|
||||
bool FightMoves::flip(TextureFlipType &flip, Direction d) {
|
||||
// Check validity of current move
|
||||
if (validMove()) {
|
||||
flip = _move[_cur]._frames[d]._flip;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Crab
|
||||
133
engines/crab/animation/fightmoves.h
Normal file
133
engines/crab/animation/fightmoves.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRAB_FIGHTMOVES_H
|
||||
#define CRAB_FIGHTMOVES_H
|
||||
|
||||
#include "crab/timer.h"
|
||||
#include "crab/animation/fightmove.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
namespace pyrodactyl {
|
||||
namespace anim {
|
||||
enum FrameUpdateResult {
|
||||
FUR_FAIL,
|
||||
FUR_WAIT,
|
||||
FUR_SUCCESS
|
||||
};
|
||||
|
||||
// This state value indicates that the move should execute regardless of actual sprite state
|
||||
const uint SPRITE_STATE_OVERRIDE = std::numeric_limits<uint>::max();
|
||||
|
||||
class FightMoves {
|
||||
// The fighting moves of a sprite
|
||||
Common::Array<FightMove> _move;
|
||||
|
||||
// The currently selected move
|
||||
int _cur;
|
||||
|
||||
// For AI - the move about to be executed
|
||||
int _next;
|
||||
|
||||
// The timer used for playing animations
|
||||
Timer _timer;
|
||||
|
||||
// We need to instantly show the new frame for a move that has started
|
||||
bool _start;
|
||||
|
||||
// The current frame and total frames
|
||||
uint _frameCur, _frameTotal;
|
||||
|
||||
public:
|
||||
FightMoves();
|
||||
|
||||
~FightMoves() {}
|
||||
|
||||
void reset() {
|
||||
_cur = -1;
|
||||
}
|
||||
|
||||
void load(rapidxml::xml_node<char> *node);
|
||||
|
||||
bool curMove(FightMove &fm);
|
||||
bool nextMove(FightMove &fm);
|
||||
|
||||
FrameUpdateResult updateFrame(const Direction &d);
|
||||
bool curFrame(FightAnimFrame &faf, const Direction &d);
|
||||
|
||||
uint findMove(const pyrodactyl::input::FightAnimationType &type, const int &state);
|
||||
|
||||
void listAttackMoves(Common::Array<uint> &list);
|
||||
|
||||
bool forceUpdate(const uint &index, pyrodactyl::input::FightInput &input, const Direction &d);
|
||||
|
||||
bool lastFrame() {
|
||||
return _frameCur >= _frameTotal;
|
||||
}
|
||||
|
||||
void frameIndex(uint val) {
|
||||
_frameCur = val;
|
||||
}
|
||||
|
||||
void curCombo(pyrodactyl::input::FightInput &input) {
|
||||
input = _move[_cur]._input;
|
||||
}
|
||||
|
||||
bool validMove() {
|
||||
return _cur >= 0 && (uint)_cur < _move.size();
|
||||
}
|
||||
|
||||
bool empty() {
|
||||
return _move.empty();
|
||||
}
|
||||
|
||||
bool flip(TextureFlipType &flip, Direction d);
|
||||
|
||||
const ShadowOffset &shadow(Direction d) {
|
||||
return _move[_cur]._frames[d]._shadow;
|
||||
}
|
||||
|
||||
void next(int val) {
|
||||
_next = val;
|
||||
}
|
||||
|
||||
int next() {
|
||||
return _next;
|
||||
}
|
||||
|
||||
void evaluate(pyrodactyl::event::Info &info);
|
||||
};
|
||||
} // End of namespace anim
|
||||
} // End of namespace pyrodactyl
|
||||
|
||||
} // End of namespace Crab
|
||||
|
||||
#endif // CRAB_FIGHTMOVES_H
|
||||
82
engines/crab/animation/fm_ai_data.h
Normal file
82
engines/crab/animation/fm_ai_data.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRAB_FM_AI_DATA_H
|
||||
#define CRAB_FM_AI_DATA_H
|
||||
|
||||
#include "crab/animation/range.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
namespace pyrodactyl {
|
||||
namespace anim {
|
||||
enum AIMoveType {
|
||||
MOVE_NONE, // AI sprites do not use this move
|
||||
MOVE_ATTACK, // AI sprites use this move to attack you
|
||||
MOVE_DEFEND // AI sprites use this move to dodge or defend
|
||||
};
|
||||
|
||||
struct FightMoveAIData {
|
||||
// Can this move be used by AI to attack
|
||||
AIMoveType _type;
|
||||
|
||||
// The range of the move
|
||||
Range _range;
|
||||
|
||||
// The AI delays executing the move by this long
|
||||
uint _delay;
|
||||
|
||||
FightMoveAIData() {
|
||||
_type = MOVE_NONE;
|
||||
_delay = 0;
|
||||
}
|
||||
|
||||
void load(rapidxml::xml_node<char> *node) {
|
||||
if (!loadNum(_delay, "delay", node, false))
|
||||
_delay = 0;
|
||||
|
||||
_range.load(node->first_node("range"));
|
||||
|
||||
Common::String str;
|
||||
loadStr(str, "type", node, false);
|
||||
if (str == "attack")
|
||||
_type = MOVE_ATTACK;
|
||||
else if (str == "defend")
|
||||
_type = MOVE_DEFEND;
|
||||
else
|
||||
_type = MOVE_NONE;
|
||||
}
|
||||
};
|
||||
} // End of namespace anim
|
||||
} // End of namespace pyrodactyl
|
||||
|
||||
} // End of namespace Crab
|
||||
|
||||
#endif // CRAB_FM_AI_DATA_H
|
||||
51
engines/crab/animation/imageeffect.cpp
Normal file
51
engines/crab/animation/imageeffect.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "crab/crab.h"
|
||||
#include "crab/animation/imageeffect.h"
|
||||
#include "crab/image/ImageManager.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
using namespace pyrodactyl::anim;
|
||||
|
||||
void ImageEffect::load(rapidxml::xml_node<char> *node) {
|
||||
if (nodeValid(node, false)) {
|
||||
if (loadImgKey(_img, "img", node) && loadXY(x, y, node))
|
||||
_visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ImageEffect::draw(const int &xOffset, const int &yOffset) {
|
||||
if (_visible)
|
||||
g_engine->_imageManager->draw(x + xOffset, y + yOffset, _img);
|
||||
}
|
||||
|
||||
} // End of namespace Crab
|
||||
57
engines/crab/animation/imageeffect.h
Normal file
57
engines/crab/animation/imageeffect.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRAB_IMAGEEFFECT_H
|
||||
#define CRAB_IMAGEEFFECT_H
|
||||
|
||||
#include "crab/image/ImageManager.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
namespace pyrodactyl {
|
||||
namespace anim {
|
||||
struct ImageEffect : public Vector2i {
|
||||
ImageKey _img;
|
||||
bool _visible;
|
||||
|
||||
ImageEffect() {
|
||||
_visible = false;
|
||||
_img = 0;
|
||||
}
|
||||
|
||||
void load(rapidxml::xml_node<char> *node);
|
||||
void draw(const int &xOffset, const int &yOffset);
|
||||
};
|
||||
} // End of namespace anim
|
||||
} // End of namespace pyrodactyl
|
||||
|
||||
} // End of namespace Crab
|
||||
|
||||
#endif // CRAB_IMAGEEFFECT_H
|
||||
65
engines/crab/animation/range.h
Normal file
65
engines/crab/animation/range.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRAB_RANGE_H
|
||||
#define CRAB_RANGE_H
|
||||
|
||||
#include "crab/animation/animframe.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
namespace pyrodactyl {
|
||||
namespace anim {
|
||||
struct Range {
|
||||
bool _valid;
|
||||
Rect _val[DIRECTION_TOTAL];
|
||||
|
||||
Range() {
|
||||
_valid = false;
|
||||
}
|
||||
|
||||
void load(rapidxml::xml_node<char> *node) {
|
||||
if (nodeValid(node, false)) {
|
||||
_val[DIRECTION_DOWN].load(node->first_node("down"));
|
||||
_val[DIRECTION_UP].load(node->first_node("up"));
|
||||
_val[DIRECTION_LEFT].load(node->first_node("left"));
|
||||
_val[DIRECTION_RIGHT].load(node->first_node("right"));
|
||||
|
||||
_valid = true;
|
||||
} else
|
||||
_valid = false;
|
||||
}
|
||||
};
|
||||
} // End of namespace anim
|
||||
} // End of namespace pyrodactyl
|
||||
|
||||
} // End of namespace Crab
|
||||
|
||||
#endif // CRAB_RANGE_H
|
||||
83
engines/crab/animation/shadow.h
Normal file
83
engines/crab/animation/shadow.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRAB_SHADOW_H
|
||||
#define CRAB_SHADOW_H
|
||||
|
||||
#include "crab/crab.h"
|
||||
#include "crab/vectors.h"
|
||||
#include "crab/image/ImageManager.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
namespace pyrodactyl {
|
||||
namespace anim {
|
||||
struct ShadowData {
|
||||
// The image of the sprite's shadow
|
||||
ImageKey _img;
|
||||
|
||||
// Size of image
|
||||
Vector2i _size;
|
||||
|
||||
// The default shadow offset
|
||||
Vector2i _offset;
|
||||
|
||||
ShadowData() : _size(1, 1) {
|
||||
_img = 0;
|
||||
}
|
||||
|
||||
void load(rapidxml::xml_node<char> *node) {
|
||||
loadImgKey(_img, "img", node);
|
||||
_offset.load(node);
|
||||
|
||||
using namespace pyrodactyl::image;
|
||||
Image dat;
|
||||
g_engine->_imageManager->getTexture(_img, dat);
|
||||
_size.x = dat.w() / 2;
|
||||
_size.y = dat.h() / 2;
|
||||
}
|
||||
};
|
||||
|
||||
// Used when a set of animation frames needs a specific shadow offset
|
||||
class ShadowOffset : public Vector2i {
|
||||
public:
|
||||
// Only use this offset if this is true
|
||||
bool _valid;
|
||||
|
||||
ShadowOffset() {
|
||||
_valid = false;
|
||||
}
|
||||
};
|
||||
} // End of namespace anim
|
||||
} // End of namespace pyrodactyl
|
||||
|
||||
} // End of namespace Crab
|
||||
|
||||
#endif // CRAB_SHADOW_H
|
||||
668
engines/crab/animation/sprite.cpp
Normal file
668
engines/crab/animation/sprite.cpp
Normal file
@@ -0,0 +1,668 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "crab/animation/sprite.h"
|
||||
#include "crab/input/cursor.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
using namespace pyrodactyl::ai;
|
||||
using namespace pyrodactyl::anim;
|
||||
using namespace pyrodactyl::input;
|
||||
using namespace pyrodactyl::event;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//------------------------------------------------------------------------
|
||||
Sprite::Sprite() : _imgSize(1, 1), _velMod(1.0f, 1.0f) {
|
||||
_dir = DIRECTION_LEFT;
|
||||
_layer = -1;
|
||||
_image = 0;
|
||||
visible(true);
|
||||
_damageDone = false;
|
||||
_hover = false;
|
||||
// _pathing.SetSprite(this);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Load sprite from XML and animations from the index of all animation files
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::load(rapidxml::xml_node<char> *node, Common::Array<Common::Path> &animations) {
|
||||
using namespace pyrodactyl::image;
|
||||
|
||||
if (nodeValid(node)) {
|
||||
loadStr(_id, "id", node);
|
||||
|
||||
// The amount by which the sprite x,y should be multiplied
|
||||
int multiply = 1;
|
||||
loadNum(multiply, "multiply", node, false);
|
||||
|
||||
loadNum(_pos.x, "x", node);
|
||||
loadNum(_pos.y, "y", node);
|
||||
|
||||
_pos.x *= multiply;
|
||||
_pos.y *= multiply;
|
||||
|
||||
loadImgKey(_image, "img", node);
|
||||
loadNum(_layer, "layer", node, false);
|
||||
|
||||
Image dat;
|
||||
g_engine->_imageManager->getTexture(_image, dat);
|
||||
_imgSize.x = dat.w();
|
||||
_imgSize.y = dat.h();
|
||||
|
||||
uint index = 0;
|
||||
loadNum(index, "moveset", node);
|
||||
|
||||
if (index < animations.size())
|
||||
_animSet.load(animations[index]);
|
||||
|
||||
_animSet._fight.listAttackMoves(_aiData._fight._attack);
|
||||
|
||||
loadDirection(_dir, node);
|
||||
_clip = _animSet._walk.clip(_dir);
|
||||
_boxV = _animSet._walk.boxV(_dir);
|
||||
|
||||
if (nodeValid("visible", node, false))
|
||||
_visible.load(node->first_node("visible"));
|
||||
|
||||
if (nodeValid("movement", node, false))
|
||||
_aiData._walk.load(node->first_node("movement"));
|
||||
|
||||
if (nodeValid("popup", node, false))
|
||||
_popup.load(node->first_node("popup"));
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Move along x and y axis
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::move(const SpriteConstant &sc) {
|
||||
if (_target.x == 0.0f && (_vel.x > -sc._tweening && _vel.x < sc._tweening))
|
||||
_vel.x = 0.0f;
|
||||
else {
|
||||
_vel.x += (_target.x - _vel.x) * sc._tweening;
|
||||
_pos.x += _vel.x;
|
||||
}
|
||||
|
||||
if (_target.y == 0.0f && (_vel.y > -sc._tweening && _vel.y < sc._tweening))
|
||||
_vel.y = 0.0f;
|
||||
else {
|
||||
_vel.y += (_target.y - _vel.y) * sc._tweening;
|
||||
_pos.y += _vel.y;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Resolve collision with shapes excluding the level bounding rectangle
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::resolveCollide() {
|
||||
// NOTE: we don't check i->intersect here because we do that in the level functions
|
||||
for (const auto &i : _collideData) {
|
||||
Rect bounds = boundRect();
|
||||
if (i._type == SHAPE_POLYGON) {
|
||||
_pos.x -= i._data.x;
|
||||
_pos.y -= i._data.y;
|
||||
} else {
|
||||
Direction d = bounds.resolveY(i._data);
|
||||
if (d == DIRECTION_UP)
|
||||
_pos.y -= i._data.y + i._data.h - _animSet._bounds.y + _animSet.anchorY(_dir) + 1;
|
||||
else if (d == DIRECTION_DOWN)
|
||||
_pos.y -= i._data.y - bounds.h - _animSet._bounds.y + _animSet.anchorY(_dir) - 1;
|
||||
|
||||
d = bounds.resolveX(i._data);
|
||||
if (d == DIRECTION_LEFT)
|
||||
_pos.x -= i._data.x + i._data.w - _animSet._bounds.x + _animSet.anchorX(_dir) + 1;
|
||||
else if (d == DIRECTION_RIGHT)
|
||||
_pos.x -= i._data.x - bounds.w - _animSet._bounds.x + _animSet.anchorX(_dir) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the collision data
|
||||
_collideData.clear();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Resolve collision with the level bounding rectangle
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::resolveInside(Rect collider) {
|
||||
Rect bounds = boundRect();
|
||||
Direction d = bounds.resolveX(collider);
|
||||
|
||||
if (d == DIRECTION_RIGHT)
|
||||
_pos.x = collider.x - _animSet._bounds.x + _animSet.anchorX(_dir) + 1;
|
||||
else if (d == DIRECTION_LEFT)
|
||||
_pos.x = collider.x + collider.w - _animSet._bounds.x - bounds.w + _animSet.anchorX(_dir) - 1;
|
||||
|
||||
bounds = boundRect();
|
||||
d = bounds.resolveY(collider);
|
||||
|
||||
if (d == DIRECTION_DOWN)
|
||||
_pos.y = collider.y - _animSet._bounds.y + _animSet.anchorY(_dir) + 1;
|
||||
else if (d == DIRECTION_UP)
|
||||
_pos.y = collider.y + collider.h - _animSet._bounds.y - bounds.h + _animSet.anchorY(_dir) - 1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Various rectangles of the sprite
|
||||
// Note: Every sprite in the game uses bottom center coordinates:
|
||||
// draw_x = x - clip.w/2, draw_y = y - clip.h
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
// Used for walking and level geometry collision
|
||||
Rect Sprite::boundRect() {
|
||||
Rect rect;
|
||||
rect.x = _pos.x + _animSet._bounds.x - _animSet.anchorX(_dir);
|
||||
rect.y = _pos.y + _animSet._bounds.y - _animSet.anchorY(_dir);
|
||||
rect.w = _animSet._bounds.w;
|
||||
rect.h = _animSet._bounds.h;
|
||||
return rect;
|
||||
}
|
||||
|
||||
// Used for fighting
|
||||
Rect Sprite::boxV() {
|
||||
Rect rect;
|
||||
rect.x = _pos.x + _boxV.x;
|
||||
rect.y = _pos.y + _boxV.y;
|
||||
rect.w = _boxV.w;
|
||||
rect.h = _boxV.h;
|
||||
return rect;
|
||||
}
|
||||
|
||||
// Used for fighting
|
||||
Rect Sprite::boxD() {
|
||||
Rect rect;
|
||||
rect.x = _pos.x + _boxD.x;
|
||||
rect.y = _pos.y + _boxD.y;
|
||||
rect.w = _boxD.w;
|
||||
rect.h = _boxD.h;
|
||||
return rect;
|
||||
}
|
||||
|
||||
// Used for drawing object notifications over stuff
|
||||
Rect Sprite::posRect() {
|
||||
Rect rect;
|
||||
rect.x = _pos.x - _animSet.anchorX(_dir);
|
||||
rect.y = _pos.y - _animSet.anchorY(_dir);
|
||||
rect.w = _clip.w;
|
||||
rect.h = _clip.h;
|
||||
return rect;
|
||||
}
|
||||
|
||||
// The range rectangle is relative to the bounding rectangle, and needs to be updated according to the actual position
|
||||
// Used for enemy sprite to find their required spot to attack the player
|
||||
Rect Sprite::rangeRect(const Rect &bounds, const Range &range) {
|
||||
Rect rect;
|
||||
rect.x = bounds.x + range._val[_dir].x;
|
||||
rect.y = bounds.y + range._val[_dir].y;
|
||||
rect.w = range._val[_dir].w;
|
||||
rect.h = range._val[_dir].h;
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
// Used for focusing the camera on the sprite
|
||||
Vector2i Sprite::camFocus() {
|
||||
Vector2i v;
|
||||
v.x = _pos.x + _animSet._focus.x;
|
||||
v.y = _pos.y + _animSet._focus.y;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Draw the sprite
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::draw(pyrodactyl::event::Info &info, const Rect &camera) {
|
||||
using namespace pyrodactyl::image;
|
||||
using namespace pyrodactyl::text;
|
||||
|
||||
int x = _pos.x - camera.x - _animSet.anchorX(_dir), y = _pos.y - camera.y - _animSet.anchorY(_dir);
|
||||
|
||||
// Draw the shadow image relative to the bottom center of the sprite
|
||||
ShadowOffset sh = _animSet.shadow(_dir);
|
||||
if (sh._valid) {
|
||||
// Draw using custom offset
|
||||
g_engine->_imageManager->draw(x + _clip.w / 2 - _animSet._shadow._size.x + sh.x,
|
||||
y + _clip.h - _animSet._shadow._size.y + sh.y,
|
||||
_animSet._shadow._img);
|
||||
} else {
|
||||
// Draw using default offset
|
||||
g_engine->_imageManager->draw(x + _clip.w / 2 - _animSet._shadow._size.x + _animSet._shadow._offset.x,
|
||||
y + _clip.h - _animSet._shadow._size.y + _animSet._shadow._offset.y,
|
||||
_animSet._shadow._img);
|
||||
}
|
||||
|
||||
g_engine->_imageManager->draw(x, y, _image, &_clip, _animSet.flip(_dir));
|
||||
_imgEff.draw(x, y);
|
||||
|
||||
if (g_engine->_debugDraw & DRAW_SPRITE_BOUNDS) {
|
||||
// Nice boxes for the frames and boxV, boxD
|
||||
Rect bounds = boundRect(), vul = boxV(), dmg = boxD(), debugpos = posRect();
|
||||
bounds.draw(-camera.x, -camera.y);
|
||||
debugpos.draw(-camera.x, -camera.y, 255, 255, 255);
|
||||
dmg.draw(-camera.x, -camera.y, 255, 0, 0);
|
||||
vul.draw(-camera.x, -camera.y, 0, 0, 255);
|
||||
|
||||
FightMove fm;
|
||||
if (_animSet._fight.nextMove(fm)) {
|
||||
Rect actualRange;
|
||||
actualRange.x = bounds.x + fm._ai._range._val[_dir].x;
|
||||
actualRange.y = bounds.y + fm._ai._range._val[_dir].y;
|
||||
actualRange.w = fm._ai._range._val[_dir].w;
|
||||
actualRange.h = fm._ai._range._val[_dir].h;
|
||||
|
||||
actualRange.draw(-camera.x, -camera.y, 255, 0, 255);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_engine->_debugDraw & DRAW_PATHING) {
|
||||
for (const auto &iter : _pathing._vSolution) {
|
||||
bool nextToWall = false;
|
||||
for (const auto &neighbor : iter->_neighborNodes) {
|
||||
if (neighbor->getMovementCost() < 0 || neighbor->getMovementCost() > 1) {
|
||||
nextToWall = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nextToWall)
|
||||
iter->getRect().draw(-camera.x, -camera.y, 0, 0, 0, 254);
|
||||
else
|
||||
iter->getRect().draw(-camera.x, -camera.y, 200, 200, 0, 254);
|
||||
}
|
||||
|
||||
if (_pathing._goalTile && _pathing._startTile) {
|
||||
_pathing._goalTile->getRect().draw(-camera.x, -camera.y, 0, 0, 200, 254);
|
||||
_pathing._startTile->getRect().draw(-camera.x, -camera.y, 0, 200, 0, 254);
|
||||
}
|
||||
|
||||
Rect destinationRect = Rect((int)_pathing._destination.x - 5,
|
||||
(int)_pathing._destination.y - 5,
|
||||
10,
|
||||
10);
|
||||
destinationRect.draw(-camera.x, -camera.y, 0, 200, 0, 254);
|
||||
}
|
||||
}
|
||||
|
||||
void Sprite::drawPopup(pyrodactyl::ui::ParagraphData &pop, const Rect &camera) {
|
||||
// This is different from draw because we draw the popup centered over the head
|
||||
int x = _pos.x - camera.x - _animSet.anchorX(_dir) + (_animSet._bounds.w / 2);
|
||||
int y = _pos.y - camera.y - _animSet.anchorY(_dir);
|
||||
|
||||
_popup.draw(x, y, pop, camera);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Handle the movement in a level for the player only
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::handleEvents(Info &info, const Rect &camera, const SpriteConstant &sc, const Common::Event &event) {
|
||||
|
||||
int num = 0;
|
||||
info.statGet(_id, pyrodactyl::stat::STAT_SPEED, num);
|
||||
++num;
|
||||
float playerSpeed = static_cast<float>(num);
|
||||
|
||||
// This is for Diablo style hold-mouse-button-in-direction-of-movement
|
||||
// This is only used if - point and click movement isn't being used, cursor is not inside the hud, the cursor is a normal cursor and the mouse is pressed
|
||||
if (!_aiData._dest._active && !g_engine->_mouse->_insideHud && !g_engine->_mouse->_hover && g_engine->_mouse->pressed()) {
|
||||
// To find where the click is w.r.t sprite, we need to see where it is being drawn
|
||||
int x = _pos.x - camera.x - _animSet.anchorX(_dir), y = _pos.y - camera.y - _animSet.anchorY(_dir);
|
||||
|
||||
// Just use the bound rectangle dimensions
|
||||
Rect b = boundRect();
|
||||
int w = b.w, h = b.h;
|
||||
|
||||
// X axis
|
||||
if (g_engine->_mouse->_motion.x > x + w)
|
||||
xVel(playerSpeed * sc._walkVelMod.x);
|
||||
else if (g_engine->_mouse->_motion.x < x)
|
||||
xVel(-playerSpeed * sc._walkVelMod.x);
|
||||
else
|
||||
xVel(0.0f);
|
||||
|
||||
// Y axis
|
||||
if (g_engine->_mouse->_motion.y > y + h)
|
||||
yVel(playerSpeed * sc._walkVelMod.y);
|
||||
else if (g_engine->_mouse->_motion.y < y)
|
||||
yVel(-playerSpeed * sc._walkVelMod.y);
|
||||
else
|
||||
yVel(0.0f);
|
||||
} else { // Keyboard movement
|
||||
// Disable destination as soon as player presses a direction key
|
||||
// X axis
|
||||
if (g_engine->_inputManager->state(IG_LEFT)) {
|
||||
_aiData._dest._active = false;
|
||||
xVel(-playerSpeed * sc._walkVelMod.x);
|
||||
} else if (g_engine->_inputManager->state(IG_RIGHT)) {
|
||||
_aiData._dest._active = false;
|
||||
xVel(playerSpeed * sc._walkVelMod.x);
|
||||
} else if (!_aiData._dest._active)
|
||||
xVel(0.0f);
|
||||
|
||||
// Y axis
|
||||
if (g_engine->_inputManager->state(IG_UP)) {
|
||||
_aiData._dest._active = false;
|
||||
yVel(-playerSpeed * sc._walkVelMod.y);
|
||||
} else if (g_engine->_inputManager->state(IG_DOWN)) {
|
||||
_aiData._dest._active = false;
|
||||
yVel(playerSpeed * sc._walkVelMod.y);
|
||||
} else if (!_aiData._dest._active)
|
||||
yVel(0.0f);
|
||||
|
||||
}
|
||||
|
||||
updateMove(_input.handleEvents(event));
|
||||
|
||||
// This is to prevent one frame of drawing with incorrect parameters
|
||||
animate(info);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Set destination for sprite movement
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::setDestPathfinding(const Vector2i &dest, bool reachable) {
|
||||
_aiData.dest(dest, true);
|
||||
_pathing.setDestination(dest, reachable);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Walking animation
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::walk(const pyrodactyl::people::PersonState &pst) {
|
||||
_imgEff._visible = false;
|
||||
|
||||
bool firstX = true;
|
||||
|
||||
if (_aiData._dest._active) {
|
||||
Rect b = boundRect();
|
||||
if (_pos.x - _aiData._dest.x > -b.w && _pos.x - _aiData._dest.x < b.w)
|
||||
firstX = false;
|
||||
}
|
||||
|
||||
bool reset = _animSet._walk.type(_vel, _dir, pst, firstX);
|
||||
|
||||
if (reset)
|
||||
_animSet._walk.resetClip(_dir);
|
||||
|
||||
walk(reset);
|
||||
}
|
||||
|
||||
void Sprite::walk(const bool &reset) {
|
||||
if (_animSet._walk.updateClip(_dir, reset)) {
|
||||
_clip = _animSet._walk.clip(_dir);
|
||||
_boxV = _animSet._walk.boxV(_dir);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Decide which animation to play
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::animate(Info &info) {
|
||||
if (_input.idle())
|
||||
walk(info.state(_id));
|
||||
else
|
||||
updateFrame(info.state(_id));
|
||||
}
|
||||
|
||||
void Sprite::animate(const pyrodactyl::people::PersonState &pst) {
|
||||
walk(pst);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: We need to find if the vulnerable area of this sprite collides
|
||||
// with hitbox (usually the damage area of another sprite)
|
||||
//------------------------------------------------------------------------
|
||||
bool Sprite::fightCollide(Rect hitbox, Rect enemyBounds, Range &range, const SpriteConstant &sc) {
|
||||
Rect bounds = boundRect();
|
||||
|
||||
if (range._valid) {
|
||||
Rect actualRange = rangeRect(bounds, range);
|
||||
|
||||
// The second part is a sanity check so the stray hitbox of a sprite 1000 pixels below does not cause damage
|
||||
if (hitbox.collide(actualRange) && abs(bounds.y + bounds.h - enemyBounds.y - enemyBounds.h) < sc._planeW)
|
||||
return true;
|
||||
} else {
|
||||
if (hitbox.collide(bounds) && abs(bounds.y + bounds.h - enemyBounds.y - enemyBounds.h) < sc._planeW)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Update the frame info of the sprite
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::updateFrame(const pyrodactyl::people::PersonState &pst, const bool &repeat) {
|
||||
FrameUpdateResult res = _animSet._fight.updateFrame(_dir);
|
||||
if (res == FUR_SUCCESS) {
|
||||
assignFrame();
|
||||
} else if (res == FUR_FAIL) {
|
||||
_damageDone = false;
|
||||
stop();
|
||||
|
||||
if (repeat == false)
|
||||
resetFrame(pst);
|
||||
else
|
||||
_animSet._fight.frameIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Sprite::assignFrame() {
|
||||
FightAnimFrame faf;
|
||||
if (_animSet._fight.curFrame(faf, _dir)) {
|
||||
_clip = faf._clip;
|
||||
boxV(faf._boxV);
|
||||
boxD(faf._boxD);
|
||||
|
||||
_pos.x += faf._delta.x;
|
||||
_pos.y += faf._delta.y;
|
||||
|
||||
_input._state = faf._state;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Update the move info of the player sprite
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::updateMove(const FightAnimationType &combo) {
|
||||
if (combo != FA_IDLE) {
|
||||
if (_input.idle())
|
||||
forceUpdateMove(combo);
|
||||
else {
|
||||
FightAnimFrame faf;
|
||||
if (_animSet._fight.curFrame(faf, _dir))
|
||||
if (faf._branch)
|
||||
forceUpdateMove(combo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sprite::forceUpdateMove(const FightAnimationType &combo) {
|
||||
uint index = _animSet._fight.findMove(combo, _input._state);
|
||||
forceUpdateMove(index);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Update the move info of the AI or player sprite
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::updateMove(const uint &index) {
|
||||
if (_input.idle())
|
||||
forceUpdateMove(index);
|
||||
}
|
||||
|
||||
void Sprite::forceUpdateMove(const uint &index) {
|
||||
if (_animSet._fight.forceUpdate(index, _input, _dir)) {
|
||||
// This sets the sprite input to the current move input
|
||||
_animSet._fight.curCombo(_input);
|
||||
|
||||
stop();
|
||||
assignFrame();
|
||||
} else
|
||||
_input.reset();
|
||||
}
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Reset the frame info of the sprite
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::resetFrame(const pyrodactyl::people::PersonState &pst) {
|
||||
_input.reset();
|
||||
walk(true);
|
||||
_animSet._fight.reset();
|
||||
|
||||
_boxD.w = 0;
|
||||
_boxD.h = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Check if both sprites in the same plane
|
||||
//------------------------------------------------------------------------
|
||||
bool Sprite::damageValid(Sprite &s, const SpriteConstant &sc) {
|
||||
// Get the y coordinates where these sprites are standing
|
||||
float Y = _pos.y + _clip.h, SY = s._pos.y + s._clip.h;
|
||||
|
||||
if (abs(Y - SY) < sc._planeW)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Checks about dealing damage to sprite
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::calcProperties(Info &info) {
|
||||
_visible.evaluate(info);
|
||||
_animSet._fight.evaluate(info);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Checks about dealing damage to sprite
|
||||
//------------------------------------------------------------------------
|
||||
bool Sprite::takingDamage(Sprite &sp, const SpriteConstant &sc) {
|
||||
if (damageValid(sp, sc))
|
||||
if (boxV().w > 0 && boxV().h > 0 && sp.boxD().w > 0 && sp.boxD().h > 0)
|
||||
if (boxV().collide(sp.boxD()))
|
||||
return true;
|
||||
|
||||
/*Common::String words = NumberToString(BoxV().x) + " " + NumberToString(BoxV().y)+ " " + NumberToString(BoxV().w)
|
||||
+ " " + NumberToString(BoxV().h) + "\n" + NumberToString(sp.BoxD().x) + " " + NumberToString(sp.BoxD().y)
|
||||
+ " " + NumberToString(sp.BoxD().w) + " " + NumberToString(sp.BoxD().h) + "\n";
|
||||
fprintf(stdout,words.c_str());*/
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: We know we are taking damage, now is the time to update stats
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::takeDamage(Info &info, Sprite &s) {
|
||||
using namespace pyrodactyl::stat;
|
||||
using namespace pyrodactyl::music;
|
||||
|
||||
FightMove f;
|
||||
if (s._animSet._fight.curMove(f) && info.personValid(s.id()) && info.personValid(_id)) {
|
||||
int dmg = -1 * (f._eff._dmg + info.personGet(s.id())._stat._val[STAT_ATTACK]._cur - info.personGet(_id)._stat._val[STAT_DEFENSE]._cur);
|
||||
if (dmg >= 0)
|
||||
dmg = -1;
|
||||
|
||||
info.statChange(_id, STAT_HEALTH, dmg);
|
||||
|
||||
int health = 1;
|
||||
info.statGet(_id, STAT_HEALTH, health);
|
||||
|
||||
// Play death animation if dead, hurt animation otherwise
|
||||
if (health <= 0 && f._eff._death != -1)
|
||||
forceUpdateMove(f._eff._death);
|
||||
else if (f._eff._hurt != -1)
|
||||
forceUpdateMove(f._eff._hurt);
|
||||
|
||||
g_engine->_musicManager->playEffect(f._eff._hit, 0);
|
||||
_imgEff = f._eff._img;
|
||||
}
|
||||
|
||||
stop();
|
||||
s._damageDone = true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: We have 2 sprites, *this and s.
|
||||
// Check damage between s.boxV and this->boxD and vice versa
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::exchangeDamage(Info &info, Sprite &s, const SpriteConstant &sc) {
|
||||
using namespace pyrodactyl::people;
|
||||
using namespace pyrodactyl::stat;
|
||||
|
||||
// This object is taking damage from s
|
||||
if (!s._damageDone && takingDamage(s, sc))
|
||||
takeDamage(info, s);
|
||||
|
||||
// Is the other sprite taking damage from this sprite?
|
||||
if (!_damageDone && s.takingDamage(*this, sc))
|
||||
s.takeDamage(info, *this);
|
||||
|
||||
// We change the animation to dying in order to give time to the death animation to play out
|
||||
int num = 0;
|
||||
info.statGet(s.id(), STAT_HEALTH, num);
|
||||
if (num <= 0) {
|
||||
info.state(s.id(), PST_DYING);
|
||||
info.statChange(s.id(), STAT_HEALTH, 1);
|
||||
}
|
||||
|
||||
info.statGet(_id, STAT_HEALTH, num);
|
||||
if (num <= 0) {
|
||||
info.state(_id, PST_DYING);
|
||||
info.statChange(_id, STAT_HEALTH, 1);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Update status of ambient dialog via popup object
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::internalEvents(Info &info, const Common::String &player_id, Common::Array<EventResult> &result, Common::Array<EventSeqInfo> &end_seq) {
|
||||
_popup.internalEvents(info, player_id, result, end_seq);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Save all sprite positions to save file
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::saveState(rapidxml::xml_document<> &doc, rapidxml::xml_node<char> *root) {
|
||||
root->append_attribute(doc.allocate_attribute("id", _id.c_str()));
|
||||
root->append_attribute(doc.allocate_attribute("x", g_engine->_stringPool->get(_pos.x)));
|
||||
root->append_attribute(doc.allocate_attribute("y", g_engine->_stringPool->get(_pos.y)));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Load all sprite positions from save file
|
||||
//------------------------------------------------------------------------
|
||||
void Sprite::loadState(rapidxml::xml_node<char> *node) {
|
||||
loadNum(_pos.x, "x", node);
|
||||
loadNum(_pos.y, "y", node);
|
||||
}
|
||||
|
||||
} // End of namespace Crab
|
||||
295
engines/crab/animation/sprite.h
Normal file
295
engines/crab/animation/sprite.h
Normal file
@@ -0,0 +1,295 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRAB_SPRITE_H
|
||||
#define CRAB_SPRITE_H
|
||||
|
||||
#include "crab/collision.h"
|
||||
#include "crab/timer.h"
|
||||
#include "crab/ai/spriteai.h"
|
||||
#include "crab/ai/SpriteConstant.h"
|
||||
#include "crab/animation/animset.h"
|
||||
#include "crab/animation/PopUp.h"
|
||||
#include "crab/level/LevelExit.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
class PathfindingAgent;
|
||||
|
||||
namespace pyrodactyl {
|
||||
namespace anim {
|
||||
|
||||
class Sprite {
|
||||
protected:
|
||||
// Used to sync sprite to character
|
||||
Common::String _id;
|
||||
|
||||
// The position of the sprite
|
||||
Vector2i _pos;
|
||||
|
||||
// The velocity of the sprite, target velocity is our maximum velocity
|
||||
Vector2f _vel, _target;
|
||||
|
||||
// The image of the sprite and it's dimensions
|
||||
ImageKey _image;
|
||||
Vector2i _imgSize;
|
||||
|
||||
// Clip is the portion of the sprite map to be drawn
|
||||
Rect _clip;
|
||||
|
||||
// The hit boxes of the character - v is vulnerable hit box, d is damage hit box
|
||||
Rect _boxV, _boxD;
|
||||
|
||||
// The direction the sprite is facing
|
||||
Direction _dir;
|
||||
|
||||
// The currently playing image effect
|
||||
ImageEffect _imgEff;
|
||||
|
||||
// The complete animation set for the sprite
|
||||
AnimSet _animSet;
|
||||
|
||||
// The conditions for sprite visibility
|
||||
pyrodactyl::event::TriggerSet _visible;
|
||||
|
||||
// Current sprite combo and input for the sprite
|
||||
pyrodactyl::input::FightInput _input;
|
||||
|
||||
// Have we done damage for this frame - used to avoid repeated damage for the same frame
|
||||
bool _damageDone;
|
||||
|
||||
// Dialog shown without events
|
||||
PopUpCollection _popup;
|
||||
|
||||
protected:
|
||||
void resetFrame(const pyrodactyl::people::PersonState &pst);
|
||||
bool fightCollide(Rect hitbox, Rect enemy_bounds, Range &range, const pyrodactyl::ai::SpriteConstant &sc);
|
||||
bool damageValid(Sprite &s, const pyrodactyl::ai::SpriteConstant &sc);
|
||||
|
||||
void clip(const Rect &rect) { _clip = rect; }
|
||||
void boxV(const Rect &rect) { _boxV = rect; }
|
||||
void boxD(const Rect &rect) { _boxD = rect; }
|
||||
|
||||
public:
|
||||
// The AI data for the sprite
|
||||
pyrodactyl::ai::SpriteAIData _aiData;
|
||||
PathfindingAgent _pathing;
|
||||
|
||||
// The modifier applied to the sprite velocity
|
||||
Vector2f _velMod;
|
||||
|
||||
// The layer associated with the sprite (used to show/hide sprite according to auto hide layers)
|
||||
int _layer;
|
||||
|
||||
// Is the mouse hovering over this sprite?
|
||||
bool _hover;
|
||||
|
||||
// The list of collisions currently taking place with the sprite
|
||||
Common::List<CollisionData> _collideData;
|
||||
|
||||
Sprite();
|
||||
|
||||
~Sprite() {
|
||||
_pathing.reset();
|
||||
}
|
||||
|
||||
void visible(bool val) {
|
||||
_visible.result(val);
|
||||
}
|
||||
|
||||
bool visible() {
|
||||
return _visible.result();
|
||||
}
|
||||
|
||||
void calcProperties(pyrodactyl::event::Info &info);
|
||||
|
||||
void x(int X) {
|
||||
_pos.x = X;
|
||||
}
|
||||
|
||||
void y(int Y) {
|
||||
_pos.y = Y;
|
||||
}
|
||||
|
||||
int x() {
|
||||
return _pos.x;
|
||||
}
|
||||
|
||||
int y() {
|
||||
return _pos.y;
|
||||
}
|
||||
|
||||
void walkPattern(const pyrodactyl::ai::MovementSet &set) {
|
||||
_aiData._walk = set;
|
||||
}
|
||||
|
||||
void move(const pyrodactyl::ai::SpriteConstant &sc);
|
||||
|
||||
// Resolve collisions for polygons we want to be outside of
|
||||
void resolveCollide();
|
||||
|
||||
// Resolve collisions for the walk rectangle
|
||||
void resolveInside(Rect collider);
|
||||
|
||||
void stop() {
|
||||
_vel.Set();
|
||||
_target.Set();
|
||||
_aiData._dest._active = false;
|
||||
}
|
||||
void inputStop() {
|
||||
_input.reset();
|
||||
}
|
||||
|
||||
void xVel(const float &val) {
|
||||
_target.x = val * _velMod.x;
|
||||
}
|
||||
void yVel(const float &val) {
|
||||
_target.y = val * _velMod.y;
|
||||
}
|
||||
|
||||
float xVel() {
|
||||
return _vel.x;
|
||||
}
|
||||
|
||||
float yVel() {
|
||||
return _vel.y;
|
||||
}
|
||||
|
||||
Vector2f vel() {
|
||||
return _vel;
|
||||
}
|
||||
|
||||
const Common::String &id() {
|
||||
return _id;
|
||||
}
|
||||
|
||||
int w() {
|
||||
return _clip.w;
|
||||
}
|
||||
|
||||
int h() {
|
||||
return _clip.h;
|
||||
}
|
||||
|
||||
const ImageKey &img() {
|
||||
return _image;
|
||||
}
|
||||
|
||||
Rect dialogClip(const pyrodactyl::people::PersonState &state) {
|
||||
return _animSet._walk.dialogClip(state);
|
||||
}
|
||||
|
||||
void dialogUpdateClip(const pyrodactyl::people::PersonState &state) {
|
||||
_animSet._walk.updateClip(state);
|
||||
}
|
||||
|
||||
bool popupShow() {
|
||||
return _popup.show();
|
||||
}
|
||||
|
||||
Rect boundRect();
|
||||
Rect boxV();
|
||||
Rect boxD();
|
||||
Rect posRect();
|
||||
Rect rangeRect(const Rect &bounds, const Range &range);
|
||||
Vector2i camFocus();
|
||||
|
||||
double distSq(const Sprite &s);
|
||||
|
||||
void effectImg(bool vis) {
|
||||
_imgEff._visible = vis;
|
||||
}
|
||||
|
||||
bool lastFrame() {
|
||||
return _animSet._fight.lastFrame();
|
||||
}
|
||||
|
||||
bool takingDamage(Sprite &sp, const pyrodactyl::ai::SpriteConstant &sc);
|
||||
void takeDamage(pyrodactyl::event::Info &info, Sprite &s);
|
||||
void exchangeDamage(pyrodactyl::event::Info &info, Sprite &s, const pyrodactyl::ai::SpriteConstant &sc);
|
||||
|
||||
void load(rapidxml::xml_node<char> *node, Common::Array<Common::Path> &animations);
|
||||
void internalEvents(pyrodactyl::event::Info &info, const Common::String &player_id,
|
||||
Common::Array<pyrodactyl::event::EventResult> &result, Common::Array<pyrodactyl::event::EventSeqInfo> &end_seq);
|
||||
|
||||
void draw(pyrodactyl::event::Info &info, const Rect &camera);
|
||||
void drawPopup(pyrodactyl::ui::ParagraphData &pop, const Rect &camera);
|
||||
|
||||
void walk(const bool &reset);
|
||||
void walk(const pyrodactyl::people::PersonState &pst);
|
||||
|
||||
void updateFrame(const pyrodactyl::people::PersonState &pst, const bool &repeat = false);
|
||||
void assignFrame();
|
||||
|
||||
void updateMove(const pyrodactyl::input::FightAnimationType &combo);
|
||||
void forceUpdateMove(const pyrodactyl::input::FightAnimationType &combo);
|
||||
|
||||
void updateMove(const uint &index);
|
||||
void forceUpdateMove(const uint &index);
|
||||
|
||||
// Set sprite destination
|
||||
void setDestPathfinding(const Vector2i &dest, bool reachable = true);
|
||||
|
||||
// Used for sprite movement controlled by player input (usually the player sprite)
|
||||
void handleEvents(pyrodactyl::event::Info &info, const Rect &camera, const pyrodactyl::ai::SpriteConstant &sc, const Common::Event &event);
|
||||
|
||||
// This is for sprites with valid object ids
|
||||
void animate(pyrodactyl::event::Info &info);
|
||||
|
||||
// This is for objects without valid ids - like <background> and <fly> sprites
|
||||
void animate(const pyrodactyl::people::PersonState &pst);
|
||||
|
||||
// AI behavior routine for sprites attacking the player
|
||||
void attack(pyrodactyl::event::Info &info, Sprite &targetSp, const pyrodactyl::ai::SpriteConstant &sc);
|
||||
|
||||
// AI behavior routine for sprites running away from the player
|
||||
// Requires every exit in the level be accessible
|
||||
void flee(pyrodactyl::event::Info &info, Common::Array<pyrodactyl::level::Exit> &areaExit, const pyrodactyl::ai::SpriteConstant &sc);
|
||||
|
||||
// Used for sprites that fly across semi randomly on the screen
|
||||
void flyAround(const Rect &camera, const pyrodactyl::ai::SpriteConstant &sc);
|
||||
|
||||
// Used for the player destination movement
|
||||
void moveToDest(pyrodactyl::event::Info &info, const pyrodactyl::ai::SpriteConstant &sc);
|
||||
void moveToDestPathfinding(pyrodactyl::event::Info &info, const pyrodactyl::ai::SpriteConstant &sc);
|
||||
|
||||
// Used for AI movement - returns true if at the destination, false otherwise
|
||||
bool moveToLoc(Vector2i &dest, const float &vel, const pyrodactyl::ai::SpriteConstant &sc);
|
||||
bool moveToLocPathfinding(Vector2i &dest, const float &vel, const pyrodactyl::ai::SpriteConstant &sc);
|
||||
|
||||
void saveState(rapidxml::xml_document<> &doc, rapidxml::xml_node<char> *root);
|
||||
void loadState(rapidxml::xml_node<char> *node);
|
||||
};
|
||||
} // End of namespace anim
|
||||
} // End of namespace pyrodactyl
|
||||
|
||||
} // End of namespace Crab
|
||||
|
||||
#endif // CRAB_SPRITE_H
|
||||
155
engines/crab/animation/walkframes.cpp
Normal file
155
engines/crab/animation/walkframes.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "crab/animation/walkframes.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
using namespace pyrodactyl::anim;
|
||||
using namespace pyrodactyl::people;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Loader Function
|
||||
//------------------------------------------------------------------------
|
||||
void WalkFrames::load(rapidxml::xml_node<char> *node) {
|
||||
if (nodeValid("stand", node))
|
||||
_set[WT_STAND].load(node->first_node("stand"));
|
||||
|
||||
if (nodeValid("walk", node))
|
||||
_set[WT_WALK].load(node->first_node("walk"));
|
||||
|
||||
if (nodeValid("fight", node))
|
||||
_set[WT_FIGHT].load(node->first_node("fight"));
|
||||
|
||||
if (nodeValid("ko", node))
|
||||
_set[WT_KO].load(node->first_node("ko"));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Used for walking inside levels
|
||||
//------------------------------------------------------------------------
|
||||
bool WalkFrames::updateClip(Direction d, bool reset) {
|
||||
if (_timer.ticks() > _set[_cur].frames[d].currentFrame()._repeat || reset) {
|
||||
_timer.start();
|
||||
return _set[_cur].frames[d].updateClip();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void WalkFrames::resetClip(Direction d) {
|
||||
_set[_cur].frames[d].reset();
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Used inside dialog box
|
||||
//------------------------------------------------------------------------
|
||||
void WalkFrames::updateClip(WalkAnimType type, Direction d) {
|
||||
if (!_timer.started())
|
||||
_timer.start();
|
||||
|
||||
if (_timer.ticks() > _set[type].frames[d].currentFrame()._repeat) {
|
||||
_set[type].frames[d].updateClip();
|
||||
_timer.start();
|
||||
}
|
||||
}
|
||||
|
||||
Rect WalkFrames::dialogClip(const PersonState &state) {
|
||||
if (state == PST_FIGHT)
|
||||
return _set[WT_FIGHT].frames[DIRECTION_DOWN].currentFrame()._clip;
|
||||
else if (state == PST_KO)
|
||||
return _set[WT_KO].frames[DIRECTION_DOWN].currentFrame()._clip;
|
||||
|
||||
return _set[WT_STAND].frames[DIRECTION_DOWN].currentFrame()._clip;
|
||||
}
|
||||
|
||||
void WalkFrames::updateClip(const PersonState &state) {
|
||||
if (state == PST_FIGHT)
|
||||
updateClip(WT_FIGHT, DIRECTION_DOWN);
|
||||
else if (state == PST_KO)
|
||||
updateClip(WT_KO, DIRECTION_DOWN);
|
||||
else
|
||||
updateClip(WT_STAND, DIRECTION_DOWN);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Purpose: Decide direction and type of animation, return whether it has changed
|
||||
//------------------------------------------------------------------------
|
||||
bool WalkFrames::type(const Vector2f &vel, Direction &dir, const pyrodactyl::people::PersonState &pst, const bool &firstX) {
|
||||
Direction prevDir = dir;
|
||||
WalkAnimType prevType = _cur;
|
||||
|
||||
if (pst == PST_KO) {
|
||||
_cur = WT_KO;
|
||||
} else if (firstX) {
|
||||
// If we prioritize the X direction, X velocity is checked first for direction and then Y velocity
|
||||
if (vel.x > 0) {
|
||||
dir = DIRECTION_RIGHT;
|
||||
_cur = WT_WALK;
|
||||
} else if (vel.x < 0) {
|
||||
dir = DIRECTION_LEFT;
|
||||
_cur = WT_WALK;
|
||||
} else if (vel.y > 0) {
|
||||
dir = DIRECTION_DOWN;
|
||||
_cur = WT_WALK;
|
||||
} else if (vel.y < 0) {
|
||||
dir = DIRECTION_UP;
|
||||
_cur = WT_WALK;
|
||||
} else {
|
||||
_cur = WT_STAND;
|
||||
}
|
||||
} else {
|
||||
// If we prioritize the Y direction, Y velocity is checked first for direction and then Y velocity
|
||||
if (vel.y > 0) {
|
||||
dir = DIRECTION_DOWN;
|
||||
_cur = WT_WALK;
|
||||
} else if (vel.y < 0) {
|
||||
dir = DIRECTION_UP;
|
||||
_cur = WT_WALK;
|
||||
} else if (vel.x > 0) {
|
||||
dir = DIRECTION_RIGHT;
|
||||
_cur = WT_WALK;
|
||||
} else if (vel.x < 0) {
|
||||
dir = DIRECTION_LEFT;
|
||||
_cur = WT_WALK;
|
||||
} else {
|
||||
_cur = WT_STAND;
|
||||
}
|
||||
}
|
||||
|
||||
if (prevDir != dir || prevType != _cur)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Crab
|
||||
130
engines/crab/animation/walkframes.h
Normal file
130
engines/crab/animation/walkframes.h
Normal file
@@ -0,0 +1,130 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRAB_WALKFRAMES_H
|
||||
#define CRAB_WALKFRAMES_H
|
||||
|
||||
#include "crab/timer.h"
|
||||
#include "crab/ai/movement.h"
|
||||
#include "crab/animation/animframe.h"
|
||||
#include "crab/people/personbase.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
namespace pyrodactyl {
|
||||
namespace anim {
|
||||
enum WalkAnimType {
|
||||
WT_STAND,
|
||||
WT_WALK,
|
||||
WT_FIGHT,
|
||||
WT_KO,
|
||||
WT_TOTAL
|
||||
};
|
||||
|
||||
class WalkFrames {
|
||||
struct WalkFrameSet {
|
||||
AnimationFrames frames[DIRECTION_TOTAL];
|
||||
|
||||
void load(rapidxml::xml_node<char> *node) {
|
||||
frames[DIRECTION_DOWN].load(node->first_node("down"));
|
||||
frames[DIRECTION_UP].load(node->first_node("up"));
|
||||
frames[DIRECTION_LEFT].load(node->first_node("left"));
|
||||
frames[DIRECTION_RIGHT].load(node->first_node("right"));
|
||||
}
|
||||
};
|
||||
|
||||
// The walking animations of the sprite
|
||||
WalkFrameSet _set[WT_TOTAL];
|
||||
|
||||
// The current walking animation
|
||||
WalkAnimType _cur;
|
||||
|
||||
// The timers used for animation playing
|
||||
Timer _timer;
|
||||
|
||||
// Dialog box related
|
||||
void updateClip(WalkAnimType type, Direction d);
|
||||
|
||||
public:
|
||||
WalkFrames() {
|
||||
_cur = WT_STAND;
|
||||
_timer.start();
|
||||
}
|
||||
~WalkFrames() {}
|
||||
|
||||
void load(rapidxml::xml_node<char> *node);
|
||||
|
||||
bool updateClip(Direction d, bool reset);
|
||||
void resetClip(Direction d);
|
||||
|
||||
void type(WalkAnimType type) {
|
||||
_cur = type;
|
||||
}
|
||||
|
||||
WalkAnimType type() {
|
||||
return _cur;
|
||||
}
|
||||
|
||||
bool type(const Vector2f &vel, Direction &dir, const pyrodactyl::people::PersonState &pst, const bool &first_x);
|
||||
|
||||
const Rect &clip(Direction d) {
|
||||
return _set[_cur].frames[d].currentFrame()._clip;
|
||||
}
|
||||
|
||||
const Rect &boxV(Direction d) {
|
||||
return _set[_cur].frames[d].currentFrame()._boxV;
|
||||
}
|
||||
|
||||
const TextureFlipType &flip(Direction d) {
|
||||
return _set[_cur].frames[d]._flip;
|
||||
}
|
||||
|
||||
const ShadowOffset &shadow(Direction d) {
|
||||
return _set[_cur].frames[d]._shadow;
|
||||
}
|
||||
|
||||
int anchorX(Direction d) {
|
||||
return _set[_cur].frames[d].currentFrame()._anchor.x;
|
||||
}
|
||||
|
||||
int anchorY(Direction d) {
|
||||
return _set[_cur].frames[d].currentFrame()._anchor.y;
|
||||
}
|
||||
|
||||
// Dialog box related
|
||||
Rect dialogClip(const pyrodactyl::people::PersonState &state);
|
||||
void updateClip(const pyrodactyl::people::PersonState &state);
|
||||
};
|
||||
} // End of namespace anim
|
||||
} // End of namespace pyrodactyl
|
||||
|
||||
} // End of namespace Crab
|
||||
|
||||
#endif // CRAB_WALKFRAMES_H
|
||||
Reference in New Issue
Block a user