summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-12-11 19:52:31 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-12-11 19:52:31 -0500
commit4f09a7b0931afbc9a304e371aab3b7c93071027f (patch)
treedfde0156e696e7ab9a1cdfb928d163517850a0c1
parent9a1c65dd2328d3da94cdaac6b1f170481222fabe (diff)
random setups
-rw-r--r--Makefile2
-rw-r--r--platforms.cpp101
-rw-r--r--setup.cpp138
-rw-r--r--sim.cpp168
-rw-r--r--sim.hpp20
-rw-r--r--util.cpp40
6 files changed, 338 insertions, 131 deletions
diff --git a/Makefile b/Makefile
index fa629e2..1f6b4f2 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
WARNINGS=-Wall -Wextra -Wshadow -Wconversion -Wpedantic -pedantic -std=gnu++11 -Wno-unused-function -Wimplicit-fallthrough
LIBS=-ldl `pkg-config --libs --cflags sdl2 gl` -l:libbox2d.a
-DEBUG_CFLAGS=$(CFLAGS) $(WARNINGS) $(LIBS) -DDEBUG -O0 -g
+DEBUG_CFLAGS=$(CFLAGS) $(WARNINGS) $(LIBS) -DDEBUG -O0 -g3
obj/debug: physics obj/sim.so obj
touch obj/debug
physics: *.[ch]*
diff --git a/platforms.cpp b/platforms.cpp
index d208e50..e52b302 100644
--- a/platforms.cpp
+++ b/platforms.cpp
@@ -1,3 +1,15 @@
+#define PLATFORM_RADIUS_MIN 0.2f
+#define PLATFORM_RADIUS_MAX 5.0f
+#define PLATFORM_MOVE_SPEED_MIN 0.1f
+#define PLATFORM_MOVE_SPEED_MAX 5.0f
+#define PLATFORM_ROTATE_SPEED_MIN -3.0f
+#define PLATFORM_ROTATE_SPEED_MAX +3.0f
+
+// additional cost for each additional meter of platform radius
+#define PLATFORM_RADIUS_COST 1.0f
+#define PLATFORM_MOVE_SPEED_COST 1.0f
+#define PLATFORM_ROTATE_SPEED_COST 1.0f
+
// how far right could any part of this platform possibly go?
static float platform_rightmost_x(Platform const *platform) {
float angle;
@@ -139,21 +151,8 @@ static void platforms_render(State *state, Platform *platforms, u32 nplatforms)
}
}
-static uintptr_t platform_to_user_data(State *state, Platform *platform) {
- return USER_DATA_PLATFORM | (uintptr_t)(platform - state->platforms);
-}
-
-static Platform *platform_from_user_data(State *state, uintptr_t user_data) {
- if ((user_data & USER_DATA_TYPE) == USER_DATA_PLATFORM) {
- uintptr_t index = user_data & USER_DATA_INDEX;
- return &state->platforms[index];
- } else {
- return NULL;
- }
-}
-
// sets platform->body to a new Box2D body.
-static void platform_make_body(State *state, Platform *platform) {
+static void platform_make_body(State *state, Platform *platform, u32 index) {
b2World *world = state->world;
float radius = platform->radius;
@@ -175,18 +174,12 @@ static void platform_make_body(State *state, Platform *platform) {
b2FixtureDef fixture;
fixture.shape = &shape;
fixture.friction = 0.5f;
- fixture.userData.pointer = platform_to_user_data(state, platform);
+ fixture.userData.pointer = USER_DATA_PLATFORM | index;
body->CreateFixture(&fixture);
- if (platform->moves) {
- float speed = platform->move_speed;
- v2 p1 = platform->move_p1, p2 = platform->move_p2;
- v2 direction = v2_normalize(v2_sub(p2, p1));
- v2 velocity = v2_scale(direction, speed);
- body->SetLinearVelocity(v2_to_b2(velocity));
- }
- body->SetAngularVelocity(platform->rotate_speed);
-
+
+ // velocity and rotate speed will be set when setup_reset is called
+
platform->body = body;
}
@@ -196,8 +189,15 @@ public:
this->state = state_;
}
bool ReportFixture(b2Fixture *fixture) {
- platform = platform_from_user_data(state, fixture->GetUserData().pointer);
- return !platform; // if we haven't found a platform, keep going
+ uintptr_t userdata = fixture->GetUserData().pointer;
+ if (userdata & USER_DATA_PLATFORM) {
+ u32 index = (u32)(userdata & ~USER_DATA_PLATFORM);
+ assert(index < state->nplatforms);
+ platform = &state->platforms[index];
+ return false; // we can stop now
+ } else {
+ return true; // keep going
+ }
}
Platform *platform = NULL;
State *state = NULL;
@@ -227,7 +227,7 @@ static void platform_delete(State *state, Platform *platform) {
// set this platform to last platform
platforms[index] = platforms[nplatforms-1];
memset(&platforms[nplatforms-1], 0, sizeof(Platform));
- platforms[index].body->GetFixtureList()->GetUserData().pointer = platform_to_user_data(state, &platforms[index]);
+ platforms[index].body->GetFixtureList()->GetUserData().pointer = index | USER_DATA_PLATFORM;
} else {
// platform is at end of array; don't need to do anything special
memset(&platforms[index], 0, sizeof(Platform));
@@ -237,11 +237,11 @@ static void platform_delete(State *state, Platform *platform) {
}
static float platform_cost(Platform const *platform) {
- float cost = platform->radius;
+ float cost = platform->radius * PLATFORM_RADIUS_COST;
if (platform->moves)
- cost += platform->move_speed;
+ cost += platform->move_speed * PLATFORM_MOVE_SPEED_COST;
if (platform->rotates)
- cost += platform->rotate_speed;
+ cost += fabsf(platform->rotate_speed) * PLATFORM_ROTATE_SPEED_COST;
return cost;
}
@@ -252,3 +252,44 @@ static float platforms_cost(Platform const *platforms, u32 nplatforms) {
}
return total_cost;
}
+
+static void platform_write_to_file(Platform const *p, FILE *fp) {
+ fwrite_float(fp, p->radius);
+ fwrite_float(fp, p->start_angle);
+ fwrite_u32(fp, p->color);
+
+ u8 flags = (u8)(p->moves * 1) | (u8)(p->rotates * 2);
+ fwrite_u8(fp, flags);
+ if (p->moves) {
+ fwrite_float(fp, p->move_speed);
+ fwrite_v2(fp, p->move_p1);
+ fwrite_v2(fp, p->move_p2);
+ } else {
+ fwrite_v2(fp, p->center);
+ }
+ if (p->rotates) {
+ fwrite_float(fp, p->rotate_speed);
+ }
+}
+
+static void platform_read_from_file(Platform const *p, FILE *fp) {
+ p->radius = fread_float(fp);
+ p->start_angle = fread_float(fp);
+ p->color = fread_u32(fp);
+
+ u8 flags = fread_u8(fp);
+ p->moves = (flags & 1) != 0;
+ p->rotates = (flags & 2) != 0;
+
+ if (p->moves) {
+ p->move_speed = fread_float(fp);
+ p->move_p1 = fread_v2(fp);
+ p->move_p2 = fread_v2(fp);
+ } else {
+ p->center = fread_v2(fp);
+ }
+
+ if (p->rotates) {
+ p->rotate_speed = fread_float(fp);
+ }
+}
diff --git a/setup.cpp b/setup.cpp
new file mode 100644
index 0000000..19c6374
--- /dev/null
+++ b/setup.cpp
@@ -0,0 +1,138 @@
+// these only apply to computer-generated setups
+#define SETUP_MIN_X 1.0f
+#define SETUP_MAX_X 10.0f
+#define SETUP_MIN_Y 1.0f
+#define SETUP_MAX_Y 10.0f
+
+static v2 setup_rand_point(void) {
+ return V2(
+ rand_uniform(SETUP_MIN_X, SETUP_MAX_X),
+ rand_uniform(SETUP_MIN_Y, SETUP_MAX_Y)
+ );
+}
+
+#define PLATFORM_MOVE_CHANCE 0.5f // chance that the platform will be a moving one
+#define PLATFORM_ROTATE_CHANCE 0.5f // chance that the platform will be a rotating one (platforms can be moving and rotating)
+static void setup_random(State *state, Setup *setup, float cost_allowed) {
+ // how much "money" we have to spend
+ float cost_left = cost_allowed;
+
+ while (cost_left > PLATFORM_RADIUS_MIN * PLATFORM_RADIUS_COST && setup->nplatforms < MAX_PLATFORMS) {
+ Platform *platform = &setup->platforms[setup->nplatforms++];
+
+ platform->color = rand_u32() | 0xFF;
+ float max_radius_allowed = cost_left / PLATFORM_RADIUS_COST;
+ if (max_radius_allowed > PLATFORM_RADIUS_MAX)
+ max_radius_allowed = PLATFORM_RADIUS_MAX;
+ platform->radius = rand_uniform(PLATFORM_RADIUS_MIN, max_radius_allowed);
+ platform->center = setup_rand_point();
+ platform->start_angle = rand_uniform(0, PIf);
+ cost_left -= platform->radius * PLATFORM_RADIUS_COST;
+
+ if (cost_left > PLATFORM_MOVE_SPEED_COST * PLATFORM_MOVE_SPEED_MIN) {
+ if (randf() < PLATFORM_MOVE_CHANCE) {
+ platform->moves = true;
+ float max_speed_allowed = cost_left / PLATFORM_MOVE_SPEED_COST;
+ if (max_speed_allowed > PLATFORM_MOVE_SPEED_MAX)
+ max_speed_allowed = PLATFORM_MOVE_SPEED_MAX;
+ platform->move_speed = rand_uniform(PLATFORM_MOVE_SPEED_MIN, max_speed_allowed);
+ platform->move_p1 = platform->center;
+ platform->move_p2 = setup_rand_point();
+ cost_left -= platform->move_speed * PLATFORM_MOVE_SPEED_COST;
+ }
+ }
+
+ if (cost_left > PLATFORM_ROTATE_SPEED_COST * 0.1f) {
+ if (randf() < PLATFORM_ROTATE_CHANCE) {
+ float max_rotate_speed_allowed = cost_left / PLATFORM_ROTATE_SPEED_COST;
+ if (max_rotate_speed_allowed > PLATFORM_ROTATE_SPEED_MAX)
+ max_rotate_speed_allowed = PLATFORM_ROTATE_SPEED_MAX;
+ platform->rotates = true;
+ platform->rotate_speed = rand_uniform(0.1f, max_rotate_speed_allowed);
+ if (rand() % 2)
+ platform->rotate_speed = -platform->rotate_speed; // clockwise
+ cost_left -= fabsf(platform->rotate_speed) * PLATFORM_ROTATE_SPEED_COST;
+ }
+ }
+
+ platform_make_body(state, platform, setup->nplatforms - 1);
+ }
+ assert(cost_left >= 0);
+}
+
+// make this setup the active one
+static void setup_use(State *state, Setup *setup) {
+ memcpy(state->platforms, setup->platforms, setup->nplatforms * sizeof(Platform));
+ state->nplatforms = setup->nplatforms;
+}
+
+static void setup_reset(State *state) {
+ { // reset ball
+ Ball *ball = &state->ball;
+ b2World *world = state->world;
+ if (ball->body)
+ world->DestroyBody(ball->body);
+
+
+ ball->radius = 0.3f;
+ ball->pos = V2(BALL_STARTING_X, 10.0f);
+
+ // create ball
+ b2BodyDef ball_def;
+ ball_def.type = b2_dynamicBody;
+ ball_def.position.Set(ball->pos.x, ball->pos.y);
+ b2Body *ball_body = ball->body = world->CreateBody(&ball_def);
+
+ b2CircleShape ball_shape;
+ ball_shape.m_radius = ball->radius;
+
+ b2FixtureDef ball_fixture;
+ ball_fixture.shape = &ball_shape;
+ ball_fixture.density = 1.0f;
+ ball_fixture.friction = 0.3f;
+ ball_fixture.restitution = 0.6f; // bounciness
+
+ ball_body->CreateFixture(&ball_fixture);
+
+ }
+ for (Platform *platform = state->platforms, *end = platform + state->nplatforms; platform != end; ++platform) { // reset platforms
+ b2Body *body = platform->body;
+ assert(body);
+ platform->angle = platform->start_angle;
+ if (platform->moves) platform->center = platform->move_p1;
+ body->SetTransform(v2_to_b2(platform->center), platform->angle);
+ if (platform->moves) {
+ float speed = platform->move_speed;
+ v2 p1 = platform->move_p1, p2 = platform->move_p2;
+ v2 direction = v2_normalize(v2_sub(p2, p1));
+ v2 velocity = v2_scale(direction, speed);
+ body->SetLinearVelocity(v2_to_b2(velocity));
+ }
+ body->SetAngularVelocity(platform->rotate_speed);
+ }
+ state->setting_move_p2 = false;
+ state->furthest_ball_x_pos = 0;
+ state->stuck_time = 0;
+ state->total_time = 0;
+ state->time_residue = 0;
+}
+
+static float setup_score(State *state, Setup *setup) {
+ setup_use(state, setup);
+ setup_reset(state);
+ Ball *ball = &state->ball;
+ float starting_line = platforms_starting_line(setup->platforms, setup->nplatforms);
+ while (ball->body) {
+ simulate_time(state, 0.1f);
+ }
+ setup->score = ball->pos.x - starting_line;
+ return setup->score;
+}
+
+static void setup_write_to_file(Setup *setup, FILE *fp) {
+ u32 nplatforms = setup->nplatforms;
+ fwrite_u32(fp, nplatforms);
+ for (u32 i = 0; i < nplatforms; ++i) {
+ platform_write_to_file(&setup->platforms[i], fp);
+ }
+}
diff --git a/sim.cpp b/sim.cpp
index c47c9d9..e8bce95 100644
--- a/sim.cpp
+++ b/sim.cpp
@@ -1,3 +1,4 @@
+// @TODO: test read/write setups
#include "gui.hpp"
#ifdef _WIN32
#include <windows.h>
@@ -39,41 +40,19 @@ static v2 b2_to_gl(State const *state, v2 box2d_coordinates) {
#include "shaders.cpp"
#include "platforms.cpp"
-// render the ball
-static void ball_render(State *state) {
- GL *gl = &state->gl;
- Ball *ball = &state->ball;
- float ball_x = ball->pos.x, ball_y = ball->pos.y;
- float ball_r = ball->radius;
- ShaderBall *shader = &state->shader_ball;
-
- shader_start_using(gl, &shader->base);
-
- gl->UniformMatrix4fv(shader->uniform_transform, 1, GL_FALSE, state->transform.e);
- gl->Uniform2f(shader->uniform_center, ball_x, ball_y);
- gl->Uniform1f(shader->uniform_radius, ball_r);
-
- glBegin(GL_QUADS);
- glColor3f(1,1,1);
- glVertex2f(ball_x-ball_r, ball_y-ball_r);
- glVertex2f(ball_x-ball_r, ball_y+ball_r);
- glVertex2f(ball_x+ball_r, ball_y+ball_r);
- glVertex2f(ball_x+ball_r, ball_y-ball_r);
- glEnd();
- shader_stop_using(gl);
-}
-
static void simulate_time(State *state, float dt) {
+ Ball *ball = &state->ball;
+ if (!ball->body) return; // we're done simulating
float time_step = 0.01f; // fixed time step
dt += state->time_residue;
while (dt >= time_step) {
- Ball *ball = &state->ball;
b2World *world = state->world;
world->Step(time_step, 8, 3); // step using recommended parameters
- if (ball->body) {
+ { // update ball
state->stuck_time += time_step;
+ state->total_time += time_step;
b2Vec2 ball_pos = ball->body->GetPosition();
bool reached_bottom = ball_pos.y - ball->radius < state->bottom_y; // ball reached bottom line
@@ -88,9 +67,12 @@ static void simulate_time(State *state, float dt) {
}
if (stuck)
state->stuck_time = max_stuck_time;
+ return; // done simulating
} else {
ball->pos = b2_to_v2(ball_pos);
- if (ball->pos.x > state->furthest_ball_x_pos) {
+ float rounded_pos = 0.01f * roundf(ball->pos.x * 100);
+ float rounded_record = 0.01f * roundf(state->furthest_ball_x_pos * 100);
+ if (rounded_pos > rounded_record) { // only update record if centimeter reading will change
state->furthest_ball_x_pos = ball->pos.x;
state->stuck_time = 0;
}
@@ -137,6 +119,32 @@ static void simulate_time(State *state, float dt) {
state->time_residue = dt;
}
+// render the ball
+static void ball_render(State *state) {
+ GL *gl = &state->gl;
+ Ball *ball = &state->ball;
+ float ball_x = ball->pos.x, ball_y = ball->pos.y;
+ float ball_r = ball->radius;
+ ShaderBall *shader = &state->shader_ball;
+
+ shader_start_using(gl, &shader->base);
+
+ gl->UniformMatrix4fv(shader->uniform_transform, 1, GL_FALSE, state->transform.e);
+ gl->Uniform2f(shader->uniform_center, ball_x, ball_y);
+ gl->Uniform1f(shader->uniform_radius, ball_r);
+
+ glBegin(GL_QUADS);
+ glColor3f(1,1,1);
+ glVertex2f(ball_x-ball_r, ball_y-ball_r);
+ glVertex2f(ball_x-ball_r, ball_y+ball_r);
+ glVertex2f(ball_x+ball_r, ball_y+ball_r);
+ glVertex2f(ball_x+ball_r, ball_y-ball_r);
+ glEnd();
+ shader_stop_using(gl);
+}
+
+#include "setup.cpp"
+
static void correct_mouse_button(State *state, u8 *button) {
if (*button == MOUSE_LEFT) {
if (state->shift) {
@@ -149,44 +157,6 @@ static void correct_mouse_button(State *state, u8 *button) {
}
}
-static void setup_reset(State *state) {
- { // reset ball
- Ball *ball = &state->ball;
- b2World *world = state->world;
- if (ball->body)
- world->DestroyBody(ball->body);
-
-
- ball->radius = 0.3f;
- ball->pos = V2(BALL_STARTING_X, 10.0f);
-
- // create ball
- b2BodyDef ball_def;
- ball_def.type = b2_dynamicBody;
- ball_def.position.Set(ball->pos.x, ball->pos.y);
- b2Body *ball_body = ball->body = world->CreateBody(&ball_def);
-
- b2CircleShape ball_shape;
- ball_shape.m_radius = ball->radius;
-
- b2FixtureDef ball_fixture;
- ball_fixture.shape = &ball_shape;
- ball_fixture.density = 1.0f;
- ball_fixture.friction = 0.3f;
- ball_fixture.restitution = 0.6f; // bounciness
-
- ball_body->CreateFixture(&ball_fixture);
-
- }
- for (Platform *p = state->platforms, *end = p + state->nplatforms; p != end; ++p) { // reset platforms
- p->angle = p->start_angle;
- if (p->moves) p->center = p->move_p1;
- p->body->SetTransform(v2_to_b2(p->center), p->angle);
- }
- state->setting_move_p2 = false;
- state->furthest_ball_x_pos = 0;
- state->stuck_time = 0;
-}
#ifdef __cplusplus
extern "C"
@@ -310,17 +280,12 @@ void sim_frame(Frame *frame) {
left_wall_body->CreateFixture(&left_wall_shape, 0);
- { // initialize platforms
- #if 0
- Platform *p = &state->platforms[0];
- p->start_angle = 0;
- p->radius = 0.5f;
- p->center = V2(1.5f, 1.5f);
- p->color = 0xFF00FFFF;
- platform_make_body(state, p);
- state->nplatforms = (u32)(p - state->platforms + 1);
- #endif
+ for (size_t i = 0; i < arr_count(state->generation); ++i) {
+ setup_random(state, &state->generation[i], 50);
+ printf("%f \n",setup_score(state, &state->generation[i]));
+ }
+ {
Platform *b = &state->platform_building;
b->radius = 1.5f;
b->color = 0xFF00FF7F;
@@ -345,6 +310,25 @@ void sim_frame(Frame *frame) {
shaders_reload_if_necessary(state);
#endif
+
+ Font *font = &state->font;
+ Font *small_font = &state->small_font;
+ Platform *mouse_platform = platform_at_mouse_pos(state);
+
+ if (state->simulating) {
+ // simulate physics
+ float dt = state->dt;
+ if (dt > 100) dt = 100; // prevent floating-point problems for very large dt's
+ simulate_time(state, dt);
+ if (keys_pressed[KEY_SPACE]) {
+ state->building = true;
+ state->simulating = false;
+ keys_pressed[KEY_SPACE] = 0;
+ setup_reset(state);
+ }
+ }
+
+
{
float half_height = 10.0f;
float half_width = half_height * state->win_width / state->win_height;
@@ -369,23 +353,6 @@ void sim_frame(Frame *frame) {
state->mouse_pos = v3_xy(m4_mul_v3(state->inv_transform, mouse_gl_coords));
}
- Font *font = &state->font;
- Font *small_font = &state->small_font;
- Platform *mouse_platform = platform_at_mouse_pos(state);
-
- if (state->simulating) {
- // simulate physics
- float dt = state->dt;
- if (dt > 100) dt = 100; // prevent floating-point problems for very large dt's
- simulate_time(state, dt);
- if (keys_pressed[KEY_SPACE]) {
- state->building = true;
- state->simulating = false;
- keys_pressed[KEY_SPACE] = 0;
- setup_reset(state);
- }
- }
-
if (state->building) {
Platform *platform_building = &state->platform_building;
@@ -480,9 +447,12 @@ void sim_frame(Frame *frame) {
platform_building->move_speed += speed_change_amount;
}
- platform_building->rotate_speed = clampf(platform_building->rotate_speed, -3, +3);
- platform_building->move_speed = clampf(platform_building->move_speed, 0.1f, 5.0f);
- platform_building->radius = clampf(platform_building->radius, 0.2f, 5.0f);
+ platform_building->rotate_speed = clampf(platform_building->rotate_speed,
+ PLATFORM_ROTATE_SPEED_MIN, PLATFORM_ROTATE_SPEED_MAX);
+ platform_building->move_speed = clampf(platform_building->move_speed,
+ PLATFORM_MOVE_SPEED_MIN, PLATFORM_MOVE_SPEED_MAX);
+ platform_building->radius = clampf(platform_building->radius,
+ PLATFORM_RADIUS_MIN, PLATFORM_RADIUS_MAX);
platform_building->angle = fmodf(platform_building->angle, TAUf);
for (u32 i = 0; i < input->nmouse_presses; ++i) {
@@ -502,7 +472,7 @@ void sim_frame(Frame *frame) {
Platform *p = &state->platforms[state->nplatforms++];
*p = *platform_building;
p->color |= 0xFF; // set alpha to 255
- platform_make_body(state, p);
+ platform_make_body(state, p, state->nplatforms - 1);
state->setting_move_p2 = false;
platform_building->moves = false;
}
@@ -631,6 +601,12 @@ void sim_frame(Frame *frame) {
pos.x = 1 - size.x;
pos.y += size.y * 1.5f;
text_render(state, small_font, text, pos);
+ // total time
+ snprintf(text, sizeof text - 1, "Total time: %.1fs", state->total_time);
+ size = text_get_size(state, small_font, text);
+ pos.x = 1 - size.x;
+ pos.y += size.y * 1.5f;
+ text_render(state, small_font, text, pos);
}
#if DEBUG
diff --git a/sim.hpp b/sim.hpp
index 3f6c025..d55b2f4 100644
--- a/sim.hpp
+++ b/sim.hpp
@@ -128,12 +128,14 @@ typedef struct {
typedef struct {
b2Body *body;
+
+ v2 center;
+ float radius; // half of the width of the platform
+
// save the starting position and rotation of the platform so we
// can restore it to reset the setup
float start_angle;
- v2 center;
- float radius; // half of the width of the platform
float angle;
bool moves; // does this platform move?
@@ -162,6 +164,13 @@ typedef struct {
// indicator that this Box2D fixture is a platform
#define USER_DATA_PLATFORM (USER_DATA_TYPE_PLATFORM << USER_DATA_TYPE_SHIFT)
+#define MAX_PLATFORMS 32
+typedef struct {
+ float score; // distance this setup can throw the ball
+ u32 nplatforms;
+ Platform platforms[MAX_PLATFORMS];
+} Setup;
+
typedef struct {
bool initialized;
@@ -193,6 +202,7 @@ typedef struct {
Ball ball;
float furthest_ball_x_pos; // furthest distance the ball has reached
float stuck_time; // amount of time furthest_ball_x_pos hasn't changed for
+ float total_time; // amount of time the simulation has been running for
float bottom_y; // y-position of "floor" (if y goes below here, it's over)
float left_x; // y-position of left wall
@@ -203,12 +213,14 @@ typedef struct {
Font small_font;
Platform platform_building; // the platform the user is currently placing
-
float platform_thickness;
+
u32 nplatforms;
-#define MAX_PLATFORMS 1000
Platform platforms[MAX_PLATFORMS];
+#define GENERATION_SIZE 100
+ Setup generation[GENERATION_SIZE];
+
u32 tmp_mem_used; // this is not measured in bytes, but in MaxAligns
#define TMP_MEM_BYTES (4L<<20)
MaxAlign tmp_mem[TMP_MEM_BYTES / sizeof(MaxAlign)];
diff --git a/util.cpp b/util.cpp
index cb37336..1c3d9e4 100644
--- a/util.cpp
+++ b/util.cpp
@@ -173,3 +173,43 @@ static int qsort_stricmp(const void *av, const void *bv) {
#endif
}
+static void fwrite_bool(FILE *fp, bool x) {
+ fwrite(&x, sizeof x, 1, fp);
+}
+
+static void fwrite_u32(FILE *fp, u32 x) {
+ fwrite(&x, sizeof x, 1, fp);
+}
+
+static void fwrite_float(FILE *fp, float x) {
+ fwrite(&x, sizeof x, 1, fp);
+}
+
+static void fwrite_v2(FILE *fp, v2 v) {
+ fwrite(&v, sizeof v, 1, fp);
+}
+
+static void fread_bool(FILE *fp) {
+ bool x;
+ fread(&x, sizeof x, 1, fp);
+ return x;
+}
+
+static void fread_u32(FILE *fp) {
+ u32 x;
+ fread(&x, sizeof x, 1, fp);
+ return x;
+}
+
+static void fread_float(FILE *fp) {
+ float x;
+ fread(&x, sizeof x, 1, fp);
+ return x;
+}
+
+static void fread_v2(FILE *fp) {
+ v2 v;
+ fread(&v, sizeof v, 1, fp);
+ return v;
+}
+