Skip to content

Commit c9f1acf

Browse files
committed
tiles: restet button, no more virtual madness
1 parent 9a22ccf commit c9f1acf

2 files changed

Lines changed: 128 additions & 82 deletions

File tree

‎cpp/unique_ptr.cpp‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,19 @@ int main() {
101101
}
102102
}
103103
}
104+
105+
/*
106+
# reset
107+
108+
Explicit destruction of pointer. Equivalent to `delete`.
109+
110+
http://stackoverflow.com/questions/25609457/unique-ptr-explicit-delete
111+
*/
112+
{
113+
Base::count = 0;
114+
std::unique_ptr<Base> p = std::unique_ptr<Base>(new Base(1));
115+
assert(Base::count == 1);
116+
p.reset();
117+
assert(Base::count == 0);
118+
}
104119
}

‎sdl/tiles.cpp‎

Lines changed: 113 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,26 @@ class Action {
3232

3333
class 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

4957
class 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) {}
89102
unsigned int Object::getX() const { return this->x; }
90103
unsigned int Object::getY() const { return this->y; }
91104
void Object::setX(unsigned int x) { this->x = x; }
92105
void 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

144142
World::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

191172
World::~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+
214226
void 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

231243
unsigned int World::getHeight() const { return this->height; }
244+
SDL_Renderer * World::getRenderer() const { return this->renderer; }
232245
unsigned int World::getTileHeightPix() const { return this->tileHeightPix; }
233246
unsigned int World::getTileWidthPix() const { return this->tileWidthPix; }
234247
unsigned int World::getWidth() const { return this->width; }
@@ -254,7 +267,7 @@ SDL_Texture * World::createSolidTexture(unsigned int r, unsigned int g, unsigned
254267

255268
int 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

Comments
 (0)