Add powerups

This commit is contained in:
RandomityGuy 2021-06-07 16:29:37 +05:30
parent f69a899c8a
commit afa0c12084
14 changed files with 382 additions and 36 deletions

View file

@ -300,7 +300,8 @@ class DtsObject extends GameObject {
rootObject.scaleX = -1;
this.boundingCollider = new BoxCollisionEntity(this.getBounds().clone(), cast this);
this.boundingCollider = new BoxCollisionEntity(this.level.instanceManager.getObjectBounds(cast this), cast this);
this.boundingCollider.setTransform(this.getTransform());
}
function computeMaterials() {
@ -331,16 +332,18 @@ class DtsObject extends GameObject {
var texture:Texture = ResourceLoader.getTexture(fullName);
texture.wrap = Wrap.Repeat;
material.texture = texture;
// if (this.useInstancing) {
var dtsshader = new DtsTexture();
dtsshader.texture = texture;
dtsshader.currentOpacity = 1;
material.mainPass.removeShader(material.textureShader);
material.mainPass.addShader(dtsshader);
// }
// TODO TRANSLUENCY SHIT
}
if (flags & 4 > 0) {
material.blendMode = BlendMode.Alpha;
material.mainPass.culling = h3d.mat.Data.Face.Front;
// material.mainPass.culling = h3d.mat.Data.Face.Front;
}
// TODO TRANSPARENCY SHIT
if (flags & 8 > 0)
@ -540,6 +543,7 @@ class DtsObject extends GameObject {
public override function setTransform(mat:Matrix) {
super.setTransform(mat);
this.boundingCollider.setTransform(mat);
this.level.collisionWorld.updateTransform(this.boundingCollider);
}
public function update(currentTime:Float, dt:Float) {
@ -774,19 +778,21 @@ class DtsObject extends GameObject {
return;
this.currentOpacity = opacity;
for (material in this.materials) {
if (this.currentOpacity != 1) {
material.blendMode = BlendMode.Alpha;
if (this.alphaShader == null) {
this.alphaShader = new AlphaMult();
}
if (material.mainPass.getShader(AlphaMult) == null) {
material.mainPass.addShader(this.alphaShader);
}
this.alphaShader.alpha = this.currentOpacity;
} else {
if (alphaShader != null) {
alphaShader.alpha = this.currentOpacity;
if (!this.useInstancing) {
for (material in this.materials) {
if (this.currentOpacity != 1) {
// material.blendMode = BlendMode.Alpha;
// if (this.alphaShader == null) {
// this.alphaShader = new AlphaMult();
// }
// if (material.mainPass.getShader(AlphaMult) == null) {
// material.mainPass.addShader(this.alphaShader);
// }
// this.alphaShader.alpha = this.currentOpacity;
// } else {
// if (alphaShader != null) {
// alphaShader.alpha = this.currentOpacity;
// }
}
}
}

View file

@ -106,6 +106,21 @@ class InstanceManager {
}
}
public function getObjectBounds(object:GameObject) {
if (isInstanced(object)) {
var minfos = objects.get(object.identifier);
var invmat = minfos[0].instances[0].gameObject.getInvPos();
var b = minfos[0].instances[0].gameObject.getBounds().clone();
b.transform(invmat);
return b;
} else {
var invmat = object.getInvPos();
var b = object.getBounds().clone();
b.transform(invmat);
return b;
}
}
public function isInstanced(object:GameObject) {
if (objects.exists(object.identifier))
return true;

View file

@ -1,5 +1,8 @@
package;
import shapes.Helicopter;
import shapes.ShockAbsorber;
import shapes.SuperBounce;
import shapes.SuperSpeed;
import shapes.SignFinish;
import shapes.Trapdoor;
@ -35,8 +38,8 @@ class Main extends hxd.App {
override function init() {
super.init();
dtsObj = new SuperSpeed();
// dtsObj.z = 5;
// dtsObj = new SuperSpeed();
// dtsObj.x = -3;
world = new MarbleWorld(s3d);
@ -86,13 +89,23 @@ class Main extends hxd.App {
// world.addPathedInterior(pi);
world.addDtsObject(dtsObj);
dtsObj.setOpacity(0.5);
// world.addDtsObject(dtsObj);
var dto = new SuperSpeed();
world.addDtsObject(dto);
dto.setOpacity(1);
dto.z = 1;
// var sj = new SuperJump();
// sj.x = 3;
// world.addDtsObject(sj);
var sb = new Helicopter();
sb.y = 3;
world.addDtsObject(sb);
// var sh = new ShockAbsorber();
// sh.y = -3;
// world.addDtsObject(sh);
// var he = new Helicopter();
// world.addDtsObject(he);
// sj.setTransform(sj.getTransform());
// for (i in 0...10) {
// for (j in 0...10) {

View file

@ -1,5 +1,9 @@
package src;
import src.DtsObject;
import sdl.Cursor;
import hxd.Cursor;
import shapes.PowerUp;
import src.GameObject;
import src.ForceObject;
import src.MarbleWorld;
@ -44,7 +48,7 @@ class Marble extends GameObject {
public var level:MarbleWorld;
var gravityDir:Vector = new Vector(0, 0, -1);
public var gravityDir:Vector = new Vector(0, 0, -1);
public var _radius = 0.2;
@ -55,7 +59,7 @@ class Marble extends GameObject {
var _staticFriction = 1.1;
var _brakingAcceleration = 30;
var _gravity = 20;
var _airAccel = 5;
var _airAccel:Float = 5;
var _maxDotSlide = 0.5;
var _minBounceVel = 0.1;
var _bounceKineticFriction = 0.2;
@ -75,6 +79,15 @@ class Marble extends GameObject {
var contacts:Array<CollisionInfo> = [];
var queuedContacts:Array<CollisionInfo> = [];
public var heldPowerup:PowerUp;
public var lastContactNormal:Vector;
var forcefield:DtsObject;
var helicopter:DtsObject;
var superBounceEnableTime:Float = -1e8;
var shockAbsorberEnableTime:Float = -1e8;
var helicopterEnableTime:Float = -1e8;
public function new() {
super();
var geom = Sphere.defaultUnitSphere();
@ -91,6 +104,31 @@ class Marble extends GameObject {
this.collider = new SphereCollisionEntity(cast this);
}
public function init(level:MarbleWorld) {
this.level = level;
this.forcefield = new DtsObject();
this.forcefield.dtsPath = "data/shapes/images/glow_bounce.dts";
this.forcefield.useInstancing = true;
this.forcefield.identifier = "GlowBounce";
this.forcefield.showSequences = false;
this.addChild(this.forcefield);
this.forcefield.x = 1e8;
this.forcefield.y = 1e8;
this.forcefield.z = 1e8;
level.addDtsObject(this.forcefield);
this.helicopter = new DtsObject();
this.helicopter.dtsPath = "data/shapes/images/helicopter.dts";
this.helicopter.useInstancing = true;
this.helicopter.identifier = "Helicopter";
this.helicopter.showSequences = true;
// this.addChild(this.helicopter);
this.helicopter.x = 1e8;
this.helicopter.y = 1e8;
this.helicopter.z = 1e8;
level.addDtsObject(this.helicopter);
}
function findContacts(collisiomWorld:CollisionWorld, dt:Float) {
this.contacts = queuedContacts;
var c = collisiomWorld.sphereIntersection(this.collider, dt);
@ -101,7 +139,7 @@ class Marble extends GameObject {
this.queuedContacts.push(collisionInfo);
}
function getMarbleAxis() {
public function getMarbleAxis() {
var cammat = Matrix.I();
var xrot = new Matrix();
xrot.initRotationX(this.camera.CameraPitch);
@ -117,9 +155,12 @@ class Marble extends GameObject {
return [sidedir, motiondir, updir];
}
function getExternalForces(m:Move, dt:Float) {
function getExternalForces(currentTime:Float, m:Move, dt:Float) {
var gWorkGravityDir = gravityDir;
var A = gWorkGravityDir.multiply(this._gravity);
if (currentTime - this.helicopterEnableTime < 5) {
A = A.multiply(0.25);
}
for (obj in level.dtsObjects) {
if (obj is ForceObject) {
var force = cast(obj, ForceObject).getForce(this.getAbsPos().getPosition());
@ -157,7 +198,11 @@ class Marble extends GameObject {
var sideDir = axes[0];
var motionDir = axes[1];
var upDir = axes[2];
A = A.add(sideDir.multiply(m.d.x).add(motionDir.multiply(m.d.y)).multiply(this._airAccel));
var airAccel = this._airAccel;
if (currentTime - this.helicopterEnableTime < 5) {
airAccel *= 2;
}
A = A.add(sideDir.multiply(m.d.x).add(motionDir.multiply(m.d.y)).multiply(airAccel));
}
return A;
}
@ -206,7 +251,7 @@ class Marble extends GameObject {
return {result: true, aControl: aControl, desiredOmega: desiredOmega};
}
function velocityCancel(surfaceSlide:Bool, noBounce:Bool, stoppedPaths:Bool, pi:Array<PathedInterior>) {
function velocityCancel(currentTime:Float, dt:Float, surfaceSlide:Bool, noBounce:Bool, stoppedPaths:Bool, pi:Array<PathedInterior>) {
var SurfaceDotThreshold = 0.001;
var looped = false;
var itersIn = 0;
@ -253,6 +298,12 @@ class Marble extends GameObject {
this.velocity = vel;
} else {
var restitution = this._bounceRestitution;
if (currentTime - this.superBounceEnableTime < 5) {
restitution = 0.9;
}
if (currentTime - this.shockAbsorberEnableTime < 5) {
restitution = 0;
}
restitution *= contacts[i].restitution;
var velocityAdd = surfaceVel.multiply(-(1 + restitution));
var vAtC = sVel.add(this.omega.cross(contacts[i].normal.multiply(-this._radius)));
@ -416,6 +467,8 @@ class Marble extends GameObject {
}
A = A.add(AFriction);
a = a.add(aFriction);
lastContactNormal = bestContact.normal;
}
a = a.add(aControl);
return [A, a];
@ -530,14 +583,14 @@ class Marble extends GameObject {
var aControl = cmf.aControl;
var desiredOmega = cmf.desiredOmega;
var stoppedPaths = false;
stoppedPaths = this.velocityCancel(isCentered, false, stoppedPaths, pathedInteriors);
var A = this.getExternalForces(m, timeStep);
stoppedPaths = this.velocityCancel(currentTime, dt, isCentered, false, stoppedPaths, pathedInteriors);
var A = this.getExternalForces(currentTime, m, timeStep);
var retf = this.applyContactForces(timeStep, m, isCentered, aControl, desiredOmega, A);
A = retf[0];
var a = retf[1];
this.velocity = this.velocity.add(A.multiply(timeStep));
this.omega = this.omega.add(a.multiply(timeStep));
stoppedPaths = this.velocityCancel(isCentered, true, stoppedPaths, pathedInteriors);
stoppedPaths = this.velocityCancel(currentTime, dt, isCentered, true, stoppedPaths, pathedInteriors);
this._totalTime += timeStep;
if (contacts.length != 0) {
this._contactTime += timeStep;
@ -577,6 +630,11 @@ class Marble extends GameObject {
this.collider.setTransform(tform);
this.collider.velocity = this.velocity;
if (this.heldPowerup != null && m.powerup) {
this.heldPowerup.use(currentTime);
this.heldPowerup = null;
}
timeRemaining -= timeStep;
it++;
} while (it <= 10);
@ -602,6 +660,9 @@ class Marble extends GameObject {
if (Key.isDown(Key.SPACE)) {
move.jump = true;
}
if (Key.isDown(Key.MOUSE_LEFT)) {
move.powerup = true;
}
}
advancePhysics(currentTime, dt, move, collisionWorld, pathedInteriors);
@ -610,6 +671,37 @@ class Marble extends GameObject {
this.camera.update(dt);
}
updatePowerupStates(currentTime, dt);
// this.camera.target.load(this.getAbsPos().getPosition().toPoint());
}
public function updatePowerupStates(currentTime:Float, dt:Float) {
if (currentTime - this.shockAbsorberEnableTime < 5) {
this.forcefield.setPosition(0, 0, 0);
} else if (currentTime - this.superBounceEnableTime < 5) {
this.forcefield.setPosition(0, 0, 0);
} else {
this.forcefield.x = 1e8;
this.forcefield.y = 1e8;
this.forcefield.z = 1e8;
}
if (currentTime - this.helicopterEnableTime < 5) {
this.helicopter.setPosition(x, y, z);
} else {
this.helicopter.setPosition(1e8, 1e8, 1e8);
}
}
public function enableSuperBounce(time:Float) {
this.superBounceEnableTime = time;
}
public function enableShockAbsorber(time:Float) {
this.shockAbsorberEnableTime = time;
}
public function enableHelicopter(time:Float) {
this.helicopterEnableTime = time;
}
}

View file

@ -1,5 +1,6 @@
package src;
import shapes.PowerUp;
import collision.SphereCollisionEntity;
import src.Sky;
import h3d.scene.Mesh;
@ -32,7 +33,7 @@ class MarbleWorld {
public var scene:Scene;
var marble:Marble;
public var marble:Marble;
public function new(scene:Scene) {
this.collisionWorld = new CollisionWorld();
@ -83,6 +84,7 @@ class MarbleWorld {
marble.level = cast this;
if (marble.controllable) {
marble.camera.init(cast this);
marble.init(cast this);
this.scene.addChild(marble.camera);
this.marble = marble;
// Ugly hack
@ -151,4 +153,26 @@ class MarbleWorld {
this.shapeImmunity = newImmunity;
}
public function pickUpPowerUp(powerUp:PowerUp) {
if (this.marble.heldPowerup != null)
return false;
this.marble.heldPowerup = powerUp;
// for (let overlayShape
// of
// this.overlayShapes
// )
// {
// if (overlayShape.dtsPath.includes("gem"))
// continue;
// // Show the corresponding icon in the HUD
// if (overlayShape.dtsPath == = powerUp.dtsPath)
// this.overlayScene.add(overlayShape.group);
// else
// this.overlayScene.remove(overlayShape.group);
// }
// if (!this.rewinding)
// AudioManager.play(powerUp.sounds[0]);
return true;
}
}

View file

@ -81,4 +81,9 @@ class CollisionWorld {
public function addMovingEntity(entity:CollisionEntity) {
this.dynamicEntities.push(entity);
}
public function updateTransform(entity:CollisionEntity) {
this.octree.remove(entity);
this.octree.insert(entity);
}
}

View file

@ -111,7 +111,7 @@ class OctreeNode implements IOctreeElement {
}
public function merge() {
if (this.count > 8 || !(this.octants == null))
if (this.count > 8 || (this.octants == null))
return;
// Add all objects in the octants back to this node
for (i in 0...8) {

View file

@ -10,4 +10,17 @@ class AntiGravity extends PowerUp {
this.isTSStatic = false;
this.identifier = "AntiGravity";
}
public function pickUp():Bool {
return this.level.pickUpPowerUp(this);
}
public function use(time:Float) {
var marble = this.level.marble;
// marble.body.addLinearVelocity(this.level.currentUp.scale(20)); // Simply add to vertical velocity
// if (!this.level.rewinding)
// AudioManager.play(this.sounds[1]);
// this.level.particles.createEmitter(superJumpParticleOptions, null, () => Util.vecOimoToThree(marble.body.getPosition()));
// this.level.deselectPowerUp();
}
}

28
src/shapes/Helicopter.hx Normal file
View file

@ -0,0 +1,28 @@
package shapes;
import src.DtsObject;
class Helicopter extends PowerUp {
public function new() {
super();
this.dtsPath = "data/shapes/images/helicopter.dts";
this.isCollideable = false;
this.isTSStatic = false;
this.showSequences = false;
this.identifier = "Helicopter";
}
public function pickUp():Bool {
return this.level.pickUpPowerUp(this);
}
public function use(time:Float) {
var marble = this.level.marble;
marble.enableHelicopter(time);
// marble.body.addLinearVelocity(this.level.currentUp.scale(20)); // Simply add to vertical velocity
// if (!this.level.rewinding)
// AudioManager.play(this.sounds[1]);
// this.level.particles.createEmitter(superJumpParticleOptions, null, () => Util.vecOimoToThree(marble.body.getPosition()));
// this.level.deselectPowerUp();
}
}

View file

@ -1,15 +1,68 @@
package shapes;
import src.Util;
import h3d.Vector;
import src.DtsObject;
class PowerUp extends DtsObject {
public var lastPickupTime:Float = -1;
class PowerupParams {
public var duration:Float = 5;
public var airAccel = 1.0;
public var activateTime:Float = 0;
public var bounce = -1.0;
public var sizeScale = 1.0;
public var massScale = 1.0;
public var gravityMod = 1.0;
public var repulseDist = 0.0;
public var repulseMax = 0.0;
public var boostDir = new Vector();
public var timeFreeze:Float = 0;
public var boostAmount = 0.0;
public var boostMassless = 0.0;
public function new() {};
}
abstract class PowerUp extends DtsObject {
public var lastPickUpTime:Float = -1;
public var cooldownDuration:Float = 7;
public var autoUse:Bool = false;
public var powerupParams:PowerupParams = new PowerupParams();
public function new() {
super();
this.isCollideable = false;
this.ambientRotate = true;
}
public override function onMarbleInside(time:Float) {
var pickupable = this.lastPickUpTime == -1 || (time - this.lastPickUpTime) >= this.cooldownDuration;
if (!pickupable)
return;
if (this.pickUp()) {
// this.level.replay.recordMarbleInside(this);
this.lastPickUpTime = time;
if (this.autoUse)
this.use(time);
// displayAlert(`You picked up a ${this.pickUpName}!`);
// if (this.element.showhelponpickup === "1" && !this.autoUse) displayHelp(`Press <func:bind mousefire> to use the ${this.pickUpName}!`);
}
}
public override function update(currentTime:Float, dt:Float) {
super.update(currentTime, dt);
var opacity = 1.0;
if (this.lastPickUpTime > 0 && this.cooldownDuration > 0) {
var availableTime = this.lastPickUpTime + this.cooldownDuration;
opacity = Util.clamp((currentTime - availableTime), 0, 1);
}
this.setOpacity(opacity);
}
public abstract function pickUp():Bool;
public abstract function use(time:Float):Void;
}

View file

@ -0,0 +1,27 @@
package shapes;
import src.DtsObject;
class ShockAbsorber extends PowerUp {
public function new() {
super();
this.dtsPath = "data/shapes/items/shockabsorber.dts";
this.isCollideable = false;
this.isTSStatic = false;
this.identifier = "ShockAbsorber";
}
public function pickUp():Bool {
return this.level.pickUpPowerUp(this);
}
public function use(time:Float) {
var marble = this.level.marble;
marble.enableShockAbsorber(time);
// marble.body.addLinearVelocity(this.level.currentUp.scale(20)); // Simply add to vertical velocity
// if (!this.level.rewinding)
// AudioManager.play(this.sounds[1]);
// this.level.particles.createEmitter(superJumpParticleOptions, null, () => Util.vecOimoToThree(marble.body.getPosition()));
// this.level.deselectPowerUp();
}
}

27
src/shapes/SuperBounce.hx Normal file
View file

@ -0,0 +1,27 @@
package shapes;
import src.DtsObject;
class SuperBounce extends PowerUp {
public function new() {
super();
this.dtsPath = "data/shapes/items/superbounce.dts";
this.isCollideable = false;
this.isTSStatic = false;
this.identifier = "SuperBounce";
}
public function pickUp():Bool {
return this.level.pickUpPowerUp(this);
}
public function use(time:Float) {
var marble = this.level.marble;
marble.enableSuperBounce(time);
// marble.body.addLinearVelocity(this.level.currentUp.scale(20)); // Simply add to vertical velocity
// if (!this.level.rewinding)
// AudioManager.play(this.sounds[1]);
// this.level.particles.createEmitter(superJumpParticleOptions, null, () => Util.vecOimoToThree(marble.body.getPosition()));
// this.level.deselectPowerUp();
}
}

View file

@ -10,4 +10,18 @@ class SuperJump extends PowerUp {
this.isTSStatic = false;
this.identifier = "SuperJump";
}
public function pickUp():Bool {
return this.level.pickUpPowerUp(this);
}
public function use(time:Float) {
var marble = this.level.marble;
marble.velocity = marble.velocity.add(marble.gravityDir.multiply(-20));
// marble.body.addLinearVelocity(this.level.currentUp.scale(20)); // Simply add to vertical velocity
// if (!this.level.rewinding)
// AudioManager.play(this.sounds[1]);
// this.level.particles.createEmitter(superJumpParticleOptions, null, () => Util.vecOimoToThree(marble.body.getPosition()));
// this.level.deselectPowerUp();
}
}

View file

@ -1,5 +1,7 @@
package shapes;
import h3d.Quat;
import h3d.Vector;
import src.DtsObject;
class SuperSpeed extends PowerUp {
@ -11,4 +13,31 @@ class SuperSpeed extends PowerUp {
this.identifier = "SuperSpeed";
this.useInstancing = true;
}
public function pickUp():Bool {
return this.level.pickUpPowerUp(this);
}
public function use(time:Float) {
var marble = this.level.marble;
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.
// var quat = level.newOrientationQuat;
// movementVector.applyQuaternion(quat);
var quat2 = new Quat();
// Determine the necessary rotation to rotate the up vector to the contact normal.
quat2.initMoveTo(marble.gravityDir.multiply(-1), marble.lastContactNormal);
movementVector.transform(quat2.toMatrix());
marble.velocity = marble.velocity.add(movementVector.multiply(-24.7));
// 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
// if (!this.level.rewinding)
// AudioManager.play(this.sounds[1]);
// this.level.particles.createEmitter(superJumpParticleOptions, null, () => Util.vecOimoToThree(marble.body.getPosition()));
// this.level.deselectPowerUp();
}
}