changed game dynamics.

This commit is contained in:
Michael Mainguy 2025-02-20 19:11:46 -06:00
parent 5b7d04bd39
commit c9d03e832d
5 changed files with 258 additions and 156 deletions

View File

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

View File

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

View File

@ -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() {

View File

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

View File

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