@@ -32,18 +32,26 @@ class Action {
3232
3333class Object {
3434 public:
35- Object (){}
36- Object (World *world, unsigned int x, unsigned int y );
37- virtual void draw (SDL_Renderer *renderer) const = 0 ;
38- virtual Action act () = 0;
35+ Object ();
36+ virtual ~ Object ();
37+ Object ( unsigned int x, unsigned int y) ;
38+ virtual Action act (World *world ) = 0;
3939 unsigned int getX () const ;
4040 unsigned int getY () const ;
4141 void setX (unsigned int x);
4242 void setY (unsigned int y);
4343 protected:
4444 unsigned int x;
4545 unsigned int y;
46- World *world;
46+ };
47+
48+ class DrawableObject {
49+ public:
50+ DrawableObject (Object *object) : object(object){}
51+ virtual ~DrawableObject (){}
52+ virtual void draw (const World * world) const = 0;
53+ protected:
54+ Object *object;
4755};
4856
4957class World {
@@ -60,14 +68,17 @@ class World {
6068 ~World ();
6169 void draw () const ;
6270 // / Collect desired actions from all objects, and resolve them
71+ unsigned int getHeight () const ;
72+ SDL_Renderer * getRenderer () const ;
73+ unsigned int getTileWidthPix () const ;
74+ unsigned int getTileHeightPix () const ;
75+ unsigned int getWidth () const ;
76+ void initPhysics ();
77+ void resetPhysics ();
6378 // / to the next world state. E.g.: what happens if two objects
6479 // / want to move to the same place next tick? Or if an object
6580 // / wants to move into a wall?
6681 void update ();
67- unsigned int getHeight () const ;
68- unsigned int getWidth () const ;
69- unsigned int getTileWidthPix () const ;
70- unsigned int getTileHeightPix () const ;
7182 private:
7283 unsigned int width;
7384 unsigned int height;
@@ -79,66 +90,53 @@ class World {
7990 SDL_Renderer *renderer;
8091 SDL_Window *window;
8192 std::vector<std::unique_ptr<Object>> objects;
93+ std::vector<std::unique_ptr<DrawableObject>> drawableObjects;
8294 std::vector<SDL_Texture *> textures;
95+
8396 SDL_Texture * createSolidTexture (unsigned int r, unsigned int g, unsigned int b, unsigned int a);
8497};
8598
86- Object::Object (World *world, unsigned int x, unsigned int y) :
87- world(world), x(x), y(y) {}
88-
99+ Object::Object (){}
100+ Object::~Object () {}
101+ Object::Object ( unsigned int x, unsigned int y) : x(x), y(y) {}
89102unsigned int Object::getX () const { return this ->x ; }
90103unsigned int Object::getY () const { return this ->y ; }
91104void Object::setX (unsigned int x) { this ->x = x; }
92105void Object::setY (unsigned int y) { this ->y = y; }
93106
94- class SingleTextureDrawableObject : public virtual Object {
107+ class MoveUpObject : public Object {
95108 public:
96- SingleTextureDrawableObject (SDL_Texture *texture) :
97- texture (texture) {
98- }
99- virtual void draw (SDL_Renderer *renderer) const {
100- SDL_Rect rect;
101- rect.x = this ->x * this ->world ->getTileWidthPix ();
102- rect.y = this ->y * this ->world ->getTileHeightPix ();
103- rect.w = this ->world ->getTileWidthPix ();
104- rect.h = this ->world ->getTileHeightPix ();
105- SDL_RenderCopy (renderer, this ->texture , NULL , &rect);
106- }
107- private:
108- // / Pointer to texture shared across all objects that look the same.
109- SDL_Texture * const texture;
110- };
111-
112- class MoveUpActableObject : public virtual Object {
113- public:
114- MoveUpActableObject (){}
115- virtual Action act () {
109+ MoveUpObject (unsigned int x, unsigned int y) : Object(x, y) {}
110+ virtual ~MoveUpObject (){}
111+ virtual Action act (World *world) {
116112 return Action (Action::Direction::UP );
117113 };
118114};
119115
120- class MoveDownActableObject : public virtual Object {
116+ class MoveDownObject : public Object {
121117 public:
122- MoveDownActableObject (){}
123- virtual Action act () {
118+ MoveDownObject (unsigned int x, unsigned int y) : Object(x, y) {}
119+ virtual ~MoveDownObject (){}
120+ virtual Action act (World *world) {
124121 return Action (Action::Direction::DOWN );
125122 };
126123};
127124
128- class SingleTextureMoveUpObject : public SingleTextureDrawableObject , public MoveUpActableObject {
129- public:
130- SingleTextureMoveUpObject (World *world, unsigned int x, unsigned int y, SDL_Texture *texture) :
131- Object (world, x, y),
132- SingleTextureDrawableObject (texture)
133- {}
134- };
135-
136- class SingleTextureMoveDownObject : public SingleTextureDrawableObject , public MoveDownActableObject {
125+ class SingleTextureDrawableObject : public DrawableObject {
137126 public:
138- SingleTextureMoveDownObject (World *world, unsigned int x, unsigned int y, SDL_Texture *texture) :
139- Object (world, x, y),
140- SingleTextureDrawableObject (texture)
141- {}
127+ SingleTextureDrawableObject (Object *object, SDL_Texture *texture) :
128+ DrawableObject (object), texture(texture) {}
129+ virtual void draw (const World * world) const {
130+ SDL_Rect rect;
131+ rect.x = this ->object ->getX () * world->getTileWidthPix ();
132+ rect.y = this ->object ->getY () * world->getTileHeightPix ();
133+ rect.w = world->getTileWidthPix ();
134+ rect.h = world->getTileHeightPix ();
135+ SDL_RenderCopy (world->getRenderer (), this ->texture , NULL , &rect);
136+ }
137+ private:
138+ // / Pointer to texture shared across all objects that look the same.
139+ SDL_Texture * texture;
142140};
143141
144142World::World (
@@ -160,32 +158,15 @@ World::World(
160158{
161159 this ->window = NULL ;
162160 this ->renderer = NULL ;
163- SDL_Texture
164- *redTexture = NULL ,
165- *blueTexture = NULL
166- ;
167161 if (this ->display ) {
168162 // Window setup.
169163 SDL_Init (SDL_INIT_TIMER | SDL_INIT_VIDEO );
170164 SDL_CreateWindowAndRenderer (this ->windowWidthPix , this ->windowHeightPix , 0 , &this ->window , &this ->renderer );
171165 SDL_SetWindowTitle (window, __FILE__);
172-
173- // Initialize textures to be reused across objects..
174- redTexture = createSolidTexture (COLOR_MAX , 0 , 0 , 0 );
175- blueTexture = createSolidTexture (0 , 0 , COLOR_MAX , 0 );
176- }
177-
178- // Initialize objects in world. TODO also load serialization.
179- for (unsigned int y = 0 ; y < this ->height ; ++y) {
180- for (unsigned int x = 0 ; x < this ->width ; ++x) {
181- unsigned int sum = x + y;
182- if (sum & 1 ) {
183- objects.push_back (std::unique_ptr<Object>(new SingleTextureMoveUpObject (this , x, y, redTexture)));
184- } else if (sum % 3 == 0 ) {
185- objects.push_back (std::unique_ptr<Object>(new SingleTextureMoveDownObject (this , x, y, blueTexture)));
186- }
187- }
166+ createSolidTexture (COLOR_MAX , 0 , 0 , 0 );
167+ createSolidTexture (0 , 0 , COLOR_MAX , 0 );
188168 }
169+ this ->initPhysics ();
189170}
190171
191172World::~World () {
@@ -204,16 +185,47 @@ void World::draw() const {
204185 Uint8 *base;
205186 SDL_SetRenderDrawColor (this ->renderer , 0 , 0 , 0 , 0 );
206187 SDL_RenderClear (this ->renderer );
207- for (auto const & object : this ->objects ) {
208- object->draw (this -> renderer );
188+ for (auto const & object : this ->drawableObjects ) {
189+ object->draw (this );
209190 }
210191 SDL_RenderPresent (this ->renderer );
211192 }
212193}
213194
195+ void World::initPhysics () {
196+ for (unsigned int y = 0 ; y < this ->height ; ++y) {
197+ for (unsigned int x = 0 ; x < this ->width ; ++x) {
198+ unsigned int sum = x + y;
199+ if (sum & 1 ) {
200+ auto object = std::unique_ptr<Object>(new MoveUpObject (x, y));
201+ if (display) {
202+ drawableObjects.push_back (std::unique_ptr<DrawableObject>(
203+ new SingleTextureDrawableObject (object.get (), this ->textures [0 ])
204+ ));
205+ }
206+ objects.push_back (std::move (object));
207+ } else if (sum % 3 == 0 ) {
208+ auto object = std::unique_ptr<Object>(new MoveDownObject (x, y));
209+ if (display) {
210+ drawableObjects.push_back (std::unique_ptr<DrawableObject>(
211+ new SingleTextureDrawableObject (object.get (), this ->textures [1 ])
212+ ));
213+ }
214+ objects.push_back (std::move (object));
215+ }
216+ }
217+ }
218+ }
219+
220+ void World::resetPhysics () {
221+ this ->objects .clear ();
222+ this ->drawableObjects .clear ();
223+ this ->initPhysics ();
224+ }
225+
214226void World::update () {
215227 for (auto & object : this ->objects ) {
216- Action a = object->act ();
228+ Action a = object->act (this );
217229 if (a.getDirection () == Action::Direction::UP ) {
218230 auto y = object->getY ();
219231 if (y < this ->getHeight () - 1 ) {
@@ -229,6 +241,7 @@ void World::update() {
229241}
230242
231243unsigned int World::getHeight () const { return this ->height ; }
244+ SDL_Renderer * World::getRenderer () const { return this ->renderer ; }
232245unsigned int World::getTileHeightPix () const { return this ->tileHeightPix ; }
233246unsigned int World::getTileWidthPix () const { return this ->tileWidthPix ; }
234247unsigned int World::getWidth () const { return this ->width ; }
@@ -254,7 +267,7 @@ SDL_Texture * World::createSolidTexture(unsigned int r, unsigned int g, unsigned
254267
255268int main (int argc, char **argv) {
256269 SDL_Event event;
257- World * world;
270+ std::unique_ptr< World> world;
258271 bool
259272 display = true ,
260273 limitFps = false
@@ -264,10 +277,10 @@ int main(int argc, char **argv) {
264277 last_time;
265278 ;
266279 unsigned int
267- width = 10 ,
280+ width = 100 ,
268281 height = width,
269282 ticks = 0 ,
270- tileWidthPix = 50 ,
283+ tileWidthPix = 5 ,
271284 tileHeightPix = tileWidthPix,
272285 windowWidthPix = width * tileWidthPix,
273286 windowHeightPix = height * tileHeightPix
@@ -277,30 +290,43 @@ int main(int argc, char **argv) {
277290 while (argc > 1 ) {
278291 argc--;
279292 if (argv[argc][0 ] == ' -' ) {
280- // -d: turn display off. Might make simulation faster
281- // or runnable in device without display.
282293 if (std::strcmp (argv[argc], " -d" ) == 0 ) {
283294 display = !display;
284- // -f 1.5: limit FPS to 1.5 fps. Helps humans visualize
285- // what is going on if simulation is too fast.
286295 } else if (std::strcmp (argv[argc], " -f" ) == 0 ) {
287296 limitFps = !limitFps;
288297 targetFps = std::strtod (argv[argc + 1 ], NULL );
298+ } else if (std::strcmp (argv[argc], " -h" ) == 0 ) {
299+ std::cerr <<
300+ " # CLI Options\n "
301+ " \n "
302+ " - `-d`: turn display off. Might make simulation faster\n "
303+ " or runnable in device without display.\n "
304+ " \n "
305+ " - `-f <double>`: limit FPS to <double> FPS. Helps humans visualize\n "
306+ " what is going on if simulation is too fast. E.g.\n "
307+ " `-f 2.0` limits simulation to 2 FPS.\n "
308+ " \n "
309+ " # Controls\n "
310+ " \n "
311+ " - `ESC`: quit\n "
312+ " - `r`: restart from initial state\n "
313+ ;
314+ std::exit (EXIT_SUCCESS );
289315 }
290316 }
291317 }
292318 auto targetSpf = 1.0 / targetFps;
293319
294- main_loop:
295- world = new World (
320+ world = std::unique_ptr<World>(new World (
296321 width,
297322 height,
298323 display,
299324 windowWidthPix,
300325 windowHeightPix,
301326 tileWidthPix,
302327 tileHeightPix
303- );
328+ ));
329+ main_loop:
304330 common_fps_init ();
305331 last_time = common_get_secs ();
306332 while (1 ) {
@@ -315,7 +341,12 @@ int main(int argc, char **argv) {
315341 } else if (event.type == SDL_KEYDOWN ) {
316342 switch (event.key .keysym .sym ) {
317343 case SDLK_ESCAPE :
344+ goto quit;
345+ break ;
346+ case SDLK_r:
347+ world->resetPhysics ();
318348 goto main_loop;
349+ break ;
319350 }
320351 }
321352 }
0 commit comments