From ccc6dc1335ed6f767800037541fcdb0be899867a Mon Sep 17 00:00:00 2001 From: Catalin Constantin Mititiuc Date: Sat, 24 Jan 2026 12:57:06 -0800 Subject: [PATCH] WIP: bounce off corners --- README.md | 1 - html/images/space.svg | 150 +++++++++++++++++++++++------------------- 2 files changed, 81 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index c5cb64d..0b21069 100644 --- a/README.md +++ b/README.md @@ -122,5 +122,4 @@ Delete your `.sitegen_cache` file. -- -- Bounce off corners algo - Bounce off multiple simultaneous contacts diff --git a/html/images/space.svg b/html/images/space.svg index 43e8544..5ddd650 100644 --- a/html/images/space.svg +++ b/html/images/space.svg @@ -127,11 +127,12 @@ + + - @@ -476,6 +477,59 @@ const Move = (() => { return [...edgeColl, ...cornerColl]; } + function vector(x, y) { + const vector = { x: x, y: y }; + vector.magnitude = Math.sqrt(x**2+y**2); + vector.dx = vector.x / vector.magnitude; + vector.dy = vector.y / vector.magnitude; + vector.rightNormal = { x: vector.y, y: -vector.x }; + vector.rightNormal.dx = vector.rightNormal.x / vector.magnitude; + vector.rightNormal.dy = vector.rightNormal.y / vector.magnitude; + + return vector; + } + + function bounceVector(v, run, rise) { + const vec1 = vector(v.x, v.y); + const vec2 = vector(run, rise); + + // From https://stackoverflow.com/a/14886099 + + // 1. Find the dot product of vec1 and vec2 + // Note: dx and dy are vx and vy divided over the length of the vector (magnitude) + // var dpA:Number = vec1.vx * vec2.dx + vec1.vy * vec2.dy; + const dpA = vec1.x * vec2.dx + vec1.y * vec2.dy; + + // 2. Project vec1 over vec2 + // var prA_vx:Number = dpA * vec2.dx; + const prAvx = dpA * vec2.dx; + // var prA_vy:Number = dpA * vec2.dy; + const prAvy = dpA * vec2.dy; + + // 3. Find the dot product of vec1 and vec2's normal + // (left or right normal depending on line's direction, let's say left) + // vec.leftNormal --> vx = vec.vy; vy = -vec.vx; + // vec.rightNormal --> vx = -vec.vy; vy = vec.vx; + // var dpB:Number = vec1.vx * vec2.leftNormal.dx + vec1.vy * vec2.leftNormal.dy; + const dpB = vec1.x * vec2.rightNormal.dx + vec1.y * vec2.rightNormal.dy; + + // 4. Project vec1 over vec2's left normal + // var prB_vx:Number = dpB * vec2.leftNormal.dx; + const prBvx = dpB * vec2.rightNormal.dx; + // var prB_vy:Number = dpB * vec2.leftNormal.dy; + const prBvy = dpB * vec2.rightNormal.dy; + + // 5. Add the first projection prA to the reverse of the second -prB + // var new_vx:Number = prA_vx - prB_vx; + // var new_vy:Number = prA_vy - prB_vy; + return { + x: prAvx - prBvx, + y: prAvy - prBvy, + vec1, + vec2 + }; + } + return { update: ({ entity_id }, elapsed) => { const { x: px, y: py } = Position[entity_id]; @@ -496,88 +550,46 @@ const Move = (() => { if (contacts.length !== 0) { console.log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + console.log("CONTACTS", contacts); let posP; const contact = contacts[0]; if (contact.corner) { - Velocity[entity_id] = { x: 0, y: 0 }; + contact.position = cornerContactPosition(p.x, p.y, px, py, contact.corner, s.radius); + console.log("contact position", contact.position); + drawLine(contact.position.x, contact.position.y, contact.position.x + vx, contact.position.y + vy, "blue"); + + const contactV = { x: contact.position.y - contact.corner.y, y: contact.position.x - contact.corner.x }; + console.log("contactV", contactV); + const normalVect = { x: contact.position.x - contact.corner.x, y: contact.position.y - contact.corner.y }; + console.log("normal vector", normalVect); + drawLine(contact.corner.x, contact.corner.y, contact.corner.x + normalVect.x, contact.corner.y + normalVect.y, "black"); + + const tangentVect = { x: normalVect.y, y: -normalVect.x }; + drawLine(contact.position.x, contact.position.y, contact.position.x + tangentVect.x, contact.position.y + tangentVect.y, "green"); + contact.velocity = bounceVector(v, tangentVect.x, tangentVect.y); + + console.log("tangent vector", tangentVect); + + drawLine(contact.position.x, contact.position.y, contact.position.x + contact.velocity.x, contact.position.y + contact.velocity.y, "blue"); + + // Velocity[entity_id] = { x: 0, y: 0 }; + Velocity[entity_id] = contact.velocity; Position[entity_id] = cornerContactPosition(p.x, p.y, px, py, contact.corner, s.radius); } else if (contact.edge) { // if (isLandable(contact.edge) && s.gearDown) s.isLanded = true; - const isHorizontal = contact.edge.ya === contact.edge.yb; - const isVertical = contact.edge.xa === contact.edge.xb; - - console.log("CURRENT POSITION", px, py); - console.log("INTENDED POSITION", p.x, p.y); - console.log("CONTACT POSITION", contact.position); + // console.log("CURRENT POSITION", px, py); + // console.log("INTENDED POSITION", p.x, p.y); + // console.log("CONTACT POSITION", contact.position); const rise = contact.edge.yb-contact.edge.ya; const run = contact.edge.xb-contact.edge.xa; drawLine(p.x - v.x, p.y - v.y, p.x, p.y, "blue"); // velocity vector - console.log("velocity vector", v.x, v.y); const det = v.x * rise - v.y * run; - console.log("DEEEEEEEETTTTTTTTTTTTTTT", det); drawLine(contact.edge.xa, contact.edge.ya, contact.edge.xb, contact.edge.yb, "green"); // edge vector - let newY; - let newX; - - function vector(x, y) { - const vector = { x: x, y: y }; - vector.magnitude = Math.sqrt(x**2+y**2); - vector.dx = vector.x / vector.magnitude; - vector.dy = vector.y / vector.magnitude; - vector.rightNormal = { x: vector.y, y: -vector.x }; - vector.rightNormal.dx = vector.rightNormal.x / vector.magnitude; - vector.rightNormal.dy = vector.rightNormal.y / vector.magnitude; - - return vector; - } - - - function bounceVector(v, run, rise) { - const vec1 = vector(v.x, v.y); - const vec2 = vector(run, rise); - - // From https://stackoverflow.com/a/14886099 - - // 1. Find the dot product of vec1 and vec2 - // Note: dx and dy are vx and vy divided over the length of the vector (magnitude) - // var dpA:Number = vec1.vx * vec2.dx + vec1.vy * vec2.dy; - const dpA = vec1.x * vec2.dx + vec1.y * vec2.dy; - - // 2. Project vec1 over vec2 - // var prA_vx:Number = dpA * vec2.dx; - const prAvx = dpA * vec2.dx; - // var prA_vy:Number = dpA * vec2.dy; - const prAvy = dpA * vec2.dy; - - // 3. Find the dot product of vec1 and vec2's normal - // (left or right normal depending on line's direction, let's say left) - // vec.leftNormal --> vx = vec.vy; vy = -vec.vx; - // vec.rightNormal --> vx = -vec.vy; vy = vec.vx; - // var dpB:Number = vec1.vx * vec2.leftNormal.dx + vec1.vy * vec2.leftNormal.dy; - const dpB = vec1.x * vec2.rightNormal.dx + vec1.y * vec2.rightNormal.dy; - - // 4. Project vec1 over vec2's left normal - // var prB_vx:Number = dpB * vec2.leftNormal.dx; - const prBvx = dpB * vec2.rightNormal.dx; - // var prB_vy:Number = dpB * vec2.leftNormal.dy; - const prBvy = dpB * vec2.rightNormal.dy; - - // 5. Add the first projection prA to the reverse of the second -prB - // var new_vx:Number = prA_vx - prB_vx; - // var new_vy:Number = prA_vy - prB_vy; - return { - x: prAvx - prBvx, - y: prAvy - prBvy, - vec1, - vec2 - }; - } - // contact.velocity = { x: prAvx - prBvx, y: prAvy - prBvy }; contact.velocity = bounceVector(v, run, rise); @@ -685,7 +697,7 @@ function init() { s.position = { x: 0, y: -10 }; // s.velocity = { x: 0, y: -10 }; // s.velocity = { x: 10, y: 20 }; - s.velocity = { x: 0, y: 0 }; + s.velocity = { x: 5, y: 0 }; s.angularVelocity = 0; // s. velocity = { x: -5*mult, y: 7*mult }; @@ -986,7 +998,7 @@ function drawLine(xa, ya, xb, yb, color = "black") { arrow.setAttribute('cx', xb); arrow.setAttribute('cy', yb); arrow.setAttribute('r', 1); - arrow.setAttribute('fill', 'teal'); + arrow.setAttribute('fill', color); svg.appendChild(arrow); svg.appendChild(el);