From b20d084b46a3652018bb58e4970435b5ddac3050 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Thu, 10 Jun 2021 17:12:39 +0530 Subject: [PATCH] Add a lot of static shapes, fix some collision stuff --- src/DtsObject.hx | 61 ++++++++++++-------------- src/Main.hx | 29 ++++++++++++ src/Marble.hx | 5 ++- src/MarbleWorld.hx | 18 ++++++++ src/ResourceLoader.hx | 2 +- src/collision/CollisionEntity.hx | 3 ++ src/collision/CollisionHull.hx | 1 + src/collision/CollisionInfo.hx | 2 + src/collision/SphereCollisionEntity.hx | 1 + src/gui/PlayGui.hx | 29 +++++++++--- src/shapes/AntiGravity.hx | 1 + src/shapes/Helicopter.hx | 1 + src/shapes/Oilslick.hx | 14 ++++++ src/shapes/PowerUp.hx | 3 +- src/shapes/RoundBumper.hx | 12 +++++ src/shapes/ShockAbsorber.hx | 1 + src/shapes/StartPad.hx | 13 ++++++ src/shapes/SuperBounce.hx | 1 + src/shapes/SuperJump.hx | 1 + src/shapes/SuperSpeed.hx | 1 + src/shapes/TimeTravel.hx | 1 + src/shapes/Trapdoor.hx | 52 ++++++++++++++++++++++ src/shapes/TriangleBumper.hx | 12 +++++ 23 files changed, 224 insertions(+), 40 deletions(-) create mode 100644 src/shapes/Oilslick.hx create mode 100644 src/shapes/RoundBumper.hx create mode 100644 src/shapes/StartPad.hx create mode 100644 src/shapes/TriangleBumper.hx diff --git a/src/DtsObject.hx b/src/DtsObject.hx index 56109d06..66262d1e 100644 --- a/src/DtsObject.hx +++ b/src/DtsObject.hx @@ -202,8 +202,7 @@ class DtsObject extends GameObject { if (this.isCollideable) { for (i in 0...dts.nodes.length) { var objects = dts.objects.filter(object -> object.node == i); - var meshSurfaces = []; - var collider = new CollisionHull(cast this); + var localColliders:Array = []; for (object in objects) { var isCollisionObject = dts.names[object.name].substr(0, 3).toLowerCase() == "col"; @@ -220,17 +219,12 @@ class DtsObject extends GameObject { var vertices = mesh.vertices.map(v -> new Vector(v.x, v.y, v.z)); var vertexNormals = mesh.normals.map(v -> new Vector(v.x, v.y, v.z)); - var surfaces = this.generateCollisionGeometry(mesh, vertices, vertexNormals); - for (surface in surfaces) - collider.addSurface(surface); - meshSurfaces = meshSurfaces.concat(surfaces); + var hulls = this.generateCollisionGeometry(mesh, vertices, vertexNormals, i); + localColliders = localColliders.concat(hulls); } } } - if (meshSurfaces.length != 0) - colliders.push(collider); - else - colliders.push(null); + colliders = colliders.concat(localColliders); } } @@ -424,22 +418,24 @@ class DtsObject extends GameObject { } } - function generateCollisionGeometry(dtsMesh:dts.Mesh, vertices:Array, vertexNormals:Array) { - var surfaces = this.dts.matNames.map(x -> new CollisionSurface()); - for (surface in surfaces) { - surface.points = []; - surface.normals = []; - surface.indices = []; - } + function generateCollisionGeometry(dtsMesh:dts.Mesh, vertices:Array, vertexNormals:Array, node:Int) { + var hulls:Array = []; for (primitive in dtsMesh.primitives) { var k = 0; - var geometrydata = surfaces[primitive.matIndex]; + + var chull = new CollisionHull(cast this); + chull.userData = node; + var hs = new CollisionSurface(); + hs.points = []; + hs.normals = []; + hs.indices = []; + var material = this.dts.matNames[primitive.matIndex]; if (dtsMaterials.exists(material)) { var data = dtsMaterials.get(material); - geometrydata.friction = data.friction; - geometrydata.force = data.force; - geometrydata.restitution = data.restitution; + hs.friction = data.friction; + hs.force = data.force; + hs.restitution = data.restitution; } for (i in primitive.firstElement...(primitive.firstElement + primitive.numElements - 2)) { @@ -456,24 +452,25 @@ class DtsObject extends GameObject { for (index in [i1, i2, i3]) { var vertex = vertices[index]; - geometrydata.points.push(new Vector(vertex.x, vertex.y, vertex.z)); + hs.points.push(new Vector(vertex.x, vertex.y, vertex.z)); var normal = vertexNormals[index]; - geometrydata.normals.push(new Vector(normal.x, normal.y, normal.z)); + hs.normals.push(new Vector(normal.x, normal.y, normal.z)); } - geometrydata.indices.push(geometrydata.indices.length); - geometrydata.indices.push(geometrydata.indices.length); - geometrydata.indices.push(geometrydata.indices.length); + hs.indices.push(hs.indices.length); + hs.indices.push(hs.indices.length); + hs.indices.push(hs.indices.length); k++; } + + hs.generateBoundingBox(); + chull.addSurface(hs); + chull.generateBoundingBox(); + hulls.push(chull); } - for (surface in surfaces) { - surface.generateBoundingBox(); - // surface.generateNormals(); - } - return surfaces; + return hulls; } function generateMaterialGeometry(dtsMesh:dts.Mesh, vertices:Array, vertexNormals:Array) { @@ -773,7 +770,7 @@ class DtsObject extends GameObject { } for (i in 0...this.colliders.length) { - var absTform = this.graphNodes[i].getAbsPos().clone(); + var absTform = this.graphNodes[this.colliders[i].userData].getAbsPos().clone(); if (this.colliders[i] != null) this.colliders[i].setTransform(absTform); } diff --git a/src/Main.hx b/src/Main.hx index 697564c5..458438c4 100644 --- a/src/Main.hx +++ b/src/Main.hx @@ -1,5 +1,9 @@ package; +import shapes.StartPad; +import shapes.TriangleBumper; +import shapes.RoundBumper; +import shapes.Oilslick; import gui.PlayGui; import shapes.Helicopter; import shapes.ShockAbsorber; @@ -117,6 +121,31 @@ class Main extends hxd.App { ag.y = 6; world.addDtsObject(ag); + var os = new Oilslick(); + os.x = 5; + os.z = 0.1; + world.addDtsObject(os); + + var tdoor = new Trapdoor(); + tdoor.x = -5; + tdoor.z = 1; + world.addDtsObject(tdoor); + + var rb = new RoundBumper(); + rb.x = -5; + rb.y = 2; + world.addDtsObject(rb); + + var tb = new TriangleBumper(); + tb.x = -5; + tb.y = 4; + world.addDtsObject(tb); + + var spad = new StartPad(); + tb.x = 5; + tb.y = 3; + world.addDtsObject(spad); + // var le:ParticleEmitterOptions = { // ejectionPeriod: 0.01, diff --git a/src/Marble.hx b/src/Marble.hx index a0812d23..ad99f7c7 100644 --- a/src/Marble.hx +++ b/src/Marble.hx @@ -235,11 +235,14 @@ class Marble extends GameObject { var contactNormal = new Vector(); var forceObjectCount = 0; + var forceObjects = []; + for (contact in contacts) { - if (contact.force != 0) { + if (contact.force != 0 && !forceObjects.contains(contact.otherObject)) { forceObjectCount++; contactNormal = contactNormal.add(contact.normal); contactForce += contact.force; + forceObjects.push(contact.otherObject); } } diff --git a/src/MarbleWorld.hx b/src/MarbleWorld.hx index baaedb11..c9a1f9d4 100644 --- a/src/MarbleWorld.hx +++ b/src/MarbleWorld.hx @@ -47,6 +47,9 @@ class MarbleWorld extends Scheduler { public var currentUp = new Vector(0, 0, 1); public var outOfBounds:Bool = false; + var helpTextTimeState:Float = -1e8; + var alertTextTimeState:Float = -1e8; + var orientationChangeTime = -1e8; var oldOrientationQuat = new Quat(); @@ -182,6 +185,7 @@ class MarbleWorld extends Scheduler { if (this.marble != null) { callCollisionHandlers(marble); } + this.updateTexts(); } public function render(e:h3d.Engine) { @@ -202,6 +206,20 @@ class MarbleWorld extends Scheduler { playGui.formatTimer(this.elapsedTime); } + function updateTexts() { + var helpTextTime = this.helpTextTimeState; + var alertTextTime = this.alertTextTimeState; + var helpTextCompletion = Math.pow(Util.clamp((this.currentTime - helpTextTime - 3), 0, 1), 2); + var alertTextCompletion = Math.pow(Util.clamp((this.currentTime - alertTextTime - 3), 0, 1), 2); + this.playGui.setHelpTextOpacity(1 - helpTextCompletion); + this.playGui.setAlertTextOpacity(1 - alertTextCompletion); + } + + public function displayAlert(text:String) { + this.playGui.setAlertText(text); + this.alertTextTimeState = this.currentTime; + } + function callCollisionHandlers(marble:Marble) { var contacts = this.collisionWorld.radiusSearch(marble.getAbsPos().getPosition(), marble._radius); var newImmunity = []; diff --git a/src/ResourceLoader.hx b/src/ResourceLoader.hx index 95205c35..b4b66952 100644 --- a/src/ResourceLoader.hx +++ b/src/ResourceLoader.hx @@ -74,7 +74,7 @@ class ResourceLoader { public static function getFullNamesOf(path:String) { var files = fileSystem.dir(Path.directory(path)); // FileSystem.readDirectory(Path.directory(path)); var names = []; - var fname = Path.withoutExtension(Path.withoutDirectory(path)).toLowerCase(); + var fname = Path.withoutDirectory(path).toLowerCase(); for (file in files) { var fname2 = file.name; if (Path.withoutExtension(fname2).toLowerCase() == fname) diff --git a/src/collision/CollisionEntity.hx b/src/collision/CollisionEntity.hx index 95f4b7e2..c8bd5aa7 100644 --- a/src/collision/CollisionEntity.hx +++ b/src/collision/CollisionEntity.hx @@ -25,6 +25,8 @@ class CollisionEntity implements IOctreeObject { public var transform:Matrix; public var go:GameObject; + public var userData:Int; + public function new(go:GameObject) { this.go = go; this.octree = new Octree(); @@ -128,6 +130,7 @@ class CollisionEntity implements IOctreeObject { // cinfo.collider = this; cinfo.velocity = this.velocity; cinfo.contactDistance = closest.distance(position); + cinfo.otherObject = this.go; // cinfo.penetration = radius - (position.sub(closest).dot(normal)); cinfo.restitution = surface.restitution; cinfo.force = surface.force; diff --git a/src/collision/CollisionHull.hx b/src/collision/CollisionHull.hx index 9ab9686c..a6d36a9a 100644 --- a/src/collision/CollisionHull.hx +++ b/src/collision/CollisionHull.hx @@ -44,6 +44,7 @@ class CollisionHull extends CollisionEntity { cinfo.velocity = velocity; cinfo.contactDistance = sph.radius + pt.length(); cinfo.restitution = restitution; + cinfo.otherObject = this.go; cinfo.friction = friction; cinfo.force = force; this.go.onMarbleContact(dt, cinfo); diff --git a/src/collision/CollisionInfo.hx b/src/collision/CollisionInfo.hx index 65bffd17..7992608b 100644 --- a/src/collision/CollisionInfo.hx +++ b/src/collision/CollisionInfo.hx @@ -1,5 +1,6 @@ package collision; +import src.GameObject; import h3d.Vector; class CollisionInfo { @@ -7,6 +8,7 @@ class CollisionInfo { public var normal:Vector; public var velocity:Vector; public var collider:CollisionEntity; + public var otherObject:GameObject; public var friction:Float; public var vAtCMag:Float; public var normalForce:Float; diff --git a/src/collision/SphereCollisionEntity.hx b/src/collision/SphereCollisionEntity.hx index b82a098b..51664b69 100644 --- a/src/collision/SphereCollisionEntity.hx +++ b/src/collision/SphereCollisionEntity.hx @@ -48,6 +48,7 @@ class SphereCollisionEntity extends CollisionEntity { contact.friction = 1; contact.restitution = 1; contact.velocity = this.velocity; + contact.otherObject = this.go; contact.point = position.add(normDist); contact.normal = normDist.multiply(-1); contact.force = 0; diff --git a/src/gui/PlayGui.hx b/src/gui/PlayGui.hx index e1263b5e..43378e2f 100644 --- a/src/gui/PlayGui.hx +++ b/src/gui/PlayGui.hx @@ -151,7 +151,7 @@ class PlayGui { gemImageObject.dtsPath = "data/shapes/items/gem.dts"; gemImageObject.ambientRotate = true; gemImageObject.showSequences = false; - gemImageObject.matNameOverride.set("base.gem", "base.gem.png"); + // gemImageObject.matNameOverride.set("base.gem", "base.gem."); gemImageObject.ambientSpinFactor /= -2; // ["base.gem"] = color + ".gem"; gemImageObject.init(null); @@ -186,30 +186,49 @@ class PlayGui { var bfont = new BitmapFont(fontdata.entry); @:privateAccess bfont.loader = ResourceLoader.loader; helpTextBackground = new Text(bfont.toFont(), scene2d); - helpTextBackground.text = "Hello Bruh"; + helpTextBackground.text = "Bruh"; helpTextBackground.x = scene2d.width / 2 - helpTextBackground.textWidth / 2 + 1; helpTextBackground.y = scene2d.height * 0.45 + 1; helpTextBackground.textColor = 0x000000; helpTextForeground = new Text(bfont.toFont(), scene2d); - helpTextForeground.text = "Hello Bruh"; + helpTextForeground.text = "Bruh"; helpTextForeground.x = scene2d.width / 2 - helpTextForeground.textWidth / 2; helpTextForeground.y = scene2d.height * 0.45; helpTextForeground.textColor = 0xFFFFFF; alertTextBackground = new Text(bfont.toFont(), scene2d); - alertTextBackground.text = "Hello Bruh"; + alertTextBackground.text = "Bruh"; alertTextBackground.x = scene2d.width / 2 - alertTextBackground.textWidth / 2 + 1; alertTextBackground.y = scene2d.height - 102 + 1; alertTextBackground.textColor = 0x000000; alertTextForeground = new Text(bfont.toFont(), scene2d); - alertTextForeground.text = "Hello Bruh"; + alertTextForeground.text = "Bruh"; alertTextForeground.x = scene2d.width / 2 - alertTextForeground.textWidth / 2; alertTextForeground.y = scene2d.height - 102; alertTextForeground.textColor = 0xFFE240; } + public function setHelpTextOpacity(value:Float) { + helpTextForeground.color.a = value; + helpTextBackground.color.a = value; + } + + public function setAlertTextOpacity(value:Float) { + alertTextForeground.color.a = value; + alertTextBackground.color.a = value; + } + + public function setAlertText(text:String) { + this.alertTextForeground.text = text; + this.alertTextBackground.text = text; + alertTextForeground.x = scene2d.width / 2 - alertTextForeground.textWidth / 2; + alertTextForeground.y = scene2d.height - 102; + alertTextBackground.x = scene2d.width / 2 - alertTextBackground.textWidth / 2 + 1; + alertTextBackground.y = scene2d.height - 102 + 1; + } + public function setPowerupImage(powerupIdentifier:String) { this.powerupImageScene.removeChildren(); if (powerupIdentifier == "SuperJump") { diff --git a/src/shapes/AntiGravity.hx b/src/shapes/AntiGravity.hx index bb03ebef..7402a857 100644 --- a/src/shapes/AntiGravity.hx +++ b/src/shapes/AntiGravity.hx @@ -10,6 +10,7 @@ class AntiGravity extends PowerUp { this.isCollideable = false; this.isTSStatic = false; this.identifier = "AntiGravity"; + this.pickUpName = "Gravity Modifier"; this.autoUse = true; } diff --git a/src/shapes/Helicopter.hx b/src/shapes/Helicopter.hx index 62f57de0..7f8b9820 100644 --- a/src/shapes/Helicopter.hx +++ b/src/shapes/Helicopter.hx @@ -10,6 +10,7 @@ class Helicopter extends PowerUp { this.isTSStatic = false; this.showSequences = false; this.identifier = "Helicopter"; + this.pickUpName = "Gyrocopter PowerUp"; } public function pickUp():Bool { diff --git a/src/shapes/Oilslick.hx b/src/shapes/Oilslick.hx new file mode 100644 index 00000000..d8e4c222 --- /dev/null +++ b/src/shapes/Oilslick.hx @@ -0,0 +1,14 @@ +package shapes; + +import src.DtsObject; + +class Oilslick extends DtsObject { + public function new() { + super(); + this.dtsPath = "data/shapes/hazards/oilslick.dts"; + this.identifier = "Oilslick"; + this.useInstancing = true; + this.isCollideable = true; + this.isTSStatic = false; + } +} diff --git a/src/shapes/PowerUp.hx b/src/shapes/PowerUp.hx index 7b881e53..cd88c128 100644 --- a/src/shapes/PowerUp.hx +++ b/src/shapes/PowerUp.hx @@ -27,6 +27,7 @@ abstract class PowerUp extends DtsObject { public var cooldownDuration:Float = 7; public var autoUse:Bool = false; public var powerupParams:PowerupParams = new PowerupParams(); + public var pickUpName:String; public function new() { super(); @@ -46,7 +47,7 @@ abstract class PowerUp extends DtsObject { if (this.autoUse) this.use(time); - // displayAlert(`You picked up a ${this.pickUpName}!`); + this.level.displayAlert('You picked up a ${this.pickUpName}!'); // if (this.element.showhelponpickup === "1" && !this.autoUse) displayHelp(`Press to use the ${this.pickUpName}!`); } } diff --git a/src/shapes/RoundBumper.hx b/src/shapes/RoundBumper.hx new file mode 100644 index 00000000..e2a59d80 --- /dev/null +++ b/src/shapes/RoundBumper.hx @@ -0,0 +1,12 @@ +package shapes; + +import src.DtsObject; + +class RoundBumper extends DtsObject { + public function new() { + super(); + dtsPath = "data/shapes/bumpers/pball_round.dts"; + isCollideable = true; + identifier = "RoundBumper"; + } +} diff --git a/src/shapes/ShockAbsorber.hx b/src/shapes/ShockAbsorber.hx index d8bfc1d1..e2bf20fe 100644 --- a/src/shapes/ShockAbsorber.hx +++ b/src/shapes/ShockAbsorber.hx @@ -9,6 +9,7 @@ class ShockAbsorber extends PowerUp { this.isCollideable = false; this.isTSStatic = false; this.identifier = "ShockAbsorber"; + this.pickUpName = "Shock Absorber PowerUp"; } public function pickUp():Bool { diff --git a/src/shapes/StartPad.hx b/src/shapes/StartPad.hx new file mode 100644 index 00000000..dd2009da --- /dev/null +++ b/src/shapes/StartPad.hx @@ -0,0 +1,13 @@ +package shapes; + +import src.DtsObject; + +class StartPad extends DtsObject { + public function new() { + super(); + dtsPath = "data/shapes/pads/startarea.dts"; + useInstancing = false; + isCollideable = true; + identifier = "StartPad"; + } +} diff --git a/src/shapes/SuperBounce.hx b/src/shapes/SuperBounce.hx index bd828ad1..a3e486a7 100644 --- a/src/shapes/SuperBounce.hx +++ b/src/shapes/SuperBounce.hx @@ -9,6 +9,7 @@ class SuperBounce extends PowerUp { this.isCollideable = false; this.isTSStatic = false; this.identifier = "SuperBounce"; + this.pickUpName = "Super Bounce PowerUp"; } public function pickUp():Bool { diff --git a/src/shapes/SuperJump.hx b/src/shapes/SuperJump.hx index f3f4bd3c..57852d59 100644 --- a/src/shapes/SuperJump.hx +++ b/src/shapes/SuperJump.hx @@ -37,6 +37,7 @@ class SuperJump extends PowerUp { this.isCollideable = false; this.isTSStatic = false; this.identifier = "SuperJump"; + this.pickUpName = "Super Jump PowerUp"; sjEmitterParticleData = new ParticleData(); sjEmitterParticleData.identifier = "superJumpParticle"; sjEmitterParticleData.texture = ResourceLoader.getTexture("data/particles/twirl.png"); diff --git a/src/shapes/SuperSpeed.hx b/src/shapes/SuperSpeed.hx index 4a76c711..ed79cbea 100644 --- a/src/shapes/SuperSpeed.hx +++ b/src/shapes/SuperSpeed.hx @@ -43,6 +43,7 @@ class SuperSpeed extends PowerUp { this.isCollideable = false; this.isTSStatic = false; this.identifier = "SuperSpeed"; + this.pickUpName = "Super Speed PowerUp"; this.useInstancing = true; ssEmitterParticleData = new ParticleData(); ssEmitterParticleData.identifier = "superSpeedParticle"; diff --git a/src/shapes/TimeTravel.hx b/src/shapes/TimeTravel.hx index f8f125cb..3a1101e3 100644 --- a/src/shapes/TimeTravel.hx +++ b/src/shapes/TimeTravel.hx @@ -7,6 +7,7 @@ class TimeTravel extends PowerUp { this.isCollideable = false; this.isTSStatic = false; this.identifier = "TimeTravel"; + this.pickUpName = '${this.timeBonus} second Time Travel bonus'; this.cooldownDuration = 1e8; this.useInstancing = true; this.autoUse = true; diff --git a/src/shapes/Trapdoor.hx b/src/shapes/Trapdoor.hx index c95d0ef3..65e8e74e 100644 --- a/src/shapes/Trapdoor.hx +++ b/src/shapes/Trapdoor.hx @@ -1,15 +1,67 @@ package shapes; +import collision.CollisionInfo; +import src.Util; import src.DtsObject; import h3d.Vector; import src.ForceObject; class Trapdoor extends DtsObject { + var lastContactTime = -1e8; + var timeout:Float = 0; + var lastDirection:Float; + var lastCompletion:Float = 0; + public function new() { super(); this.dtsPath = "data/shapes/hazards/trapdoor.dts"; this.isCollideable = true; this.isTSStatic = false; this.identifier = "Trapdoor"; + this.hasNonVisualSequences = true; + } + + public override function update(currentTime:Float, dt:Float) { + var currentCompletion = this.getCurrentCompletion(currentTime); + + // Override the keyframe + this.sequenceKeyframeOverride.set(this.dts.sequences[0], currentCompletion * (this.dts.sequences[0].numKeyFrames - 1)); + super.update(currentTime, dt); + + var diff = (currentCompletion - this.lastCompletion); + var direction = 0; + if (diff > 0) + direction = 1; + if (diff < 0) + direction = -1; + if (direction != 0 && direction != this.lastDirection) { + // If the direction has changed, play the sound + // AudioManager.play(this.sounds[0], 1, AudioManager.soundGain, this.worldPosition); + } + + this.lastCompletion = currentCompletion; + this.lastDirection = direction; + } + + function getCurrentCompletion(time:Float) { + var elapsed = time - this.lastContactTime; + var completion = Util.clamp(elapsed / 1.6666676998138428, 0, 1); + if (elapsed > 5) + completion = Util.clamp(1 - (elapsed - 5) / 1.6666676998138428, 0, 1); + return completion; + } + + override function onMarbleContact(time:Float, ?contact:CollisionInfo) { + super.onMarbleContact(this.level.currentTime, contact); + if (this.level.currentTime - this.lastContactTime <= 0) + return; // The trapdoor is queued to open, so don't do anything. + var currentCompletion = this.getCurrentCompletion(this.level.currentTime); + + // Set the last contact time accordingly so that the trapdoor starts closing (again) + this.lastContactTime = this.level.currentTime - currentCompletion * 1.6666676998138428; + if (currentCompletion == 0) + this.lastContactTime += this.timeout; + + // this.level.replay.recordMarbleContact(this); } } diff --git a/src/shapes/TriangleBumper.hx b/src/shapes/TriangleBumper.hx new file mode 100644 index 00000000..22ea751a --- /dev/null +++ b/src/shapes/TriangleBumper.hx @@ -0,0 +1,12 @@ +package shapes; + +import src.DtsObject; + +class TriangleBumper extends DtsObject { + public function new() { + super(); + dtsPath = "data/shapes/bumpers/pball_tri.dts"; + identifier = "TriangleBumper"; + isCollideable = true; + } +}