changed game dynamics.
This commit is contained in:
parent
5b7d04bd39
commit
c9d03e832d
@ -1,20 +1,21 @@
|
||||
import {DefaultScene} from "./defaultScene";
|
||||
import {
|
||||
AbstractMesh,
|
||||
Color3, DistanceConstraint, Engine, InstancedMesh, Mesh,
|
||||
Color3, DistanceConstraint, Engine, InstancedMesh, LinesMesh, Mesh,
|
||||
MeshBuilder,
|
||||
Observable,
|
||||
ParticleHelper,
|
||||
PhysicsAggregate,
|
||||
PhysicsMotionType,
|
||||
PhysicsShapeType, Sound,
|
||||
PhysicsShapeType, PointsCloudSystem, Sound,
|
||||
StandardMaterial, TransformNode,
|
||||
Vector3
|
||||
} from "@babylonjs/core";
|
||||
import {Ship} from "./ship";
|
||||
import {ScoreEvent} from "./scoreEvent";
|
||||
|
||||
import {RockFactory} from "./starfield";
|
||||
import Level from "./level";
|
||||
import {Scoreboard} from "./scoreboard";
|
||||
|
||||
export class Level1 implements Level {
|
||||
private _ship: Ship;
|
||||
@ -22,10 +23,11 @@ export class Level1 implements Level {
|
||||
private _initialized: boolean = false;
|
||||
private _startBase: AbstractMesh;
|
||||
private _endBase: AbstractMesh;
|
||||
public onScoreObservable: Observable<ScoreEvent> = new Observable<ScoreEvent>();
|
||||
private _scoreboard: Scoreboard;
|
||||
|
||||
constructor() {
|
||||
this._ship = new Ship();
|
||||
this._scoreboard = new Scoreboard();
|
||||
const xr = DefaultScene.XR;
|
||||
xr.baseExperience.onInitialXRPoseSetObservable.add(() => {
|
||||
xr.baseExperience.camera.parent = this._ship.transformNode;
|
||||
@ -35,7 +37,6 @@ export class Level1 implements Level {
|
||||
this._ship.addController(controller);
|
||||
});
|
||||
this.createStartBase();
|
||||
|
||||
this.initialize();
|
||||
|
||||
}
|
||||
@ -55,6 +56,7 @@ export class Level1 implements Level {
|
||||
this._endBase.dispose();
|
||||
}
|
||||
public async initialize() {
|
||||
console.log('initialize');
|
||||
if (this._initialized) {
|
||||
return;
|
||||
}
|
||||
@ -62,17 +64,37 @@ export class Level1 implements Level {
|
||||
ParticleHelper.BaseAssetsUrl = window.location.href;
|
||||
this._ship.position = new Vector3(0, 1, 0);
|
||||
await RockFactory.init();
|
||||
const baseTransform = new TransformNode("baseTransform", DefaultScene.MainScene);
|
||||
baseTransform.position = this._startBase.getAbsolutePosition();
|
||||
|
||||
for (let i = 0; i < 50; i++) {
|
||||
const dist = (Math.random() * 200) + 190;
|
||||
const rock = await RockFactory.createRock(i, new Vector3(Math.random() * 200 +50 * Math.sign(Math.random() -.5),200,200), Vector3.Random(1, 5))
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const dist = (Math.random() * 50) + 190;
|
||||
const size = Vector3.Random(1,1.3).scale(Math.random() * 5 + 5)
|
||||
|
||||
const rock = await RockFactory.createRock(i, new Vector3(Math.random() * 200 +50 * Math.sign(Math.random() -.5),200,200),
|
||||
size,
|
||||
this._scoreboard.onScoreObservable);
|
||||
const constraint = new DistanceConstraint(dist, DefaultScene.MainScene);
|
||||
//rock.physicsBody.addConstraint(this._endBase.physicsBody, constraint);
|
||||
|
||||
/*
|
||||
const options: {updatable: boolean, points: Array<Vector3>, instance?: LinesMesh} =
|
||||
{updatable: true, points: [rock.position, this._startBase.absolutePosition]}
|
||||
|
||||
let line = MeshBuilder.CreateLines("line", options , DefaultScene.MainScene);
|
||||
|
||||
line.color = new Color3(1, 0, 0);
|
||||
DefaultScene.MainScene.onAfterRenderObservable.add(() => {
|
||||
//const pos = rock.position;
|
||||
options.points[0].copyFrom(rock.position);
|
||||
options.instance = line;
|
||||
line = MeshBuilder.CreateLines("lines", options);
|
||||
});
|
||||
*/
|
||||
this._scoreboard.onScoreObservable.notifyObservers({
|
||||
score: 0,
|
||||
remaining: 1,
|
||||
message: "Get Ready"
|
||||
});
|
||||
this._startBase.physicsBody.addConstraint(rock.physicsBody, constraint);
|
||||
rock.physicsBody.applyForce(Vector3.Random(-1, 1).scale(50000000), rock.getAbsolutePosition());
|
||||
//rock.physicsBody.setAngularVelocity(Vector3.Random(-.5, .5));
|
||||
rock.physicsBody.applyForce(Vector3.Random(-1, 1).scale(5000000), rock.position);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
30
src/main.ts
30
src/main.ts
@ -1,4 +1,13 @@
|
||||
import {Engine, HavokPlugin, PhotoDome, Scene, Vector3, WebGPUEngine, WebXRDefaultExperience} from "@babylonjs/core";
|
||||
import {
|
||||
Color3,
|
||||
Engine,
|
||||
HavokPlugin,
|
||||
PhotoDome,
|
||||
Scene, StandardMaterial,
|
||||
Vector3,
|
||||
WebGPUEngine,
|
||||
WebXRDefaultExperience
|
||||
} from "@babylonjs/core";
|
||||
import '@babylonjs/loaders';
|
||||
import HavokPhysics from "@babylonjs/havok";
|
||||
|
||||
@ -21,6 +30,10 @@ export class Main {
|
||||
private _gameState: GameState = GameState.DEMO;
|
||||
constructor() {
|
||||
this._loadingDiv = document.querySelector('#loadingDiv');
|
||||
if (!navigator.xr) {
|
||||
this._loadingDiv.innerText = "This browser does not support WebXR";
|
||||
return;
|
||||
}
|
||||
this.initialize();
|
||||
|
||||
document.querySelector('#startButton').addEventListener('click', () => {
|
||||
@ -55,7 +68,18 @@ export class Main {
|
||||
this._currentLevel.getReadyObservable().add(() => {
|
||||
|
||||
});
|
||||
const photoDome = new PhotoDome("testdome", '/8192.webp', {}, DefaultScene.MainScene);
|
||||
|
||||
const photoDome1 = new PhotoDome("testdome", '/8192.webp', {size: 1000}, DefaultScene.MainScene);
|
||||
photoDome1.material.diffuseTexture.hasAlpha = true;
|
||||
photoDome1.material.alpha = .3;
|
||||
|
||||
const photoDome2 = new PhotoDome("testdome", '/8192.webp', {size: 2000}, DefaultScene.MainScene);
|
||||
photoDome2.rotation.y = Math.PI;
|
||||
photoDome2.rotation.x = Math.PI/2;
|
||||
DefaultScene.MainScene.onAfterRenderObservable.add(() => {
|
||||
photoDome1.position = DefaultScene.MainScene.activeCamera.globalPosition;
|
||||
photoDome2.position = DefaultScene.MainScene.activeCamera.globalPosition;
|
||||
});
|
||||
}
|
||||
private setLoadingMessage(message: string) {
|
||||
this._loadingDiv.innerText = message;
|
||||
@ -75,6 +99,7 @@ export class Main {
|
||||
}
|
||||
DefaultScene.DemoScene = new Scene(engine);
|
||||
DefaultScene.MainScene = new Scene(engine);
|
||||
DefaultScene.MainScene.ambientColor = new Color3(.2, .2, .2);
|
||||
|
||||
this.setLoadingMessage("Initializing Physics Engine..");
|
||||
await this.setupPhysics();
|
||||
@ -98,6 +123,7 @@ export class Main {
|
||||
const havok = await HavokPhysics();
|
||||
const havokPlugin = new HavokPlugin(true, havok);
|
||||
DefaultScene.MainScene.enablePhysics(new Vector3(0, 0, 0), havokPlugin);
|
||||
DefaultScene.MainScene.getPhysicsEngine().setSubTimeStep(5);
|
||||
DefaultScene.MainScene.collisionsEnabled = true;
|
||||
}
|
||||
|
||||
|
||||
@ -1,40 +1,46 @@
|
||||
import {AdvancedDynamicTexture, Control, StackPanel, TextBlock} from "@babylonjs/gui";
|
||||
import {DefaultScene} from "./defaultScene";
|
||||
import {
|
||||
AbstractMesh,
|
||||
ActionManager,
|
||||
Angle,
|
||||
ExecuteCodeAction,
|
||||
MeshBuilder,
|
||||
Observable,
|
||||
TransformNode,
|
||||
Observable, StandardMaterial,
|
||||
Vector3,
|
||||
} from "@babylonjs/core";
|
||||
import {ScoreEvent} from "./scoreEvent";
|
||||
|
||||
export type ScoreEvent = {
|
||||
score: number,
|
||||
message: string,
|
||||
remaining: number,
|
||||
timeRemaining? : number
|
||||
}
|
||||
export class Scoreboard {
|
||||
private _score: number = 0;
|
||||
private _remaining: number = 0;
|
||||
private _timeRemaining: number = 61;
|
||||
private _lastMessage: string = null;
|
||||
public onscoreObservable: Observable<ScoreEvent> = new Observable<ScoreEvent>();
|
||||
private _active = false;
|
||||
private _done = false;
|
||||
public readonly onScoreObservable: Observable<ScoreEvent> = new Observable<ScoreEvent>();
|
||||
constructor() {
|
||||
DefaultScene.MainScene.onNewMeshAddedObservable.add((mesh) => {
|
||||
if (mesh.id == 'RightUpperDisplay') {
|
||||
window.setTimeout(() => {
|
||||
//mesh.material = null;
|
||||
this.initialize();
|
||||
},1000);
|
||||
|
||||
this.initialize();
|
||||
}
|
||||
});
|
||||
//this.initialize(camera);
|
||||
}
|
||||
public get done() {
|
||||
return this._done;
|
||||
}
|
||||
public set done(value: boolean) {
|
||||
this._done = value;
|
||||
}
|
||||
private initialize() {
|
||||
const scene = DefaultScene.MainScene;
|
||||
|
||||
const parent = scene.getMeshById('RightUpperDisplay');
|
||||
const scoreboard = MeshBuilder.CreatePlane("scoreboard", {width: 1, height: 1}, scene);
|
||||
scoreboard.parent =parent;
|
||||
const material = new StandardMaterial("scoreboard", scene);
|
||||
|
||||
scoreboard.parent =parent;
|
||||
scoreboard.position.x = -.76;
|
||||
scoreboard.position.y = 4.19;
|
||||
scoreboard.position.z = .53;
|
||||
@ -42,43 +48,71 @@ export class Scoreboard {
|
||||
scoreboard.rotation.z = Math.PI;
|
||||
scoreboard.scaling = new Vector3(.3, .3, .3);
|
||||
|
||||
const advancedTexture = AdvancedDynamicTexture.CreateForMesh(scoreboard);
|
||||
const advancedTexture = AdvancedDynamicTexture.CreateForMesh(scoreboard, 512, 512);
|
||||
advancedTexture.background = "black";
|
||||
advancedTexture.hasAlpha = false;
|
||||
const scoreText = this.createText();
|
||||
advancedTexture.addControl(scoreText);
|
||||
|
||||
const fpsText = this.createText();
|
||||
fpsText.top = '120px';
|
||||
fpsText.text = "FPS: 60";
|
||||
|
||||
const hullText = this.createText();
|
||||
//hullText.top = '240px';
|
||||
hullText.text = 'Hull: 100%';
|
||||
|
||||
const remainingText = this.createText();
|
||||
remainingText.text = 'Remaining: 0';
|
||||
|
||||
const timeRemainingText = this.createText();
|
||||
timeRemainingText.text = 'Time: 2:00';
|
||||
|
||||
const panel = new StackPanel();
|
||||
panel.isVertical = true;
|
||||
advancedTexture.addControl(fpsText);
|
||||
advancedTexture.addControl(scoreText);
|
||||
panel.height = 1;
|
||||
panel.isVertical = true;
|
||||
panel.addControl(scoreText);
|
||||
panel.addControl(remainingText);
|
||||
panel.addControl(fpsText);
|
||||
panel.addControl(hullText);
|
||||
panel.addControl(timeRemainingText);
|
||||
|
||||
advancedTexture.addControl(panel);
|
||||
|
||||
scene.onAfterRenderObservable.add(() => {
|
||||
let i = 0;
|
||||
let lastSecond: number = Date.now();
|
||||
const afterRender = scene.onAfterRenderObservable.add(() => {
|
||||
scoreText.text = `Score: ${this.calculateScore()}`;
|
||||
if (this._lastMessage != null) {
|
||||
fpsText.text = this._lastMessage;
|
||||
} else {
|
||||
fpsText.text = '';
|
||||
remainingText.text = `Remaining: ${this._remaining}`;
|
||||
const now = Date.now();
|
||||
if (this._active && (Math.floor(lastSecond / 1000) < Math.floor(now/1000))) {
|
||||
this._timeRemaining--;
|
||||
if (this._timeRemaining <= 0) {
|
||||
scene.onAfterRenderObservable.remove(afterRender);
|
||||
}
|
||||
lastSecond = now;
|
||||
timeRemainingText.text = `Time: ${Math.floor(this._timeRemaining/60).toString().padStart(2,"0")}:${(this._timeRemaining%60).toString().padStart(2,"0")}`;
|
||||
}
|
||||
if (i++%60 == 0) {
|
||||
fpsText.text = `FPS: ${Math.floor(scene.getEngine().getFps())}`;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
this.onscoreObservable.add((score) => {
|
||||
this._score += score.score;
|
||||
this.onScoreObservable.add((score: ScoreEvent) => {
|
||||
this._score += score.score * this._timeRemaining;
|
||||
this._remaining += score.remaining;
|
||||
this._lastMessage = score.message;
|
||||
if (score.timeRemaining) {
|
||||
this._timeRemaining = score.timeRemaining;
|
||||
}
|
||||
});
|
||||
this._active = true;
|
||||
}
|
||||
private createText(): TextBlock {
|
||||
const text1 = new TextBlock();
|
||||
|
||||
text1.color = "white";
|
||||
text1.fontSize = 90;
|
||||
text1.fontSize = "60px";
|
||||
text1.height = "80px";
|
||||
text1.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
|
||||
text1.textVerticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
|
||||
text1.textVerticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
|
||||
return text1;
|
||||
}
|
||||
private calculateScore() {
|
||||
|
||||
148
src/ship.ts
148
src/ship.ts
@ -2,9 +2,8 @@ import {
|
||||
AbstractMesh,
|
||||
Color3,
|
||||
DirectionalLight,
|
||||
Engine,
|
||||
FreeCamera,
|
||||
GlowLayer,
|
||||
GlowLayer, InstancedMesh, Mesh,
|
||||
MeshBuilder,
|
||||
Observable,
|
||||
PhysicsAggregate,
|
||||
@ -22,9 +21,7 @@ import {
|
||||
WebXRInputSource
|
||||
} from "@babylonjs/core";
|
||||
import {DefaultScene} from "./defaultScene";
|
||||
|
||||
import {ShipEngine} from "./shipEngine";
|
||||
import {Level1} from "./level1";
|
||||
const MAX_FORWARD_THRUST = 40;
|
||||
|
||||
const controllerComponents = [
|
||||
'a-button',
|
||||
@ -49,6 +46,7 @@ type ControllerEvent = {
|
||||
}
|
||||
|
||||
enum ControllerStickMode {
|
||||
BEGINNER,
|
||||
ARCADE,
|
||||
REALISTIC
|
||||
}
|
||||
@ -56,30 +54,31 @@ enum ControllerStickMode {
|
||||
export class Ship {
|
||||
private _ship: TransformNode;
|
||||
private _controllerObservable: Observable<ControllerEvent> = new Observable<ControllerEvent>();
|
||||
public onReadyObservable: Observable<unknown> = new Observable<unknown>();
|
||||
private _engine: ShipEngine;
|
||||
private _ammoMaterial: StandardMaterial;
|
||||
private _forwardNode: TransformNode;
|
||||
private _rotationNode: TransformNode;
|
||||
private _onscore: Observable<number>;
|
||||
private _ammo: Array<AbstractMesh> = [];
|
||||
private _glowLayer: GlowLayer;
|
||||
private _thrust: Sound;
|
||||
private _thrust2: Sound;
|
||||
private _primaryThrustVectorSound: Sound;
|
||||
private _secondaryThrustVectorSound: Sound;
|
||||
private _shot: Sound;
|
||||
private _shooting: boolean = false;
|
||||
private _camera: FreeCamera;
|
||||
|
||||
constructor() {
|
||||
|
||||
private _ammoBaseMesh: AbstractMesh;
|
||||
private _controllerMode: ControllerStickMode;
|
||||
private _active = false;
|
||||
constructor(mode: ControllerStickMode = ControllerStickMode.BEGINNER) {
|
||||
this._controllerMode = mode
|
||||
this.setup();
|
||||
this.initialize();
|
||||
}
|
||||
public set controllerMode(mode: ControllerStickMode) {
|
||||
this._controllerMode = mode;
|
||||
}
|
||||
|
||||
private shoot() {
|
||||
this._shot.play();
|
||||
const ammo = MeshBuilder.CreateCapsule("bullet", {radius: .1, height: 2.5}, DefaultScene.MainScene);
|
||||
ammo.parent = this._ship
|
||||
const ammo = new InstancedMesh("ammo", this._ammoBaseMesh as Mesh);
|
||||
ammo.parent = this._ship;
|
||||
ammo.position.y = 2;
|
||||
ammo.rotation.x = Math.PI / 2;
|
||||
ammo.setParent(null);
|
||||
@ -87,17 +86,18 @@ export class Ship {
|
||||
mass: 1000,
|
||||
restitution: 0
|
||||
}, DefaultScene.MainScene);
|
||||
ammoAggregate.body.setAngularDamping(1);
|
||||
|
||||
|
||||
ammo.material = this._ammoMaterial;
|
||||
ammoAggregate.body.setMotionType(PhysicsMotionType.DYNAMIC);
|
||||
|
||||
ammoAggregate.body.setLinearVelocity(this._ship.forward.scale(200).add(this._ship.physicsBody.getLinearVelocity()));
|
||||
ammoAggregate.body.setLinearVelocity(this._ship.forward.scale(10000))
|
||||
//.add(this._ship.physicsBody.getLinearVelocity()));
|
||||
|
||||
window.setTimeout(() => {
|
||||
ammoAggregate.dispose();
|
||||
ammo.dispose()
|
||||
}, 1500)
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
public set position(newPosition: Vector3) {
|
||||
@ -113,11 +113,11 @@ export class Ship {
|
||||
this._ship = new TransformNode("ship", DefaultScene.MainScene);
|
||||
this._glowLayer = new GlowLayer('bullets', DefaultScene.MainScene);
|
||||
this._glowLayer.intensity = 1;
|
||||
this._thrust = new Sound("thrust", "/thrust5.mp3", DefaultScene.MainScene, null, {
|
||||
this._primaryThrustVectorSound = new Sound("thrust", "/thrust5.mp3", DefaultScene.MainScene, null, {
|
||||
loop: true,
|
||||
autoplay: false
|
||||
});
|
||||
this._thrust2 = new Sound("thrust2", "/thrust5.mp3", DefaultScene.MainScene, null, {
|
||||
this._secondaryThrustVectorSound = new Sound("thrust2", "/thrust5.mp3", DefaultScene.MainScene, null, {
|
||||
loop: true,
|
||||
autoplay: false,
|
||||
volume: .5
|
||||
@ -126,6 +126,9 @@ export class Ship {
|
||||
{loop: false, autoplay: false, volume: .5});
|
||||
this._ammoMaterial = new StandardMaterial("ammoMaterial", DefaultScene.MainScene);
|
||||
this._ammoMaterial.emissiveColor = new Color3(1, 1, 0);
|
||||
this._ammoBaseMesh = MeshBuilder.CreateCapsule("bullet", {radius: .1, height: 2.5}, DefaultScene.MainScene);
|
||||
this._ammoBaseMesh.material = this._ammoMaterial;
|
||||
|
||||
const light = new DirectionalLight("light", new Vector3(.1, -1, 0), DefaultScene.MainScene);
|
||||
|
||||
const landingLight = new SpotLight("landingLight", new Vector3(0, 0, 0), new Vector3(0, -.5, .5), 1.5, .5, DefaultScene.MainScene);
|
||||
@ -163,13 +166,17 @@ export class Ship {
|
||||
signtMaterial.emissiveColor = Color3.Yellow();
|
||||
sight.material = signtMaterial;
|
||||
sight.position = new Vector3(0, 2, 125);
|
||||
|
||||
window.setInterval(() => {
|
||||
this.applyForce();
|
||||
}, 50);
|
||||
let i = Date.now();
|
||||
DefaultScene.MainScene.onBeforeRenderObservable.add(() => {
|
||||
if (Date.now() - i > 50 && this._active == true) {
|
||||
this.applyForce();
|
||||
i = Date.now();
|
||||
}
|
||||
});
|
||||
this._active = true;
|
||||
}
|
||||
private async initialize() {
|
||||
const importMesh = await SceneLoader.ImportMeshAsync(null, "./", "cockpit3.glb", DefaultScene.MainScene);
|
||||
const importMesh = await SceneLoader.ImportMeshAsync(null, "./", "cockpit2.glb", DefaultScene.MainScene);
|
||||
const shipMesh = importMesh.meshes[0];
|
||||
shipMesh.id = "shipMesh";
|
||||
shipMesh.name = "shipMesh";
|
||||
@ -177,7 +184,8 @@ export class Ship {
|
||||
shipMesh.rotation.y = Math.PI;
|
||||
shipMesh.position.y = 1;
|
||||
shipMesh.position.z = -1;
|
||||
DefaultScene.MainScene.getMaterialById('glass_mat.002').alpha = .7;
|
||||
|
||||
DefaultScene.MainScene.getMaterialById('glass_mat.002').alpha = .4;
|
||||
}
|
||||
|
||||
|
||||
@ -190,65 +198,41 @@ export class Ship {
|
||||
private _mouseDown = false;
|
||||
private _mousePos = new Vector2(0, 0);
|
||||
|
||||
private scale(value: number) {
|
||||
return value * .8;
|
||||
}
|
||||
|
||||
|
||||
public get transformNode() {
|
||||
return this._ship;
|
||||
}
|
||||
|
||||
private adjust(value: number, increment: number = .8): number {
|
||||
if (Math.abs(value) < .001) {
|
||||
return 0;
|
||||
} else {
|
||||
return value * increment;
|
||||
}
|
||||
}
|
||||
|
||||
private applyForce() {
|
||||
if (!this?._ship?.physicsBody) {
|
||||
return;
|
||||
}
|
||||
const body = this._ship.physicsBody;
|
||||
if (Math.abs(this._forwardValue) > 40) {
|
||||
this._forwardValue = Math.sign(this._forwardValue) * 40;
|
||||
//If we're moving over MAX_FORWARD_THRUST, we can't add any more thrust,
|
||||
//just continue at MAX_FORWARD_THRUST
|
||||
if (Math.abs(this._forwardValue) > MAX_FORWARD_THRUST) {
|
||||
this._forwardValue = Math.sign(this._forwardValue) * MAX_FORWARD_THRUST;
|
||||
}
|
||||
|
||||
if (Math.abs(this._forwardValue) <= 40) {
|
||||
//if forward thrust is under 40 we can apply more thrust
|
||||
if (Math.abs(this._forwardValue) <= MAX_FORWARD_THRUST) {
|
||||
if (Math.abs(this._leftStickVector.y) > .1) {
|
||||
if (!this._thrust.isPlaying) {
|
||||
this._thrust.play();
|
||||
if (!this._primaryThrustVectorSound.isPlaying) {
|
||||
this._primaryThrustVectorSound.play();
|
||||
}
|
||||
this._thrust.setVolume(Math.abs(this._leftStickVector.y));
|
||||
this._primaryThrustVectorSound.setVolume(Math.abs(this._leftStickVector.y));
|
||||
this._forwardValue += this._leftStickVector.y * .8;
|
||||
} else {
|
||||
if (this._thrust.isPlaying) {
|
||||
this._thrust.pause();
|
||||
if (this._primaryThrustVectorSound.isPlaying) {
|
||||
this._primaryThrustVectorSound.pause();
|
||||
}
|
||||
this._forwardValue = this.adjust(this._forwardValue, .98);
|
||||
this._forwardValue = decrementValue(this._forwardValue, .98);
|
||||
}
|
||||
}
|
||||
|
||||
if (Math.abs(this._leftStickVector.x) > .1) {
|
||||
this._yawValue += this._leftStickVector.x * .03;
|
||||
} else {
|
||||
|
||||
this._yawValue = this.adjust(this._yawValue);
|
||||
}
|
||||
|
||||
if (Math.abs(this._rightStickVector.x) > .1) {
|
||||
this._rollValue += this._rightStickVector.x * .03;
|
||||
} else {
|
||||
this._rollValue = this.adjust(this._rollValue);
|
||||
}
|
||||
|
||||
if (Math.abs(this._rightStickVector.y) > .1) {
|
||||
this._pitchValue += this._rightStickVector.y * .03;
|
||||
} else {
|
||||
this._pitchValue = this.adjust(this._pitchValue);
|
||||
}
|
||||
this._yawValue = adjustStickValue(this._leftStickVector.x, this._yawValue);
|
||||
this._rollValue = adjustStickValue(this._rightStickVector.x, this._rollValue);
|
||||
this._pitchValue = adjustStickValue(this._rightStickVector.y, this._pitchValue);
|
||||
|
||||
this._forwardNode.position.z = this._forwardValue;
|
||||
this._rotationNode.position.y = this._yawValue;
|
||||
@ -260,20 +244,18 @@ export class Ship {
|
||||
Math.abs(this._leftStickVector.x);
|
||||
|
||||
if (thrust2 > .01) {
|
||||
if (!this._thrust2.isPlaying) {
|
||||
this._thrust2.play();
|
||||
if (!this._secondaryThrustVectorSound.isPlaying) {
|
||||
this._secondaryThrustVectorSound.play();
|
||||
}
|
||||
this._thrust2.setVolume(thrust2 * .4);
|
||||
this._secondaryThrustVectorSound.setVolume(thrust2 * .4);
|
||||
} else {
|
||||
if (this._thrust2.isPlaying) {
|
||||
this._thrust2.pause();
|
||||
if (this._secondaryThrustVectorSound.isPlaying) {
|
||||
this._secondaryThrustVectorSound.pause();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
body.setAngularVelocity(this._rotationNode.absolutePosition.subtract(this._ship.absolutePosition));
|
||||
body.setLinearVelocity(this._forwardNode.absolutePosition.subtract(this._ship.absolutePosition).scale(-1));
|
||||
//this._engine.forwardback(this._forwardValue);
|
||||
}
|
||||
|
||||
private controllerCallback = (controllerEvent: ControllerEvent) => {
|
||||
@ -349,7 +331,6 @@ export class Ship {
|
||||
case '1':
|
||||
this._camera.position.x = 15;
|
||||
this._camera.rotation.y = -Math.PI / 2;
|
||||
console.log(1);
|
||||
break;
|
||||
case ' ':
|
||||
this.shoot();
|
||||
@ -386,14 +367,12 @@ export class Ship {
|
||||
if (controller.inputSource.handedness == "left") {
|
||||
this._leftInputSource = controller;
|
||||
this._leftInputSource.onMotionControllerInitObservable.add((motionController) => {
|
||||
console.log(motionController);
|
||||
this.mapMotionController(motionController);
|
||||
});
|
||||
}
|
||||
if (controller.inputSource.handedness == "right") {
|
||||
this._rightInputSource = controller;
|
||||
this._rightInputSource.onMotionControllerInitObservable.add((motionController) => {
|
||||
console.log(motionController);
|
||||
this.mapMotionController(motionController);
|
||||
});
|
||||
}
|
||||
@ -434,4 +413,19 @@ export class Ship {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
function decrementValue(value: number, increment: number = .8): number {
|
||||
if (Math.abs(value) < .01) {
|
||||
return 0;
|
||||
} else {
|
||||
return value * increment;
|
||||
}
|
||||
}
|
||||
|
||||
function adjustStickValue(stickVector: number, thrustValue: number): number {
|
||||
if (Math.abs(stickVector) > .03) {
|
||||
return thrustValue + (Math.pow(stickVector, 3) * .1);
|
||||
} else {
|
||||
return decrementValue(thrustValue, .85);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,69 +1,95 @@
|
||||
import {
|
||||
AbstractMesh, Color3, ISceneLoaderAsyncResult, MeshBuilder, ParticleHelper, ParticleSystem, ParticleSystemSet,
|
||||
PhysicsAggregate,
|
||||
AbstractMesh,
|
||||
Color3, InstancedMesh,
|
||||
Mesh,
|
||||
MeshBuilder, Observable,
|
||||
ParticleHelper,
|
||||
ParticleSystem,
|
||||
ParticleSystemSet,
|
||||
PBRMaterial,
|
||||
PhysicsAggregate, PhysicsBody,
|
||||
PhysicsMotionType,
|
||||
PhysicsShapeType,
|
||||
SceneLoader, StandardMaterial,
|
||||
SceneLoader,
|
||||
Vector3
|
||||
} from "@babylonjs/core";
|
||||
import {DefaultScene} from "./defaultScene";
|
||||
import {ScoreEvent} from "./scoreboard";
|
||||
let _particleData: any = null;
|
||||
|
||||
export class Rock {
|
||||
private _rockMesh: AbstractMesh;
|
||||
constructor(mesh: AbstractMesh) {
|
||||
this._rockMesh = mesh;
|
||||
}
|
||||
public get physicsBody(): PhysicsBody {
|
||||
return this._rockMesh.physicsBody;
|
||||
}
|
||||
public get position(): Vector3 {
|
||||
return this._rockMesh.getAbsolutePosition();
|
||||
}
|
||||
}
|
||||
|
||||
export class RockFactory {
|
||||
private static _rockMesh: AbstractMesh;
|
||||
private static _rockMaterial: StandardMaterial;
|
||||
|
||||
private static _rockMaterial: PBRMaterial;
|
||||
private static _explosion: ParticleSystemSet;
|
||||
public static async init() {
|
||||
|
||||
if (!this._explosion) {
|
||||
const set = await ParticleHelper.CreateAsync("explosion", DefaultScene.MainScene);
|
||||
this._explosion = set.serialize(true);
|
||||
set.dispose();
|
||||
}
|
||||
if (!this._rockMesh) {
|
||||
console.log('loading mesh');
|
||||
const importMesh = await SceneLoader.ImportMeshAsync(null, "./", "asteroid.glb", DefaultScene.MainScene);
|
||||
this._rockMesh = importMesh.meshes[1].clone("asteroid", null, true);
|
||||
const importMesh = await SceneLoader.ImportMeshAsync(null, "./", "asteroid2.glb", DefaultScene.MainScene);
|
||||
this._rockMesh = importMesh.meshes[1].clone("asteroid", null, false);
|
||||
this._rockMesh.setParent(null);
|
||||
this._rockMesh.setEnabled(false);
|
||||
|
||||
//importMesh.meshes[1].dispose();
|
||||
console.log(importMesh.meshes);
|
||||
if (!this._rockMaterial) {
|
||||
this._rockMaterial = this._rockMesh.material.clone("asteroid") as StandardMaterial;
|
||||
this._rockMaterial = this._rockMesh.material.clone("asteroid") as PBRMaterial;
|
||||
this._rockMaterial.name = 'asteroid-material';
|
||||
this._rockMaterial.id = 'asteroid-material';
|
||||
const material = (this._rockMaterial as PBRMaterial)
|
||||
//material.albedoTexture = null;
|
||||
material.ambientColor = new Color3(.4, .4 ,.4);
|
||||
//material.albedoColor = new Color3(1, 1, 1);
|
||||
//material.emissiveColor = new Color3(1, 1, 1);
|
||||
this._rockMesh.material = this._rockMaterial;
|
||||
importMesh.meshes[1].dispose(false, true);
|
||||
importMesh.meshes[0].dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
public static async createRock(i: number, position: Vector3, size: Vector3): Promise<AbstractMesh> {
|
||||
const explosion = await ParticleHelper.CreateAsync("explosion", DefaultScene.MainScene);
|
||||
public static async createRock(i: number, position: Vector3, size: Vector3,
|
||||
score: Observable<ScoreEvent>): Promise<Rock> {
|
||||
|
||||
const rock = this._rockMesh.clone("asteroid-" + i, null, true);
|
||||
const rock = new InstancedMesh("asteroid-" +i, this._rockMesh as Mesh);
|
||||
|
||||
//rock.material.dispose();
|
||||
//rock.material = rockMaterial;
|
||||
rock.scaling = size;
|
||||
rock.position = position;
|
||||
//rock.setParent(null);
|
||||
|
||||
//rock.material = this._rockMaterial;
|
||||
rock.name = "asteroid-" + i;
|
||||
rock.id = "asteroid-" + i;
|
||||
rock.metadata = {type: 'asteroid'};
|
||||
rock.setEnabled(true);
|
||||
const agg = new PhysicsAggregate(rock, PhysicsShapeType.CONVEX_HULL, {mass: 10000, restitution: .0001}, DefaultScene.MainScene);
|
||||
const agg = new PhysicsAggregate(rock, PhysicsShapeType.CONVEX_HULL, {
|
||||
mass: 10000,
|
||||
restitution: .5,
|
||||
}, DefaultScene.MainScene);
|
||||
const body =agg.body;
|
||||
body.setLinearDamping(.001);
|
||||
//body.setAngularDamping(.00001);
|
||||
body.setLinearDamping(0);
|
||||
body.setMotionType(PhysicsMotionType.DYNAMIC);
|
||||
body.setCollisionCallbackEnabled(true);
|
||||
//rock.renderOutline = true;
|
||||
//rock.outlineColor = Color3.Red();
|
||||
//rock.outlineWidth = .02;
|
||||
//rock.showBoundingBox = true;
|
||||
|
||||
//rock.renderOverlay = true;
|
||||
|
||||
body.getCollisionObservable().add((eventData) => {
|
||||
if (eventData.type == 'COLLISION_STARTED') {
|
||||
if ( eventData.collidedAgainst.transformNode.id == 'bullet') {
|
||||
if ( eventData.collidedAgainst.transformNode.id == 'ammo') {
|
||||
score.notifyObservers({score: 1, remaining: -1, message: "Asteroid Destroyed"});
|
||||
const explosion = ParticleSystemSet.Parse(this._explosion, DefaultScene.MainScene, false, 10);
|
||||
const position = eventData.point;
|
||||
// _explosion.emitterNode = position;
|
||||
|
||||
@ -77,11 +103,11 @@ export class RockFactory {
|
||||
|
||||
const ball = MeshBuilder.CreateBox("ball", {size: .01}, DefaultScene.MainScene);
|
||||
|
||||
ball.scaling = new Vector3(.1, .1, .1);
|
||||
ball.scaling = new Vector3(.4, .4, .4);
|
||||
ball.position = position;
|
||||
const material = new StandardMaterial("ball-material", DefaultScene.MainScene);
|
||||
material.emissiveColor = Color3.Yellow();
|
||||
ball.material = material;
|
||||
//const material = new StandardMaterial("ball-material", DefaultScene.MainScene);
|
||||
//material.emissiveColor = Color3.Yellow();
|
||||
//ball.material = material;
|
||||
|
||||
explosion.start(ball);
|
||||
|
||||
@ -95,13 +121,13 @@ export class RockFactory {
|
||||
ball.dispose(false, true);
|
||||
}
|
||||
//ball.dispose();
|
||||
}, 2000);
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
});
|
||||
//body.setAngularVelocity(new Vector3(Math.random(), Math.random(), Math.random()));
|
||||
// body.setLinearVelocity(Vector3.Random(-10, 10));
|
||||
return rock;
|
||||
return new Rock(rock);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user