diff options
Diffstat (limited to '2d/rigidbody/rigidbody_1/main.cpp')
-rw-r--r-- | 2d/rigidbody/rigidbody_1/main.cpp | 113 |
1 files changed, 109 insertions, 4 deletions
diff --git a/2d/rigidbody/rigidbody_1/main.cpp b/2d/rigidbody/rigidbody_1/main.cpp index 26d24e2..8d4ab0e 100644 --- a/2d/rigidbody/rigidbody_1/main.cpp +++ b/2d/rigidbody/rigidbody_1/main.cpp @@ -43,6 +43,8 @@ struct Rigidbody { struct Rectangle { OrthographicShape shape; Rigidbody body; + Vector2 originalPoints[4]; + Vector2 transformedPoints[4]; void load(OrthographicRenderer* renderer, Vector4 color, float32 width, float32 height) { color = color.toNormalizedColor(); @@ -62,6 +64,11 @@ struct Rectangle { vertices[i].color = color; } + originalPoints[0] = vertices[0].position; + originalPoints[1] = vertices[1].position; + originalPoints[2] = vertices[2].position; + originalPoints[3] = vertices[4].position; + shape.load(vertices, 6, renderer); body.reset(); } @@ -69,6 +76,54 @@ struct Rectangle { void update(float32 dtSeconds) { body.update(dtSeconds); shape.model = Mat4x4().translateByVec2(body.position); + + // Note: This helps us check if the cursor is within the bounds of the + // rectangle later on. + for (int idx = 0; idx < 4; idx++) { + transformedPoints[idx] = shape.model * originalPoints[idx]; + } + } + + void render(OrthographicRenderer* renderer) { + shape.render(renderer); + } + + void unload() { + shape.unload(); + } +}; + +struct Circle { + OrthographicShape shape; + Rigidbody body; + + float32 radius = 5.f; + + void load(OrthographicRenderer* renderer, Vector4 color) { + const int32 numSegments = 36; + const float32 radiansPerSegment = (2.f * PI) / static_cast<float>(numSegments); + const int32 numVertices = numSegments * 3; + + color = color.toNormalizedColor(); + + OrthographicVertex vertices[numSegments * 3]; + for (int idx = 0; idx < numSegments; idx++) { + int vIdx = idx * 3; + + vertices[vIdx].color = color; + vertices[vIdx].position = Vector2 { radius * cosf(radiansPerSegment * idx), radius * sinf(radiansPerSegment * idx) }; + vertices[vIdx + 1].color = color; + vertices[vIdx + 1].position = Vector2 { 0.f, 0.f }; + vertices[vIdx + 2].color = color; + vertices[vIdx + 2].position = Vector2 { radius * cosf(radiansPerSegment * (idx + 1)), radius * sinf(radiansPerSegment * (idx + 1)) }; + } + + shape.load(vertices, numVertices, renderer); + body.reset(); + } + + void update(float32 dtSeconds) { + shape.model = Mat4x4().translateByVec2(body.position); } void render(OrthographicRenderer* renderer) { @@ -82,6 +137,7 @@ struct Rectangle { EM_BOOL onPlayClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData); EM_BOOL onStopClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData); +EM_BOOL onMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData); void load(); void update(float32 time, void* userData); @@ -91,11 +147,15 @@ WebglContext context; OrthographicRenderer renderer; MainLoop mainLoop; Rectangle rectangle; +Circle pointer; +bool isIntersectingPointer = false; int main() { context.init("#gl_canvas"); emscripten_set_click_callback("#gl_canvas_play", NULL, false, onPlayClicked); emscripten_set_click_callback("#gl_canvas_stop", NULL, false, onStopClicked); + emscripten_set_mousemove_callback("#gl_canvas", NULL, false, onMouseMove); + return 0; } @@ -106,11 +166,40 @@ void load() { rectangle.body.position = Vector2 { context.width / 3.f, context.height / 3.f }; rectangle.body.velocity = Vector2 { 100.f, 250.f }; + pointer.load(&renderer, Vector4 { 25.f, 235.f, 235.f, 255.f }); + mainLoop.run(update); } +bool isPointInRectangle(Vector2 p, Rectangle r) { + // https://math.stackexchange.com/a/190373 + Vector2 A = r.transformedPoints[0]; + Vector2 B = r.transformedPoints[1]; + Vector2 D = r.transformedPoints[3]; + + float32 amDotAb = (p - A).dot(B - A); + float32 abDotAb = (B - A).dot(B - A); + + float32 amDotAd = (p - A).dot(D - A); + float32 aDDotAd = (D - A).dot(D - A); + + return amDotAb > 0 && amDotAb < abDotAb && amDotAd > 0 && amDotAd < aDDotAd; + +} + void update(float32 deltaTimeSeconds, void* userData) { rectangle.update(deltaTimeSeconds); + pointer.update(deltaTimeSeconds); + + if (isPointInRectangle(pointer.body.position, rectangle)) { + if (!isIntersectingPointer) { + isIntersectingPointer = true; + rectangle.body.force += pointer.body.force; + } + } else if (isIntersectingPointer) { + isIntersectingPointer = false; + } + // Check collisions with walls so we don't go out of the scene. Simply reflect here. if (rectangle.body.position.x <= 0.f) { @@ -121,24 +210,26 @@ void update(float32 deltaTimeSeconds, void* userData) { rectangle.body.position.y = 0.f; rectangle.body.velocity = rectangle.body.velocity - Vector2 { 0.f, 1.f } * (2 * (rectangle.body.velocity.dot(Vector2 { 0.f, 1.f }))); } - if (rectangle.body.position.x >= 640.f) { - rectangle.body.position.x = 640.f; + if (rectangle.body.position.x >= 800.f) { + rectangle.body.position.x = 800.f; rectangle.body.velocity = rectangle.body.velocity - Vector2 { -1.f, 0.f } * (2 * (rectangle.body.velocity.dot(Vector2{ -1.f, 0.f }))); } - if (rectangle.body.position.y >= 480.f) { - rectangle.body.position.y = 480.f; + if (rectangle.body.position.y >= 600.f) { + rectangle.body.position.y = 600.f; rectangle.body.velocity = rectangle.body.velocity - Vector2 { 0.f, -1.f } * (2 * (rectangle.body.velocity.dot(Vector2 { 0.f, -1.f }))) ; } // Renderer renderer.render(); rectangle.render(&renderer); + pointer.render(&renderer); } void unload() { mainLoop.stop(); renderer.unload(); rectangle.unload(); + pointer.unload(); } // @@ -156,3 +247,17 @@ EM_BOOL onStopClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, voi unload(); return true; } + +EM_BOOL onMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) { + if (!mainLoop.isRunning) { + return true; + } + + pointer.body.force.x = static_cast<float32>(mouseEvent->movementX) * 1000.f; + pointer.body.force.y = static_cast<float32>(-mouseEvent->movementY) * 1000.f; + + pointer.body.position.x = static_cast<float32>(mouseEvent->targetX); + pointer.body.position.y = static_cast<float32>(600.f - mouseEvent->targetY); + + return true; +} |