diff --git a/public/shot.mp3 b/public/shot.mp3 index ff2a012..0af8930 100644 Binary files a/public/shot.mp3 and b/public/shot.mp3 differ diff --git a/public/shot2.mp3 b/public/shot2.mp3 new file mode 100644 index 0000000..ff2a012 Binary files /dev/null and b/public/shot2.mp3 differ diff --git a/public/thrust3.mp3 b/public/thrust3.mp3 new file mode 100644 index 0000000..445f830 Binary files /dev/null and b/public/thrust3.mp3 differ diff --git a/public/thrust4.mp3 b/public/thrust4.mp3 new file mode 100644 index 0000000..eceeb28 Binary files /dev/null and b/public/thrust4.mp3 differ diff --git a/public/thrust5.mp3 b/public/thrust5.mp3 new file mode 100644 index 0000000..011e4e9 Binary files /dev/null and b/public/thrust5.mp3 differ diff --git a/src/level1.ts b/src/level1.ts index ee9374e..c6e4bde 100644 --- a/src/level1.ts +++ b/src/level1.ts @@ -1,143 +1,117 @@ import {DefaultScene} from "./defaultScene"; import { - Color3, - HavokPlugin, - MeshBuilder, Observable, ParticleHelper, ParticleSystem, ParticleSystemSet, + AbstractMesh, + Color3, DistanceConstraint, InstancedMesh, Mesh, + MeshBuilder, + Observable, + ParticleHelper, PhysicsAggregate, PhysicsMotionType, PhysicsShapeType, - StandardMaterial, Texture, + StandardMaterial, TransformNode, Vector3 } from "@babylonjs/core"; import {Ship} from "./ship"; import {ScoreEvent} from "./scoreEvent"; -import {createRock} from "./starfield"; +import {RockFactory} from "./starfield"; export class Level1 { private _ship: Ship; - private _explosion: ParticleSystemSet - + private _initialized: boolean = false; + private _startBase: AbstractMesh; + private _endBase: AbstractMesh; public onScoreObservable: Observable = new Observable(); + constructor(ship: Ship) { this._ship = ship; - this.initialize(); + this.createStartBase(); + this.createEndBase(); } + private scored: Set = new Set(); - private async initialize() { - const phys = DefaultScene.MainScene.getPhysicsEngine().getPhysicsPlugin() as HavokPlugin; + + public async initialize() { + if (this._initialized) { + return; + } + this._initialized = true; ParticleHelper.BaseAssetsUrl = window.location.href; + this._ship.position = new Vector3(0, 1, 0); - //console.log(window.location.href); - DefaultScene.MainScene.onReadyObservable.addOnce(async () => { - this._explosion = await ParticleHelper.CreateAsync("explosion", DefaultScene.MainScene); - }); - // - /*phys.onTriggerCollisionObservable.add((eventData) => { - if (eventData.collider.transformNode.id.indexOf('star') > -1) { - return; - } - if (this.scored.has(eventData.collidedAgainst.transformNode.id)) { - return; - } else { - this.scored.add(eventData.collidedAgainst.transformNode.id); - //this.onScoreObservable.notifyObservers(1); - } + await RockFactory.init(); + const distance = Vector3.Distance(this._startBase.getAbsolutePosition(), this._endBase.getAbsolutePosition()); + const baseTransform = new TransformNode("baseTransform", DefaultScene.MainScene); + baseTransform.position = this._endBase.getAbsolutePosition(); - }); - */ - phys.onCollisionObservable.add( (eventData) => { - this.onScoreObservable.notifyObservers({score: 0, message: eventData?.impulse?.toFixed(2)}); - if ((eventData.collidedAgainst.transformNode.id == 'bullet' || - eventData.collider.transformNode.id == 'bullet') && - (eventData.collidedAgainst.transformNode.id.indexOf('asteroid') > -1 || - eventData.collider.transformNode.id.indexOf('asteroid') > -1) - ){ - const point = eventData.point.clone(); - if (this._explosion) { - /*this._explosion.systems.forEach((system) => { - system.stop(); - });*/ - this._explosion.emitterNode = point; - this._explosion.start(); - } - - eventData.collider.transformNode.dispose(); - eventData.collidedAgainst.transformNode.dispose() - - eventData.collider.dispose(); - eventData.collidedAgainst.dispose(); + for (let i = 0; i < 20; i++) { + //const constraintDistance = distance - 20; + const dist = (Math.random() * 80) + 20; + const startPos = this._endBase.getAbsolutePosition().add(new Vector3(dist,dist,dist)); + const startTrans = new TransformNode("startTransform", DefaultScene.MainScene); + startTrans.position = startPos; + startTrans.setParent(baseTransform); + baseTransform.rotation = Vector3.Random(0, Math.PI * 2); + const rock = await RockFactory.createRock(i, startTrans.getAbsolutePosition(), Vector3.Random(1, 5)) + startTrans.dispose(); - /*const myParticleSystem = new ParticleSystem("particles", 1000, DefaultScene.MainScene); - myParticleSystem.emitter = point; - myParticleSystem.emitRate = 100; - myParticleSystem.minEmitPower = 2; - myParticleSystem.maxEmitPower = 200; - const sphereEmitter = myParticleSystem.createSphereEmitter(10); - myParticleSystem.particleTexture = new Texture("./flare.png"); - myParticleSystem.maxLifeTime = 10000; - //const coneEmitter = myParticleSystem.createConeEmitter(0.1, Math.PI / 9); - myParticleSystem.addSizeGradient(0, 2); - myParticleSystem.addSizeGradient(1, 4); - //myParticleSystem.isLocal = true; - myParticleSystem.start(); //S - console.log(eventData);*/ - } + const constraint = new DistanceConstraint(dist, DefaultScene.MainScene); + rock.physicsBody.addConstraint(this._endBase.physicsBody, constraint); + rock.physicsBody.applyImpulse(Vector3.Random(-1, 1).scale(1000), rock.getAbsolutePosition()); + rock.physicsBody.setAngularVelocity(Vector3.Random(-.5, .5)); + /* const material = new StandardMaterial("material", DefaultScene.MainScene); + material.emissiveColor = Color3.Random(); + const sphere = MeshBuilder.CreateSphere("sphere", {diameter: 1}, DefaultScene.MainScene); + sphere.material = material; - }); - this._ship.onReadyObservable.add(() => { - this._ship.position = new Vector3(0, 1, 0); - this.createStartBase(); - this.createEndBase(); + window.setInterval(() => { + const track = new InstancedMesh("track", sphere); + track.position = rock.physicsBody.transformNode.getAbsolutePosition(); - createRock(1, new Vector3(0,0, 70), new Vector3(10,10,10)); - createRock(1, new Vector3(0,0, 100), new Vector3(10,10,10)); - createRock(1, new Vector3(0,0, 130), new Vector3(10,10,10)); - for (let i = 0; i < 100; i++) { - createRock(i , Vector3.Random(-200, 200), Vector3.Random(5,20)) - .then((rock) => { - rock.physicsBody.setAngularVelocity(Vector3.Random(-1, 1)); - }); + }, 200); - } - - }); + */ + } } + private createStartBase() { - const mesh = MeshBuilder.CreateCylinder("startBase", {diameter: 10, height: 1, tessellation: 72}, DefaultScene.MainScene); + const mesh = MeshBuilder.CreateCylinder("startBase", { + diameter: 10, + height: 1, + tessellation: 72 + }, DefaultScene.MainScene); const material = new StandardMaterial("material", DefaultScene.MainScene); material.diffuseColor = new Color3(1, 1, 0); mesh.material = material; const agg = new PhysicsAggregate(mesh, PhysicsShapeType.CONVEX_HULL, {mass: 0}, DefaultScene.MainScene); agg.body.setMotionType(PhysicsMotionType.ANIMATED); - + this._startBase = mesh; } + private createEndBase() { - const mesh = MeshBuilder.CreateCylinder("endBase", {diameter: 10, height: 1, tessellation: 72}, DefaultScene.MainScene); + const mesh = MeshBuilder.CreateCylinder("endBase", { + diameter: 10, + height: 1, + tessellation: 72 + }, DefaultScene.MainScene); mesh.position = new Vector3(0, 5, 200); const material = new StandardMaterial("material", DefaultScene.MainScene); material.diffuseColor = new Color3(0, 1, 0); mesh.material = material; const agg = new PhysicsAggregate(mesh, PhysicsShapeType.CONVEX_HULL, {mass: 0}, DefaultScene.MainScene); agg.body.setMotionType(PhysicsMotionType.ANIMATED); - /*agg.body.setCollisionCallbackEnabled(true); - const collider = agg.body.getCollisionObservable().add((eventData) => { - if (eventData.collidedAgainst.transformNode.id == 'ship') { - console.log(eventData); - this.onScoreObservable.notifyObservers({score: 0, - message: eventData?.impulse?.toFixed(2)}) - - } - }); */ - + this._endBase = mesh; } + private createTarget(i: number) { const target = MeshBuilder.CreateTorus("target" + i, {diameter: 10, tessellation: 72}, DefaultScene.MainScene); - - const targetLOD = MeshBuilder.CreateTorus("target" + i, {diameter: 50, tessellation: 10}, DefaultScene.MainScene); + const targetLOD = MeshBuilder.CreateTorus("target" + i, { + diameter: 50, + tessellation: 10 + }, DefaultScene.MainScene); targetLOD.parent = target; target.addLODLevel(300, targetLOD); @@ -146,27 +120,17 @@ export class Level1 { material.alpha = .9; target.material = material; target.position = Vector3.Random(-1000, 1000); - target.rotation = Vector3.Random(0, Math.PI*2); - const disc = MeshBuilder.CreateDisc("disc-"+i, {radius: 2, tessellation: 72}, DefaultScene.MainScene); + target.rotation = Vector3.Random(0, Math.PI * 2); + const disc = MeshBuilder.CreateDisc("disc-" + i, {radius: 2, tessellation: 72}, DefaultScene.MainScene); const discMaterial = new StandardMaterial("material", DefaultScene.MainScene); discMaterial.ambientColor = new Color3(.1, 1, .1); discMaterial.alpha = .2; target.addLODLevel(200, null); disc.material = discMaterial; disc.parent = target; - disc.rotation.x = -Math.PI/2; + disc.rotation.x = -Math.PI / 2; const agg = new PhysicsAggregate(disc, PhysicsShapeType.MESH, {mass: 0}, DefaultScene.MainScene); agg.body.setMotionType(PhysicsMotionType.STATIC); agg.shape.isTrigger = true; - //agg.shape.filterCollideMask = 2; - //agg.body.dispose(); - - //const body = new PhysicsShapeMesh(disc, DefaultScene.MainScene); - - //agg.body.setCollisionCallbackEnabled(true); - /*agg.body.getCollisionObservable().add((eventData) => { - target.dispose(false, false); - agg.dispose(); - });*/ } } \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 5057e90..501c861 100644 --- a/src/main.ts +++ b/src/main.ts @@ -28,13 +28,11 @@ export class Main { disableDefaultUI: true, }); - //const sun = createSun(); const ship = new Ship(); const scoreboard = new Scoreboard(); const level = new Level1(ship); const photoDome = new PhotoDome("testdome", '/8192.webp', {}, DefaultScene.MainScene); - //starfield(sun); - //starfield(sun); + xr.baseExperience.onInitialXRPoseSetObservable.add(() => { @@ -63,7 +61,6 @@ export class Main { engine = new Engine(canvas, true); } engine.setHardwareScalingLevel(1 / window.devicePixelRatio); - //Engine.audioEngine.useCustomUnlockedButton = true; window.onresize = () => { engine.resize(); } diff --git a/src/radar.ts b/src/radar.ts index 86714d0..1513e13 100644 --- a/src/radar.ts +++ b/src/radar.ts @@ -47,9 +47,12 @@ export class Radar { this._arrowMesh.material = material; window.setInterval(() => { const point = scene.getMeshById('endBase'); - point.computeWorldMatrix(true) - this._arrowMesh.position = this._radarTransform.absolutePosition; - this._arrowMesh.lookAt(point.absolutePosition); + if (point) { + point.computeWorldMatrix(true) + this._arrowMesh.position = this._radarTransform.absolutePosition; + this._arrowMesh.lookAt(point.absolutePosition); + } + }, 100); // arrow[0].parent = this._radarTransform; diff --git a/src/scoreboard.ts b/src/scoreboard.ts index 8b22951..9d29600 100644 --- a/src/scoreboard.ts +++ b/src/scoreboard.ts @@ -34,17 +34,13 @@ export class Scoreboard { const parent = scene.getMeshById('RightUpperDisplay'); const scoreboard = MeshBuilder.CreatePlane("scoreboard", {width: 1, height: 1}, scene); scoreboard.parent =parent; - //DefaultScene.MainScene.onBeforeDrawPhaseObservable.add(() => { - //}); - //scoreboard.parent = camera; scoreboard.position.x = -.76; scoreboard.position.y = 4.19; scoreboard.position.z = .53; - scoreboard.rotation.x = Angle.FromDegrees(108).radians(); + scoreboard.rotation.x = Angle.FromDegrees(104).radians(); scoreboard.rotation.z = Math.PI; - scoreboard.scaling = new Vector3(.5, .5, .5); - //scoreboard.position = camera.getFrontPosition(1); + scoreboard.scaling = new Vector3(.3, .3, .3); const advancedTexture = AdvancedDynamicTexture.CreateForMesh(scoreboard); advancedTexture.background = "black"; @@ -52,6 +48,9 @@ export class Scoreboard { advancedTexture.addControl(scoreText); const fpsText = this.createText(); fpsText.top = '120px'; + const hullText = this.createText(); + //hullText.top = '240px'; + hullText.text = 'Hull: 100%'; const panel = new StackPanel(); panel.isVertical = true; advancedTexture.addControl(fpsText); diff --git a/src/ship.ts b/src/ship.ts index 89e4f66..8a8a2fc 100644 --- a/src/ship.ts +++ b/src/ship.ts @@ -1,15 +1,19 @@ import { - AbstractMesh, Color3, - DirectionalLight, Engine, - - FreeCamera, GlowLayer, - Matrix, MeshBuilder, + AbstractMesh, + Color3, + DirectionalLight, + Engine, + FreeCamera, + GlowLayer, + MeshBuilder, Observable, PhysicsAggregate, PhysicsMotionType, PhysicsShapeType, - SceneLoader, Sound, - SpotLight, StandardMaterial, + SceneLoader, + Sound, + SpotLight, + StandardMaterial, TransformNode, Vector2, Vector3, @@ -20,7 +24,7 @@ import { import {DefaultScene} from "./defaultScene"; import {Radar} from "./radar"; import {ShipEngine} from "./shipEngine"; -import {Mirror} from "./mirror"; +import {Level1} from "./level1"; const controllerComponents = [ 'a-button', @@ -54,7 +58,7 @@ export class Ship { private _controllerObservable: Observable = new Observable(); public onReadyObservable: Observable = new Observable(); private _engine: ShipEngine; - + private _ammoMaterial: StandardMaterial; private _forwardNode: TransformNode; private _rotationNode: TransformNode; private _onscore: Observable; @@ -64,32 +68,53 @@ export class Ship { private _thrust2: Sound; private _shot: Sound; private _shooting: boolean = false; + private _camera: FreeCamera; + constructor() { this._ship = new TransformNode("ship", DefaultScene.MainScene); this._glowLayer = new GlowLayer('bullets', DefaultScene.MainScene); this._glowLayer.intensity = 1; - this._thrust = new Sound("thrust", "/thrust.mp3", DefaultScene.MainScene, null, {loop: true, autoplay: false}); - this._thrust2 = new Sound("thrust2", "/thrust2.mp3", DefaultScene.MainScene, null, {loop: true, autoplay: false}); + this._thrust = new Sound("thrust", "/thrust5.mp3", DefaultScene.MainScene, null, { + loop: true, + autoplay: false + }); + this._thrust2 = new Sound("thrust2", "/thrust5.mp3", DefaultScene.MainScene, null, { + loop: true, + autoplay: false, + volume: .5 + }); this._shot = new Sound("shot", "/shot.mp3", DefaultScene.MainScene, null, - {loop: false, autoplay: false}); + {loop: false, autoplay: false, volume: .5}); + this._ammoMaterial = new StandardMaterial("ammoMaterial", DefaultScene.MainScene); + this._ammoMaterial.emissiveColor = new Color3(1, 1, 0); this.initialize(); } + private shoot() { - const ammo = MeshBuilder.CreateCapsule("bullet", { radius: .05, height: 1.5}, DefaultScene.MainScene); - ammo.parent = this._ship - ammo.position.y =2; - ammo.rotation.x = Math.PI / 2; - ammo.setParent(null); - const ammoAggregate = new PhysicsAggregate(ammo, PhysicsShapeType.CONVEX_HULL, {mass: 1}, DefaultScene.MainScene); - const material = new StandardMaterial("ammoMaterial", DefaultScene.MainScene); - material.emissiveColor = new Color3(1,1,0); - ammo.material = material; - ammoAggregate.body.setMotionType(PhysicsMotionType.DYNAMIC); - ammoAggregate.body.setLinearVelocity(this._ship.forward.scale(100).add(this._ship.physicsBody.getLinearVelocity())); - this._shot.play(); - window.setTimeout(() =>{ ammoAggregate.dispose(); ammo.dispose()}, 5000) + this._shot.play(); + const ammo = MeshBuilder.CreateCapsule("bullet", {radius: .05, height: 1.5}, DefaultScene.MainScene); + ammo.parent = this._ship + ammo.position.y = 2; + ammo.rotation.x = Math.PI / 2; + ammo.setParent(null); + const ammoAggregate = new PhysicsAggregate(ammo, PhysicsShapeType.CONVEX_HULL, { + mass: 1000, + restitution: 0 + }, DefaultScene.MainScene); + + + ammo.material = this._ammoMaterial; + ammoAggregate.body.setMotionType(PhysicsMotionType.DYNAMIC); + + ammoAggregate.body.setLinearVelocity(this._ship.forward.scale(150).add(this._ship.physicsBody.getLinearVelocity())); + + window.setTimeout(() => { + ammoAggregate.dispose(); + ammo.dispose() + }, 5000) } + public set position(newPosition: Vector3) { const body = this._ship.physicsBody; body.disablePreStep = false; @@ -103,70 +128,35 @@ export class Ship { private async initialize() { const light = new DirectionalLight("light", new Vector3(.1, -1, 0), DefaultScene.MainScene); const ship = this._ship; - const landingLight = new SpotLight("landingLight", new Vector3(0,0,0), new Vector3(0, -.5, .5),1.5, .5, DefaultScene.MainScene); + const landingLight = new SpotLight("landingLight", new Vector3(0, 0, 0), new Vector3(0, -.5, .5), 1.5, .5, DefaultScene.MainScene); landingLight.parent = ship; landingLight.position.z = 5; - - //const lightCode = MeshBuilder.CreateCylinder("lightCode", {diameterBottom: 0, diameterTop: .5, height: 1}, DefaultScene.MainScene); - //lightCode.parent = ship; - //lightCode.position.z = 5; - //this._engine = new ShipEngine(ship); - //ship.position = new Vector3(0, 0, -1000); - //const landingLight = new DirectionalLight("landingLight", new Vector3(0, -1, 0), DefaultScene.MainScene); - //landingLight.parent = ship; const importMesh = await SceneLoader.ImportMeshAsync(null, "./", "cockpit3.glb", DefaultScene.MainScene); const shipMesh = importMesh.meshes[0]; shipMesh.id = "shipMesh"; shipMesh.name = "shipMesh"; shipMesh.parent = ship; - shipMesh.rotation.y = Math.PI; shipMesh.position.y = 1; shipMesh.position.z = -1; DefaultScene.MainScene.getMaterialById('glass_mat.002').alpha = .7; - - const camera = new FreeCamera("Flat Camera", - new Vector3(0, 0, -10), + this._camera = new FreeCamera("Flat Camera", + new Vector3(0, .5, 0), DefaultScene.MainScene); - camera.parent = ship; - camera.position.y = .5; - camera.position.z = 0; + this._camera.parent = ship; - - - - //right.attachToMesh(rightTransform); - - - //camera.rotation.x = -Math.PI / 2; - const body = new PhysicsAggregate(ship, PhysicsShapeType.BOX, { + const agg = new PhysicsAggregate(ship, PhysicsShapeType.BOX, { mass: 100, - extents: new Vector3(5, 2, 5) + extents: new Vector3(4, 4, 7.4), + center: new Vector3(0, 1, 1.8) }, DefaultScene.MainScene); - body.body.setMotionType(PhysicsMotionType.DYNAMIC); - body.body.setLinearDamping(.1); - body.body.setAngularDamping(.2); - body.body.setAngularVelocity(new Vector3(0, 0, 0)); - body.body.setCollisionCallbackEnabled(true) - //body.shape.filterCollideMask = 1; - /*const sight = MeshBuilder.CreateDisc("sight", { - radius: .1, - sideOrientation: Mesh.DOUBLESIDE - }, DefaultScene.MainScene); - const sightMaterial = new StandardMaterial("sightMaterial", DefaultScene.MainScene); - sightMaterial.ambientColor = new Color3(1, 1, 1); - sightMaterial.alpha = .5; - sight.material = sightMaterial; - sight.parent = ship; - sight.rotation.x = Math.PI; - sight.position.z = 10; - const line = MeshBuilder.CreateLines("line", {points: [Vector3.Zero(), new Vector3(0, 0, 10)]}, DefaultScene.MainScene); - line.parent = ship; - line.material = sightMaterial; */ + agg.body.setMotionType(PhysicsMotionType.DYNAMIC); + agg.body.setLinearDamping(.1); + agg.body.setAngularDamping(.2); + agg.body.setAngularVelocity(new Vector3(0, 0, 0)); + agg.body.setCollisionCallbackEnabled(true) DefaultScene.MainScene.setActiveCameraByName("Flat Camera"); - - this.setupKeyboard(); this.setupMouse(); this._controllerObservable.add(this.controllerCallback); @@ -174,8 +164,13 @@ export class Ship { this._rotationNode = new TransformNode("rotation", DefaultScene.MainScene); this._forwardNode.parent = this._ship; this._rotationNode.parent = this._ship; - - //const radar = new Radar(this._ship); + //const sightPos = this._forwardNode.position.scale(30); + const sight = MeshBuilder.CreateSphere("sight", {diameter: 1}, DefaultScene.MainScene); + sight.parent = this._ship + const signtMaterial = new StandardMaterial("sightMaterial", DefaultScene.MainScene); + signtMaterial.emissiveColor = Color3.Yellow(); + sight.material = signtMaterial; + sight.position = new Vector3(0, 2, 125); window.setInterval(() => { this.applyForce(); }, 50); @@ -184,20 +179,25 @@ export class Ship { const radar = new Radar(this._ship); document.querySelector('#loadingDiv').remove(); - const startButton = document.querySelector('#startButton'); - startButton.classList.add('ready'); - + //const startButton = document.querySelector('#startButton'); + //startButton.classList.add('ready'); + const level = new Level1(this); const background = new Sound("background", "/background.mp3", DefaultScene.MainScene, () => { const startButton = document.querySelector('#startButton'); startButton.classList.add('ready'); - startButton.addEventListener('click', () => { - Engine.audioEngine.unlock(); - background.play(); - DefaultScene.XR.baseExperience.enterXRAsync('immersive-vr', 'local-floor'); + startButton.addEventListener('click', async () => { + if (!Engine.audioEngine.unlocked) { + Engine.audioEngine.unlock(); + } + console.log('start background'); + await DefaultScene.XR.baseExperience.enterXRAsync('immersive-vr', 'local-floor'); + await level.initialize(); }); - }, {loop: true, autoplay: false, volume: .1}); + }, {loop: true, autoplay: true, volume: .2}); + } + private _leftStickVector = Vector2.Zero().clone(); private _rightStickVector = Vector2.Zero().clone(); private _forwardValue = 0; @@ -292,6 +292,7 @@ export class Ship { body.setLinearVelocity(this._forwardNode.absolutePosition.subtract(this._ship.absolutePosition).scale(-1)); //this._engine.forwardback(this._forwardValue); } + private controllerCallback = (controllerEvent: ControllerEvent) => { if (controllerEvent.type == 'thumbstick') { if (controllerEvent.hand == 'left') { @@ -318,6 +319,7 @@ export class Ship { } } } + private setupMouse() { this._ship.getScene().onPointerDown = (evt) => { this._mousePos.x = evt.x; @@ -332,48 +334,62 @@ export class Ship { }; this._ship.getScene().onPointerMove = (ev) => { - if (!this._mouseDown) {return}; - const xInc = this._rightStickVector.x = (ev.x - this._mousePos.x) / 100; - const yInc = this._rightStickVector.y = (ev.y - this._mousePos.y) / 100; - if (Math.abs(xInc) <= 1) { - this._rightStickVector.x = xInc; - } else { - this._rightStickVector.x = Math.sign(xInc); - } - if (Math.abs(yInc) <= 1) { - this._rightStickVector.y = yInc; - } else { - this._rightStickVector.y = Math.sign(yInc); - } + if (!this._mouseDown) { + return + } + ; + const xInc = this._rightStickVector.x = (ev.x - this._mousePos.x) / 100; + const yInc = this._rightStickVector.y = (ev.y - this._mousePos.y) / 100; + if (Math.abs(xInc) <= 1) { + this._rightStickVector.x = xInc; + } else { + this._rightStickVector.x = Math.sign(xInc); + } + if (Math.abs(yInc) <= 1) { + this._rightStickVector.y = yInc; + } else { + this._rightStickVector.y = Math.sign(yInc); + } }; } + private setupKeyboard() { + document.onkeyup = () => { + this._leftStickVector.y = 0; + this._leftStickVector.x = 0; + this._rightStickVector.y = 0; + this._rightStickVector.x = 0; + } document.onkeydown = (ev) => { switch (ev.key) { + case '1': + this._camera.position.x = 15; + this._camera.rotation.y = -Math.PI / 2; + console.log(1); + break; case ' ': this.shoot(); break; case 'e': - break; case 'w': - this._leftStickVector.y =-1; + this._leftStickVector.y = -1; break; case 's': - this._leftStickVector.y =1; + this._leftStickVector.y = 1; break; case 'a': - this._leftStickVector.x =-1; + this._leftStickVector.x = -1; break; case 'd': - this._leftStickVector.x =1; + this._leftStickVector.x = 1; break; case 'ArrowUp': - + this._rightStickVector.y = -1; break; case 'ArrowDown': - + this._rightStickVector.y = 1; break; } diff --git a/src/starfield.ts b/src/starfield.ts index 90245a4..e57f794 100644 --- a/src/starfield.ts +++ b/src/starfield.ts @@ -1,30 +1,107 @@ import { - AbstractMesh, + AbstractMesh, Color3, ISceneLoaderAsyncResult, MeshBuilder, ParticleHelper, ParticleSystem, ParticleSystemSet, PhysicsAggregate, PhysicsMotionType, PhysicsShapeType, - SceneLoader, + SceneLoader, StandardMaterial, Vector3 } from "@babylonjs/core"; import {DefaultScene} from "./defaultScene"; +let _particleData: any = null; -export async function createRock(i: number, position: Vector3, size: Vector3): Promise { - const importMesh = await SceneLoader.ImportMeshAsync(null, "./", "asteroid.glb", DefaultScene.MainScene); - const rock = importMesh.meshes[1]; - rock.scaling = size; - rock.position = position; - rock.setParent(null); - importMesh.meshes[0].dispose(); - rock.name = "asteroid-" + i; - rock.id = "asteroid-" + i; - const agg = new PhysicsAggregate(rock, PhysicsShapeType.CONVEX_HULL, {mass: 10000}, DefaultScene.MainScene); - const body =agg.body; - body.setLinearDamping(.001); - body.setAngularDamping(.00001); - body.setMotionType(PhysicsMotionType.DYNAMIC); - body.setCollisionCallbackEnabled(true); - //body.setAngularVelocity(new Vector3(Math.random(), Math.random(), Math.random())); - // body.setLinearVelocity(Vector3.Random(-10, 10)); - return rock; +export class RockFactory { + private static _rockMesh: AbstractMesh; + private static _rockMaterial: StandardMaterial; + + public static async init() { + 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); + 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.name = 'asteroid-material'; + this._rockMaterial.id = 'asteroid-material'; + importMesh.meshes[1].dispose(false, true); + importMesh.meshes[0].dispose(); + } + } + } + public static async createRock(i: number, position: Vector3, size: Vector3): Promise { + const explosion = await ParticleHelper.CreateAsync("explosion", DefaultScene.MainScene); + + const rock = this._rockMesh.clone("asteroid-" + i, null, true); + + //rock.material.dispose(); + //rock.material = rockMaterial; + rock.scaling = size; + rock.position = position; + //rock.setParent(null); + + 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 body =agg.body; + body.setLinearDamping(.001); + //body.setAngularDamping(.00001); + 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') { + const position = eventData.point; + // _explosion.emitterNode = position; + + eventData.collider.shape.dispose(); + eventData.collider.transformNode.dispose(); + eventData.collider.dispose(); + + eventData.collidedAgainst.shape.dispose(); + eventData.collidedAgainst.transformNode.dispose(); + eventData.collidedAgainst.dispose(); + + const ball = MeshBuilder.CreateBox("ball", {size: .01}, DefaultScene.MainScene); + + ball.scaling = new Vector3(.1, .1, .1); + ball.position = position; + const material = new StandardMaterial("ball-material", DefaultScene.MainScene); + material.emissiveColor = Color3.Yellow(); + ball.material = material; + + explosion.start(ball); + + setTimeout(() => { + explosion.systems.forEach((system: ParticleSystem) => { + system.stop(); + system.dispose(true, true, true); + }); + explosion.dispose(); + if (ball && !ball.isDisposed()) { + ball.dispose(false, true); + } + //ball.dispose(); + }, 2000); + } + } + }); + //body.setAngularVelocity(new Vector3(Math.random(), Math.random(), Math.random())); + // body.setLinearVelocity(Vector3.Random(-10, 10)); + return rock; + } } +