mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2025-10-30 08:11:25 +00:00
Add start and finish things
This commit is contained in:
parent
0060a403d2
commit
7644c4c8de
6 changed files with 228 additions and 36 deletions
|
|
@ -1,5 +1,6 @@
|
|||
package src;
|
||||
|
||||
import src.Util;
|
||||
import h3d.Quat;
|
||||
import sdl.Cursor;
|
||||
import sdl.Sdl;
|
||||
|
|
@ -51,6 +52,11 @@ class CameraController extends Object {
|
|||
var screenHeight:Int;
|
||||
var screenWidth:Int;
|
||||
|
||||
var lastCamPos:Vector;
|
||||
|
||||
public var oob:Bool = false;
|
||||
public var finish:Bool = false;
|
||||
|
||||
public function new(marble:Marble) {
|
||||
super();
|
||||
this.marble = marble;
|
||||
|
|
@ -132,9 +138,15 @@ class CameraController extends Object {
|
|||
q.z = vr.z;
|
||||
return q;
|
||||
}
|
||||
|
||||
var orientationQuat = level.getOrientationQuat(currentTime);
|
||||
|
||||
if (this.finish) {
|
||||
// Make the camera spin around slowly
|
||||
CameraPitch = Util.lerp(this.level.finishPitch, -0.45,
|
||||
Util.clamp((this.level.timeState.currentAttemptTime - this.level.finishTime.currentAttemptTime) / 0.3, 0, 1));
|
||||
CameraYaw = this.level.finishYaw - (this.level.timeState.currentAttemptTime - this.level.finishTime.currentAttemptTime) / -1 * 0.6;
|
||||
}
|
||||
|
||||
var up = new Vector(0, 0, 1);
|
||||
up.transform(orientationQuat.toMatrix());
|
||||
camera.up = up;
|
||||
|
|
@ -195,6 +207,13 @@ class CameraController extends Object {
|
|||
|
||||
var toPos = targetpos.add(directionVec);
|
||||
camera.pos = toPos;
|
||||
if (oob) {
|
||||
camera.pos = lastCamPos;
|
||||
camera.target = targetpos.add(cameraVerticalTranslation);
|
||||
}
|
||||
|
||||
if (!oob)
|
||||
lastCamPos = camera.pos;
|
||||
// camera.target = null;
|
||||
// camera.target = targetpos.add(cameraVerticalTranslation);
|
||||
// this.x = targetpos.x + directionVec.x;
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ class Main extends hxd.App {
|
|||
override function init() {
|
||||
super.init();
|
||||
|
||||
var ltr = File.getContent("data/missions/beginner/finale.mis");
|
||||
var ltr = File.getContent("data/missions/beginner/movement.mis");
|
||||
var mfp = new MisParser(ltr);
|
||||
var mis = mfp.parse();
|
||||
|
||||
|
|
@ -62,13 +62,10 @@ class Main extends hxd.App {
|
|||
world = new MarbleWorld(s3d, s2d, mission);
|
||||
|
||||
world.init();
|
||||
world.start();
|
||||
|
||||
// s3d.camera.
|
||||
|
||||
var marble = new Marble();
|
||||
marble.controllable = true;
|
||||
world.addMarble(marble);
|
||||
marble.setPosition(5, 0, 5);
|
||||
// marble.setPosition(5, 0, 5);
|
||||
|
||||
// var marble2 = new Marble();
|
||||
// world.addMarble(marble2);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package src;
|
||||
|
||||
import shapes.StartPad;
|
||||
import src.TimeState;
|
||||
import src.ParticleSystem.ParticleEmitter;
|
||||
import src.ParticleSystem.ParticleData;
|
||||
|
|
@ -40,6 +41,12 @@ class Move {
|
|||
public function new() {}
|
||||
}
|
||||
|
||||
enum Mode {
|
||||
Start;
|
||||
Play;
|
||||
Finish;
|
||||
}
|
||||
|
||||
final bounceParticleOptions:ParticleEmitterOptions = {
|
||||
ejectionPeriod: 80,
|
||||
ambientVelocity: new Vector(0, 0, 0.0),
|
||||
|
|
@ -143,6 +150,10 @@ class Marble extends GameObject {
|
|||
var trailEmitterData:ParticleData;
|
||||
var trailEmitterNode:ParticleEmitter;
|
||||
|
||||
public var mode:Mode = Play;
|
||||
|
||||
public var startPad:StartPad;
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
var geom = Sphere.defaultUnitSphere();
|
||||
|
|
@ -221,7 +232,9 @@ class Marble extends GameObject {
|
|||
|
||||
function getExternalForces(currentTime:Float, m:Move, dt:Float) {
|
||||
var gWorkGravityDir = this.level.currentUp.multiply(-1);
|
||||
var A = gWorkGravityDir.multiply(this._gravity);
|
||||
var A = new Vector();
|
||||
if (this.mode != Finish)
|
||||
A = gWorkGravityDir.multiply(this._gravity);
|
||||
if (currentTime - this.helicopterEnableTime < 5) {
|
||||
A = A.multiply(0.25);
|
||||
}
|
||||
|
|
@ -231,7 +244,7 @@ class Marble extends GameObject {
|
|||
A = A.add(force.multiply(1 / _mass));
|
||||
}
|
||||
}
|
||||
if (contacts.length != 0) {
|
||||
if (contacts.length != 0 && this.mode != Start) {
|
||||
var contactForce = 0.0;
|
||||
var contactNormal = new Vector();
|
||||
var forceObjectCount = 0;
|
||||
|
|
@ -500,7 +513,9 @@ class Marble extends GameObject {
|
|||
var AFriction = new Vector(0, 0, 0);
|
||||
if (vAtCMag != 0) {
|
||||
slipping = true;
|
||||
var friction = this._kineticFriction * bestContact.friction;
|
||||
var friction = 0.0;
|
||||
if (this.mode != Start)
|
||||
friction = this._kineticFriction * bestContact.friction;
|
||||
var angAMagnitude = 5 * friction * bestNormalForce / (2 * this._radius);
|
||||
var AMagnitude = bestNormalForce * friction;
|
||||
var totalDeltaV = (angAMagnitude * this._radius + AMagnitude) * dt;
|
||||
|
|
@ -528,10 +543,14 @@ class Marble extends GameObject {
|
|||
}
|
||||
var Aadd = aControl.cross(bestContact.normal.multiply(this._radius));
|
||||
var aAtCMag = aadd.cross(bestContact.normal.multiply(-this._radius)).add(Aadd).length();
|
||||
var friction2 = this._staticFriction * bestContact.friction;
|
||||
var friction2 = 0.0;
|
||||
if (mode != Start)
|
||||
friction2 = this._staticFriction * bestContact.friction;
|
||||
|
||||
if (aAtCMag > friction2 * bestNormalForce) {
|
||||
friction2 = this._kineticFriction * bestContact.friction;
|
||||
friction2 = 0;
|
||||
if (mode != Start)
|
||||
friction2 = this._kineticFriction * bestContact.friction;
|
||||
Aadd = Aadd.multiply(friction2 * bestNormalForce / aAtCMag);
|
||||
}
|
||||
A = A.add(Aadd);
|
||||
|
|
@ -724,6 +743,15 @@ class Marble extends GameObject {
|
|||
|
||||
var pos = this.getAbsPos().getPosition();
|
||||
|
||||
if (mode == Start) {
|
||||
var startPadNormal = this.startPad.getAbsPos().up();
|
||||
this.velocity = startPadNormal.multiply(this.velocity.dot(startPadNormal));
|
||||
}
|
||||
|
||||
if (mode == Finish) {
|
||||
this.velocity = this.velocity.multiply(0.9);
|
||||
}
|
||||
|
||||
var newPos = pos.add(this.velocity.multiply(timeStep));
|
||||
var rot = this.getRotationQuat();
|
||||
var quat = new Quat();
|
||||
|
|
@ -755,7 +783,7 @@ class Marble extends GameObject {
|
|||
public function update(timeState:TimeState, collisionWorld:CollisionWorld, pathedInteriors:Array<PathedInterior>) {
|
||||
var move = new Move();
|
||||
move.d = new Vector();
|
||||
if (this.controllable) {
|
||||
if (this.controllable && this.mode != Finish) {
|
||||
if (Key.isDown(Key.W)) {
|
||||
move.d.x -= 1;
|
||||
}
|
||||
|
|
@ -822,4 +850,14 @@ class Marble extends GameObject {
|
|||
public function enableHelicopter(time:Float) {
|
||||
this.helicopterEnableTime = time;
|
||||
}
|
||||
|
||||
public override function reset() {
|
||||
this.velocity = new Vector();
|
||||
this.collider.velocity = new Vector();
|
||||
this.omega = new Vector();
|
||||
this.superBounceEnableTime = Math.NEGATIVE_INFINITY;
|
||||
this.shockAbsorberEnableTime = Math.NEGATIVE_INFINITY;
|
||||
this.helicopterEnableTime = Math.NEGATIVE_INFINITY;
|
||||
this.lastContactNormal = new Vector(0, 0, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ class MarbleWorld extends Scheduler {
|
|||
public var sky:Sky;
|
||||
|
||||
var endPadElement:MissionElementStaticShape;
|
||||
var endPad:EndPad;
|
||||
|
||||
public var scene:Scene;
|
||||
public var scene2d:h2d.Scene;
|
||||
|
|
@ -86,6 +87,8 @@ class MarbleWorld extends Scheduler {
|
|||
public var outOfBounds:Bool = false;
|
||||
public var outOfBoundsTime:TimeState;
|
||||
public var finishTime:TimeState;
|
||||
public var finishPitch:Float;
|
||||
public var finishYaw:Float;
|
||||
public var totalGems:Int = 0;
|
||||
public var gemCount:Int = 0;
|
||||
|
||||
|
|
@ -130,8 +133,10 @@ class MarbleWorld extends Scheduler {
|
|||
scanMission(this.mission.root);
|
||||
|
||||
this.initScene();
|
||||
this.initMarble();
|
||||
|
||||
this.addSimGroup(this.mission.root);
|
||||
this.endPad.generateCollider();
|
||||
this.playGui.formatGemCounter(this.gemCount, this.totalGems);
|
||||
}
|
||||
|
||||
|
|
@ -173,6 +178,12 @@ class MarbleWorld extends Scheduler {
|
|||
scene.addChild(sky);
|
||||
}
|
||||
|
||||
public function initMarble() {
|
||||
var marble = new Marble();
|
||||
marble.controllable = true;
|
||||
this.addMarble(marble);
|
||||
}
|
||||
|
||||
public function start() {
|
||||
restart();
|
||||
for (interior in this.interiors)
|
||||
|
|
@ -186,7 +197,26 @@ class MarbleWorld extends Scheduler {
|
|||
this.timeState.gameplayClock = 0;
|
||||
this.bonusTime = 0;
|
||||
this.outOfBounds = false;
|
||||
this.marble.camera.CameraPitch = 0.45;
|
||||
this.finishTime = null;
|
||||
|
||||
var startquat = this.getStartPositionAndOrientation();
|
||||
|
||||
this.marble.setPosition(startquat.position.x, startquat.position.y, startquat.position.z + 3);
|
||||
this.marble.collider.transform.setPosition(startquat.position);
|
||||
this.marble.reset();
|
||||
|
||||
var euler = startquat.quat.toEuler();
|
||||
this.marble.camera.CameraYaw = euler.z - Math.PI / 2;
|
||||
this.marble.camera.CameraPitch = -0.45;
|
||||
this.marble.camera.oob = false;
|
||||
this.marble.mode = Start;
|
||||
this.marble.startPad = cast startquat.pad;
|
||||
sky.follow = marble;
|
||||
|
||||
var missionInfo:MissionElementScriptObject = cast this.mission.root.elements.filter((element) -> element._type == MissionElementType.ScriptObject
|
||||
&& element._name == "MissionInfo")[0];
|
||||
if (missionInfo.starthelptext != "")
|
||||
displayHelp(missionInfo.starthelptext); // Show the start help text
|
||||
|
||||
for (shape in dtsObjects)
|
||||
shape.reset();
|
||||
|
|
@ -216,6 +246,7 @@ class MarbleWorld extends Scheduler {
|
|||
}
|
||||
if ((this.timeState.currentAttemptTime >= 3.5) && (this.timeState.currentAttemptTime < 5.5)) {
|
||||
this.playGui.setCenterText('go');
|
||||
this.marble.mode = Play;
|
||||
}
|
||||
if (this.timeState.currentAttemptTime >= 5.5) {
|
||||
this.playGui.setCenterText('none');
|
||||
|
|
@ -225,6 +256,25 @@ class MarbleWorld extends Scheduler {
|
|||
}
|
||||
}
|
||||
|
||||
function getStartPositionAndOrientation() {
|
||||
// The player is spawned at the last start pad in the mission file.
|
||||
var startPad = this.dtsObjects.filter(x -> x is StartPad).pop();
|
||||
var position:Vector;
|
||||
var quat:Quat = new Quat();
|
||||
if (startPad != null) {
|
||||
// If there's a start pad, start there
|
||||
position = startPad.getAbsPos().getPosition();
|
||||
quat = startPad.getRotationQuat().clone();
|
||||
} else {
|
||||
position = new Vector(0, 0, 300);
|
||||
}
|
||||
return {
|
||||
position: position,
|
||||
quat: quat,
|
||||
pad: startPad
|
||||
};
|
||||
}
|
||||
|
||||
public function addSimGroup(simGroup:MissionElementSimGroup) {
|
||||
if (simGroup.elements.filter((element) -> element._type == MissionElementType.PathedInterior).length != 0) {
|
||||
// Create the pathed interior
|
||||
|
|
@ -311,9 +361,11 @@ class MarbleWorld extends Scheduler {
|
|||
if (dataBlockLowerCase == "") {} // Make sure we don't do anything if there's no data block
|
||||
else if (dataBlockLowerCase == "startpad")
|
||||
shape = new StartPad();
|
||||
else if (dataBlockLowerCase == "endpad")
|
||||
else if (dataBlockLowerCase == "endpad") {
|
||||
shape = new EndPad();
|
||||
else if (dataBlockLowerCase == "signfinish")
|
||||
if (element == endPadElement)
|
||||
endPad = cast shape;
|
||||
} else if (dataBlockLowerCase == "signfinish")
|
||||
shape = new SignFinish();
|
||||
else if (StringTools.startsWith(dataBlockLowerCase, "signplain"))
|
||||
shape = new SignPlain(element);
|
||||
|
|
@ -555,15 +607,18 @@ class MarbleWorld extends Scheduler {
|
|||
this.timeState.dt = dt;
|
||||
this.timeState.currentAttemptTime += dt;
|
||||
this.timeState.timeSinceLoad += dt;
|
||||
if (this.bonusTime != 0) {
|
||||
if (this.bonusTime != 0 && this.timeState.currentAttemptTime >= 3.5) {
|
||||
this.bonusTime -= dt;
|
||||
if (this.bonusTime < 0) {
|
||||
this.timeState.gameplayClock -= this.bonusTime;
|
||||
this.bonusTime = 0;
|
||||
}
|
||||
} else {
|
||||
this.timeState.gameplayClock += dt;
|
||||
if (this.timeState.currentAttemptTime >= 3.5)
|
||||
this.timeState.gameplayClock += dt;
|
||||
}
|
||||
if (finishTime != null)
|
||||
this.timeState.gameplayClock = finishTime.gameplayClock;
|
||||
playGui.formatTimer(this.timeState.gameplayClock);
|
||||
}
|
||||
|
||||
|
|
@ -631,6 +686,20 @@ class MarbleWorld extends Scheduler {
|
|||
var contactsphere = new SphereCollisionEntity(marble);
|
||||
contactsphere.velocity = new Vector();
|
||||
|
||||
var spherebounds = new Bounds();
|
||||
var center = marble.collider.transform.getPosition();
|
||||
var radius = marble._radius;
|
||||
spherebounds.xMin = center.x - radius;
|
||||
spherebounds.yMin = center.y - radius;
|
||||
spherebounds.zMin = center.z - radius;
|
||||
spherebounds.xMax = center.x + radius;
|
||||
spherebounds.yMax = center.y + radius;
|
||||
spherebounds.zMax = center.z + radius;
|
||||
|
||||
var gjkSphere = new collision.gjk.Sphere();
|
||||
gjkSphere.position = center;
|
||||
gjkSphere.radius = radius;
|
||||
|
||||
for (contact in contacts) {
|
||||
if (contact.go != marble) {
|
||||
if (contact.go is DtsObject) {
|
||||
|
|
@ -659,17 +728,7 @@ class MarbleWorld extends Scheduler {
|
|||
var trigger:Trigger = cast contact.go;
|
||||
var triggeraabb = trigger.collider.boundingBox;
|
||||
|
||||
var box = new Bounds();
|
||||
var center = marble.collider.transform.getPosition();
|
||||
var radius = marble._radius;
|
||||
box.xMin = center.x - radius;
|
||||
box.yMin = center.y - radius;
|
||||
box.zMin = center.z - radius;
|
||||
box.xMax = center.x + radius;
|
||||
box.yMax = center.y + radius;
|
||||
box.zMax = center.z + radius;
|
||||
|
||||
if (triggeraabb.collide(box)) {
|
||||
if (triggeraabb.collide(spherebounds)) {
|
||||
trigger.onMarbleInside(timeState);
|
||||
if (!this.shapeOrTriggerInside.contains(contact.go)) {
|
||||
this.shapeOrTriggerInside.push(contact.go);
|
||||
|
|
@ -688,9 +747,32 @@ class MarbleWorld extends Scheduler {
|
|||
}
|
||||
}
|
||||
|
||||
if (spherebounds.collide(this.endPad.finishBounds)) {
|
||||
if (collision.gjk.GJK.gjk(gjkSphere, this.endPad.finishCollider) != null) {
|
||||
touchFinish();
|
||||
}
|
||||
}
|
||||
this.shapeImmunity = newImmunity;
|
||||
}
|
||||
|
||||
function touchFinish() {
|
||||
if (this.finishTime != null
|
||||
|| (this.outOfBounds && this.timeState.currentAttemptTime - this.outOfBoundsTime.currentAttemptTime >= 0.5))
|
||||
return;
|
||||
|
||||
if (this.gemCount < this.totalGems) {
|
||||
// AudioManager.play('missinggems.wav');
|
||||
displayAlert("You can't finish without all the gems!!");
|
||||
} else {
|
||||
this.endPad.spawnFirework(this.timeState);
|
||||
this.finishTime = this.timeState.clone();
|
||||
this.marble.mode = Finish;
|
||||
this.marble.camera.finish = true;
|
||||
this.finishYaw = this.marble.camera.CameraYaw;
|
||||
this.finishPitch = this.marble.camera.CameraPitch;
|
||||
}
|
||||
}
|
||||
|
||||
public function pickUpPowerUp(powerUp:PowerUp) {
|
||||
if (this.marble.heldPowerup == powerUp)
|
||||
return false;
|
||||
|
|
@ -763,6 +845,8 @@ class MarbleWorld extends Scheduler {
|
|||
// this.updateCamera(this.timeState); // Update the camera at the point of OOB-ing
|
||||
this.outOfBounds = true;
|
||||
this.outOfBoundsTime = this.timeState.clone();
|
||||
this.marble.camera.oob = true;
|
||||
sky.follow = null;
|
||||
// this.oobCameraPosition = camera.position.clone();
|
||||
playGui.setCenterText('outofbounds');
|
||||
// AudioManager.play('whoosh.wav');
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
package shapes;
|
||||
|
||||
import h3d.Quat;
|
||||
import h3d.mat.Material;
|
||||
import h3d.scene.Mesh;
|
||||
import h3d.prim.Polygon;
|
||||
import h3d.col.Bounds;
|
||||
import h2d.col.Matrix;
|
||||
import collision.gjk.ConvexHull;
|
||||
import src.TimeState;
|
||||
import collision.CollisionInfo;
|
||||
import src.Util;
|
||||
|
|
@ -14,7 +21,9 @@ import h3d.Vector;
|
|||
|
||||
class EndPad extends DtsObject {
|
||||
var fireworks:Array<Firework> = [];
|
||||
var isEntered:Bool = false;
|
||||
|
||||
var finishCollider:ConvexHull;
|
||||
var finishBounds:Bounds;
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
|
|
@ -24,12 +33,12 @@ class EndPad extends DtsObject {
|
|||
this.identifier = "EndPad";
|
||||
}
|
||||
|
||||
override function onMarbleContact(timeState:TimeState, ?contact:CollisionInfo) {
|
||||
if (!isEntered) {
|
||||
isEntered = true;
|
||||
spawnFirework(timeState);
|
||||
}
|
||||
}
|
||||
// override function onMarbleContact(timeState:TimeState, ?contact:CollisionInfo) {
|
||||
// if (!isEntered) {
|
||||
// isEntered = true;
|
||||
// spawnFirework(timeState);
|
||||
// }
|
||||
// }
|
||||
|
||||
function spawnFirework(time:TimeState) {
|
||||
var firework = new Firework(this.getAbsPos().getPosition(), time.timeSinceLoad, this.level);
|
||||
|
|
@ -37,6 +46,44 @@ class EndPad extends DtsObject {
|
|||
// AudioManager.play(this.sounds[0], 1, AudioManager.soundGain, this.worldPosition);
|
||||
}
|
||||
|
||||
function generateCollider() {
|
||||
var height = 4.8;
|
||||
var radius = 1.7;
|
||||
var vertices = [];
|
||||
|
||||
for (i in 0...2) {
|
||||
for (j in 0...64) {
|
||||
var angle = j / 64 * Math.PI * 2;
|
||||
var x = Math.cos(angle);
|
||||
var z = Math.sin(angle);
|
||||
|
||||
vertices.push(new Vector(x * radius * this.scaleX, (i != 0 ? 4.8 : 0) * 1, z * radius * this.scaleY));
|
||||
}
|
||||
}
|
||||
finishCollider = new ConvexHull(vertices);
|
||||
|
||||
finishBounds = new Bounds();
|
||||
for (vert in vertices)
|
||||
finishBounds.addPoint(vert.toPoint());
|
||||
|
||||
var rotQuat = new Quat();
|
||||
rotQuat.initRotation(0, Math.PI / 2, 0);
|
||||
var rotMat = rotQuat.toMatrix();
|
||||
|
||||
var tform = this.getAbsPos().clone();
|
||||
tform.prependRotation(Math.PI / 2, 0, 0);
|
||||
|
||||
finishCollider.transform = tform;
|
||||
|
||||
finishBounds.transform(tform);
|
||||
|
||||
// var polygon = new Polygon(vertices.map(x -> x.toPoint()));
|
||||
// polygon.addNormals();
|
||||
// polygon.addUVs();
|
||||
// var collidermesh = new Mesh(polygon, Material.create(), this.level.scene);
|
||||
// collidermesh.setTransform(tform);
|
||||
}
|
||||
|
||||
override function update(timeState:TimeState) {
|
||||
super.update(timeState);
|
||||
|
||||
|
|
|
|||
|
|
@ -38,4 +38,11 @@ class Tornado extends ForceObject {
|
|||
},
|
||||
];
|
||||
}
|
||||
|
||||
public override function init(level:src.MarbleWorld) {
|
||||
super.init(level);
|
||||
for (material in this.materials) {
|
||||
// material.mainPass.setPassName("overlay");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue