#include <Moof/Tilemap.hh>
+struct Character;
+typedef boost::shared_ptr<Character> CharacterP;
+
+
/**
* Parent class of animate objects with "personalities." This basically
* includes the heroine herself and the bad guys.
*/
-class Character : public Mf::Entity
+struct Character : public Mf::Entity
{
-public:
-
struct Derivative
{
Mf::Vector2 velocity;
}
};
-
- Character(const std::string& name);
- virtual ~Character();
-
- void update(Mf::Scalar t, Mf::Scalar dt);
- void handleEvent(const Mf::Event& event);
- void draw(Mf::Scalar alpha) const;
-
- Mf::Tilemap& getTilemap();
- Mf::Animation& getAnimation();
-
State previous;
State current;
stlplus::ntree<Mf::OctreeNode>::iterator treeNode;
-private:
- void updateContainers();
+private:
static const Mf::Scalar z = 96.0;
Mf::Tilemap tilemap_;
Mf::Animation animation_;
-};
-typedef boost::shared_ptr<Character> CharacterPtr;
+ void updateContainers();
+
+public:
+
+ inline static CharacterP alloc(const std::string& name)
+ {
+ return CharacterP(new Character(name));
+ }
+
+ Character(const std::string& name);
+ virtual ~Character();
+
+ void update(Mf::Scalar t, Mf::Scalar dt);
+ void handleEvent(const Mf::Event& event);
+ void draw(Mf::Scalar alpha) const;
+
+ Mf::Tilemap& getTilemap();
+ Mf::Animation& getAnimation();
+};
inline Character::State operator*(Mf::Scalar scalar, const Character::State& state)
* instances.
*/
-struct Animation::Impl
+class Animation::Impl
{
+ friend class Animation;
/**
* Contains "global" animation data for the various animations which get
* which wants to use these loaded sequences.
*/
- struct GlobalData : public Mippleton<GlobalData>
+ class Data : public Mippleton<Data>
{
+ friend class Impl;
+ friend class Mippleton<Data>;
+
/**
* A frame of an animation sequence. A frame is merely an index which
* presumably represents a "slide" or tile which should be displayed,
* frame map which is probably loaded within an animation file.
*/
- Frame(SerializablePtr root) :
+ Frame(SerializableP root) :
index(0),
duration(1.0)
{
- std::map<std::string,SerializablePtr> rootObj;
+ Serializable::Map rootObj;
if (root->get(rootObj))
{
- std::map<std::string,SerializablePtr>::iterator it;
+ Serializable::Map::iterator it;
for (it = rootObj.begin(); it != rootObj.end(); ++it)
{
* constructor which loads each individual frame.
*/
- Sequence(SerializablePtr root) :
+ Sequence(SerializableP root) :
delay(0.0),
loop(true)
{
- std::map<std::string,SerializablePtr> rootObj;
+ Serializable::Map rootObj;
if (root->get(rootObj))
{
- std::map<std::string,SerializablePtr>::iterator it;
+ Serializable::Map::iterator it;
for (it = rootObj.begin(); it != rootObj.end(); ++it)
{
std::string key = (*it).first;
if (key == "frames")
{
- std::vector<SerializablePtr> framesObj;
+ Serializable::Array framesObj;
if ((*it).second->get(framesObj))
{
- std::vector<SerializablePtr>::iterator jt;
+ Serializable::Array::iterator jt;
for (jt = framesObj.begin();
jt != framesObj.end(); ++jt)
Deserializer deserializer(filePath);
- SerializablePtr root = deserializer.deserialize();
+ SerializableP root = deserializer.deserialize();
if (root)
{
- std::map<std::string,SerializablePtr> rootObj;
+ Serializable::Map rootObj;
if (root->get(rootObj))
{
- std::map<std::string,SerializablePtr>::iterator it;
+ Serializable::Map::iterator it;
for (it = rootObj.begin(); it != rootObj.end(); ++it)
{
* registers itself as a mippleton and then loads the animation data.
*/
- explicit GlobalData(const std::string& name) :
- Mippleton<GlobalData>(name)
+ explicit Data(const std::string& name) :
+ Mippleton<Data>(name)
{
loadFromFile();
}
*/
Impl(const std::string& name) :
- data(GlobalData::getInstance(name)),
+ data(Data::getInstance(name)),
currentSequence(0),
frameCounter(0),
frameIndex(0),
void startSequence(const std::string& name)
{
- std::map<std::string,GlobalData::Sequence>::iterator it;
+ std::map<std::string,Data::Sequence>::iterator it;
it = data->sequences.find(name);
}
}
- boost::shared_ptr<GlobalData> data; ///< Internal data.
+ boost::shared_ptr<Data> data; ///< Internal data.
- GlobalData::Sequence* currentSequence; ///< Active sequence.
- unsigned frameCounter; ///< Current frame.
- unsigned frameIndex; ///< Index of current frame.
- Scalar timeAccum; ///< Time accumulation.
- Scalar frameDuration; ///< Scaled frame duration.
+ Data::Sequence* currentSequence; ///< Active sequence.
+ unsigned frameCounter; ///< Current frame.
+ unsigned frameIndex; ///< Index of current frame.
+ Scalar timeAccum; ///< Time accumulation.
+ Scalar frameDuration; ///< Scaled frame duration.
};
namespace Mf {
+class Animation;
+typedef boost::shared_ptr<Animation> AnimationP;
+
/**
* A class to manage frame-based animation. Animation sequences can be loaded
* from file, then named sequences are started. The animation is updated
class Animation : public Resource
{
+ class Impl;
+ boost::shared_ptr<Impl> impl_;
+
public:
+
+ static AnimationP alloc(const std::string& name)
+ {
+ return AnimationP(new Animation(name));
+ }
+
Animation(const std::string& name);
void startSequence(const std::string& name);
unsigned getFrame() const;
static std::string getPath(const std::string& name);
-
-private:
- class Impl;
- boost::shared_ptr<Impl> impl_;
};
#include <yajl/yajl_parse.h>
#include "Deserializer.hh"
+#include "Log.hh"
#include "Serializable.hh"
namespace Mf {
-class Deserializer::DeserializerImpl
+class Deserializer::Impl
{
public:
- DeserializerImpl(const std::string& filePath, bool comments = false,
+ Impl(const std::string& filePath, bool comments = false,
bool check = false)
{
std::ifstream* input = new std::ifstream(filePath.c_str());
init(*input, true, comments, check);
}
- DeserializerImpl(std::istream& input, bool comments = false,
+ Impl(std::istream& input, bool comments = false,
bool check = false)
{
init(input, false, comments, check);
}
- ~DeserializerImpl()
+ ~Impl()
{
while (!parsed.empty())
{
yajl_free(hand);
}
- void throwError()
+ void raise()
{
unsigned char* errorStr = yajl_get_error(hand, 0, 0, 0);
- Deserializer::Exception exception((char*)errorStr);
+ logError("parser error: %s", errorStr);
yajl_free_error(hand, errorStr);
- throw exception;
+
+ throw Exception(Exception::PARSING_FAILED);
}
static int parsedNull(void* ctx)
{
- ((DeserializerImpl*)ctx)->parsed.push(new SerializableNull);
+ ((Impl*)ctx)->parsed.push(new SerializableNull);
return 1;
}
static int parsedBoolean(void* ctx, int value)
{
- ((DeserializerImpl*)ctx)->parsed.push(new SerializableBoolean(value));
+ ((Impl*)ctx)->parsed.push(new SerializableBasic<Serializable::Boolean>(value));
return 1;
}
static int parsedInteger(void* ctx, long value)
{
- ((DeserializerImpl*)ctx)->parsed.push(new SerializableInteger(value));
+ ((Impl*)ctx)->parsed.push(new SerializableBasic<Serializable::Integer>(value));
return 1;
}
static int parsedFloat(void* ctx, double value)
{
- ((DeserializerImpl*)ctx)->parsed.push(new SerializableReal(value));
+ ((Impl*)ctx)->parsed.push(new SerializableBasic<Serializable::Float>(value));
return 1;
}
static int parsedString(void* ctx, const unsigned char* value,
unsigned length)
{
- SerializableString* parsed =
- new SerializableString(std::string((char*)value, length));
- ((DeserializerImpl*)ctx)->parsed.push(parsed);
+ ((Impl*)ctx)->parsed.push(new SerializableBasic<Serializable::String>(std::string((char*)value, length)));
return 1;
}
static int parsedBeginMap(void* ctx)
{
- ((DeserializerImpl*)ctx)->parsed.push(new SerializableMap);
+ ((Impl*)ctx)->parsed.push(new SerializableBasic<Serializable::Map>);
return 1;
}
static int parsedEndMap(void* ctx)
{
- ((DeserializerImpl*)ctx)->parsed.push(0);
+ // null means the end of a structure
+ ((Impl*)ctx)->parsed.push(0);
return 1;
}
static int parsedBeginArray(void* ctx)
{
- ((DeserializerImpl*)ctx)->parsed.push(new SerializableArray);
+ ((Impl*)ctx)->parsed.push(new SerializableBasic<Serializable::Array>);
return 1;
}
static int parsedEndArray(void* ctx)
{
- ((DeserializerImpl*)ctx)->parsed.push(0);
+ // null means the end of a structure
+ ((Impl*)ctx)->parsed.push(0);
return 1;
}
if (stat != yajl_status_ok &&
stat != yajl_status_insufficient_data)
{
- throwError();
+ raise();
}
}
}
// internal data structures but rather keeps a pointer to this
static const yajl_callbacks callbacks =
{
- DeserializerImpl::parsedNull,
- DeserializerImpl::parsedBoolean,
- DeserializerImpl::parsedInteger,
- DeserializerImpl::parsedFloat,
+ Impl::parsedNull,
+ Impl::parsedBoolean,
+ Impl::parsedInteger,
+ Impl::parsedFloat,
0,
- DeserializerImpl::parsedString,
- DeserializerImpl::parsedBeginMap,
- DeserializerImpl::parsedMapKey,
- DeserializerImpl::parsedEndMap,
- DeserializerImpl::parsedBeginArray,
- DeserializerImpl::parsedEndArray
+ Impl::parsedString,
+ Impl::parsedBeginMap,
+ Impl::parsedMapKey,
+ Impl::parsedEndMap,
+ Impl::parsedBeginArray,
+ Impl::parsedEndArray
};
in = &input;
Deserializer::Deserializer(const std::string& filePath, bool comments,
bool check) :
// pass through
- impl_(new Deserializer::DeserializerImpl(filePath, comments, check)) {}
+ impl_(new Deserializer::Impl(filePath, comments, check)) {}
Deserializer::Deserializer(std::istream& input, bool comments, bool check) :
// pass through
- impl_(new Deserializer::DeserializerImpl(input, comments, check)) {}
+ impl_(new Deserializer::Impl(input, comments, check)) {}
-SerializablePtr Deserializer::deserialize()
+SerializableP Deserializer::deserialize()
{
Serializable* ptr = pullNext();
if (ptr)
{
ptr->deserialize(*this);
}
- return SerializablePtr(ptr);
+ return SerializableP(ptr);
}
#include <boost/shared_ptr.hpp>
+#include <Moof/Exception.hh>
+
namespace Mf {
class Serializable; // forward declaration
-typedef boost::shared_ptr<Serializable> SerializablePtr;
+typedef boost::shared_ptr<Serializable> SerializableP;
+
class Deserializer
{
+ class Impl;
+ boost::shared_ptr<Impl> impl_;
+
public:
/**
* deserializer.
*/
- SerializablePtr deserialize();
+ SerializableP deserialize();
/**
* Used by serializable objects to parse themselves. These methods should
* This exception is thrown upon deserialization errors.
*/
- struct Exception : std::runtime_error
+ struct Exception : public Mf::Exception
{
- explicit Exception(const std::string& what_arg) :
- std::runtime_error(what_arg) {}
+ enum
+ {
+ PARSING_FAILED = 1024
+ };
+
+ explicit Exception(unsigned error) :
+ Mf::Exception(error) {}
+
+ void raise()
+ {
+ throw *this;
+ }
+
+ const char* what() const throw()
+ {
+ switch (code)
+ {
+ case PARSING_FAILED:
+ return "parsing failed";
+ }
+ return Mf::Exception::what();
+ }
};
-
-private:
- class DeserializerImpl;
- boost::shared_ptr<DeserializerImpl> impl_;
};
printFps = false;
settings.get("video.printfps", printFps);
- video = VideoPtr(new Video(name, iconFile));
+ video = Video::alloc(name, iconFile);
video->makeActive();
}
Engine* interface;
- VideoPtr video;
+ VideoP video;
bool running;
int exitCode;
namespace Mf {
+class Entity;
+typedef boost::shared_ptr<Entity> EntityP;
+
class Camera;
+
/**
* Interface for game objects that can be drawn to the screen and have a
* specified size.
Sphere sphere_;
};
-typedef boost::shared_ptr<Entity> EntityPtr;
-
} // namespace Mf
static LogLevel logLevel_ = WARNING;
-static void printLog_(int logLevel, const char* fmt, va_list args)
+inline void printLog_(int logLevel, const char* fmt, va_list args)
{
if (logLevel_ < logLevel) return;
}
-void
-logError(const char* fmt, ...)
+void logError(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
va_end(args);
}
-void
-logWarning(const char* fmt, ...)
+void logWarning(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
va_end(args);
}
-void
-logInfo(const char* fmt, ...)
+void logInfo(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
va_end(args);
}
-void
-logDebug(const char* fmt, ...)
+void logDebug(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
*/
#include <cstdlib> // exit
-#include <cerrno> // errno
#include <cstring> // strerror
-namespace Mf {
-
-
/**
* Macro which tests an assertion and issues an logError() and exits if false.
- * This differs from the standard assert() in that this is a runtime assertion
- * test and will always be compiled in.
* @param X test to perform
*/
-#define ASSERT(X) if (!(X)) logError("false assertion at %s:%d, " #X \
- " (errno: %d, %s)", __FILE__, __LINE__, errno, strerror(errno)), exit(1)
+#if ! NDEBUG
+#define ASSERT(X) if (!(X)) Mf::logError("false assertion at %s:%d, " #X, \
+ __FILE__, __LINE__), exit(1)
+#else
+#define ASSERT(X)
+#endif
+
+
+namespace Mf {
/**
*******************************************************************************/
#include "Camera.hh"
+#include "Log.hh"
#include "Octree.hh"
stlplus::ntree<OctreeNode>::iterator Octree::insert(stlplus::ntree<OctreeNode>::iterator node,
- EntityPtr entity)
+ EntityP entity)
{
+ ASSERT(node.valid() && "invalid node passed");
+ ASSERT(entity && "null entity passed");
+
Plane::Halfspace halfspace;
int octantNum = -1;
- if (!node.valid())
- {
- std::cerr << "cannot insert into invalid node" << std::endl;
- return stlplus::ntree<OctreeNode>::iterator();
- }
-
Plane xy = node->getAabb().getPlaneXY();
halfspace = xy.intersectsSphere(entity->getSphere());
if (halfspace == Plane::INTERSECT)
}
stlplus::ntree<OctreeNode>::iterator child = tree_.child(node, octantNum);
+ ASSERT(child.valid() && "expected valid child node");
- if (child.valid())
- {
- return insert(child, entity);
- }
- else
- {
- std::cerr << "expected but found no child at index " << octantNum << std::endl;
- return stlplus::ntree<OctreeNode>::iterator();
- }
+ return insert(child, entity);
}
}
-stlplus::ntree<OctreeNode>::iterator Octree::reinsert(EntityPtr entity,
+stlplus::ntree<OctreeNode>::iterator Octree::reinsert(EntityP entity,
stlplus::ntree<OctreeNode>::iterator node)
{
- if (!node.valid())
- {
- std::cerr << "cannot move entity from invalid node" << std::endl;
- return stlplus::ntree<OctreeNode>::iterator();
- }
+ ASSERT(entity && "null entity passed");
+ ASSERT(node.valid() && "invalid node passed");
- std::list<EntityPtr>::iterator it;
+ std::list<EntityP>::iterator it;
it = std::find(node->objects.begin(), node->objects.end(), entity);
if (it != node->objects.end())
void Octree::addChild(stlplus::ntree<OctreeNode>::iterator node, int index)
{
- Aabb octant;
+ ASSERT(node.valid() && "invalid node passed");
- if (!node.valid())
- {
- std::cerr << "cannot add children to invalid node" << std::endl;
- return;
- }
+ Aabb octant;
for (int i = tree_.children(node); i <= index; ++i)
{
void Octree::draw(stlplus::ntree<OctreeNode>::iterator node, Scalar alpha)
{
- if (!node.valid())
- {
- std::cerr << "cannot draw null child node :-(" << std::endl;
- return;
- }
+ ASSERT(node.valid() && "invalid node passed");
node->draw(alpha);
for (unsigned i = 0; i < tree_.children(node); ++i)
{
stlplus::ntree<OctreeNode>::iterator child = tree_.child(node, i);
+ ASSERT(child.valid() && "expected valid child node");
- if (child.valid())
- {
- draw(child, alpha);
- }
- else
- {
- std::cerr << "node is not a leaf, but has an invalid child" << std::endl;
- }
-
+ draw(child, alpha);
}
}
void Octree::drawIfVisible(stlplus::ntree<OctreeNode>::iterator node,
Scalar alpha, const Camera& cam)
{
- //node.drawIfVisible(alpha, cam);
-
- if (!node.valid())
- {
- std::cerr << "invalid child while drawing :-(" << std::endl;
- return;
- }
+ ASSERT(node.valid() && "invalid node passed");
+ // try to cull by sphere
Frustum::Collision collision =
cam.getFrustum().containsSphere(node->getSphere());
if (collision == Frustum::OUTSIDE) return;
+ // try to cull by aabb
collision = cam.getFrustum().containsAabb(node->getAabb());
if (collision == Frustum::OUTSIDE) return;
for (unsigned i = 0; i < tree_.children(node); ++i)
{
stlplus::ntree<OctreeNode>::iterator child = tree_.child(node, i);
+ ASSERT(child.valid() && "expected valid child node");
- if (child.valid())
- {
- draw(child, alpha);
- }
- else
- {
- std::cerr << "node is not a leaf, but has an invalid child" << std::endl;
- }
-
+ draw(child, alpha);
}
}
else // collision == Frustum::INTERSECT
for (unsigned i = 0; i < tree_.children(node); ++i)
{
stlplus::ntree<OctreeNode>::iterator child = tree_.child(node, i);
+ ASSERT(child.valid() && "expected valid child node");
- if (child.valid())
- {
- drawIfVisible(child, alpha, cam);
- }
- else
- {
- std::cerr << "node is not a leaf, but has an invalid child" << std::endl;
- }
+ drawIfVisible(child, alpha, cam);
}
}
}
struct OctreeNode : public Entity
{
- std::list<EntityPtr> objects;
+ std::list<EntityP> objects;
OctreeNode()
{
void draw(Scalar alpha) const
{
- std::list<EntityPtr>::const_iterator it;
+ std::list<EntityP>::const_iterator it;
for (it = objects.begin(); it != objects.end(); ++it)
{
(*it)->draw(alpha);
}
- //if (!objects.empty())
- //aabb_.draw(); // temporary
+ if (!objects.empty())
+ aabb_.draw(); // temporary
}
void drawIfVisible(Scalar alpha, const Camera& cam) const
{
- std::list<EntityPtr>::const_iterator it;
+ std::list<EntityP>::const_iterator it;
for (it = objects.begin(); it != objects.end(); ++it)
{
(*it)->drawIfVisible(alpha, cam);
}
- //if (!objects.empty())
- //aabb_.draw();
+ if (!objects.empty())
+ aabb_.draw();
}
}
- static bool compareZOrder(EntityPtr a, EntityPtr b)
+ static bool compareZOrder(EntityP a, EntityP b)
{
return a->getSphere().point[2] < b->getSphere().point[2];
}
};
+class Octree;
+typedef boost::shared_ptr<Octree> OctreeP;
+
class Octree
{
+ stlplus::ntree<OctreeNode>::iterator
+ insert(stlplus::ntree<OctreeNode>::iterator node, EntityP entity);
+
+ void addChild(stlplus::ntree<OctreeNode>::iterator node, int index);
+
+ void draw(stlplus::ntree<OctreeNode>::iterator node, Scalar alpha);
+ void drawIfVisible(stlplus::ntree<OctreeNode>::iterator node,
+ Scalar alpha, const Camera& cam);
+
+ stlplus::ntree<OctreeNode> tree_;
+
public:
+ inline static OctreeP alloc(const OctreeNode& rootNode)
+ {
+ return OctreeP(new Octree(rootNode));
+ }
+
explicit Octree(const OctreeNode& rootNode)
{
tree_.insert(rootNode);
}
- stlplus::ntree<OctreeNode>::iterator insert(EntityPtr entity)
+ stlplus::ntree<OctreeNode>::iterator insert(EntityP entity)
{
return insert(tree_.root(), entity);
}
- stlplus::ntree<OctreeNode>::iterator reinsert(EntityPtr entity,
+ stlplus::ntree<OctreeNode>::iterator reinsert(EntityP entity,
stlplus::ntree<OctreeNode>::iterator node);
void drawIfVisible(Scalar alpha, const Camera& cam)
}
void sort();
-
-private:
- stlplus::ntree<OctreeNode>::iterator insert(stlplus::ntree<OctreeNode>::iterator node, EntityPtr entity);
-
- void addChild(stlplus::ntree<OctreeNode>::iterator node, int index);
-
- void draw(stlplus::ntree<OctreeNode>::iterator node, Scalar alpha);
- void drawIfVisible(stlplus::ntree<OctreeNode>::iterator node,
- Scalar alpha, const Camera& cam);
-
- stlplus::ntree<OctreeNode> tree_;
};
-typedef boost::shared_ptr<Octree> OctreePtr;
-
} // namespace Mf
};
- static void loadBox(Aabb& theBox, SerializablePtr obj)
+ static void loadBox(Aabb& theBox, SerializableP obj)
{
- std::vector<SerializablePtr> numbers;
+ Serializable::Array numbers;
if (obj->get(numbers) && numbers.size() == 6)
{
- double num;
+ Serializable::Float num;
if (numbers[0]->getNumber(num)) theBox.min[0] = Scalar(num);
if (numbers[1]->getNumber(num)) theBox.min[1] = Scalar(num);
}
- void loadInstructions(SerializablePtr root)
+ void loadInstructions(SerializableP root)
{
- std::vector<SerializablePtr> rootObj;
- std::vector<SerializablePtr>::iterator it;
+ Serializable::Array rootObj;
+ Serializable::Array::iterator it;
if (!root->get(rootObj))
{
}
else if (instruction == "translate")
{
- std::vector<SerializablePtr> values;
+ Serializable::Array values;
++it;
if ((*it)->get(values))
for (size_t i = 0; i < values.size(); ++i)
{
- double value;
+ Serializable::Float value;
if (values[i]->getNumber(value))
{
}
else if (instruction == "scale")
{
- std::vector<SerializablePtr> values;
+ Serializable::Array values;
++it;
if ((*it)->get(values))
{
if (values.size() == 1)
{
- double value = 1.0;
+ Serializable::Float value = 1.0;
values[0]->getNumber(value);
for (size_t i = 0; i < values.size(); ++i)
{
- double value;
+ Serializable::Float value;
if (values[i]->getNumber(value))
{
}
else if (instruction == "rotate")
{
- std::vector<SerializablePtr> values;
+ Serializable::Array values;
++it;
if ((*it)->get(values))
{
std::string axis;
size_t index = 0;
- double value = 0.0;
+ Serializable::Float value = 0.0;
if (values[0]->get(axis))
{
}
- void loadTilemap(SerializablePtr root, const Matrix4& transform,
+ void loadTilemap(SerializableP root, const Matrix4& transform,
const std::string& texture)
{
- std::map<std::string,SerializablePtr> rootObj;
- std::map<std::string,SerializablePtr>::iterator it;
+ Serializable::Map rootObj;
+ Serializable::Map::iterator it;
if (!root->get(rootObj))
{
return;
}
- std::vector<SerializablePtr> tiles;
+ Serializable::Array tiles;
if ((it = rootObj.find("tiles")) != rootObj.end() &&
(*it).second->get(tiles) &&
tiles.size() % width == 0)
{
- std::vector<SerializablePtr>::iterator jt;
+ Serializable::Array::iterator jt;
int w, h;
height = tiles.size() / width;
for (w = 0; w < width && jt != tiles.end(); ++w, ++jt)
{
- long index;
+ Serializable::Integer index;
if ((*jt)->get(index))
{
}
}
- void loadBillboard(SerializablePtr root, const Matrix4& transform,
+ void loadBillboard(SerializableP root, const Matrix4& transform,
const std::string& texture)
{
- std::map<std::string,SerializablePtr> rootObj;
- std::map<std::string,SerializablePtr>::iterator it;
+ Serializable::Map rootObj;
+ Serializable::Map::iterator it;
Tilemap::Index index = 0;
long width = 1;
{
if ((it = rootObj.find("tile")) != rootObj.end())
{
- long value;
+ Serializable::Integer value;
if ((*it).second->get(value))
{
index = Tilemap::Index(value);
std::string filePath = Scene::getPath(getName());
Deserializer deserializer(filePath, true);
- SerializablePtr root = deserializer.deserialize();
+ SerializableP root = deserializer.deserialize();
- std::map<std::string,SerializablePtr> rootObj;
- std::map<std::string,SerializablePtr>::iterator it;
+ Serializable::Map rootObj;
+ Serializable::Map::iterator it;
if (!root || !root->get(rootObj))
{
}
// create the tree to store the quads
- octree = OctreePtr(new Octree(maximumBounds));
+ octree = Octree::alloc(maximumBounds);
if ((it = rootObj.find("instructions")) != rootObj.end())
{
Aabb playfieldBounds;
Aabb maximumBounds;
- OctreePtr octree;
+ OctreeP octree;
};
}
-OctreePtr Scene::getOctree() const
+OctreeP Scene::getOctree() const
{
// pass through
return impl_->octree;
namespace Mf {
+class Scene;
+typedef boost::shared_ptr<Scene> SceneP;
+
class Camera;
+
class Scene : public Resource
{
+ class Impl;
+ boost::shared_ptr<Impl> impl_;
+
public:
+
+ inline static SceneP alloc(const std::string& name)
+ {
+ return SceneP(new Scene(name));
+ }
+
Scene(const std::string& name);
void draw(Scalar alpha, const Camera& cam) const;
void refresh();
- OctreePtr getOctree() const;
+ OctreeP getOctree() const;
static std::string getPath(const std::string& name);
-
-private:
- class Impl;
- boost::shared_ptr<Impl> impl_;
};
}
-bool Serializable::get(long& value)
+bool Serializable::get(Integer& value)
{
return false;
}
-bool Serializable::get(double& value)
+bool Serializable::get(Float& value)
{
return false;
}
-bool Serializable::get(bool& value)
+bool Serializable::get(Boolean& value)
{
return false;
}
-bool Serializable::get(std::string& value)
+bool Serializable::get(String& value)
{
return false;
}
-bool Serializable::get(std::wstring& value)
+bool Serializable::get(WideString& value)
{
return false;
}
-bool Serializable::get(std::vector<SerializablePtr>& value)
+bool Serializable::get(Array& value)
{
return false;
}
-bool Serializable::get(std::map<std::string,SerializablePtr>& value)
+bool Serializable::get(Map& value)
{
return false;
}
}
-bool Serializable::getNumber(long& value)
+bool Serializable::getNumber(Integer& value)
{
if (get(value))
{
}
else
{
- double doubleValue;
+ Float doubleValue;
if (get(doubleValue))
{
- value = long(doubleValue);
+ value = Integer(doubleValue);
return true;
}
}
return false;
}
-bool Serializable::getNumber(double& value)
+bool Serializable::getNumber(Float& value)
{
if (get(value))
{
}
else
{
- long longValue;
+ Integer longValue;
if (get(longValue))
{
- value = double(longValue);
+ value = Float(longValue);
return true;
}
}
* Interface for a type which can be serialized and deserialized.
*/
-class Serializable
+struct Serializable
{
-public:
+ // basic types which are serializable
+ typedef long Integer;
+ typedef double Float;
+ typedef bool Boolean;
+ typedef std::string String;
+ typedef std::wstring WideString;
+ typedef std::vector<SerializableP> Array;
+ typedef std::map<String,SerializableP> Map;
+
+
virtual ~Serializable();
virtual void serialize(Serializer& out) const = 0;
virtual void print() const = 0;
- virtual bool get(long& value);
- virtual bool get(double& value);
- virtual bool get(bool& value);
- virtual bool get(std::string& value);
- virtual bool get(std::wstring& value);
- virtual bool get(std::vector<SerializablePtr>& value);
- virtual bool get(std::map<std::string,SerializablePtr>& value);
+ virtual bool get(Integer& value);
+ virtual bool get(Float& value);
+ virtual bool get(Boolean& value);
+ virtual bool get(String& value);
+ virtual bool get(WideString& value);
+ virtual bool get(Array& value);
+ virtual bool get(Map& value);
/*
* To get a number value which may have been parsed as either an integer or
* double, use these getters instead.
*/
- bool getNumber(long&);
- bool getNumber(double&);
+ bool getNumber(Integer& value);
+ bool getNumber(Float& value);
virtual bool isNull();
};
template <class T>
-class SerializableBase : public Serializable
+class SerializableBasic : public Serializable
{
+ T value_;
+
public:
- SerializableBase() {}
- SerializableBase(const T& value) :
+
+ SerializableBasic() {}
+ SerializableBasic(const T& value) :
value_(value) {}
void serialize(Serializer& out) const;
void print() const;
bool get(T& value);
-public:
- T value_;
};
-class SerializableNull : public Serializable
+struct SerializableNull : public Serializable
{
-public:
SerializableNull() {}
+
void serialize(Serializer& out) const;
void deserialize(Deserializer& in);
};
-typedef SerializableBase<long> SerializableInteger;
-typedef SerializableBase<double> SerializableReal;
-typedef SerializableBase<bool> SerializableBoolean;
-typedef SerializableBase<std::string> SerializableString;
-typedef SerializableBase<std::wstring> SerializableWideString;
-typedef SerializableBase<std::vector<SerializablePtr> > SerializableArray;
-typedef SerializableBase<std::map<std::string,SerializablePtr> >
- SerializableMap;
-
-
-
template <class T>
-inline void SerializableBase<T>::serialize(Serializer& out) const
+inline void SerializableBasic<T>::serialize(Serializer& out) const
{
out.push(value_);
}
template <>
inline void
-SerializableBase<std::vector<SerializablePtr> >::serialize(Serializer& out) const
+SerializableBasic<Serializable::Array>::serialize(Serializer& out) const
{
out.pushArrayHead();
- std::vector<SerializablePtr>::const_iterator it;
+ std::vector<SerializableP>::const_iterator it;
for (it = value_.begin(); it < value_.end(); ++it)
{
(*it)->serialize(out);
template <>
inline void
-SerializableBase<std::map<std::string,SerializablePtr> >::serialize(Serializer& out) const
+SerializableBasic<Serializable::Map>::serialize(Serializer& out) const
{
out.pushMapHead();
- std::map<std::string,SerializablePtr>::const_iterator it;
- for (it = value_.begin(); it != value_.end(); ++it)
+ for (Map::const_iterator it = value_.begin(); it != value_.end(); ++it)
{
out.push((*it).first);
(*it).second->serialize(out);
template <class T>
-inline void SerializableBase<T>::deserialize(Deserializer& in)
+inline void SerializableBasic<T>::deserialize(Deserializer& in)
{
in.pop();
}
template <>
-inline void SerializableBase<std::vector<SerializablePtr> >::deserialize(Deserializer& in)
+inline void
+SerializableBasic<Serializable::Array>::deserialize(Deserializer& in)
{
- SerializablePtr obj;
+ SerializableP obj;
in.pop();
while (obj = in.deserialize())
{
- value_.push_back(SerializablePtr(obj));
+ value_.push_back(obj);
}
in.pop();
template <>
inline void
-SerializableBase<std::map<std::string,SerializablePtr> >::deserialize(Deserializer& in)
+SerializableBasic<Serializable::Map>::deserialize(Deserializer& in)
{
- SerializablePtr obj;
+ SerializableP obj;
in.pop();
template <class T>
-inline void SerializableBase<T>::print() const
+inline void SerializableBasic<T>::print() const
{
std::cout << std::boolalpha << typeid(T).name() << "(" << value_ << ")";
}
template <>
-inline void SerializableBase<std::wstring>::print() const
+inline void SerializableBasic<Serializable::WideString>::print() const
{
std::wcout << value_;
}
template <>
-inline void SerializableBase<std::vector<SerializablePtr> >::print() const
+inline void SerializableBasic<Serializable::Array>::print() const
{
std::cout << "array";
}
template <>
-inline void SerializableBase<std::map<std::string,SerializablePtr> >::print() const
+inline void SerializableBasic<Serializable::Map>::print() const
{
std::cout << "map";
}
template <class T>
-inline bool SerializableBase<T>::get(T& value)
+inline bool SerializableBasic<T>::get(T& value)
{
value = value_;
return true;
namespace Mf {
-class Serializer::SerializerImpl
+struct Serializer::Impl
{
-public:
- SerializerImpl(const std::string& filePath, const std::string& indent = "")
+ Impl(const std::string& filePath, const std::string& indent = "")
{
std::ofstream* output = new std::ofstream(filePath.c_str());
init(*output, true, indent);
}
- SerializerImpl(std::ostream& output, const std::string& indent = "")
+ Impl(std::ostream& output, const std::string& indent = "")
{
init(output, false, indent);
}
- ~SerializerImpl()
+ ~Impl()
{
if (deleteWhenDone)
{
yajl_gen_free(gen);
}
- static void throwError(yajl_gen_status err)
+ static void raise(yajl_gen_status err)
{
switch (err)
{
case yajl_gen_generation_complete:
- throw Serializer::Exception("the archive has already terminated");
+ throw Serializer::Exception(Exception::ARCHIVE_TERMINATED);
case yajl_gen_keys_must_be_strings:
- throw Serializer::Exception("map keys must be strings");
+ throw Serializer::Exception(Exception::KEYS_MUST_BE_STRINGS);
case yajl_max_depth_exceeded:
- throw Serializer::Exception("maximum archive depth exceeded");
+ throw Serializer::Exception(Exception::RECURSION_TOO_DEEP);
case yajl_gen_in_error_state:
- throw Serializer::Exception("serializer already in error state");
+ throw Serializer::Exception(Exception::ALREADY_FAILED);
case yajl_gen_status_ok:
; // There is no error here. Move along...
}
bool deleteWhenDone;
private:
+
void init(std::ostream& output, bool deleteOut, const std::string& indent)
{
yajl_gen_config config;
Serializer::Serializer(const std::string& filePath, const std::string& indent) :
// pass through
- impl_(new Serializer::SerializerImpl(filePath, indent)) {}
+ impl_(new Serializer::Impl(filePath, indent)) {}
Serializer::Serializer(std::ostream& output, const std::string& indent) :
// pass through
- impl_(new Serializer::SerializerImpl(output, indent)) {}
+ impl_(new Serializer::Impl(output, indent)) {}
Serializer::~Serializer()
{
void Serializer::push(long value)
{
yajl_gen_status stat = yajl_gen_integer(impl_->gen, value);
- if (stat != yajl_gen_status_ok)
- Serializer::SerializerImpl::throwError(stat);
+ if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat);
}
void Serializer::push(double value)
{
yajl_gen_status stat = yajl_gen_double(impl_->gen, value);
- if (stat != yajl_gen_status_ok)
- Serializer::SerializerImpl::throwError(stat);
+ if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat);
}
void Serializer::push(bool value)
{
yajl_gen_status stat = yajl_gen_bool(impl_->gen, value);
- if (stat != yajl_gen_status_ok)
- Serializer::SerializerImpl::throwError(stat);
+ if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat);
}
void Serializer::push(const std::string& value)
{
yajl_gen_status stat = yajl_gen_string(impl_->gen,
(const unsigned char*)value.c_str(), value.length());
- if (stat != yajl_gen_status_ok)
- Serializer::SerializerImpl::throwError(stat);
+ if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat);
}
void Serializer::push(const std::wstring& value)
void Serializer::pushNull()
{
yajl_gen_status stat = yajl_gen_null(impl_->gen);
- if (stat != yajl_gen_status_ok)
- Serializer::SerializerImpl::throwError(stat);
+ if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat);
}
void Serializer::pushMapHead()
{
yajl_gen_status stat = yajl_gen_map_open(impl_->gen);
- if (stat != yajl_gen_status_ok)
- Serializer::SerializerImpl::throwError(stat);
+ if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat);
}
void Serializer::pushMapTail()
{
yajl_gen_status stat = yajl_gen_map_close(impl_->gen);
- if (stat != yajl_gen_status_ok)
- Serializer::SerializerImpl::throwError(stat);
+ if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat);
}
void Serializer::pushArrayHead()
{
yajl_gen_status stat = yajl_gen_array_open(impl_->gen);
- if (stat != yajl_gen_status_ok)
- Serializer::SerializerImpl::throwError(stat);
+ if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat);
}
void Serializer::pushArrayTail()
{
yajl_gen_status stat = yajl_gen_array_close(impl_->gen);
- if (stat != yajl_gen_status_ok)
- Serializer::SerializerImpl::throwError(stat);
+ if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat);
}
#include <boost/shared_ptr.hpp>
+#include <Moof/Exception.hh>
+
namespace Mf {
class Serializer
{
+ class Impl;
+ boost::shared_ptr<Impl> impl_;
+
public:
/**
void flush();
+
/**
* This exception is thrown for serializer-related exceptional errors.
*/
- struct Exception : std::runtime_error
+ struct Exception : public Mf::Exception
{
- explicit Exception(const std::string& what_arg) :
- std::runtime_error(what_arg) {}
+ enum
+ {
+ ARCHIVE_TERMINATED = 1024,
+ KEYS_MUST_BE_STRINGS = 1025,
+ RECURSION_TOO_DEEP = 1026,
+ ALREADY_FAILED = 1027,
+ };
+
+ explicit Exception(unsigned error) :
+ Mf::Exception(error) {}
+
+ void raise()
+ {
+ throw *this;
+ }
+
+ const char* what() const throw()
+ {
+ switch (code)
+ {
+ case ARCHIVE_TERMINATED:
+ return "archive is already terminated";
+ case KEYS_MUST_BE_STRINGS:
+ return "map keys must be strings";
+ case RECURSION_TOO_DEEP:
+ return "generator recursion too deep";
+ case ALREADY_FAILED:
+ return "generator already errored out";
+ }
+ return Mf::Exception::what();
+ }
};
-
-private:
- class SerializerImpl;
- boost::shared_ptr<SerializerImpl> impl_;
};
} // namespace Mf
try
{
- SerializablePtr value(deserializer.deserialize());
+ SerializableP value(deserializer.deserialize());
map_[key] = value;
}
catch (std::exception e)
{
// it doesn't deserialize to anything we know, so just store it
// as a string
- map_[key] = SerializablePtr(new SerializableString(stringValue));
+ map_[key] = SerializableP(new SerializableBasic<Serializable::String>(stringValue));
}
}
}
{
Deserializer deserializer(*it, true);
- SerializablePtr obj = deserializer.deserialize();
- std::map<std::string,SerializablePtr> map;
+ SerializableP obj = deserializer.deserialize();
+ Serializable::Map map;
if (obj && obj->get(map))
{
bool getNumber(const std::string& key, T& value);
private:
- std::map<std::string,SerializablePtr> map_;
+ Serializable::Map map_;
};
template <typename T>
bool Settings::get(const std::string& key, T& value)
{
- std::map<std::string,SerializablePtr>::const_iterator it = map_.find(key);
+ Serializable::Map::const_iterator it = map_.find(key);
if (it != map_.end())
{
- SerializablePtr obj = (*it).second;
+ SerializableP obj = (*it).second;
return obj->get(value);
}
else
template <typename T>
bool Settings::getNumber(const std::string& key, T& value)
{
- std::map<std::string,SerializablePtr>::const_iterator it = map_.find(key);
+ Serializable::Map::const_iterator it = map_.find(key);
if (it != map_.end())
{
- SerializablePtr obj = (*it).second;
+ SerializableP obj = (*it).second;
return obj->getNumber(value);
}
else
namespace Mf {
+class Sound;
+typedef boost::shared_ptr<Sound> SoundP;
+
+
class Sound : public Resource
{
+protected:
+ Sound() {}
+ class Impl;
+ boost::shared_ptr<Impl> impl_;
+
public:
+
+ static SoundP alloc(const std::string& name)
+ {
+ return SoundP(new Sound(name));
+ }
+
Sound(const std::string& name);
void play();
static std::string getPath(const std::string& name);
+
struct Exception : public Mf::Exception
{
enum
return Mf::Exception::what();
}
};
-
-protected:
- Sound() {}
- class Impl;
- boost::shared_ptr<Impl> impl_;
};
namespace Mf {
+class Texture;
+typedef boost::shared_ptr<Texture> TextureP;
+
+
class Texture : public Resource
{
+ class Impl;
+ boost::shared_ptr<Impl> impl_;
+
public:
+
+ static TextureP alloc(const std::string& name)
+ {
+ return TextureP(new Texture(name));
+ }
+
Texture(const std::string& name);
void bind() const;
static std::string getPath(const std::string& name);
+
struct Exception : public Mf::Exception
{
enum
switch (code)
{
case BAD_IMAGE_FORMAT:
- return "inappropriate image format";
+ return "unknown image format";
}
return Mf::Exception::what();
}
};
-
-private:
- class Impl;
- boost::shared_ptr<Impl> impl_;
};
{
Deserializer deserializer(Tilemap::getPath(getName()));
- SerializablePtr root = deserializer.deserialize();
+ SerializableP root = deserializer.deserialize();
if (root)
{
- std::map<std::string,SerializablePtr> rootObj;
+ Serializable::Map rootObj;
if (root->get(rootObj))
{
- std::map<std::string,SerializablePtr>::iterator it;
+ Serializable::Map::iterator it;
if ((it = rootObj.find("tiles_s")) != rootObj.end())
{
Settings& settings = Settings::getInstance();
- std::vector<SerializablePtr> colors;
+ Serializable::Array colors;
settings.get("video.colorbuffers", colors);
if (colors.size() > 0) colors[0]->get(colorBuffer[0]);
if (colors.size() > 1) colors[1]->get(colorBuffer[1]);
settings.get("video.depthbuffer", depthBuffer);
settings.get("video.stencilbuffer", stencilBuffer);
- std::vector<SerializablePtr> accum;
+ Serializable::Array accum;
settings.get("video.accumbuffers", accum);
if (accum.size() > 0) accum[0]->get(accumBuffer[0]);
if (accum.size() > 1) accum[1]->get(accumBuffer[1]);
}
settings.get("video.icon", icon);
- std::vector<SerializablePtr> dimensions;
+ Serializable::Array dimensions;
settings.get("video.mode", dimensions);
if (dimensions.size() > 0) dimensions[0]->get(mode[0]);
if (dimensions.size() > 1) dimensions[1]->get(mode[1]);
namespace Mf {
-class Video
+class Video;
+typedef boost::shared_ptr<Video> VideoP;
+
+
+struct Video
{
-public:
struct Attributes
{
// OpenGL attributes
Attributes();
};
+
+private:
+
+ void init(const Attributes& attribs);
+
+ void recreateContext();
+ void setOpenGLAttributes();
+
+ void setIcon();
+
+ SDL_Surface* context_;
+ unsigned flags_;
+ Attributes attribs_;
+
+public:
+
+ inline static VideoP alloc(const std::string& caption,
+ const std::string& icon)
+ {
+ return VideoP(new Video(caption, icon));
+ }
+
Video();
explicit Video(const Attributes& attribs);
explicit Video(const std::string& caption, const std::string& icon);
explicit Exception(const std::string& what_arg) :
std::runtime_error(what_arg) {}
};
-
-private:
- void init(const Attributes& attribs);
-
- void recreateContext();
- void setOpenGLAttributes();
-
- void setIcon();
-
- SDL_Surface* context_;
- unsigned flags_;
- Attributes attribs_;
};
-typedef boost::shared_ptr<Video> VideoPtr;
-
} // namespace Mf
state = 0.0;
- heroine = CharacterPtr(new Character("RobotTrooper"));
+ heroine = Character::alloc("RobotTrooper");
heroine->getAnimation().startSequence("Run");
font = new TilemapFont;
//heroine->draw(alpha);
+ heroine->getAabb().draw();
hud.draw();
int status = 0;
-//start:
try
{
YoinkApp app(argc, argv);
status = app.run();
}
- //catch (Mf::Texture::Exception e)
- //{
- //std::cout << "Unhandled exception: " << e.what() << std::endl;
- //status = 1;
- //}
catch (Mf::Exception e)
{
- //std::cout << "Unhandled exception: " << e.what() << std::endl;
Mf::logError("unhandled exception: <<%s>>", e.what());
- Mf::logInfo("it's time to crash now ;-(");
+ Mf::logInfo("it's time to crash now :-(");
status = 1;
-
- //std::cout << "Yoink stopped. Do you want to run it again? [yes/No]"
- //<< std::endl;
-
- //char answer;
- //std::cin >> answer;
-
- //if (answer == 'y' || answer == 'Y') goto start;
}
std::cout << std::endl << "Goodbye..." << std::endl << std::endl;
Mf::Lerps musicFade;
Mf::SoundStream music;
- CharacterPtr heroine;
+ CharacterP heroine;
Mf::Sound punchSound;
TilemapFont *font;