--- /dev/null
+/*
+ * Application.cpp
+ *
+ * Created on: Apr 8, 2012
+ * Author: holy
+ */
+
+#include "Application.h"
+
+#include "State.h"
+
+#include <cassert>
+
+namespace app {
+
+Application::Application(sdl::InitScreen *screen, State *initialState)
+: screen(screen)
+, states()
+, last(SDL_GetTicks()) {
+ assert(screen && "cannot create application without screen");
+ assert(initialState && "cannot create application without initial state");
+ RealPushState(initialState);
+}
+
+Application::~Application(void) {
+ PopAllStates();
+}
+
+
+State *Application::CurrentState(void) {
+ return states.top();
+}
+
+void Application::ChangeState(State *s) {
+ RealPopState();
+ RealPushState(s);
+}
+
+void Application::PushState(State *s) {
+ RealPushState(s);
+}
+
+void Application::RealPushState(State *s) {
+ states.push(s);
+ s->EnterState(this, screen->Screen());
+}
+
+void Application::PopState(void) {
+ RealPopState();
+}
+
+void Application::RealPopState(void) {
+ if (states.empty()) return;
+ states.top()->ExitState();
+ delete states.top();
+ states.pop();
+}
+
+void Application::Quit(void) {
+ PopAllStates();
+}
+
+void Application::PopAllStates(void) {
+ while (!states.empty()) {
+ RealPopState();
+ }
+}
+
+
+void Application::Run(void) {
+ while (CurrentState()) {
+ Loop();
+ }
+}
+
+void Application::Loop(void) {
+ Uint32 now(SDL_GetTicks());
+ Uint32 deltaT(now - last);
+ if (deltaT > 34) deltaT = 34;
+
+ HandleEvents();
+ UpdateWorld(deltaT);
+ Render();
+
+ last = now;
+}
+
+
+void Application::HandleEvents(void) {
+ if (!CurrentState()) return;
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) {
+ switch (event.type) {
+ case SDL_QUIT:
+ PopAllStates();
+ break;
+ default:
+ CurrentState()->HandleEvent(event);
+ break;
+ }
+ }
+}
+
+void Application::UpdateWorld(Uint32 deltaT) {
+ if (!CurrentState()) return;
+ for (Uint32 i(0); i < deltaT; ++i) {
+ CurrentState()->UpdateWorld(0.001f);
+ }
+}
+
+void Application::Render(void) {
+ if (!CurrentState()) return;
+ CurrentState()->Render(screen->Screen());
+ screen->Flip();
+}
+
+}
--- /dev/null
+/*
+ * Application.h
+ *
+ * Created on: Apr 8, 2012
+ * Author: holy
+ */
+
+#ifndef APP_APPLICATION_H_
+#define APP_APPLICATION_H_
+
+#include "Control.h"
+#include "../sdl/InitScreen.h"
+
+#include <stack>
+#include <SDL/SDL.h>
+
+
+namespace app {
+
+class State;
+
+class Application
+: public Control {
+
+ public:
+ explicit Application(sdl::InitScreen *screen, State *initialState);
+ virtual ~Application(void);
+ private:
+ Application(const Application &);
+ Application &operator =(const Application &);
+
+ public:
+ void Run(void);
+ void Loop(void);
+
+ public:
+ virtual void ChangeState(State *);
+ virtual void PushState(State *);
+ virtual void PopState(void);
+ virtual void Quit(void);
+
+ private:
+ State *CurrentState(void);
+ void RealPushState(State *);
+ void RealPopState(void);
+ void PopAllStates(void);
+
+ private:
+ void HandleEvents(void);
+ void UpdateWorld(Uint32 deltaT);
+ void Render(void);
+
+ private:
+ sdl::InitScreen *screen;
+ std::stack<State *> states;
+ Uint32 last;
+
+};
+
+}
+
+#endif /* APP_APPLICATION_H_ */
--- /dev/null
+/*
+ * Control.h
+ *
+ * Created on: Apr 19, 2012
+ * Author: holy
+ */
+
+#ifndef APP_CONTROL_H_
+#define APP_CONTROL_H_
+
+namespace app {
+
+class State;
+
+class Control {
+
+ public:
+ virtual ~Control(void) { };
+
+ public:
+ virtual void ChangeState(State *) = 0;
+ virtual void PushState(State *) = 0;
+ virtual void PopState(void) = 0;
+ virtual void Quit(void) = 0;
+};
+
+}
+
+#endif /* APP_CONTROL_H_ */
--- /dev/null
+/*
+ * State.h
+ *
+ * Created on: Apr 8, 2012
+ * Author: holy
+ */
+
+#ifndef APP_APPLICATIONSTATE_H_
+#define APP_APPLICATIONSTATE_H_
+
+#include <SDL/SDL.h>
+
+namespace app {
+
+class Control;
+
+class State {
+
+ public:
+ virtual ~State(void) { };
+
+ public:
+ virtual void EnterState(Control *ctrl, SDL_Surface *screen) = 0;
+ virtual void ExitState(void) = 0;
+
+ virtual void HandleEvent(const SDL_Event &) = 0;
+ virtual void UpdateWorld(float deltaT) = 0;
+ virtual void Render(SDL_Surface *) = 0;
+
+};
+
+}
+
+#endif /* APP_STATE_H_ */
--- /dev/null
+/*
+ * Collision.h
+ *
+ * Created on: Apr 22, 2012
+ * Author: holy
+ */
+
+#ifndef GAME_COLLISION_H_
+#define GAME_COLLISION_H_
+
+#include "Entity.h"
+
+
+namespace game {
+
+class Collision {
+
+ public:
+ Collision(Entity *left, Entity *right, const Entity::Vector &normal) : left(left), right(right), normal(normal) { };
+ ~Collision(void) { };
+
+ public:
+ Entity *left, *right;
+ Entity::Vector normal;
+
+};
+
+}
+
+#endif /* GAME_COLLISION_H_ */
--- /dev/null
+/*
+ * Entity.cpp
+ *
+ * Created on: Apr 9, 2012
+ * Author: holy
+ */
+
+#include "Entity.h"
+
+#include <limits>
+
+#include <iostream>
+using namespace std;
+
+using geometry::Shape;
+using std::numeric_limits;
+
+
+namespace game {
+
+Entity::Entity(Shape *shape)
+: bounds(shape)
+, position()
+, velocity()
+, nextVelocity()
+, maxVelocitySquared(numeric_limits<Scalar>::infinity())
+, dynamic(true)
+, updateVelocity(false) {
+
+}
+
+Entity::Entity(const Vector &position, Shape *shape)
+: bounds(shape)
+, position(position)
+, velocity()
+, nextVelocity()
+, maxVelocitySquared(numeric_limits<Scalar>::infinity())
+, dynamic(true)
+, updateVelocity(false) {
+
+}
+
+Entity::~Entity(void) {
+
+}
+
+
+void Entity::Move(const Vector &delta) {
+ position += delta;
+ bounds->SetPosition(position);
+}
+
+void Entity::SetPosition(const Vector &p) {
+ position = p;
+ bounds->SetPosition(position);
+}
+
+
+void Entity::SetVelocity(const Vector &v) {
+ if (updateVelocity) {
+ nextVelocity = v;
+ } else {
+ velocity = v;
+ }
+}
+
+
+Entity::Vector Entity::Center(void) const {
+ return bounds->Center();
+}
+
+
+void Entity::Accelerate(Scalar factor) {
+ if (updateVelocity) {
+ Vector scaled(nextVelocity * factor);
+ float speedSquared(scaled.LengthSquared());
+ if (speedSquared <= maxVelocitySquared) {
+ nextVelocity = scaled;
+ }
+ } else {
+ Vector scaled(velocity * factor);
+ float speedSquared(scaled.LengthSquared());
+ if (speedSquared <= maxVelocitySquared) {
+ velocity = scaled;
+ }
+ }
+}
+
+void Entity::SetMaxVelocity(Scalar max) {
+ maxVelocitySquared = max * max;
+}
+
+
+void Entity::Update(float deltaT) {
+ if (velocity.X() == Limits::quiet_NaN() || velocity.X() == -Limits::quiet_NaN()) {
+ cout << "NaN! " << velocity << endl;
+ }
+ position += velocity * deltaT;
+ bounds->SetPosition(position);
+}
+
+void Entity::Revert(float deltaT) {
+ position -= velocity * deltaT;
+ bounds->SetPosition(position);
+}
+
+void Entity::Collide(Entity &other, const Vector &normal) {
+ nextVelocity = velocity;
+ nextVelocity.Reflect(normal);
+ updateVelocity = true;
+}
+
+void Entity::PostCollide(void) {
+ if (updateVelocity) {
+ velocity = nextVelocity;
+ updateVelocity = false;
+ }
+}
+
+}
--- /dev/null
+/*
+ * Entity.h
+ *
+ * Created on: Apr 9, 2012
+ * Author: holy
+ */
+
+#ifndef GAME_ENTITY_H_
+#define GAME_ENTITY_H_
+
+#include "../geometry/Shape.h"
+#include "../geometry/Vector2D.h"
+
+#include <cmath>
+#include <ostream>
+#include <SDL/SDL.h>
+
+
+namespace game {
+
+class Entity {
+
+ public:
+ typedef geometry::Shape::Scalar Scalar;
+ typedef geometry::Shape::Vector Vector;
+ typedef geometry::Shape::Limits Limits;
+
+ public:
+ explicit Entity(geometry::Shape *);
+ Entity(const Vector &position, geometry::Shape *);
+ virtual ~Entity(void);
+
+ public:
+ void Move(const Vector &d);
+
+ void SetPosition(const Vector &);
+
+ public:
+ const Vector &Position(void) const { return position; };
+ Vector Center(void) const;
+ const Vector &Velocity() const { return velocity; };
+ void SetVelocity(const Vector &);
+
+ public:
+ const geometry::Shape &Bounds(void) const { return *bounds; };
+ bool Overlaps(const Entity &other, Vector &normal) {
+ return bounds->Overlaps(*other.bounds, normal);
+ };
+
+ public:
+ void Update(float deltaT);
+ void Revert(float deltaT);
+ virtual void Collide(Entity &, const Vector &normal);
+ virtual void PostCollide(void);
+ virtual void Render(SDL_Surface *dest) { };
+
+ public:
+ bool IsDynamic(void) const { return dynamic; };
+ bool IsStatic(void) const { return !dynamic; };
+ void SetDynamic(void) { dynamic = true; };
+ void SetStatic(void) { dynamic = false; };
+
+ public:
+ void Accelerate(float factor);
+ void SetMaxVelocity(float);
+
+ private:
+ geometry::Shape *bounds;
+ Vector position, velocity, nextVelocity;
+ Scalar maxVelocitySquared;
+ bool dynamic, updateVelocity;
+};
+
+}
+
+#endif /* GAME_ENTITY_H_ */
--- /dev/null
+/*
+ * AABB.cpp
+ *
+ * Created on: Apr 20, 2012
+ * Author: holy
+ */
+
+#include "AABB.h"
+
+#include "Circle.h"
+#include "FakeLens.h"
+
+namespace geometry {
+
+bool AABB::Overlaps(const Shape &other, Vector &normal) const {
+ if (other.Overlaps(*this, normal)) {
+ normal *= -1;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool AABB::Overlaps(const AABB &other, Vector &normal) const {
+ if (Bottom() <= other.Top()) return false;
+ if (other.Bottom() <= Top()) return false;
+ if (Right() <= other.Left()) return false;
+ if (other.Right() <= Left()) return false;
+
+ if (HorizontalOverlap(other)) {
+ if (Top() < other.Top()) {
+ normal = Vector(0, -1);
+ } else {
+ normal = Vector(0, 1);
+ }
+ } else {
+ if (Left() < other.Left()) {
+ normal = Vector(-1, 0);
+ } else {
+ normal = Vector(1, 0);
+ }
+ }
+
+ return true;
+}
+
+bool AABB::Overlaps(const Circle &other, Vector &normal) const {
+ if (other.Overlaps(*this, normal)) {
+ normal *= -1;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool AABB::Overlaps(const FakeLens &other, Vector &normal) const {
+ if (other.Overlaps(*this, normal)) {
+ normal *= -1;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+std::ostream &AABB::Write(std::ostream &out) const {
+ return out << "AABB(" << Width() << 'x' << Height() << '+' << X() << '+' << Y() << ')';
+}
+
+} /* namespace geometry */
--- /dev/null
+/*
+ * AABB.h
+ *
+ * Created on: Apr 10, 2012
+ * Author: holy
+ */
+
+#ifndef GEOMETRY_AABB_H_
+#define GEOMETRY_AABB_H_
+
+#include "Shape.h"
+
+#include <ostream>
+#include <SDL/SDL.h>
+
+
+namespace geometry {
+
+class AABB
+: public Shape {
+
+ public:
+ AABB(void) : leftTop(), rightBottom() { };
+ explicit AABB(const Vector &size) : leftTop(), rightBottom(size) { };
+ AABB(const Vector &position, const Vector &size)
+ : leftTop(position), rightBottom(position + size) { };
+ virtual ~AABB(void) { };
+
+ public:
+ Scalar Left(void) const { return leftTop.X(); };
+ Scalar Top(void) const { return leftTop.Y(); };
+ Scalar Right(void) const { return rightBottom.X(); };
+ Scalar Bottom(void) const { return rightBottom.Y(); };
+
+ Scalar X(void) const { return Left(); };
+ Scalar Y(void) const { return Top(); };
+ Scalar Width(void) const { return Right() - Left(); };
+ Scalar Height(void) const { return Bottom() - Top(); };
+
+ public:
+ virtual bool Overlaps(const Shape &other, Vector &normal) const;
+ virtual bool Overlaps(const AABB &other, Vector &normal) const;
+ virtual bool Overlaps(const Circle &other, Vector &normal) const;
+ virtual bool Overlaps(const FakeLens &, Vector &normal) const;
+
+ bool VerticalOverlap(const AABB &other) const {
+ if (Bottom() < other.Top()) return false;
+ if (other.Bottom() < Top()) return false;
+ return true;
+ };
+ bool HorizontalOverlap(const AABB &other) const {
+ if (Right() < other.Left()) return false;
+ if (other.Right() < Left()) return false;
+ return true;
+ };
+
+ public:
+ void Move(const Vector &delta) {
+ leftTop += delta;
+ rightBottom += delta;
+ };
+
+ void SetBounds(const Vector &position, const Vector &size) {
+ leftTop = position;
+ rightBottom = position + size;
+ };
+ void SetPosition(const Vector &position) {
+ rightBottom = position + (rightBottom - leftTop);
+ leftTop = position;
+ };
+ void SetSize(const Vector &size) {
+ rightBottom = leftTop + size;
+ };
+
+ virtual Vector Center(void) const {
+ return leftTop + (rightBottom - leftTop) / 2;
+ };
+
+ virtual std::ostream &Write(std::ostream &out) const;
+
+ public:
+ void WriteRect(SDL_Rect &rect) const {
+ rect.x = X();
+ rect.y = Y();
+ rect.w = Width();
+ rect.h = Height();
+ };
+
+ private:
+ Vector leftTop, rightBottom;
+
+};
+
+}
+
+#endif /* GEOMETRY_AABB_H_ */
--- /dev/null
+/*
+ * Circle.cpp
+ *
+ * Created on: Apr 20, 2012
+ * Author: holy
+ */
+
+#include "Circle.h"
+
+#include "AABB.h"
+#include "FakeLens.h"
+#include "../game/Entity.h"
+
+
+namespace geometry {
+
+bool Circle::Overlaps(const Shape &other, Vector &normal) const {
+ if (other.Overlaps(*this, normal)) {
+ normal *= -1;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool Circle::Overlaps(const AABB &other, Vector &normal) const {
+ // fast checks for far away shapes
+ if (Bottom() <= other.Top()) return false;
+ if (other.Bottom() <= Top()) return false;
+ if (Right() <= other.Left()) return false;
+ if (other.Right() <= Left()) return false;
+
+ int xZone(
+ X() < other.Left() ? 0 : (
+ other.Right() < X() ? 2 : 1));
+ int yZone(
+ Y() < other.Top() ? 0 : (
+ other.Bottom() < Y() ? 2 : 1));
+ int zone(xZone + 3*yZone);
+
+ if (zone == 4) {
+ normal = (Center() - other.Center()).Unit();
+ return true;
+ }
+
+ if (zone % 2) {
+ if (xZone == 1) { // vertical
+ if (Bottom() < other.Top()) return false;
+ if (other.Bottom() < Top()) return false;
+
+ if (Bottom() < other.Bottom()) {
+ normal = Vector(0, -1);
+ } else {
+ normal = Vector(0, 1);
+ }
+
+ return true;
+ } else {
+ if (Right() < other.Left()) return false;
+ if (other.Right() < Left()) return false;
+
+ if (Left() < other.Left()) {
+ normal = Vector(-1, 0);
+ } else {
+ normal = Vector(1, 0);
+ }
+
+ return true;
+ }
+ } else {
+ Vector near(
+ yZone ? other.Right() : other.Left(),
+ xZone ? other.Bottom() : other.Top());
+ Vector distance(position - near);
+ Sint32 distanceSquared(distance.LengthSquared());
+ if (distanceSquared < (Radius() * Radius())) {
+ normal = distance.Unit();
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
+
+bool Circle::Overlaps(const Circle &other, Vector &normal) const {
+ Vector delta(position - other.position);
+ Sint32 distanceSquared(delta.LengthSquared()), minDistance(Radius() + other.Radius());
+ if (distanceSquared < (minDistance * minDistance)) {
+ normal = delta.Unify();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool Circle::Overlaps(const FakeLens &other, Vector &normal) const {
+ if (other.Overlaps(*this, normal)) {
+ normal *= -1;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+std::ostream &Circle::Write(std::ostream &out) const {
+ return out << "Circle(" << Radius() << '+' << Top() << '+' << Left() << ')';
+}
+
+}
--- /dev/null
+/*
+ * Circle.h
+ *
+ * Created on: Apr 19, 2012
+ * Author: holy
+ */
+
+#ifndef GEOMETRY_CIRCLE_H_
+#define GEOMETRY_CIRCLE_H_
+
+#include "Shape.h"
+
+#include "AABB.h"
+
+#include <SDL/SDL.h>
+
+
+namespace geometry {
+
+class Circle
+: public Shape {
+
+ public:
+ Circle(void) : position(), radius() { };
+ explicit Circle(Scalar radius) : position(), radius(radius) { };
+ explicit Circle(const Vector &position, Scalar radius = Scalar()) : position(position), radius(radius) { };
+ virtual ~Circle(void) { };
+
+ public:
+ Scalar X(void) const { return position.X(); };
+ Scalar Y(void) const { return position.Y(); };
+ Scalar Radius(void) const { return radius; };
+ Scalar Diameter(void) const { return 2 * Radius(); };
+
+ Scalar Width(void) const { return Diameter(); };
+ Scalar Height(void) const { return Diameter(); };
+
+ Scalar Left(void) const { return X() - Radius(); };
+ Scalar Top(void) const { return Y() - Radius(); };
+ Scalar Right(void) const { return X() + Radius(); };
+ Scalar Bottom(void) const { return Y() + Radius(); };
+
+ public:
+ virtual bool Overlaps(const Shape &other, Vector &normal) const;
+ virtual bool Overlaps(const AABB &other, Vector &normal) const;
+ virtual bool Overlaps(const Circle &other, Vector &normal) const;
+ virtual bool Overlaps(const FakeLens &, Vector &normal) const;
+
+ bool VerticalOverlap(const AABB &other) const {
+ if (Bottom() < other.Top()) return false;
+ if (other.Bottom() < Top()) return false;
+ return true;
+ };
+ bool HorizontalOverlap(const AABB &other) const {
+ if (Right() < other.Left()) return false;
+ if (other.Right() < Left()) return false;
+ return true;
+ };
+
+ public:
+ void Move(const Vector &delta) {
+ position += delta;
+ };
+
+ void SetPosition(const Vector &pos) {
+ position = pos;
+ };
+ void SetRadius(Scalar r) {
+ radius = r;
+ };
+
+ virtual Vector Center(void) const {
+ return position;
+ };
+
+ virtual std::ostream &Write(std::ostream &out) const;
+
+ private:
+ Vector position;
+ Scalar radius;
+
+};
+
+}
+
+#endif /* GEOMETRY_CIRCLE_H_ */
--- /dev/null
+/*
+ * FakeLens.cpp
+ *
+ * Created on: Apr 24, 2012
+ * Author: holy
+ */
+
+#include "FakeLens.h"
+
+#include "Circle.h"
+
+
+#include <iostream>
+using namespace std;
+
+
+namespace geometry {
+
+bool FakeLens::Overlaps(const Shape &other, Vector &normal) const {
+ if (other.Overlaps(*this, normal)) {
+ normal *= -1;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool FakeLens::Overlaps(const AABB &other, Vector &normal) const {
+ if (AABB::Overlaps(other, normal)) {
+ MessUpNormal(normal, other);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool FakeLens::Overlaps(const Circle &other, Vector &normal) const {
+ if (AABB::Overlaps(other, normal)) {
+ MessUpNormal(normal, other);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool FakeLens::Overlaps(const FakeLens &other, Vector &normal) const {
+ if (AABB::Overlaps(static_cast<const AABB &>(other), normal)) {
+ MessUpNormal(normal, other);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+std::ostream &FakeLens::Write(std::ostream &out) const {
+ return out << "FakeLens(" << Width() << 'x' << Height() << '+' << X() << '+' << Y() << ')';
+}
+
+
+void FakeLens::MessUpNormal(Vector &normal, const Shape &other) const {
+ Vector direction((Center() - other.Center()).Unify());
+ normal = ((1 - bendFactor) * normal) + (bendFactor* direction);
+ normal.Unify();
+}
+
+}
--- /dev/null
+/*
+ * FakeLens.h
+ *
+ * Created on: Apr 24, 2012
+ * Author: holy
+ */
+
+#ifndef GEOMETRY_FAKELENS_H_
+#define GEOMETRY_FAKELENS_H_
+
+#include "AABB.h"
+
+
+namespace geometry {
+
+class FakeLens
+: public AABB {
+
+ public:
+ FakeLens(void) : AABB(), bendFactor(0.22f) { };
+ explicit FakeLens(const Vector &size) : AABB(size), bendFactor(0.22f) { };
+ FakeLens(const Vector &position, const Vector &size, float bendFactor = 0.22f) : AABB(position, size), bendFactor(bendFactor) { };
+
+ public:
+ void SetBendFactor(float b) { bendFactor = b; };
+
+ public:
+ virtual bool Overlaps(const Shape &, Vector &normal) const;
+
+ virtual bool Overlaps(const AABB &, Vector &normal) const;
+ virtual bool Overlaps(const Circle &, Vector &normal) const;
+ virtual bool Overlaps(const FakeLens &, Vector &normal) const;
+
+ public:
+ virtual std::ostream &Write(std::ostream &out) const;
+
+ private:
+ void MessUpNormal(Vector &normal, const Shape &other) const;
+
+ private:
+ float bendFactor;
+
+};
+
+}
+
+#endif /* GEOMETRY_FAKELENS_H_ */
--- /dev/null
+/*
+ * Shape.h
+ *
+ * Created on: Apr 20, 2012
+ * Author: holy
+ */
+
+#ifndef GEOMETRY_SHAPE_H_
+#define GEOMETRY_SHAPE_H_
+
+#include "Vector2D.h"
+
+#include <limits>
+#include <ostream>
+
+namespace geometry {
+
+class AABB;
+class Circle;
+class FakeLens;
+
+class Shape {
+
+ public:
+ typedef float Scalar;
+ typedef Vector2D<Scalar> Vector;
+ typedef std::numeric_limits<Scalar> Limits;
+
+ protected:
+ Shape(void) { };
+ virtual ~Shape(void) { };
+
+ public:
+ virtual bool Overlaps(const Shape &, Vector &normal) const = 0;
+
+ virtual bool Overlaps(const AABB &, Vector &normal) const = 0;
+ virtual bool Overlaps(const Circle &, Vector &normal) const = 0;
+ virtual bool Overlaps(const FakeLens &, Vector &normal) const = 0;
+
+ public:
+ virtual std::ostream &Write(std::ostream &out) const = 0;
+
+ public:
+ virtual void SetPosition(const Vector &) = 0;
+ virtual Vector Center(void) const = 0;
+
+};
+
+}
+
+
+namespace std {
+
+inline ostream &operator <<(ostream &out, const geometry::Shape &s) {
+ return s.Write(out);
+};
+
+}
+
+#endif /* GEOMETRY_SHAPE_H_ */
--- /dev/null
+/*
+ * Vector.h
+ *
+ * Created on: Apr 23, 2012
+ * Author: holy
+ */
+
+#ifndef GEOMETRY_VECTOR2D_H_
+#define GEOMETRY_VECTOR2D_H_
+
+#include <cmath>
+#include <ostream>
+
+
+namespace geometry {
+
+template<typename Scalar>
+class Vector2D {
+
+ public:
+ Vector2D(void) : x(), y() { };
+ Vector2D(Scalar x, Scalar y) : x(x), y(y) { };
+
+ public:
+ Scalar X(void) const { return x; };
+ Scalar Y(void) const { return y; };
+
+ public:
+ Scalar Dot(const Vector2D<Scalar> &o) const { return (X() * o.X()) + (Y() * o.Y()); };
+ Scalar LengthSquared(void) const { return Dot(*this); };
+ Scalar Length(void) const { return std::sqrt(LengthSquared()); };
+
+ public:
+ Vector2D<Scalar> &Unify(void) {
+ if (LengthSquared() == Scalar()) return *this;
+ *this /= Length();
+ return *this;
+ };
+ Vector2D<Scalar> Unit(void) const {
+ if (LengthSquared() == Scalar()) return *this;
+ return *this / Length();
+ };
+ Vector2D<Scalar> &Reflect(const Vector2D<Scalar> &normal);
+
+ public:
+ Vector2D<Scalar> &operator +=(const Vector2D<Scalar> &o) {
+ x += o.X();
+ y += o.Y();
+ return *this;
+ };
+ Vector2D<Scalar> &operator -=(const Vector2D<Scalar> &o) {
+ x -= o.X();
+ y -= o.Y();
+ return *this;
+ };
+ template<typename T>
+ Vector2D<Scalar> &operator +=(T s) { x += s; y += s; return *this; };
+ template<typename T>
+ Vector2D<Scalar> &operator -=(T s) { x -= s; y -= s; return *this; };
+ template<typename T>
+ Vector2D<Scalar> &operator *=(T s) { x *= s; y *= s; return *this; };
+ template<typename T>
+ Vector2D<Scalar> &operator /=(T s) { x /= s; y /= s; return *this; };
+
+ private:
+ Scalar x, y;
+
+};
+
+template<typename Scalar>
+inline Vector2D<Scalar> &Vector2D<Scalar>::Reflect(const Vector2D<Scalar> &normal) {
+ Scalar doubleDot(2 * Dot(normal));
+ x -= doubleDot * normal.X();
+ y -= doubleDot * normal.Y();
+ return *this;
+};
+
+
+template<typename Scalar>
+inline Vector2D<Scalar> operator +(const Vector2D<Scalar> &v) {
+ return v;
+};
+template<typename Scalar>
+inline Vector2D<Scalar> operator -(const Vector2D<Scalar> &v) {
+ return Vector2D<Scalar>(-v.X(), -v.Y());
+};
+
+template<typename Scalar>
+inline Vector2D<Scalar> operator +(const Vector2D<Scalar> &lhs, const Vector2D<Scalar> &rhs) {
+ Vector2D<Scalar> temp(lhs);
+ temp += rhs;
+ return temp;
+};
+template<typename Scalar>
+inline Vector2D<Scalar> operator -(const Vector2D<Scalar> &lhs, const Vector2D<Scalar> &rhs) {
+ Vector2D<Scalar> temp(lhs);
+ temp -= rhs;
+ return temp;
+};
+
+template<typename VScalar, typename SScalar>
+inline Vector2D<VScalar> operator +(const Vector2D<VScalar> &v, SScalar s) {
+ Vector2D<VScalar> temp(v);
+ temp += s;
+ return temp;
+};
+template<typename VScalar, typename SScalar>
+inline Vector2D<VScalar> operator -(const Vector2D<VScalar> &v, SScalar s) {
+ Vector2D<VScalar> temp(v);
+ temp -= s;
+ return temp;
+};
+
+template<typename VScalar, typename SScalar>
+inline Vector2D<VScalar> operator +(SScalar s, const Vector2D<VScalar> &v) {
+ Vector2D<VScalar> temp(v);
+ temp += s;
+ return temp;
+};
+template<typename VScalar, typename SScalar>
+inline Vector2D<VScalar> operator -(SScalar s, const Vector2D<VScalar> &v) {
+ Vector2D<VScalar> temp(v);
+ temp -= s;
+ return temp;
+};
+
+template<typename VScalar, typename SScalar>
+inline Vector2D<VScalar> operator *(const Vector2D<VScalar> &v, SScalar s) {
+ Vector2D<VScalar> temp(v);
+ temp *= s;
+ return temp;
+};
+template<typename VScalar, typename SScalar>
+inline Vector2D<VScalar> operator *(SScalar s, const Vector2D<VScalar> &v) {
+ Vector2D<VScalar> temp(v);
+ temp *= s;
+ return temp;
+};
+template<typename VScalar, typename SScalar>
+inline Vector2D<VScalar> operator /(const Vector2D<VScalar> &v, SScalar s) {
+ Vector2D<VScalar> temp(v);
+ temp /= s;
+ return temp;
+};
+template<typename VScalar, typename SScalar>
+inline Vector2D<VScalar> operator /(SScalar s, const Vector2D<VScalar> &v) {
+ Vector2D<VScalar> temp(v);
+ temp /= s;
+ return temp;
+};
+
+
+template<typename Scalar>
+std::ostream &operator <<(std::ostream &out, const Vector2D<Scalar> &v) {
+ return out << '<' << v.X() << '|' << v.Y() << '>';
+}
+
+}
+
+#endif /* GEOMETRY_VECTOR2D_H_ */
--- /dev/null
+/*
+ * Ball.cpp
+ *
+ * Created on: Apr 9, 2012
+ * Author: holy
+ */
+
+#include "Ball.h"
+
+#include "Paddle.h"
+
+#include <cmath>
+#include <SDL/SDL_gfxPrimitives.h>
+
+using game::Entity;
+
+
+namespace pong {
+
+Ball::Ball(Scalar radius)
+: Entity(&shape)
+, shape(radius) {
+
+}
+
+Ball::Ball(const Vector &position, Scalar radius)
+: Entity(position, &shape)
+, shape(position, radius) {
+
+}
+
+
+void Ball::Collide(Entity &other, const Vector &normal) {
+ Entity::Collide(other, normal);
+
+ if (dynamic_cast<Paddle *>(&other)) {
+ Accelerate(1.015f);
+ }
+}
+
+void Ball::Render(SDL_Surface *screen) {
+ circleRGBA(screen, shape.X(), shape.Y(), shape.Radius(), 0xFF, 0xFF, 0xFF, 0xFF);
+}
+
+}
--- /dev/null
+/*
+ * Ball.h
+ *
+ * Created on: Apr 9, 2012
+ * Author: holy
+ */
+
+#ifndef PONG_BALL_H_
+#define PONG_BALL_H_
+
+#include "../game/Entity.h"
+#include "../geometry/Circle.h"
+
+#include <SDL/SDL.h>
+
+
+namespace pong {
+
+class Ball
+: public game::Entity {
+
+ public:
+ explicit Ball(Scalar radius);
+ Ball(const Vector &position, Scalar radius);
+
+ public:
+ virtual void Collide(Entity &, const Vector &normal);
+ virtual void Render(SDL_Surface *dest);
+
+ private:
+ geometry::Circle shape;
+
+};
+
+}
+
+#endif /* PONG_BALL_H_ */
--- /dev/null
+/*
+ * CountingWall.cpp
+ *
+ * Created on: Apr 17, 2012
+ * Author: holy
+ */
+
+#include "CountingWall.h"
+
+using game::Entity;
+
+
+namespace pong {
+
+CountingWall::CountingWall(const Vector &size)
+: Entity(&shape)
+, shape(size)
+, count(0) {
+
+}
+
+CountingWall::~CountingWall(void) {
+
+}
+
+
+void CountingWall::Collide(Entity &e, const Vector &normal) {
+ ++count;
+}
+
+void CountingWall::Render(SDL_Surface *dest) {
+
+}
+
+}
--- /dev/null
+/*
+ * CountingWall.h
+ *
+ * Created on: Apr 17, 2012
+ * Author: holy
+ */
+
+#ifndef PONG_COUNTINGWALL_H_
+#define PONG_COUNTINGWALL_H_
+
+#include "../game/Entity.h"
+#include "../geometry/AABB.h"
+
+#include <SDL/SDL.h>
+
+namespace pong {
+
+class CountingWall
+: public game::Entity {
+
+ public:
+ explicit CountingWall(const Vector &size);
+ virtual ~CountingWall(void);
+
+ public:
+ int HitCount(void) { return count; };
+
+ public:
+ virtual void Collide(Entity &, const Vector &normal);
+ virtual void Render(SDL_Surface *dest);
+
+ private:
+ geometry::AABB shape;
+ int count;
+
+};
+
+}
+
+#endif /* PONG_COUNTINGWALL_H_ */
--- /dev/null
+/*
+ * Match.cpp
+ *
+ * Created on: Apr 9, 2012
+ * Author: holy
+ */
+
+#include "Match.h"
+
+#include "../app/Control.h"
+
+#include <sstream>
+#include <stdexcept>
+#include <utility>
+#include <SDL/SDL.h>
+
+using app::Control;
+using game::Collision;
+using game::Entity;
+using std::runtime_error;
+using std::stringstream;
+using std::vector;
+
+
+namespace pong {
+
+Match::Match(void)
+: ctrl(0)
+, scoreFont(TTF_OpenFont("data/font/Magra-Regular.ttf", 30))
+, leftScoreText(0)
+, rightScoreText(0)
+, paddleSpeed(150)
+, worldWidth(800)
+, worldHeight(480)
+, ball(10)
+, secondBall(7)
+, leftPaddle(Entity::Vector(10, 100))
+, rightPaddle(Entity::Vector(10, 100))
+, topWall(Entity::Vector(800, 10))
+, bottomWall(Entity::Vector(800, 10))
+, leftWall(Entity::Vector(10, 480))
+, rightWall(Entity::Vector(10, 480))
+, entities()
+, collisions()
+, updateScore(true) {
+
+ if (!scoreFont) {
+ throw runtime_error("failed to load score font");
+ }
+
+ ball.SetPosition(Entity::Vector(400, 240));
+ ball.SetVelocity(Entity::Vector(180, 180));
+ ball.SetMaxVelocity(500.0f);
+
+ secondBall.SetPosition(Entity::Vector(300, 240));
+ secondBall.SetVelocity(Entity::Vector(-20, -20));
+ secondBall.SetMaxVelocity(600.0f);
+
+ leftPaddle.SetPosition(Entity::Vector(0, 200));
+ rightPaddle.SetPosition(Entity::Vector(790, 280));
+
+ leftPaddle.SetMovementSpeed(Entity::Vector(0, paddleSpeed));
+ rightPaddle.SetMovementSpeed(Entity::Vector(0, paddleSpeed));
+
+ leftPaddle.SetStatic();
+ rightPaddle.SetStatic();
+
+ topWall.SetPosition(Entity::Vector(0, -10));
+ rightWall.SetPosition(Entity::Vector(800, 0));
+ bottomWall.SetPosition(Entity::Vector(0, 480));
+ leftWall.SetPosition(Entity::Vector(-10, 0));
+
+ topWall.SetStatic();
+ rightWall.SetStatic();
+ bottomWall.SetStatic();
+ leftWall.SetStatic();
+
+ entities.reserve(8);
+ entities.push_back(&ball);
+ entities.push_back(&secondBall);
+ entities.push_back(&leftPaddle);
+ entities.push_back(&rightPaddle);
+ entities.push_back(&topWall);
+ entities.push_back(&bottomWall);
+ entities.push_back(&leftWall);
+ entities.push_back(&rightWall);
+
+ collisions.reserve(2 * entities.size());
+}
+
+Match::~Match(void) {
+
+}
+
+
+void Match::EnterState(Control *c, SDL_Surface *screen) {
+ ctrl = c;
+}
+
+void Match::ExitState(void) {
+ if (scoreFont) {
+ TTF_CloseFont(scoreFont);
+ scoreFont = 0;
+ }
+}
+
+void Match::HandleEvent(const SDL_Event &e) {
+ if (e.type == SDL_KEYDOWN) {
+ if (e.key.keysym.sym == SDLK_w) {
+ leftPaddle.StartMovingUp();
+ } else if (e.key.keysym.sym == SDLK_s) {
+ leftPaddle.StartMovingDown();
+ } else if (e.key.keysym.sym == SDLK_UP) {
+ rightPaddle.StartMovingUp();
+ } else if (e.key.keysym.sym == SDLK_DOWN) {
+ rightPaddle.StartMovingDown();
+ }
+ } else if (e.type == SDL_KEYUP) {
+ if (e.key.keysym.sym == SDLK_w) {
+ leftPaddle.StopMovingUp();
+ } else if (e.key.keysym.sym == SDLK_s) {
+ leftPaddle.StopMovingDown();
+ } else if (e.key.keysym.sym == SDLK_UP) {
+ rightPaddle.StopMovingUp();
+ } else if (e.key.keysym.sym == SDLK_DOWN) {
+ rightPaddle.StopMovingDown();
+ } else if (e.key.keysym.sym == SDLK_q) {
+ if (ctrl) ctrl->Quit();
+ }
+ }
+}
+
+void Match::UpdateWorld(float deltaT) {
+ UpdateEntities(deltaT);
+ CheckCollisions(deltaT);
+ HandleCollisions(deltaT);
+}
+
+void Match::UpdateEntities(float deltaT) {
+ for (vector<Entity *>::const_iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
+ (*i)->Update(deltaT);
+ }
+}
+
+void Match::CheckCollisions(float deltaT) {
+ Entity::Vector normal;
+ for (vector<Entity *>::const_iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
+ for (vector<Entity *>::const_iterator j(i + 1); j != end; ++j) {
+ if ((*i)->Overlaps(**j, normal)) {
+ if ((*i)->IsDynamic()) {
+ (*i)->Move(normal);
+ while ((*i)->Overlaps(**j, normal)) {
+ (*i)->Move(normal);
+ }
+ } else if ((*j)->IsDynamic()) {
+ (*j)->Move(normal);
+ while ((*j)->Overlaps(**i, normal)) {
+ (*j)->Move(normal);
+ }
+ } else {
+ (*i)->Revert(deltaT);
+ (*j)->Revert(deltaT);
+ }
+ collisions.push_back(Collision(*i, *j, normal));
+ }
+ }
+ }
+}
+
+void Match::HandleCollisions(float deltaT) {
+ for (vector<Collision>::const_iterator i(collisions.begin()), end(collisions.end()); i != end; ++i) {
+ i->left->Collide(*(i->right), i->normal);
+ i->right->Collide(*(i->left), -(i->normal));
+ i->left->PostCollide();
+ i->right->PostCollide();
+
+ }
+ if (!collisions.empty()) {
+ updateScore = true;
+ }
+ collisions.clear();
+}
+
+
+void Match::Render(SDL_Surface *screen) {
+ SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0));
+ for (vector<Entity *>::const_iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
+ (*i)->Render(screen);
+ }
+ RenderHUD(screen);
+}
+
+void Match::RenderHUD(SDL_Surface *screen) {
+ if (updateScore) {
+ UpdateScore(screen);
+ updateScore = false;
+ }
+ RenderScore(screen);
+}
+
+void Match::RenderScore(SDL_Surface *screen) {
+ SDL_Rect dest = { 2, 2, 0, 0 };
+ SDL_BlitSurface(leftScoreText, 0, screen, &dest);
+
+ dest.x = screen->w - rightScoreText->w - 2;
+ SDL_BlitSurface(rightScoreText, 0, screen, &dest);
+}
+
+void Match::UpdateScore(SDL_Surface *screen) {
+ if (!scoreFont) return;
+ if (leftScoreText) SDL_FreeSurface(leftScoreText);
+ if (rightScoreText) SDL_FreeSurface(rightScoreText);
+
+ SDL_Color color;
+ color.r = 0xFF;
+ color.g = 0xFF;
+ color.b = 0xFF;
+
+ stringstream s;
+ s << rightWall.HitCount();
+ leftScoreText = TTF_RenderUTF8_Blended(scoreFont, s.str().c_str(), color);
+
+ s.str("");
+ s << leftWall.HitCount();
+ rightScoreText = TTF_RenderUTF8_Blended(scoreFont, s.str().c_str(), color);
+}
+
+}
--- /dev/null
+/*
+ * Match.h
+ *
+ * Created on: Apr 9, 2012
+ * Author: holy
+ */
+
+#ifndef PONG_MATCH_H_
+#define PONG_MATCH_H_
+
+#include "Ball.h"
+#include "CountingWall.h"
+#include "Paddle.h"
+#include "../app/State.h"
+#include "../game/Collision.h"
+#include "../game/Entity.h"
+
+#include <utility>
+#include <vector>
+#include <SDL/SDL_ttf.h>
+
+
+namespace pong {
+
+class Match
+: public app::State {
+
+ public:
+ Match(void);
+ virtual ~Match(void);
+
+ public:
+ virtual void EnterState(app::Control *ctrl, SDL_Surface *screen);
+ virtual void ExitState(void);
+
+ virtual void HandleEvent(const SDL_Event &);
+ virtual void UpdateWorld(float deltaT);
+ virtual void Render(SDL_Surface *);
+
+ private:
+ void UpdateEntities(float deltaT);
+ void CheckCollisions(float deltaT);
+ void CheckWorldCollisions(float deltaT);
+ void HandleCollisions(float deltaT);
+ void UpdateScore(SDL_Surface *);
+ void RenderHUD(SDL_Surface *);
+ void RenderScore(SDL_Surface *);
+
+ private:
+ app::Control *ctrl;
+ TTF_Font *scoreFont;
+ SDL_Surface *leftScoreText, *rightScoreText;
+ Sint32 paddleSpeed;
+ Uint32 worldWidth, worldHeight;
+ Ball ball, secondBall;
+ Paddle leftPaddle, rightPaddle;
+ CountingWall topWall, bottomWall, leftWall, rightWall;
+ std::vector<game::Entity *> entities;
+ std::vector<game::Collision> collisions;
+ bool updateScore;
+
+};
+
+}
+
+#endif /* PONG_MATCH_H_ */
--- /dev/null
+/*
+ * Paddle.cpp
+ *
+ * Created on: Apr 10, 2012
+ * Author: holy
+ */
+
+#include "Paddle.h"
+
+#include "Ball.h"
+
+
+namespace pong {
+
+Paddle::Paddle(const Vector &size)
+: Entity(&shape)
+, shape(size) {
+
+}
+
+
+void Paddle::Collide(game::Entity &other, const Vector &normal) {
+
+}
+
+void Paddle::Render(SDL_Surface *screen) {
+ SDL_Rect destRect;
+ shape.WriteRect(destRect);
+ SDL_FillRect(screen, &destRect, SDL_MapRGB(screen->format, 0xFF, 0xFF, 0xFF));
+}
+
+
+void Paddle::SetMovementSpeed(Vector s) {
+ movementSpeed = s;
+
+ Vector v;
+ v = Velocity();
+ SetVelocity(v.Unify() * s.Length());
+}
+
+
+void Paddle::StartMovingUp(void) {
+ SetVelocity(Velocity() - movementSpeed);
+}
+
+void Paddle::StopMovingUp(void) {
+ SetVelocity(Velocity() + movementSpeed);
+}
+
+void Paddle::StartMovingDown(void) {
+ SetVelocity(Velocity() + movementSpeed);
+}
+
+void Paddle::StopMovingDown(void) {
+ SetVelocity(Velocity() - movementSpeed);
+}
+
+}
--- /dev/null
+/*
+ * Paddle.h
+ *
+ * Created on: Apr 10, 2012
+ * Author: holy
+ */
+
+#ifndef PONG_PADDLE_H_
+#define PONG_PADDLE_H_
+
+#include "../game/Entity.h"
+#include "../geometry/FakeLens.h"
+
+#include <SDL/SDL.h>
+
+namespace pong {
+
+class Paddle
+: public game::Entity {
+
+ public:
+ explicit Paddle(const Vector &size);
+
+ public:
+ virtual void Collide(game::Entity &, const Vector &normal);
+ virtual void Render(SDL_Surface *dest);
+
+ public:
+ void SetMovementSpeed(Vector);
+
+ void StartMovingUp(void);
+ void StopMovingUp(void);
+ void StartMovingDown(void);
+ void StopMovingDown(void);
+
+ private:
+ geometry::FakeLens shape;
+ Vector movementSpeed;
+
+};
+
+}
+
+#endif /* PONG_PADDLE_H_ */
--- /dev/null
+//============================================================================
+// Name : sdl-test7.cpp
+// Author : HolySmoke
+// Version :
+// Copyright :
+// Description : Hello World in C++, Ansi-style
+//============================================================================
+
+#include "app/Application.h"
+#include "pong/Match.h"
+#include "sdl/InitScreen.h"
+#include "sdl/InitSDL.h"
+#include "sdl/InitTTF.h"
+
+int main(int argc, char *argv[]) {
+ const int width(800);
+ const int height(480);
+
+ sdl::InitSDL initSDL;
+ sdl::InitTTF initTTF;
+ sdl::InitScreen initScreen(width, height);
+
+ app::Application a(&initScreen, new pong::Match);
+ a.Run();
+ return 0;
+}
--- /dev/null
+/*
+ * InitSDL.cpp
+ *
+ * Created on: Apr 22, 2012
+ * Author: holy
+ */
+
+#include "InitSDL.h"
+
+#include <stdexcept>
+
+using std::runtime_error;
+
+
+namespace sdl {
+
+InitSDL::InitSDL(Uint32 flags) {
+ if (SDL_Init(flags) != 0) {
+ throw runtime_error("failed to initialize SDL");
+ }
+}
+
+InitSDL::~InitSDL(void) {
+ SDL_Quit();
+}
+
+}
--- /dev/null
+/*
+ * InitSDL.h
+ *
+ * Created on: Apr 22, 2012
+ * Author: holy
+ */
+
+#ifndef SDL_INITSDL_H_
+#define SDL_INITSDL_H_
+
+#include <SDL/SDL.h>
+
+
+namespace sdl {
+
+class InitSDL {
+
+ public:
+ explicit InitSDL(Uint32 flags = SDL_INIT_EVERYTHING);
+ virtual ~InitSDL(void);
+ private:
+ InitSDL(const InitSDL &);
+ InitSDL &operator =(const InitSDL &);
+
+};
+
+}
+
+#endif /* SDL_INITSDL_H_ */
--- /dev/null
+/*
+ * InitScreen.cpp
+ *
+ * Created on: Apr 22, 2012
+ * Author: holy
+ */
+
+#include "InitScreen.h"
+
+#include <stdexcept>
+
+using std::runtime_error;
+
+
+namespace sdl {
+
+InitScreen::InitScreen(int width, int height, int bpp, Sint32 flags)
+: screen(SDL_SetVideoMode(width, height, bpp, flags)) {
+ if (!screen) {
+ throw runtime_error("failed to open screen");
+ }
+}
+
+InitScreen::~InitScreen(void) {
+
+}
+
+}
--- /dev/null
+/*
+ * InitScreen.h
+ *
+ * Created on: Apr 22, 2012
+ * Author: holy
+ */
+
+#ifndef SDL_INITSCREEN_H_
+#define SDL_INITSCREEN_H_
+
+#include <SDL/SDL.h>
+
+namespace sdl {
+
+class InitScreen {
+
+ public:
+ InitScreen(int width, int height, int bpp = 32, Sint32 flags = SDL_HWSURFACE | SDL_DOUBLEBUF);
+ virtual ~InitScreen(void);
+ private:
+ InitScreen(const InitScreen &);
+ InitScreen &operator =(const InitScreen &);
+
+ public:
+ SDL_Surface *Screen(void) { return screen; };
+ const SDL_Surface *Screen(void) const { return screen; };
+
+ void Flip(void) { SDL_Flip(screen); };
+
+ private:
+ SDL_Surface *screen;
+
+};
+
+}
+
+#endif /* SDL_INITSCREEN_H_ */
--- /dev/null
+/*
+ * InitTTF.cpp
+ *
+ * Created on: Apr 22, 2012
+ * Author: holy
+ */
+
+#include "InitTTF.h"
+
+#include <stdexcept>
+#include <SDL/SDL_ttf.h>
+
+using std::runtime_error;
+
+
+namespace sdl {
+
+InitTTF::InitTTF(void) {
+ if (TTF_Init() != 0) {
+ throw runtime_error("failed to initialize SDL TTF");
+ }
+}
+
+InitTTF::~InitTTF(void) {
+ TTF_Quit();
+}
+
+}
--- /dev/null
+/*
+ * InitTTF.h
+ *
+ * Created on: Apr 22, 2012
+ * Author: holy
+ */
+
+#ifndef SDL_INITTTF_H_
+#define SDL_INITTTF_H_
+
+namespace sdl {
+
+class InitTTF {
+
+ public:
+ InitTTF(void);
+ virtual ~InitTTF(void);
+ private:
+ InitTTF(const InitTTF &);
+ InitTTF &operator =(const InitTTF &);
+
+};
+
+}
+
+#endif /* SDL_INITTTF_H_ */