Initial commit after git corruption, old repo deleted.
Working: Rendering Resources Physics Player movement with mouse Shooting with mouse Tiles
This commit is contained in:
commit
45f0b31d57
31 changed files with 1813 additions and 0 deletions
219
source/Game.cpp
Normal file
219
source/Game.cpp
Normal file
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* Game.cpp
|
||||
*
|
||||
* Created on: 05.07.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#include "Game.h"
|
||||
|
||||
#include "abstract/Actor.h"
|
||||
#include "sprite/Cover.h"
|
||||
#include "util/Loader.h"
|
||||
#include "util/ResourceManager.h"
|
||||
#include "util/String.h"
|
||||
#include "util/Log.h"
|
||||
|
||||
/// Goal amount of frames per second.
|
||||
const int Game::FPS_GOAL = 60;
|
||||
|
||||
/// Milliseconds per tick at FPS_GOAL.
|
||||
const float Game::TICKS_GOAL = 1000 / Game::FPS_GOAL;
|
||||
|
||||
/**
|
||||
* Initializes game, including window and objects (sprites).
|
||||
*/
|
||||
Game::Game(const Vector2i& resolution) :
|
||||
mWorld(b2Vec2(0, 0)),
|
||||
mWindow(sf::VideoMode(resolution.x, resolution.y, 32), "Roguelike Shooter",
|
||||
sf::Style::Close | sf::Style::Titlebar),
|
||||
mView(Vector2f(0, 0), Vector2f(resolution)),
|
||||
//mFps("test"),
|
||||
mTileManager(mWorld),
|
||||
mPlayer(mWorld, mCollection),
|
||||
mElapsed(0),
|
||||
mQuit(false),
|
||||
mPaused(false) {
|
||||
mWindow.setFramerateLimit(FPS_GOAL);
|
||||
mWindow.setKeyRepeatEnabled(true);
|
||||
for (int i = 0; i < 500; i += 50) {
|
||||
mCollection.insert(std::shared_ptr<Sprite>(new Cover(Vector2f(i, i), Vector2i(20, 20),
|
||||
mWorld)), Collection::LEVEL_STATIC);
|
||||
}
|
||||
mTileManager.generate();
|
||||
mWorld.SetContactListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes window.
|
||||
*/
|
||||
Game::~Game() {
|
||||
mWindow.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the game loop.
|
||||
*/
|
||||
void
|
||||
Game::loop() {
|
||||
sf::Uint32 left = 0;
|
||||
while (!mQuit) {
|
||||
|
||||
input();
|
||||
|
||||
for (; !mPaused && (left >= TICKS_GOAL); left -= TICKS_GOAL) {
|
||||
Actor::think(TICKS_GOAL);
|
||||
mWorld.Step(1.0f / FPS_GOAL, 8, 3);
|
||||
|
||||
mCollection.checkDelete();
|
||||
}
|
||||
|
||||
//mFps.setString(getFps());
|
||||
|
||||
tick();
|
||||
left += mElapsed;
|
||||
|
||||
render();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves ticks since last call.
|
||||
*/
|
||||
void
|
||||
Game::tick() {
|
||||
mElapsed = mClock.restart().asMilliseconds();
|
||||
if (mPaused) {
|
||||
mElapsed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles general game input.
|
||||
*/
|
||||
void
|
||||
Game::input() {
|
||||
sf::Event event;
|
||||
while (mWindow.pollEvent(event)) {
|
||||
switch (event.type) {
|
||||
case sf::Event::Closed:
|
||||
mQuit = true;
|
||||
break;
|
||||
case sf::Event::KeyPressed:
|
||||
keyDown(event);
|
||||
break;
|
||||
case sf::Event::KeyReleased:
|
||||
keyUp(event);
|
||||
break;
|
||||
case sf::Event::MouseButtonReleased:
|
||||
mouseUp(event);
|
||||
break;
|
||||
case sf::Event::MouseMoved:
|
||||
mPlayer.setCrosshairPosition(convertCoordinates(event.mouseMove.x, event.mouseMove.y));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles key up event. This is used for events that only fire once per keypress.
|
||||
*/
|
||||
void
|
||||
Game::keyUp(const sf::Event& event) {
|
||||
switch (event.key.code) {
|
||||
case sf::Keyboard::Escape:
|
||||
mQuit = true;
|
||||
break;
|
||||
case sf::Keyboard::Space:
|
||||
mPaused = !mPaused;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles key down event. This is used for any events that refire automatically.
|
||||
*/
|
||||
void
|
||||
Game::keyDown(const sf::Event& event) {
|
||||
switch (event.key.code) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a screen coordinate to a world coordinate.
|
||||
*/
|
||||
sf::Vector2<float>
|
||||
Game::convertCoordinates(int x, int y) {
|
||||
return mWindow.convertCoords(Vector2i(x, y), mView);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles mouse key up events.
|
||||
*/
|
||||
void
|
||||
Game::mouseUp(const sf::Event& event) {
|
||||
switch (event.mouseButton.button) {
|
||||
case sf::Mouse::Left:
|
||||
mPlayer.fire();
|
||||
break;
|
||||
case sf::Mouse::Right:
|
||||
mPlayer.move(convertCoordinates(event.mouseButton.x, event.mouseButton.y));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders world and GUI.
|
||||
*/
|
||||
void
|
||||
Game::render() {
|
||||
mWindow.clear();
|
||||
|
||||
mView.setCenter(mPlayer.getPosition());
|
||||
|
||||
// Render world and dynamic stuff.
|
||||
mWindow.setView(mView);
|
||||
|
||||
mWindow.draw(mTileManager);
|
||||
mWindow.draw(mCollection);
|
||||
mWindow.draw(mPlayer);
|
||||
|
||||
// Render GUI and static stuff.
|
||||
mWindow.setView(mWindow.getDefaultView());
|
||||
|
||||
//mWindow.draw(mFps);
|
||||
|
||||
mWindow.display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current FPS as string.
|
||||
*/
|
||||
sf::String
|
||||
Game::getFps() {
|
||||
return str((mElapsed != 0) ? 1000.0f / mElapsed : 0.0f, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin of collision, call callback function on both objects.
|
||||
*/
|
||||
void
|
||||
Game::BeginContact(b2Contact* contact) {
|
||||
Physical& first = *static_cast<Physical*>(contact->GetFixtureA()->GetBody()->GetUserData());
|
||||
Physical& second = *static_cast<Physical*>(contact->GetFixtureB()->GetBody()->GetUserData());
|
||||
|
||||
if (!first.doesCollide(second) || !second.doesCollide(first)) {
|
||||
contact->SetEnabled(false);
|
||||
return;
|
||||
}
|
||||
first.onCollide(second, second.getCategory());
|
||||
second.onCollide(first, first.getCategory());
|
||||
}
|
71
source/Game.h
Normal file
71
source/Game.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Game.h
|
||||
*
|
||||
* Created on: 05.07.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#ifndef DG_GAME_H_
|
||||
#define DG_GAME_H_
|
||||
|
||||
#include <SFML/System.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
#include <Thor/Resources.hpp>
|
||||
|
||||
#include <Box2D/Box2D.h>
|
||||
|
||||
#include "TileManager.h"
|
||||
#include "sprite/Player.h"
|
||||
#include "util/Collection.h"
|
||||
|
||||
/*
|
||||
* Use vertex for tiles.
|
||||
*/
|
||||
class Game : private sf::NonCopyable, public b2ContactListener {
|
||||
// Public functions.
|
||||
public:
|
||||
Game(const Vector2i& resolution);
|
||||
~Game();
|
||||
|
||||
void loop();
|
||||
void BeginContact(b2Contact* contact);
|
||||
|
||||
// Private functions.
|
||||
private:
|
||||
void input();
|
||||
void render();
|
||||
void tick();
|
||||
|
||||
void keyDown(const sf::Event& event);
|
||||
void keyUp(const sf::Event& event);
|
||||
void mouseUp(const sf::Event& event);
|
||||
|
||||
sf::String getFps();
|
||||
sf::Vector2<float> convertCoordinates(int x, int y);
|
||||
|
||||
// Private variables.
|
||||
private:
|
||||
static const int FPS_GOAL;
|
||||
static const float TICKS_GOAL;
|
||||
|
||||
b2World mWorld;
|
||||
|
||||
sf::RenderWindow mWindow;
|
||||
sf::Clock mClock;
|
||||
sf::View mView;
|
||||
//sf::Text mFps;
|
||||
|
||||
Collection mCollection;
|
||||
TileManager mTileManager;
|
||||
Player mPlayer;
|
||||
|
||||
/// Milliseconds since the last tick.
|
||||
sf::Uint32 mElapsed;
|
||||
|
||||
bool mQuit;
|
||||
bool mPaused;
|
||||
};
|
||||
|
||||
|
||||
#endif /* DG_GAME_H_ */
|
116
source/TileManager.cpp
Executable file
116
source/TileManager.cpp
Executable file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* TileManager.cpp
|
||||
*
|
||||
* Created on: 08.08.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#include "TileManager.h"
|
||||
|
||||
#include <Thor/Resources.hpp>
|
||||
|
||||
#include "util/Loader.h"
|
||||
#include "util/ResourceManager.h"
|
||||
#include "abstract/Sprite.h"
|
||||
|
||||
const Vector2i TileManager::TILE_SIZE = Vector2i(100, 100);
|
||||
|
||||
/**
|
||||
* Loads tile resources.
|
||||
*
|
||||
* @param world Box2D world to create (physical) tiles in.
|
||||
*/
|
||||
TileManager::TileManager(b2World& world) :
|
||||
mWorld(world) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a tile.
|
||||
*
|
||||
* @param pType Type of the tile to create.
|
||||
* @param pPosition Position of the tile in tile coordinates.
|
||||
* @param world Box2D world object.
|
||||
*/
|
||||
TileManager::Tile::Tile(Type type, const TilePosition& position, b2World& world) :
|
||||
Sprite(getTexture(type), PhysicalData(Vector2f(position.x * TILE_SIZE.x, position.y * TILE_SIZE.y),
|
||||
TILE_SIZE, world, CATEGORY_WORLD, (type == TYPE_FLOOR) ? MASK_NONE : MASK_ALL, false)),
|
||||
mType(type) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a texture key for a certain tile type.
|
||||
*
|
||||
* @param type The type of tile to load a resource key for.
|
||||
* @return Resource key to the correct texture.
|
||||
*/
|
||||
std::shared_ptr<sf::Texture>
|
||||
TileManager::Tile::getTexture(Type type) {
|
||||
sf::String filename;
|
||||
switch (type) {
|
||||
case TYPE_FLOOR:
|
||||
filename = "floor.png";
|
||||
break;
|
||||
case TYPE_WALL:
|
||||
filename = "wall.png";
|
||||
break;
|
||||
default:
|
||||
throw new aurora::Exception("Invalid tile type.");
|
||||
}
|
||||
return ResourceManager::i().acquire(Loader::i().fromFile<sf::Texture>(filename));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Type of this tile.
|
||||
*/
|
||||
TileManager::Type
|
||||
TileManager::Tile::getType() const {
|
||||
return mType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the position of the tile with tile width/height as a unit.
|
||||
*/
|
||||
TileManager::TilePosition
|
||||
TileManager::Tile::getTilePosition() const {
|
||||
return TilePosition(getPosition().x / TILE_SIZE.x, getPosition().y / TILE_SIZE.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills the world with predefined tiles.
|
||||
*/
|
||||
void
|
||||
TileManager::generate() {
|
||||
for (int x = 0; x < 10; x++)
|
||||
for (int y = 0; y < 10; y++)
|
||||
setTile(TilePosition(x, y), TYPE_WALL);
|
||||
|
||||
for (int x = 1; x < 9; x++)
|
||||
for (int y = 1; y < 9; y++)
|
||||
setTile(TilePosition(x, y), TYPE_FLOOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a tile at the position. Deletes an existing tile first if one is at the position.
|
||||
*
|
||||
* @param position Grid coordinate of the tile (not pixel coordinate).
|
||||
* @param type Type of tile to be inserted.
|
||||
*/
|
||||
void
|
||||
TileManager::setTile(const TilePosition& position, Type type) {
|
||||
for (auto it = mTiles.begin(); it != mTiles.end(); it++) {
|
||||
if ((*it)->getTilePosition() == position) {
|
||||
mTiles.erase(it);
|
||||
}
|
||||
}
|
||||
mTiles.push_back(std::unique_ptr<Tile>(new Tile(type, position, mWorld)));
|
||||
}
|
||||
|
||||
/**
|
||||
* \copydoc sf::Drawable::draw
|
||||
*/
|
||||
void
|
||||
TileManager::draw(sf::RenderTarget& target, sf::RenderStates states) const {
|
||||
for (auto it = mTiles.begin(); it != mTiles.end(); it++) {
|
||||
target.draw((**it), states);
|
||||
}
|
||||
}
|
79
source/TileManager.h
Executable file
79
source/TileManager.h
Executable file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* TileManager.h
|
||||
*
|
||||
* Created on: 08.08.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#ifndef DG_TILEMANAGER_H_
|
||||
#define DG_TILEMANAGER_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
#include <Box2D/Box2D.h>
|
||||
|
||||
#include "util/Vector.h"
|
||||
#include "abstract/Sprite.h"
|
||||
|
||||
class TileManager : public sf::Drawable {
|
||||
// Public constants.
|
||||
public:
|
||||
/// The size of a single tile (pixels).
|
||||
static const Vector2i TILE_SIZE;
|
||||
|
||||
// Public functions.
|
||||
public:
|
||||
TileManager(b2World& world);
|
||||
|
||||
void generate();
|
||||
|
||||
// Private types.
|
||||
private:
|
||||
enum Type {
|
||||
TYPE_FLOOR,
|
||||
TYPE_WALL
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the length/width of a tile as a unit.
|
||||
*/
|
||||
typedef Vector2i TilePosition;
|
||||
|
||||
class Tile;
|
||||
|
||||
// Private functions.
|
||||
private:
|
||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const;
|
||||
void setTile(const TilePosition& position, Type type);
|
||||
|
||||
// Private variables.
|
||||
private:
|
||||
b2World& mWorld;
|
||||
std::vector<std::unique_ptr<Tile> > mTiles;
|
||||
};
|
||||
|
||||
/**
|
||||
* Holds information about a single tile.
|
||||
*/
|
||||
class TileManager::Tile : public Sprite {
|
||||
// Public functions.
|
||||
public:
|
||||
Tile(Type type, const TilePosition& position, b2World& world);
|
||||
|
||||
Type getType() const;
|
||||
TilePosition getTilePosition() const;
|
||||
|
||||
static std::shared_ptr<sf::Texture> getTexture(Type type);
|
||||
|
||||
// Private variables.
|
||||
private:
|
||||
Type mType;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* DG_TILEMANAGER_H_ */
|
41
source/abstract/Actor.cpp
Executable file
41
source/abstract/Actor.cpp
Executable file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Actor.cpp
|
||||
*
|
||||
* Created on: 02.09.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#include "Actor.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
|
||||
std::vector<Actor*> Actor::mInstances = std::vector<Actor*>();
|
||||
|
||||
/**
|
||||
* Saves pointer to this instance in static var for think().
|
||||
*/
|
||||
Actor::Actor() {
|
||||
mInstances.push_back(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes pointer from think() static var.
|
||||
*/
|
||||
Actor::~Actor() {
|
||||
auto it = std::find(mInstances.begin(), mInstances.end(), this);
|
||||
assert(it != mInstances.end());
|
||||
mInstances.erase(it);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls onThink on all Actor instances.
|
||||
*
|
||||
* @param elapsedTime Amount of time to simulate.
|
||||
*/
|
||||
void
|
||||
Actor::think(float elapsedTime) {
|
||||
for (auto i : mInstances) {
|
||||
i->onThink(elapsedTime);
|
||||
}
|
||||
}
|
38
source/abstract/Actor.h
Executable file
38
source/abstract/Actor.h
Executable file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Actor.h
|
||||
*
|
||||
* Created on: 02.09.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#ifndef DG_ACTOR_H_
|
||||
#define DG_ACTOR_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* Provides think function for AI.
|
||||
*/
|
||||
class Actor {
|
||||
// Public functions.
|
||||
public:
|
||||
Actor();
|
||||
virtual ~Actor() = 0;
|
||||
|
||||
static void think(float elapsedTime);
|
||||
|
||||
// Protected functions.
|
||||
protected:
|
||||
/**
|
||||
* Implement this function for any (regular) AI computations.
|
||||
*
|
||||
* @param elapsedTime Amount of time to simulate.
|
||||
*/
|
||||
virtual void onThink(float elapsedTime) = 0;
|
||||
|
||||
// Private variables.
|
||||
private:
|
||||
static std::vector<Actor*> mInstances;
|
||||
};
|
||||
|
||||
#endif /* DG_ACTOR_H_ */
|
166
source/abstract/Physical.cpp
Executable file
166
source/abstract/Physical.cpp
Executable file
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Physical.cpp
|
||||
*
|
||||
* Created on: 11.08.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#include "Physical.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <Thor/Vectors.hpp>
|
||||
|
||||
/**
|
||||
* Initializes Box2D body.
|
||||
*
|
||||
* @param data Data needed for construction.
|
||||
*/
|
||||
Physical::Physical(const PhysicalData& data) :
|
||||
mDelete(false) {
|
||||
assert(data.size != Vector2i());
|
||||
assert(data.category);
|
||||
|
||||
b2BodyDef bodyDef;
|
||||
// not moving -> static body
|
||||
// moving -> dynamic body
|
||||
// bullet -> kinematic body
|
||||
bodyDef.type = (data.moving) ?
|
||||
(data.bullet)
|
||||
? b2_dynamicBody
|
||||
: b2_dynamicBody
|
||||
: b2_staticBody;
|
||||
bodyDef.position = vector(data.position);
|
||||
bodyDef.allowSleep = true;
|
||||
bodyDef.fixedRotation = true;
|
||||
bodyDef.bullet = data.bullet;
|
||||
bodyDef.userData = this;
|
||||
|
||||
mBody = data.world.CreateBody(&bodyDef);
|
||||
|
||||
b2PolygonShape boxShape;
|
||||
boxShape.SetAsBox(pixelToMeter(data.size.x) / 2, pixelToMeter(data.size.y) / 2);
|
||||
|
||||
b2FixtureDef fixtureDef;
|
||||
fixtureDef.shape = &boxShape;
|
||||
fixtureDef.density = 1.0f;
|
||||
fixtureDef.filter.categoryBits = data.category;
|
||||
fixtureDef.filter.maskBits = ~data.maskExclude;
|
||||
fixtureDef.restitution = 0;
|
||||
|
||||
mBody->CreateFixture(&fixtureDef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes body from world.
|
||||
*/
|
||||
Physical::~Physical() {
|
||||
mBody->GetWorld()->DestroyBody(mBody);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes container.
|
||||
*
|
||||
* @link Physical::PhysicalData
|
||||
*/
|
||||
Physical::PhysicalData::PhysicalData( const Vector2f& position, const Vector2i& size,
|
||||
b2World& world, uint16 category, uint16 maskExclude, bool moving, bool bullet) :
|
||||
position(position),
|
||||
size(size),
|
||||
world(world),
|
||||
category(category),
|
||||
maskExclude(maskExclude),
|
||||
moving(moving),
|
||||
bullet(bullet) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the position of the sprite (center).
|
||||
*/
|
||||
Vector2f
|
||||
Physical::getPosition() const {
|
||||
return vector(mBody->GetPosition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the movement speed of the body.
|
||||
*/
|
||||
Vector2f
|
||||
Physical::getSpeed() const {
|
||||
return vector(mBody->GetLinearVelocity());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the rotation of the body (converted to an SFML angle).
|
||||
*/
|
||||
float
|
||||
Physical::getAngle() const {
|
||||
return - thor::toDegree(mBody->GetAngle());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this object should be deleted.
|
||||
*/
|
||||
bool
|
||||
Physical::getDelete() const {
|
||||
return mDelete;
|
||||
}
|
||||
|
||||
uint16
|
||||
Physical::getCategory() const {
|
||||
return mBody->GetFixtureList()->GetFilterData().categoryBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method filters collisions with other physicals. Implement it if you want to
|
||||
* limit collisions to/with certain objects. Default implementation always returns true.
|
||||
*
|
||||
* @param other The Physical this object is about to collide with.
|
||||
* @return True if the objects should collide.
|
||||
*/
|
||||
bool
|
||||
Physical::doesCollide(Physical& other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a collision with another body occured. Override this method
|
||||
* to manage collision events.
|
||||
*
|
||||
* @param other Reference to the other Physical in the collision.
|
||||
* @param category The Category of the other object (as passed in constructor).
|
||||
*/
|
||||
void
|
||||
Physical::onCollide(Physical& other, uint16 type) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to mark this object for deletion from the world.
|
||||
*/
|
||||
void
|
||||
Physical::setDelete(bool value) {
|
||||
mDelete = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets movement speed and direction of the body. Set either value to zero to stop movement.
|
||||
*
|
||||
* @param direction The direction the body moves in, does not have to be normalized.
|
||||
* @param speed The value of the movement speed to be used.
|
||||
*/
|
||||
void
|
||||
Physical::setSpeed(Vector2f direction, float speed) {
|
||||
if (direction != Vector2f()) {
|
||||
direction = thor::unitVector<float>(direction);
|
||||
}
|
||||
direction *= speed;
|
||||
mBody->SetLinearVelocity(vector(direction));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the angle of the body based on the direction of a vector.
|
||||
*/
|
||||
void
|
||||
Physical::setAngle(float angle) {
|
||||
mBody->SetTransform(mBody->GetPosition(), - thor::toRadian(angle));
|
||||
}
|
90
source/abstract/Physical.h
Executable file
90
source/abstract/Physical.h
Executable file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Physical.h
|
||||
*
|
||||
* Created on: 11.08.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#ifndef DG_PHYSICAL_H_
|
||||
#define DG_PHYSICAL_H_
|
||||
|
||||
#include <Box2D/Box2D.h>
|
||||
|
||||
#include "../util/Vector.h"
|
||||
|
||||
/**
|
||||
* An object with physical properties.
|
||||
*
|
||||
* @warning May only handle bodies with one fixture.
|
||||
*/
|
||||
class Physical {
|
||||
// Public types.
|
||||
public:
|
||||
/**
|
||||
* POD container that carries all data required to construct this class.
|
||||
*/
|
||||
class PhysicalData {
|
||||
public:
|
||||
PhysicalData() = default;
|
||||
PhysicalData(const Vector2f& position, const Vector2i& size, b2World& world,
|
||||
uint16 category, uint16 maskExclude, bool moving, bool bullet = false);
|
||||
const Vector2f& position; //< World position of the body in pixel coordinates.
|
||||
const Vector2i& size; //< Pixel size of the body.
|
||||
b2World& world; //< Box2D world object.
|
||||
uint16 category; //< The category for collision filtering. Only one may be set. @link Physical::Category
|
||||
uint16 maskExclude; //< All categories set here will have collisions disabled with this object.
|
||||
bool moving; //< True if the body may move on its own (player, monster).
|
||||
bool bullet; //< True if the object is a bullet.
|
||||
};
|
||||
|
||||
/**
|
||||
* Categories of physical objects, for Box2D collision filtering.
|
||||
*
|
||||
* @warning An object may only have one category.
|
||||
*/
|
||||
enum Category {
|
||||
CATEGORY_NONSOLID = 0,
|
||||
CATEGORY_WORLD = 1 << 1,
|
||||
CATEGORY_ACTOR = 1 << 2,
|
||||
CATEGORY_PARTICLE = 1 << 3
|
||||
};
|
||||
|
||||
/**
|
||||
* Common Box2D collision masking values.
|
||||
*/
|
||||
enum Mask {
|
||||
MASK_NONE = 0xffff, //< Disables any collisions.
|
||||
MASK_ALL = 0 //< Enables all collisions.
|
||||
};
|
||||
|
||||
// Public functions.
|
||||
public:
|
||||
Physical(const PhysicalData& data);
|
||||
virtual ~Physical() = 0;
|
||||
|
||||
Vector2f getPosition() const;
|
||||
Vector2f getSpeed() const;
|
||||
float getAngle() const;
|
||||
bool getDelete() const;
|
||||
uint16 getCategory() const;
|
||||
|
||||
virtual bool doesCollide(Physical& other);
|
||||
virtual void onCollide(Physical& other, uint16 category);
|
||||
|
||||
// Protected functions.
|
||||
protected:
|
||||
void setDelete(bool value);
|
||||
void setSpeed(Vector2f direction, float speed);
|
||||
void setAngle(float angle);
|
||||
|
||||
// Protected variables.
|
||||
protected:
|
||||
// Currently protected to allow for (debug only) direct player input.
|
||||
b2Body* mBody;
|
||||
|
||||
// Private variables.
|
||||
private:
|
||||
bool mDelete;
|
||||
};
|
||||
|
||||
#endif /* DG_PHYSICAL_H_ */
|
58
source/abstract/Sprite.cpp
Normal file
58
source/abstract/Sprite.cpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Sprite.cpp
|
||||
*
|
||||
* Created on: 22.07.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#include "Sprite.h"
|
||||
|
||||
#include "../util/Loader.h"
|
||||
#include "../util/Log.h"
|
||||
#include "../util/String.h"
|
||||
#include "../util/ResourceManager.h"
|
||||
|
||||
/**
|
||||
* Loads sprite from ResourceManager, sets world position.
|
||||
*
|
||||
* @param texturePath Relative path to the texture file in the resource folder.
|
||||
*/
|
||||
Sprite::Sprite(const sf::String& texturePath, const PhysicalData& data) :
|
||||
Physical(data),
|
||||
mTexture(ResourceManager::i().acquire(Loader::i().fromFile<sf::Texture>(texturePath))),
|
||||
mSize(data.size) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads sprite from ResourceManager, sets world position. Use this if the texture has already been loaded.
|
||||
*
|
||||
* @param texture Pointer to the texture to be used (must already be loaded).
|
||||
*/
|
||||
Sprite::Sprite(const std::shared_ptr<sf::Texture>& texture, const PhysicalData& data) :
|
||||
Physical(data),
|
||||
mTexture(texture),
|
||||
mSize(data.size) {
|
||||
|
||||
}
|
||||
/**
|
||||
* Does nothing.
|
||||
*/
|
||||
Sprite::~Sprite() {
|
||||
}
|
||||
|
||||
/**
|
||||
* \copydoc sf::Drawable::draw
|
||||
*/
|
||||
void
|
||||
Sprite::draw(sf::RenderTarget& target, sf::RenderStates states) const {
|
||||
// Create a temporary shape to apply box2d body transformations to.
|
||||
sf::RectangleShape shape = sf::RectangleShape(Vector2f(mSize));
|
||||
shape.setTexture(&*mTexture, true);
|
||||
shape.setOrigin(Vector2f(mSize.x / 2, mSize.y / 2));
|
||||
shape.setTextureRect(sf::IntRect(Vector2i(0, 0), mSize));
|
||||
|
||||
shape.setPosition(getPosition());
|
||||
shape.setRotation(getAngle());
|
||||
|
||||
target.draw(shape, states);
|
||||
}
|
36
source/abstract/Sprite.h
Normal file
36
source/abstract/Sprite.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Sprite.h
|
||||
*
|
||||
* Created on: 22.07.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#ifndef DG_SPRITE_H_
|
||||
#define DG_SPRITE_H_
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
#include <Thor/Resources.hpp>
|
||||
|
||||
#include "Physical.h"
|
||||
#include "../util/Vector.h"
|
||||
|
||||
/**
|
||||
* Represents a drawable object.
|
||||
*
|
||||
* Handles drawing to world.
|
||||
*/
|
||||
class Sprite : public sf::Drawable, public Physical {
|
||||
public:
|
||||
Sprite(const sf::String& texturePath, const PhysicalData& data);
|
||||
Sprite(const std::shared_ptr<sf::Texture>& texture, const PhysicalData& data);
|
||||
virtual ~Sprite() = 0;
|
||||
|
||||
private:
|
||||
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;
|
||||
|
||||
std::shared_ptr<sf::Texture> mTexture;
|
||||
Vector2i mSize;
|
||||
};
|
||||
|
||||
#endif /* DG_SPRITE_H_ */
|
45
source/effects/Bullet.cpp
Executable file
45
source/effects/Bullet.cpp
Executable file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Bullet.cpp
|
||||
*
|
||||
* Created on: 12.08.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#include "Bullet.h"
|
||||
|
||||
#include "../util/Log.h"
|
||||
|
||||
const float Bullet::SPEED = 500.0f;
|
||||
|
||||
/**
|
||||
* Places a bullet in the world.
|
||||
*
|
||||
* @param position World position of the bullet.
|
||||
* @param world Box2d world.
|
||||
* @param texture Texture to display for bullet.
|
||||
*/
|
||||
Bullet::Bullet(const Vector2f& position, b2World& world,
|
||||
const std::shared_ptr<sf::Texture>& texture, Physical& shooter, float direction) :
|
||||
Particle(texture, PhysicalData(position, Vector2i(20, 20), world, CATEGORY_PARTICLE,
|
||||
CATEGORY_PARTICLE, true, true)),
|
||||
mShooter(shooter) {
|
||||
setSpeed(angle(direction), SPEED);
|
||||
setAngle(direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Physical::onCollide
|
||||
*/
|
||||
void
|
||||
Bullet::onCollide(Physical& other, uint16 type) {
|
||||
// Make sure we do not damage twice.
|
||||
if (!getDelete()) {
|
||||
// Call onShot on other, with damage as param.
|
||||
setDelete(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Bullet::doesCollide(Physical& other) {
|
||||
return &other != &mShooter;
|
||||
}
|
31
source/effects/Bullet.h
Executable file
31
source/effects/Bullet.h
Executable file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Bullet.h
|
||||
*
|
||||
* Created on: 12.08.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#ifndef DG_BULLET_H_
|
||||
#define DG_BULLET_H_
|
||||
|
||||
#include "../particle/Particle.h"
|
||||
|
||||
/**
|
||||
* Bullet particle fired by a weapon, may damage actors.
|
||||
*/
|
||||
class Bullet : public Particle {
|
||||
// Public functions.
|
||||
public:
|
||||
Bullet(const Vector2f& position, b2World& world, const std::shared_ptr<sf::Texture>& texture,
|
||||
Physical& shooter, float direction);
|
||||
|
||||
void onCollide(Physical& other, uint16 category);
|
||||
bool doesCollide(Physical& other);
|
||||
|
||||
// Private variables.
|
||||
private:
|
||||
static const float SPEED;
|
||||
Physical& mShooter;
|
||||
};
|
||||
|
||||
#endif /* DG_BULLET_H_ */
|
38
source/items/Weapon.cpp
Executable file
38
source/items/Weapon.cpp
Executable file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Weapon.cpp
|
||||
*
|
||||
* Created on: 12.08.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#include "Weapon.h"
|
||||
|
||||
#include "../util/Collection.h"
|
||||
#include "../effects/Bullet.h"
|
||||
#include "../util/Loader.h"
|
||||
#include "../util/ResourceManager.h"
|
||||
|
||||
Weapon::Weapon(Physical& holder, Collection& collection, b2World& world) :
|
||||
Emitter(collection),
|
||||
mHolder(holder),
|
||||
mBulletTexture(ResourceManager::i().acquire(Loader::i().fromFile<sf::Texture>("bullet.png"))),
|
||||
mWorld(world) {
|
||||
}
|
||||
|
||||
Weapon::~Weapon() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Call on any button press/refire.
|
||||
*/
|
||||
void
|
||||
Weapon::fire() {
|
||||
// Only call if has ammo, consider firing rate etc.
|
||||
emit();
|
||||
}
|
||||
|
||||
std::shared_ptr<Particle>
|
||||
Weapon::createParticle() {
|
||||
return std::shared_ptr<Particle>(new Bullet(mHolder.getPosition(), mWorld, mBulletTexture,
|
||||
mHolder, mHolder.getAngle()));
|
||||
}
|
37
source/items/Weapon.h
Executable file
37
source/items/Weapon.h
Executable file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Weapon.h
|
||||
*
|
||||
* Created on: 12.08.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#ifndef DG_WEAPON_H_
|
||||
#define DG_WEAPON_H_
|
||||
|
||||
#include <Thor/Particles.hpp>
|
||||
|
||||
#include "../abstract/Physical.h"
|
||||
#include "../particle/Emitter.h"
|
||||
|
||||
/**
|
||||
* Loading mechanism:
|
||||
* - pass enum value and load mapped xml
|
||||
* - pass xml filename
|
||||
*/
|
||||
class Weapon : public Emitter {
|
||||
public:
|
||||
Weapon(Physical& holder, Collection& collection, b2World& world);
|
||||
~Weapon();
|
||||
|
||||
void fire();
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Particle> createParticle();
|
||||
|
||||
private:
|
||||
Physical& mHolder;
|
||||
std::shared_ptr<sf::Texture> mBulletTexture;
|
||||
b2World& mWorld;
|
||||
};
|
||||
|
||||
#endif /* DG_WEAPON_H_ */
|
23
source/main.cpp
Normal file
23
source/main.cpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* main.cpp
|
||||
*
|
||||
* Created on: 19.07.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#include "Game.h"
|
||||
#include "util/Loader.h"
|
||||
|
||||
/**
|
||||
* Creates Game object.
|
||||
*/
|
||||
int main(int argc, char* argv[]) {
|
||||
Loader::i().setFolder("resources/");
|
||||
Loader::i().setSubFolder<sf::Texture>("textures/");
|
||||
|
||||
Game game(Vector2i(800, 600));
|
||||
|
||||
game.loop();
|
||||
|
||||
return 0;
|
||||
}
|
23
source/particle/Emitter.cpp
Executable file
23
source/particle/Emitter.cpp
Executable file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Emitter.cpp
|
||||
*
|
||||
* Created on: 15.08.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#include "Emitter.h"
|
||||
|
||||
Emitter::Emitter(Collection& collection) :
|
||||
mCollection(collection) {
|
||||
}
|
||||
|
||||
Emitter::~Emitter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a new particle into the system, using createParticle().
|
||||
*/
|
||||
void
|
||||
Emitter::emit() {
|
||||
mCollection.insert(createParticle(), Collection::LEVEL_PARTICLE);
|
||||
}
|
32
source/particle/Emitter.h
Executable file
32
source/particle/Emitter.h
Executable file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Emitter.h
|
||||
*
|
||||
* Created on: 15.08.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#ifndef DG_EMITTER_H_
|
||||
#define DG_EMITTER_H_
|
||||
|
||||
#include "../abstract/Physical.h"
|
||||
#include "../util/Collection.h"
|
||||
#include "Particle.h"
|
||||
|
||||
class Emitter {
|
||||
// Public functions.
|
||||
public:
|
||||
Emitter(Collection& collection);
|
||||
virtual ~Emitter();
|
||||
|
||||
// Protected functions.
|
||||
protected:
|
||||
void emit();
|
||||
/// Creates a particle. Allows to use a user-defined particle class and custom settings.
|
||||
virtual std::shared_ptr<Particle> createParticle() = 0;
|
||||
|
||||
// Private variables.
|
||||
private:
|
||||
Collection& mCollection;
|
||||
};
|
||||
|
||||
#endif /* DG_EMITTER_H_ */
|
16
source/particle/Particle.cpp
Executable file
16
source/particle/Particle.cpp
Executable file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Particle.cpp
|
||||
*
|
||||
* Created on: 15.08.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#include "Particle.h"
|
||||
|
||||
Particle::Particle(const std::shared_ptr<sf::Texture>& texture, const PhysicalData& data) :
|
||||
Sprite(texture, data) {
|
||||
}
|
||||
|
||||
Particle::~Particle() {
|
||||
}
|
||||
|
22
source/particle/Particle.h
Executable file
22
source/particle/Particle.h
Executable file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Particle.h
|
||||
*
|
||||
* Created on: 15.08.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#ifndef DG_PARTICLE_H_
|
||||
#define DG_PARTICLE_H_
|
||||
|
||||
#include "../abstract/Sprite.h"
|
||||
|
||||
/**
|
||||
* Prototype for a particle.
|
||||
*/
|
||||
class Particle : public Sprite {
|
||||
public:
|
||||
Particle(const std::shared_ptr<sf::Texture>& texture, const PhysicalData& data);
|
||||
virtual ~Particle();
|
||||
};
|
||||
|
||||
#endif /* DG_PARTICLE_H_ */
|
13
source/sprite/Cover.cpp
Executable file
13
source/sprite/Cover.cpp
Executable file
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Cover.cpp
|
||||
*
|
||||
* Created on: 12.08.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#include "Cover.h"
|
||||
|
||||
Cover::Cover(const Vector2f& position, const Vector2i& size, b2World& world) :
|
||||
Sprite("cover.png", PhysicalData(position, size, world, CATEGORY_WORLD, MASK_ALL, false)) {
|
||||
}
|
||||
|
21
source/sprite/Cover.h
Executable file
21
source/sprite/Cover.h
Executable file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Cover.h
|
||||
*
|
||||
* Created on: 12.08.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#ifndef DG_COVER_H_
|
||||
#define DG_COVER_H_
|
||||
|
||||
#include "../abstract/Sprite.h"
|
||||
|
||||
/**
|
||||
* A wall that can be placed anywhere (not limited by tiles) and have any (rectangular) size.
|
||||
*/
|
||||
class Cover : public Sprite {
|
||||
public:
|
||||
Cover(const Vector2f& position, const Vector2i& size, b2World& world);
|
||||
};
|
||||
|
||||
#endif /* DG_COVER_H_ */
|
74
source/sprite/Player.cpp
Normal file
74
source/sprite/Player.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Player.cpp
|
||||
*
|
||||
* Created on: 21.07.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#include "Player.h"
|
||||
|
||||
#include <Thor/Vectors.hpp>
|
||||
|
||||
#include "../util/Vector.h"
|
||||
#include "../items/Weapon.h"
|
||||
|
||||
const float Player::SPEED = 100.0f;
|
||||
|
||||
/**
|
||||
* Initializes Sprite.
|
||||
*/
|
||||
Player::Player(b2World& world, Collection& collection) :
|
||||
Sprite("player.png", PhysicalData(Vector2f(200.0f, 100.0f), Vector2i(50, 50), world,
|
||||
CATEGORY_ACTOR, MASK_ALL, true)),
|
||||
mWeapon(*this, collection, world),
|
||||
mDestination(Vector2i(50, 50)) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the point where to look and shoot at.
|
||||
*
|
||||
* @param Absolute world coordinates of the crosshair.
|
||||
*/
|
||||
void
|
||||
Player::setCrosshairPosition(const Vector2f& position) {
|
||||
mCrosshairPosition = position - getPosition();
|
||||
}
|
||||
/**
|
||||
* Fire the attacked Weapon, emitting a Bullet object.
|
||||
*/
|
||||
void
|
||||
Player::fire() {
|
||||
mWeapon.fire();
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the player to a destination point.
|
||||
*
|
||||
* @param destination Absolute world coordinate of the destination point.
|
||||
*/
|
||||
void
|
||||
Player::move(const Vector2f& destination) {
|
||||
mDestination = destination;
|
||||
// Convert to relative destination.
|
||||
setSpeed(mDestination - getPosition(), SPEED);
|
||||
}
|
||||
|
||||
void
|
||||
Player::onThink(float elapsedTime) {
|
||||
// Stop if we are close enough.
|
||||
if (thor::length(mDestination - getPosition()) < 1.0f) {
|
||||
setSpeed(Vector2f(), 0);
|
||||
}
|
||||
// Look towards crosshair.
|
||||
setAngle(angle(mCrosshairPosition));
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop movement if we collide with anything except bullets.
|
||||
*/
|
||||
void
|
||||
Player::onCollide(Physical& other, uint16 category) {
|
||||
if (category != CATEGORY_PARTICLE) {
|
||||
mDestination = getPosition();
|
||||
}
|
||||
}
|
46
source/sprite/Player.h
Normal file
46
source/sprite/Player.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Player.h
|
||||
*
|
||||
* Created on: 21.07.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#ifndef DG_PLAYER_H_
|
||||
#define DG_PLAYER_H_
|
||||
|
||||
#include <SFML/System.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
#include "../abstract/Actor.h"
|
||||
#include "../abstract/Sprite.h"
|
||||
#include "../items/Weapon.h"
|
||||
#include "../util/Vector.h"
|
||||
|
||||
class Sprite;
|
||||
|
||||
/**
|
||||
* Player object.
|
||||
*/
|
||||
class Player : public Sprite, public Actor {
|
||||
// Public functions.
|
||||
public:
|
||||
Player(b2World& world, Collection& collection);
|
||||
|
||||
void setCrosshairPosition(const Vector2f& position);
|
||||
void fire();
|
||||
void move(const Vector2f& destination);
|
||||
|
||||
// Protected functions.
|
||||
protected:
|
||||
void onCollide(Physical& other, uint16 category);
|
||||
void onThink(float elapsedTime);
|
||||
|
||||
// Private variables.
|
||||
private:
|
||||
static const float SPEED;
|
||||
Weapon mWeapon; //< Weapon object used for Player::fire().
|
||||
Vector2f mDestination; //< Absolute position of the movement destination.
|
||||
Vector2f mCrosshairPosition; //< Relative position of the point to fire at (mouse cursor).
|
||||
};
|
||||
|
||||
#endif /* DG_PLAYER_H_ */
|
65
source/util/Collection.cpp
Executable file
65
source/util/Collection.cpp
Executable file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Collection.cpp
|
||||
*
|
||||
* Created on: 29.08.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#include "Collection.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
/**
|
||||
* Insert a drawable into the group. Drawables should only be handled with shared_ptr.
|
||||
* An object can't be inserted more than once at the same level.
|
||||
*/
|
||||
void
|
||||
Collection::insert(std::shared_ptr<Sprite> drawable, Level level) {
|
||||
auto item = std::find(mDrawables[level].begin(), mDrawables[level].end(), drawable);
|
||||
if (item == mDrawables[level].end()) {
|
||||
mDrawables[level].push_back(drawable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a drawable from the group.
|
||||
*/
|
||||
void
|
||||
Collection::remove(std::shared_ptr<Sprite> drawable) {
|
||||
for (auto v = mDrawables.begin(); v != mDrawables.end(); v++) {
|
||||
auto item = std::find(v->second.begin(), v->second.end(), drawable);
|
||||
if (item != v->second.end()) {
|
||||
v->second.erase(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes any sprites which return true for getDelete().
|
||||
*/
|
||||
void
|
||||
Collection::checkDelete() {
|
||||
for (auto v = mDrawables.begin(); v != mDrawables.end(); v++) {
|
||||
for (auto item = v->second.begin(); item != v->second.end(); ) {
|
||||
if ((*item)->getDelete()) {
|
||||
item = v->second.erase(item);
|
||||
}
|
||||
else {
|
||||
item++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws all elements in the group.
|
||||
*/
|
||||
void
|
||||
Collection::draw(sf::RenderTarget& target, sf::RenderStates states) const {
|
||||
for (auto v = mDrawables.begin(); v != mDrawables.end(); v++) {
|
||||
for (auto item : v->second) {
|
||||
target.draw(static_cast<sf::Drawable&>(*item), states);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
48
source/util/Collection.h
Executable file
48
source/util/Collection.h
Executable file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Collection.h
|
||||
*
|
||||
* Created on: 29.08.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#ifndef DG_COLLECTION_H_
|
||||
#define DG_COLLECTION_H_
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
#include "../abstract/Sprite.h"
|
||||
|
||||
/**
|
||||
* A collection of sprites, which can be put into different layers.
|
||||
*/
|
||||
class Collection : public sf::Drawable {
|
||||
// Public types.
|
||||
public:
|
||||
/**
|
||||
* Determines in what order sprites are rendered, dynamics and actors should be on top.
|
||||
*/
|
||||
enum Level {
|
||||
LEVEL_STATIC,
|
||||
LEVEL_PARTICLE,
|
||||
LEVEL_ACTOR
|
||||
};
|
||||
|
||||
// Public functions.
|
||||
public:
|
||||
void insert(std::shared_ptr<Sprite> drawable, Level level);
|
||||
void remove(std::shared_ptr<Sprite> drawable);
|
||||
void checkDelete();
|
||||
|
||||
// Private functions.
|
||||
private:
|
||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const;
|
||||
|
||||
// Private variables.
|
||||
private:
|
||||
std::map<Level, std::vector<std::shared_ptr<Sprite> > > mDrawables;
|
||||
};
|
||||
|
||||
#endif /* DG_COLLECTION_H_ */
|
137
source/util/Loader.h
Executable file
137
source/util/Loader.h
Executable file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Loader.h
|
||||
*
|
||||
* Created on: 13.08.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#ifndef DG_LOADER_H_
|
||||
#define DG_LOADER_H_
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include <SFML/System.hpp>
|
||||
|
||||
#include <Thor/Resources.hpp>
|
||||
|
||||
#include "Singleton.h"
|
||||
|
||||
/**
|
||||
* This class allows to set default resource folders and subfolders, which means that these
|
||||
* folders only have to be set once, and not be included in the creation of every single
|
||||
* resource key.
|
||||
*
|
||||
* If the general resource folder or a specific resource folder is not set, the current
|
||||
* directory is searched.
|
||||
*
|
||||
* R is any resource that can be loaded with Thor's resource loader.
|
||||
*
|
||||
* Any folder/file parameter can be a full path and is relative to the current directory,
|
||||
* or the directory set by the higher variables.
|
||||
*
|
||||
* @code
|
||||
* Loader l;
|
||||
* l.setFolder("resources/");
|
||||
* l.setSubFolder<sf::Texture>("textures/");
|
||||
* thor::ResourceKey<sf::Texture> t = l.fromFile<sf::Texture>("myimage.png");
|
||||
*
|
||||
* ResourceManager r;
|
||||
* r.acquire(t); // This loads from "resources/textures/myimage.png".
|
||||
* // folder subfolder file
|
||||
* @endcode
|
||||
*/
|
||||
class Loader : public Singleton<Loader> {
|
||||
// Public functions.
|
||||
public:
|
||||
/**
|
||||
* Sets the general resource folder path.
|
||||
*/
|
||||
inline void setFolder(const std::string& folder) {mFolder = folder;};
|
||||
|
||||
/**
|
||||
* Sets the resource subfolder for the specific type.
|
||||
*/
|
||||
template <typename R> void
|
||||
setSubFolder(std::string path) {
|
||||
getLoader<R>()->setSubFolder(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a resource from a file, looking in the specific resource folder for this type.
|
||||
*/
|
||||
template <typename T> thor::ResourceKey<T>
|
||||
fromFile(const std::string& file) {
|
||||
return static_cast<SpecificLoader<T>* >(getLoader<T>().get())->fromFile(mFolder, file);
|
||||
}
|
||||
|
||||
// Private types.
|
||||
private:
|
||||
/**
|
||||
* We need this to save templates of different types in the same container.
|
||||
*/
|
||||
class LoaderBase {
|
||||
public:
|
||||
virtual void setSubFolder(const std::string& path) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class forwards the loading of each individual type to Thor.
|
||||
*/
|
||||
template <typename T>
|
||||
class SpecificLoader : public LoaderBase {
|
||||
public:
|
||||
/**
|
||||
* Sets the subfolder for the current type.
|
||||
*/
|
||||
void
|
||||
setSubFolder(const std::string& path) {
|
||||
mSubfolder = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a resource from file via Thor.
|
||||
*
|
||||
* @param folder The general resource folder
|
||||
* @param file Path/name of the file within the resource subfolder.
|
||||
*/
|
||||
thor::ResourceKey<T>
|
||||
fromFile(const std::string& folder, const std::string& file) {
|
||||
return thor::Resources::fromFile<T>(folder + mSubfolder + file);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string mSubfolder;
|
||||
};
|
||||
|
||||
// Private functions.
|
||||
private:
|
||||
/**
|
||||
* For Singleton behaviour.
|
||||
*/
|
||||
Loader() = default;
|
||||
friend class Singleton<Loader>;
|
||||
|
||||
/**
|
||||
* Gets the correct loader for each template type, creates it if it does not exist.
|
||||
*/
|
||||
template <typename T> std::unique_ptr<LoaderBase>&
|
||||
getLoader() {
|
||||
auto loader = mLoaders.find(typeid(T));
|
||||
if (loader != mLoaders.end()) {
|
||||
return static_cast<std::unique_ptr<LoaderBase>&>(loader->second);
|
||||
}
|
||||
else {
|
||||
return (*mLoaders.insert(std::pair<std::type_index, std::unique_ptr<LoaderBase> >
|
||||
(typeid(T), std::unique_ptr<LoaderBase>(new SpecificLoader<T>))).first).second;
|
||||
}
|
||||
};
|
||||
|
||||
// Private variables.
|
||||
private:
|
||||
std::string mFolder;
|
||||
std::map<std::type_index, std::unique_ptr<LoaderBase> > mLoaders;
|
||||
};
|
||||
|
||||
#endif /* DG_LOADER_H_ */
|
37
source/util/Log.h
Normal file
37
source/util/Log.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Log.h
|
||||
*
|
||||
* Created on: 25.07.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#ifndef DG_LOG_H_
|
||||
#define DG_LOG_H_
|
||||
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* \def LOG_E(str)
|
||||
* Log an error to the error stream.
|
||||
*/
|
||||
#define LOG_E(str) std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " \"" << str << "\"" << std::endl
|
||||
|
||||
/**
|
||||
* \def LOG_E(str)
|
||||
* Log a warning to the output stream.
|
||||
*/
|
||||
#define LOG_W(str) std::cout << "Warning: " << __FILE__ << ":" << __LINE__ << " \"" << str << "\"" << std::endl
|
||||
|
||||
/**
|
||||
* \def LOG_E(str)
|
||||
* Log a debug message to the output stream.
|
||||
*/
|
||||
#define LOG_D(str) std::cout << "Debug: " << __FILE__ << ":" << __LINE__ << " \"" << str << "\"" << std::endl
|
||||
|
||||
/**
|
||||
* \def LOG_E(str)
|
||||
* Log an info to the output stream.
|
||||
*/
|
||||
#define LOG_I(str) std::cout << "Info: " << __FILE__ << ":" << __LINE__ << " \"" << str << "\"" << std::endl
|
||||
|
||||
#endif /* DG_LOG_H_ */
|
26
source/util/ResourceManager.h
Normal file
26
source/util/ResourceManager.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* ResourceManager.h
|
||||
*
|
||||
* Created on: 22.07.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#ifndef DG_RESOURCEMANAGER_H_
|
||||
#define DG_RESOURCEMANAGER_H_
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
#include <Thor/Resources.hpp>
|
||||
|
||||
#include "Singleton.h"
|
||||
|
||||
/**
|
||||
* Loads and manages all resources by providing Singleton access to Thor ResourceManager.
|
||||
*/
|
||||
class ResourceManager : public thor::MultiResourceCache, public Singleton<ResourceManager> {
|
||||
private:
|
||||
friend class Singleton<ResourceManager>;
|
||||
ResourceManager() = default;
|
||||
};
|
||||
|
||||
#endif /* DG_RESOURCEMANAGER_H_ */
|
31
source/util/Singleton.h
Normal file
31
source/util/Singleton.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Singleton.h
|
||||
*
|
||||
* Created on: 04.07.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#ifndef DG_SINGLETON_H_
|
||||
#define DG_SINGLETON_H_
|
||||
|
||||
#include <SFML/System.hpp>
|
||||
|
||||
/**
|
||||
* Template class for inheriting singleton behaviour.
|
||||
*
|
||||
* To use, just make a subclass with only a private default constructor and Singleton<T>
|
||||
* as friend class.
|
||||
*/
|
||||
template <class T>
|
||||
class Singleton : public sf::NonCopyable {
|
||||
public:
|
||||
/**
|
||||
* Get the instance of this class.
|
||||
*/
|
||||
static T& i() {
|
||||
static T s;
|
||||
return s;
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* DG_SINGLETON_H_ */
|
50
source/util/String.h
Normal file
50
source/util/String.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* String.h
|
||||
*
|
||||
* Created on: 19.07.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
/**
|
||||
* Use this as a replacement for std::to_string as MingW does not support it.
|
||||
*/
|
||||
|
||||
#ifndef DG_STRING_H_
|
||||
#define DG_STRING_H_
|
||||
|
||||
#include <math.h>
|
||||
#include <sstream>
|
||||
|
||||
#include <SFML/System.hpp>
|
||||
|
||||
/**
|
||||
* Converts any value to a string.
|
||||
*
|
||||
* @param val Any variable.
|
||||
* @return val converted to string.
|
||||
*/
|
||||
template <typename T>
|
||||
sf::String
|
||||
str(T val) {
|
||||
std::stringstream out;
|
||||
out << val;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts floating point variable to string,
|
||||
*
|
||||
* @param val Any floating point variable.
|
||||
* @param digits Number of decimal places to round to.
|
||||
* @return val converted to string.
|
||||
*/
|
||||
template <typename T>
|
||||
sf::String
|
||||
str(T val, int digits) {
|
||||
std::stringstream out;
|
||||
out.precision(digits);
|
||||
out << val;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
#endif /* DG_STRING_H_ */
|
84
source/util/Vector.h
Executable file
84
source/util/Vector.h
Executable file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Vector.h
|
||||
*
|
||||
* Created on: 03.08.2012
|
||||
* Author: Felix
|
||||
*/
|
||||
|
||||
#ifndef VECTOR_H_
|
||||
#define VECTOR_H_
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <SFML/System.hpp>
|
||||
|
||||
#include <Box2D/Box2D.h>
|
||||
|
||||
#include <Thor/Vectors.hpp>
|
||||
|
||||
/**
|
||||
* 2D floating point vector with x/y members.
|
||||
*/
|
||||
typedef sf::Vector2f Vector2f;
|
||||
|
||||
/**
|
||||
* 2D integer vector with x/y members.
|
||||
*/
|
||||
typedef sf::Vector2i Vector2i;
|
||||
|
||||
/**
|
||||
* Constant for conversion between Box2D vectors and SFML vectors.
|
||||
*/
|
||||
static const int PIXELS_PER_METER = 25;
|
||||
|
||||
/**
|
||||
* Converts a distance from pixels to meters.
|
||||
*/
|
||||
inline float
|
||||
pixelToMeter(float in) {
|
||||
return in / PIXELS_PER_METER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a distance from meters to pixels.
|
||||
*/
|
||||
inline float
|
||||
meterToPixel(float in) {
|
||||
return in * PIXELS_PER_METER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts Box2D metric vector to SFML pixel vector.
|
||||
*/
|
||||
inline Vector2f
|
||||
vector(const b2Vec2& in) {
|
||||
return Vector2f(meterToPixel(in.x), meterToPixel(in.y));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts SFML pixel vector to Box2D metric vector.
|
||||
*/
|
||||
inline b2Vec2
|
||||
vector(const Vector2f& in) {
|
||||
return b2Vec2(pixelToMeter(in.x), pixelToMeter(in.y));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a vector to an SFML angle with the same direction.
|
||||
*/
|
||||
inline float
|
||||
angle(Vector2f in) {
|
||||
return 180 - thor::toDegree(atan2(in.x, in.y));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an SFML angle to a unit vector with the same direction.
|
||||
*/
|
||||
inline Vector2f
|
||||
angle(float in) {
|
||||
in = thor::toRadian(180 - in);
|
||||
return Vector2f(sin(in), cos(in));
|
||||
}
|
||||
|
||||
|
||||
#endif /* VECTOR_H_ */
|
Reference in a new issue