fix a lot of things, camera (attempt), improve pathedinteriors scalability, touch support things, spectator mode mobile camera

This commit is contained in:
RandomityGuy 2024-07-12 00:38:10 +05:30
parent 3964b43aca
commit e216be4ec9
18 changed files with 383 additions and 216 deletions

View file

@ -127,12 +127,20 @@ class CameraController extends Object {
public function enableSpectate() { public function enableSpectate() {
spectate = true; spectate = true;
@:privateAccess this.level.playGui.setSpectateMenu(true); if (@:privateAccess this.level.playGui.setSpectateMenu(true)) {
if (Util.isTouchDevice()) {
MarbleGame.instance.touchInput.setSpectatorControls(true);
MarbleGame.instance.touchInput.setSpectatorControlsVisibility(false);
}
}
} }
public function stopSpectate() { public function stopSpectate() {
spectate = false; spectate = false;
@:privateAccess this.level.playGui.setSpectateMenu(false); @:privateAccess this.level.playGui.setSpectateMenu(false);
if (Util.isTouchDevice()) {
MarbleGame.instance.touchInput.setSpectatorControls(false);
}
} }
public function orbit(mouseX:Float, mouseY:Float, isTouch:Bool = false) { public function orbit(mouseX:Float, mouseY:Float, isTouch:Bool = false) {
@ -163,7 +171,7 @@ class CameraController extends Object {
} }
var factor = isTouch ? Util.lerp(1 / 25, 1 / 15, var factor = isTouch ? Util.lerp(1 / 25, 1 / 15,
Settings.controlsSettings.cameraSensitivity) : Util.lerp(1 / 2500, 1 / 100, Settings.controlsSettings.cameraSensitivity); Settings.controlsSettings.cameraSensitivity) : Util.lerp(1 / 1000, 1 / 200, Settings.controlsSettings.cameraSensitivity);
// CameraPitch += deltaposY * factor; // CameraPitch += deltaposY * factor;
// CameraYaw += deltaposX * factor; // CameraYaw += deltaposX * factor;
@ -264,8 +272,8 @@ class CameraController extends Object {
nextCameraPitch = Math.max(-Math.PI / 2 + Math.PI / 4, Math.min(Math.PI / 2 - 0.0001, nextCameraPitch)); nextCameraPitch = Math.max(-Math.PI / 2 + Math.PI / 4, Math.min(Math.PI / 2 - 0.0001, nextCameraPitch));
CameraYaw = Util.lerp(CameraYaw, nextCameraYaw, lerpt); CameraYaw = nextCameraYaw; // Util.lerp(CameraYaw, nextCameraYaw, lerpt);
CameraPitch = Util.lerp(CameraPitch, nextCameraPitch, lerpt); CameraPitch = nextCameraPitch; // Util.lerp(CameraPitch, nextCameraPitch, lerpt);
CameraPitch = Math.max(-Math.PI / 2 + Math.PI / 4, Math.min(Math.PI / 2 - 0.0001, CameraPitch)); // Util.clamp(CameraPitch, -Math.PI / 12, Math.PI / 2); CameraPitch = Math.max(-Math.PI / 2 + Math.PI / 4, Math.min(Math.PI / 2 - 0.0001, CameraPitch)); // Util.clamp(CameraPitch, -Math.PI / 12, Math.PI / 2);
@ -331,7 +339,7 @@ class CameraController extends Object {
if (MarbleGame.instance.touchInput.movementInput.pressed) { if (MarbleGame.instance.touchInput.movementInput.pressed) {
dx = -MarbleGame.instance.touchInput.movementInput.value.x * CameraSpeed * dt; dx = -MarbleGame.instance.touchInput.movementInput.value.x * CameraSpeed * dt;
dy = MarbleGame.instance.touchInput.movementInput.value.y * CameraSpeed * dt; dy = -MarbleGame.instance.touchInput.movementInput.value.y * CameraSpeed * dt;
} }
if ((!Util.isTouchDevice() && Key.isDown(Settings.controlsSettings.powerup)) if ((!Util.isTouchDevice() && Key.isDown(Settings.controlsSettings.powerup))
@ -342,10 +350,12 @@ class CameraController extends Object {
} }
if (Key.isPressed(Settings.controlsSettings.blast) if (Key.isPressed(Settings.controlsSettings.blast)
|| (MarbleGame.instance.touchInput.blastbutton.pressed) || (MarbleGame.instance.touchInput.blastbutton.pressed && MarbleGame.instance.touchInput.blastbutton.didPressIt)
|| Gamepad.isPressed(Settings.gamepadSettings.blast)) { || Gamepad.isPressed(Settings.gamepadSettings.blast)) {
var freeMarbleIndex = -1; var freeMarbleIndex = -1;
MarbleGame.instance.touchInput.blastbutton.didPressIt = false;
for (i in 0...level.marbles.length) { for (i in 0...level.marbles.length) {
var marble = level.marbles[i]; var marble = level.marbles[i];
@:privateAccess if ((marble.connection != null && !marble.connection.spectator)) { @:privateAccess if ((marble.connection != null && !marble.connection.spectator)) {
@ -354,6 +364,7 @@ class CameraController extends Object {
} }
} }
spectateMarbleIndex = freeMarbleIndex; spectateMarbleIndex = freeMarbleIndex;
MarbleGame.instance.touchInput.setSpectatorControlsVisibility(true);
return; return;
} }
@ -366,7 +377,9 @@ class CameraController extends Object {
camera.target = camera.pos.add(directionVector); camera.target = camera.pos.add(directionVector);
} else { } else {
@:privateAccess level.playGui.setSpectateMenuText(1); @:privateAccess level.playGui.setSpectateMenuText(1);
if (Key.isPressed(Settings.controlsSettings.left)) { if (Key.isPressed(Settings.controlsSettings.left)
|| (MarbleGame.instance.touchInput.leftButton.pressed && MarbleGame.instance.touchInput.leftButton.didPressIt)) {
MarbleGame.instance.touchInput.leftButton.didPressIt = false;
spectateMarbleIndex = (spectateMarbleIndex - 1 + level.marbles.length) % level.marbles.length; spectateMarbleIndex = (spectateMarbleIndex - 1 + level.marbles.length) % level.marbles.length;
@:privateAccess while (level.marbles[spectateMarbleIndex].connection == null @:privateAccess while (level.marbles[spectateMarbleIndex].connection == null
|| level.marbles[spectateMarbleIndex].connection.spectator) { || level.marbles[spectateMarbleIndex].connection.spectator) {
@ -374,7 +387,9 @@ class CameraController extends Object {
} }
} }
if (Key.isPressed(Settings.controlsSettings.right)) { if (Key.isPressed(Settings.controlsSettings.right)
|| (MarbleGame.instance.touchInput.rightButton.pressed && MarbleGame.instance.touchInput.rightButton.didPressIt)) {
MarbleGame.instance.touchInput.rightButton.didPressIt = false;
spectateMarbleIndex = (spectateMarbleIndex + 1 + level.marbles.length) % level.marbles.length; spectateMarbleIndex = (spectateMarbleIndex + 1 + level.marbles.length) % level.marbles.length;
@:privateAccess while (level.marbles[spectateMarbleIndex].connection == null @:privateAccess while (level.marbles[spectateMarbleIndex].connection == null
|| level.marbles[spectateMarbleIndex].connection.spectator) { || level.marbles[spectateMarbleIndex].connection.spectator) {
@ -383,9 +398,16 @@ class CameraController extends Object {
} }
if (Key.isPressed(Settings.controlsSettings.blast) if (Key.isPressed(Settings.controlsSettings.blast)
|| (MarbleGame.instance.touchInput.blastbutton.pressed) || (MarbleGame.instance.touchInput.blastbutton.pressed && MarbleGame.instance.touchInput.blastbutton.didPressIt)
|| Gamepad.isPressed(Settings.gamepadSettings.blast)) { || Gamepad.isPressed(Settings.gamepadSettings.blast)) {
MarbleGame.instance.touchInput.blastbutton.didPressIt = false;
spectateMarbleIndex = -1; spectateMarbleIndex = -1;
MarbleGame.instance.touchInput.setSpectatorControlsVisibility(false);
return;
}
if (@:privateAccess level.marbles.length <= spectateMarbleIndex) {
spectateMarbleIndex = -1;
MarbleGame.instance.touchInput.setSpectatorControlsVisibility(false);
return; return;
} }
@ -479,7 +501,8 @@ class CameraController extends Object {
var camera = level.scene.camera; var camera = level.scene.camera;
var lerpt = Math.pow(0.5, dt / 0.032); // Math.min(1, 1 - Math.pow(0.6, dt / 0.032)); // hxd.Math.min(1, 1 - Math.pow(0.6, dt * 600)); var lerpt = hxd.Math.min(1,
1 - Math.pow(0.6, dt * 600)); // Math.min(1, 1 - Math.pow(0.6, dt / 0.032)); // hxd.Math.min(1, 1 - Math.pow(0.6, dt * 600));
var cameraPitchDelta = (Key.isDown(Settings.controlsSettings.camBackward) ? 1 : 0) var cameraPitchDelta = (Key.isDown(Settings.controlsSettings.camBackward) ? 1 : 0)
- (Key.isDown(Settings.controlsSettings.camForward) ? 1 : 0) - (Key.isDown(Settings.controlsSettings.camForward) ? 1 : 0)
@ -495,8 +518,8 @@ class CameraController extends Object {
nextCameraPitch = Math.max(-Math.PI / 2 + Math.PI / 4, Math.min(Math.PI / 2 - 0.0001, nextCameraPitch)); nextCameraPitch = Math.max(-Math.PI / 2 + Math.PI / 4, Math.min(Math.PI / 2 - 0.0001, nextCameraPitch));
CameraYaw = Util.lerp(CameraYaw, nextCameraYaw, lerpt); CameraYaw = nextCameraYaw; // Util.lerp(CameraYaw, nextCameraYaw, lerpt);
CameraPitch = Util.lerp(CameraPitch, nextCameraPitch, lerpt); CameraPitch = nextCameraPitch; // Util.lerp(CameraPitch, nextCameraPitch, lerpt);
CameraPitch = Math.max(-Math.PI / 2 + Math.PI / 4, Math.min(Math.PI / 2 - 0.0001, CameraPitch)); // Util.clamp(CameraPitch, -Math.PI / 12, Math.PI / 2); CameraPitch = Math.max(-Math.PI / 2 + Math.PI / 4, Math.min(Math.PI / 2 - 0.0001, CameraPitch)); // Util.clamp(CameraPitch, -Math.PI / 12, Math.PI / 2);

View file

@ -579,32 +579,99 @@ class DtsObject extends GameObject {
hs.restitution = data.restitution; hs.restitution = data.restitution;
} }
for (i in primitive.firstElement...(primitive.firstElement + primitive.numElements - 2)) { var drawType = primitive.matIndex & TSDrawPrimitive.TypeMask;
var i1 = dtsMesh.indices[i];
var i2 = dtsMesh.indices[i + 1];
var i3 = dtsMesh.indices[i + 2];
if (k % 2 == 0) { if (drawType == TSDrawPrimitive.Triangles) {
// Swap the first and last index to mainting correct winding order var i = primitive.firstElement;
var temp = i1; while (i < primitive.firstElement + primitive.numElements) {
i1 = i3; var i1 = dtsMesh.indices[i];
i3 = temp; var i2 = dtsMesh.indices[i + 1];
var i3 = dtsMesh.indices[i + 2];
var t1 = vertices[i2].sub(vertices[i1]);
var t2 = vertices[i3].sub(vertices[i1]);
var tarea = Math.abs(t1.cross(t2).length()) / 2.0;
if (tarea < 0.00001)
continue;
for (index in [i1, i2, i3]) {
var vertex = vertices[index];
hs.addPoint(vertex.x, vertex.y, vertex.z);
hs.transformKeys.push(0);
var normal = vertexNormals[index];
hs.addNormal(normal.x, normal.y, normal.z);
}
hs.indices.push(hs.indices.length);
hs.indices.push(hs.indices.length);
hs.indices.push(hs.indices.length);
i += 3;
} }
} else if (drawType == TSDrawPrimitive.Strip) {
var k = 0;
for (i in primitive.firstElement...(primitive.firstElement + primitive.numElements - 2)) {
var i1 = dtsMesh.indices[i];
var i2 = dtsMesh.indices[i + 1];
var i3 = dtsMesh.indices[i + 2];
for (index in [i1, i2, i3]) { if (k % 2 == 0) {
var vertex = vertices[index]; // Swap the first and last index to mainting correct winding order
hs.addPoint(vertex.x, vertex.y, vertex.z); var temp = i1;
hs.transformKeys.push(0); i1 = i3;
i3 = temp;
}
var normal = vertexNormals[index]; var t1 = vertices[i2].sub(vertices[i1]);
hs.addNormal(normal.x, normal.y, normal.z); var t2 = vertices[i3].sub(vertices[i1]);
var tarea = Math.abs(t1.cross(t2).length()) / 2.0;
if (tarea < 0.00001)
continue;
for (index in [i1, i2, i3]) {
var vertex = vertices[index];
hs.addPoint(vertex.x, vertex.y, vertex.z);
hs.transformKeys.push(0);
var normal = vertexNormals[index];
hs.addNormal(normal.x, normal.y, normal.z);
}
hs.indices.push(hs.indices.length);
hs.indices.push(hs.indices.length);
hs.indices.push(hs.indices.length);
k++;
} }
} else if (drawType == TSDrawPrimitive.Fan) {
var i = primitive.firstElement;
while (i < primitive.firstElement + primitive.numElements - 2) {
var i1 = dtsMesh.indices[primitive.firstElement];
var i2 = dtsMesh.indices[i + 1];
var i3 = dtsMesh.indices[i + 2];
hs.indices.push(hs.indices.length); var t1 = vertices[i2].sub(vertices[i1]);
hs.indices.push(hs.indices.length); var t2 = vertices[i3].sub(vertices[i1]);
hs.indices.push(hs.indices.length); var tarea = Math.abs(t1.cross(t2).length()) / 2.0;
if (tarea < 0.00001)
continue;
k++; for (index in [i1, i2, i3]) {
var vertex = vertices[index];
hs.addPoint(vertex.x, vertex.y, vertex.z);
hs.transformKeys.push(0);
var normal = vertexNormals[index];
hs.addNormal(normal.x, normal.y, normal.z);
}
hs.indices.push(hs.indices.length);
hs.indices.push(hs.indices.length);
hs.indices.push(hs.indices.length);
i++;
}
} }
hs.generateBoundingBox(); hs.generateBoundingBox();

View file

@ -1276,6 +1276,8 @@ class Marble extends GameObject {
if (obj.go != null && !obj.go.isCollideable) if (obj.go != null && !obj.go.isCollideable)
continue; continue;
var isDts = obj.go is DtsObject;
var invMatrix = @:privateAccess obj.invTransform; var invMatrix = @:privateAccess obj.invTransform;
if (obj.go is PathedInterior) if (obj.go is PathedInterior)
invMatrix = obj.transform.getInverse(); invMatrix = obj.transform.getInverse();
@ -1338,10 +1340,11 @@ class Marble extends GameObject {
// var vT = v.transformed(obj.transform); // var vT = v.transformed(obj.transform);
// var v2T = v2.transformed(obj.transform); // var v2T = v2.transformed(obj.transform);
// var vN = surfaceNormal.transformed3x3(obj.transform); // var vN = surfaceNormal.transformed3x3(obj.transform);
testTriangles.push({ if (!isDts)
v: [v0.clone(), v.clone(), v2.clone()], testTriangles.push({
n: surfaceNormal.clone(), v: [v0.clone(), v.clone(), v2.clone()],
}); n: surfaceNormal.clone(),
});
// Time until collision with the plane // Time until collision with the plane
var collisionTime = (radius - position.dot(surfaceNormal) - surfaceD) / surfaceNormal.dot(relVel); var collisionTime = (radius - position.dot(surfaceNormal) - surfaceD) / surfaceNormal.dot(relVel);

View file

@ -224,9 +224,9 @@ class MarbleWorld extends Scheduler {
public var currentInputMoves:Array<InputRecorderFrame>; public var currentInputMoves:Array<InputRecorderFrame>;
// Multiplayer // Multiplayer
public var isMultiplayer:Bool; public var isMultiplayer:Bool = false;
public var serverStartTicks:Int; public var serverStartTicks:Int = 0;
public var startTime:Float = 1e8; public var startTime:Float = 1e8;
public var multiplayerStarted:Bool = false; public var multiplayerStarted:Bool = false;
@ -2762,7 +2762,8 @@ class MarbleWorld extends Scheduler {
// this.oobCameraPosition = camera.position.clone(); // this.oobCameraPosition = camera.position.clone();
if (marble == this.marble) { if (marble == this.marble) {
playGui.setCenterText('outofbounds'); playGui.setCenterText('outofbounds');
AudioManager.playSound(ResourceLoader.getResource('data/sound/whoosh.wav', ResourceLoader.getAudio, this.soundResources)); if (@:privateAccess !this.marble.isNetUpdate)
AudioManager.playSound(ResourceLoader.getResource('data/sound/whoosh.wav', ResourceLoader.getAudio, this.soundResources));
// if (this.replay.mode != = 'playback') // if (this.replay.mode != = 'playback')
this.oobSchedule = this.schedule(this.timeState.currentAttemptTime + 2, () -> { this.oobSchedule = this.schedule(this.timeState.currentAttemptTime + 2, () -> {
playGui.setCenterText('none'); playGui.setCenterText('none');

View file

@ -59,6 +59,7 @@ class PathedInterior extends InteriorObject {
var savedVelocity:Vector; var savedVelocity:Vector;
var savedStopped:Bool; var savedStopped:Bool;
var savedStoppedPosition:Vector; var savedStoppedPosition:Vector;
var savedInvPosition:Vector;
var savedTime:Float; var savedTime:Float;
var soundChannel:Channel; var soundChannel:Channel;
@ -115,7 +116,14 @@ class PathedInterior extends InteriorObject {
this.markerData = this.path.markers.map(x -> { this.markerData = this.path.markers.map(x -> {
var marker = new PathedInteriorMarker(); var marker = new PathedInteriorMarker();
marker.msToNext = MisParser.parseNumber(x.mstonext) / 1000; marker.msToNext = MisParser.parseNumber(x.mstonext) / 1000;
marker.smoothingType = x.smoothingtype; marker.smoothingType = switch (x.smoothingtype) {
case "Accelerate":
PathedInteriorMarker.SMOOTHING_ACCELERATE;
case "Spline":
PathedInteriorMarker.SMOOTHING_SPLINE;
default:
PathedInteriorMarker.SMOOTHING_LINEAR;
};
marker.position = MisParser.parseVector3(x.position); marker.position = MisParser.parseVector3(x.position);
marker.position.x = -marker.position.x; marker.position.x = -marker.position.x;
marker.rotation = MisParser.parseRotation(x.rotation); marker.rotation = MisParser.parseRotation(x.rotation);
@ -214,9 +222,10 @@ class PathedInterior extends InteriorObject {
return; return;
if (this.velocity.length() == 0) if (this.velocity.length() == 0)
return; return;
static var tform = new Matrix();
velocity.w = 0; velocity.w = 0;
var newp = position.add(velocity.multiply(timeDelta)); var newp = position.add(velocity.multiply(timeDelta));
var tform = this.getAbsPos().clone(); tform.load(this.getAbsPos()); // .clone();
tform.setPosition(newp); tform.setPosition(newp);
if (this.isCollideable) { if (this.isCollideable) {
@ -251,6 +260,7 @@ class PathedInterior extends InteriorObject {
public function pushTickState() { public function pushTickState() {
savedPosition = this.position.clone(); savedPosition = this.position.clone();
savedInvPosition = @:privateAccess this.collider.invTransform.getPosition();
savedVelocity = this.velocity.clone(); savedVelocity = this.velocity.clone();
savedStopped = this.stopped; savedStopped = this.stopped;
savedStoppedPosition = this.stoppedPosition != null ? this.stoppedPosition.clone() : null; savedStoppedPosition = this.stoppedPosition != null ? this.stoppedPosition.clone() : null;
@ -262,7 +272,17 @@ class PathedInterior extends InteriorObject {
this.velocity.load(savedVelocity); this.velocity.load(savedVelocity);
this.stopped = savedStopped; this.stopped = savedStopped;
this.stoppedPosition = savedStoppedPosition; this.stoppedPosition = savedStoppedPosition;
var oldtPos = this.collider.transform.getPosition();
this.collider.transform.setPosition(savedPosition); this.collider.transform.setPosition(savedPosition);
@:privateAccess this.collider.invTransform.setPosition(savedInvPosition);
this.collider.boundingBox.xMin += savedPosition.x - oldtPos.x;
this.collider.boundingBox.xMax += savedPosition.x - oldtPos.x;
this.collider.boundingBox.yMin += savedPosition.y - oldtPos.y;
this.collider.boundingBox.yMax += savedPosition.y - oldtPos.y;
this.collider.boundingBox.zMin += savedPosition.z - oldtPos.z;
this.collider.boundingBox.zMax += savedPosition.z - oldtPos.z;
collisionWorld.updateTransform(this.collider); collisionWorld.updateTransform(this.collider);
this.currentTime = savedTime; this.currentTime = savedTime;
@ -301,7 +321,8 @@ class PathedInterior extends InteriorObject {
if (m1 == null) { if (m1 == null) {
// Incase there are no markers at all // Incase there are no markers at all
var tmp = new Matrix(); var tmp = new Matrix();
var mat = Matrix.S(this.baseScale.x, this.baseScale.y, this.baseScale.z); var mat = new Matrix();
mat.initScale(this.baseScale.x, this.baseScale.y, this.baseScale.z);
this.baseOrientation.toMatrix(tmp); this.baseOrientation.toMatrix(tmp);
mat.multiply3x4(mat, tmp); mat.multiply3x4(mat, tmp);
mat.setPosition(this.basePosition); mat.setPosition(this.basePosition);
@ -324,10 +345,10 @@ class PathedInterior extends InteriorObject {
var duration = m2Time - m1Time; var duration = m2Time - m1Time;
var position:Vector = null; var position:Vector = null;
var compvarion = Util.clamp(duration != 0 ? (time - m1Time) / duration : 1, 0, 1); var compvarion = Util.clamp(duration != 0 ? (time - m1Time) / duration : 1, 0, 1);
if (m1.smoothingType == "Accelerate") { if (m1.smoothingType == PathedInteriorMarker.SMOOTHING_ACCELERATE) {
// A simple easing function // A simple easing function
compvarion = Math.sin(compvarion * Math.PI - (Math.PI / 2)) * 0.5 + 0.5; compvarion = Math.sin(compvarion * Math.PI - (Math.PI / 2)) * 0.5 + 0.5;
} else if (m1.smoothingType == "Spline") { } else if (m1.smoothingType == PathedInteriorMarker.SMOOTHING_SPLINE) {
// Smooth the path like it's a Catmull-Rom spline. // Smooth the path like it's a Catmull-Rom spline.
var preStart = (i - 2) - 1; var preStart = (i - 2) - 1;
var postEnd = (i - 1) + 1; var postEnd = (i - 1) + 1;
@ -355,7 +376,8 @@ class PathedInterior extends InteriorObject {
position = position.add(basePosition); // Add the base position position = position.add(basePosition); // Add the base position
var tmp = new Matrix(); var tmp = new Matrix();
var mat = Matrix.S(this.baseScale.x, this.baseScale.y, this.baseScale.z); var mat = new Matrix();
mat.initScale(this.baseScale.x, this.baseScale.y, this.baseScale.z);
this.baseOrientation.toMatrix(tmp); this.baseOrientation.toMatrix(tmp);
mat.multiply3x4(mat, tmp); mat.multiply3x4(mat, tmp);
mat.setPosition(position); mat.setPosition(position);

View file

@ -5,10 +5,14 @@ import h3d.Vector;
class PathedInteriorMarker { class PathedInteriorMarker {
public var msToNext:Float; public var msToNext:Float;
public var smoothingType:String; public var smoothingType:Int;
public var position:Vector; public var position:Vector;
public var rotation:Quat; public var rotation:Quat;
public static var SMOOTHING_LINEAR = 0;
public static var SMOOTHING_ACCELERATE = 1;
public static var SMOOTHING_SPLINE = 2;
public function new() {} public function new() {}
public function clone() { public function clone() {

View file

@ -11,6 +11,7 @@ class Renderer extends h3d.scene.Renderer {
super(); super();
defaultPass = new h3d.pass.Default("default"); defaultPass = new h3d.pass.Default("default");
allPasses = [defaultPass, shadow]; allPasses = [defaultPass, shadow];
shadow.enabled = false;
} }
inline function get_def() inline function get_def()

View file

@ -146,110 +146,14 @@ class Collision {
} }
public static inline function TriangleSphereIntersection(v0:Vector, v1:Vector, v2:Vector, N:Vector, P:Vector, r:Float, point:Vector, normal:Vector) { public static inline function TriangleSphereIntersection(v0:Vector, v1:Vector, v2:Vector, N:Vector, P:Vector, r:Float, point:Vector, normal:Vector) {
var A = v0.sub(P); ClosestPtPointTriangle(P, v0, v1, v2, point);
var B = v1.sub(P); var v = point.sub(P);
var C = v2.sub(P); if (v.dot(v) <= r * r) {
var ca = C.sub(A); normal.load(P.sub(point));
var ba = B.sub(A); normal.normalize();
var radiusSq = r * r;
var cp = ba.cross(ca);
var aDotCp = A.dot(cp);
var cpLenSq = cp.lengthSq();
if (aDotCp * aDotCp > radiusSq * cpLenSq) {
return false;
}
var aSq = A.dot(A);
var aDotB = A.dot(B);
var aDotC = A.dot(C);
var bSq = B.dot(B);
var bDotC = B.dot(C);
var cSq = C.dot(C);
if (aSq > radiusSq && aDotB > aSq && aDotC > aSq) {
return false;
}
if (bSq > radiusSq && aDotB > bSq && bDotC > bSq) {
return false;
}
if (cSq > radiusSq && aDotC > cSq && bDotC > cSq) {
return false;
}
var cSubB = C.sub(B);
var aSubC = A.sub(C);
var baSq = ba.lengthSq();
var cSubBSq = cSubB.lengthSq();
var aSubCSq = aSubC.lengthSq();
var aTest = A.multiply(baSq).sub(ba.multiply(aDotB - aSq));
var bTest = B.multiply(cSubBSq).sub(cSubB.multiply(bDotC - bSq));
var cTest = C.multiply(aSubCSq).sub(aSubC.multiply(aDotC - cSq));
var rhs = C.multiply(baSq).sub(aTest);
var rhs2 = A.multiply(cSubBSq).sub(bTest);
var rhs3 = B.multiply(aSubCSq).sub(cTest);
if (aTest.dot(aTest) > radiusSq * baSq * baSq && aTest.dot(rhs) > 0) {
return false;
}
if (bTest.dot(bTest) > radiusSq * cSubBSq * cSubBSq && bTest.dot(rhs2) > 0) {
return false;
}
if (cTest.dot(cTest) > radiusSq * aSubCSq * aSubCSq && cTest.dot(rhs3) > 0) {
return false;
}
var lhs = P.sub(v0);
var baca = ba.dot(ca);
var caSq = ca.lengthSq();
var lhsBa = lhs.dot(ba);
var lhsCa = lhs.dot(ca);
var len = baSq * caSq - baca * baca;
var d1 = (caSq * lhsBa - baca * lhsCa) / len;
var d2 = (baSq * lhsCa - baca * lhsBa) / len;
if (1 - d1 - d2 >= 0 && d1 >= 0 && d2 >= 0) {
normal.load(N);
point.load(P.sub(N.multiply(P.sub(v0).dot(N))));
return true; return true;
} else { } else {
var closestPt = P.sub(N.multiply(P.sub(v0).dot(N))); return false;
var r1 = ClosestPointLine(v0, v1, closestPt);
var r2 = ClosestPointLine(v1, v2, closestPt);
var r3 = ClosestPointLine(v2, v0, closestPt);
var chosenEdge = 0; // Bitfield
var chosenPt:Vector = new Vector();
if (r1.distanceSq(P) < r2.distanceSq(P)) {
chosenPt.load(r1);
chosenEdge = 1;
} else {
chosenPt.load(r2);
chosenEdge = 2;
}
if (chosenPt.distanceSq(P) < r3.distanceSq(P))
point.load(chosenPt);
else {
chosenEdge = 4;
point.load(r3);
}
normal.load(P.sub(point).normalized());
return true;
// if (res.normal.dot(N) > 0.8) {
// // Internal edge
// if (chosenEdge & edgeData > 0) {
// chosenEdge -= 1;
// if (chosenEdge > 2)
// chosenEdge--;
// // if (edgeNormals[chosenEdge].length() < 0.5) {
// // res.normal = center.sub(res.point).normalized();
// // } else
// if (edgeConcavities[chosenEdge]) { // Our edge is concave
// res.normal = N.clone();
// }
// }
// }
} }
} }
@ -431,38 +335,65 @@ class Collision {
return null; return null;
} }
public static function ClosestPtPointTriangle(pt:Vector, radius:Float, p0:Vector, p1:Vector, p2:Vector, normal:Vector) { public static inline function ClosestPtPointTriangle(p:Vector, a:Vector, b:Vector, c:Vector, outP:Vector) {
var closest:Vector = null; // Check if P in vertex region outside A
var ptDot = pt.dot(normal); var ab = b.sub(a);
var triDot = p0.dot(normal); var ac = c.sub(a);
if (Math.abs(ptDot - triDot) > radius * 1.1) { var ap = p.sub(a);
return null; var d1 = ab.dot(ap);
var d2 = ac.dot(ap);
if (d1 <= 0.0 && d2 <= 0.0) { // barycentric coordinates (1,0,0)
outP.load(a);
return;
} }
closest = pt.add(normal.multiply(triDot - ptDot)); // Check if P in vertex region outside B
if (Collision.PointInTriangle2(closest, p0, p1, p2)) { var bp = p.sub(b);
return closest; var d3 = ab.dot(bp);
var d4 = ac.dot(bp);
if (d3 >= 0.0 && d4 <= d3) { // barycentric coordinates (0,1,0
outP.load(b);
return;
} }
var t = 10.0;
var r1 = Collision.IntersectSegmentCapsule(pt, pt, p0, p1, radius); // Check if P in edge region of AB, if so return projection of P onto AB
if (r1.result && r1.tSeg < t) { var vc = d1 * d4 - d3 * d2;
closest = p0.add((p1.sub(p0).multiply(r1.tCap))); if (vc <= 0.0 && d1 >= 0.0 && d3 <= 0.0) {
t = r1.tSeg; var v = d1 / (d1 - d3);
outP.load(a.add(ab.multiply(v)));
return;
} }
var r2 = Collision.IntersectSegmentCapsule(pt, pt, p1, p2, radius);
if (r2.result && r2.tSeg < t) { // Check if P in vertex region outside C
closest = p1.add((p2.sub(p1).multiply(r2.tCap))); var cp = p.sub(c);
t = r2.tSeg; var d5 = ab.dot(cp);
var d6 = ac.dot(cp);
if (d6 >= 0.0 && d5 <= d6) { // barycentric coordinates (0,0,1)
outP.load(c);
return;
} }
var r3 = Collision.IntersectSegmentCapsule(pt, pt, p2, p0, radius);
if (r3.result && r3.tSeg < t) { // Check if P in edge region of AC, if so return projection of P onto AC
closest = p2.add((p2.sub(p2).multiply(r3.tCap))); var vb = d5 * d2 - d1 * d6;
t = r3.tSeg; if (vb <= 0.0 && d2 >= 0.0 && d6 <= 0.0) {
var w = d2 / (d2 - d6);
outP.load(a.add(ac.multiply(w)));
return;
} }
var res = t < 1;
if (res) { // Check if P in edge region of BC, if so return projection of P onto BC
return closest; var va = d3 * d6 - d5 * d4;
if (va <= 0.0 && (d4 - d3) >= 0.0 && (d5 - d6) >= 0.0) {
var w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
outP.load(b.add((c.sub(b)).multiply(w)));
return;
} }
return null; // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
var denom = 1.0 / (va + vb + vc);
var v = vb * denom;
var w = vc * denom;
outP.load(a.add(ab.multiply(v)).add(ac.multiply(w)));
return;
} }
public static function capsuleSphereNearestOverlap(a0:Vector, a1:Vector, radA:Float, b:Vector, radB:Float) { public static function capsuleSphereNearestOverlap(a0:Vector, a1:Vector, radA:Float, b:Vector, radB:Float) {

View file

@ -96,26 +96,39 @@ class CollisionEntity implements IOctreeObject implements IBVHObject {
if (this.transform.equal(transform)) if (this.transform.equal(transform))
return; return;
// Speedup // Speedup
// if (this.fastTransform && Util.mat3x3equal(this.transform, transform)) { if (this.fastTransform && Util.mat3x3equal(this.transform, transform)) {
// var oldPos = this.transform.getPosition(); var oldPos = this.transform.getPosition();
// var newPos = transform.getPosition(); var newPos = transform.getPosition();
// this.transform.setPosition(newPos); this.transform.setPosition(newPos);
// this.invTransform = this.transform.getInverse(); this.invTransform.prependTranslation(oldPos.x - newPos.x, oldPos.y - newPos.y, oldPos.z - newPos.z);
// if (this.boundingBox == null) if (this.boundingBox == null)
// generateBoundingBox(); generateBoundingBox();
// else { else {
// this.boundingBox.xMin += newPos.x - oldPos.x; this.boundingBox.xMin += newPos.x - oldPos.x;
// this.boundingBox.xMax += newPos.x - oldPos.x; this.boundingBox.xMax += newPos.x - oldPos.x;
// this.boundingBox.yMin += newPos.y - oldPos.y; this.boundingBox.yMin += newPos.y - oldPos.y;
// this.boundingBox.yMax += newPos.y - oldPos.y; this.boundingBox.yMax += newPos.y - oldPos.y;
// this.boundingBox.zMin += newPos.z - oldPos.z; this.boundingBox.zMin += newPos.z - oldPos.z;
// this.boundingBox.zMax += newPos.z - oldPos.z; this.boundingBox.zMax += newPos.z - oldPos.z;
// }
// } else { if (Debug.drawBounds) {
this.transform.load(transform); if (_dbgEntity == null) {
this.invTransform = transform.getInverse(); _dbgEntity = cast this.boundingBox.makeDebugObj();
generateBoundingBox(); _dbgEntity.getMaterials()[0].mainPass.wireframe = true;
// } MarbleGame.instance.scene.addChild(_dbgEntity);
} else {
_dbgEntity.remove();
_dbgEntity = cast this.boundingBox.makeDebugObj();
_dbgEntity.getMaterials()[0].mainPass.wireframe = true;
MarbleGame.instance.scene.addChild(_dbgEntity);
}
}
}
} else {
this.transform.load(transform);
this.invTransform = transform.getInverse();
generateBoundingBox();
}
_transformKey++; _transformKey++;
} }

View file

@ -168,11 +168,11 @@ class MPPreGameDlg extends GuiControl {
}; };
dialogImg.addChild(levelName); dialogImg.addChild(levelName);
var levelDesc = new GuiText(markerFelt18); var levelDesc = new GuiMLText(markerFelt18, null);
levelDesc.text.textColor = 0xFFFFFF; levelDesc.text.textColor = 0xFFFFFF;
levelDesc.position = new Vector(60, 185); levelDesc.position = new Vector(60, 185);
levelDesc.extent = new Vector(516, 63); levelDesc.extent = new Vector(516, 63);
levelDesc.text.text = MarbleGame.instance.world.mission.description; levelDesc.text.text = StringTools.htmlEscape(MarbleGame.instance.world.mission.description);
levelDesc.text.dropShadow = { levelDesc.text.dropShadow = {
dx: 1, dx: 1,
dy: 1, dy: 1,
@ -244,8 +244,8 @@ class MPPreGameDlg extends GuiControl {
ready: Net.lobbyHostReady, ready: Net.lobbyHostReady,
spectate: Net.hostSpectate spectate: Net.hostSpectate
}); });
spectateBtn.pressed = Net.hostSpectate; spectateBtn.anim.currentFrame = Net.hostSpectate ? 2 : 0;
readyBtn.pressed = Net.lobbyHostReady; readyBtn.anim.currentFrame = Net.lobbyHostReady ? 2 : 0;
} }
if (Net.isClient) { if (Net.isClient) {
playerListArr.push({ playerListArr.push({
@ -253,8 +253,8 @@ class MPPreGameDlg extends GuiControl {
ready: Net.lobbyClientReady, ready: Net.lobbyClientReady,
spectate: Net.clientSpectate spectate: Net.clientSpectate
}); });
spectateBtn.pressed = Net.clientSpectate; spectateBtn.anim.currentFrame = Net.clientSpectate ? 2 : 0;
readyBtn.pressed = Net.lobbyClientReady; readyBtn.anim.currentFrame = Net.lobbyClientReady ? 2 : 0;
} }
if (Net.clientIdMap != null) { if (Net.clientIdMap != null) {
for (c => v in Net.clientIdMap) { for (c => v in Net.clientIdMap) {

View file

@ -346,8 +346,8 @@ class OptionsDlg extends GuiImage {
makeSlider("Field of View:", (Settings.optionsSettings.fovX - 60) / (140 - 60), yPos, generalPanel, (val) -> { makeSlider("Field of View:", (Settings.optionsSettings.fovX - 60) / (140 - 60), yPos, generalPanel, (val) -> {
Settings.optionsSettings.fovX = cast(60 + val * (140 - 60)); Settings.optionsSettings.fovX = cast(60 + val * (140 - 60));
}); });
makeSlider("Mouse Speed:", (Settings.controlsSettings.cameraSensitivity - 0.2) / (3 - 0.2), yPos, generalPanel, (val) -> { makeSlider("Mouse Speed:", (Settings.controlsSettings.cameraSensitivity - 0.12) / (1.2 - 0.12), yPos, generalPanel, (val) -> {
Settings.controlsSettings.cameraSensitivity = cast(0.2 + val * (3 - 0.2)); Settings.controlsSettings.cameraSensitivity = cast(0.12 + val * (1.2 - 0.12));
}, true); }, true);
function getConflictingBinding(bindingName:String, key:Int) { function getConflictingBinding(bindingName:String, key:Int) {

View file

@ -225,7 +225,7 @@ class PlayGui {
} }
if (Util.isTouchDevice()) { if (Util.isTouchDevice()) {
MarbleGame.instance.touchInput.showControls(this.playGuiCtrl, game == 'ultra'); MarbleGame.instance.touchInput.showControls(this.playGuiCtrl, game == 'ultra' || MarbleGame.instance.world.isMultiplayer);
} }
playGuiCtrl.render(scene2d); playGuiCtrl.render(scene2d);
@ -592,6 +592,10 @@ class PlayGui {
} }
public function setBlastValue(value:Float) { public function setBlastValue(value:Float) {
if (Net.clientSpectate || Net.hostSpectate) {
MarbleGame.instance.touchInput.blastbutton.setEnabled(true);
return; // Is not changed
}
if (value <= 1) { if (value <= 1) {
if (blastFill.extent.y == 16) { // Was previously charged if (blastFill.extent.y == 16) { // Was previously charged
blastFrame.bmp.tile = ResourceLoader.getResource("data/ui/game/blastbar.png", ResourceLoader.getImage, this.imageResources).toTile(); blastFrame.bmp.tile = ResourceLoader.getResource("data/ui/game/blastbar.png", ResourceLoader.getImage, this.imageResources).toTile();
@ -862,9 +866,10 @@ class PlayGui {
public function setSpectateMenu(enabled:Bool) { public function setSpectateMenu(enabled:Bool) {
if (enabled && spectatorCtrl == null) { if (enabled && spectatorCtrl == null) {
initSpectatorMenu(); initSpectatorMenu();
playGuiCtrl.render(MarbleGame.canvas.scene2d); spectatorCtrl.render(MarbleGame.canvas.scene2d, @:privateAccess playGuiCtrl._flow);
blastFill.bmp.visible = false; blastFill.bmp.visible = false;
blastFrame.bmp.visible = false; blastFrame.bmp.visible = false;
return true;
} }
if (!enabled && spectatorCtrl != null) { if (!enabled && spectatorCtrl != null) {
spectatorCtrl.dispose(); spectatorCtrl.dispose();
@ -872,7 +877,9 @@ class PlayGui {
blastFill.bmp.visible = true; blastFill.bmp.visible = true;
blastFrame.bmp.visible = true; blastFrame.bmp.visible = true;
spectatorTxtMode = -1; spectatorTxtMode = -1;
return true;
} }
return false;
} }
public function setSpectateMenuText(mode:Int) { public function setSpectateMenuText(mode:Int) {

View file

@ -550,10 +550,6 @@ class HuntMode extends NullMode {
var beam = gemToBeamMap.get(gem); var beam = gemToBeamMap.get(gem);
beam.setHide(true); beam.setHide(true);
if (!this.level.isMultiplayer || Net.isHost) {
spawnHuntGems();
}
var incr = 0; var incr = 0;
switch (gem.gemColor.toLowerCase()) { switch (gem.gemColor.toLowerCase()) {
case "red.gem": case "red.gem":
@ -641,6 +637,9 @@ class HuntMode extends NullMode {
if (this.level.isMultiplayer && Net.isClient) { if (this.level.isMultiplayer && Net.isClient) {
gem.pickUpClient = @:privateAccess marble.connection == null ? Net.clientId : @:privateAccess marble.connection.id; gem.pickUpClient = @:privateAccess marble.connection == null ? Net.clientId : @:privateAccess marble.connection.id;
} }
if (!this.level.isMultiplayer || Net.isHost) {
spawnHuntGems();
}
} }
public function setCompetitiveTimerStartTicks(ticks:Int) { public function setCompetitiveTimerStartTicks(ticks:Int) {

View file

@ -8,10 +8,16 @@ import src.ResourceLoader;
import src.Settings; import src.Settings;
class BlastButton extends TouchButton { class BlastButton extends TouchButton {
public var didPressIt:Bool = true;
public function new() { public function new() {
var mode = MarbleGame.instance.world != null ? @:privateAccess MarbleGame.instance.world.marble.camera.spectate : false; var mode = MarbleGame.instance.world != null ? @:privateAccess MarbleGame.instance.world.marble.camera.spectate : false;
super(ResourceLoader.getImage(mode ? "data/ui/touch/video-camera.png" : "data/ui/touch/explosion.png").resource, super(ResourceLoader.getImage(mode ? "data/ui/touch/video-camera.png" : "data/ui/touch/explosion.png").resource,
new Vector(Settings.touchSettings.blastButtonPos[0], Settings.touchSettings.blastButtonPos[1]), Settings.touchSettings.blastButtonSize); new Vector(Settings.touchSettings.blastButtonPos[0], Settings.touchSettings.blastButtonPos[1]), Settings.touchSettings.blastButtonSize);
this.setEnabled(false); this.setEnabled(false);
this.onClick = () -> {
this.pressed = true;
didPressIt = true;
}
} }
} }

View file

@ -87,9 +87,9 @@ class CameraInput {
if (jumpcam) { if (jumpcam) {
scaleFactor /= Settings.touchSettings.buttonJoystickMultiplier; scaleFactor /= Settings.touchSettings.buttonJoystickMultiplier;
} }
if (Math.abs(delta.x) < 0.03) if (Math.abs(delta.x) < 0.05)
delta.x = 0; delta.x = 0;
if (Math.abs(delta.y) < 0.03) if (Math.abs(delta.y) < 0.05)
delta.y = 0; delta.y = 0;
MarbleGame.instance.world.marble.camera.orbit(applyNonlinearScale(delta.x / scaleFactor), applyNonlinearScale(delta.y / scaleFactor), true); MarbleGame.instance.world.marble.camera.orbit(applyNonlinearScale(delta.x / scaleFactor), applyNonlinearScale(delta.y / scaleFactor), true);
if (delta.x != 0) if (delta.x != 0)

View file

@ -12,7 +12,7 @@ class PauseButton extends TouchButton {
this.guiElement.vertSizing = Bottom; this.guiElement.vertSizing = Bottom;
this.onClick = () -> { this.onClick = () -> {
if (MarbleGame.instance.world != null) { if (MarbleGame.instance.world != null && @:privateAccess !MarbleGame.instance.paused) {
@:privateAccess MarbleGame.instance.paused = true; @:privateAccess MarbleGame.instance.paused = true;
MarbleGame.instance.handlePauseGame(); MarbleGame.instance.handlePauseGame();
} }

View file

@ -0,0 +1,25 @@
package touch;
import src.MarbleGame;
import touch.TouchInput.Touch;
import h3d.Vector;
import hxd.Window;
import src.ResourceLoader;
import src.Settings;
class SpectatorChangeTargetButton extends TouchButton {
public var didPressIt:Bool = true;
public function new(rightFacing:Bool) {
super(ResourceLoader.getImage(rightFacing ? "data/ui/touch/right.png" : "data/ui/touch/left.png").resource, new Vector(rightFacing ? 560 : 70, 120),
60);
if (!rightFacing) {
this.guiElement.horizSizing = Right;
}
this.setEnabled(false);
this.onClick = () -> {
this.pressed = true;
didPressIt = true;
}
}
}

View file

@ -4,6 +4,8 @@ import gui.GuiControl;
import src.MarbleWorld; import src.MarbleWorld;
import h3d.Vector; import h3d.Vector;
import src.Settings; import src.Settings;
import src.MarbleGame;
import src.ResourceLoader;
enum TouchState { enum TouchState {
Pressed; Pressed;
@ -44,6 +46,8 @@ class TouchInput {
public var pauseButton:PauseButton; public var pauseButton:PauseButton;
public var rewindButton:RewindButton; public var rewindButton:RewindButton;
public var restartButton:RestartButton; public var restartButton:RestartButton;
public var leftButton:SpectatorChangeTargetButton;
public var rightButton:SpectatorChangeTargetButton;
public var currentTouchState:TouchEventState; public var currentTouchState:TouchEventState;
@ -118,17 +122,19 @@ class TouchInput {
this.movementInput = new MovementInput(); this.movementInput = new MovementInput();
this.jumpButton = new JumpButton(); this.jumpButton = new JumpButton();
this.powerupButton = new PowerupButton(); this.powerupButton = new PowerupButton();
if (Settings.optionsSettings.rewindEnabled) if (Settings.optionsSettings.rewindEnabled && !MarbleGame.instance.world.isMultiplayer)
this.rewindButton = new RewindButton(); this.rewindButton = new RewindButton();
if (ultra) if (ultra)
this.blastbutton = new BlastButton(); this.blastbutton = new BlastButton();
this.pauseButton = new PauseButton(); this.pauseButton = new PauseButton();
this.restartButton = new RestartButton(); if (!MarbleGame.instance.world.isMultiplayer)
this.restartButton = new RestartButton();
pauseButton.add(parentGui); pauseButton.add(parentGui);
restartButton.add(parentGui); if (!MarbleGame.instance.world.isMultiplayer)
restartButton.add(parentGui);
jumpButton.add(parentGui); jumpButton.add(parentGui);
powerupButton.add(parentGui); powerupButton.add(parentGui);
if (Settings.optionsSettings.rewindEnabled) if (Settings.optionsSettings.rewindEnabled && !MarbleGame.instance.world.isMultiplayer)
rewindButton.add(parentGui); rewindButton.add(parentGui);
if (ultra) if (ultra)
blastbutton.add(parentGui); blastbutton.add(parentGui);
@ -147,6 +153,10 @@ class TouchInput {
this.restartButton.setVisible(false); this.restartButton.setVisible(false);
if (this.rewindButton != null) if (this.rewindButton != null)
this.rewindButton.setVisible(false); this.rewindButton.setVisible(false);
if (this.leftButton != null)
this.leftButton.setVisible(false);
if (this.rightButton != null)
this.rightButton.setVisible(false);
} }
} }
@ -157,10 +167,15 @@ class TouchInput {
this.blastbutton.setVisible(enabled); this.blastbutton.setVisible(enabled);
this.movementInput.setVisible(enabled); this.movementInput.setVisible(enabled);
this.pauseButton.setVisible(enabled); this.pauseButton.setVisible(enabled);
this.restartButton.setVisible(enabled); if (this.restartButton != null)
this.restartButton.setVisible(enabled);
if (this.rewindButton != null) if (this.rewindButton != null)
this.rewindButton.setVisible(enabled); this.rewindButton.setVisible(enabled);
this.cameraInput.enabled = enabled; this.cameraInput.enabled = enabled;
if (this.leftButton != null)
this.leftButton.setVisible(enabled);
if (this.rightButton != null)
this.rightButton.setVisible(enabled);
if (Settings.touchSettings.hideControls) { if (Settings.touchSettings.hideControls) {
this.jumpButton.setVisible(false); this.jumpButton.setVisible(false);
@ -170,6 +185,10 @@ class TouchInput {
this.movementInput.setVisible(false); this.movementInput.setVisible(false);
if (this.rewindButton != null) if (this.rewindButton != null)
this.rewindButton.setVisible(false); this.rewindButton.setVisible(false);
if (this.leftButton != null)
this.leftButton.setVisible(false);
if (this.rightButton != null)
this.rightButton.setVisible(false);
} }
} }
@ -180,10 +199,19 @@ class TouchInput {
blastbutton.remove(parentGui); blastbutton.remove(parentGui);
movementInput.remove(parentGui); movementInput.remove(parentGui);
pauseButton.remove(parentGui); pauseButton.remove(parentGui);
restartButton.remove(parentGui); if (this.restartButton != null)
restartButton.remove(parentGui);
cameraInput.remove(parentGui); cameraInput.remove(parentGui);
if (this.rewindButton != null) if (this.rewindButton != null)
rewindButton.remove(parentGui); rewindButton.remove(parentGui);
if (this.leftButton != null) {
leftButton.remove(parentGui);
leftButton.dispose();
}
if (this.rightButton != null) {
rightButton.remove(parentGui);
rightButton.dispose();
}
jumpButton.dispose(); jumpButton.dispose();
powerupButton.dispose(); powerupButton.dispose();
movementInput.dispose(); movementInput.dispose();
@ -193,4 +221,41 @@ class TouchInput {
if (this.rewindButton != null) if (this.rewindButton != null)
rewindButton.dispose(); rewindButton.dispose();
} }
public function setSpectatorControls(enabled:Bool) {
var tile = ResourceLoader.getImage(enabled ? "data/ui/touch/video-camera.png" : "data/ui/touch/explosion.png").resource;
@:privateAccess this.blastbutton.guiElement.graphics.content.state.tail.texture = tile.toTexture();
if (enabled) {
jumpButton.setVisible(false);
if (this.leftButton == null) { // both are added at same time so it doesnt matter
var par = jumpButton.guiElement.parent;
this.leftButton = new SpectatorChangeTargetButton(false);
this.rightButton = new SpectatorChangeTargetButton(true);
this.leftButton.add(par);
this.rightButton.add(par);
this.leftButton.guiElement.render(MarbleGame.canvas.scene2d, @:privateAccess par._flow);
this.rightButton.guiElement.render(MarbleGame.canvas.scene2d, @:privateAccess par._flow);
}
} else {
jumpButton.setVisible(true);
if (this.leftButton != null) {
this.leftButton.remove(this.leftButton.guiElement.parent);
this.leftButton.dispose();
this.leftButton = null;
}
if (this.rightButton != null) {
this.rightButton.remove(this.rightButton.guiElement.parent);
this.rightButton.dispose();
this.rightButton = null;
}
}
}
public function setSpectatorControlsVisibility(enabled:Bool) {
if (this.leftButton != null) {
this.leftButton.setVisible(enabled);
this.rightButton.setVisible(enabled);
this.movementInput.setVisible(!enabled);
}
}
} }