Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View 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
*
*/
#include "crab/level/LevelExit.h"
namespace Crab {
using namespace pyrodactyl::level;
void Exit::load(rapidxml::xml_node<char> *node) {
_dim.load(node);
loadStr(_name, "name", node);
if (nodeValid("properties", node)) {
rapidxml::xml_node<char> *propertynode = node->first_node("properties");
for (auto n = propertynode->first_node("property"); n != nullptr; n = n->next_sibling("property")) {
Common::String nodeName;
loadStr(nodeName, "name", n);
if (nodeName == "entry_x") {
if (!loadNum(_entry.x, "value", n))
_entry.x = -1;
} else if (nodeName == "entry_y") {
if (!loadNum(_entry.y, "value", n))
_entry.y = -1;
}
}
}
}
} // End of namespace Crab

View 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_LEVELEXIT_H
#define CRAB_LEVELEXIT_H
#include "crab/Shape.h"
namespace Crab {
namespace pyrodactyl {
namespace level {
struct Exit {
Common::String _name;
Shape _dim;
Vector2i _entry;
Exit() : _entry(-1, -1) {}
Exit(rapidxml::xml_node<char> *node) {
load(node);
}
void load(rapidxml::xml_node<char> *node);
};
} // End of namespace level
} // End of namespace pyrodactyl
} // End of namespace Crab
#endif // CRAB_LEVELEXIT_H

View 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/level/MusicArea.h"
namespace Crab {
using namespace pyrodactyl::level;
void MusicArea::load(rapidxml::xml_node<char> *node, const bool &echo) {
Shape::load(node, echo);
if (nodeValid("properties", node, echo)) {
auto pnode = node->first_node("properties");
for (auto n = pnode->first_node("property"); n != nullptr; n = n->next_sibling("property")) {
Common::String name;
if (loadStr(name, "name", n, echo)) {
if (name == "music")
loadBool(_track, "value", n, echo);
else if (name == "id")
loadNum(_id, "value", n, echo);
else if (name == "loops")
loadNum(_loops, "value", n, echo);
}
}
}
}
} // End of namespace Crab

View File

@@ -0,0 +1,71 @@
/* 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_MUSICAREA_H
#define CRAB_MUSICAREA_H
#include "crab/Shape.h"
#include "crab/music/musicparam.h"
namespace Crab {
namespace pyrodactyl {
namespace level {
struct MusicInfo {
// Are we playing a sound effect or a music track
bool _track;
// The id of the music track or sound effect being played
int _id;
// The amount of loops
int _loops;
MusicInfo() {
_track = false;
_id = -1;
_loops = -1;
}
~MusicInfo() {}
};
class MusicArea : public Shape, public MusicInfo {
public:
MusicArea() {}
~MusicArea() {}
void load(rapidxml::xml_node<char> *node, const bool &echo = true);
};
} // End of namespace level
} // End of namespace pyrodactyl
} // End of namespace Crab
#endif // CRAB_MUSICAREA_H

View File

@@ -0,0 +1,54 @@
/* 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/level/Stairs.h"
namespace Crab {
using namespace pyrodactyl::level;
void Stairs::load(rapidxml::xml_node<char> *node, const bool &echo) {
Shape::load(node, echo);
if (nodeValid("properties", node, echo)) {
auto pnode = node->first_node("properties");
for (auto n = pnode->first_node("property"); n != nullptr; n = n->next_sibling("property")) {
Common::String name;
if (loadStr(name, "name", n, echo)) {
if (name == "x")
loadNum(_modifier.x, "value", n, echo);
else if (name == "y")
loadNum(_modifier.y, "value", n, echo);
}
}
}
}
} // End of namespace Crab

View File

@@ -0,0 +1,55 @@
/* 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_STAIRS_H
#define CRAB_STAIRS_H
#include "crab/Shape.h"
namespace Crab {
namespace pyrodactyl {
namespace level {
class Stairs : public Shape {
public:
// The modifier by which the velocity of the character walking over the stairs is changed
Vector2f _modifier;
Stairs() : _modifier(1.0f, 1.0f) {}
~Stairs() {}
void load(rapidxml::xml_node<char> *node, const bool &echo = true);
};
} // End of namespace level
} // End of namespace pyrodactyl
} // End of namespace Crab
#endif // CRAB_STAIRS_H

View File

@@ -0,0 +1,147 @@
/* 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/input/cursor.h"
#include "crab/level/level.h"
namespace Crab {
using namespace TMX;
using namespace pyrodactyl::stat;
using namespace pyrodactyl::anim;
using namespace pyrodactyl::level;
using namespace pyrodactyl::image;
using namespace pyrodactyl::people;
using namespace pyrodactyl::input;
using namespace pyrodactyl::event;
//------------------------------------------------------------------------
// Purpose: We re-use the same level object each time
// this function cleans up everything to make it good as new (get it)
//------------------------------------------------------------------------
void Level::reset() {
if (_playerIndex > 0 && _objects.size() > _playerIndex)
_objects[_playerIndex]._pathing.shutdown();
_playerIndex = 0;
_terrain.reset();
_objects.clear();
_objSeq.clear();
_background.clear();
_fly.clear();
Camera(0, 0, g_engine->_screenSettings->_cur.w, g_engine->_screenSettings->_cur.h);
_showmap.set(true);
_insideExit = false;
_firstHit = true;
_music._id = -1;
_previewPath.clear();
_img.deleteImage();
}
//------------------------------------------------------------------------
// Purpose: Get sprite in the object array
//------------------------------------------------------------------------
pyrodactyl::anim::Sprite *Level::getSprite(const Common::String &id) {
for (auto &i : _objects)
if (i.id() == id)
return &i;
return nullptr;
}
//------------------------------------------------------------------------
// Purpose: Figure visibility and let the AI see what moves are allowed
//------------------------------------------------------------------------
void Level::calcProperties(pyrodactyl::event::Info &info) {
for (auto &i : _objects)
i.calcProperties(info);
}
//------------------------------------------------------------------------
// Purpose: Handle the level movement
//------------------------------------------------------------------------
void Level::handleEvents(Info &info, const Common::Event &event) {
if (!g_engine->_mouse->_insideHud) {
if (event.type == Common::EVENT_LBUTTONDOWN || event.type == Common::EVENT_RBUTTONDOWN) {
// Only go to path if our mouse is a normal walking cursor
if (!g_engine->_mouse->_hover) {
// The destination coordinate is set by adding camera position to click position
Vector2i dest = g_engine->_mouse->_button;
dest.x += _camera.x;
dest.y += _camera.y;
Rect b = _objects[_playerIndex].boundRect();
b.w /= 2;
b.h /= 2;
b.x = dest.x - b.w / 2;
b.y = dest.y - b.h / 2;
_objects[_playerIndex].setDestPathfinding(dest, !_terrain.insideNoWalk(dest));
}
}
}
_objects[_playerIndex].handleEvents(info, _camera, _scDefault, event);
}
//------------------------------------------------------------------------
// Purpose: Swap the player sprites
//------------------------------------------------------------------------
void Level::playerId(const Common::String &ID, const int &x, const int &y) {
int index = 0;
for (auto i = _objects.begin(); i != _objects.end(); ++i, ++index) {
if (i->id() == ID) {
_playerIndex = index;
if (x != -1)
i->x(x);
if (y != -1)
i->y(y);
break;
}
}
}
//------------------------------------------------------------------------
// Purpose: Rearrange stuff after resolution change
//------------------------------------------------------------------------
void Level::setUI() {
_camera.w = g_engine->_screenSettings->_cur.w;
_camera.h = g_engine->_screenSettings->_cur.h;
setCamera();
}
} // End of namespace Crab

220
engines/crab/level/level.h Normal file
View File

@@ -0,0 +1,220 @@
/* 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_LEVEL_H
#define CRAB_LEVEL_H
#include "common/multimap.h"
#include "crab/PathfindingGrid.h"
#include "crab/animation/sprite.h"
#include "crab/level/level_objects.h"
#include "crab/level/talknotify.h"
#include "crab/TMX/TMXMap.h"
namespace Crab {
namespace pyrodactyl {
namespace level {
class Level {
// The .tmx file to import terrain from
TMX::TMXMap _terrain;
// The pathfinding grid for the level
PathfindingGrid _pathfindingGrid;
// The area we display to the player
Rect _camera;
// The player sprite location in the object list
uint _playerIndex;
// The order in which to draw the sprites
Common::MultiMap<int, pyrodactyl::anim::Sprite *> _objSeq;
// The file index which contains the fighting moves of all characters
Common::Array<Common::Path> _animSet;
// The movement sets for sprites in levels
Common::Array<pyrodactyl::ai::MovementSet> _moveSet;
// These sprites are only for animated objects and cannot be interacted with
Common::Array<pyrodactyl::anim::Sprite> _background;
// These sprites fly across the screen randomly
Common::Array<pyrodactyl::anim::Sprite> _fly;
// The id of the music track being played
MusicInfo _music;
// Is the world map accessible from this level?
MapVis _showmap;
// We disable exits when player is fighting enemies - this is used to check if we are in an exit area WHILE fighting enemies
// If we are fighting inside exit area, the level switch is delayed until we walk out of exit and back in
// to prevent instant level switch as soon as you beat all enemies
bool _insideExit;
bool _firstHit;
// Default sprite parameters
pyrodactyl::ai::SpriteConstant _scDefault;
// Protected level functions
bool collidingWithObject(pyrodactyl::event::Info &info, Common::String &id);
bool collidingWithLevel(pyrodactyl::event::Info &info, pyrodactyl::anim::Sprite &s);
bool playerInCombat(pyrodactyl::event::Info &info);
void battleAlert(pyrodactyl::event::Info &info);
void sortObjectsToDraw();
void moveObject(pyrodactyl::event::Info &info, pyrodactyl::anim::Sprite &s);
void think(pyrodactyl::event::Info &info, Common::Array<pyrodactyl::event::EventResult> &result,
Common::Array<pyrodactyl::event::EventSeqInfo> &endSeq, Common::String &id);
void drawObjects(pyrodactyl::event::Info &info);
void setCamera();
bool layerVisible(pyrodactyl::anim::Sprite *obj);
public:
// The objects in the level, and the player character
Common::Array<pyrodactyl::anim::Sprite> _objects;
// The notification text drawn if the player is able to talk to a sprite
TalkNotify _talkNotify;
// Used for drawing the destination marker for point and click movement
PlayerDestMarker _destMarker;
// The location of this level on the world map
Vector2i _mapLoc;
// The clip revealed by this level on the world map
struct MapClip {
// Which world map is this clip added to?
int _id;
// The clip itself
Rect _rect;
MapClip() {
_id = 0;
}
} _mapClip;
// Used to draw ambient dialog
pyrodactyl::ui::ParagraphData _pop;
// The path of the preview image
Common::Path _previewPath;
// A full rendered image of the level
pyrodactyl::image::Image _img;
Level() : _playerIndex(0) {
reset();
}
~Level() {
reset();
}
void reset();
void Camera(int x, int y, int w, int h) {
_camera.x = x;
_camera.y = y;
_camera.w = w;
_camera.h = h;
}
Rect camera() {
return _camera;
}
void playerStop() {
_objects[_playerIndex].stop();
}
const Common::String &playerId() {
return _objects[_playerIndex].id();
}
void playerId(const Common::String &ID, const int &x, const int &y);
void showMap(bool val) {
_showmap._normal = val;
}
bool showMap() {
return _showmap._current;
}
bool operator()(int i, int j);
// This calculates the unlocked moves for each sprite in the level, and the visibility of objects
void calcProperties(pyrodactyl::event::Info &info);
// Loading function
void load(const Common::Path &filename, pyrodactyl::event::Info &info, pyrodactyl::event::TriggerSet &gameOver,
const int &playerX = -1, const int &playerY = -1);
// One time load called first-time
void loadMoves(const Common::Path &filename);
void loadConst(const Common::Path &filename);
// Used to see if a sprite collides with a rectangle
void calcTrigCollide(pyrodactyl::event::Info &info);
// See if a player clicked on the sprite in contact
bool containsClick(const Common::String &id, const Common::Event &event);
// Get index of a sprite in the object array
pyrodactyl::anim::Sprite *getSprite(const Common::String &id);
void handleEvents(pyrodactyl::event::Info &info, const Common::Event &event);
LevelResult internalEvents(pyrodactyl::event::Info &info, Common::Array<pyrodactyl::event::EventResult> &result,
Common::Array<pyrodactyl::event::EventSeqInfo> &endSeq, bool eventInProgress);
void preDraw();
void preDrawObjects(Graphics::ManagedSurface *surf);
void draw(pyrodactyl::event::Info &info);
void saveState(rapidxml::xml_document<> &doc, rapidxml::xml_node<char> *root);
void loadState(rapidxml::xml_node<char> *node);
void setUI();
};
} // End of namespace level
} // End of namespace pyrodactyl
} // End of namespace Crab
#endif // CRAB_LEVEL_H

View File

@@ -0,0 +1,219 @@
/* 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/level/level.h"
namespace Crab {
using namespace TMX;
using namespace pyrodactyl::stat;
using namespace pyrodactyl::anim;
using namespace pyrodactyl::level;
using namespace pyrodactyl::image;
using namespace pyrodactyl::people;
using namespace pyrodactyl::input;
using namespace pyrodactyl::event;
//------------------------------------------------------------------------
// Purpose: Let the level tick along and notify if we go into an exit
//------------------------------------------------------------------------
LevelResult Level::internalEvents(Info &info, Common::Array<EventResult> &result, Common::Array<EventSeqInfo> &endSeq, bool eventInProgress) {
LevelResult lResult;
// input.internalEvents();
calcTrigCollide(info);
if (_terrain.collideWithExit(_objects[_playerIndex].boundRect(), lResult)) {
if (playerInCombat(info)) {
_insideExit = true;
} else if (_insideExit == false) {
lResult._type = LR_LEVEL;
return lResult;
}
} else {
_insideExit = false;
if (playerInCombat(info))
_showmap._current = false;
else
_showmap._current = _showmap._normal;
}
if (eventInProgress)
playerStop();
else
think(info, result, endSeq, lResult._val);
if (lResult._val != "")
info.lastPerson(lResult._val);
else if (collidingWithObject(info, lResult._val))
info.lastPerson(lResult._val);
else
info.lastPerson("");
return lResult;
}
//------------------------------------------------------------------------
// Purpose: Let the AI think and animate the level
//------------------------------------------------------------------------
void Level::think(pyrodactyl::event::Info &info, Common::Array<pyrodactyl::event::EventResult> &result,
Common::Array<pyrodactyl::event::EventSeqInfo> &endSeq, Common::String &id) {
uint index = 0;
for (auto i = _objects.begin(); i != _objects.end(); ++i, ++index) {
// Only bother if the sprite is visible
if (i->visible()) {
// TODO: Find a place where this should be initialized... (SZ)
if (i->_pathing._grid == nullptr)
i->_pathing.initialize(&_pathfindingGrid);
// If a sprite is dead, nothing else matters
if (info.state(i->id()) == PST_DYING) {
if (i->lastFrame()) {
info.statSet(i->id(), STAT_HEALTH, 0);
info.state(i->id(), PST_KO);
i->effectImg(false);
i->inputStop();
}
} else if (info.state(i->id()) != PST_KO) {
Rect boundRect = i->boundRect();
i->_pathing.setPosition(Vector2f((float)(boundRect.x + boundRect.w / 2), (float)boundRect.y + boundRect.h / 2));
i->_pathing.update(0);
// For the AI sprites
if (index != _playerIndex) {
switch (info.state(i->id())) {
case PST_FIGHT: {
// Only attack if the player is alive
if (info.state(_objects[_playerIndex].id()) < PST_KO)
i->attack(info, _objects[_playerIndex], _scDefault);
} break;
case PST_FLEE:
i->flee(info, _terrain._areaExit, _scDefault);
break;
case PST_NORMAL:
if (i->takingDamage(_objects[_playerIndex], _scDefault)) {
if (_firstHit) {
battleAlert(info);
_firstHit = false;
}
}
/*else
TraversePath(*i);*/
break;
default:
break;
}
// Only do this if the player is alive
if (info.state(_objects[_playerIndex].id()) < PST_KO)
_objects[_playerIndex].exchangeDamage(info, *i, _scDefault);
} else {
// For the player sprite
boundRect = i->boundRect();
i->_pathing.setPosition(Vector2f((float)(boundRect.x + boundRect.w / 2), (float)boundRect.y + boundRect.h / 2));
i->_pathing.update(0);
i->moveToDestPathfinding(info, _scDefault);
}
i->internalEvents(info, playerId(), result, endSeq);
moveObject(info, *i);
}
i->animate(info);
}
}
// Background sprites don't move
for (auto &i : _background)
i.animate(PST_NORMAL);
// Flier sprites fly across the screen from left to right or vice versa
// The movement is semi-random
for (auto &i : _fly) {
i.flyAround(_camera, _scDefault);
i.animate(PST_NORMAL);
}
}
//------------------------------------------------------------------------
// Purpose: Once a player provokes any sprite, call this function
//------------------------------------------------------------------------
void Level::battleAlert(pyrodactyl::event::Info &info) {
uint index = 0;
for (auto i = _objects.begin(); i != _objects.end(); ++i, ++index) {
if (index != _playerIndex && i->visible() && info.state(i->id()) != PST_KO) {
switch (info.type(i->id())) {
case PE_NEUTRAL:
case PE_HOSTILE:
info.state(i->id(), PST_FIGHT);
break;
case PE_COWARD:
info.state(i->id(), PST_FLEE);
break;
default:
break;
}
}
}
}
//------------------------------------------------------------------------
// Purpose: Move a sprite according to its velocity
//------------------------------------------------------------------------
void Level::moveObject(pyrodactyl::event::Info &info, pyrodactyl::anim::Sprite &s) {
// Update x,y coordinates according to velocity
s.move(_scDefault);
// First check collision with objects and forbidden areas inside a level
if (collidingWithLevel(info, s))
s.resolveCollide();
// Finally see if we are inside the overall level bounds
if (!_terrain.insideWalk(s.boundRect()))
s.resolveInside(_terrain.areaWalk());
}
//------------------------------------------------------------------------
// Purpose: If any other object is trying to kill you, you are in combat
//------------------------------------------------------------------------
bool Level::playerInCombat(pyrodactyl::event::Info &info) {
uint index = 0;
for (auto i = _objects.begin(); i != _objects.end(); ++i, ++index)
if (index != _playerIndex && info.state(i->id()) == PST_FIGHT && i->visible())
return true;
return false;
}
} // End of namespace Crab

View File

@@ -0,0 +1,149 @@
/* 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/input/cursor.h"
#include "crab/level/level.h"
namespace Crab {
using namespace TMX;
using namespace pyrodactyl::stat;
using namespace pyrodactyl::anim;
using namespace pyrodactyl::level;
using namespace pyrodactyl::image;
using namespace pyrodactyl::people;
using namespace pyrodactyl::input;
using namespace pyrodactyl::event;
using namespace pyrodactyl::music;
//------------------------------------------------------------------------
// Purpose: See if player clicked on a sprite they are colliding with
//------------------------------------------------------------------------
bool Level::containsClick(const Common::String &id, const Common::Event &event) {
// If mouse is moved and is hovering on the specified sprite (id), set hover = true
if (event.type == Common::EVENT_MOUSEMOVE) {
for (auto &i : _objects) {
Rect r = i.posRect();
if (r.contains(g_engine->_mouse->_motion.x + _camera.x, g_engine->_mouse->_motion.y + _camera.y)) {
// This is to show the sprite's name on top of their head
i._hover = true;
// This is to update the mouse cursor only if we're in talking range of a sprite
if (i.id() == id)
g_engine->_mouse->_hover = true;
} else
i._hover = false;
}
return false;
} else if (g_engine->_mouse->pressed()) {
for (auto &i : _objects) {
if (i.id() == id) {
Rect r = i.posRect();
if (r.contains(g_engine->_mouse->_button.x + _camera.x, g_engine->_mouse->_button.y + _camera.y)) {
g_engine->_mouse->_hover = true;
return true;
}
}
}
}
return false;
}
//------------------------------------------------------------------------
// Purpose: Find if a layer is visible (used only for objects with layers associated with them)
//------------------------------------------------------------------------
bool Level::layerVisible(pyrodactyl::anim::Sprite *obj) {
if (obj->_layer < 0)
return true;
if ((uint)obj->_layer < _terrain._layer.size())
return _terrain._layer[obj->_layer]._collide;
return false;
}
//------------------------------------------------------------------------
// Purpose: Check if a sprite is colliding with the trigger areas
// Common::String &id is set to the id of colliding object
//------------------------------------------------------------------------
void Level::calcTrigCollide(pyrodactyl::event::Info &info) {
for (auto &i : _objects)
if (info.personValid(i.id()))
_terrain.collideWithTrigger(i.boundRect(), info.personGet(i.id())._trig);
}
//------------------------------------------------------------------------
// Purpose: Check if a sprite is colliding with interactive objects
// Common::String &id is set to the id of colliding object
//------------------------------------------------------------------------
bool Level::collidingWithObject(pyrodactyl::event::Info &info, Common::String &id) {
// Clip and Bounding rectangle of player
Rect pPos = _objects[_playerIndex].posRect(), pBound = _objects[_playerIndex].boundRect();
uint index = 0;
for (auto i = _objects.begin(); i != _objects.end(); ++i, ++index) {
if (i->visible() && _playerIndex != index && info.state(i->id()) == PST_NORMAL) {
// Clip and bounding rectangles for the NPC sprite
Rect iPos = i->posRect(), iBound = i->boundRect();
if (pPos.collide(iPos) || iPos.contains(pPos) || pBound.collide(iBound) || iBound.contains(pBound)) {
id = i->id();
return true;
}
}
}
return false;
}
//------------------------------------------------------------------------
// Purpose: Check if a sprite is colliding with non-interactive stuff in the level
// id is set to the id of colliding object
//------------------------------------------------------------------------
bool Level::collidingWithLevel(pyrodactyl::event::Info &info, pyrodactyl::anim::Sprite &s) {
_terrain.collideWithNoWalk(s.boundRect(), s._collideData);
_terrain.collideWithStairs(s.boundRect(), s._velMod);
if (_terrain.collideWithMusic(s.boundRect(), _music)) {
if (_music._track)
g_engine->_musicManager->playMusic(_music._id);
else
g_engine->_musicManager->playEffect(_music._id, _music._loops);
}
// If we are colliding with something, return true
return !s._collideData.empty();
}
} // End of namespace Crab

View File

@@ -0,0 +1,271 @@
/* 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 "graphics/managed_surface.h"
#include "crab/ScreenSettings.h"
#include "crab/level/level.h"
namespace Crab {
using namespace TMX;
using namespace pyrodactyl::stat;
using namespace pyrodactyl::anim;
using namespace pyrodactyl::level;
using namespace pyrodactyl::image;
using namespace pyrodactyl::people;
using namespace pyrodactyl::input;
// Purpose: Pre render the terrain layer
void Level::preDraw() {
Graphics::ManagedSurface *surf = new Graphics::ManagedSurface(_terrain.w(), _terrain.h(), g_engine->_format);
uint layerCount = 0u;
for (auto l = _terrain._layer.begin(); l != _terrain._layer.end(); ++l, ++layerCount) {
g_engine->_imageManager->_tileset.preDraw(*l, _terrain._tileSize, surf);
// Draw the normal sprites if this is the layer for it
if (layerCount == _terrain._spriteLayer)
preDrawObjects(surf);
}
// This is to ensure we don't miss out on drawing sprites
if (layerCount <= _terrain._spriteLayer)
preDrawObjects(surf);
_img.load(surf);
delete surf;
}
//------------------------------------------------------------------------
// Purpose: Draw the level
//------------------------------------------------------------------------
void Level::draw(pyrodactyl::event::Info &info) {
setCamera();
sortObjectsToDraw();
// Background sprites are assumed to be sorted by their layer count
auto b = _background.begin();
uint layerCount = 0u;
// Draw the terrain layer
g_engine->_imageManager->_tileset.draw(_terrain._layer[0], _camera, _terrain._tileSize, _objects[_playerIndex].posRect(), _img);
Vector2i pos = _objects[_playerIndex]._aiData._dest;
Rect newpos(pos.x - (_destMarker._size.x / 2), pos.y - (_destMarker._size.y / 2), _destMarker._size.x, _destMarker._size.y);
for (auto l = _terrain._layer.begin(); l != _terrain._layer.end(); ++l, ++layerCount) {
// Draw the background sprites
for (; b != _background.end(); ++b) {
if ((uint)b->_layer > layerCount) // We don't have any sprites to draw at this layer
break;
else if ((uint)b->_layer == layerCount && b->visible())
b->draw(info, _camera);
}
// Draw the normal sprites if this is the layer for it
if (layerCount == _terrain._spriteLayer)
drawObjects(info);
// Draw the terrain layer
g_engine->_imageManager->_tileset.forceDraw(*l, _camera, _terrain._tileSize, _objects[_playerIndex].posRect());
}
// Draw the background sprites
for (; b != _background.end(); ++b) {
if ((uint)b->_layer > layerCount) // We don't have any sprites to draw at this layer
break;
else if ((uint)b->_layer >= layerCount && b->visible())
b->draw(info, _camera);
}
// This is to ensure we don't miss out on drawing sprites
if (layerCount <= _terrain._spriteLayer)
drawObjects(info);
// Fliers are drawn above every sprite but below popup text
for (auto &i : _fly) {
// Only draw if it is supposed to be flying
if (i._aiData._walk._enabled)
i.draw(info, _camera);
}
// Draw popup text over all level layers
for (auto &i : _objects) {
// Only draw popups for visible sprites
if (i.visible()) {
if (i.popupShow())
i.drawPopup(_pop, _camera);
else {
// Only draw their name if they are
//(a) hovered over by the mouse, OR
//(b) are in talk range and don't have popup text over their head
if (i._hover || (info.lastPerson() == i.id() && !i.popupShow()))
_talkNotify.draw(info, i, _camera);
}
}
}
if (g_engine->_debugDraw & DRAW_TMX)
_terrain.drawDebug(_camera);
}
//------------------------------------------------------------------------
// Purpose: Draw sprites and prop layers in sequences according to depth
//------------------------------------------------------------------------
void Level::drawObjects(pyrodactyl::event::Info &info) {
// Draw player destination marker
if (_objects[_playerIndex]._aiData._dest._active)
_destMarker.draw(_objects[_playerIndex]._aiData._dest, _camera);
Vector2i pos = _objects[_playerIndex]._aiData._dest;
Rect newpos(pos.x - (_destMarker._size.x / 2), pos.y - (_destMarker._size.y / 2), _destMarker._size.x, _destMarker._size.y);
if (_terrain._prop.empty()) {
for (auto &entry : _objSeq) {
if (entry.second->visible() && layerVisible(entry.second))
entry.second->draw(info, _camera);
}
} else {
auto a = _terrain._prop.begin();
auto b = _objSeq.begin();
while (a != _terrain._prop.end() && b != _objSeq.end()) {
auto obj = b->second;
if (a->_pos.y + a->_pos.h < obj->y() + obj->h()) {
for (auto &i : a->_boundRect) {
// draw prop bounds if requested
if (g_engine->_debugDraw & DRAW_PROP_BOUNDS)
i.draw(-_camera.x, -_camera.y, 128, 128, 0, 255);
if (i.collide(_objects[_playerIndex].posRect())) {
g_engine->_imageManager->_tileset.forceDraw(*a, _camera, _terrain._tileSize, _objects[_playerIndex].posRect());
}
if (i.contains(_objects[_playerIndex]._aiData._dest)) {
g_engine->_imageManager->_tileset.forceDraw(*a, _camera, _terrain._tileSize, newpos);
}
}
++a;
} else {
if (obj->visible() && layerVisible(obj))
obj->draw(info, _camera);
++b;
}
}
if (a == _terrain._prop.end()) {
for (; b != _objSeq.end(); ++b) {
auto obj = b->second;
if (obj->visible() && layerVisible(obj))
obj->draw(info, _camera);
}
} else if (b == _objSeq.end()) {
for (; a != _terrain._prop.end(); ++a) {
for (auto &i : a->_boundRect) {
// draw prop bounds if requested
if (g_engine->_debugDraw & DRAW_PROP_BOUNDS)
i.draw(-_camera.x, -_camera.y, 128, 128, 0, 255);
if (i.collide(_objects[_playerIndex].posRect())) {
g_engine->_imageManager->_tileset.forceDraw(*a, _camera, _terrain._tileSize, _objects[_playerIndex].posRect());
}
if (i.contains(_objects[_playerIndex]._aiData._dest)) {
g_engine->_imageManager->_tileset.forceDraw(*a, _camera, _terrain._tileSize, newpos);
}
}
}
}
}
}
void Level::preDrawObjects(Graphics::ManagedSurface *surf) {
if (_terrain._prop.empty()) {
return;
} else {
auto a = _terrain._prop.begin();
auto b = _objSeq.begin();
while (a != _terrain._prop.end() && b != _objSeq.end()) {
auto obj = b->second;
if (a->_pos.y + a->_pos.h < obj->y() + obj->h()) {
g_engine->_imageManager->_tileset.preDraw(*a, _terrain._tileSize, surf);
++a;
} else {
++b;
}
}
if (a == _terrain._prop.end()) {
} else if (b == _objSeq.end()) {
for (; a != _terrain._prop.end(); ++a)
g_engine->_imageManager->_tileset.preDraw(*a, _terrain._tileSize, surf);
}
}
}
//------------------------------------------------------------------------
// Purpose: Sort objects to draw them according to their Y coordinates
//------------------------------------------------------------------------
bool Level::operator()(int i, int j) {
return _objects[i].y() + _objects[i].h() < _objects[j].y() + _objects[j].h();
}
void Level::sortObjectsToDraw() {
// add each object to the map to sort it
_objSeq.clear();
for (auto &object : _objects)
_objSeq.insert(Common::Pair<int, Sprite *>(object.y() + object.h(), &object));
}
//------------------------------------------------------------------------
// Purpose: Center the camera on the player for scrolling levels
//------------------------------------------------------------------------
void Level::setCamera() {
// Use the focus points of sprites
Vector2i focus = _objects[_playerIndex].camFocus();
// Center the camera over the player
_camera.x = focus.x - (g_engine->_screenSettings->_cur.w / 2);
_camera.y = focus.y - (g_engine->_screenSettings->_cur.h / 2);
// Keep the camera in bounds
if (_camera.x > _terrain.w() - _camera.w)
_camera.x = _terrain.w() - _camera.w;
if (_camera.y > _terrain.h() - _camera.h)
_camera.y = _terrain.h() - _camera.h;
if (_camera.x < 0)
_camera.x = 0;
if (_camera.y < 0)
_camera.y = 0;
}
} // End of namespace Crab

View File

@@ -0,0 +1,238 @@
/* 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/ScreenSettings.h"
#include "crab/level/level.h"
namespace Crab {
using namespace TMX;
using namespace pyrodactyl::stat;
using namespace pyrodactyl::anim;
using namespace pyrodactyl::level;
using namespace pyrodactyl::image;
using namespace pyrodactyl::people;
using namespace pyrodactyl::input;
//------------------------------------------------------------------------
// Purpose: Used to sort background sprites
//------------------------------------------------------------------------
static bool compSpriteLayer(const Sprite &a, const Sprite &b) {
return (a._layer < b._layer);
}
//------------------------------------------------------------------------
// Purpose: Load the level
//------------------------------------------------------------------------
void Level::load(const Common::Path &filename, pyrodactyl::event::Info &info,
pyrodactyl::event::TriggerSet &gameOver, const int &playerX, const int &playerY) {
reset();
XMLDoc conf(filename);
if (conf.ready()) {
rapidxml::xml_node<char> *node = conf.doc()->first_node("level");
if (nodeValid(node)) {
Common::String vis;
loadStr(vis, "map", node, false);
if (vis == "false")
_showmap.set(false);
else
_showmap.set(true);
if (nodeValid("preview", node))
loadPath(_previewPath, "path", node->first_node("preview"));
if (nodeValid("music", node)) {
loadNum(_music._id, "id", node->first_node("music"));
g_engine->_musicManager->playMusic(_music._id);
}
if (nodeValid("map", node)) {
rapidxml::xml_node<char> *mapnode = node->first_node("map");
Common::Path path;
Common::String tmxfile;
loadPath(path, "path", mapnode);
loadStr(tmxfile, "file", mapnode);
_terrain.load(path, tmxfile);
// Remember to load the terrain data before constructing the pathfinding grid
_pathfindingGrid.setupNodes(_terrain);
_terrain._grid = &_pathfindingGrid;
if (nodeValid("loc", mapnode))
_mapLoc.load(mapnode->first_node("loc"));
if (nodeValid("clip", mapnode)) {
rapidxml::xml_node<char> *clipnode = mapnode->first_node("clip");
loadNum(_mapClip._id, "id", clipnode);
_mapClip._rect.load(clipnode);
}
}
if (nodeValid("sprites", node)) {
rapidxml::xml_node<char> *spritenode = node->first_node("sprites");
int count = 0;
for (auto n = spritenode->first_node(); n != nullptr; n = n->next_sibling(), ++count) {
Sprite s;
s.load(n, _animSet);
Common::String str = n->name();
if (str == "player") {
_playerIndex = _objects.size();
if (playerX != -1 && playerY != -1) {
s.x(playerX);
s.y(playerY);
}
}
_objects.push_back(s);
}
}
if (nodeValid("background", node)) {
rapidxml::xml_node<char> *spritenode = node->first_node("background");
for (auto n = spritenode->first_node(); n != nullptr; n = n->next_sibling()) {
Sprite s;
s.load(n, _animSet);
_background.push_back(s);
}
Common::sort(_background.begin(), _background.end(), compSpriteLayer);
}
if (nodeValid("fly", node)) {
rapidxml::xml_node<char> *spritenode = node->first_node("fly");
for (auto n = spritenode->first_node(); n != nullptr; n = n->next_sibling()) {
Sprite s;
s.load(n, _animSet);
// Set the timer target for the first time
//s.ai_data.walk.timer.Target(sc_default.fly.delay_min + (gRandom.Num() % sc_default.fly.delay_max));
s._aiData._walk._timer.target(_scDefault._fly._delayMax);
_fly.push_back(s);
}
}
if (nodeValid("movement", node)) {
rapidxml::xml_node<char> *movnode = node->first_node("movement");
for (auto n = movnode->first_node("set"); n != nullptr; n = n->next_sibling("set"))
_moveSet.push_back(n);
}
if (nodeValid("popup", node, false))
_pop.load(node->first_node("popup"));
gameOver.clear();
if (nodeValid("game_over", node, false))
gameOver.load(node->first_node("game_over"));
else if (_playerIndex < _objects.size()) {
// The default lose condition is the death of the player
using namespace pyrodactyl::event;
Trigger t;
t._type = TRIG_STAT;
t._target = STATNAME_HEALTH;
t._subject = _objects[_playerIndex].id();
t._operation = "<";
t._val = "1";
gameOver.add(t);
}
calcProperties(info);
}
}
setCamera();
}
//------------------------------------------------------------------------
// Purpose: Build an index of all animation files, called once at start
//------------------------------------------------------------------------
void Level::loadMoves(const Common::Path &filename) {
XMLDoc movList(filename);
if (movList.ready()) {
rapidxml::xml_node<char> *node = movList.doc()->first_node("movelist");
for (auto n = node->first_node("set"); n != nullptr; n = n->next_sibling("set")) {
uint pos = _animSet.size();
loadNum(pos, "id", n);
if (pos >= _animSet.size())
_animSet.resize(pos + 1);
// See if there is an alternate moveset for low quality setting
// If no, just load the regular one
if (!g_engine->_screenSettings->_quality) {
if (!loadPath(_animSet[pos], "path_low", n))
loadPath(_animSet[pos], "path", n);
} else
loadPath(_animSet[pos], "path", n);
}
}
}
//------------------------------------------------------------------------
// Purpose: Load the default sprite constant parameters
//------------------------------------------------------------------------
void Level::loadConst(const Common::Path &filename) {
XMLDoc doc(filename);
if (doc.ready()) {
rapidxml::xml_node<char> *node = doc.doc()->first_node("constant");
if (nodeValid(node))
_scDefault.load(node);
}
}
//------------------------------------------------------------------------
// Purpose: Save all sprite positions to save file
//------------------------------------------------------------------------
void Level::saveState(rapidxml::xml_document<> &doc, rapidxml::xml_node<char> *root) {
root->append_attribute(doc.allocate_attribute("player_index", g_engine->_stringPool->get(_playerIndex)));
for (auto &i : _objects) {
rapidxml::xml_node<char> *child = doc.allocate_node(rapidxml::node_element, "sprite");
i.saveState(doc, child);
root->append_node(child);
}
}
//------------------------------------------------------------------------
// Purpose: Load all sprite positions from save file
//------------------------------------------------------------------------
void Level::loadState(rapidxml::xml_node<char> *node) {
loadNum(_playerIndex, "player_index", node);
auto i = _objects.begin();
for (auto *n = node->first_node("sprite"); n != nullptr && i != _objects.end(); n = n->next_sibling("sprite"), ++i)
i->loadState(n);
}
} // End of namespace Crab

View File

@@ -0,0 +1,50 @@
/* 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/image/ImageManager.h"
#include "crab/level/level_objects.h"
namespace Crab {
using namespace pyrodactyl::image;
using namespace pyrodactyl::level;
void PlayerDestMarker::load(rapidxml::xml_node<char> *node) {
loadImgKey(_img, "dest", node);
_size.x = g_engine->_imageManager->getTexture(_img).w();
_size.y = g_engine->_imageManager->getTexture(_img).h();
}
void PlayerDestMarker::draw(const Vector2i &pos, const Rect &camera) {
g_engine->_imageManager->draw(pos.x - (_size.x / 2) - camera.x, pos.y - (_size.y / 2) - camera.y, _img);
}
} // End of namespace Crab

View File

@@ -0,0 +1,72 @@
/* 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_LEVEL_OBJECTS_H
#define CRAB_LEVEL_OBJECTS_H
#include "crab/image/ImageManager.h"
#include "crab/Rectangle.h"
namespace Crab {
namespace pyrodactyl {
namespace level {
// Is the world map accessible from this level?
struct MapVis {
bool _normal, _current;
MapVis() {
set(true);
}
void set(bool val) {
_normal = val;
_current = val;
}
};
// Used for drawing the destination marker for point and click movement
struct PlayerDestMarker {
ImageKey _img;
Vector2i _size;
PlayerDestMarker() {
_img = 0;
}
void load(rapidxml::xml_node<char> *node);
void draw(const Vector2i &pos, const Rect &camera);
};
} // End of namespace level
} // End of namespace pyrodactyl
} // End of namespace Crab
#endif // CRAB_LEVEL_OBJECTS_H

View File

@@ -0,0 +1,60 @@
/* 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/level/talknotify.h"
namespace Crab {
using namespace pyrodactyl::text;
using namespace pyrodactyl::level;
using namespace pyrodactyl::image;
void TalkNotify::load(rapidxml::xml_node<char> *node) {
_offset.load(node);
loadNum(_font, "font", node);
loadAlign(_align, node);
loadNum(_col, "col", node);
}
void TalkNotify::draw(pyrodactyl::event::Info &info, pyrodactyl::anim::Sprite &s, const Rect &camera) {
Rect rect = s.posRect();
// Find position to draw name (over the sprite's top edge)
Vector2i pos;
pos.x = rect.x + rect.w / 2 + _offset.x;
pos.y = rect.y + _offset.y;
// Find the sprite name
Common::String text = info.getName(s.id());
g_engine->_textManager->draw(pos.x - camera.x, pos.y - camera.y, text, _col, _font, _align, true);
}
} // End of namespace Crab

View File

@@ -0,0 +1,62 @@
/* 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_TALKNOTIFY_H
#define CRAB_TALKNOTIFY_H
#include "crab/animation/sprite.h"
namespace Crab {
namespace pyrodactyl {
namespace level {
class TalkNotify {
// The offset to the sprite at which the name is drawn - along with alignment, font and color used to draw the name
Vector2i _offset;
FontKey _font;
int _col;
Align _align;
public:
TalkNotify() {
_font = 0;
_col = 0;
_align = ALIGN_CENTER;
}
void load(rapidxml::xml_node<char> *node);
void draw(pyrodactyl::event::Info &info, pyrodactyl::anim::Sprite &s, const Rect &camera);
};
} // End of namespace level
} // End of namespace pyrodactyl
} // End of namespace Crab
#endif // CRAB_TALKNOTIFY_H