Last active
December 14, 2015 09:09
-
-
Save PeterHajdu/5063326 to your computer and use it in GitHub Desktop.
object container
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
*swp | |
*~ | |
*.o | |
a.out | |
demo | |
testFile | |
a | |
gmon* | |
prof* | |
*core* | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Aabb.hpp" | |
platformer::Aabb::Aabb() | |
: m_bottomLeft{ 0, 0 } | |
, m_topRight{ 0, 0 } | |
{ | |
} | |
platformer::Aabb::Aabb( const Coordinate& bottomLeft, const Coordinate& topRight ) | |
: m_bottomLeft( bottomLeft ) | |
, m_topRight( topRight ) | |
{ | |
} | |
platformer::Aabb::Aabb( const TileCoordinate& bottomLeft, const TileCoordinate& topRight ) | |
: m_bottomLeft{ Coordinate::Type( bottomLeft.x * TILEWIDTH ), | |
Coordinate::Type( bottomLeft.y * TILEHEIGHT ) } | |
, m_topRight{ Coordinate::Type( ( topRight.x + 1 ) * TILEWIDTH ), | |
Coordinate::Type( ( topRight.y + 1 ) * TILEHEIGHT ) } | |
{ | |
} | |
bool | |
platformer::Aabb::intersectsWith( const Aabb& other) const | |
{ | |
return ! (m_bottomLeft.x >= other.m_topRight.x || | |
other.m_bottomLeft.x >= m_topRight.x || | |
m_bottomLeft.y >= other.m_topRight.y || | |
other.m_bottomLeft.y >= m_topRight.y ); | |
} | |
bool | |
platformer::Aabb::contains( const Coordinate& coordinate ) const | |
{ | |
return coordinate.x <= m_topRight.x | |
&& coordinate.x >= m_bottomLeft.x | |
&& coordinate.y >= m_bottomLeft.y | |
&& coordinate.y <= m_topRight.y; | |
} | |
const platformer::Coordinate& | |
platformer::Aabb::bottomLeft() const | |
{ | |
return m_bottomLeft; | |
} | |
const platformer::Coordinate& | |
platformer::Aabb::topRight() const | |
{ | |
return m_topRight; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <vector> | |
#include "BaseTypes.hpp" | |
namespace platformer | |
{ | |
/* | |
* Axis aligned bounding box with tile coordinates. | |
*/ | |
class Aabb | |
{ | |
public: | |
Aabb(); | |
Aabb( const TileCoordinate& bottomLeft, const TileCoordinate& topRight ); | |
Aabb( const Coordinate& bottomLeft, const Coordinate& topRight ); | |
bool intersectsWith( const Aabb& other) const; | |
bool contains( const Coordinate& coordinate ) const; | |
const Coordinate& bottomLeft() const; | |
const Coordinate& topRight() const; | |
private: | |
Coordinate m_bottomLeft; | |
Coordinate m_topRight; | |
}; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "BaseTypes.hpp" | |
bool | |
platformer::operator==( const TileCoordinate& l, | |
const TileCoordinate& r ) | |
{ | |
return l.x == r.x && | |
l.y == r.y; | |
} | |
const platformer::TileCoordinate | |
platformer::operator+=( TileCoordinate& l, const TileCoordinate& r ) | |
{ | |
l.x += r.x; | |
l.y += r.y; | |
return l; | |
} | |
const platformer::TileCoordinate | |
platformer::operator+( TileCoordinate l, const TileCoordinate& r ) | |
{ | |
return l+=r; | |
} | |
std::ostream& | |
platformer::operator<<( std::ostream& output, const TileCoordinate& coordinate ) | |
{ | |
output << "( " << coordinate.x << ", " << coordinate.y << " )"; | |
return output; | |
} | |
platformer::TileCoordinate | |
platformer::tileCoordinateOf( const Coordinate& coordinate ) | |
{ | |
return TileCoordinate{ | |
TileCoordinate::Type( coordinate.x / TILEWIDTH ), | |
TileCoordinate::Type( coordinate.y / TILEHEIGHT ) }; | |
} | |
const platformer::Coordinate | |
platformer::operator+=( Coordinate& l, const Coordinate& r ) | |
{ | |
l.x += r.x; | |
l.y += r.y; | |
return l; | |
} | |
const platformer::Coordinate | |
platformer::operator+( Coordinate l, const Coordinate& r ) | |
{ | |
return l+=r; | |
} | |
const platformer::Coordinate | |
platformer::operator-=( Coordinate& l, const Coordinate& r ) | |
{ | |
l.x -= r.x; | |
l.y -= r.y; | |
return l; | |
} | |
const platformer::Coordinate | |
platformer::operator-( Coordinate l, const Coordinate& r ) | |
{ | |
return l-=r; | |
} | |
std::ostream& | |
platformer::operator<<( std::ostream& output, const Coordinate& coordinate ) | |
{ | |
output << "( " << coordinate.x << ", " << coordinate.y << " )"; | |
return output; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <ostream> | |
namespace platformer | |
{ | |
static const int TILEWIDTH = 32; | |
static const int TILEHEIGHT = 32; | |
struct TileCoordinate | |
{ | |
typedef int Type; | |
Type x; | |
Type y; | |
}; | |
const TileCoordinate operator+=( TileCoordinate&, const TileCoordinate& ); | |
const TileCoordinate operator+( TileCoordinate, const TileCoordinate& ); | |
bool operator==( const TileCoordinate&, const TileCoordinate& ); | |
std::ostream& operator<<( std::ostream&, const TileCoordinate& ); | |
struct Coordinate | |
{ | |
typedef double Type; | |
Type x; | |
Type y; | |
}; | |
const Coordinate operator+=( Coordinate&, const Coordinate& ); | |
const Coordinate operator+( Coordinate, const Coordinate& ); | |
const Coordinate operator-=( Coordinate&, const Coordinate& ); | |
const Coordinate operator-( Coordinate, const Coordinate& ); | |
std::ostream& operator<<( std::ostream&, const Coordinate& ); | |
typedef Coordinate Velocity; | |
TileCoordinate tileCoordinateOf( const Coordinate& ); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <allegro5/allegro.h> | |
#include <stdlib.h> | |
#include <iostream> | |
#include <cmath> | |
#include <memory> | |
#include "Object.hpp" | |
#include "Updaters.hpp" | |
#include "ObjectContainer.hpp" | |
#include "Aabb.hpp" | |
#include "Graphics.hpp" | |
#include "World.hpp" | |
#include "WorldGenerator.hpp" | |
#include "PerlinNoise.hpp" | |
class Cricket : public platformer::Object | |
{ | |
public: | |
Cricket() = delete; | |
Cricket( platformer::View& graphics, const platformer::ObjectContainer& tiles ) | |
: platformer::Object( { { 50, 1750 }, { 0, 0 }, { 32, 32 } } ) | |
, m_cricketPhysics( new platformer::MoveAndCollide( this, m_data, tiles ) ) | |
, m_graphicsUpdater( new platformer::PlayerGraphics ( m_data, graphics ) ) | |
{ | |
platformer::Updater* gravity( new platformer::SpeedAddition( m_data, { 0, -0.3 } ) ); | |
registerUpdater( gravity ); | |
registerUpdater( new platformer::SpeedLimiter( m_data, { 5, 100 } ) ); | |
registerUpdater( m_cricketPhysics ); | |
registerUpdater( m_graphicsUpdater ); | |
} | |
virtual ~Cricket() noexcept ( true ) | |
{ | |
} | |
const platformer::Coordinate& center() const | |
{ | |
return m_data.coordinate; | |
} | |
void up() | |
{ | |
m_cricketPhysics->jump(); | |
} | |
void right() | |
{ | |
m_cricketPhysics->moveRight(); | |
m_graphicsUpdater->step(); | |
} | |
void left() | |
{ | |
m_cricketPhysics->moveLeft(); | |
m_graphicsUpdater->step(); | |
} | |
void fly() | |
{ | |
m_data.velocity.y += 1; | |
} | |
private: | |
platformer::MoveAndCollide* m_cricketPhysics; | |
platformer::PlayerGraphics* m_graphicsUpdater; | |
}; | |
class TerrainGenerator : public platformer::ObjectFactory | |
{ | |
public: | |
TerrainGenerator( platformer::ObjectFactory& objectFactory ) | |
: m_objectFactory( objectFactory ) | |
, m_perlinNoise( 0.4, 5 ) | |
{ | |
} | |
virtual platformer::Object::Ref buildTopTile( const platformer::TileCoordinate& coordinate ) | |
{ | |
return m_objectFactory.buildGroundTile( coordinate ); | |
} | |
virtual platformer::Object::Ref buildCaveTile( const platformer::TileCoordinate& coordinate ) | |
{ | |
return m_objectFactory.buildCaveTile( coordinate ); | |
} | |
virtual platformer::Object::Ref buildGroundTile( const platformer::TileCoordinate& coordinate ) | |
{ | |
const int currentGroundLevel( groundLevel( coordinate ) ); | |
if ( currentGroundLevel < coordinate.y ) | |
{ | |
return platformer::Object::Ref( nullptr ); | |
} | |
if ( currentGroundLevel == coordinate.y ) | |
{ | |
return m_objectFactory.buildTopTile( coordinate ); | |
} | |
if ( !isRock( coordinate ) ) | |
{ | |
return m_objectFactory.buildCaveTile( coordinate ); | |
} | |
return m_objectFactory.buildGroundTile( coordinate ); | |
} | |
private: | |
int groundLevel( const platformer::TileCoordinate& coordinate ) const | |
{ | |
int y( m_perlinNoise.noiseFor( double( coordinate.x ) / 20 ) * 20 ); | |
while ( !isRock( platformer::TileCoordinate{ coordinate.x, y-- } ) ) {} | |
return y; | |
} | |
bool isRock( const platformer::TileCoordinate& coordinate ) const | |
{ | |
const double CAVETHRESHOLD( -20 ); | |
return m_perlinNoise.noiseFor( double( coordinate.y ) / 20, double( coordinate.x ) / 20 ) * 100 > CAVETHRESHOLD; | |
} | |
platformer::ObjectFactory& m_objectFactory; | |
platformer::PerlinNoise m_perlinNoise; | |
}; | |
int main() | |
{ | |
const int x( 640 ); | |
const int y( 480 ); | |
platformer::Graphics graphics( x, y ); | |
platformer::Image backGround( "/home/tacsko/bg.png" ); | |
platformer::View view( graphics, { x, y }, backGround ); | |
al_install_keyboard(); | |
platformer::ObjectContainer objects( { platformer::TileCoordinate{ -10000, -10000 }, | |
platformer::TileCoordinate{ 10000, 10000 } } ); | |
platformer::GraphicalObjectFactory factory( view ); | |
TerrainGenerator terrainFactory( factory ); | |
platformer::WorldGenerator worldGenerator( objects, terrainFactory ); | |
Cricket* cricket( new Cricket( view, objects ) ); | |
objects.insert( platformer::Object::Ref( cricket ) ); | |
bool shouldQuit( false ); | |
while ( !shouldQuit ) | |
{ | |
ALLEGRO_KEYBOARD_STATE keyState; | |
al_get_keyboard_state(&keyState); | |
if( al_key_down(&keyState, ALLEGRO_KEY_UP) ) | |
{ | |
cricket->up(); | |
} | |
if( al_key_down(&keyState, ALLEGRO_KEY_RIGHT) ) | |
{ | |
cricket->right(); | |
} | |
if( al_key_down(&keyState, ALLEGRO_KEY_LEFT) ) | |
{ | |
cricket->left(); | |
} | |
if( al_key_down(&keyState, ALLEGRO_KEY_Q) ) | |
{ | |
shouldQuit = true; | |
} | |
if( al_key_down(&keyState, ALLEGRO_KEY_F) ) | |
{ | |
cricket->fly(); | |
} | |
view.clear(); | |
view.focus( cricket->center() ); | |
std::vector< platformer::Object* > objectsInScreen; | |
platformer::Aabb visibleArea( view.visibleArea() ); | |
worldGenerator.generate( visibleArea ); | |
objects.collectIn( visibleArea, std::back_inserter( objectsInScreen ) ); | |
std::for_each( begin( objectsInScreen ), end( objectsInScreen ), | |
[]( platformer::Object* object ) | |
{ | |
object->update(); | |
} ); | |
graphics.printfps(); | |
graphics.printCoordinate( cricket->center() ); | |
view.show(); | |
} | |
return 0; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "Object.hpp" | |
namespace platformer | |
{ | |
namespace test | |
{ | |
class DummyObject : public platformer::Object | |
{ | |
public: | |
DummyObject() | |
: Object( { { 0.0, 0.0 }, { 0.0, 0.0 }, { platformer::TILEWIDTH + 1, platformer::TILEHEIGHT + 1 } } ) | |
, updateTimes( 0 ) | |
{ | |
} | |
DummyObject( const platformer::ObjectData& objectData ) | |
: Object( objectData ) | |
, updateTimes( 0 ) | |
{ | |
} | |
unsigned int updateTimes; | |
}; | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Graphics.hpp" | |
#include "BaseTypes.hpp" | |
#include "Object.hpp" | |
#include "Aabb.hpp" | |
#include <allegro5/allegro.h> | |
#include <allegro5/allegro_primitives.h> | |
#include <allegro5/allegro_image.h> | |
#include <allegro5/allegro_font.h> | |
#include <sstream> | |
#include <algorithm> | |
platformer::Image::Image( const char* fileName ) | |
: m_image( al_load_bitmap( fileName ) ) | |
{ | |
} | |
void | |
platformer::Image::draw( unsigned int x, unsigned int y ) | |
{ | |
al_draw_bitmap( m_image, x, y, 0 ); | |
} | |
unsigned int | |
platformer::Image::height() const | |
{ | |
return al_get_bitmap_height( m_image ); | |
} | |
unsigned int | |
platformer::Image::width() const | |
{ | |
return al_get_bitmap_width( m_image ); | |
} | |
platformer::Image::~Image() | |
{ | |
al_destroy_bitmap( m_image ); | |
} | |
platformer::Graphics::Graphics( size_t x, size_t y ) | |
: m_display( nullptr ) | |
, m_width( x ) | |
, m_height( y ) | |
, m_font( 0 ) | |
, m_previousRefreshTime() | |
{ | |
al_init(); | |
al_init_primitives_addon(); | |
al_init_image_addon(); | |
al_init_font_addon(); | |
m_display = al_create_display( m_width, m_height ); | |
assert( m_display ); | |
m_font = al_create_builtin_font(); | |
assert( m_font ); | |
m_previousRefreshTime = al_get_time(); | |
} | |
void | |
platformer::Graphics::printText( int x, int y, const char* text ) | |
{ | |
al_draw_text( m_font, al_map_rgb(255,255,255), x, y,ALLEGRO_ALIGN_LEFT, text ); | |
} | |
void | |
platformer::Graphics::printfps() | |
{ | |
const double newTime( al_get_time() ); | |
std::stringstream fps; | |
fps << ( 1 / ( ( newTime - m_previousRefreshTime ) * 1000 ) ); | |
m_previousRefreshTime = newTime; | |
printText( 100, 10, fps.str().c_str() ); | |
} | |
void | |
platformer::Graphics::printCoordinate( const Coordinate& coordinate ) | |
{ | |
std::stringstream coord; | |
coord<< "( " << coordinate.x << ", " << coordinate.y << " )"; | |
printText( 100, 30, coord.str().c_str() ); | |
} | |
void | |
platformer::Graphics::clear() | |
{ | |
al_clear_to_color( al_map_rgb( 0, 0, 0 ) ); | |
} | |
void | |
platformer::Graphics::show() | |
{ | |
al_flip_display(); | |
} | |
platformer::Graphics::~Graphics() | |
{ | |
al_destroy_display( m_display ); | |
} | |
platformer::View::View( Graphics& graphics, const Coordinate& border, Drawable& backGround ) | |
: m_graphics( graphics ) | |
, m_borders( border ) | |
, m_focus{ border.x / 2, border.y / 2 } | |
, m_bg( backGround ) | |
, m_ground( "/home/tacsko/ground.png" ) | |
, m_cave( "/home/tacsko/cave.png" ) | |
, m_topGround( "/home/tacsko/tile.png" ) | |
, m_drawOperations() | |
{ | |
} | |
void | |
platformer::View::clear() | |
{ | |
m_graphics.clear(); | |
m_bg.draw( 0, 0 ); | |
} | |
void | |
platformer::View::show() | |
{ | |
std::for_each( begin( m_drawOperations ), end( m_drawOperations ), | |
[] ( DrawOperationContainer::value_type& operation ) | |
{ | |
std::for_each( begin( operation.second ), end( operation.second ), | |
[] ( DrawOperation& operation ) | |
{ | |
operation.drawable.draw( operation.x, operation.y ); | |
} ); | |
} ); | |
m_drawOperations.clear(); | |
m_graphics.show(); | |
} | |
void | |
platformer::View::draw( const Coordinate& coordinate, Drawable& drawable, Layer layer ) | |
{ | |
const Coordinate topLeft( translate( coordinate ) ); | |
m_drawOperations[ layer ].push_back( | |
DrawOperation{ drawable, int( topLeft.x ), int( topLeft.y ) } ); | |
} | |
void | |
platformer::View::focus( const Coordinate& focus ) | |
{ | |
m_focus = focus; | |
} | |
platformer::Aabb | |
platformer::View::visibleArea() const | |
{ | |
const Coordinate half{ m_borders.x / 2, m_borders.y / 2 }; | |
return Aabb( | |
Coordinate( m_focus - half ), | |
Coordinate( m_focus + half ) ); | |
} | |
platformer::Coordinate | |
platformer::View::translate( const Coordinate& coordinate ) | |
{ | |
return Coordinate{ | |
coordinate.x - m_focus.x + m_borders.x / 2, | |
m_borders.y * 2/3 - ( coordinate.y - m_focus.y ) }; | |
} | |
platformer::Image& | |
platformer::View::groundImage() | |
{ | |
return m_ground; | |
} | |
platformer::Image& | |
platformer::View::caveImage() | |
{ | |
return m_cave; | |
} | |
platformer::Image& | |
platformer::View::groundTopImage() | |
{ | |
return m_topGround; | |
} | |
platformer::PlayerSprite::PlayerSprite( const ObjectData& data ) | |
: m_image() | |
, m_data( data ) | |
{ | |
m_image.push_back( Image::Ref( new Image( "/home/tacsko/l0.png" ) ) ); | |
m_image.push_back( Image::Ref( new Image( "/home/tacsko/l1.png" ) ) ); | |
m_image.push_back( Image::Ref( new Image( "/home/tacsko/l2.png" ) ) ); | |
m_image.push_back( Image::Ref( new Image( "/home/tacsko/r0.png" ) ) ); | |
m_image.push_back( Image::Ref( new Image( "/home/tacsko/r1.png" ) ) ); | |
m_image.push_back( Image::Ref( new Image( "/home/tacsko/r2.png" ) ) ); | |
} | |
void | |
platformer::PlayerSprite::draw( unsigned int x, unsigned int y ) | |
{ | |
size_t start( m_data.velocity.x > 0 ? 3 : 0 ); | |
start += ( m_i / 3 ) % 3; | |
m_image[ start ]->draw( x, y ); | |
} | |
void | |
platformer::PlayerSprite::step() | |
{ | |
++m_i; | |
} | |
platformer::GraphicalTile::GraphicalTile( View& graphics, const TileCoordinate& coordinate, Image& image, const Layer layer ) | |
: Tile( coordinate, layer ) | |
{ | |
registerUpdater( new TileGraphics( m_data, image, graphics ) ); | |
} | |
platformer::TileGraphics::TileGraphics( ObjectData& objectData, Image& image, View& graphics ) | |
: Updater() | |
, m_image( image ) | |
, m_graphics( graphics ) | |
, m_topLeftCorner( objectData.coordinate + Coordinate{ 0.0, TILEHEIGHT } ) | |
, m_layer( objectData.layer ) | |
{ | |
} | |
void | |
platformer::TileGraphics::update() | |
{ | |
m_graphics.draw( m_topLeftCorner, m_image, m_layer ); | |
} | |
platformer::PlayerGraphics::PlayerGraphics( ObjectData& objectData, View& graphics ) | |
: Updater() | |
, m_data( objectData ) | |
, m_graphics( graphics ) | |
, m_player( objectData ) | |
, m_topLeftDelta{ 0, m_data.size.y } | |
{ | |
} | |
void | |
platformer::PlayerGraphics::step() | |
{ | |
m_player.step(); | |
} | |
void | |
platformer::PlayerGraphics::update() | |
{ | |
m_graphics.draw( m_data.coordinate + m_topLeftDelta, m_player ); | |
} | |
platformer::GraphicalObjectFactory::GraphicalObjectFactory( View& view ) | |
: ObjectFactory() | |
, m_view( view ) | |
{ | |
} | |
platformer::Object::Ref | |
platformer::GraphicalObjectFactory::buildTopTile( const TileCoordinate& coordinate ) | |
{ | |
return Object::Ref( new GraphicalTile( m_view, coordinate, m_view.groundTopImage() ) ); | |
} | |
platformer::Object::Ref | |
platformer::GraphicalObjectFactory::buildGroundTile( const TileCoordinate& coordinate ) | |
{ | |
return Object::Ref( new GraphicalTile( m_view, coordinate, m_view.groundImage() ) ); | |
} | |
platformer::Object::Ref | |
platformer::GraphicalObjectFactory::buildCaveTile( const TileCoordinate& coordinate ) | |
{ | |
return Object::Ref( new GraphicalTile( m_view, coordinate, m_view.caveImage(), -1 ) ); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <memory> | |
#include <map> | |
#include <vector> | |
#include "BaseTypes.hpp" | |
#include "Object.hpp" | |
#include "ObjectFactory.hpp" | |
class ALLEGRO_BITMAP; | |
class ALLEGRO_DISPLAY; | |
class ALLEGRO_FONT; | |
namespace platformer | |
{ | |
class Aabb; | |
class Drawable | |
{ | |
public: | |
virtual void draw( unsigned int x, unsigned int y ) = 0; | |
}; | |
class Image : public Drawable | |
{ | |
public: | |
typedef std::unique_ptr< Image > Ref; | |
Image( const char* fileName ); | |
~Image(); | |
void draw( unsigned int x, unsigned int y ); | |
unsigned int height() const; | |
unsigned int width() const; | |
private: | |
ALLEGRO_BITMAP* m_image; | |
}; | |
class Graphics | |
{ | |
public: | |
Graphics( size_t x, size_t y ); | |
~Graphics(); | |
void printText( int x, int y, const char* text ); | |
void printfps(); | |
void printCoordinate( const Coordinate& coordinate ); | |
void clear(); | |
void show(); | |
private: | |
ALLEGRO_DISPLAY *m_display; | |
size_t m_width; | |
size_t m_height; | |
ALLEGRO_FONT* m_font; | |
double m_previousRefreshTime; | |
}; | |
struct DrawOperation | |
{ | |
Drawable& drawable; | |
int x; | |
int y; | |
}; | |
class View | |
{ | |
public: | |
View( Graphics& graphics, const Coordinate& border, Drawable& backGround ); | |
void clear(); | |
void draw( const Coordinate& coordinate, Drawable& stuff, Layer layer = DEFAULT_LAYER ); | |
void focus( const Coordinate& focus ); | |
void show(); | |
Aabb visibleArea() const; | |
Image& groundImage(); | |
Image& groundTopImage(); | |
Image& caveImage(); | |
private: | |
Coordinate translate( const Coordinate& coordinate ); | |
Graphics& m_graphics; | |
Coordinate m_borders; | |
Coordinate m_focus; | |
Drawable& m_bg; | |
Image m_ground; | |
Image m_cave; | |
Image m_topGround; | |
typedef std::map< Layer, std::vector< DrawOperation > > DrawOperationContainer; | |
DrawOperationContainer m_drawOperations; | |
}; | |
class PlayerSprite : public Drawable | |
{ | |
public: | |
PlayerSprite( const ObjectData& data ); | |
void draw( unsigned int x, unsigned int y ); | |
void step(); | |
private: | |
unsigned int m_i{ 0 }; | |
std::vector< Image::Ref > m_image; | |
const ObjectData& m_data; | |
}; | |
class GraphicalTile : public Tile | |
{ | |
public: | |
GraphicalTile( View& graphics, const TileCoordinate& coordinate, Image& image, const Layer layer = DEFAULT_LAYER ); | |
}; | |
class TileGraphics : public Updater | |
{ | |
public: | |
TileGraphics( ObjectData& objectData, Image& image, View& graphics ); | |
virtual void update(); | |
private: | |
Image& m_image; | |
View& m_graphics; | |
const Coordinate m_topLeftCorner; | |
const Layer m_layer; | |
}; | |
class PlayerGraphics : public Updater | |
{ | |
public: | |
PlayerGraphics( ObjectData& objectData, View& graphics ); | |
void step(); | |
virtual void update(); | |
private: | |
ObjectData& m_data; | |
View& m_graphics; | |
PlayerSprite m_player; | |
const Coordinate m_topLeftDelta; | |
}; | |
class GraphicalObjectFactory : public ObjectFactory | |
{ | |
public: | |
GraphicalObjectFactory( View& ); | |
virtual Object::Ref buildTopTile( const TileCoordinate& ); | |
virtual Object::Ref buildGroundTile( const TileCoordinate& ); | |
virtual Object::Ref buildCaveTile( const TileCoordinate& ); | |
private: | |
View& m_view; | |
}; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SRC=BaseTypes.cpp Object.cpp Aabb.cpp Updaters.cpp World.cpp PerlinNoise.cpp WorldGenerator.cpp | |
TEST_SRC=$(SRC) test_platformer.cpp | |
DEMO_SRC=$(SRC) demo.cpp Graphics.cpp | |
CFLAGS=-std=c++11 -Wall -pedantic -Werror -Wextra -std=c++11 | |
default: demo | |
demo: $(DEMO_SRC) | |
g++ $(CFLAGS) $(DEMO_SRC) -o demo -l allegro -l allegro_primitives -l allegro_image -l allegro_font -O3 -pg | |
test: testFile runTest | |
testFile: $(TEST_SRC) | |
g++ $(CFLAGS) $(TEST_SRC) -ggdb -o testFile | |
runTest: testFile | |
valgrind ./testFile | |
clean: | |
rm -rf *.o demo test a.out | |
.PHONY: clean | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Object.hpp" | |
#include <algorithm> | |
platformer::ObjectData::ObjectData( | |
const Coordinate& coordinate, | |
const Velocity& velocity, | |
const Coordinate& size ) | |
: coordinate( coordinate ) | |
, velocity( velocity ) | |
, size( size ) | |
, layer( DEFAULT_LAYER ) | |
{ | |
} | |
platformer::ObjectData::ObjectData( | |
const Coordinate& coordinate, | |
const Velocity& velocity, | |
const Coordinate& size, | |
const Layer layer ) | |
: coordinate( coordinate ) | |
, velocity( velocity ) | |
, size( size ) | |
, layer( layer ) | |
{ | |
} | |
platformer::Object::Object( const ObjectData& data ) | |
: m_data( data ) | |
{ | |
} | |
namespace | |
{ | |
platformer::Aabb | |
objectAabb( const platformer::ObjectData& objectData ) | |
{ | |
return platformer::Aabb( objectData.coordinate, objectData.coordinate + objectData.size ); | |
} | |
} | |
bool | |
platformer::Object::intersectsWith( const Aabb& aabb ) const | |
{ | |
return objectAabb( m_data ).intersectsWith( aabb ); | |
} | |
bool | |
platformer::Object::contains( const Coordinate& coordinate ) const | |
{ | |
return objectAabb( m_data ).contains( coordinate ); | |
} | |
bool | |
platformer::Object::isOnLayer( const Layer layer ) const | |
{ | |
return m_data.layer == layer; | |
} | |
void | |
platformer::Object::registerUpdater( Updater* updater ) | |
{ | |
m_updaters.push_back( Updater::Ref( updater ) ); | |
} | |
void | |
platformer::Object::update() | |
{ | |
std::for_each( begin( m_updaters ), end( m_updaters ), std::mem_fn( &Updater::update ) ); | |
} | |
platformer::Tile::Tile( const TileCoordinate& coordinate ) | |
: Object( | |
{ Coordinate{ coordinate.x * TILEWIDTH * 1.0, coordinate.y * TILEHEIGHT * 1.0 }, | |
Velocity{ 0.0, 0.0 }, | |
Coordinate{ TILEWIDTH, TILEHEIGHT } } ) | |
{ | |
} | |
platformer::Tile::Tile( const TileCoordinate& coordinate, const Layer layer ) | |
: Object( | |
{ Coordinate{ coordinate.x * TILEWIDTH * 1.0, coordinate.y * TILEHEIGHT * 1.0 }, | |
Velocity{ 0.0, 0.0 }, | |
Coordinate{ TILEWIDTH, TILEHEIGHT }, | |
layer } ) | |
{ | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <memory> | |
#include "BaseTypes.hpp" | |
#include "Aabb.hpp" | |
#include "Updater.hpp" | |
namespace platformer | |
{ | |
typedef int Layer; | |
const Layer DEFAULT_LAYER = 0; | |
struct ObjectData | |
{ | |
ObjectData( const Coordinate&, const Velocity&, const Coordinate& ); | |
ObjectData( const Coordinate&, const Velocity&, const Coordinate&, const Layer ); | |
Coordinate coordinate; | |
Velocity velocity; | |
Coordinate size; | |
Layer layer; | |
}; | |
class Object | |
{ | |
public: | |
typedef std::unique_ptr< Object > Ref; | |
Object( const ObjectData& ); | |
virtual void update(); | |
bool intersectsWith( const Aabb& aabb ) const; | |
bool contains( const Coordinate& coordinate ) const; | |
void registerUpdater( Updater* updater ); | |
bool isOnLayer( const Layer layer ) const; | |
protected: | |
ObjectData m_data; | |
private: | |
Updater::Container m_updaters; | |
}; | |
class Tile : public Object | |
{ | |
public: | |
Tile( const TileCoordinate& ); | |
Tile( const TileCoordinate&, const Layer ); | |
}; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <algorithm> | |
#include "Aabb.hpp" | |
#include "Object.hpp" | |
namespace platformer | |
{ | |
class ObjectContainer | |
{ | |
public: | |
ObjectContainer( const Aabb& aabb ) | |
: m_aabb( aabb ) | |
{ | |
} | |
void insert( Object::Ref object ) | |
{ | |
if ( !object || | |
!object->intersectsWith( m_aabb ) ) | |
{ | |
return; | |
} | |
m_objects.push_back( object.get() ); | |
m_owningContainer.push_back( std::move( object ) ); | |
} | |
template < class OutputIterator > | |
void collectIn( const Aabb& aabb, OutputIterator output ) const | |
{ | |
if ( !aabb.intersectsWith( m_aabb ) ) | |
{ | |
return; | |
} | |
std::copy_if( begin( m_objects ), end( m_objects ), | |
output, IntersectsWith( aabb ) ); | |
} | |
private: | |
struct IntersectsWith | |
{ | |
IntersectsWith( const Aabb& aabb ) | |
: m_aabb( aabb ) | |
{ | |
} | |
bool operator()( Object* object ) const | |
{ | |
return object->intersectsWith( m_aabb ); | |
} | |
Aabb m_aabb; | |
}; | |
Aabb m_aabb; | |
std::vector< Object* > m_objects; | |
std::vector< Object::Ref > m_owningContainer; | |
}; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "Object.hpp" | |
namespace platformer | |
{ | |
class TileCoordinate; | |
class ObjectFactory | |
{ | |
public: | |
virtual Object::Ref buildTopTile( const TileCoordinate& ) = 0; | |
virtual Object::Ref buildGroundTile( const TileCoordinate& ) = 0; | |
virtual Object::Ref buildCaveTile( const TileCoordinate& ) = 0; | |
}; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "PerlinNoise.hpp" | |
#include <cmath> | |
#include <iostream> | |
namespace | |
{ | |
double | |
pseudoNoise( int x ) | |
{ | |
x = (x << 13) ^ x; | |
return ( 1.0 - ( (x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0); | |
} | |
double | |
pseudoNoise2d( int x, int y ) | |
{ | |
int n( x + y * 57 ); | |
n = ( n <<13 ) ^ n; | |
int nn( (n*(n*n*60493+19990303)+1376312589)&0x7fffffff ); | |
return 1.0 - ( (double) nn / 1073741824.0 ); | |
} | |
double | |
smoothNoise( double x ) | |
{ | |
return pseudoNoise( x )*0.5 + ( pseudoNoise( x - 1 ) + pseudoNoise( x + 1 ) )*0.25; | |
} | |
double | |
cosineInterpolation( double a, double b, double x ) | |
{ | |
double ft( x * M_PI ); | |
double f( (1 - cos( ft )) * 0.5 ); | |
return a * (1 - f) + b * f; | |
} | |
double | |
interpolatedNoise( double x ) | |
{ | |
int intx( floor( x ) ); | |
double FraqX( x - intx ); | |
double v1( smoothNoise( intx ) ); | |
double v2( smoothNoise( intx + 1 ) ); | |
return cosineInterpolation( v1, v2, FraqX ); | |
} | |
double | |
interpolatedNoise( double x, double y ) | |
{ | |
double floorx( floor( x ) ); | |
double floory( floor( y ) ); | |
double s ( pseudoNoise2d( floorx, floory ) ); | |
double t ( pseudoNoise2d( floorx + 1, floory ) ); | |
double u ( pseudoNoise2d( floorx, floory + 1 ) ); | |
double v ( pseudoNoise2d( floorx + 1, floory + 1 ) ); | |
double int1( cosineInterpolation( s, t, x-floorx ) ); | |
double int2( cosineInterpolation( u, v, x-floorx ) ); | |
return cosineInterpolation( int1, int2, y-floory ); | |
} | |
} | |
platformer::PerlinNoise::PerlinNoise( double persistance, int octaveNumber ) | |
: m_persistance( persistance ) | |
, m_octaveNumber( octaveNumber ) | |
{ | |
} | |
double | |
platformer::PerlinNoise::noiseFor( double x ) const | |
{ | |
double sum( 0.0 ); | |
for( unsigned int i = 0; i < m_octaveNumber; ++i ) | |
{ | |
int frequency( 1<<i ); | |
double amplitude( pow( m_persistance, i ) ); | |
sum += interpolatedNoise( x * frequency ) * amplitude; | |
} | |
return sum; | |
} | |
double | |
platformer::PerlinNoise::noiseFor( double x, double y ) const | |
{ | |
double sum( 0.0 ); | |
for( unsigned int i = 0; i < m_octaveNumber; ++i ) | |
{ | |
int frequency( 1<<i ); | |
double amplitude( pow( m_persistance, i ) ); | |
sum += interpolatedNoise( x * frequency, y * frequency ) * amplitude; | |
} | |
return sum; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
namespace platformer | |
{ | |
class PerlinNoise | |
{ | |
public: | |
PerlinNoise( double persistance, int octaveNumber ); | |
double noiseFor( double x ) const; | |
double noiseFor( double x, double y ) const; | |
private: | |
double InterpolatedNoise( double x ) const; | |
double m_persistance; | |
unsigned int m_octaveNumber; | |
}; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "Aabb.hpp" | |
Describe( axis_aligned_bounding_box ) | |
{ | |
It ( should_intersect_with_the_same_aabb ) | |
{ | |
platformer::Aabb sameAabb( platformer::TileCoordinate{ 0,0 }, platformer::TileCoordinate{ 10, 11 } ); | |
AssertThat( aabb.intersectsWith( sameAabb ), | |
Equals( true ) ); | |
AssertThat( sameAabb.intersectsWith( aabb ), | |
Equals( true ) ); | |
} | |
It ( should_intersect_with_aabb_with_one_common_corner ) | |
{ | |
platformer::Aabb bottomLeft( platformer::TileCoordinate{ -10, -11 }, platformer::TileCoordinate{ 0, 0 } ); | |
AssertThat( aabb.intersectsWith( bottomLeft ), | |
Equals( true ) ); | |
AssertThat( bottomLeft.intersectsWith( aabb ), | |
Equals( true ) ); | |
platformer::Aabb topLeft( platformer::TileCoordinate{ -10, 11 }, platformer::TileCoordinate{ 0, 21 } ); | |
AssertThat( aabb.intersectsWith( topLeft ), | |
Equals( true ) ); | |
AssertThat( topLeft.intersectsWith( aabb ), | |
Equals( true ) ); | |
} | |
It ( should_not_intersect_with_not_intersecting_aabbs ) | |
{ | |
platformer::Aabb neighbour( platformer::TileCoordinate{ 11,10 }, platformer::TileCoordinate{ 12, 11 } ); | |
AssertThat( aabb.intersectsWith( neighbour ), | |
Equals( false ) ); | |
AssertThat( neighbour.intersectsWith( aabb ), | |
Equals( false ) ); | |
} | |
It ( should_be_able_to_detect_if_it_contains_a_coordinate ) | |
{ | |
AssertThat( aabb.contains( platformer::Coordinate{ 0.0, 0.0 } ), Equals( true ) ); | |
AssertThat( aabb.contains( platformer::Coordinate{ 352.0, 0.0 } ), Equals( true ) ); | |
AssertThat( aabb.contains( platformer::Coordinate{ -0.1, 0.0 } ), Equals( false ) ); | |
AssertThat( aabb.contains( platformer::Coordinate{ 352.1, 0.0 } ), Equals( false ) ); | |
AssertThat( aabb.contains( platformer::Coordinate{ 0.0, 384.0 } ), Equals( true ) ); | |
AssertThat( aabb.contains( platformer::Coordinate{ 0.0, 384.1 } ), Equals( false ) ); | |
AssertThat( aabb.contains( platformer::Coordinate{ 0.0, -0.1 } ), Equals( false ) ); | |
} | |
platformer::Aabb aabb{ platformer::TileCoordinate{ 0, 0 }, platformer::TileCoordinate{ 10, 11 } }; | |
}; | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "BaseTypes.hpp" | |
Describe( tile_coordinates ) | |
{ | |
It( should_be_comparable ) | |
{ | |
platformer::TileCoordinate location{ 0, 0 }; | |
AssertThat( location, Equals( platformer::TileCoordinate{ 0, 0 } ) ); | |
AssertThat( location, Is().Not().EqualTo( platformer::TileCoordinate{ 1, 0 } ) ); | |
} | |
It( should_have_operator_plusassignment ) | |
{ | |
platformer::TileCoordinate first{ 0, 0 }; | |
first += { 1, 1 }; | |
AssertThat( first, Equals( platformer::TileCoordinate{ 1, 1 } ) ); | |
} | |
}; | |
Describe( coordinates ) | |
{ | |
It( should_be_convertable_to_tile_coordinates ) | |
{ | |
AssertThat( | |
tileCoordinateOf( platformer::Coordinate{ platformer::TILEWIDTH, 0.0 } ), | |
Equals( platformer::TileCoordinate{ 1, 0 } ) ); | |
AssertThat( | |
tileCoordinateOf( platformer::Coordinate{ platformer::TILEWIDTH, platformer::TILEHEIGHT } ), | |
Equals( platformer::TileCoordinate{ 1, 1 } ) ); | |
} | |
It( should_have_operator_plusassignment ) | |
{ | |
platformer::Coordinate first{ 0.0, 0.0 }; | |
first += { 1.0, 1.0 }; | |
AssertThat( first.x, EqualsWithDelta( 1.0, 0.00001 ) ); | |
AssertThat( first.y, EqualsWithDelta( 1.0, 0.00001 ) ); | |
} | |
}; | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "Object.hpp" | |
#include "DummyObject.hpp" | |
Describe( object ) | |
{ | |
class DummyUpdater : public platformer::Updater | |
{ | |
public: | |
DummyUpdater( platformer::test::DummyObject& object ) | |
: m_object( object ) | |
{ | |
} | |
virtual void update() | |
{ | |
++m_object.updateTimes; | |
} | |
private: | |
platformer::test::DummyObject& m_object; | |
}; | |
It ( should_call_each_updater_if_the_object_is_asked_to_update_itself ) | |
{ | |
std::unique_ptr< platformer::test::DummyObject > dummy( new platformer::test::DummyObject ); | |
dummy->registerUpdater( new DummyUpdater( *dummy.get() ) ); | |
dummy->registerUpdater( new DummyUpdater( *dummy.get() ) ); | |
dummy->update(); | |
AssertThat( dummy->updateTimes, Equals( 2 ) ); | |
} | |
It ( should_detect_intersecting_aabb ) | |
{ | |
platformer::test::DummyObject dummy; | |
AssertThat( dummy.intersectsWith( { platformer::TileCoordinate{ 0, 0 }, platformer::TileCoordinate{ 0, 0 } } ), Equals( true ) ); | |
AssertThat( dummy.intersectsWith( { platformer::TileCoordinate{ 0, 1 }, platformer::TileCoordinate{ 0, 1 } } ), Equals( true ) ); | |
AssertThat( dummy.intersectsWith( { platformer::TileCoordinate{ 1, 0 }, platformer::TileCoordinate{ 1, 0 } } ), Equals( true ) ); | |
AssertThat( dummy.intersectsWith( { platformer::TileCoordinate{ 1, 1 }, platformer::TileCoordinate{ 1, 1 } } ), Equals( true ) ); | |
AssertThat( dummy.intersectsWith( { platformer::TileCoordinate{ -1, -1 }, platformer::TileCoordinate{ -1, -1 } } ), Equals( false ) ); | |
} | |
}; | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <igloo/igloo_alt.h> | |
#include "ObjectContainer.hpp" | |
#include "Aabb.hpp" | |
Describe( object_container ) | |
{ | |
typedef platformer::Aabb AabbType; | |
typedef platformer::Tile ObjectType; | |
typedef std::vector< platformer::Object* > ObjectVector; | |
void SetUp() | |
{ | |
objects.reset( new platformer::ObjectContainer( aabb ) ); | |
} | |
It( should_be_able_to_store_and_find_objects_in_subaabbs ) | |
{ | |
ObjectType* object( new ObjectType( { 10, 10 } ) ); | |
ObjectType* object2( new ObjectType( { 19, 19 } ) ); | |
objects->insert( std::unique_ptr<platformer::Object>( object ) ); | |
objects->insert( std::unique_ptr<platformer::Object>( object2 ) ); | |
ObjectVector collectedObjects; | |
objects->collectIn( AabbType{ platformer::TileCoordinate{ 5, 5 }, platformer::TileCoordinate{ 5, 5 } }, | |
std::back_inserter< ObjectVector >( collectedObjects ) ); | |
AssertThat( collectedObjects, IsEmpty() ); | |
objects->collectIn( AabbType{ platformer::TileCoordinate{ 10, 10 }, platformer::TileCoordinate{ 19, 19 } }, | |
std::back_inserter< ObjectVector >( collectedObjects) ); | |
AssertThat( collectedObjects, HasLength( 2 ) ); | |
AssertThat( collectedObjects, Contains( object ) ); | |
AssertThat( collectedObjects, Contains( object2 ) ); | |
} | |
It( should_not_store_objects_outside_the_aabb_of_the_objects ) | |
{ | |
ObjectType* object( new ObjectType( { 101, 101 } ) ); | |
objects->insert( std::unique_ptr<platformer::Object>( object ) ); | |
ObjectVector collectedObjects; | |
objects->collectIn( AabbType{ platformer::TileCoordinate{ 0, 0 }, platformer::TileCoordinate{ 110, 110 } }, | |
std::back_inserter< ObjectVector >( collectedObjects) ); | |
AssertThat( collectedObjects, Is().Not().Containing( object ) ); | |
} | |
It( should_handle_nullptr ) | |
{ | |
objects->insert( std::unique_ptr<platformer::Object>( nullptr ) ); | |
} | |
AabbType aabb{ platformer::TileCoordinate{ 0, 0 }, platformer::TileCoordinate{ 100, 100 } }; | |
std::unique_ptr< platformer::ObjectContainer > objects; | |
}; | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <igloo/igloo_alt.h> | |
using namespace igloo; | |
#include "test_world_generator.hpp" | |
#include "test_coordinate.hpp" | |
#include "test_object.hpp" | |
#include "test_tile.hpp" | |
#include "test_aabb.hpp" | |
#include "test_object_container.hpp" | |
#include "test_updaters.hpp" | |
int main() | |
{ | |
return TestRunner::RunAllTests(); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "Object.hpp" | |
Describe( tile ) | |
{ | |
It ( should_detect_intersecting_aabb ) | |
{ | |
platformer::Tile tile( { 0, 0 } ); | |
AssertThat( tile.intersectsWith( { platformer::TileCoordinate{ 0, 0 }, platformer::TileCoordinate{ 0, 0 } } ), Equals( true ) ); | |
AssertThat( tile.intersectsWith( { platformer::TileCoordinate{ 0, 1 }, platformer::TileCoordinate{ 0, 1 } } ), Equals( false ) ); | |
AssertThat( tile.intersectsWith( { platformer::TileCoordinate{ 0, -1 }, platformer::TileCoordinate{ 0, -1 } } ), Equals( false ) ); | |
AssertThat( tile.intersectsWith( { platformer::TileCoordinate{ 1, 0 }, platformer::TileCoordinate{ 1, 0 } } ), Equals( false ) ); | |
AssertThat( tile.intersectsWith( { platformer::TileCoordinate{ -1, 0 }, platformer::TileCoordinate{ -1, 0 } } ), Equals( false ) ); | |
} | |
}; | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "Object.hpp" | |
#include "DummyObject.hpp" | |
#include "Updaters.hpp" | |
#include "ObjectContainer.hpp" | |
Describe( speed_limiter ) | |
{ | |
It ( should_not_allow_to_increase_the_object_speed_over_a_defined_limit ) | |
{ | |
platformer::ObjectData objectDataWithPositiveVelocity{ { 0, 0 }, { 10, 10 }, { 10, 10 } }; | |
platformer::SpeedLimiter limiter( objectDataWithPositiveVelocity, { 5, 5 } ); | |
limiter.update(); | |
AssertThat( objectDataWithPositiveVelocity.velocity.x, EqualsWithDelta( 5, 0.00001 ) ); | |
AssertThat( objectDataWithPositiveVelocity.velocity.y, EqualsWithDelta( 5, 0.00001 ) ); | |
} | |
It ( should_not_allow_to_increase_the_abs_of_object_speed_over_a_defined_limit ) | |
{ | |
platformer::ObjectData objectDataWithPositiveVelocity{ { 0, 0 }, { -10, -10 }, { 10, 10 } }; | |
platformer::SpeedLimiter limiter( objectDataWithPositiveVelocity, { 5, 5 } ); | |
limiter.update(); | |
AssertThat( objectDataWithPositiveVelocity.velocity.x, EqualsWithDelta( -5, 0.00001 ) ); | |
AssertThat( objectDataWithPositiveVelocity.velocity.y, EqualsWithDelta( -5, 0.00001 ) ); | |
} | |
}; | |
Describe( speed_addition ) | |
{ | |
It ( should_add_defined_speed_amount_in_each_update_iteration ) | |
{ | |
platformer::ObjectData objectData{ { 0, 0 }, { -10, -10 }, { 10, 10 } }; | |
platformer::SpeedAddition speedAddition( objectData, { 5, 5 } ); | |
speedAddition.update(); | |
AssertThat( objectData.velocity.x, EqualsWithDelta( -5, 0.00001 ) ); | |
AssertThat( objectData.velocity.y, EqualsWithDelta( -5, 0.00001 ) ); | |
} | |
}; | |
Describe( mover_collider ) | |
{ | |
void SetUp() | |
{ | |
objects.reset( new platformer::ObjectContainer( | |
{ platformer::TileCoordinate{ 0, 0 }, | |
platformer::TileCoordinate{ 100, 100 } } ) ); | |
} | |
It ( should_collide_with_tiles_from_all_directions ) | |
{ | |
objects->insert( platformer::Object::Ref( | |
new platformer::Tile( { 0, 0 } ) ) ); | |
std::vector< platformer::ObjectData > objectDatas = { | |
//bottom colliders | |
{ { 5, platformer::TILEHEIGHT * 1.5 }, { 0, -platformer::TILEHEIGHT }, { 5, 5 } }, | |
{ { -8, platformer::TILEHEIGHT * 1.5 }, { 0, -platformer::TILEHEIGHT }, { 10, 10 } }, | |
{ { platformer::TILEWIDTH - 2, platformer::TILEHEIGHT * 1.5 }, { 0, -platformer::TILEHEIGHT }, { 10, 10 } }, | |
//right colliders | |
{ { -15, 5 }, { platformer::TILEWIDTH, 0 }, { 10, 10 } }, | |
{ { -15, platformer::TILEHEIGHT - 3 }, { platformer::TILEWIDTH, 0 }, { 10, 10 } }, | |
{ { -15, -7 }, { platformer::TILEWIDTH, 0 }, { 10, 10 } }, | |
//left colliders | |
{ { platformer::TILEWIDTH + 15, 5 }, { -platformer::TILEWIDTH, 0 }, { 20, 10 } }, | |
{ { platformer::TILEWIDTH + 15, platformer::TILEHEIGHT - 3 }, { -platformer::TILEWIDTH, 0 }, { 20, 10 } }, | |
{ { platformer::TILEWIDTH + 15, -7 }, { -platformer::TILEWIDTH, 0 }, { 20, 10 } }, | |
//top colliders | |
{ { 5, -platformer::TILEHEIGHT - 2 }, { 0, platformer::TILEHEIGHT }, { 10, 10 } }, | |
{ { -8, -platformer::TILEHEIGHT - 2 }, { 0, platformer::TILEHEIGHT }, { 10, 10 } }, | |
{ { platformer::TILEWIDTH - 2, -platformer::TILEHEIGHT - 2 }, { 0, platformer::TILEHEIGHT }, { 10, 10 } }, | |
}; | |
std::for_each( begin( objectDatas ), end( objectDatas ), | |
[ this ]( platformer::ObjectData& data ) | |
{ | |
platformer::ObjectData old( data ); | |
platformer::MoveAndCollide collider( nullptr, data, *objects ); | |
collider.update(); | |
AssertThat( data.coordinate.y, EqualsWithDelta( old.coordinate.y, 0.00001 ) ); | |
AssertThat( data.coordinate.x, EqualsWithDelta( old.coordinate.x, 0.00001 ) ); | |
AssertThat( data.velocity.y, EqualsWithDelta( 0, 0.00001 ) ); | |
AssertThat( data.velocity.x, EqualsWithDelta( 0, 0.00001 ) ); | |
} ); | |
} | |
It ( should_be_able_to_jump_only_if_it_stands_on_ground ) | |
{ | |
platformer::ObjectData objectData{ { 5, platformer::TILEHEIGHT }, { 0, 0 }, { 5, 5 } }; | |
platformer::MoveAndCollide mover( nullptr, objectData, *objects ); | |
mover.update(); | |
mover.jump(); | |
AssertThat( objectData.velocity.y, EqualsWithDelta( 0, 0.00001 ) ); | |
objects->insert( platformer::Object::Ref( | |
new platformer::Tile( { 0, 0 } ) ) ); | |
mover.update(); | |
mover.jump(); | |
AssertThat( objectData.velocity.y, IsGreaterThan( platformer::MoveAndCollide::Acceleration ) ); | |
} | |
It ( should_take_care_of_drag_on_ground_if_not_moving ) | |
{ | |
objects->insert( platformer::Object::Ref( | |
new platformer::Tile( { 0, 0 } ) ) ); | |
platformer::ObjectData objectData{ { 0, platformer::TILEHEIGHT }, { 0, 0 }, { 5, 5 } }; | |
platformer::MoveAndCollide mover( nullptr, objectData, *objects ); | |
mover.update(); | |
mover.moveRight(); | |
mover.update(); | |
AssertThat( objectData.velocity.x, EqualsWithDelta( platformer::MoveAndCollide::Acceleration, 0.00001 ) ); | |
mover.update(); | |
AssertThat( objectData.velocity.x, IsLessThan( platformer::MoveAndCollide::Acceleration / 2 ) ); | |
} | |
It ( should_move_objects_with_its_velocity_if_no_collision_happens ) | |
{ | |
platformer::ObjectData objectData{ { 5, 5 }, { 2, 3 }, { 5, 5 } }; | |
platformer::MoveAndCollide collider( nullptr, objectData, *objects ); | |
collider.update(); | |
AssertThat( objectData.coordinate.x, EqualsWithDelta( 5 + 2, 0.00001 ) ); | |
AssertThat( objectData.coordinate.y, EqualsWithDelta( 5 + 3, 0.00001 ) ); | |
} | |
It ( should_modify_x_velocity_if_moved_left_or_right ) | |
{ | |
platformer::ObjectData objectData{ { 5, 5 }, { 2, 3 }, { 5, 5 } }; | |
platformer::MoveAndCollide mover( nullptr, objectData, *objects ); | |
mover.moveLeft(); | |
AssertThat( objectData.velocity.x, EqualsWithDelta( 2 - platformer::MoveAndCollide::Acceleration, 0.00001 ) ); | |
mover.moveRight(); | |
AssertThat( objectData.velocity.x, EqualsWithDelta( 2, 0.00001 ) ); | |
} | |
It ( should_not_check_collision_with_owning_object ) | |
{ | |
platformer::Coordinate startPoint{ 0.0, 0.0 }; | |
platformer::Coordinate velocity{ 0.3, 0.4 }; | |
platformer::ObjectData objectData{ startPoint, velocity, { 5, 5 } }; | |
platformer::test::DummyObject* object( new platformer::test::DummyObject( objectData ) ); | |
objects->insert( platformer::Object::Ref( object ) ); | |
platformer::MoveAndCollide mover( object, objectData, *objects ); | |
mover.update(); | |
AssertThat( objectData.coordinate.x, EqualsWithDelta( startPoint.x + velocity.x, 0.00001 ) ); | |
AssertThat( objectData.coordinate.y, EqualsWithDelta( startPoint.y + velocity.y, 0.00001 ) ); | |
} | |
It ( should_not_collide_with_objects_on_other_layers ) | |
{ | |
platformer::Coordinate startPoint{ 0.0, 0.0 }; | |
platformer::Coordinate velocity{ 1.0, 0.0 }; | |
platformer::ObjectData objectData{ startPoint, velocity, { 5, 5 } }; | |
platformer::test::DummyObject* object( new platformer::test::DummyObject( objectData ) ); | |
objects->insert( platformer::Object::Ref( object ) ); | |
platformer::MoveAndCollide mover( object, objectData, *objects ); | |
const platformer::Layer OTHER_LAYER( 1 ); | |
objects->insert( platformer::Object::Ref( new platformer::test::DummyObject( | |
platformer::ObjectData{ | |
{ 5.5, 0.0 }, | |
{ 0.0, 0.0 }, | |
{ 10.0, 10.0 }, | |
OTHER_LAYER | |
} | |
)) ); | |
mover.update(); | |
AssertThat( objectData.coordinate.x, EqualsWithDelta( startPoint.x + velocity.x, 0.00001 ) ); | |
AssertThat( objectData.coordinate.y, EqualsWithDelta( startPoint.y + velocity.y, 0.00001 ) ); | |
} | |
std::unique_ptr< platformer::ObjectContainer > objects; | |
}; | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "ObjectFactory.hpp" | |
#include "BaseTypes.hpp" | |
#include "Aabb.hpp" | |
#include "WorldGenerator.hpp" | |
#include "ObjectContainer.hpp" | |
namespace | |
{ | |
class FactoryDouble : public platformer::ObjectFactory | |
{ | |
public: | |
bool tileWasBuilt{ false }; | |
virtual platformer::Object::Ref buildTopTile( const platformer::TileCoordinate& coordinate ) | |
{ | |
tileWasBuilt = true; | |
return someObject( coordinate ); | |
} | |
virtual platformer::Object::Ref buildGroundTile( const platformer::TileCoordinate& coordinate ) | |
{ | |
tileWasBuilt = true; | |
return someObject( coordinate ); | |
} | |
virtual platformer::Object::Ref buildCaveTile( const platformer::TileCoordinate& coordinate ) | |
{ | |
tileWasBuilt = true; | |
return someObject( coordinate ); | |
} | |
void reset() | |
{ | |
tileWasBuilt = false; | |
} | |
private: | |
platformer::Object::Ref someObject( const platformer::TileCoordinate& coordinate ) const | |
{ | |
return platformer::Object::Ref( | |
new platformer::Tile( coordinate ) ); | |
} | |
}; | |
} | |
Describe( world_generator ) | |
{ | |
It ( should_generate_necessary_chunks_for_simple_coordinate_aabb_only_once ) | |
{ | |
platformer::Aabb aabb( | |
platformer::Coordinate{ 100.0, 100.0 }, | |
platformer::Coordinate{ 200.0, 200.0 } ); | |
platformer::ObjectContainer objects( aabb ); | |
FactoryDouble factory; | |
platformer::WorldGenerator worldGenerator( objects, factory ); | |
worldGenerator.generate( aabb ); | |
AssertThat( factory.tileWasBuilt, Equals( true ) ); | |
std::vector< platformer::Object* > objectsInAabb; | |
objects.collectIn( aabb, std::back_inserter( objectsInAabb ) ); | |
AssertThat( objectsInAabb, Is().Not().Empty() ); | |
factory.reset(); | |
worldGenerator.generate( aabb ); | |
AssertThat( factory.tileWasBuilt, Equals( false ) ); | |
} | |
}; | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1. clean up duplicates in test_updaters.hpp | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <vector> | |
#include <memory> | |
namespace platformer | |
{ | |
class Updater | |
{ | |
public: | |
typedef std::unique_ptr< Updater > Ref; | |
typedef std::vector< Ref > Container; | |
virtual void update() = 0; | |
}; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Updaters.hpp" | |
#include "BaseTypes.hpp" | |
#include "Object.hpp" | |
#include <cstdlib> | |
namespace platformer | |
{ | |
double MoveAndCollide::Acceleration = 1; | |
} | |
platformer::SpeedLimiter::SpeedLimiter( ObjectData& objectData, const Coordinate& speedLimit ) | |
: Updater() | |
, m_speedLimit( speedLimit ) | |
, m_objectData( objectData ) | |
{ | |
} | |
namespace | |
{ | |
double absMax( const double& value, const double& limit ) | |
{ | |
return value > 0 ? | |
std::min( value, limit ) : | |
std::max( value, limit * -1.0 ); | |
} | |
} | |
void | |
platformer::SpeedLimiter::update() | |
{ | |
m_objectData.velocity.x = absMax( m_objectData.velocity.x, m_speedLimit.x ); | |
m_objectData.velocity.y = absMax( m_objectData.velocity.y, m_speedLimit.y ); | |
} | |
platformer::SpeedAddition::SpeedAddition( ObjectData& objectData, const Coordinate& speedDelta ) | |
: Updater() | |
, m_speedDelta( speedDelta ) | |
, m_objectData( objectData ) | |
{ | |
} | |
void | |
platformer::SpeedAddition::update() | |
{ | |
m_objectData.velocity+=m_speedDelta; | |
} | |
platformer::MoveAndCollide::MoveAndCollide( Object* owner, ObjectData& objectData, const ObjectContainer& objects ) | |
: Updater() | |
, m_ownerObject( owner ) | |
, m_objects( objects ) | |
, m_objectData( objectData ) | |
, m_isOnGround( false ) | |
, m_isInMove( false ) | |
{ | |
} | |
namespace | |
{ | |
platformer::Aabb | |
collisionAreaFromObject( const platformer::ObjectData& data, | |
const platformer::Coordinate& coordinate ) | |
{ | |
const platformer::Coordinate bottomLeft( | |
coordinate + platformer::Coordinate{ -platformer::TILEWIDTH / 2, -platformer::TILEHEIGHT / 2 } ); | |
const platformer::Coordinate topRight( | |
coordinate + data.size + platformer::Coordinate{ platformer::TILEWIDTH / 2, platformer::TILEHEIGHT / 2 } ); | |
return platformer::Aabb( bottomLeft, topRight ); | |
} | |
} | |
typedef std::vector<platformer::Coordinate> CoordinateContainer; | |
namespace | |
{ | |
struct ObjectCollider | |
{ | |
ObjectCollider( const platformer::Object* object ) | |
: m_object( object ) | |
{ | |
} | |
bool operator()( const platformer::Coordinate& coordinate ) | |
{ | |
return m_object->contains( coordinate ); | |
} | |
const platformer::Object* m_object; | |
}; | |
} | |
void | |
platformer::MoveAndCollide::update() | |
{ | |
Coordinate newCoordinate( m_objectData.coordinate + m_objectData.velocity ); | |
std::vector< Object* > objectsInCollisionArea; | |
m_objects.collectIn( | |
collisionAreaFromObject( m_objectData, newCoordinate ), | |
std::back_inserter( objectsInCollisionArea ) ); | |
CoordinateContainer bottomColliders{ | |
newCoordinate + platformer::Coordinate{ m_objectData.size.x * 1/2, 0 }, | |
newCoordinate + platformer::Coordinate{ m_objectData.size.x * 2/10, 0 }, | |
newCoordinate + platformer::Coordinate{ m_objectData.size.x * 8/10, 0 }, | |
}; | |
CoordinateContainer topColliders{ | |
newCoordinate + platformer::Coordinate{ m_objectData.size.x * 1/2, m_objectData.size.y * 9/10 }, | |
newCoordinate + platformer::Coordinate{ m_objectData.size.x * 1/5, m_objectData.size.y * 9/10 }, | |
newCoordinate + platformer::Coordinate{ m_objectData.size.x * 4/5, m_objectData.size.y * 9/10 }, | |
}; | |
CoordinateContainer leftColliders{ | |
newCoordinate + platformer::Coordinate{ m_objectData.size.x * 1/10, 2 }, | |
newCoordinate + platformer::Coordinate{ m_objectData.size.x * 1/10, m_objectData.size.y * 1/2 }, | |
newCoordinate + platformer::Coordinate{ m_objectData.size.x * 1/10, m_objectData.size.y * 1/4 }, | |
newCoordinate + platformer::Coordinate{ m_objectData.size.x * 1/10, m_objectData.size.y * 3/4 }, | |
}; | |
CoordinateContainer rightColliders{ | |
newCoordinate + platformer::Coordinate{ m_objectData.size.x * 9/10, 2 }, | |
newCoordinate + platformer::Coordinate{ m_objectData.size.x * 9/10, m_objectData.size.y * 1/2 }, | |
newCoordinate + platformer::Coordinate{ m_objectData.size.x * 9/10, m_objectData.size.y * 1/4 }, | |
newCoordinate + platformer::Coordinate{ m_objectData.size.x * 9/10, m_objectData.size.y * 3/4 }, | |
}; | |
m_isOnGround = false; | |
std::for_each( begin( objectsInCollisionArea ), end( objectsInCollisionArea ), | |
[ this, &newCoordinate, &bottomColliders, &topColliders, &leftColliders, &rightColliders ] ( Object* object ) | |
{ | |
if ( object == m_ownerObject ) | |
{ | |
return; | |
} | |
if ( !object->isOnLayer( m_objectData.layer ) ) | |
{ | |
return; | |
} | |
ObjectCollider collidesWithObject( object ); | |
if ( std::any_of( begin( bottomColliders ), end( bottomColliders ), collidesWithObject ) ) | |
{ | |
m_objectData.velocity.y = 0; | |
newCoordinate.y = m_objectData.coordinate.y; | |
m_isOnGround = true; | |
} | |
if ( std::any_of( begin( topColliders ), end( topColliders ), collidesWithObject ) ) | |
{ | |
m_objectData.velocity.y = 0; | |
newCoordinate.y = m_objectData.coordinate.y; | |
} | |
const bool movingLeftAndLeftSideCollides( | |
m_objectData.velocity.x < 0 && | |
std::any_of( begin( leftColliders ), end( leftColliders ), collidesWithObject ) ); | |
const bool movingRightAndRightSideCollides( | |
m_objectData.velocity.x > 0 && | |
std::any_of( begin( rightColliders ), end( rightColliders ), collidesWithObject ) ); | |
if ( movingLeftAndLeftSideCollides || | |
movingRightAndRightSideCollides ) | |
{ | |
m_objectData.velocity.x = 0; | |
newCoordinate.x = m_objectData.coordinate.x; | |
} | |
} ); | |
applyGroundDrag(); | |
m_objectData.coordinate = newCoordinate; | |
m_isInMove = false; | |
} | |
void | |
platformer::MoveAndCollide::applyGroundDrag() | |
{ | |
if ( m_isOnGround && !m_isInMove ) | |
{ | |
const double GroundDrag( 0.1 ); | |
m_objectData.velocity.x *= GroundDrag; | |
} | |
} | |
void | |
platformer::MoveAndCollide::moveLeft() | |
{ | |
m_isInMove = true; | |
m_objectData.velocity.x -= Acceleration; | |
} | |
void | |
platformer::MoveAndCollide::moveRight() | |
{ | |
m_isInMove = true; | |
m_objectData.velocity.x += Acceleration; | |
} | |
void | |
platformer::MoveAndCollide::jump() | |
{ | |
if ( !m_isOnGround ) | |
{ | |
return; | |
} | |
const double JumpMultiplier( 8 ); | |
m_objectData.velocity.y+=Acceleration * JumpMultiplier; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "BaseTypes.hpp" | |
#include "Updater.hpp" | |
#include "ObjectContainer.hpp" | |
namespace platformer | |
{ | |
class ObjectData; | |
class SpeedLimiter : public Updater | |
{ | |
public: | |
SpeedLimiter( ObjectData& objectData, const Coordinate& speedLimit ); | |
virtual void update(); | |
private: | |
Coordinate m_speedLimit; | |
ObjectData& m_objectData; | |
}; | |
class SpeedAddition : public Updater | |
{ | |
public: | |
SpeedAddition( ObjectData& objectData, const Coordinate& speedDelta ); | |
virtual void update(); | |
private: | |
Coordinate m_speedDelta; | |
ObjectData& m_objectData; | |
}; | |
class MoveAndCollide : public Updater | |
{ | |
public: | |
static double Acceleration; | |
MoveAndCollide( Object* ownerObject, ObjectData& objectData, const ObjectContainer& objects ); | |
virtual void update(); | |
void moveLeft(); | |
void moveRight(); | |
void jump(); | |
private: | |
void applyGroundDrag(); | |
Object* m_ownerObject; | |
const ObjectContainer& m_objects; | |
ObjectData& m_objectData; | |
bool m_isOnGround; | |
bool m_isInMove; | |
}; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "World.hpp" | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "WorldGenerator.hpp" | |
#include "BaseTypes.hpp" | |
#include "Aabb.hpp" | |
#include "ObjectContainer.hpp" | |
#include "ObjectFactory.hpp" | |
namespace | |
{ | |
const int TILENUM( 5 ); | |
const int CHUNKWIDTH( platformer::TILEWIDTH * TILENUM ); | |
const int CHUNKHEIGHT( platformer::TILEHEIGHT * TILENUM ); | |
} | |
platformer::WorldGenerator::WorldGenerator( ObjectContainer& tiles, ObjectFactory& factory ) | |
: m_tiles( tiles ) | |
, m_factory( factory ) | |
, m_generatedChunks() | |
{ | |
} | |
void | |
platformer::WorldGenerator::generate( const Aabb& aabb ) | |
{ | |
ChunkCoordinate bottomLeft{ | |
static_cast<int>( aabb.bottomLeft().x / CHUNKWIDTH ), | |
static_cast<int>( aabb.bottomLeft().y / CHUNKHEIGHT ) }; | |
ChunkCoordinate topRight{ | |
static_cast<int>( aabb.topRight().x / CHUNKWIDTH ), | |
static_cast<int>( aabb.topRight().y / CHUNKHEIGHT ) }; | |
for ( int x( bottomLeft.x ); x <= topRight.x; ++x ) | |
{ | |
for ( int y( bottomLeft.y ); y <= topRight.y; ++y ) | |
{ | |
generateTilesInChunk( x, y ); | |
} | |
} | |
} | |
namespace | |
{ | |
template <class Iterator, typename Value > | |
bool contains( Iterator begin, Iterator end, const Value& value ) | |
{ | |
return std::any_of( begin, end, | |
[ &value ]( const Value& val ) | |
{ | |
return value == val; | |
} ); | |
} | |
} | |
void | |
platformer::WorldGenerator::generateTilesInChunk( int chunkx, int chunky ) | |
{ | |
ChunkCoordinate chunkCoordinate{ chunkx, chunky }; | |
if ( contains( begin( m_generatedChunks ), end( m_generatedChunks ), chunkCoordinate ) ) | |
{ | |
return; | |
} | |
for ( int tx( chunkx * TILENUM ); tx < ( chunkx + 1 ) * TILENUM; ++tx ) | |
{ | |
for ( int ty( chunky * TILENUM ); ty < ( chunky + 1 ) * TILENUM; ++ty ) | |
{ | |
m_tiles.insert( m_factory.buildGroundTile( { tx, ty } ) ); | |
} | |
} | |
m_generatedChunks.push_back( chunkCoordinate ); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "BaseTypes.hpp" | |
#include <vector> | |
namespace platformer | |
{ | |
class Aabb; | |
class ObjectContainer; | |
class ObjectFactory; | |
class WorldGenerator | |
{ | |
public: | |
typedef TileCoordinate ChunkCoordinate; | |
WorldGenerator( ObjectContainer& tiles, ObjectFactory& factory ); | |
void generate( const Aabb& aabb ); | |
private: | |
void generateTilesInChunk( int x, int y ); | |
ObjectContainer& m_tiles; | |
ObjectFactory& m_factory; | |
std::vector< ChunkCoordinate > m_generatedChunks; | |
}; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment