diff --git a/.gitignore b/.gitignore index fd919169..52aaf06a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ interiors -*.hl *.js *.js.map *.tmp diff --git a/marblegame.hl b/marblegame.hl new file mode 100644 index 00000000..cdd915a7 Binary files /dev/null and b/marblegame.hl differ diff --git a/src/Marble.hx b/src/Marble.hx index 8c727a45..a8971a78 100644 --- a/src/Marble.hx +++ b/src/Marble.hx @@ -204,8 +204,11 @@ class Marble extends GameObject { this.rollSound = AudioManager.playSound(ResourceLoader.getAudio("data/sound/rolling_hard.wav"), this.getAbsPos().getPosition(), true); this.slipSound = AudioManager.playSound(ResourceLoader.getAudio("data/sound/sliding.wav"), this.getAbsPos().getPosition(), true); this.shockabsorberSound = AudioManager.playSound(ResourceLoader.getAudio("data/sound/superbounceactive.wav"), null, true); + this.shockabsorberSound.pause = true; this.superbounceSound = AudioManager.playSound(ResourceLoader.getAudio("data/sound/forcefield.wav"), null, true); + this.superbounceSound.pause = true; this.helicopterSound = AudioManager.playSound(ResourceLoader.getAudio("data/sound/use_gyrocopter.wav"), null, true); + this.helicopterSound.pause = true; } public function init(level:MarbleWorld) { @@ -364,7 +367,7 @@ class Marble extends GameObject { } function velocityCancel(currentTime:Float, dt:Float, surfaceSlide:Bool, noBounce:Bool, stoppedPaths:Bool, pi:Array) { - var SurfaceDotThreshold = 0.001; + var SurfaceDotThreshold = 0.0001; var looped = false; var itersIn = 0; var done:Bool; @@ -480,29 +483,14 @@ class Marble extends GameObject { dir.normalize(); var soFar = 0.0; for (k in 0...contacts.length) { - if (contacts[k].contactDistance < this._radius) { - var timeToSeparate = 0.1; - var dist = contacts[k].contactDistance; // contacts[k].penetration; - if (dist >= 0) { - var flag1 = this.velocity.sub(contacts[k].velocity).add(dir.multiply(soFar)).dot(contacts[k].normal) * timeToSeparate; - if (flag1 < dist) { - var flag2 = (dist - flag1) / timeToSeparate; - soFar += flag2 / contacts[k].normal.dot(dir); - } + var dist = this._radius - contacts[k].contactDistance; + if (dist >= 0) { + var f1 = this.velocity.sub(contacts[k].velocity).add(dir.multiply(soFar)).dot(contacts[k].normal); + var f2 = 0.016 * f1; + if (f2 < dist) { + var f3 = (dist - f2) / 0.016; + soFar += f3 / contacts[k].normal.dot(dir); } - - // var normal = contacts[k].normal; - // var unk = normal.multiply(soFar); - // var tickle = this.velocity.sub(contacts[k].velocity); - // var plop = unk.add(tickle); - // var outVel = plop.dot(normal); - // var cancan = timeToSeparate * outVel; - - // if (dist > cancan) { - // var bla = contacts[k].normal; - // var bFac = (dist - cancan) / timeToSeparate; - // soFar += bFac / bla.dot(dir); - // } } } if (soFar < -25) @@ -731,7 +719,15 @@ class Marble extends GameObject { invMatrix.invert(); var localpos = position.clone(); localpos.transform(invMatrix); - var surfaces = obj.octree.radiusSearch(localpos, radius * 1.1); + + var relLocalVel = velocity.sub(obj.velocity); + relLocalVel.transform3x3(invMatrix); + + var boundThing = new Bounds(); + boundThing.addSpherePos(localpos.x, localpos.y, localpos.z, radius * 1.1); + boundThing.addSpherePos(localpos.x + relLocalVel.x * dt, localpos.y + relLocalVel.y * dt, localpos.z + relLocalVel.z * dt, radius * 1.1); + + var surfaces = obj.octree.boundingSearch(boundThing); var tform = obj.transform.clone(); @@ -753,20 +749,22 @@ class Marble extends GameObject { var surfacenormal = surface.normals[surface.indices[i]].transformed3x3(obj.transform); - var closest = Collision.IntersectTriangleCapsule(position, position.add(relVelocity.multiply(dt)), _radius, v0, v, v2, surfacenormal); + // var closest = Collision.IntersectTriangleCapsule(position, position.add(relVelocity.multiply(dt)), _radius, v0, v, v2, surfacenormal); // var closest = Collision.IntersectTriangleSphere(v0, v, v2, surfacenormal, position, radius); - if (closest != null) { - var t = (-position.dot(surfacenormal) - v0.dot(surfacenormal)) / relVelocity.dot(surfacenormal); + // if (closest != null) { + // This is some ballpark approximation, very bruh + var radiusDir = relVelocity.normalized().multiply(radius); + var t = (-position.add(radiusDir).dot(surfacenormal) + v0.dot(surfacenormal)) / relVelocity.dot(surfacenormal); - var pt = position.add(relVelocity.multiply(t)); + var pt = position.add(radiusDir).add(relVelocity.multiply(t)); - if (Collision.PointInTriangle(pt, v0, v, v2)) { - if (t > 0 && t < intersectT) { - intersectT = t; - } + if (Collision.PointInTriangle(pt, v0, v, v2)) { + if (t > 0 && t < intersectT) { + intersectT = t; } } + // } i += 3; } @@ -792,6 +790,7 @@ class Marble extends GameObject { if (this.controllable) { for (interior in pathedInteriors) { // interior.popTickState(); + // interior.pushTickState(); interior.setStopped(false); // interior.recomputeVelocity(piTime + 0.032, 0.032); // interior.update(piTime, timeStep); @@ -806,8 +805,8 @@ class Marble extends GameObject { if (timeRemaining <= 0) break; - var timeStep = 0.002; - if (timeRemaining < 0.002) + var timeStep = 0.008; + if (timeRemaining < 0.008) timeStep = timeRemaining; var tempState = timeState.clone(); @@ -816,7 +815,9 @@ class Marble extends GameObject { if (this.controllable) { for (interior in pathedInteriors) { interior.pushTickState(); - interior.recomputeVelocity(piTime + 0.032, 0.032); + var l1 = interior.velocity.length(); + interior.recomputeVelocity(piTime + timeStep * 2, timeStep * 2); + var l2 = interior.velocity.length(); } } diff --git a/src/collision/Collision.hx b/src/collision/Collision.hx index d51f085c..ddab67a7 100644 --- a/src/collision/Collision.hx +++ b/src/collision/Collision.hx @@ -43,6 +43,18 @@ class Collision { return p; } + public static function ClosestPointLine(start:Vector, end:Vector, center:Vector) { + var d = end.sub(start); + var v = center.sub(start); + var t = v.dot(d) / d.lengthSq(); + if (t < 0) + t = 0; + if (t > 1) + t = 1; + var p = start.add(d.multiply(t)); + return p; + } + public static function IntersectTriangleSphere(v0:Vector, v1:Vector, v2:Vector, normal:Vector, center:Vector, radius:Float) { var radiusSq = radius * radius; @@ -52,6 +64,9 @@ class Collision { normal: null }; + var pnorm = v1.sub(v0).cross(v2.sub(v0)).normalized(); + var d = -v0.dot(normal); + var p = PlaneF.PointNormal(new Point3F(v0.x, v0.y, v0.z), new Point3F(normal.x, normal.y, normal.z)); var pdist = p.distance(new Point3F(center.x, center.y, center.z)); @@ -59,29 +74,6 @@ class Collision { return res; // Dont collide internal edges } - // Check edges - var r1 = IntersectLineSphere(v0, v1, center, radius); - if (r1 != null) { - res.result = true; - res.point = r1; - res.normal = center.sub(r1).normalized(); - return res; - } - var r2 = IntersectLineSphere(v1, v2, center, radius); - if (r2 != null) { - res.result = true; - res.point = r2; - res.normal = center.sub(r2).normalized(); - return res; - } - var r3 = IntersectLineSphere(v2, v0, center, radius); - if (r3 != null) { - res.result = true; - res.point = r3; - res.normal = center.sub(r3).normalized(); - return res; - } - if (pdist < radius) { var n = normal.normalized(); var t = center.dot(n) - v0.dot(n); @@ -97,6 +89,50 @@ class Collision { // return res; } + // Check edges + + var r1 = ClosestPointLine(v0, v1, center); + var r2 = ClosestPointLine(v1, v2, center); + var r3 = ClosestPointLine(v2, v0, center); + + var chosenPt:Vector; + if (r1.distanceSq(center) < r2.distanceSq(center)) + chosenPt = r1; + else + chosenPt = r2; + if (chosenPt.distanceSq(center) < r3.distanceSq(center)) + res.point = chosenPt; + else + res.point = r3; + + if (res.point.distanceSq(center) <= radiusSq) { + res.result = true; + res.normal = center.sub(res.point).normalized(); + return res; + } + + // var r1 = IntersectLineSphere(v0, v1, center, radius); + // if (r1 != null) { + // res.result = true; + // res.point = r1; + // res.normal = center.sub(r1).normalized(); + // return res; + // } + // var r2 = IntersectLineSphere(v1, v2, center, radius); + // if (r2 != null) { + // res.result = true; + // res.point = r2; + // res.normal = center.sub(r2).normalized(); + // return res; + // } + // var r3 = IntersectLineSphere(v2, v0, center, radius); + // if (r3 != null) { + // res.result = true; + // res.point = r3; + // res.normal = center.sub(r3).normalized(); + // return res; + // } + // Check points // if (center.sub(v0).lengthSq() < radiusSq) { // res.result = true; diff --git a/src/collision/CollisionEntity.hx b/src/collision/CollisionEntity.hx index 4a814ec5..fbb875a1 100644 --- a/src/collision/CollisionEntity.hx +++ b/src/collision/CollisionEntity.hx @@ -141,11 +141,11 @@ class CollisionEntity implements IOctreeObject { bestDot = testDot; var cinfo = new CollisionInfo(); - cinfo.normal = normal; // surface.normals[surface.indices[i]]; + cinfo.normal = normal; cinfo.point = closest; // cinfo.collider = this; cinfo.velocity = this.velocity.clone(); - cinfo.contactDistance = radius - closest.distance(position); + cinfo.contactDistance = closest.distance(position); cinfo.otherObject = this.go; // cinfo.penetration = radius - (position.sub(closest).dot(normal)); cinfo.restitution = surface.restitution;