mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2025-10-30 08:11:25 +00:00
refactor a lot to get powerups sorta working
This commit is contained in:
parent
1fef9a5bdc
commit
bd8527bae6
28 changed files with 286 additions and 151 deletions
|
|
@ -6,6 +6,7 @@ import h3d.scene.Object;
|
||||||
import src.Resource;
|
import src.Resource;
|
||||||
import h3d.mat.Texture;
|
import h3d.mat.Texture;
|
||||||
import hxd.res.Sound;
|
import hxd.res.Sound;
|
||||||
|
import src.Marble;
|
||||||
|
|
||||||
class GameObject extends Object {
|
class GameObject extends Object {
|
||||||
public var identifier:String;
|
public var identifier:String;
|
||||||
|
|
@ -22,13 +23,13 @@ class GameObject extends Object {
|
||||||
return currentOpacity;
|
return currentOpacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onMarbleContact(time:TimeState, ?contact:CollisionInfo) {}
|
public function onMarbleContact(marble:Marble, time:TimeState, ?contact:CollisionInfo) {}
|
||||||
|
|
||||||
public function onMarbleInside(time:TimeState) {}
|
public function onMarbleInside(marble:Marble, time:TimeState) {}
|
||||||
|
|
||||||
public function onMarbleEnter(time:TimeState) {}
|
public function onMarbleEnter(marble:Marble, time:TimeState) {}
|
||||||
|
|
||||||
public function onMarbleLeave(time:TimeState) {}
|
public function onMarbleLeave(marble:Marble, time:TimeState) {}
|
||||||
|
|
||||||
public function onLevelStart() {}
|
public function onLevelStart() {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package src;
|
package src;
|
||||||
|
|
||||||
|
import net.NetPacket.MarbleUpdatePacket;
|
||||||
import net.MoveManager;
|
import net.MoveManager;
|
||||||
import net.MoveManager.NetMove;
|
import net.MoveManager.NetMove;
|
||||||
import shaders.marble.CrystalMarb;
|
import shaders.marble.CrystalMarb;
|
||||||
|
|
@ -1573,7 +1574,7 @@ class Marble extends GameObject {
|
||||||
var pTime = timeState.clone();
|
var pTime = timeState.clone();
|
||||||
pTime.dt = timeStep;
|
pTime.dt = timeStep;
|
||||||
pTime.currentAttemptTime = passedTime;
|
pTime.currentAttemptTime = passedTime;
|
||||||
this.heldPowerup.use(pTime);
|
this.heldPowerup.use(this, pTime);
|
||||||
this.heldPowerup = null;
|
this.heldPowerup = null;
|
||||||
if (this.level.isRecording) {
|
if (this.level.isRecording) {
|
||||||
this.level.replay.recordPowerupPickup(null);
|
this.level.replay.recordPowerupPickup(null);
|
||||||
|
|
@ -1608,7 +1609,7 @@ class Marble extends GameObject {
|
||||||
|
|
||||||
newPos = this.collider.transform.getPosition();
|
newPos = this.collider.transform.getPosition();
|
||||||
|
|
||||||
if (this.controllable && this.prevPos != null) {
|
if (this.prevPos != null) {
|
||||||
var tempTimeState = timeState.clone();
|
var tempTimeState = timeState.clone();
|
||||||
tempTimeState.currentAttemptTime = passedTime;
|
tempTimeState.currentAttemptTime = passedTime;
|
||||||
this.level.callCollisionHandlers(cast this, tempTimeState, oldPos, newPos);
|
this.level.callCollisionHandlers(cast this, tempTimeState, oldPos, newPos);
|
||||||
|
|
@ -1622,55 +1623,24 @@ class Marble extends GameObject {
|
||||||
public function packUpdate(move:NetMove) {
|
public function packUpdate(move:NetMove) {
|
||||||
var b = new haxe.io.BytesOutput();
|
var b = new haxe.io.BytesOutput();
|
||||||
b.writeByte(NetPacketType.MarbleUpdate);
|
b.writeByte(NetPacketType.MarbleUpdate);
|
||||||
b.writeUInt16(connection != null ? connection.id : 0);
|
var marbleUpdate = new MarbleUpdatePacket();
|
||||||
MoveManager.packMove(move, b);
|
marbleUpdate.clientId = connection != null ? connection.id : 0;
|
||||||
b.writeUInt16(this.level.ticks); // So we can get the clients to do stuff about it
|
marbleUpdate.serverTicks = move.timeState.ticks;
|
||||||
b.writeFloat(this.newPos.x);
|
marbleUpdate.position = this.newPos;
|
||||||
b.writeFloat(this.newPos.y);
|
marbleUpdate.velocity = this.velocity;
|
||||||
b.writeFloat(this.newPos.z);
|
marbleUpdate.omega = this.omega;
|
||||||
b.writeFloat(this.velocity.x);
|
marbleUpdate.move = move;
|
||||||
b.writeFloat(this.velocity.y);
|
marbleUpdate.serialize(b);
|
||||||
b.writeFloat(this.velocity.z);
|
|
||||||
b.writeFloat(this.omega.x);
|
|
||||||
b.writeFloat(this.omega.y);
|
|
||||||
b.writeFloat(this.omega.z);
|
|
||||||
return b.getBytes();
|
return b.getBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unpackUpdate(b:haxe.io.BytesInput) {
|
public function unpackUpdate(p:MarbleUpdatePacket) {
|
||||||
// Assume packet header is already read
|
// Assume packet header is already read
|
||||||
var serverMove = MoveManager.unpackMove(b);
|
|
||||||
if (Net.isClient)
|
|
||||||
Net.clientConnection.moveManager.acknowledgeMove(serverMove.id);
|
|
||||||
var serverTicks = b.readUInt16();
|
|
||||||
this.oldPos = this.newPos;
|
this.oldPos = this.newPos;
|
||||||
this.newPos = new Vector(b.readFloat(), b.readFloat(), b.readFloat());
|
this.newPos = p.position;
|
||||||
this.collider.transform.setPosition(this.newPos);
|
this.collider.transform.setPosition(this.newPos);
|
||||||
this.velocity = new Vector(b.readFloat(), b.readFloat(), b.readFloat());
|
this.velocity = p.velocity;
|
||||||
this.omega = new Vector(b.readFloat(), b.readFloat(), b.readFloat());
|
this.omega = p.omega;
|
||||||
|
|
||||||
// Apply the moves we have queued
|
|
||||||
if (Net.isClient) {
|
|
||||||
this.isNetUpdate = true;
|
|
||||||
if (this.controllable) {
|
|
||||||
for (move in @:privateAccess Net.clientConnection.moveManager.queuedMoves) {
|
|
||||||
moveMotionDir = move.motionDir;
|
|
||||||
advancePhysics(move.timeState, move.move, this.level.collisionWorld, this.level.pathedInteriors);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var tickDiff = this.level.ticks - serverTicks;
|
|
||||||
if (tickDiff > 0) {
|
|
||||||
var timeState = this.level.timeState.clone();
|
|
||||||
timeState.dt = 0.032;
|
|
||||||
var m = serverMove.move;
|
|
||||||
moveMotionDir = serverMove.motionDir;
|
|
||||||
for (o in 0...tickDiff) {
|
|
||||||
advancePhysics(timeState, m, this.level.collisionWorld, this.level.pathedInteriors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.isNetUpdate = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateServer(timeState:TimeState, collisionWorld:CollisionWorld, pathedInteriors:Array<PathedInterior>, packets:Array<haxe.io.Bytes>) {
|
public function updateServer(timeState:TimeState, collisionWorld:CollisionWorld, pathedInteriors:Array<PathedInterior>, packets:Array<haxe.io.Bytes>) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package src;
|
package src;
|
||||||
|
|
||||||
|
import net.NetPacket.MarbleUpdatePacket;
|
||||||
|
import net.NetPacket.MarbleMovePacket;
|
||||||
import net.MoveManager;
|
import net.MoveManager;
|
||||||
import net.NetCommands;
|
import net.NetCommands;
|
||||||
import net.Net;
|
import net.Net;
|
||||||
|
|
@ -196,12 +198,14 @@ class MarbleWorld extends Scheduler {
|
||||||
|
|
||||||
public var startRealTime:Float = 0;
|
public var startRealTime:Float = 0;
|
||||||
public var multiplayerStarted:Bool = false;
|
public var multiplayerStarted:Bool = false;
|
||||||
public var ticks:Int = 0; // How many 32ms ticks have happened
|
|
||||||
|
|
||||||
var tickAccumulator:Float = 0.0;
|
var tickAccumulator:Float = 0.0;
|
||||||
|
var maxPredictionTicks:Int = 16;
|
||||||
|
|
||||||
var clientMarbles:Map<ClientConnection, Marble> = [];
|
var clientMarbles:Map<ClientConnection, Marble> = [];
|
||||||
|
|
||||||
|
public var lastMoves:Map<Int, MarbleUpdatePacket> = [];
|
||||||
|
|
||||||
// Loading
|
// Loading
|
||||||
var resourceLoadFuncs:Array<(() -> Void)->Void> = [];
|
var resourceLoadFuncs:Array<(() -> Void)->Void> = [];
|
||||||
|
|
||||||
|
|
@ -588,7 +592,7 @@ class MarbleWorld extends Scheduler {
|
||||||
interior.reset();
|
interior.reset();
|
||||||
|
|
||||||
this.setUp(startquat.up, this.timeState, true);
|
this.setUp(startquat.up, this.timeState, true);
|
||||||
this.deselectPowerUp();
|
this.deselectPowerUp(this.marble);
|
||||||
playGui.setCenterText('');
|
playGui.setCenterText('');
|
||||||
|
|
||||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/spawn_alternate.wav', ResourceLoader.getAudio, this.soundResources));
|
AudioManager.playSound(ResourceLoader.getResource('data/sound/spawn_alternate.wav', ResourceLoader.getAudio, this.soundResources));
|
||||||
|
|
@ -1020,6 +1024,53 @@ class MarbleWorld extends Scheduler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function applyReceivedMoves() {
|
||||||
|
for (client => lastMove in lastMoves) {
|
||||||
|
if (lastMove.applied)
|
||||||
|
continue;
|
||||||
|
if (lastMove.clientId == Net.clientId)
|
||||||
|
marble.unpackUpdate(lastMove);
|
||||||
|
else
|
||||||
|
clientMarbles[Net.clientIdMap[client]].unpackUpdate(lastMove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function applyClientPrediction() {
|
||||||
|
for (client => lastMove in lastMoves) {
|
||||||
|
if (lastMove.applied)
|
||||||
|
continue;
|
||||||
|
var marbleToUpdate = lastMove.clientId == Net.clientId ? marble : clientMarbles[Net.clientIdMap[client]];
|
||||||
|
|
||||||
|
@:privateAccess marbleToUpdate.isNetUpdate = true;
|
||||||
|
if (marbleToUpdate == marble) {
|
||||||
|
var moveManager = @:privateAccess Net.clientConnection.moveManager;
|
||||||
|
var catchUpTickCount = 0;
|
||||||
|
Net.clientConnection.moveManager.acknowledgeMove(lastMove.move.id);
|
||||||
|
var advanceTimeState = timeState.clone();
|
||||||
|
advanceTimeState.dt = 0.032;
|
||||||
|
for (move in @:privateAccess moveManager.queuedMoves) {
|
||||||
|
@:privateAccess marbleToUpdate.moveMotionDir = move.motionDir;
|
||||||
|
@:privateAccess marbleToUpdate.advancePhysics(advanceTimeState, move.move, this.collisionWorld, this.pathedInteriors);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var tickDiff = timeState.ticks - lastMove.serverTicks;
|
||||||
|
if (tickDiff > this.maxPredictionTicks)
|
||||||
|
tickDiff = this.maxPredictionTicks;
|
||||||
|
if (tickDiff > 0) {
|
||||||
|
var advanceTimeState = timeState.clone();
|
||||||
|
advanceTimeState.dt = 0.032;
|
||||||
|
var m = lastMove.move.move;
|
||||||
|
@:privateAccess marbleToUpdate.moveMotionDir = lastMove.move.motionDir;
|
||||||
|
for (o in 0...(tickDiff + 1)) {
|
||||||
|
@:privateAccess marbleToUpdate.advancePhysics(advanceTimeState, m, this.collisionWorld, this.pathedInteriors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@:privateAccess marbleToUpdate.isNetUpdate = false;
|
||||||
|
lastMove.applied = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function rollback(t:Float) {
|
public function rollback(t:Float) {
|
||||||
var newT = timeState.currentAttemptTime - t;
|
var newT = timeState.currentAttemptTime - t;
|
||||||
var rewindFrame = rewindManager.getNextRewindFrame(timeState.currentAttemptTime - t);
|
var rewindFrame = rewindManager.getNextRewindFrame(timeState.currentAttemptTime - t);
|
||||||
|
|
@ -1216,6 +1267,14 @@ class MarbleWorld extends Scheduler {
|
||||||
if (this.isMultiplayer) {
|
if (this.isMultiplayer) {
|
||||||
tickAccumulator += timeState.dt;
|
tickAccumulator += timeState.dt;
|
||||||
while (tickAccumulator >= 0.032) {
|
while (tickAccumulator >= 0.032) {
|
||||||
|
// Apply the server side ticks
|
||||||
|
if (Net.isClient) {
|
||||||
|
applyReceivedMoves();
|
||||||
|
// Catch up
|
||||||
|
applyClientPrediction();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the clientside prediction sim
|
||||||
var fixedDt = timeState.clone();
|
var fixedDt = timeState.clone();
|
||||||
fixedDt.dt = 0.032;
|
fixedDt.dt = 0.032;
|
||||||
tickAccumulator -= 0.032;
|
tickAccumulator -= 0.032;
|
||||||
|
|
@ -1231,7 +1290,7 @@ class MarbleWorld extends Scheduler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ticks++;
|
timeState.ticks++;
|
||||||
}
|
}
|
||||||
marble.updateClient(timeState, this.pathedInteriors);
|
marble.updateClient(timeState, this.pathedInteriors);
|
||||||
for (client => marble in clientMarbles) {
|
for (client => marble in clientMarbles) {
|
||||||
|
|
@ -1491,10 +1550,10 @@ class MarbleWorld extends Scheduler {
|
||||||
var shape:DtsObject = cast contact.go;
|
var shape:DtsObject = cast contact.go;
|
||||||
|
|
||||||
if (contact.boundingBox.collide(box)) {
|
if (contact.boundingBox.collide(box)) {
|
||||||
shape.onMarbleInside(timeState);
|
shape.onMarbleInside(marble, timeState);
|
||||||
if (!this.shapeOrTriggerInside.contains(contact.go)) {
|
if (!this.shapeOrTriggerInside.contains(contact.go)) {
|
||||||
this.shapeOrTriggerInside.push(contact.go);
|
this.shapeOrTriggerInside.push(contact.go);
|
||||||
shape.onMarbleEnter(timeState);
|
shape.onMarbleEnter(marble, timeState);
|
||||||
}
|
}
|
||||||
inside.push(contact.go);
|
inside.push(contact.go);
|
||||||
}
|
}
|
||||||
|
|
@ -1504,10 +1563,10 @@ class MarbleWorld extends Scheduler {
|
||||||
var triggeraabb = trigger.collider.boundingBox;
|
var triggeraabb = trigger.collider.boundingBox;
|
||||||
|
|
||||||
if (triggeraabb.collide(box)) {
|
if (triggeraabb.collide(box)) {
|
||||||
trigger.onMarbleInside(timeState);
|
trigger.onMarbleInside(marble, timeState);
|
||||||
if (!this.shapeOrTriggerInside.contains(contact.go)) {
|
if (!this.shapeOrTriggerInside.contains(contact.go)) {
|
||||||
this.shapeOrTriggerInside.push(contact.go);
|
this.shapeOrTriggerInside.push(contact.go);
|
||||||
trigger.onMarbleEnter(timeState);
|
trigger.onMarbleEnter(marble, timeState);
|
||||||
}
|
}
|
||||||
inside.push(contact.go);
|
inside.push(contact.go);
|
||||||
}
|
}
|
||||||
|
|
@ -1518,7 +1577,7 @@ class MarbleWorld extends Scheduler {
|
||||||
for (object in shapeOrTriggerInside) {
|
for (object in shapeOrTriggerInside) {
|
||||||
if (!inside.contains(object)) {
|
if (!inside.contains(object)) {
|
||||||
this.shapeOrTriggerInside.remove(object);
|
this.shapeOrTriggerInside.remove(object);
|
||||||
object.onMarbleLeave(timeState);
|
object.onMarbleLeave(marble, timeState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1726,27 +1785,31 @@ class MarbleWorld extends Scheduler {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pickUpPowerUp(powerUp:PowerUp) {
|
public function pickUpPowerUp(marble:Marble, powerUp:PowerUp) {
|
||||||
if (powerUp == null)
|
if (powerUp == null)
|
||||||
return false;
|
return false;
|
||||||
if (this.marble.heldPowerup != null)
|
if (marble.heldPowerup != null)
|
||||||
if (this.marble.heldPowerup.identifier == powerUp.identifier)
|
if (marble.heldPowerup.identifier == powerUp.identifier)
|
||||||
return false;
|
return false;
|
||||||
Console.log("PowerUp pickup: " + powerUp.identifier);
|
Console.log("PowerUp pickup: " + powerUp.identifier);
|
||||||
this.marble.heldPowerup = powerUp;
|
marble.heldPowerup = powerUp;
|
||||||
|
if (this.marble == marble) {
|
||||||
this.playGui.setPowerupImage(powerUp.identifier);
|
this.playGui.setPowerupImage(powerUp.identifier);
|
||||||
MarbleGame.instance.touchInput.powerupButton.setEnabled(true);
|
MarbleGame.instance.touchInput.powerupButton.setEnabled(true);
|
||||||
|
}
|
||||||
if (this.isRecording) {
|
if (this.isRecording) {
|
||||||
this.replay.recordPowerupPickup(powerUp);
|
this.replay.recordPowerupPickup(powerUp);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deselectPowerUp() {
|
public function deselectPowerUp(marble:Marble) {
|
||||||
this.marble.heldPowerup = null;
|
marble.heldPowerup = null;
|
||||||
|
if (this.marble == marble) {
|
||||||
this.playGui.setPowerupImage("");
|
this.playGui.setPowerupImage("");
|
||||||
MarbleGame.instance.touchInput.powerupButton.setEnabled(false);
|
MarbleGame.instance.touchInput.powerupButton.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function addBonusTime(t:Float) {
|
public function addBonusTime(t:Float) {
|
||||||
this.bonusTime += t;
|
this.bonusTime += t;
|
||||||
|
|
@ -1929,11 +1992,11 @@ class MarbleWorld extends Scheduler {
|
||||||
this.playGui.setCenterText('');
|
this.playGui.setCenterText('');
|
||||||
this.clearSchedule();
|
this.clearSchedule();
|
||||||
this.outOfBounds = false;
|
this.outOfBounds = false;
|
||||||
this.deselectPowerUp(); // Always deselect first
|
this.deselectPowerUp(this.marble); // Always deselect first
|
||||||
// Wait a bit to select the powerup to prevent immediately using it incase the user skipped the OOB screen by clicking
|
// Wait a bit to select the powerup to prevent immediately using it incase the user skipped the OOB screen by clicking
|
||||||
if (this.checkpointHeldPowerup != null) {
|
if (this.checkpointHeldPowerup != null) {
|
||||||
var powerup = this.checkpointHeldPowerup;
|
var powerup = this.checkpointHeldPowerup;
|
||||||
this.pickUpPowerUp(powerup);
|
this.pickUpPowerUp(this.marble, powerup);
|
||||||
}
|
}
|
||||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/spawn_alternate.wav', ResourceLoader.getAudio, this.soundResources));
|
AudioManager.playSound(ResourceLoader.getResource('data/sound/spawn_alternate.wav', ResourceLoader.getAudio, this.soundResources));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ class TimeState {
|
||||||
var currentAttemptTime:Float;
|
var currentAttemptTime:Float;
|
||||||
var gameplayClock:Float;
|
var gameplayClock:Float;
|
||||||
var dt:Float;
|
var dt:Float;
|
||||||
|
var ticks:Int; // How many 32ms ticks have happened
|
||||||
|
|
||||||
public function new() {}
|
public function new() {}
|
||||||
|
|
||||||
|
|
@ -15,6 +16,7 @@ class TimeState {
|
||||||
n.currentAttemptTime = this.currentAttemptTime;
|
n.currentAttemptTime = this.currentAttemptTime;
|
||||||
n.gameplayClock = this.gameplayClock;
|
n.gameplayClock = this.gameplayClock;
|
||||||
n.dt = this.dt;
|
n.dt = this.dt;
|
||||||
|
n.ticks = ticks;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -247,7 +247,7 @@ class CollisionEntity implements IOctreeObject implements IBVHObject {
|
||||||
cinfo.force = surface.force;
|
cinfo.force = surface.force;
|
||||||
cinfo.friction = surface.friction;
|
cinfo.friction = surface.friction;
|
||||||
contacts.push(cinfo);
|
contacts.push(cinfo);
|
||||||
this.go.onMarbleContact(timeState, cinfo);
|
this.go.onMarbleContact(collisionEntity.marble, timeState, cinfo);
|
||||||
// surfaceBestContact = cinfo;
|
// surfaceBestContact = cinfo;
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ class CollisionHull extends CollisionEntity {
|
||||||
cinfo.otherObject = this.go;
|
cinfo.otherObject = this.go;
|
||||||
cinfo.friction = friction;
|
cinfo.friction = friction;
|
||||||
cinfo.force = force;
|
cinfo.force = force;
|
||||||
this.go.onMarbleContact(timeState, cinfo);
|
this.go.onMarbleContact(collisionEntity.marble, timeState, cinfo);
|
||||||
return [cinfo];
|
return [cinfo];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ class Polygon extends MeshPrimitive {
|
||||||
public var uvs:Array<UV>;
|
public var uvs:Array<UV>;
|
||||||
public var idx:hxd.IndexBuffer;
|
public var idx:hxd.IndexBuffer;
|
||||||
|
|
||||||
|
var bounds:h3d.col.Bounds;
|
||||||
|
|
||||||
var scaled = 1.;
|
var scaled = 1.;
|
||||||
var translatedX = 0.;
|
var translatedX = 0.;
|
||||||
var translatedY = 0.;
|
var translatedY = 0.;
|
||||||
|
|
@ -23,10 +25,13 @@ class Polygon extends MeshPrimitive {
|
||||||
}
|
}
|
||||||
|
|
||||||
override function getBounds() {
|
override function getBounds() {
|
||||||
|
if (bounds == null) {
|
||||||
var b = new h3d.col.Bounds();
|
var b = new h3d.col.Bounds();
|
||||||
for (p in points)
|
for (p in points)
|
||||||
b.addPoint(p);
|
b.addPoint(p);
|
||||||
return b;
|
bounds = b;
|
||||||
|
}
|
||||||
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
override function alloc(engine:h3d.Engine) {
|
override function alloc(engine:h3d.Engine) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package net;
|
package net;
|
||||||
|
|
||||||
|
import net.NetPacket.MarbleMovePacket;
|
||||||
import src.TimeState;
|
import src.TimeState;
|
||||||
import src.Console;
|
import src.Console;
|
||||||
import net.Net.ClientConnection;
|
import net.Net.ClientConnection;
|
||||||
|
|
@ -35,7 +36,7 @@ class MoveManager {
|
||||||
var lastMove:NetMove;
|
var lastMove:NetMove;
|
||||||
var lastAckMoveId:Int = -1;
|
var lastAckMoveId:Int = -1;
|
||||||
|
|
||||||
static var maxMoves = 45; // Taken from Torque
|
static var maxMoves = 16;
|
||||||
|
|
||||||
public function new(connection:ClientConnection) {
|
public function new(connection:ClientConnection) {
|
||||||
queuedMoves = [];
|
queuedMoves = [];
|
||||||
|
|
@ -84,15 +85,19 @@ class MoveManager {
|
||||||
nextMoveId = 0;
|
nextMoveId = 0;
|
||||||
|
|
||||||
var b = new haxe.io.BytesOutput();
|
var b = new haxe.io.BytesOutput();
|
||||||
|
var movePacket = new MarbleMovePacket();
|
||||||
|
movePacket.clientId = Net.clientId;
|
||||||
|
movePacket.move = netMove;
|
||||||
|
movePacket.clientTicks = timeState.ticks;
|
||||||
b.writeByte(NetPacketType.MarbleMove);
|
b.writeByte(NetPacketType.MarbleMove);
|
||||||
b.writeUInt16(Net.clientId);
|
movePacket.serialize(b);
|
||||||
|
|
||||||
Net.sendPacketToHost(packMove(netMove, b));
|
Net.sendPacketToHost(b);
|
||||||
|
|
||||||
return netMove;
|
return netMove;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function packMove(m:NetMove, b:haxe.io.BytesOutput) {
|
public static inline function packMove(m:NetMove, b:haxe.io.BytesOutput) {
|
||||||
b.writeUInt16(m.id);
|
b.writeUInt16(m.id);
|
||||||
b.writeFloat(m.move.d.x);
|
b.writeFloat(m.move.d.x);
|
||||||
b.writeFloat(m.move.d.y);
|
b.writeFloat(m.move.d.y);
|
||||||
|
|
@ -108,7 +113,7 @@ class MoveManager {
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function unpackMove(b:haxe.io.BytesInput) {
|
public static inline function unpackMove(b:haxe.io.BytesInput) {
|
||||||
var moveId = b.readUInt16();
|
var moveId = b.readUInt16();
|
||||||
var move = new Move();
|
var move = new Move();
|
||||||
move.d = new Vector();
|
move.d = new Vector();
|
||||||
|
|
@ -147,7 +152,6 @@ class MoveManager {
|
||||||
if (queuedMoves.length == 0)
|
if (queuedMoves.length == 0)
|
||||||
return;
|
return;
|
||||||
while (m != queuedMoves[0].id) {
|
while (m != queuedMoves[0].id) {
|
||||||
trace('Ignoring move ${queuedMoves[0].id}, need ${m}');
|
|
||||||
queuedMoves.shift();
|
queuedMoves.shift();
|
||||||
}
|
}
|
||||||
if (m == queuedMoves[0].id)
|
if (m == queuedMoves[0].id)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package net;
|
package net;
|
||||||
|
|
||||||
|
import net.NetPacket.MarbleUpdatePacket;
|
||||||
|
import net.NetPacket.MarbleMovePacket;
|
||||||
import haxe.Json;
|
import haxe.Json;
|
||||||
import datachannel.RTCPeerConnection;
|
import datachannel.RTCPeerConnection;
|
||||||
import datachannel.RTCDataChannel;
|
import datachannel.RTCDataChannel;
|
||||||
|
|
@ -241,21 +243,24 @@ class Net {
|
||||||
}
|
}
|
||||||
|
|
||||||
case MarbleUpdate:
|
case MarbleUpdate:
|
||||||
var marbleClientId = input.readUInt16();
|
var marbleUpdatePacket = new MarbleUpdatePacket();
|
||||||
if (marbleClientId == clientId) {
|
marbleUpdatePacket.deserialize(input);
|
||||||
if (MarbleGame.instance.world != null)
|
var cc = marbleUpdatePacket.clientId;
|
||||||
MarbleGame.instance.world.marble.unpackUpdate(input);
|
if (MarbleGame.instance.world != null) {
|
||||||
|
var m = MarbleGame.instance.world.lastMoves;
|
||||||
|
if (m.exists(cc)) {
|
||||||
|
if (m[cc].serverTicks < marbleUpdatePacket.serverTicks)
|
||||||
|
m.set(cc, marbleUpdatePacket);
|
||||||
} else {
|
} else {
|
||||||
var cc = clientIdMap[marbleClientId];
|
m.set(cc, marbleUpdatePacket);
|
||||||
if (MarbleGame.instance.world != null)
|
}
|
||||||
@:privateAccess MarbleGame.instance.world.clientMarbles[cc].unpackUpdate(input);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case MarbleMove:
|
case MarbleMove:
|
||||||
var marbleClientId = input.readUInt16();
|
var movePacket = new MarbleMovePacket();
|
||||||
var cc = clientIdMap[marbleClientId];
|
movePacket.deserialize(input);
|
||||||
var m = MoveManager.unpackMove(input);
|
var cc = clientIdMap[movePacket.clientId];
|
||||||
cc.moveManager.queueMove(m);
|
cc.moveManager.queueMove(movePacket.move);
|
||||||
|
|
||||||
case _:
|
case _:
|
||||||
trace("unknown command: " + packetType);
|
trace("unknown command: " + packetType);
|
||||||
|
|
|
||||||
67
src/net/NetPacket.hx
Normal file
67
src/net/NetPacket.hx
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
package net;
|
||||||
|
|
||||||
|
import h3d.Vector;
|
||||||
|
import net.MoveManager.NetMove;
|
||||||
|
|
||||||
|
interface NetPacket {
|
||||||
|
public function serialize(b:haxe.io.BytesOutput):Void;
|
||||||
|
public function deserialize(b:haxe.io.BytesInput):Void;
|
||||||
|
}
|
||||||
|
|
||||||
|
@:publicFields
|
||||||
|
class MarbleMovePacket implements NetPacket {
|
||||||
|
var clientId:Int;
|
||||||
|
var clientTicks:Int;
|
||||||
|
var move:NetMove;
|
||||||
|
|
||||||
|
public function new() {}
|
||||||
|
|
||||||
|
public inline function deserialize(b:haxe.io.BytesInput) {
|
||||||
|
clientId = b.readUInt16();
|
||||||
|
clientTicks = b.readUInt16();
|
||||||
|
move = MoveManager.unpackMove(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public inline function serialize(b:haxe.io.BytesOutput) {
|
||||||
|
b.writeUInt16(clientId);
|
||||||
|
b.writeUInt16(clientTicks);
|
||||||
|
MoveManager.packMove(move, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@:publicFields
|
||||||
|
class MarbleUpdatePacket implements NetPacket {
|
||||||
|
var clientId:Int;
|
||||||
|
var move:NetMove;
|
||||||
|
var serverTicks:Int;
|
||||||
|
var position:Vector;
|
||||||
|
var velocity:Vector;
|
||||||
|
var omega:Vector;
|
||||||
|
var applied:Bool = false;
|
||||||
|
|
||||||
|
public function new() {}
|
||||||
|
|
||||||
|
public inline function serialize(b:haxe.io.BytesOutput) {
|
||||||
|
b.writeUInt16(clientId);
|
||||||
|
MoveManager.packMove(move, b);
|
||||||
|
b.writeUInt16(serverTicks);
|
||||||
|
b.writeFloat(position.x);
|
||||||
|
b.writeFloat(position.y);
|
||||||
|
b.writeFloat(position.z);
|
||||||
|
b.writeFloat(velocity.x);
|
||||||
|
b.writeFloat(velocity.y);
|
||||||
|
b.writeFloat(velocity.z);
|
||||||
|
b.writeFloat(omega.x);
|
||||||
|
b.writeFloat(omega.y);
|
||||||
|
b.writeFloat(omega.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public inline function deserialize(b:haxe.io.BytesInput) {
|
||||||
|
clientId = b.readUInt16();
|
||||||
|
move = MoveManager.unpackMove(b);
|
||||||
|
serverTicks = b.readUInt16();
|
||||||
|
position = new Vector(b.readFloat(), b.readFloat(), b.readFloat());
|
||||||
|
velocity = new Vector(b.readFloat(), b.readFloat(), b.readFloat());
|
||||||
|
omega = new Vector(b.readFloat(), b.readFloat(), b.readFloat());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -128,13 +128,13 @@ class RewindManager {
|
||||||
|
|
||||||
if (level.marble.heldPowerup == null) {
|
if (level.marble.heldPowerup == null) {
|
||||||
if (rf.marblePowerup != null) {
|
if (rf.marblePowerup != null) {
|
||||||
level.pickUpPowerUp(rf.marblePowerup);
|
level.pickUpPowerUp(level.marble, rf.marblePowerup);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (rf.marblePowerup == null) {
|
if (rf.marblePowerup == null) {
|
||||||
level.deselectPowerUp();
|
level.deselectPowerUp(level.marble);
|
||||||
} else {
|
} else {
|
||||||
level.pickUpPowerUp(rf.marblePowerup);
|
level.pickUpPowerUp(level.marble, rf.marblePowerup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import collision.CollisionInfo;
|
||||||
import src.DtsObject;
|
import src.DtsObject;
|
||||||
import src.TimeState;
|
import src.TimeState;
|
||||||
import src.Util;
|
import src.Util;
|
||||||
|
import src.Marble;
|
||||||
|
|
||||||
class AbstractBumper extends DtsObject {
|
class AbstractBumper extends DtsObject {
|
||||||
var lastContactTime = Math.NEGATIVE_INFINITY;
|
var lastContactTime = Math.NEGATIVE_INFINITY;
|
||||||
|
|
@ -27,8 +28,8 @@ class AbstractBumper extends DtsObject {
|
||||||
return completion;
|
return completion;
|
||||||
}
|
}
|
||||||
|
|
||||||
override function onMarbleContact(time:TimeState, ?contact:CollisionInfo) {
|
override function onMarbleContact(marble:Marble, time:TimeState, ?contact:CollisionInfo) {
|
||||||
super.onMarbleContact(time, contact);
|
super.onMarbleContact(marble, time, contact);
|
||||||
if (time.timeSinceLoad - this.lastContactTime <= 0)
|
if (time.timeSinceLoad - this.lastContactTime <= 0)
|
||||||
return;
|
return;
|
||||||
var currentCompletion = this.getCurrentCompletion(time);
|
var currentCompletion = this.getCurrentCompletion(time);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package shapes;
|
package shapes;
|
||||||
|
|
||||||
|
import src.Marble;
|
||||||
import mis.MisParser;
|
import mis.MisParser;
|
||||||
import dts.DtsFile;
|
import dts.DtsFile;
|
||||||
import src.ResourceLoader;
|
import src.ResourceLoader;
|
||||||
|
|
@ -26,13 +27,13 @@ class AntiGravity extends PowerUp {
|
||||||
this.cooldownDuration = Math.NEGATIVE_INFINITY;
|
this.cooldownDuration = Math.NEGATIVE_INFINITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pickUp():Bool {
|
public function pickUp(marble:Marble):Bool {
|
||||||
var direction = new Vector(0, 0, -1);
|
var direction = new Vector(0, 0, -1);
|
||||||
direction.transform(this.getRotationQuat().toMatrix());
|
direction.transform(this.getRotationQuat().toMatrix());
|
||||||
return !direction.equals(this.level.currentUp);
|
return !direction.equals(this.level.currentUp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function use(timeState:TimeState) {
|
public function use(marble:Marble, timeState:TimeState) {
|
||||||
if (!this.level.rewinding) {
|
if (!this.level.rewinding) {
|
||||||
var direction = new Vector(0, 0, -1);
|
var direction = new Vector(0, 0, -1);
|
||||||
direction.transform(this.getRotationQuat().toMatrix());
|
direction.transform(this.getRotationQuat().toMatrix());
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package shapes;
|
package shapes;
|
||||||
|
|
||||||
|
import src.Marble;
|
||||||
import src.MarbleWorld;
|
import src.MarbleWorld;
|
||||||
import src.ResourceLoader;
|
import src.ResourceLoader;
|
||||||
import src.TimeState;
|
import src.TimeState;
|
||||||
|
|
@ -27,11 +28,11 @@ class Blast extends PowerUp {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pickUp():Bool {
|
public function pickUp(marble:Marble):Bool {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function use(timeState:TimeState) {
|
public function use(marble:Marble, timeState:TimeState) {
|
||||||
this.level.blastAmount = 1.2;
|
this.level.blastAmount = 1.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package shapes;
|
package shapes;
|
||||||
|
|
||||||
|
import src.Marble;
|
||||||
import gui.AchievementsGui;
|
import gui.AchievementsGui;
|
||||||
import src.Settings;
|
import src.Settings;
|
||||||
import mis.MissionElement.MissionElementItem;
|
import mis.MissionElement.MissionElementItem;
|
||||||
|
|
@ -16,7 +17,7 @@ class EasterEgg extends PowerUp {
|
||||||
this.autoUse = true;
|
this.autoUse = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pickUp():Bool {
|
public function pickUp(marble:Marble):Bool {
|
||||||
var found:Bool = false;
|
var found:Bool = false;
|
||||||
if (Settings.easterEggs.exists(this.level.mission.path)) {
|
if (Settings.easterEggs.exists(this.level.mission.path)) {
|
||||||
found = true;
|
found = true;
|
||||||
|
|
@ -42,7 +43,7 @@ class EasterEgg extends PowerUp {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function use(timeState:src.TimeState) {}
|
public function use(marble:Marble, timeState:src.TimeState) {}
|
||||||
|
|
||||||
override function getPreloadMaterials(dts:dts.DtsFile) {
|
override function getPreloadMaterials(dts:dts.DtsFile) {
|
||||||
var mats = super.getPreloadMaterials(dts);
|
var mats = super.getPreloadMaterials(dts);
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import src.TimeState;
|
||||||
import src.DtsObject;
|
import src.DtsObject;
|
||||||
import src.ResourceLoaderWorker;
|
import src.ResourceLoaderWorker;
|
||||||
import src.ResourceLoader;
|
import src.ResourceLoader;
|
||||||
|
import src.Marble;
|
||||||
|
|
||||||
class Gem extends DtsObject {
|
class Gem extends DtsObject {
|
||||||
public var pickedUp:Bool;
|
public var pickedUp:Bool;
|
||||||
|
|
@ -60,8 +61,8 @@ class Gem extends DtsObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override function onMarbleInside(timeState:TimeState) {
|
override function onMarbleInside(marble:Marble, timeState:TimeState) {
|
||||||
super.onMarbleInside(timeState);
|
super.onMarbleInside(marble, timeState);
|
||||||
if (this.pickedUp || this.level.rewinding)
|
if (this.pickedUp || this.level.rewinding)
|
||||||
return;
|
return;
|
||||||
this.pickedUp = true;
|
this.pickedUp = true;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package shapes;
|
package shapes;
|
||||||
|
|
||||||
|
import src.Marble;
|
||||||
import h3d.mat.Material;
|
import h3d.mat.Material;
|
||||||
import src.ResourceLoader;
|
import src.ResourceLoader;
|
||||||
import mis.MissionElement.MissionElementItem;
|
import mis.MissionElement.MissionElementItem;
|
||||||
|
|
@ -28,14 +29,13 @@ class Helicopter extends PowerUp {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pickUp():Bool {
|
public function pickUp(marble:Marble):Bool {
|
||||||
return this.level.pickUpPowerUp(this);
|
return this.level.pickUpPowerUp(marble, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function use(timeState:TimeState) {
|
public function use(marble:Marble, timeState:TimeState) {
|
||||||
var marble = this.level.marble;
|
|
||||||
marble.enableHelicopter(timeState.currentAttemptTime);
|
marble.enableHelicopter(timeState.currentAttemptTime);
|
||||||
this.level.deselectPowerUp();
|
this.level.deselectPowerUp(marble);
|
||||||
}
|
}
|
||||||
|
|
||||||
override function postProcessMaterial(matName:String, material:Material) {
|
override function postProcessMaterial(matName:String, material:Material) {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import src.ResourceLoader;
|
||||||
import src.TimeState;
|
import src.TimeState;
|
||||||
import mis.MissionElement.MissionElementItem;
|
import mis.MissionElement.MissionElementItem;
|
||||||
import src.AudioManager;
|
import src.AudioManager;
|
||||||
|
import src.Marble;
|
||||||
|
|
||||||
class MegaMarble extends PowerUp {
|
class MegaMarble extends PowerUp {
|
||||||
public function new(element:MissionElementItem) {
|
public function new(element:MissionElementItem) {
|
||||||
|
|
@ -35,13 +36,13 @@ class MegaMarble extends PowerUp {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pickUp():Bool {
|
public function pickUp(marble:Marble):Bool {
|
||||||
return this.level.pickUpPowerUp(this);
|
return this.level.pickUpPowerUp(marble, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function use(timeState:TimeState) {
|
public function use(marble:Marble, timeState:TimeState) {
|
||||||
this.level.marble.enableMegaMarble(timeState.currentAttemptTime);
|
marble.enableMegaMarble(timeState.currentAttemptTime);
|
||||||
this.level.deselectPowerUp();
|
this.level.deselectPowerUp(marble);
|
||||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/use_mega.wav', ResourceLoader.getAudio, this.soundResources));
|
AudioManager.playSound(ResourceLoader.getResource('data/sound/use_mega.wav', ResourceLoader.getAudio, this.soundResources));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package shapes;
|
package shapes;
|
||||||
|
|
||||||
|
import src.Marble;
|
||||||
import src.AudioManager;
|
import src.AudioManager;
|
||||||
import hxd.res.Sound;
|
import hxd.res.Sound;
|
||||||
import mis.MissionElement.MissionElementItem;
|
import mis.MissionElement.MissionElementItem;
|
||||||
|
|
@ -26,18 +27,19 @@ abstract class PowerUp extends DtsObject {
|
||||||
this.element = element;
|
this.element = element;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override function onMarbleInside(timeState:TimeState) {
|
public override function onMarbleInside(marble:Marble, timeState:TimeState) {
|
||||||
var pickupable = this.lastPickUpTime == -1 || (timeState.currentAttemptTime - this.lastPickUpTime) >= this.cooldownDuration;
|
var pickupable = this.lastPickUpTime == -1 || (timeState.currentAttemptTime - this.lastPickUpTime) >= this.cooldownDuration;
|
||||||
if (!pickupable)
|
if (!pickupable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.pickUp()) {
|
if (this.pickUp(marble)) {
|
||||||
// this.level.replay.recordMarbleInside(this);
|
// this.level.replay.recordMarbleInside(this);
|
||||||
|
|
||||||
this.lastPickUpTime = timeState.currentAttemptTime;
|
this.lastPickUpTime = timeState.currentAttemptTime;
|
||||||
if (this.autoUse)
|
if (this.autoUse)
|
||||||
this.use(timeState);
|
this.use(marble, timeState);
|
||||||
|
|
||||||
|
if (level.marble == marble) {
|
||||||
if (customPickupMessage != null)
|
if (customPickupMessage != null)
|
||||||
this.level.displayAlert(customPickupMessage);
|
this.level.displayAlert(customPickupMessage);
|
||||||
else
|
else
|
||||||
|
|
@ -50,6 +52,7 @@ abstract class PowerUp extends DtsObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override function update(timeState:TimeState) {
|
public override function update(timeState:TimeState) {
|
||||||
super.update(timeState);
|
super.update(timeState);
|
||||||
|
|
@ -62,9 +65,9 @@ abstract class PowerUp extends DtsObject {
|
||||||
this.setOpacity(opacity);
|
this.setOpacity(opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract function pickUp():Bool;
|
public abstract function pickUp(marble:Marble):Bool;
|
||||||
|
|
||||||
public abstract function use(timeState:TimeState):Void;
|
public abstract function use(marble:Marble, timeState:TimeState):Void;
|
||||||
|
|
||||||
public override function reset() {
|
public override function reset() {
|
||||||
this.lastPickUpTime = Math.NEGATIVE_INFINITY;
|
this.lastPickUpTime = Math.NEGATIVE_INFINITY;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package shapes;
|
package shapes;
|
||||||
|
|
||||||
|
import src.Marble;
|
||||||
import src.ResourceLoader;
|
import src.ResourceLoader;
|
||||||
import mis.MissionElement.MissionElementItem;
|
import mis.MissionElement.MissionElementItem;
|
||||||
import src.TimeState;
|
import src.TimeState;
|
||||||
|
|
@ -62,21 +63,21 @@ class SuperJump extends PowerUp {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pickUp():Bool {
|
public function pickUp(marble:Marble):Bool {
|
||||||
return this.level.pickUpPowerUp(this);
|
return this.level.pickUpPowerUp(marble, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function use(timeState:TimeState) {
|
public function use(marble:Marble, timeState:TimeState) {
|
||||||
var marble = this.level.marble;
|
|
||||||
var masslessFactor = marble.getMass() * 0.7 + 1 - 0.7;
|
var masslessFactor = marble.getMass() * 0.7 + 1 - 0.7;
|
||||||
var boost = this.level.currentUp.multiply(20 * masslessFactor / marble.getMass());
|
var boost = this.level.currentUp.multiply(20 * masslessFactor / marble.getMass());
|
||||||
marble.velocity = marble.velocity.add(boost);
|
marble.velocity = marble.velocity.add(boost);
|
||||||
this.level.particleManager.createEmitter(superJumpParticleOptions, this.sjEmitterParticleData, null, () -> marble.getAbsPos().getPosition());
|
this.level.particleManager.createEmitter(superJumpParticleOptions, this.sjEmitterParticleData, null, () -> marble.getAbsPos().getPosition());
|
||||||
// marble.body.addLinearVelocity(this.level.currentUp.scale(20)); // Simply add to vertical velocity
|
// marble.body.addLinearVelocity(this.level.currentUp.scale(20)); // Simply add to vertical velocity
|
||||||
// if (!this.level.rewinding)
|
// if (!this.level.rewinding)
|
||||||
|
if (level.marble == marble)
|
||||||
AudioManager.playSound(ResourceLoader.getResource("data/sound/use_superjump.wav", ResourceLoader.getAudio, this.soundResources));
|
AudioManager.playSound(ResourceLoader.getResource("data/sound/use_superjump.wav", ResourceLoader.getAudio, this.soundResources));
|
||||||
// this.level.particles.createEmitter(superJumpParticleOptions, null, () => Util.vecOimoToThree(marble.body.getPosition()));
|
// this.level.particles.createEmitter(superJumpParticleOptions, null, () => Util.vecOimoToThree(marble.body.getPosition()));
|
||||||
this.level.deselectPowerUp();
|
this.level.deselectPowerUp(marble);
|
||||||
}
|
}
|
||||||
|
|
||||||
override function getPreloadMaterials(dts:dts.DtsFile) {
|
override function getPreloadMaterials(dts:dts.DtsFile) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package shapes;
|
package shapes;
|
||||||
|
|
||||||
|
import src.Marble;
|
||||||
import mis.MissionElement.MissionElementItem;
|
import mis.MissionElement.MissionElementItem;
|
||||||
import src.TimeState;
|
import src.TimeState;
|
||||||
import src.ResourceLoader;
|
import src.ResourceLoader;
|
||||||
|
|
@ -63,12 +64,11 @@ class SuperSpeed extends PowerUp {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pickUp():Bool {
|
public function pickUp(marble:Marble):Bool {
|
||||||
return this.level.pickUpPowerUp(this);
|
return this.level.pickUpPowerUp(marble, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function use(timeState:TimeState) {
|
public function use(marble:Marble, timeState:TimeState) {
|
||||||
var marble = this.level.marble;
|
|
||||||
var movementVector = marble.getMarbleAxis()[0];
|
var movementVector = marble.getMarbleAxis()[0];
|
||||||
|
|
||||||
// Okay, so super speed directionality is a bit strange. In general, the direction is based on the normal vector of the last surface you had contact with.
|
// Okay, so super speed directionality is a bit strange. In general, the direction is based on the normal vector of the last surface you had contact with.
|
||||||
|
|
@ -86,9 +86,10 @@ class SuperSpeed extends PowerUp {
|
||||||
// marble.body.addLinearVelocity(Util.vecThreeToOimo(movementVector).scale(24.7)); // Whirligig's determined value
|
// marble.body.addLinearVelocity(Util.vecThreeToOimo(movementVector).scale(24.7)); // Whirligig's determined value
|
||||||
// marble.body.addLinearVelocity(this.level.currentUp.scale(20)); // Simply add to vertical velocity
|
// marble.body.addLinearVelocity(this.level.currentUp.scale(20)); // Simply add to vertical velocity
|
||||||
// if (!this.level.rewinding)
|
// if (!this.level.rewinding)
|
||||||
|
if (level.marble == marble)
|
||||||
AudioManager.playSound(ResourceLoader.getResource("data/sound/use_speed.wav", ResourceLoader.getAudio, this.soundResources));
|
AudioManager.playSound(ResourceLoader.getResource("data/sound/use_speed.wav", ResourceLoader.getAudio, this.soundResources));
|
||||||
this.level.particleManager.createEmitter(superSpeedParticleOptions, this.ssEmitterParticleData, null, () -> marble.getAbsPos().getPosition());
|
this.level.particleManager.createEmitter(superSpeedParticleOptions, this.ssEmitterParticleData, null, () -> marble.getAbsPos().getPosition());
|
||||||
this.level.deselectPowerUp();
|
this.level.deselectPowerUp(marble);
|
||||||
}
|
}
|
||||||
|
|
||||||
override function postProcessMaterial(matName:String, material:h3d.mat.Material) {
|
override function postProcessMaterial(matName:String, material:h3d.mat.Material) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package shapes;
|
package shapes;
|
||||||
|
|
||||||
|
import src.Marble;
|
||||||
import src.ResourceLoader;
|
import src.ResourceLoader;
|
||||||
import mis.MissionElement.MissionElementItem;
|
import mis.MissionElement.MissionElementItem;
|
||||||
import src.TimeState;
|
import src.TimeState;
|
||||||
|
|
@ -39,11 +40,11 @@ class TimeTravel extends PowerUp {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pickUp():Bool {
|
public function pickUp(marble:Marble):Bool {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function use(time:TimeState) {
|
public function use(marble:Marble, time:TimeState) {
|
||||||
if (!this.level.rewinding)
|
if (!this.level.rewinding)
|
||||||
level.addBonusTime(this.timeBonus);
|
level.addBonusTime(this.timeBonus);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import src.ForceObject;
|
||||||
import src.ResourceLoader;
|
import src.ResourceLoader;
|
||||||
import src.AudioManager;
|
import src.AudioManager;
|
||||||
import src.MarbleWorld;
|
import src.MarbleWorld;
|
||||||
|
import src.Marble;
|
||||||
|
|
||||||
class Trapdoor extends DtsObject {
|
class Trapdoor extends DtsObject {
|
||||||
var lastContactTime = -1e8;
|
var lastContactTime = -1e8;
|
||||||
|
|
@ -64,8 +65,8 @@ class Trapdoor extends DtsObject {
|
||||||
return completion;
|
return completion;
|
||||||
}
|
}
|
||||||
|
|
||||||
override function onMarbleContact(time:TimeState, ?contact:CollisionInfo) {
|
override function onMarbleContact(marble:Marble, time:TimeState, ?contact:CollisionInfo) {
|
||||||
super.onMarbleContact(time, contact);
|
super.onMarbleContact(marble, time, contact);
|
||||||
if (time.timeSinceLoad - this.lastContactTime <= 0)
|
if (time.timeSinceLoad - this.lastContactTime <= 0)
|
||||||
return; // The trapdoor is queued to open, so don't do anything.
|
return; // The trapdoor is queued to open, so don't do anything.
|
||||||
var currentCompletion = this.getCurrentCompletion(time);
|
var currentCompletion = this.getCurrentCompletion(time);
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import src.MarbleWorld;
|
||||||
import mis.MissionElement.MissionElementTrigger;
|
import mis.MissionElement.MissionElementTrigger;
|
||||||
import src.ResourceLoader;
|
import src.ResourceLoader;
|
||||||
import mis.MisParser;
|
import mis.MisParser;
|
||||||
|
import src.Marble;
|
||||||
|
|
||||||
class CheckpointTrigger extends Trigger {
|
class CheckpointTrigger extends Trigger {
|
||||||
public var disableOOB = false;
|
public var disableOOB = false;
|
||||||
|
|
@ -28,8 +29,8 @@ class CheckpointTrigger extends Trigger {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override function onMarbleEnter(time:src.TimeState) {
|
public override function onMarbleEnter(marble:Marble, time:src.TimeState) {
|
||||||
super.onMarbleEnter(time);
|
super.onMarbleEnter(marble, time);
|
||||||
if (simGroup == null)
|
if (simGroup == null)
|
||||||
return;
|
return;
|
||||||
var shape = level.simGroups[simGroup].filter(x -> x.identifier == "Checkpoint");
|
var shape = level.simGroups[simGroup].filter(x -> x.identifier == "Checkpoint");
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,10 @@ package triggers;
|
||||||
import src.TimeState;
|
import src.TimeState;
|
||||||
import src.ResourceLoader;
|
import src.ResourceLoader;
|
||||||
import src.AudioManager;
|
import src.AudioManager;
|
||||||
|
import src.Marble;
|
||||||
|
|
||||||
class HelpTrigger extends Trigger {
|
class HelpTrigger extends Trigger {
|
||||||
override function onMarbleEnter(timeState:TimeState) {
|
override function onMarbleEnter(marble:Marble, timeState:TimeState) {
|
||||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/infotutorial.wav', ResourceLoader.getAudio, this.soundResources));
|
AudioManager.playSound(ResourceLoader.getResource('data/sound/infotutorial.wav', ResourceLoader.getAudio, this.soundResources));
|
||||||
if (this.element.text != null && this.element.text != "")
|
if (this.element.text != null && this.element.text != "")
|
||||||
this.level.displayHelp(this.element.text);
|
this.level.displayHelp(this.element.text);
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,10 @@ package triggers;
|
||||||
|
|
||||||
import src.TimeState;
|
import src.TimeState;
|
||||||
import src.ResourceLoader;
|
import src.ResourceLoader;
|
||||||
|
import src.Marble;
|
||||||
|
|
||||||
class InBoundsTrigger extends Trigger {
|
class InBoundsTrigger extends Trigger {
|
||||||
override function onMarbleLeave(timeState:TimeState) {
|
override function onMarbleLeave(marble:Marble, timeState:TimeState) {
|
||||||
this.level.goOutOfBounds();
|
this.level.goOutOfBounds();
|
||||||
// this.level.replay.recordMarbleLeave(this);
|
// this.level.replay.recordMarbleLeave(this);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import src.PathedInterior;
|
||||||
import mis.MissionElement.MissionElementTrigger;
|
import mis.MissionElement.MissionElementTrigger;
|
||||||
import src.TimeState;
|
import src.TimeState;
|
||||||
import mis.MisParser;
|
import mis.MisParser;
|
||||||
|
import src.Marble;
|
||||||
|
|
||||||
class MustChangeTrigger extends Trigger {
|
class MustChangeTrigger extends Trigger {
|
||||||
var interior:PathedInterior;
|
var interior:PathedInterior;
|
||||||
|
|
@ -13,7 +14,7 @@ class MustChangeTrigger extends Trigger {
|
||||||
this.interior = interior;
|
this.interior = interior;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override function onMarbleEnter(time:TimeState) {
|
public override function onMarbleEnter(marble:Marble, time:TimeState) {
|
||||||
var ttime = MisParser.parseNumber(this.element.targettime);
|
var ttime = MisParser.parseNumber(this.element.targettime);
|
||||||
if (ttime > 0)
|
if (ttime > 0)
|
||||||
ttime /= 1000;
|
ttime /= 1000;
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,10 @@ package triggers;
|
||||||
|
|
||||||
import src.TimeState;
|
import src.TimeState;
|
||||||
import src.ResourceLoader;
|
import src.ResourceLoader;
|
||||||
|
import src.Marble;
|
||||||
|
|
||||||
class OutOfBoundsTrigger extends Trigger {
|
class OutOfBoundsTrigger extends Trigger {
|
||||||
override function onMarbleInside(time:TimeState) {
|
override function onMarbleInside(marble:Marble, time:TimeState) {
|
||||||
this.level.goOutOfBounds();
|
this.level.goOutOfBounds();
|
||||||
// this.level.replay.recordMarbleInside(this);
|
// this.level.replay.recordMarbleInside(this);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue