mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2025-12-28 10:52:17 +00:00
working teleporter
This commit is contained in:
parent
2ae5f79890
commit
1a5529efb6
7 changed files with 231 additions and 2 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
5
src/triggers/DestinationTrigger.hx
Normal file
5
src/triggers/DestinationTrigger.hx
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
package triggers;
|
||||
|
||||
class DestinationTrigger extends Trigger {
|
||||
// Stub
|
||||
}
|
||||
119
src/triggers/TeleportTrigger.hx
Normal file
119
src/triggers/TeleportTrigger.hx
Normal 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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue