working teleporter

This commit is contained in:
RandomityGuy 2022-11-13 19:31:02 +05:30
parent 2ae5f79890
commit 1a5529efb6
7 changed files with 231 additions and 2 deletions

View file

@ -1,5 +1,7 @@
package src;
import h3d.shader.AlphaMult;
import shaders.DtsTexture;
import collision.gjk.GJK;
import collision.gjk.ConvexHull;
import hxd.snd.effect.Pitch;
@ -167,6 +169,8 @@ class Marble extends GameObject {
var shockAbsorberEnableTime:Float = -1e8;
var helicopterEnableTime:Float = -1e8;
var teleportEnableTime:Null<Float> = null;
var teleportDisableTime:Null<Float> = null;
var bounceEmitDelay:Float = 0;
var bounceEmitterData:ParticleData;
@ -187,6 +191,10 @@ class Marble extends GameObject {
public var prevPos:Vector;
var cloak:Bool = false;
var teleporting:Bool = false;
public function new() {
super();
var geom = Sphere.defaultUnitSphere();
@ -195,6 +203,11 @@ class Marble extends GameObject {
var marbleMaterial = Material.create(marbleTexture);
marbleMaterial.shadows = false;
marbleMaterial.castShadows = true;
// marbleMaterial.mainPass.removeShader(marbleMaterial.textureShader);
// var dtsShader = new DtsTexture();
// dtsShader.texture = marbleTexture;
// dtsShader.currentOpacity = 1;
// marbleMaterial.mainPass.addShader(dtsShader);
var obj = new Mesh(geom, marbleMaterial, this);
obj.scale(_radius);
@ -1396,6 +1409,7 @@ class Marble extends GameObject {
}
updatePowerupStates(timeState.currentAttemptTime, timeState.dt);
this.updateTeleporterState(timeState);
this.trailEmitter();
if (bounceEmitDelay > 0)
@ -1453,6 +1467,47 @@ class Marble extends GameObject {
this.helicopterEnableTime = time;
}
function updateTeleporterState(time:TimeState) {
var teleportFadeCompletion:Float = 0;
if (this.teleportEnableTime != null)
teleportFadeCompletion = Util.clamp((time.currentAttemptTime - this.teleportEnableTime) / 0.5, 0, 1);
if (this.teleportDisableTime != null)
teleportFadeCompletion = Util.clamp(1 - (time.currentAttemptTime - this.teleportDisableTime) / 0.5, 0, 1);
if (teleportFadeCompletion > 0) {
var mesh:Mesh = cast this.children[0];
var shad:AlphaMult = mesh.material.mainPass.getShader(AlphaMult);
if (shad == null) {
shad = new AlphaMult();
mesh.material.mainPass.addShader(shad);
mesh.material.blendMode = Alpha;
this.teleporting = true;
}
shad.alpha = Util.lerp(1, 0.25, teleportFadeCompletion);
} else {
if (this.teleporting) {
var mesh:Mesh = cast this.children[0];
mesh.material.mainPass.removeShader(mesh.material.mainPass.getShader(AlphaMult));
mesh.material.blendMode = None;
this.teleporting = false;
}
}
}
public function setCloaking(active:Bool, time:TimeState) {
this.cloak = active;
if (this.cloak) {
var completion = (this.teleportDisableTime != null) ? Util.clamp((time.currentAttemptTime - this.teleportDisableTime) / 0.5, 0, 1) : 1;
this.teleportEnableTime = time.currentAttemptTime - 0.5 * (1 - completion);
this.teleportDisableTime = null;
} else {
var completion = Util.clamp((time.currentAttemptTime - this.teleportEnableTime) / 0.5, 0, 1);
this.teleportDisableTime = time.currentAttemptTime - 0.5 * (1 - completion);
this.teleportEnableTime = null;
}
}
public override function reset() {
this.velocity = new Vector();
this.collider.velocity = new Vector();
@ -1461,5 +1516,14 @@ class Marble extends GameObject {
this.shockAbsorberEnableTime = Math.NEGATIVE_INFINITY;
this.helicopterEnableTime = Math.NEGATIVE_INFINITY;
this.lastContactNormal = new Vector(0, 0, 1);
this.cloak = false;
if (this.teleporting) {
var mesh:Mesh = cast this.children[0];
mesh.material.mainPass.removeShader(mesh.material.mainPass.getShader(AlphaMult));
mesh.material.blendMode = None;
}
this.teleporting = false;
this.teleportDisableTime = null;
this.teleportEnableTime = null;
}
}

View file

@ -1,5 +1,7 @@
package src;
import triggers.TeleportTrigger;
import triggers.DestinationTrigger;
import shapes.Nuke;
import shapes.Magnet;
import src.Replay;
@ -744,6 +746,10 @@ class MarbleWorld extends Scheduler {
trigger = new InBoundsTrigger(element, cast this);
} else if (element.datablock == "HelpTrigger") {
trigger = new HelpTrigger(element, cast this);
} else if (element.datablock == "TeleportTrigger") {
trigger = new TeleportTrigger(element, cast this);
} else if (element.datablock == "DestinationTrigger") {
trigger = new DestinationTrigger(element, cast this);
} else {
onFinish();
return;
@ -907,6 +913,9 @@ class MarbleWorld extends Scheduler {
for (obj in dtsObjects) {
obj.update(timeState);
}
for (obj in triggers) {
obj.update(timeState);
}
ProfilerUI.measure("updateMarbles");
for (marble in marbles) {
marble.update(timeState, collisionWorld, this.pathedInteriors);

View file

@ -519,4 +519,15 @@ class MisParser {
}
return result;
}
/** Parses a boolean value. */
public static function parseBoolean(string:String) {
if (string == null)
return false;
if (string == "")
return false;
if (string == "0")
return false;
return true;
}
}

View file

@ -227,6 +227,22 @@ class MissionElementTrigger extends MissionElementBase {
var instant:Null<String>;
var icontinuetottime:Null<String>;
// checkpoint stuff:
var respawnpoint:Null<String>;
var add:Null<String>;
var sub:Null<String>;
var gravity:Null<String>;
var disableOob:Null<String>;
// teleport/destination trigger stuff:
var destination:Null<String>;
var delay:Null<String>;
var centerdestpoint:Null<String>;
var keepvelocity:Null<String>;
var inversevelocity:Null<String>;
var keepangular:Null<String>;
var keepcamera:Null<String>;
var camerayaw:Null<String>;
public function new() {
_type = MissionElementType.Trigger;
}

View file

@ -0,0 +1,5 @@
package triggers;
class DestinationTrigger extends Trigger {
// Stub
}

View file

@ -0,0 +1,119 @@
package triggers;
import h3d.Vector;
import src.ResourceLoader;
import src.AudioManager;
import mis.MisParser;
import src.MarbleWorld;
import mis.MissionElement.MissionElementTrigger;
class TeleportTrigger extends Trigger {
var delay:Float = 2;
var entryTime:Null<Float> = null;
var exitTime:Null<Float> = null;
public function new(element:MissionElementTrigger, level:MarbleWorld) {
super(element, level);
if (element.delay != null)
this.delay = MisParser.parseNumber(element.delay) / 1000;
}
override function onMarbleEnter(time:src.TimeState) {
this.exitTime = null;
this.level.marble.setCloaking(true, time);
if (this.entryTime != null)
return;
this.entryTime = time.currentAttemptTime;
this.level.displayAlert("Teleporter has been activated, please wait.");
AudioManager.playSound(ResourceLoader.getResource("data/sound/teleport.wav", ResourceLoader.getAudio, this.soundResources));
}
override function onMarbleLeave(time:src.TimeState) {
this.exitTime = time.currentAttemptTime;
this.level.marble.setCloaking(false, time);
}
public override function update(timeState:src.TimeState) {
if (this.entryTime == null)
return;
if (timeState.currentAttemptTime - this.entryTime >= this.delay) {
this.executeTeleport();
return;
}
// There's a little delay after exiting before the teleporter gets cancelled
if (this.exitTime != null && timeState.currentAttemptTime - this.exitTime > 0.050) {
this.entryTime = null;
this.exitTime = null;
return;
}
}
override function init(onFinish:() -> Void) {
ResourceLoader.load("sound/teleport.wav").entry.load(onFinish);
}
function executeTeleport() {
this.entryTime = null;
function chooseNonNull(a:String, b:String) {
if (a != null)
return a;
if (b != null)
return b;
return null;
}
// Find the destination trigger
if (this.element.destination == null)
return;
var destinationList = this.level.triggers.filter(x -> x is DestinationTrigger
&& x.element._name.toLowerCase() == this.element.destination.toLowerCase());
if (destinationList.length == 0)
return; // Who knows
var destination = destinationList[0];
var pos = MisParser.parseVector3(destination.element.position);
pos.x = -pos.x;
// Determine where to place the marble
var position:Vector;
if (MisParser.parseBoolean(chooseNonNull(this.element.centerdestpoint, destination.element.centerdestpoint))) {
position = destination.collider.boundingBox.getCenter().toVector(); // Put the marble in the middle of the thing
} else {
position = destination.vertices[0].add(new Vector(0, 0, 3)).add(pos); // destination.vertices[0].clone().add(new Vector(0, 0, 3));
}
this.level.marble.prevPos.load(position);
this.level.marble.setPosition(position.x, position.y, position.z);
if (!MisParser.parseBoolean(chooseNonNull(this.element.keepvelocity, destination.element.keepvelocity)))
this.level.marble.velocity.set(0, 0, 0);
if (MisParser.parseBoolean(chooseNonNull(this.element.inversevelocity, destination.element.inversevelocity)))
this.level.marble.velocity.scale(-1);
if (!MisParser.parseBoolean(chooseNonNull(this.element.keepangular, destination.element.keepangular)))
this.level.marble.omega.set(0, 0, 0);
// Determine camera orientation
if (!MisParser.parseBoolean(chooseNonNull(this.element.keepcamera, destination.element.keepcamera))) {
var yaw:Float;
if (this.element.camerayaw != null)
yaw = MisParser.parseNumber(this.element.camerayaw) * Math.PI / 180;
else if (destination.element.camerayaw != null)
yaw = MisParser.parseNumber(destination.element.camerayaw) * Math.PI / 180;
else
yaw = 0;
yaw = -yaw; // Need to flip it for some reason
this.level.marble.camera.CameraYaw = yaw + Math.PI / 2;
this.level.marble.camera.CameraPitch = 0.45;
this.level.marble.camera.nextCameraYaw = yaw + Math.PI / 2;
this.level.marble.camera.nextCameraPitch = 0.45;
}
AudioManager.playSound(ResourceLoader.getResource("data/sound/spawn.wav", ResourceLoader.getAudio, this.soundResources));
}
}

View file

@ -1,5 +1,6 @@
package triggers;
import src.TimeState;
import h3d.scene.Mesh;
import h3d.mat.Material;
import h3d.prim.Cube;
@ -17,6 +18,8 @@ class Trigger extends GameObject {
var level:MarbleWorld;
var element:MissionElementTrigger;
var vertices:Array<Vector>;
public var collider:BoxCollisionEntity;
public function new(element:MissionElementTrigger, level:MarbleWorld) {
@ -43,7 +46,7 @@ class Trigger extends GameObject {
var mat = new Matrix();
var quat = MisParser.parseRotation(element.rotation);
// quat.x = -quat.x;
quat.x = -quat.x;
// quat.w = -quat.w;
quat.toMatrix(mat);
var scale = MisParser.parseVector3(element.scale);
@ -52,7 +55,7 @@ class Trigger extends GameObject {
pos.x = -pos.x;
// mat.setPosition(pos);
var vertices = [p1, p2, p3, p4, p5, p6, p7, p8].map((vert) -> vert.transformed(mat));
vertices = [p1, p2, p3, p4, p5, p6, p7, p8].map((vert) -> vert.transformed(mat));
var boundingbox = new Bounds();
for (vector in vertices) {
@ -74,6 +77,8 @@ class Trigger extends GameObject {
// mesh.setPosition(boundingbox.xMin, boundingbox.yMin, boundingbox.zMin);
}
public function update(timeState:TimeState) {}
public function init(onFinish:Void->Void) {
onFinish();
}