From 59389c5ea5f7c7081150bcbce034de0ec5096796 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Mon, 7 Jun 2021 23:25:36 +0530 Subject: [PATCH] Add GravMod --- src/CameraController.hx | 55 ++++++++++++++++++++++++++++--- src/Main.hx | 8 +++-- src/Marble.hx | 13 ++++---- src/MarbleWorld.hx | 68 +++++++++++++++++++++++++++++++++++++-- src/shapes/AntiGravity.hx | 10 ++++-- src/shapes/SuperJump.hx | 2 +- src/shapes/SuperSpeed.hx | 2 +- src/shapes/TimeTravel.hx | 20 ++++++++++++ 8 files changed, 158 insertions(+), 20 deletions(-) create mode 100644 src/shapes/TimeTravel.hx diff --git a/src/CameraController.hx b/src/CameraController.hx index 9b0388ec..d18ce0f1 100644 --- a/src/CameraController.hx +++ b/src/CameraController.hx @@ -1,5 +1,6 @@ package src; +import h3d.Quat; import sdl.Cursor; import sdl.Sdl; import hxd.Window; @@ -92,17 +93,61 @@ class CameraController extends Object { CameraPitch = 0.001; } - public function update(dt:Float) { + public function update(currentTime:Float, dt:Float) { + // camera.position.set(marblePosition.x, marblePosition.y, marblePosition.z).sub(directionVector.clone().multiplyScalar(2.5)); + // this.level.scene.camera.target = marblePosition.add(cameraVerticalTranslation); + // camera.position.add(cameraVerticalTranslation); var camera = level.scene.camera; + function getRotQuat(v1:Vector, v2:Vector) { + function orthogonal(v:Vector) { + var x = Math.abs(v.x); + var y = Math.abs(v.y); + var z = Math.abs(v.z); + var other = x < y ? (x < z ? new Vector(1, 0, 0) : new Vector(0, 0, 1)) : (y < z ? new Vector(0, 1, 0) : new Vector(0, 0, 1)); + return v.cross(other); + } + + var u = v1.normalized(); + var v = v2.normalized(); + if (u.multiply(-1).equals(v)) { + var q = new Quat(); + var o = orthogonal(u).normalized(); + q.x = o.x; + q.y = o.y; + q.z = o.z; + q.w = 0; + return q; + } + var half = u.add(v).normalized(); + var q = new Quat(); + q.w = u.dot(half); + var vr = u.cross(half); + q.x = vr.x; + q.y = vr.y; + q.z = vr.z; + return q; + } + + var orientationQuat = level.getOrientationQuat(currentTime); + + var up = new Vector(0, 0, 1); + up.transform(orientationQuat.toMatrix()); + camera.up = up; + var upVec = new Vector(0, 0, 1); + var quat = getRotQuat(upVec, up); + var x = CameraDistance * Math.sin(CameraPitch) * Math.cos(CameraYaw); var y = CameraDistance * Math.sin(CameraPitch) * Math.sin(CameraYaw); var z = CameraDistance * Math.cos(CameraPitch); + var directionVec = new Vector(x, y, z); + directionVec.transform(orientationQuat.toMatrix()); + var targetpos = this.marble.getAbsPos().getPosition(); - this.x = targetpos.x + x; - this.y = targetpos.y + y; - this.z = targetpos.z + z; - camera.follow = {pos: this, target: this.marble}; + this.x = targetpos.x + directionVec.x; + this.y = targetpos.y + directionVec.y; + this.z = targetpos.z + directionVec.z; + this.level.scene.camera.follow = {pos: this, target: this.marble}; } } diff --git a/src/Main.hx b/src/Main.hx index 5cae616d..b474e54e 100644 --- a/src/Main.hx +++ b/src/Main.hx @@ -44,10 +44,10 @@ class Main extends hxd.App { world = new MarbleWorld(s3d); var db = new InteriorObject(); - db.interiorFile = "data/interiors/beginner/training_friction.dif"; + db.interiorFile = "data/interiors/beginner/beginner_finish.dif"; world.addInterior(db); var tform = db.getTransform(); - tform.setPosition(new Vector(0, 0, 7.5)); + tform.setPosition(new Vector(0, 0, 0)); db.setTransform(tform); // var pi = new PathedInterior(); @@ -112,6 +112,10 @@ class Main extends hxd.App { world.addDtsObject(he); sj.setTransform(sj.getTransform()); + var ag = new AntiGravity(); + ag.y = 6; + world.addDtsObject(ag); + // for (i in 0...10) { // for (j in 0...10) { // var trapdoor = new Tornado(); diff --git a/src/Marble.hx b/src/Marble.hx index 83d95fc7..34c9c535 100644 --- a/src/Marble.hx +++ b/src/Marble.hx @@ -48,8 +48,6 @@ class Marble extends GameObject { public var level:MarbleWorld; - public var gravityDir:Vector = new Vector(0, 0, -1); - public var _radius = 0.2; var _maxRollVelocity = 15; @@ -146,7 +144,8 @@ class Marble extends GameObject { var zrot = new Matrix(); zrot.initRotationZ(this.camera.CameraYaw); cammat.multiply(xrot, zrot); - var updir = gravityDir.multiply(-1); + cammat.multiply(cammat, this.level.newOrientationQuat.toMatrix()); + var updir = this.level.currentUp; var motiondir = new Vector(cammat._21, cammat._22, cammat._23); var sidedir = motiondir.cross(updir); @@ -156,7 +155,7 @@ class Marble extends GameObject { } function getExternalForces(currentTime:Float, m:Move, dt:Float) { - var gWorkGravityDir = gravityDir; + var gWorkGravityDir = this.level.currentUp.multiply(-1); var A = gWorkGravityDir.multiply(this._gravity); if (currentTime - this.helicopterEnableTime < 5) { A = A.multiply(0.25); @@ -210,7 +209,7 @@ class Marble extends GameObject { function computeMoveForces(m:Move) { var aControl = new Vector(); var desiredOmega = new Vector(); - var currentGravityDir = gravityDir; + var currentGravityDir = this.level.currentUp.multiply(-1); var R = currentGravityDir.multiply(-this._radius); var rollVelocity = this.omega.cross(R); var axes = this.getMarbleAxis(); @@ -388,7 +387,7 @@ class Marble extends GameObject { function applyContactForces(dt:Float, m:Move, isCentered:Bool, aControl:Vector, desiredOmega:Vector, A:Vector) { var a = new Vector(); this._slipAmount = 0; - var gWorkGravityDir = new Vector(0, 0, -1); + var gWorkGravityDir = this.level.currentUp.multiply(-1); var bestSurface = -1; var bestNormalForce = 0.0; for (i in 0...contacts.length) { @@ -669,7 +668,7 @@ class Marble extends GameObject { advancePhysics(currentTime, dt, move, collisionWorld, pathedInteriors); if (this.controllable) { - this.camera.update(dt); + this.camera.update(currentTime, dt); } updatePowerupStates(currentTime, dt); diff --git a/src/MarbleWorld.hx b/src/MarbleWorld.hx index 663a595a..b108210a 100644 --- a/src/MarbleWorld.hx +++ b/src/MarbleWorld.hx @@ -1,5 +1,7 @@ package src; +import src.Util; +import h3d.Quat; import shapes.PowerUp; import collision.SphereCollisionEntity; import src.Sky; @@ -34,6 +36,14 @@ class MarbleWorld { public var scene:Scene; public var marble:Marble; + public var worldOrientation:Quat; + public var currentUp = new Vector(0, 0, 1); + + var orientationChangeTime = -1e8; + var oldOrientationQuat = new Quat(); + + /** The new target camera orientation quat */ + public var newOrientationQuat = new Quat(); public function new(scene:Scene) { this.collisionWorld = new CollisionWorld(); @@ -122,7 +132,7 @@ class MarbleWorld { if (contact.go is DtsObject) { var shape:DtsObject = cast contact.go; - var contacttest = shape.colliders.map(x -> x.sphereIntersection(contactsphere, 0)); + var contacttest = shape.colliders.filter(x -> x != null).map(x -> x.sphereIntersection(contactsphere, 0)); var contactlist:Array = []; for (l in contacttest) { contactlist = contactlist.concat(l); @@ -155,7 +165,7 @@ class MarbleWorld { } public function pickUpPowerUp(powerUp:PowerUp) { - if (this.marble.heldPowerup != null) + if (this.marble.heldPowerup == powerUp) return false; this.marble.heldPowerup = powerUp; // for (let overlayShape @@ -175,4 +185,58 @@ class MarbleWorld { // AudioManager.play(powerUp.sounds[0]); return true; } + + /** Get the current interpolated orientation quaternion. */ + public function getOrientationQuat(time:Float) { + var completion = Util.clamp((time - this.orientationChangeTime) / 0.3, 0, 1); + var q = this.oldOrientationQuat.clone(); + q.slerp(q, this.newOrientationQuat, completion); + return q; + } + + public function setUp(vec:Vector, time:Float) { + this.currentUp = vec; + var currentQuat = this.getOrientationQuat(time); + var oldUp = new Vector(0, 0, 1); + oldUp.transform(currentQuat.toMatrix()); + + function getRotQuat(v1:Vector, v2:Vector) { + function orthogonal(v:Vector) { + var x = Math.abs(v.x); + var y = Math.abs(v.y); + var z = Math.abs(v.z); + var other = x < y ? (x < z ? new Vector(1, 0, 0) : new Vector(0, 0, 1)) : (y < z ? new Vector(0, 1, 0) : new Vector(0, 0, 1)); + return v.cross(other); + } + + var u = v1.normalized(); + var v = v2.normalized(); + if (u.multiply(-1).equals(v)) { + var q = new Quat(); + var o = orthogonal(u).normalized(); + q.x = o.x; + q.y = o.y; + q.z = o.z; + q.w = 0; + return q; + } + var half = u.add(v).normalized(); + var q = new Quat(); + q.w = u.dot(half); + var vr = u.cross(half); + q.x = vr.x; + q.y = vr.y; + q.z = vr.z; + return q; + } + + var quatChange = getRotQuat(oldUp, vec); + // Instead of calculating the new quat from nothing, calculate it from the last one to guarantee the shortest possible rotation. + // quatChange.initMoveTo(oldUp, vec); + quatChange.multiply(quatChange, currentQuat); + + this.newOrientationQuat = quatChange; + this.oldOrientationQuat = currentQuat; + this.orientationChangeTime = time; + } } diff --git a/src/shapes/AntiGravity.hx b/src/shapes/AntiGravity.hx index 888bcb2c..bb03ebef 100644 --- a/src/shapes/AntiGravity.hx +++ b/src/shapes/AntiGravity.hx @@ -1,5 +1,6 @@ package shapes; +import h3d.Vector; import src.DtsObject; class AntiGravity extends PowerUp { @@ -9,14 +10,19 @@ class AntiGravity extends PowerUp { this.isCollideable = false; this.isTSStatic = false; this.identifier = "AntiGravity"; + this.autoUse = true; } public function pickUp():Bool { - return this.level.pickUpPowerUp(this); + var direction = new Vector(0, 0, -1); + direction.transform(this.getRotationQuat().toMatrix()); + return !direction.equals(this.level.currentUp); } public function use(time:Float) { - var marble = this.level.marble; + var direction = new Vector(0, 0, -1); + direction.transform(this.getRotationQuat().toMatrix()); + this.level.setUp(direction, time); // marble.body.addLinearVelocity(this.level.currentUp.scale(20)); // Simply add to vertical velocity // if (!this.level.rewinding) // AudioManager.play(this.sounds[1]); diff --git a/src/shapes/SuperJump.hx b/src/shapes/SuperJump.hx index 4cafe508..475d6e73 100644 --- a/src/shapes/SuperJump.hx +++ b/src/shapes/SuperJump.hx @@ -17,7 +17,7 @@ class SuperJump extends PowerUp { public function use(time:Float) { var marble = this.level.marble; - marble.velocity = marble.velocity.add(marble.gravityDir.multiply(-20)); + marble.velocity = marble.velocity.add(this.level.currentUp.multiply(20)); // marble.body.addLinearVelocity(this.level.currentUp.scale(20)); // Simply add to vertical velocity // if (!this.level.rewinding) // AudioManager.play(this.sounds[1]); diff --git a/src/shapes/SuperSpeed.hx b/src/shapes/SuperSpeed.hx index 0aab72b2..fba09272 100644 --- a/src/shapes/SuperSpeed.hx +++ b/src/shapes/SuperSpeed.hx @@ -29,7 +29,7 @@ class SuperSpeed extends PowerUp { var quat2 = new Quat(); // Determine the necessary rotation to rotate the up vector to the contact normal. - quat2.initMoveTo(marble.gravityDir.multiply(-1), marble.lastContactNormal); + quat2.initMoveTo(this.level.currentUp, marble.lastContactNormal); movementVector.transform(quat2.toMatrix()); marble.velocity = marble.velocity.add(movementVector.multiply(-24.7)); diff --git a/src/shapes/TimeTravel.hx b/src/shapes/TimeTravel.hx new file mode 100644 index 00000000..f8f125cb --- /dev/null +++ b/src/shapes/TimeTravel.hx @@ -0,0 +1,20 @@ +class TimeTravel extends PowerUp { + var timeBonus:Float = 5; + + public function new() { + super(); + this.dtsPath = "data/shapes/items/timetravel.dts"; + this.isCollideable = false; + this.isTSStatic = false; + this.identifier = "TimeTravel"; + this.cooldownDuration = 1e8; + this.useInstancing = true; + this.autoUse = true; + } + + public function pickUp():Bool { + return true; + } + + public function use(time:Float) {} +}