From cfe41fdfebe0913eeac99f8ac78ec52d5e00cc84 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Wed, 9 Dec 2020 18:20:00 -0500 Subject: moving platforms in editor --- math.cpp | 9 +++++ sim.cpp | 139 +++++++++++++++++++++++++++++++++++++++++++++------------------ sim.hpp | 2 +- 3 files changed, 110 insertions(+), 40 deletions(-) diff --git a/math.cpp b/math.cpp index 060eb0d..534438a 100644 --- a/math.cpp +++ b/math.cpp @@ -155,6 +155,15 @@ static v2 v2_lerp(float x, v2 a, v2 b) { return V2(lerpf(x, a.x, b.x), lerpf(x, a.y, b.y)); } +// rotate v theta radians counterclockwise +static v2 v2_rotate(v2 v, float theta) { + float c = cosf(theta), s = sinf(theta); + return V2( + c * v.x - s * v.y, + s * v.x + c * v.y + ); +} + static v2 v2_normalize(v2 v) { float len = v2_len(v); float mul = len == 0.0f ? 1.0f : 1.0f/len; diff --git a/sim.cpp b/sim.cpp index 843b331..94a41db 100644 --- a/sim.cpp +++ b/sim.cpp @@ -166,12 +166,17 @@ static void shaders_reload_if_necessary(State *state) { } #endif +// converts Box2D coordinates to GL coordinates +static v2 b2_to_gl(State const *state, v2 box2d_coordinates) { + v3 v = m4_mul_v3(state->transform, v3_from_v2(box2d_coordinates)); + return V2(v.x, v.y); +} + // render the given platforms static void platforms_render(State *state, Platform *platforms, u32 nplatforms) { GL *gl = &state->gl; ShaderPlatform *shader = &state->shader_platform; float platform_render_thickness = state->platform_thickness; - m4 transform = state->transform; shader_start_using(gl, &shader->base); @@ -208,39 +213,70 @@ static void platforms_render(State *state, Platform *platforms, u32 nplatforms) if (state->building) { // show arrows for platforms + glBegin(GL_LINES); for (Platform *platform = platforms, *end = platform + nplatforms; platform != end; ++platform) { gl_rgbacolor(platform->color); if (platform->rotates) { float speed = platform->rotate_speed; float angle = speed * 0.5f; if (angle) { + // draw arc-shaped arrow to show rotation float theta1 = HALF_PIf; float theta2 = theta1 + angle; float dtheta = 0.03f * sgnf(angle); float radius = platform->size; - glBegin(GL_LINE_STRIP); + v2 last_point; for (float theta = theta1; angle > 0 ? (theta < theta2) : (theta > theta2); theta += dtheta) { - v3 point = v3_from_v2(v2_add(platform->center, v2_polar(radius, theta))); - point = m4_mul_v3(transform, point); - v3_gl_vertex(point); + v2 point = b2_to_gl(state, v2_add(platform->center, v2_polar(radius, theta))); + if (theta != theta1) { + v2_gl_vertex(last_point); + v2_gl_vertex(point); + } + last_point = point; } - glEnd(); - - v3 p1 = v3_from_v2(v2_add(platform->center, v2_polar(radius-0.2f, theta2-0.1f * sgnf(angle)))); - v3 p2 = v3_from_v2(v2_add(platform->center, v2_polar(radius, theta2))); - v3 p3 = v3_from_v2(v2_add(platform->center, v2_polar(radius+0.2f, theta2-0.1f * sgnf(angle)))); - - p1 = m4_mul_v3(transform, p1); - p2 = m4_mul_v3(transform, p2); - p3 = m4_mul_v3(transform, p3); - glBegin(GL_LINE_STRIP); - v3_gl_vertex(p1); - v3_gl_vertex(p2); - v3_gl_vertex(p3); - glEnd(); + + v2 p1 = b2_to_gl(state, v2_add(platform->center, v2_polar(radius-0.2f, theta2-0.1f * sgnf(angle)))); + v2 p2 = b2_to_gl(state, v2_add(platform->center, v2_polar(radius, theta2))); + v2 p3 = b2_to_gl(state, v2_add(platform->center, v2_polar(radius+0.2f, theta2-0.1f * sgnf(angle)))); + + v2_gl_vertex(p1); v2_gl_vertex(p2); + v2_gl_vertex(p2); v2_gl_vertex(p3); } } + + if (platform->moves) { + // draw double-headed arrow to show back & forth motion + v2 p1 = platform->move_p1; + v2 p2 = platform->move_p2; + v2 p2_to_p1 = v2_scale(v2_normalize(v2_sub(p1, p2)), platform->move_speed * 0.5f); + v2 p1_to_p2 = v2_scale(p2_to_p1, -1); + v2 arrowhead_a1 = v2_add(p1, v2_rotate(p1_to_p2, +0.5f)); + v2 arrowhead_b1 = v2_add(p1, v2_rotate(p1_to_p2, -0.5f)); + v2 arrowhead_a2 = v2_add(p2, v2_rotate(p2_to_p1, +0.5f)); + v2 arrowhead_b2 = v2_add(p2, v2_rotate(p2_to_p1, -0.5f)); + + v2 p1_gl = b2_to_gl(state, p1); + v2 p2_gl = b2_to_gl(state, p2); + v2 aa1_gl = b2_to_gl(state, arrowhead_a1); + v2 ab1_gl = b2_to_gl(state, arrowhead_b1); + v2 aa2_gl = b2_to_gl(state, arrowhead_a2); + v2 ab2_gl = b2_to_gl(state, arrowhead_b2); + + v2_gl_vertex(p1_gl); + v2_gl_vertex(p2_gl); + + v2_gl_vertex(aa1_gl); + v2_gl_vertex(p1_gl); + v2_gl_vertex(p1_gl); + v2_gl_vertex(ab1_gl); + + v2_gl_vertex(aa2_gl); + v2_gl_vertex(p2_gl); + v2_gl_vertex(p2_gl); + v2_gl_vertex(ab2_gl); + } } + glEnd(); } } @@ -467,10 +503,11 @@ static void setup_reset(State *state) { ball_body->CreateFixture(&ball_fixture); } for (Platform *p = state->platforms, *end = p + state->nplatforms; p != end; ++p) { // reset platforms - p->center = p->start_center; 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; } #ifdef __cplusplus @@ -595,9 +632,9 @@ void sim_frame(Frame *frame) { { // initialize platforms Platform *p = &state->platforms[0]; - p->start_center = V2(-1.0f, 5.0f); p->start_angle = 0; p->size = 1.0f; + p->center = V2(1.5f, 1.5f); p->color = 0xFF00FFFF; platform_make_body(state, p); state->nplatforms = (u32)(p - state->platforms + 1); @@ -662,7 +699,35 @@ void sim_frame(Frame *frame) { if (state->building) { Platform *platform_building = &state->platform_building; - platform_building->center = state->mouse_pos; + + if (keys_pressed[KEY_R]) { + // toggle rotating platform + bool rotates = platform_building->rotates = !platform_building->rotates; + if (rotates) { + if (platform_building->rotate_speed == 0) { + platform_building->rotate_speed = 1; + } + } else { + platform_building->rotate_speed = 0; + } + } + + if (keys_pressed[KEY_M]) { + // toggle moving platform + bool moves = platform_building->moves = !platform_building->moves; + if (moves) { + platform_building->move_p1 = platform_building->center; + platform_building->move_speed = 1.0f; + state->setting_move_p2 = true; + } + } + + if (state->setting_move_p2) { + platform_building->move_p2 = state->mouse_pos; + } else { + platform_building->center = state->mouse_pos; + platform_building->move_p1 = platform_building->center; + } float dt = state->dt; float rotate_amount = 2.0f * dt; float size_change_amount = 4.0f * dt; @@ -689,44 +754,40 @@ void sim_frame(Frame *frame) { platform_building->rotate_speed -= rotate_change_amount; } + if (platform_building->moves) { + // change move speed + float speed_change_amount = 2.0f * dt; + if (keys_down[KEY_A]) + platform_building->move_speed -= speed_change_amount; + if (keys_down[KEY_D]) + 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->size = clampf(platform_building->size, 0.3f, 10.0f); platform_building->angle = fmodf(platform_building->angle, TAUf); - if (keys_pressed[KEY_R]) { - // toggle rotating platform - bool rotates = platform_building->rotates = !platform_building->rotates; - if (rotates) { - if (platform_building->rotate_speed == 0) { - platform_building->rotate_speed = 1; - } - } else { - platform_building->rotate_speed = 0; - } - } - - if (keys_pressed[KEY_M]) { - // toggle moving platform - } - for (u32 i = 0; i < input->nmouse_presses; ++i) { MousePress *press = &input->mouse_presses[i]; u8 button = press->button; if (button == MOUSE_LEFT) { if (mouse_platform) { + // edit platform *platform_building = *mouse_platform; platform_delete(state, mouse_platform); platform_building->color = (platform_building->color & 0xFFFFFF00) | 0x7F; } else { // left-click to build platform if (state->nplatforms < MAX_PLATFORMS) { - platform_building->start_center = platform_building->center; platform_building->start_angle = platform_building->angle; Platform *p = &state->platforms[state->nplatforms++]; *p = *platform_building; p->color |= 0xFF; // set alpha to 255 platform_make_body(state, p); + state->setting_move_p2 = false; + platform_building->moves = false; } } } else if (button == MOUSE_RIGHT) { diff --git a/sim.hpp b/sim.hpp index a6591d3..bbcc6e8 100644 --- a/sim.hpp +++ b/sim.hpp @@ -130,7 +130,6 @@ typedef struct { // save the starting position and rotation of the platform so we // can restore it to reset the setup - v2 start_center; float start_angle; v2 center; @@ -185,6 +184,7 @@ typedef struct { ShaderBall shader_ball; bool building; // is the user building a setup? + bool setting_move_p2; // is the user setting the move_p2 of the platform they're placing? bool simulating; // are we simulating the world's physics? b2World *world; // Box2D world -- cgit v1.2.3