summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--README.md9
-rw-r--r--gui.hpp10
-rw-r--r--main.cpp29
-rw-r--r--sim.cpp91
-rw-r--r--sim.hpp12
6 files changed, 147 insertions, 8 deletions
diff --git a/Makefile b/Makefile
index 304acaf..79eac2d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
-WARNINGS=-Wall -Wextra -Wshadow -Wconversion -Wpedantic -pedantic -std=gnu++11 -Wno-unused-function -Wno-fixed-enum-extension -Wimplicit-fallthrough
-LIBS=-ldl `pkg-config --libs --cflags box2d sdl2 gl`
+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
obj/debug: physics obj/sim.so obj
touch obj/debug
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..47c1441
--- /dev/null
+++ b/README.md
@@ -0,0 +1,9 @@
+To install box2d:
+```bash
+git clone https://github.com/erincatto/box2d/
+cd box2d
+mkdir -p build
+cd build
+cmake -DBOX2D_BUILD_TESTBED=False ..
+sudo make -j8 install
+```
diff --git a/gui.hpp b/gui.hpp
index f40c361..0c09e22 100644
--- a/gui.hpp
+++ b/gui.hpp
@@ -33,9 +33,10 @@ enum {
};
typedef u16 Key;
-#define MOUSE_LEFT 0
-#define MOUSE_MIDDLE 1
-#define MOUSE_RIGHT 2
+#define MOUSE_OTHER 0
+#define MOUSE_LEFT 1
+#define MOUSE_MIDDLE 2
+#define MOUSE_RIGHT 3
typedef struct {
u8 button;
@@ -51,6 +52,9 @@ typedef struct {
u16 nmouse_presses;
#define MAX_MOUSE_PRESSES_PER_FRAME 256
MousePress mouse_presses[MAX_MOUSE_PRESSES_PER_FRAME];
+ u16 nmouse_releases;
+#define MAX_MOUSE_RELEASES_PER_FRAME MAX_MOUSE_PRESSES_PER_FRAME
+ MousePress mouse_releases[MAX_MOUSE_RELEASES_PER_FRAME];
i32 mouse_x, mouse_y; // (+y = down)
bool shift, ctrl;
diff --git a/main.cpp b/main.cpp
index 7fe4994..25c037d 100644
--- a/main.cpp
+++ b/main.cpp
@@ -267,6 +267,35 @@ int main(void) {
Key key = keycode_to_key(event.key.keysym.sym);
++input->keys_released[key];
} break;
+ case SDL_MOUSEBUTTONDOWN:
+ case SDL_MOUSEBUTTONUP: {
+ int x = event.button.x, y = event.button.y;
+ u8 button = 0;
+ switch (event.button.button) {
+ case SDL_BUTTON_LEFT:
+ button = MOUSE_LEFT;
+ break;
+ case SDL_BUTTON_MIDDLE:
+ button = MOUSE_MIDDLE;
+ break;
+ case SDL_BUTTON_RIGHT:
+ button = MOUSE_RIGHT;
+ break;
+ }
+ MousePress *press = NULL;
+ if (event.type == SDL_MOUSEBUTTONDOWN) {
+ if (input->nmouse_presses < MAX_MOUSE_PRESSES_PER_FRAME)
+ press = &input->mouse_presses[input->nmouse_presses++];
+ } else {
+ if (input->nmouse_releases < MAX_MOUSE_RELEASES_PER_FRAME)
+ press = &input->mouse_releases[input->nmouse_releases++];
+ }
+ if (press) {
+ press->button = button;
+ press->x = x;
+ press->y = y;
+ }
+ } break;
case SDL_QUIT:
input->closed = true;
break;
diff --git a/sim.cpp b/sim.cpp
index 70a2830..4ea76c7 100644
--- a/sim.cpp
+++ b/sim.cpp
@@ -229,6 +229,18 @@ static void ball_render(State *state) {
shader_stop_using(gl);
}
+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) {
@@ -253,6 +265,7 @@ static void platform_make_body(State *state, Platform *platform) {
b2FixtureDef fixture;
fixture.shape = &shape;
fixture.friction = 0.8f;
+ fixture.userData.pointer = platform_to_user_data(state, platform);
body->CreateFixture(&fixture);
if (platform->moves) {
@@ -267,6 +280,32 @@ static void platform_make_body(State *state, Platform *platform) {
platform->body = body;
}
+class PlatformQueryCallback : public b2QueryCallback {
+public:
+ PlatformQueryCallback(State *state_) {
+ 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
+ }
+ Platform *platform = NULL;
+ State *state = NULL;
+};
+
+static Platform *platform_at_mouse_pos(State *state) {
+ v2 mouse_pos = state->mouse_pos;
+ v2 mouse_radius = V2(0.3f, 0.3f); // you don't have to hover exactly over a platform to select it. this is the tolerance.
+ v2 a = v2_sub(mouse_pos, mouse_radius);
+ v2 b = v2_add(mouse_pos, mouse_radius);
+ PlatformQueryCallback callback(state);
+ b2AABB aabb;
+ aabb.lowerBound = v2_to_b2(a);
+ aabb.upperBound = v2_to_b2(b);
+ state->world->QueryAABB(&callback, aabb);
+ return callback.platform;
+}
+
static void simulate_time(State *state, float dt) {
float time_step = 0.01f; // fixed time step
dt += state->time_residue;
@@ -328,6 +367,25 @@ static void simulate_time(State *state, float dt) {
state->time_residue = dt;
}
+static void platform_delete(State *state, u32 index) {
+ Platform *platforms = state->platforms;
+ u32 nplatforms = state->nplatforms;
+
+ state->world->DestroyBody(platforms[index].body);
+
+ if (index+1 < nplatforms) {
+ // 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]);
+ } else {
+ // platform is at end of array; don't need to do anything special
+ memset(&platforms[index], 0, sizeof(Platform));
+ }
+ --state->nplatforms;
+
+}
+
#ifdef __cplusplus
extern "C"
#endif
@@ -506,6 +564,7 @@ void sim_frame(Frame *frame) {
}
Font *font = &state->font;
+ Platform *mouse_platform = platform_at_mouse_pos(state);
if (state->simulating) {
// simulate physics
@@ -534,12 +593,42 @@ void sim_frame(Frame *frame) {
platform_building->size = clampf(platform_building->size, 0.3f, 10.0f);
platform_building->angle = fmodf(platform_building->angle, TAUf);
+
+ for (u32 i = 0; i < input->nmouse_presses; ++i) {
+ if (input->mouse_presses[i].button == MOUSE_LEFT) {
+ if (mouse_platform) {
+ // click to delete platform
+ platform_delete(state, (u32)(mouse_platform - state->platforms));
+ } else {
+ // left-click to build platform
+ if (state->nplatforms < MAX_PLATFORMS) {
+ Platform *p = &state->platforms[state->nplatforms++];
+ *p = *platform_building;
+ p->color |= 0xFF; // set alpha to 255
+ platform_make_body(state, p);
+ }
+ }
+ }
+ }
+
+ if (keys_pressed[KEY_SPACE]) {
+ state->building = false;
+ state->simulating = true;
+ }
}
+ u32 prev_mouse_platform_color = mouse_platform ? mouse_platform->color : 0;
+ if (state->building) {
+ // turn platform under mouse red (if user clicks, it will be deleted)
+ if (mouse_platform) mouse_platform->color = 0xFF0000FF;
+ }
platforms_render(state, state->platforms, state->nplatforms);
if (state->building) {
- platforms_render(state, &state->platform_building, 1);
+ if (mouse_platform)
+ mouse_platform->color = prev_mouse_platform_color;
+ else
+ platforms_render(state, &state->platform_building, 1);
}
ball_render(state);
diff --git a/sim.hpp b/sim.hpp
index dcc32fb..7cfbe59 100644
--- a/sim.hpp
+++ b/sim.hpp
@@ -4,7 +4,7 @@
#if _WIN32
#include <box2d.h>
#else
-#include <Box2D/Box2D.h>
+#include <box2d/box2d.h>
#endif
#define STBTT_STATIC
@@ -150,6 +150,13 @@ typedef struct {
b2Body *body;
} Ball;
+#define USER_DATA_TYPE_SHIFT 12
+#define USER_DATA_TYPE (((uintptr_t)-1) << USER_DATA_TYPE_SHIFT)
+#define USER_DATA_INDEX (~USER_DATA_TYPE)
+#define USER_DATA_TYPE_PLATFORM ((uintptr_t)0x1)
+// indicator that this Box2D fixture is a platform
+#define USER_DATA_PLATFORM (USER_DATA_TYPE_PLATFORM << USER_DATA_TYPE_SHIFT)
+
typedef struct {
bool initialized;
@@ -185,7 +192,8 @@ typedef struct {
float platform_thickness;
u32 nplatforms;
- Platform platforms[1000];
+#define MAX_PLATFORMS 1000
+ Platform platforms[MAX_PLATFORMS];
u32 tmp_mem_used; // this is not measured in bytes, but in MaxAligns
#define TMP_MEM_BYTES (4L<<20)