Add start and finish things

This commit is contained in:
RandomityGuy 2021-06-15 22:27:17 +05:30
parent 0060a403d2
commit 7644c4c8de
6 changed files with 228 additions and 36 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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');

View file

@ -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);

View file

@ -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");
}
}
}