From f8c0d21db3c9b2df5b62ffe76793f8fc7ff060b1 Mon Sep 17 00:00:00 2001 From: Ancient Pixel Date: Fri, 23 Oct 2026 00:24:27 +0200 Subject: [PATCH] added src --- src/3d/cam.js | 214 ++ src/3d/character.js | 36 + src/3d/dataQuad.js | 801 ++++++ src/3d/editor.js | 530 ++++ src/3d/geometryController.js | 174 ++ src/3d/groups/grpElevator.js | 145 ++ src/3d/levels/___lvlEmpty.js | 18 + src/3d/levels/lvlChurch00.js | 244 ++ src/3d/levels/lvlChurch00old.js | 364 +++ src/3d/levels/lvlDream00.js | 844 ++++++ src/3d/levels/lvlHangar00.js | 684 +++++ src/3d/levels/lvlHangar01.js | 492 ++++ src/3d/levels/lvlMarketsquareApartements00.js | 525 ++++ src/3d/levels/lvlMenu3d.js | 478 ++++ src/3d/levels/lvlModelbuilder.js | 261 ++ src/3d/levels/lvlPlayerApartement00.js | 267 ++ src/3d/levels/lvlQuadRingsTest.js | 2292 +++++++++++++++++ src/3d/levels/lvlRaceDirectorOffice00.js | 81 + src/3d/model.js | 1012 ++++++++ src/3d/player3d.js | 690 +++++ src/3d/player6dof.js | 1349 ++++++++++ src/3d/playerEuler.js | 742 ++++++ src/3d/racing/shipManager.js | 2048 +++++++++++++++ src/3d/racing/shipManagerBackup.js | 1663 ++++++++++++ src/3d/racing/trackBuilder.js | 2145 +++++++++++++++ src/3d/transform.js | 126 + src/additionalMath/euclidianDistance.js | 18 + src/additionalMath/gl_mat3.js | 496 ++++ src/additionalMath/gl_quat.js | 445 ++++ src/additionalMath/gl_rvaa.js | 343 +++ src/additionalMath/gl_vec3.js | 702 +++++ src/additionalMath/gl_vec4.js | 420 +++ src/additionalMath/pointInPolygon.js | 22 + src/additionalMath/rayTriangleIntersection.js | 119 + src/character.js | 6 + src/flagManager.js | 32 + src/hand.js | 210 ++ src/inputs.js | 60 + src/librarySounds.js | 65 + src/preloader.js | 36 + src/racingSounds.js | 212 ++ src/scn3d.js | 2042 +++++++++++++++ src/scnLoad.js | 311 +++ src/scnMain.js | 73 + src/scnMainMenu.js | 100 + src/scnSavegameCheck.js | 87 + src/soundManager.js | 449 ++++ src/ui/button.js | 219 ++ .../computer/programs/programCalendarAero.js | 115 + .../computer/programs/programMessengerAero.js | 22 + .../programs/programRegulationsAero.js | 152 ++ src/ui/computer/programs/programSystemAero.js | 236 ++ src/ui/computer/windowAero.js | 135 + src/ui/conversationManager.js | 539 ++++ src/ui/conversationOption.js | 116 + src/ui/movingGrid.js | 87 + src/ui/panelElevator.js | 225 ++ src/ui/panelElevatorMaster.js | 185 ++ src/ui/panelEndOfCanyon.js | 169 ++ src/ui/panelEndOfRace.js | 144 ++ src/ui/panelEnterShip.js | 108 + src/ui/panelEnterShipDemo00.js | 190 ++ src/ui/panelEscapeMenu.js | 400 +++ src/ui/panelFlavourText.js | 59 + src/ui/panelIntro.js | 240 ++ src/ui/panelInventory.js | 160 ++ src/ui/panelJoeComputer.js | 207 ++ src/ui/panelLevelname.js | 57 + src/ui/panelLoungeRoundtable00.js | 72 + src/ui/panelPainting.js | 48 + src/ui/panelPlayerComputer.js | 250 ++ src/ui/panelRaceTutorial.js | 174 ++ src/ui/panelStopTrain.js | 134 + src/ui/panelTunnelMainMenu.js | 369 +++ src/ui/panelTunnelOptions.js | 298 +++ src/ui/panelTunnelSelector.js | 310 +++ src/ui/panelTunnelTrackSelection.js | 408 +++ src/ui/panelWakeUp.js | 74 + src/ui/panelWelcome.js | 55 + src/ui/racing/times.js | 5 + src/ui/racing/ui.js | 527 ++++ src/ui/slider.js | 412 +++ 82 files changed, 31374 insertions(+) create mode 100755 src/3d/cam.js create mode 100755 src/3d/character.js create mode 100755 src/3d/dataQuad.js create mode 100755 src/3d/editor.js create mode 100755 src/3d/geometryController.js create mode 100644 src/3d/groups/grpElevator.js create mode 100755 src/3d/levels/___lvlEmpty.js create mode 100644 src/3d/levels/lvlChurch00.js create mode 100644 src/3d/levels/lvlChurch00old.js create mode 100755 src/3d/levels/lvlDream00.js create mode 100755 src/3d/levels/lvlHangar00.js create mode 100755 src/3d/levels/lvlHangar01.js create mode 100755 src/3d/levels/lvlMarketsquareApartements00.js create mode 100644 src/3d/levels/lvlMenu3d.js create mode 100755 src/3d/levels/lvlModelbuilder.js create mode 100755 src/3d/levels/lvlPlayerApartement00.js create mode 100755 src/3d/levels/lvlQuadRingsTest.js create mode 100755 src/3d/levels/lvlRaceDirectorOffice00.js create mode 100755 src/3d/model.js create mode 100755 src/3d/player3d.js create mode 100755 src/3d/player6dof.js create mode 100755 src/3d/playerEuler.js create mode 100644 src/3d/racing/shipManager.js create mode 100644 src/3d/racing/shipManagerBackup.js create mode 100644 src/3d/racing/trackBuilder.js create mode 100644 src/3d/transform.js create mode 100755 src/additionalMath/euclidianDistance.js create mode 100644 src/additionalMath/gl_mat3.js create mode 100644 src/additionalMath/gl_quat.js create mode 100644 src/additionalMath/gl_rvaa.js create mode 100644 src/additionalMath/gl_vec3.js create mode 100644 src/additionalMath/gl_vec4.js create mode 100755 src/additionalMath/pointInPolygon.js create mode 100755 src/additionalMath/rayTriangleIntersection.js create mode 100644 src/character.js create mode 100755 src/flagManager.js create mode 100755 src/hand.js create mode 100755 src/inputs.js create mode 100755 src/librarySounds.js create mode 100755 src/preloader.js create mode 100755 src/racingSounds.js create mode 100755 src/scn3d.js create mode 100755 src/scnLoad.js create mode 100755 src/scnMain.js create mode 100755 src/scnMainMenu.js create mode 100755 src/scnSavegameCheck.js create mode 100644 src/soundManager.js create mode 100755 src/ui/button.js create mode 100644 src/ui/computer/programs/programCalendarAero.js create mode 100644 src/ui/computer/programs/programMessengerAero.js create mode 100644 src/ui/computer/programs/programRegulationsAero.js create mode 100644 src/ui/computer/programs/programSystemAero.js create mode 100644 src/ui/computer/windowAero.js create mode 100755 src/ui/conversationManager.js create mode 100755 src/ui/conversationOption.js create mode 100755 src/ui/movingGrid.js create mode 100755 src/ui/panelElevator.js create mode 100755 src/ui/panelElevatorMaster.js create mode 100755 src/ui/panelEndOfCanyon.js create mode 100755 src/ui/panelEndOfRace.js create mode 100755 src/ui/panelEnterShip.js create mode 100755 src/ui/panelEnterShipDemo00.js create mode 100755 src/ui/panelEscapeMenu.js create mode 100755 src/ui/panelFlavourText.js create mode 100755 src/ui/panelIntro.js create mode 100755 src/ui/panelInventory.js create mode 100755 src/ui/panelJoeComputer.js create mode 100755 src/ui/panelLevelname.js create mode 100755 src/ui/panelLoungeRoundtable00.js create mode 100755 src/ui/panelPainting.js create mode 100755 src/ui/panelPlayerComputer.js create mode 100755 src/ui/panelRaceTutorial.js create mode 100755 src/ui/panelStopTrain.js create mode 100755 src/ui/panelTunnelMainMenu.js create mode 100755 src/ui/panelTunnelOptions.js create mode 100755 src/ui/panelTunnelSelector.js create mode 100755 src/ui/panelTunnelTrackSelection.js create mode 100755 src/ui/panelWakeUp.js create mode 100755 src/ui/panelWelcome.js create mode 100644 src/ui/racing/times.js create mode 100644 src/ui/racing/ui.js create mode 100755 src/ui/slider.js diff --git a/src/3d/cam.js b/src/3d/cam.js new file mode 100755 index 0000000..a67a034 --- /dev/null +++ b/src/3d/cam.js @@ -0,0 +1,214 @@ +import Transform from "./transform.js"; + +export default class Cam{ + constructor(_scene){ + this.scene = _scene; + this.pos = { + x: 0, + y: -24, + z: 0 + } + this.dir = { + yaw: 0, + pitch: 0, + roll: 0, + spd: { + yaw: 0.04, + pitch: 0.04, + roll: 0.04 + } + } + this.zoom = 800; //original: 800 + this.zOffset = 15; //original: 15 + this.fov = 2.5; //original: 2.5 + this.shadeMod = 0.04; //0.04;// 0.125 + this.shadeModTarget = 0.04; + + this.transform = new Transform(); + + /* + this.zoomTween = this.scene.tweens.add({ + targets: this, + zoom: 0.0001, + // x: '+=1', + // x: '-=1', + // x: '*=1', + // x: '/=1', + // x: 'random(0.25, 0.75)', + // x: 'int(10, 100)', + // x: [100, 300, 200, 600], + // x: { from: 0, to: 1 }, + // x: { start: 0, to: 1 }, + // x: { start: value0, from: value1, to: value2 }, + // x: { + // getActive: function (target, key, value, targetIndex, totalTargets, tween) { return newValue; }, + // getStart: function (target, key, value, targetIndex, totalTargets, tween) { return newValue; }, + // getEnd: function (target, key, value, targetIndex, totalTargets, tween) { return newValue; } + // }, + ease: 'Linear', // 'Cubic', 'Elastic', 'Bounce', 'Back' + duration: 1000, + repeat: 0, // -1: infinity + yoyo: true, + //persist: true, + // interpolation: null, + onYoyo: () => { + console.log(this) + } + }).pause(); + */ + } + + update(){ + //dynamically change depth shading of quads + if(this.shadeMod !== this.shadeModTarget){ + let dis = this.shadeModTarget - this.shadeMod + this.shadeMod += dis * 0.01; + if(dis < 0.001 && dis > -0.001){ + this.shadeMod = this.shadeModTarget; + } + } + } + + setPositionAndRotation(_pos, _dir){ + this.pos.x = _pos.x; + this.pos.y = _pos.y; + this.pos.z = _pos.z; + this.dir.yaw = _dir.yaw; + this.dir.pitch = _dir.pitch; + this.dir.roll = _dir.roll; + } + + setDefaultZoom(){ + this.zoom = 800; + this.zOffset = 15; + this.fov = 2.5; + } + + setZoomTween(_level, _params){ + //this.zoomTween.destroy(); + this.zoomTween = this.scene.tweens.add({ + targets: this, + zoom: 0.0001, + // x: '+=1', + // x: '-=1', + // x: '*=1', + // x: '/=1', + // x: 'random(0.25, 0.75)', + // x: 'int(10, 100)', + // x: [100, 300, 200, 600], + // x: { from: 0, to: 1 }, + // x: { start: 0, to: 1 }, + // x: { start: value0, from: value1, to: value2 }, + // x: { + // getActive: function (target, key, value, targetIndex, totalTargets, tween) { return newValue; }, + // getStart: function (target, key, value, targetIndex, totalTargets, tween) { return newValue; }, + // getEnd: function (target, key, value, targetIndex, totalTargets, tween) { return newValue; } + // }, + ease: 'Linear', // 'Cubic', 'Elastic', 'Bounce', 'Back' + duration: 1000, + repeat: 0, // -1: infinity + yoyo: true, + //persist: true, + // interpolation: null, + onYoyo: () => { + this.scene.loadLevel(_level, _params); + } + })//.pause(); + } + + rotateByQuaternion(_quat){ + //rotate local axis around quaternion + let opts = [this.transform.forward.x, this.transform.forward.y, this.transform.forward.z]; + let npts = this.getRotatedVectorByQuaternion(opts, _quat); + this.transform.forward.x = npts[0]; + this.transform.forward.y = npts[1]; + this.transform.forward.z = npts[2]; + this.transform.forward = gl_rvaa.AIOvec3normalize(this.transform.forward, this.transform.forward); + + opts = [this.transform.right.x, this.transform.right.y, this.transform.right.z]; + npts = this.getRotatedVectorByQuaternion(opts, _quat); + this.transform.right.x = npts[0]; + this.transform.right.y = npts[1]; + this.transform.right.z = npts[2]; + this.transform.right = gl_rvaa.AIOvec3normalize(this.transform.right, this.transform.right); + + opts = [this.transform.up.x, this.transform.up.y, this.transform.up.z]; + npts = this.getRotatedVectorByQuaternion(opts, _quat); + this.transform.up.x = npts[0]; + this.transform.up.y = npts[1]; + this.transform.up.z = npts[2]; + this.transform.up = gl_rvaa.AIOvec3normalize(this.transform.up, this.transform.up); + } + + getRotatedVectorByQuaternion(_vector, _quat){ + let u = [_quat[0], _quat[1], _quat[2]]; + let s = _quat[3]; + + //let cros = gl_rvaa.AIOvec3cross([0, 0, 0], u, _vector) + //return 2 * gl_rvaa.AIOvec3dot(u, _vector) * u + (s*s - gl_rvaa.AIOvec3dot(u, u)) * _vector + 2 * s * gl_rvaa.AIOvec3cross(u, u, _vector); + let dot0 = gl_rvaa.AIOvec3dot(u, _vector); + let vec0 = [ + 2 * dot0 * u[0], + 2 * dot0 * u[1], + 2 * dot0 * u[2] + ]; + let dot1 = gl_rvaa.AIOvec3dot(u, u); + let vec1 = [ + (s*s - dot1) * _vector[0], + (s*s - dot1) * _vector[1], + (s*s - dot1) * _vector[2] + ] + let cro0 = gl_rvaa.AIOvec3cross(u, u, _vector); + let vec2 = [ + 2 * s * cro0[0], + 2 * s * cro0[1], + 2 * s * cro0[2] + ] + let vet = [ + vec0[0] + vec1[0] + vec2[0], + vec0[1] + vec1[1] + vec2[1], + vec0[2] + vec1[2] + vec2[2] + ] + return vet; + } + + rotateAroundAxis(_axis, _angle){ + // credi @Lewa helpdesk + + //INFO maybe set the rotation of the rotationQuat to the new forward, up and right vectors with (gl_quat.setAxis(out, view, right, up)) + + //turn the transform rotationQuat around axis and angle + //let totrans = gl_rvaa.AIOquatcreate(); + let totrans = gl_rvaa.AIOquatCreateFromAngleAxis(_axis[0], _axis[1], _axis[2], _angle) + let tempQuat = [0, 0, 0, 1]; + gl_rvaa.AIOquatmultiply(tempQuat, this.transform.rotationQuat, totrans); + + //create a matrix from transform rotationQuat + let rotMatrix = gl_rvaa.AIOmat3create() + gl_rvaa.AIOmat3fromQuat(rotMatrix, tempQuat) + + let npts = [this.transform.forward.x, this.transform.forward.y, this.transform.forward.z]; + gl_rvaa.AIOvec3multiplyWithMatrix(npts, [this.transform.forward.x, this.transform.forward.y, this.transform.forward.z], rotMatrix) + this.transform.forward.x = npts[0]; + this.transform.forward.y = npts[1]; + this.transform.forward.z = npts[2]; + this.transform.forward = gl_rvaa.AIOvec3normalize(this.transform.forward, this.transform.forward); + + npts = [this.transform.right.x, this.transform.right.y, this.transform.right.z]; + gl_rvaa.AIOvec3multiplyWithMatrix(npts, [this.transform.right.x, this.transform.right.y, this.transform.right.z], rotMatrix) + this.transform.right.x = npts[0]; + this.transform.right.y = npts[1]; + this.transform.right.z = npts[2]; + this.transform.right = gl_rvaa.AIOvec3normalize(this.transform.right, this.transform.right); + + npts = [this.transform.up.x, this.transform.up.y, this.transform.up.z]; + gl_rvaa.AIOvec3multiplyWithMatrix(npts, [this.transform.up.x, this.transform.up.y, this.transform.up.z], rotMatrix) + this.transform.up.x = npts[0]; + this.transform.up.y = npts[1]; + this.transform.up.z = npts[2]; + this.transform.up = gl_rvaa.AIOvec3normalize(this.transform.up, this.transform.up); + + //normalize to prevent weird rotations + this.transform.normalizeRotationQuat(); + } +} \ No newline at end of file diff --git a/src/3d/character.js b/src/3d/character.js new file mode 100755 index 0000000..16f46dc --- /dev/null +++ b/src/3d/character.js @@ -0,0 +1,36 @@ +export default class Character { + constructor(_scene, _name, _reactions = null, _promoAtlas, _promoAsset, _team = null) { + this.scene = _scene; + this.controlledModel; + + this.name = _name; + this.team = _team; + this.color = "yellow"; + this.promoAtlas = _promoAtlas; + this.promoAsset = _promoAsset; + this.locked = false; + + this.sympathy = 0; //-2 hat -1 dislike 0 neutral 1 like 2 love + this.reactions = _reactions; + if (this.reactions === null) { + this.reactions = { + atlas: "charSheetExpressions", + angry: [], + normal: [], + thinking: [], + hit: [], + haha: [], + taunt: [], + cheer: [] + } + } + } + + update() { + + } + + destroy() { + + } +} diff --git a/src/3d/dataQuad.js b/src/3d/dataQuad.js new file mode 100755 index 0000000..97b16f8 --- /dev/null +++ b/src/3d/dataQuad.js @@ -0,0 +1,801 @@ +export default class DataQuad { + constructor(_scene, _modelId, _runNo, _type, _pos, _points, _texture, _frame) { + this.scene = _scene; + this.modelId = _modelId; + this.runNo = _runNo; + this.type = _type; + this.pos = _pos; + this.d2dPos = { + x: 0, + y: 0, + z: 0 + } + this.points = _points; //array of 4 xyz coords + this.texture = _texture; + this.frame = _frame; + this.quads = [];// to be filled by a phaser quad if it should be rendered + this.mipmapped = false; + this.depth = 0; + this.shade = 0; + this.alpha = 1; + this.scale = { + x: 1, + y: 1, + } + this.zDepth = 0; + + this.screenCoords = [ + { x: 0, y: 0 }, + { x: 0, y: 0 }, + { x: 0, y: 0 }, + { x: 0, y: 0 } + ]; + + //additional helperScreencoords + this.sc01 = { + x: 0, + y: 0 + } + this.sc03 = { + x: 0, + y: 0 + } + this.sc12 = { + x: 0, + y: 0 + } + this.sc32 = { + x: 0, + y: 0 + } + this.scM = { + x: 0, + y: 0 + } + } + + update() { + + } + + draw() { + if (this.quads.length > 0) { + if (this.mipmapped === false) { + this.quads[0].setTopLeft(this.screenCoords[0].x, this.screenCoords[0].y); + this.quads[0].setTopRight(this.screenCoords[1].x, this.screenCoords[1].y); + this.quads[0].setBottomRight(this.screenCoords[2].x, this.screenCoords[2].y); + this.quads[0].setBottomLeft(this.screenCoords[3].x, this.screenCoords[3].y); + this.quads[0].depth = this.depth; + } else { + this.quads[0].setTopLeft(this.screenCoords[0].x, this.screenCoords[0].y); + this.quads[0].setTopRight(this.sc01.x, this.sc01.y); + this.quads[0].setBottomRight(this.scM.x, this.scM.y); + this.quads[0].setBottomLeft(this.sc03.x, this.sc03.y); + this.quads[0].depth = this.depth; + + this.quads[1].setTopLeft(this.sc01.x, this.sc01.y); + this.quads[1].setTopRight(this.screenCoords[1].x, this.screenCoords[1].y); + this.quads[1].setBottomRight(this.sc12.x, this.sc12.y); + this.quads[1].setBottomLeft(this.scM.x, this.scM.y); + this.quads[1].depth = this.depth; + + this.quads[2].setTopLeft(this.scM.x, this.scM.y); + this.quads[2].setTopRight(this.sc12.x, this.sc12.y); + this.quads[2].setBottomRight(this.screenCoords[2].x, this.screenCoords[2].y); + this.quads[2].setBottomLeft(this.sc32.x, this.sc32.y); + this.quads[2].depth = this.depth; + + this.quads[3].setTopLeft(this.sc03.x, this.sc03.y); + this.quads[3].setTopRight(this.scM.x, this.scM.y); + this.quads[3].setBottomRight(this.sc32.x, this.sc32.y); + this.quads[3].setBottomLeft(this.screenCoords[3].x, this.screenCoords[3].y); + this.quads[3].depth = this.depth; + } + + + let col = Phaser.Display.Color.GetColor(this.shade, this.shade, this.shade); + for (let q of this.quads) { + //shading + q.topLeftColor = col; + q.topRightColor = col; + q.bottomLeftColor = col; + q.bottomRightColor = col; + } + + } + } + + drawNo3d(_from, _dir, _withScale) { + if (this.quads.length > 0) { + //this.calculateHelpPoints(); + //this.quads[0].x = this.scM.x; + //this.quads[0].y = this.scM.y; + + //calculate the billboard position of a quad seen from the camera + let pt = { + x: this.d2dPos.x + this.pos.x - _from.x, + y: this.d2dPos.y + this.pos.y - _from.y, + z: this.d2dPos.z + this.pos.z - _from.z + } + let outXZ = rti.rotateY([0, 0, 0], [pt.x, pt.y, pt.z], [0, 0, 0], _dir.yaw); + let nx = outXZ[0]; + let ny = outXZ[1]; + let nz = outXZ[2]; + let outYZ = rti.rotateX([0, 0, 0], [nx, ny, nz], [0, 0, 0], _dir.pitch); + nx = outYZ[0]; + ny = outYZ[1]; + nz = outYZ[2]; + + let nzMod = nz + 10; + let zoom = 400; + this.quads[0].x = (nx / (Math.abs(nzMod) * 1)) * zoom; + this.quads[0].y = (ny / (Math.abs(nzMod) * 1)) * zoom; + + if (_withScale === true) { + //this.quads[0].setScale(this.zDepth); + this.quads[0].setScale(256 / nz); + } + this.quads[0].depth = nz; + } + } + + drawNo3dFromQuat(_from, _quat, _withScale) { + if (this.quads.length > 0) { + //this.calculateHelpPoints(); + //this.quads[0].x = this.scM.x; + //this.quads[0].y = this.scM.y; + + //calculate the billboard position of a quad seen from the camera + let pt = { + x: this.d2dPos.x + this.pos.x - _from.x, + y: this.d2dPos.y + this.pos.y - _from.y, + z: this.d2dPos.z + this.pos.z - _from.z + } + + let npts = [pt.x, pt.y, pt.z]; + + let u = [_quat[0], _quat[1], _quat[2]]; + let s = _quat[3]; + + let dot0 = gl_rvaa.AIOvec3dot(u, npts); + let vec0 = [ + 2 * dot0 * u[0], + 2 * dot0 * u[1], + 2 * dot0 * u[2] + ]; + let dot1 = gl_rvaa.AIOvec3dot(u, u); + let vec1 = [ + (s*s - dot1) * npts[0], + (s*s - dot1) * npts[1], + (s*s - dot1) * npts[2] + ] + let cro0 = gl_rvaa.AIOvec3cross(u, u, npts); + let vec2 = [ + 2 * s * cro0[0], + 2 * s * cro0[1], + 2 * s * cro0[2] + ] + let vet = [ + vec0[0] + vec1[0] + vec2[0], + vec0[1] + vec1[1] + vec2[1], + vec0[2] + vec1[2] + vec2[2] + ] + + let nx = vet[0]; + let ny = vet[1]; + let nz = vet[2]; + + + let nzMod = nz + 10; + let zoom = 400; + this.quads[0].x = (nx / (Math.abs(nzMod) * 1)) * zoom; + this.quads[0].y = (ny / (Math.abs(nzMod) * 1)) * zoom; + + if (_withScale === true) { + //this.quads[0].setScale(this.zDepth); + this.quads[0].setScale(256 / nz); + } + this.quads[0].depth = nz; + } + } + + calculate3d(_from, _dir, _mipmap = true) { + let recZ = -9999; + let recY = -9999; + let sumZ = 0; + + let outsideScreenSafe = false; + let cull = false; + let ptsOoB = 0; + + //calculate the quads point in 3d seen from the camera + for (let [i, p] of this.points.entries()) { + let pts = { + x: p.x + this.pos.x - _from.x, + y: p.y + this.pos.y - _from.y, + z: p.z + this.pos.z - _from.z + } + + let nx = pts.x; + let ny = pts.y; + let nz = pts.z; + let outXZ = rti.rotateY([0, 0, 0], [nx, ny, nz], [0, 0, 0], _dir.yaw); + nx = outXZ[0]; + ny = outXZ[1]; + nz = outXZ[2]; + let outYZ = rti.rotateX([0, 0, 0], [nx, ny, nz], [0, 0, 0], _dir.pitch); + nx = outYZ[0]; + ny = outYZ[1]; + nz = outYZ[2]; + let outXY = rti.rotateZ([0, 0, 0], [nx, ny, nz], [0, 0, 0], _dir.roll); + nx = outXY[0]; + ny = outXY[1]; + nz = outXY[2]; + + if (nz <= 10) { + //cull = true; + ptsOoB += 1; + } + if (nz < 0) { + nz *= 0.001;//original 0.001 + } + nz *= this.scene.cam.fov;//original + + let nzMod = nz + this.scene.cam.zOffset; + let zoom = this.scene.cam.zoom; + //this.screenCoords[i].x = (nx / (Math.abs(Math.max(0.1, nzMod)) * 1)) * zoom;//ruckelig bc of abs + //this.screenCoords[i].y = (ny / (Math.abs(Math.max(0.1, nzMod)) * 1)) * zoom;//ruckelig bc of abs + this.screenCoords[i].x = (nx / Math.max(0.1, nzMod) * 1) * zoom; + this.screenCoords[i].y = (ny / Math.max(0.1, nzMod) * 1) * zoom; + + if (outsideScreenSafe === false) { + outsideScreenSafe = this.screenCoords[i].x <= this.scene.left || this.screenCoords[i].x >= this.scene.right || this.screenCoords[i].y <= this.scene.top || this.screenCoords[i].y >= this.scene.bottom; + } + + this.zDepth = (1 / Math.abs(nzMod)) * zoom; + + //ortho rendering + //this.screenCoords[i].x = nx; + //this.screenCoords[i].y = ny; + + //clamp screenCoords + //this.screenCoords[i].x = Math.max(-this.scene.game.config.width * 20, Math.min(this.scene.game.config.width * 20, this.screenCoords[i].x)); + //this.screenCoords[i].y = Math.max(-this.scene.game.config.height * 20, Math.min(this.scene.game.config.height * 20, this.screenCoords[i].y)); + + if (nz > recZ) { + recZ = nzMod; + } + if(ny > recY){ + recY = ny; + } + //sumZ += nz; + //sumZ += (nz + (512 - Phaser.Math.Distance.Between(this.screenCoords[i].x, this.screenCoords[i].y, 0, 0) * -0.1)) * 1; + sumZ += nz;// + (Math.abs(this.screenCoords[i].y + this.screenCoords[i].x) * 0.1); + } + this.depth = sumZ * -0.25; + //this.depth = recZ*-1; + //this.shade = Math.max(0, 255 - ((recZ + 0) * 0.125) ); + this.shade = Math.max(0, 255 - ((recZ + 0) * 0.05) ); + //trippy effect or even able to do a torchlight effect + //let shadeDist = Math.sqrt(recZ * recZ + ((recY * recY) * 10000)); + //this.shade = Math.max(0, 255 - (shadeDist * 0.125)); + + //if (ptsOoB === 4){ + if(ptsOoB > 3){ + cull = true; + } + + if (this.type !== "collisionQuad") { + if (cull === true) {//if(this.depth >= 0 || cull === true){//near clipping plane could be at -25 for example + if (this.quads.length > 0) { + this.clearQuads(); + } + } else {// if(this.depth < 0){ + if (this.quads.length === 0) { + this.createQuad(); + } + //quad so near that mipmapping is required? + //if (this.depth > -50){ + if (outsideScreenSafe === true) { + if (_mipmap === true && this.quads.length > 0) { + this.mipmapQuad(); + } + } else { + if (this.quads.length > 0) { + this.unmipmapQuad(); + } + } + } + + if (this.quads.length > 0) { + //if (this.depth < -12) {// (recZ > 16) at sumZ * -0.25 + if(cull === false){ + for (let q of this.quads) { + q.alphas = [this.alpha, this.alpha, this.alpha, this.alpha, this.alpha, this.alpha]; + } + } else { + for (let q of this.quads) { + q.alphas = [0, 0, 0, 0, 0, 0]; + } + } + } + } + } + + calculate3dFromMatrix(_from, _matrix, _mipmap = true) { + let recZ = -9999; + let recY = -9999; + let sumZ = 0; + + let outsideScreenSafe = false; + let cull = false; + let ptsOoB = 0; + + //calculate the quads point in 3d seen from the camera + for (let [i, p] of this.points.entries()) { + let pts = { + x: p.x + this.pos.x - _from.x, + y: p.y + this.pos.y - _from.y, + z: p.z + this.pos.z - _from.z + } + + let npts = [pts.x, pts.y, pts.z]; + gl_rvaa.AIOvec3multiplyWithMatrix(npts, [pts.x, pts.y, pts.z], _matrix) + let nx = npts[0]; + let ny = npts[1]; + let nz = npts[2]; + + /* + let nx = pts.x; + let ny = pts.y; + let nz = pts.z; + let outXZ = rti.rotateY([0, 0, 0], [nx, ny, nz], [0, 0, 0], _dir.yaw); + nx = outXZ[0]; + ny = outXZ[1]; + nz = outXZ[2]; + let outYZ = rti.rotateX([0, 0, 0], [nx, ny, nz], [0, 0, 0], _dir.pitch); + nx = outYZ[0]; + ny = outYZ[1]; + nz = outYZ[2]; + let outXY = rti.rotateZ([0, 0, 0], [nx, ny, nz], [0, 0, 0], _dir.roll); + nx = outXY[0]; + ny = outXY[1]; + nz = outXY[2]; + */ + + if (nz <= 10) { + //cull = true; + ptsOoB += 1; + } + if (nz < 0) { + nz *= 0.001;//original 0.001 + } + nz *= this.scene.cam.fov;//original + + let nzMod = nz + this.scene.cam.zOffset; + let zoom = this.scene.cam.zoom; + //this.screenCoords[i].x = (nx / (Math.abs(Math.max(0.1, nzMod)) * 1)) * zoom;//ruckelig bc of abs + //this.screenCoords[i].y = (ny / (Math.abs(Math.max(0.1, nzMod)) * 1)) * zoom;//ruckelig bc of abs + this.screenCoords[i].x = (nx / Math.max(0.1, nzMod) * 1) * zoom; + this.screenCoords[i].y = (ny / Math.max(0.1, nzMod) * 1) * zoom; + + if (outsideScreenSafe === false) { + outsideScreenSafe = this.screenCoords[i].x <= this.scene.left || this.screenCoords[i].x >= this.scene.right || this.screenCoords[i].y <= this.scene.top || this.screenCoords[i].y >= this.scene.bottom; + } + + this.zDepth = (1 / Math.abs(nzMod)) * zoom; + + //ortho rendering + //this.screenCoords[i].x = nx; + //this.screenCoords[i].y = ny; + + //clamp screenCoords + //this.screenCoords[i].x = Math.max(-this.scene.game.config.width * 20, Math.min(this.scene.game.config.width * 20, this.screenCoords[i].x)); + //this.screenCoords[i].y = Math.max(-this.scene.game.config.height * 20, Math.min(this.scene.game.config.height * 20, this.screenCoords[i].y)); + + if (nz > recZ) { + recZ = nzMod; + } + if(ny > recY){ + recY = ny; + } + //sumZ += nz; + //sumZ += (nz + (512 - Phaser.Math.Distance.Between(this.screenCoords[i].x, this.screenCoords[i].y, 0, 0) * -0.1)) * 1; + sumZ += nz;// + (Math.abs(this.screenCoords[i].y + this.screenCoords[i].x) * 0.1); + } + this.depth = sumZ * -0.25; + //this.depth = recZ*-1; + //this.shade = Math.max(0, 255 - ((recZ + 0) * 0.125) ); + this.shade = Math.max(0, 255 - ((recZ + 0) * 0.05) ); + //trippy effect or even able to do a torchlight effect + //let shadeDist = Math.sqrt(recZ * recZ + ((recY * recY) * 10000)); + //this.shade = Math.max(0, 255 - (shadeDist * 0.125)); + + //if (ptsOoB === 4){ + if(ptsOoB > 3){ + cull = true; + } + + if (this.type !== "collisionQuad") { + if (cull === true) {//if(this.depth >= 0 || cull === true){//near clipping plane could be at -25 for example + if (this.quads.length > 0) { + this.clearQuads(); + } + } else {// if(this.depth < 0){ + if (this.quads.length === 0) { + this.createQuad(); + } + //quad so near that mipmapping is required? + //if (this.depth > -50){ + if (outsideScreenSafe === true) { + if (_mipmap === true && this.quads.length > 0) { + this.mipmapQuad(); + } + } else { + if (this.quads.length > 0) { + this.unmipmapQuad(); + } + } + } + + if (this.quads.length > 0) { + //if (this.depth < -12) {// (recZ > 16) at sumZ * -0.25 + if(cull === false){ + for (let q of this.quads) { + q.alphas = [this.alpha, this.alpha, this.alpha, this.alpha, this.alpha, this.alpha]; + } + } else { + for (let q of this.quads) { + q.alphas = [0, 0, 0, 0, 0, 0]; + } + } + } + } + } + + calculate3dFromQuat(_from, _quat, _mipmap = true) { + let recZ = -9999; + let recY = -9999; + let sumZ = 0; + + let outsideScreenSafe = false; + let cull = false; + let ptsOoB = 0; + + //calculate the quads point in 3d seen from the camera + for (let [i, p] of this.points.entries()) { + let pts = { + x: p.x + this.pos.x - _from.x, + y: p.y + this.pos.y - _from.y, + z: p.z + this.pos.z - _from.z + } + + let npts = [pts.x, pts.y, pts.z]; + + let u = [_quat[0], _quat[1], _quat[2]]; + let s = _quat[3]; + + let dot0 = gl_rvaa.AIOvec3dot(u, npts); + let vec0 = [ + 2 * dot0 * u[0], + 2 * dot0 * u[1], + 2 * dot0 * u[2] + ]; + let dot1 = gl_rvaa.AIOvec3dot(u, u); + let vec1 = [ + (s*s - dot1) * npts[0], + (s*s - dot1) * npts[1], + (s*s - dot1) * npts[2] + ] + let cro0 = gl_rvaa.AIOvec3cross(u, u, npts); + let vec2 = [ + 2 * s * cro0[0], + 2 * s * cro0[1], + 2 * s * cro0[2] + ] + let vet = [ + vec0[0] + vec1[0] + vec2[0], + vec0[1] + vec1[1] + vec2[1], + vec0[2] + vec1[2] + vec2[2] + ] + + let nx = vet[0]; + let ny = vet[1]; + let nz = vet[2]; + + if (nz <= 10) { + //cull = true; + ptsOoB += 1; + } + if (nz < 0) { + nz *= 0.001;//original 0.001 + } + nz *= this.scene.cam.fov;//original + + let nzMod = nz + this.scene.cam.zOffset; + let zoom = this.scene.cam.zoom; + //this.screenCoords[i].x = (nx / (Math.abs(Math.max(0.1, nzMod)) * 1)) * zoom;//ruckelig bc of abs + //this.screenCoords[i].y = (ny / (Math.abs(Math.max(0.1, nzMod)) * 1)) * zoom;//ruckelig bc of abs + this.screenCoords[i].x = (nx / Math.max(0.1, nzMod) * 1) * zoom; + this.screenCoords[i].y = (ny / Math.max(0.1, nzMod) * 1) * zoom; + + if (outsideScreenSafe === false) { + outsideScreenSafe = this.screenCoords[i].x <= this.scene.left || this.screenCoords[i].x >= this.scene.right || this.screenCoords[i].y <= this.scene.top || this.screenCoords[i].y >= this.scene.bottom; + } + + this.zDepth = (1 / Math.abs(nzMod)) * zoom; + + //ortho rendering + //this.screenCoords[i].x = nx; + //this.screenCoords[i].y = ny; + + //clamp screenCoords + //this.screenCoords[i].x = Math.max(-this.scene.game.config.width * 20, Math.min(this.scene.game.config.width * 20, this.screenCoords[i].x)); + //this.screenCoords[i].y = Math.max(-this.scene.game.config.height * 20, Math.min(this.scene.game.config.height * 20, this.screenCoords[i].y)); + + if (nz > recZ) { + recZ = nzMod; + } + if(ny > recY){ + recY = ny; + } + //sumZ += nz; + //sumZ += (nz + (512 - Phaser.Math.Distance.Between(this.screenCoords[i].x, this.screenCoords[i].y, 0, 0) * -0.1)) * 1; + sumZ += nz;// + (Math.abs(this.screenCoords[i].y + this.screenCoords[i].x) * 0.1); + } + this.depth = sumZ * -0.25; + //this.depth = recZ*-1; + //this.shade = Math.max(0, 255 - ((recZ + 0) * 0.125) );0.04 0.125 + this.shade = Math.max(0, 255 - ((recZ + 0) * this.scene.cam.shadeMod) ); + //trippy effect or even able to do a torchlight effect + //let shadeDist = Math.sqrt(recZ * recZ + ((recY * recY) * 10000)); + //this.shade = Math.max(0, 255 - (shadeDist * 0.125)); + + //if (ptsOoB === 4){ + if(ptsOoB > 3){ + cull = true; + } + + if (this.type !== "collisionQuad") { + if (cull === true) {//if(this.depth >= 0 || cull === true){//near clipping plane could be at -25 for example + if (this.quads.length > 0) { + this.clearQuads(); + } + } else {// if(this.depth < 0){ + if (this.quads.length === 0) { + this.createQuad(); + } + //quad so near that mipmapping is required? + //if (this.depth > -50){ + if (outsideScreenSafe === true) { + //if (this.shade >= 246) { + if (_mipmap === true && this.quads.length > 0) { + this.mipmapQuad(); + } + } else { + if (this.quads.length > 0) { + this.unmipmapQuad(); + } + } + } + + if (this.quads.length > 0) { + //if (this.depth < -12) {// (recZ > 16) at sumZ * -0.25 + if(cull === false){ + for (let q of this.quads) { + q.alphas = [this.alpha, this.alpha, this.alpha, this.alpha, this.alpha, this.alpha]; + } + } else { + for (let q of this.quads) { + q.alphas = [0, 0, 0, 0, 0, 0]; + } + } + } + } + } + + getIntersect(_x, _y, _z, _toX, _toY, _toZ) { + // probe first tri of quad + let tri = [ + [this.points[0].x + this.pos.x, this.points[0].y + this.pos.y, this.points[0].z + this.pos.z], + [this.points[1].x + this.pos.x, this.points[1].y + this.pos.y, this.points[1].z + this.pos.z], + [this.points[2].x + this.pos.x, this.points[2].y + this.pos.y, this.points[2].z + this.pos.z], + ]; + let pt = [_x, _y, _z]; + let dir = [_toX, _toY, _toZ]; + let odir = [_toX * -1, _toY * -1, _toZ * -1]; + let hit = rti.intersect([], pt, dir, tri); + let ohit = rti.intersect([], pt, odir, tri); + if (hit === null && ohit === null) { + // probe 2nd tri part of quad + tri = [ + [this.points[0].x + this.pos.x, this.points[0].y + this.pos.y, this.points[0].z + this.pos.z], + [this.points[2].x + this.pos.x, this.points[2].y + this.pos.y, this.points[2].z + this.pos.z], + [this.points[3].x + this.pos.x, this.points[3].y + this.pos.y, this.points[3].z + this.pos.z], + ]; + hit = rti.intersect([], pt, dir, tri); + ohit = rti.intersect([], pt, odir, tri); + } + if (hit !== null) { + return hit; + } + if (ohit !== null) {//TODO actually never happens bc the first hit covers infinite length in both ways + return ohit; + } + return null; + } + + clearQuads() { + this.mipmapped = false; + for (let i = this.quads.length - 1; i >= 0; i--) { + this.quads[i].destroy(); + } + this.quads = []; + } + + createQuad() { + this.quads.push(this.scene.add.quad(0, 0, this.texture, this.frame)); + //console.log(this.quads[0].uv); + } + + mipmapQuad() { + this.calculateHelpPoints(); + + if (this.mipmapped === false) { + this.mipmapped = true; + + this.quads.push(this.scene.add.quad(0, 0, this.texture, this.frame)); + this.quads.push(this.scene.add.quad(0, 0, this.texture, this.frame)); + this.quads.push(this.scene.add.quad(0, 0, this.texture, this.frame)); + + this.calculateUVs(); + + //old method for single images + /*this.quads[0].uv = [0, 0, 0, 0.5, 0.5, 0.5, 0, 0, 0.5, 0.5, 0.5, 0]; + this.quads[1].uv = [0.5, 0, 0.5, 0.5, 1, 0.5, 0.5, 0, 1, 0.5, 1, 0]; + this.quads[2].uv = [0.5, 0.5, 0.5, 1, 1, 1, 0.5, 0.5, 1, 1, 1, 0.5]; + this.quads[3].uv = [0, 0.5, 0, 1, 0.5, 1, 0, 0.5, 0.5, 1, 0.5, 0.5];*/ + } + } + + unmipmapQuad() { + if (this.mipmapped === true) { + this.mipmapped = false; + + this.clearQuads(); + this.createQuad(); + + //this.quads[0].uv = [0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0]; + this.setTexture(this.texture, this.frame); + } + } + + calculateUVs(){ + if(this.quads.length > 1){ + //hard copy original uvs + let saveUv = []; + for (let c of this.quads[0].uv) { + saveUv.push(c); + } + + //calculate mid point of the part of the image from the used texture + let m = { + x: (saveUv[0] + saveUv[4]) * 0.5, + y: (saveUv[1] + saveUv[5]) * 0.5 + } + + if(this.quads.length > 1){ + this.quads[0].uv = [saveUv[0], saveUv[1], saveUv[2], m.y, m.x, m.y, saveUv[6], saveUv[7], m.x, m.y, m.x, saveUv[11]]; + this.quads[1].uv = [m.x, saveUv[1], m.x, m.y, saveUv[4], m.y, m.x, saveUv[7], saveUv[8], m.y, saveUv[10], saveUv[11]]; + this.quads[2].uv = [m.x, m.y, m.x, saveUv[3], saveUv[4], saveUv[5], m.x, m.y, saveUv[8], saveUv[9], saveUv[10], m.y]; + this.quads[3].uv = [saveUv[0], m.y, saveUv[2], saveUv[3], m.x, saveUv[5], saveUv[6], m.y, m.x, saveUv[9], m.x, m.y]; + } + } + } + + calculateHelpPoints() { + this.sc01.x = (this.screenCoords[0].x + this.screenCoords[1].x) * 0.5; + this.sc01.y = (this.screenCoords[0].y + this.screenCoords[1].y) * 0.5; + this.sc03.x = (this.screenCoords[0].x + this.screenCoords[3].x) * 0.5; + this.sc03.y = (this.screenCoords[0].y + this.screenCoords[3].y) * 0.5; + this.sc12.x = (this.screenCoords[1].x + this.screenCoords[2].x) * 0.5; + this.sc12.y = (this.screenCoords[1].y + this.screenCoords[2].y) * 0.5; + this.sc32.x = (this.screenCoords[3].x + this.screenCoords[2].x) * 0.5; + this.sc32.y = (this.screenCoords[3].y + this.screenCoords[2].y) * 0.5; + this.scM.x = (this.sc03.x + this.sc12.x) * 0.5; + this.scM.y = (this.sc03.y + this.sc12.y) * 0.5; + } + + recalculatePosition() { + /* + //TODO rework this - this doesnt calculate the mdipoint of the quad + this.pos = { + x: (this.points[0].x + this.points[1].x + this.points[2].x + this.points[3].x) / 4, + y: (this.points[0].y + this.points[1].y + this.points[2].y + this.points[3].y) / 4, + z: (this.points[0].z + this.points[1].z + this.points[2].z + this.points[3].z) / 4 + };*/ + } + + cyclePoints(_cw = true) { + if (_cw === true) { + let help = { + x: this.points[0].x, + y: this.points[0].y, + z: this.points[0].z + } + for (let i = 0; i < 3; i++) { + this.points[i].x = this.points[i + 1].x; + this.points[i].y = this.points[i + 1].y; + this.points[i].z = this.points[i + 1].z; + } + this.points[3].x = help.x; + this.points[3].y = help.y; + this.points[3].z = help.z; + } else { + let help = { + x: this.points[3].x, + y: this.points[3].y, + z: this.points[3].z + } + for (let i = 3; i > 0; i--) { + this.points[i].x = this.points[i - 1].x; + this.points[i].y = this.points[i - 1].y; + this.points[i].z = this.points[i - 1].z; + } + this.points[0].x = help.x; + this.points[0].y = help.y; + this.points[0].z = help.z; + } + } + + mirrorPoints(_vertical = true){ + console.log("mirrier") + let help0 = { + x: this.points[0].x, + y: this.points[0].y, + z: this.points[0].z + } + let help3 = { + x: this.points[3].x, + y: this.points[3].y, + z: this.points[3].z + } + this.points[0].x = this.points[1].x; + this.points[0].y = this.points[1].y; + this.points[0].z = this.points[1].z; + this.points[3].x = this.points[2].x; + this.points[3].y = this.points[2].y; + this.points[3].z = this.points[2].z; + + this.points[2].x = help3.x; + this.points[2].y = help3.y; + this.points[2].z = help3.z; + this.points[1].x = help0.x; + this.points[1].y = help0.y; + this.points[1].z = help0.z; + } + + setTexture(_tex, _frame = 0, _saveUv = true) { + this.texture = _tex; + this.frame = _frame; + for (let qq of this.quads) { + let saveUv = []; + for (let c of qq.uv) { + saveUv.push(c); + } + qq.setTexture(this.texture, this.frame); + if(_saveUv === true){ + qq.uv = saveUv; + }else{ + + } + } + if (_saveUv === false) { + this.calculateUVs(); + } + } + + destroy() { + this.clearQuads(); + } +} \ No newline at end of file diff --git a/src/3d/editor.js b/src/3d/editor.js new file mode 100755 index 0000000..6072b06 --- /dev/null +++ b/src/3d/editor.js @@ -0,0 +1,530 @@ +export default class Editor { + constructor(_scene) { + this.scene = _scene; + + this.enabled = false; + this.photoMode = false; + this.points = [ + this.scene.add.sprite(0, 0, "sprDebugQuadPoint1"), + this.scene.add.sprite(0, 0, "sprDebugQuadPoint2"), + this.scene.add.sprite(0, 0, "sprDebugQuadPoint3"), + this.scene.add.sprite(0, 0, "sprDebugQuadPoint4")//, + //this.add.sprite(0, 0, "sprDebugQuadPoint4"), + //this.add.sprite(0, 0, "sprDebugQuadPointCenter") + ]; + for (let p of this.points) { + p.alpha = 0; + } + this.editPointsEnabled = [false, false, false, false]; + this.quad = null; + this.model = null; + this.pressed = false; + this.editCollisions = false; + + this.atlas = { + palette: [ + "atlasAll", + "atlasAdverts", + "atlasObstacles", + "atlasPlating", + "atlasDesktopBackgrounds", + "atlasFire" + ], + data: JSON.parse(JSON.stringify(this.scene.cache.json.get("atlasAll"))), + position: 0, + bank: 0 + } + + + this.grid = { + size: 4, + min: 0.1, + max: 16, + txt: this.scene.add.bitmapText((this.scene.game.config.width * 0.5) - 16, (this.scene.game.config.height * -0.5) + 16, "uiFont", "grid: 4.00", 14, 0).setOrigin(1, 0).setLetterSpacing(0) + } + this.grid.txt.alpha = 0; + + + //setup Editor key grabs + //grab quads edge points + this.scene.keys.one.on("up", (_key, _event) => { + this.toggleEditPoint(0); + }, this); + this.scene.keys.two.on("up", (_key, _event) => { + this.toggleEditPoint(1); + }, this); + this.scene.keys.three.on("up", (_key, _event) => { + this.toggleEditPoint(2); + }, this); + this.scene.keys.four.on("up", (_key, _event) => { + this.toggleEditPoint(3); + }, this); + this.scene.keys.five.on("up", (_key, _event) => { + this.toggleEditPoint(0); + this.toggleEditPoint(1); + this.toggleEditPoint(2); + this.toggleEditPoint(3); + }, this); + + //move quad keys + this.scene.numkeys.eight.on("up", (_key, _event) => { + for (let [i, e] of this.editPointsEnabled.entries()) { + if (e === true) { + let out = [0, 0, 0]; + out = gl_vec3.cross(out, this.scene.cam.transform.toVectorArray(this.scene.cam.transform.right), [0, -1, 0]); + this.moveToolPoint(i, { x: out[0] * -this.grid.size, y: 0, z: out[2] * -this.grid.size }); + } + } + }, this); + this.scene.numkeys.two.on("up", (_key, _event) => { + for (let [i, e] of this.editPointsEnabled.entries()) { + if (e === true) { + let out = [0, 0, 0]; + out = gl_vec3.cross(out, this.scene.cam.transform.toVectorArray(this.scene.cam.transform.right), [0, -1, 0]); + this.moveToolPoint(i, { x: out[0] * this.grid.size, y: 0, z: out[2] * this.grid.size }); + } + } + }, this); + this.scene.numkeys.four.on("up", (_key, _event) => { + for (let [i, e] of this.editPointsEnabled.entries()) { + if (e === true) { + this.moveToolPoint(i, { x: this.scene.cam.transform.right.x * -this.grid.size, y: 0, z: this.scene.cam.transform.right.z * -this.grid.size }); + } + } + }, this); + this.scene.numkeys.six.on("up", (_key, _event) => { + for (let [i, e] of this.editPointsEnabled.entries()) { + if (e === true) { + this.moveToolPoint(i, { x: this.scene.cam.transform.right.x * this.grid.size, y: 0, z: this.scene.cam.transform.right.z * this.grid.size }); + } + } + }, this); + this.scene.numkeys.nine.on("up", (_key, _event) => { + for (let [i, e] of this.editPointsEnabled.entries()) { + if (e === true) { + this.moveToolPoint(i, { x: 0, y: -this.grid.size, z: 0 }); + } + } + }, this); + this.scene.numkeys.three.on("up", (_key, _event) => { + for (let [i, e] of this.editPointsEnabled.entries()) { + if (e === true) { + this.moveToolPoint(i, { x: 0, y: this.grid.size, z: 0 }); + } + } + }, this); + + //move quad keys alternative + this.scene.keys.i.on("up", (_key, _event) => { + for (let [i, e] of this.editPointsEnabled.entries()) { + if (e === true) { + let out = [0, 0, 0]; + out = gl_vec3.cross(out, this.scene.cam.transform.toVectorArray(this.scene.cam.transform.right), [0, -1, 0]); + this.moveToolPoint(i, { x: out[0] * -this.grid.size, y: 0, z: out[2] * -this.grid.size }); + } + } + }, this); + this.scene.keys.k.on("up", (_key, _event) => { + for (let [i, e] of this.editPointsEnabled.entries()) { + if (e === true) { + let out = [0, 0, 0]; + out = gl_vec3.cross(out, this.scene.cam.transform.toVectorArray(this.scene.cam.transform.right), [0, -1, 0]); + this.moveToolPoint(i, { x: out[0] * this.grid.size, y: 0, z: out[2] * this.grid.size }); + } + } + }, this); + this.scene.keys.j.on("up", (_key, _event) => { + for (let [i, e] of this.editPointsEnabled.entries()) { + if (e === true) { + //this.moveToolPoint(i, { x: Math.sin(this.scene.cam.dir.yaw - HALFPI) * this.grid.size, y: 0, z: Math.cos(this.scene.cam.dir.yaw - HALFPI) * -this.grid.size }); + this.moveToolPoint(i, { x: this.scene.cam.transform.right.x * -this.grid.size, y: 0, z: this.scene.cam.transform.right.z * -this.grid.size }); + } + } + }, this); + this.scene.keys.l.on("up", (_key, _event) => { + for (let [i, e] of this.editPointsEnabled.entries()) { + if (e === true) { + //this.moveToolPoint(i, { x: Math.sin(this.scene.cam.dir.yaw + HALFPI) * this.grid.size, y: 0, z: Math.cos(this.scene.cam.dir.yaw + HALFPI) * -this.grid.size }); + this.moveToolPoint(i, { x: this.scene.cam.transform.right.x * this.grid.size, y: 0, z: this.scene.cam.transform.right.z * this.grid.size }); + } + } + }, this); + this.scene.keys.o.on("up", (_key, _event) => { + for (let [i, e] of this.editPointsEnabled.entries()) { + if (e === true) { + this.moveToolPoint(i, { x: 0, y: -this.grid.size, z: 0 }); + } + } + }, this); + this.scene.keys.u.on("up", (_key, _event) => { + for (let [i, e] of this.editPointsEnabled.entries()) { + if (e === true) { + this.moveToolPoint(i, { x: 0, y: this.grid.size, z: 0 }); + } + } + }, this); + + /*this.scene.numkeys.five.on("up", (_key, _event) => { + if(this.quad !== null){ + this.quad.recalculatePosition(); + } + }, this);*/ + + this.scene.numkeys.plus.on("up", (_key, _event) => { + //this.scene.keys.x.on("up", (_key, _event) => { + if (this.scene.keys.z.isDown) { + //change texture bank + this.changeAtlasBank(this.atlas.bank + 1); + } else if (this.scene.keys.t.isDown) { + //change texture + this.changeAtlasPosition(this.atlas.position + 1); + } else if (this.scene.keys.g.isDown) { + //enlarge gridsize + this.grid.size += 1; + this.grid.size = Math.max(this.grid.min, Math.min(this.grid.max, this.grid.size)); + this.grid.txt.setText("Grid: " + this.grid.size.toFixed(1)); + //console.log(this.grid.size); + } else { + if (this.quad !== null) { + this.quad.cyclePoints(true); + } + } + }, this); + this.scene.numkeys.minus.on("up", (_key, _event) => { + //this.scene.keys.y.on("up", (_key, _event) => { + if (this.scene.keys.z.isDown) { + //change texture bank + this.changeAtlasBank(this.atlas.bank - 1); + } else if (this.scene.keys.t.isDown) { + //change texture + this.changeAtlasPosition(this.atlas.position - 1); + } else if (this.scene.keys.g.isDown) { + //enlarge gridsize + this.grid.size -= 1; + this.grid.size = Math.max(this.grid.min, Math.min(this.grid.max, this.grid.size)); + this.grid.txt.setText("Grid: " + this.grid.size.toFixed(1)); + //console.log(this.grid.size); + } else { + if (this.quad !== null) { + this.quad.cyclePoints(false); + } + } + }, this); + + //rotate texture + this.scene.keys.period.on("up", (_key, _event) => { + if (this.scene.keys.z.isDown) { + //change texture bank + this.changeAtlasBank(this.atlas.bank + 1); + } else if (this.scene.keys.t.isDown) { + //change texture + this.changeAtlasPosition(this.atlas.position + 1); + } else if (this.scene.keys.g.isDown) { + //enlarge gridsize + this.grid.size += 1; + this.grid.size = Math.max(this.grid.min, Math.min(this.grid.max, this.grid.size)); + this.grid.txt.setText("Grid: " + this.grid.size.toFixed(1)); + //console.log(this.grid.size); + } else { + if (this.quad !== null) { + this.quad.cyclePoints(true); + } + } + }, this); + this.scene.keys.comma.on("up", (_key, _event) => { + if (this.scene.keys.z.isDown) { + //change texture bank + this.changeAtlasBank(this.atlas.bank - 1); + } else if (this.scene.keys.t.isDown) { + //change texture + this.changeAtlasPosition(this.atlas.position - 1); + } else if (this.scene.keys.g.isDown) { + //enlarge gridsize + this.grid.size -= 1; + this.grid.size = Math.max(this.grid.min, Math.min(this.grid.max, this.grid.size)); + this.grid.txt.setText("Grid: " + this.grid.size.toFixed(1)); + //console.log(this.grid.size); + } else { + if (this.quad !== null) { + this.quad.cyclePoints(false); + } + } + }, this); + + //mirror texture + this.scene.numkeys.five.on("up", (_key, _event) => { + if (this.quad !== null) { + this.quad.mirrorPoints(true); + } + }, this); + + //texture bank and palette + this.scene.input.on("wheel", (_pointer, _gameObjs, _deltaX, _deltaY, _deltaZ) => { + //change texture bank + if (this.scene.keys.z.isDown) { + if (_deltaY > 0) { + this.changeAtlasBank(this.atlas.bank - 1); + } else if (_deltaY < 0) { + this.changeAtlasBank(this.atlas.bank + 1); + } + } + //flip through texture + if (this.scene.keys.t.isDown) { + //console.log(_deltaY); //-100 to 100 + if (_deltaY > 0) { + this.changeAtlasPosition(this.atlas.position - 1); + } else if (_deltaY < 0) { + this.changeAtlasPosition(this.atlas.position + 1); + } + } + + //change gridsize + if (this.scene.keys.g.isDown) { + if (_deltaY > 0) { + this.grid.size -= 1; + this.grid.size = Math.max(this.grid.min, Math.min(this.grid.max, this.grid.size)); + this.grid.txt.setText("Grid: " + this.grid.size.toFixed(1)); + //console.log(this.grid.size); + } else if (_deltaY < 0) { + this.grid.size += 1; + this.grid.size = Math.max(this.grid.min, Math.min(this.grid.max, this.grid.size)); + this.grid.txt.setText("Grid: " + this.grid.size.toFixed(1)); + //console.log(this.grid.size); + } + } + }, this); + + //duplicate quad + this.scene.keys.n.on("up", (_key, _event) => { + if (this.quad != null) { + if (this.scene.keys.x.isDown) { + this.duplicateQuad(this.quad.pos, [-1, 1, 1]); + } else { + this.duplicateQuad(this.quad.pos); + } + } else { + this.duplicateQuad({ x: 0, y: 0, z: 0 }); + } + }, this); + + //delete selected quad + this.scene.keys.del.on("up", (_key, _event) => { + if (this.model != null) { + this.model.deleteQuad(this.quad, this.editCollisions); + } + }, this); + + //log model + this.scene.keys.end.on("up", (_key, _event) => { + if (this.model != null) { + this.model.log(); + } + }, this); + this.scene.keys.insert.on("up", (_key, _event) => { + //log all textures in order + if (this.model != null) { + this.model.logTextures(); + } + }, this); + + //flick current model in debug mode - this is ONLY drawing the collision boxes + this.scene.keys.m.on("up", (_key, _event) => { + if (this.model != null) { + this.model.toggleDrawCollisions(); + //press spacbar too to edit collision boxes + if (this.scene.keys.q.isDown) { + this.toggleEditCollisions(); + if (this.model.debug.drawCollisions === false) { + this.model.toggleDrawCollisions(); + } + } + } + }, this); + + //toggle photomode + this.scene.keys.p.on("down", (_key, _event) => { + _event.stopPropagation(); + if (this.scene.keys.q.isDown) { + this.togglePhotoMode(); + } + }); + + //toggle editor + this.scene.keys.e.on("down", (_key, _event) => { + _event.stopPropagation(); + if (this.scene.keys.q.isDown) { + this.toggleEditor(); + } + }, this); + + $("#btnPrintModel").on("click", (_ev) => { + _ev.stopPropagation(); + if (this.scene.editor.model != null) { + this.scene.editor.model.log(); + } + }); + $("#btnNewModel").on("click", (_ev) => { + _ev.stopPropagation(); + //this.createNewModel(); + if (this.scene.editor.model != null) { + this.scene.editor.model.log(); + } + this.scene.geometryController.destroyModelById(this.scene.level.model.id); + this.scene.level.model = this.scene.geometryController.loadModel("model name", "modDebugTile", { x: 0, y: 0, z: 0 }); + this.scene.level.model.flags.draw = true; + }); + } + + update() { + //mark quad points + if (this.quad !== null) { + for (let [i, p] of this.quad.screenCoords.entries()) { + this.points[i].x = p.x; + this.points[i].y = p.y; + } + } + } + + changeAtlasBank(_bank) { + this.atlas.bank = Math.max(0, Math.min(_bank, this.atlas.palette.length - 1)); + this.atlas.data = JSON.parse(JSON.stringify(this.scene.cache.json.get(this.atlas.palette[this.atlas.bank]))); + + this.atlas.position = 0; + if (this.quad !== null) { + this.quad.setTexture(this.atlas.palette[this.atlas.bank], this.atlas.data.textures[0].frames[this.atlas.position].filename, false); + console.log(this.atlas.palette[this.atlas.bank]); + } + } + + changeAtlasPosition(_position) { + this.atlas.position = Math.max(0, Math.min(_position, this.atlas.data.textures[0].frames.length - 1)); + if (this.quad !== null) { + this.quad.setTexture(this.atlas.palette[this.atlas.bank], this.atlas.data.textures[0].frames[this.atlas.position].filename, false); + //console.log(this.atlas.data.textures[0].frames[this.atlas.position].filename) + } + } + + toggleEditor() { + this.enabled = !this.enabled; + if (this.enabled === true) { + this.grid.txt.alpha = 1; + for (let p of this.points) { + p.alpha = 1; + } + this.scene.hand.setMouseLock(false); + if (this.scene.player !== null) { + this.scene.player.hideUI(); + } + this.scene.cameras.main.setBackgroundColor(0x343444); + this.scene.playerEditor.pos.x = this.scene.player.pos.x; + this.scene.playerEditor.pos.y = this.scene.player.pos.y - this.scene.player.eyeHeight; + this.scene.playerEditor.pos.z = this.scene.player.pos.z; + this.scene.player = this.scene.playerEditor; + this.scene.cam = this.scene.camEditor; + + $("#editorbox").show(); + } else { + this.grid.txt.alpha = 0; + for (let p of this.points) { + p.alpha = 0; + } + this.scene.hand.setMouseLock(true); + if (this.scene.player !== null) { + this.scene.player.showUI(); + } + this.scene.cameras.main.setBackgroundColor(0x000000); + this.scene.player = this.scene.playerWalk; + this.scene.cam = this.scene.camWalk; + + $("#editorbox").hide(); + } + this.scene.player.dir.roll = 0; + + console.log("EDITOR " + (this.enabled ? "ENABLED" : "DISABLED")); + } + + toggleEditPoint(_ptNum) { + this.editPointsEnabled[_ptNum] = !this.editPointsEnabled[_ptNum]; + if (this.editPointsEnabled[_ptNum] === true) { + this.points[_ptNum].setTint(0x00e436); + } else { + this.points[_ptNum].setTint(0xff77a8); + } + } + + moveToolPoint(_pt, _pos) { + this.quad.points[_pt].x += _pos.x; + this.quad.points[_pt].y += _pos.y; + this.quad.points[_pt].z += _pos.z; + + this.quad.points[_pt].x = Math.round(this.quad.points[_pt].x / this.grid.size) * this.grid.size; + this.quad.points[_pt].y = Math.round(this.quad.points[_pt].y / this.grid.size) * this.grid.size; + this.quad.points[_pt].z = Math.round(this.quad.points[_pt].z / this.grid.size) * this.grid.size; + } + + duplicateQuad(_pos, _axis = [1, 1, 1]) { + let model = this.scene.geometryController.getModelById(this.quad.modelId); + if (model != null || model != undefined) { + model.addQuadFromData({ + type: this.quad.type, + texture: this.quad.texture, + frame: this.quad.frame, + position: { + x: this.quad.pos.x - this.model.pos.x, + y: this.quad.pos.y - this.model.pos.y, + z: this.quad.pos.z - this.model.pos.z, + }, + points: [ + { + x: this.quad.points[0].x * _axis[0], + y: this.quad.points[0].y * _axis[1], + z: this.quad.points[0].z * _axis[2], + }, { + x: this.quad.points[1].x * _axis[0], + y: this.quad.points[1].y * _axis[1], + z: this.quad.points[1].z * _axis[2], + }, { + x: this.quad.points[2].x * _axis[0], + y: this.quad.points[2].y * _axis[1], + z: this.quad.points[2].z * _axis[2], + }, { + x: this.quad.points[3].x * _axis[0], + y: this.quad.points[3].y * _axis[1], + z: this.quad.points[3].z * _axis[2], + } + ] + }); + + this.quad = this.editCollisions ? model.collisionData[model.collisionData.length - 1] : model.quadData[model.quadData.length - 1]; + } else { + console.log("couldnt find model!"); + } + //console.log(model); + } + + toggleEditCollisions() { + this.editCollisions = !this.editCollisions; + if (this.editCollisions === true) { + console.log("edit collisions enabled"); + } else { + console.log("edit collisions disabled"); + } + } + + togglePhotoMode() { + this.photoMode = !this.photoMode; + if (this.photoMode === true) { + this.scene.cameras.main.setBackgroundColor(0x000000); + for (let p of this.points) { + p.alpha = 0; + } + this.grid.txt.alpha = 0; + } else { + this.scene.cameras.main.setBackgroundColor(0x343444); + for (let p of this.points) { + p.alpha = 1; + } + this.grid.txt.alpha = 1; + } + } +} diff --git a/src/3d/geometryController.js b/src/3d/geometryController.js new file mode 100755 index 0000000..eee8b76 --- /dev/null +++ b/src/3d/geometryController.js @@ -0,0 +1,174 @@ +import PIP from "../additionalMath/pointInPolygon.js"; +import Model from "./model.js"; + +export default class GeometryController{ + constructor(_scene) { + this.scene = _scene; + this.geometryData = null; + this.geometry = []; + this.models = []; + this.collisionDistance = 128; + this.drawDistance = 256; + } + + update(_collCheckArr){ + for (let m of this.models) { + if(m.flags.update === true){ + m.update(); + + //if (Phaser.Math.Distance.Between(m.pos.x, m.pos.z, this.scene.player.pos.x, this.scene.player.pos.z) < this.collisionDistance) { + if(m.flags.collision === true){ + for (let q of m.collisionData){ + for(let c of _collCheckArr){ + let hitData = this.collide(q, c); + if(hitData.pt !== null){ + hitData.model = m; + c.hit.push(hitData); + } + } + } + } + //} + } + } + return _collCheckArr; + } + + draw(_from, _dir){ + for(let m of this.models){ + //m.flags.draw = false; + //if (Phaser.Math.Distance.Between(m.pos.x, m.pos.z, this.scene.player.pos.x, this.scene.player.pos.z) < this.drawDistance) { + if(m.flags.draw === true){ + m.draw(_from, _dir); + } + } + } + + drawFromMatrix(_from, _matrix){ + for(let m of this.models){ + if(m.flags.draw === true){ + m.drawFromMatrix(_from, _matrix); + } + } + } + + drawFromQuat(_from, _quat){ + for(let m of this.models){ + if(m.flags.draw === true){ + m.drawFromQuat(_from, _quat); + } + } + } + + collide(_quad, _collChecker){ + let h = { + pt: _quad.getIntersect(_collChecker.pos.x, _collChecker.pos.y, _collChecker.pos.z, _collChecker.dir.x, _collChecker.dir.y, _collChecker.dir.z), + quad: _quad, + model: null + } + return h; + } + + getQuadsFromScreenspaceAt(_x, _y, _checkCollisionMask){ + let hits = []; + for (let m of this.models) { + if(m.flags.ignoreRaycast === false){ + if(_checkCollisionMask === false){ + for (let q of m.quadData) { + if(q.depth < 0){ + if (pip.pointInPolygon( + [_x, _y], + [ + [q.screenCoords[0].x, q.screenCoords[0].y], + [q.screenCoords[1].x, q.screenCoords[1].y], + [q.screenCoords[2].x, q.screenCoords[2].y] + ] + )){ + hits.push(q); + }else if(pip.pointInPolygon( + [_x, _y], + [ + [q.screenCoords[0].x, q.screenCoords[0].y], + [q.screenCoords[2].x, q.screenCoords[2].y], + [q.screenCoords[3].x, q.screenCoords[3].y] + ] + )){ + hits.push(q); + } + } + } + }else{ + for (let q of m.collisionData) { + if (q.depth < 0) { + if (pip.pointInPolygon( + [_x, _y], + [ + [q.screenCoords[0].x, q.screenCoords[0].y], + [q.screenCoords[1].x, q.screenCoords[1].y], + [q.screenCoords[2].x, q.screenCoords[2].y] + ] + )) { + hits.push(q); + } else if (pip.pointInPolygon( + [_x, _y], + [ + [q.screenCoords[0].x, q.screenCoords[0].y], + [q.screenCoords[2].x, q.screenCoords[2].y], + [q.screenCoords[3].x, q.screenCoords[3].y] + ] + )) { + hits.push(q); + } + } + } + } + } + } + return hits; + } + + getModelById(_id){ + /*let arr = this.models.filter((m) => m.id === _id); + if(arr !== null || arr.length > 0){ + return arr[0]; + }else{ + console.error("no model with id " + _id + " found"); + return null; + }*/ + return this.models.find((m) => m.id === _id); + } + + logLevel() { + //TODO make object and array of each model and its quads + /*for (let m of this.models) { + m.draw(_from, _dir); + }*/ + } + + loadData(_data){ + + } + + loadModel(_id, _modelDataJson, _pos){ + this.models.push( + new Model(this.scene, this, _id, _modelDataJson, _pos) + ); + return this.models[this.models.length-1]; + } + + destroyModels(){ + for(let m of this.models){ + m.destroy(); + } + this.models = []; + } + + destroyModelById(_id){ + for(let i = this.models.length - 1 ; i >= 0 ; i--){ + if(this.models[i].id === _id){ + this.models[i].destroy(); + this.models.splice(i, 1); + } + } + } +} \ No newline at end of file diff --git a/src/3d/groups/grpElevator.js b/src/3d/groups/grpElevator.js new file mode 100644 index 0000000..588c18a --- /dev/null +++ b/src/3d/groups/grpElevator.js @@ -0,0 +1,145 @@ +import PanelElevator from "../../ui/panelElevator.js"; + +export default class GroupElevator{ + constructor(_scene, _level, _pos){ + this.scene = _scene; + this.level = _level; + + this.pos = { + x: _pos.x, + y: _pos.y, + z: _pos.z + }; + + this.base = this.scene.geometryController.loadModel("elevator base", "modElevatorBase", { x: this.pos.x, y: this.pos.y, z: this.pos.z }); + this.base.flags.draw = true; + + this.button = this.scene.geometryController.loadModel("elevator button", "modElevatorButton", { x: this.pos.x, y: this.pos.y, z: this.pos.z }); + this.button.flags.draw = true; + this.button.data = { + open: true + } + this.button.interactable = true; + this.button.interact = () => { + if(this.scene.player.panel === null){ + //todo: fix auto clicking on back when it was oopen once and the mosue is still on the back button position (locked) + /*if(this.scene.input.mouse.locked === true){ + this.scene.hand.setMouseLock(false); + }*/ + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelElevator(this.scene); + } + } + + this.doorRight = this.scene.geometryController.loadModel("doorRight", "modElevatorDoor", { + x: _pos.x + 8, + y: _pos.y, + z: _pos.z + 30 + }); + this.doorLeft = this.scene.geometryController.loadModel("doorLeft", "modElevatorDoor", { + x: _pos.x - 8, + y: _pos.y, + z: _pos.z + 30 + }); + + let _this = this; + this.doorRight.data = { + positions: [ + _this.doorRight.pos.x, + _this.doorRight.pos.x + 12 + ], + currentPosition: 1 + } + this.doorLeft.data = { + positions: [ + _this.doorLeft.pos.x, + _this.doorLeft.pos.x - 12 + ], + currentPosition: 1 + } + this.doorRight.action = () => { + _this.doorRight.mover.isMoving = true; + _this.doorRight.mover.target.pos.spd = 0.1; + _this.doorRight.mover.target.pos.x = _this.doorRight.data.positions[_this.doorRight.data.currentPosition]; + _this.doorLeft.mover.isMoving = true; + _this.doorLeft.mover.target.pos.spd = 0.1; + _this.doorLeft.mover.target.pos.x = _this.doorLeft.data.positions[_this.doorLeft.data.currentPosition]; + }; + this.doorLeft.action = () => { + _this.doorRight.action(); + } + this.doorRight.action(); + + this.flags = { + draw: false + } + } + + update(){ + + } + + setPosition(_pos){ + let offset = { + x: _pos.x - this.pos.x , + y: _pos.y - this.pos.y , + z: _pos.z - this.pos.z + } + this.pos.x += offset.x; + this.pos.y += offset.y; + this.pos.z += offset.z; + + this.base.jumpToPosition({ + x: this.base.pos.x + offset.x, + y: this.base.pos.y + offset.y, + z: this.base.pos.z + offset.z + }, true); + this.button.jumpToPosition({ + x: this.button.pos.x + offset.x, + y: this.button.pos.y + offset.y, + z: this.button.pos.z + offset.z + }, true); + this.doorLeft.jumpToPosition({ + x: this.doorLeft.pos.x + offset.x, + y: this.doorLeft.pos.y + offset.y, + z: this.doorLeft.pos.z + offset.z + }, true); + this.doorRight.jumpToPosition({ + x: this.doorRight.pos.x + offset.x, + y: this.doorRight.pos.y + offset.y, + z: this.doorRight.pos.z + offset.z + }, true); + } + + setDoor(_bool){ + let p = 0; + if(_bool === true){ + p = 1; + } + this.doorRight.action = () => { + this.doorRight.mover.isMoving = true; + this.doorRight.mover.target.pos.spd = 0.1; + this.doorRight.mover.target.pos.x = _this.doorRight.data.positions[p]; + this.doorLeft.mover.isMoving = true; + this.doorLeft.mover.target.pos.spd = 0.1; + this.doorLeft.mover.target.pos.x = _this.doorLeft.data.positions[p]; + }; + this.doorLeft.action = () => { + this.doorRight.action(); + } + } + + setDraw(_bool){ + this.base.flags.draw = _bool; + this.doorRight.flags.draw = _bool; + this.doorLeft.flags.draw = _bool; + this.button.flags.draw = _bool; + + this.flags.draw = _bool; + } + + destroy(){ + + } +} \ No newline at end of file diff --git a/src/3d/levels/___lvlEmpty.js b/src/3d/levels/___lvlEmpty.js new file mode 100755 index 0000000..f848fd2 --- /dev/null +++ b/src/3d/levels/___lvlEmpty.js @@ -0,0 +1,18 @@ +import PanelWelcome from "../../ui/panelWelcome.js"; + +export default class LevelEmpty00{ + constructor(_scene){ + this.scene = _scene; + + this.ref = this.scene.geometryController.loadModel("levelOrigin", "modDebugTile", { x: 0, y: 0, z: 0 }); + this.ref.flags.draw = true; + } + + update(){ + + } + + destroy() { + + } +} \ No newline at end of file diff --git a/src/3d/levels/lvlChurch00.js b/src/3d/levels/lvlChurch00.js new file mode 100644 index 0000000..945ce6a --- /dev/null +++ b/src/3d/levels/lvlChurch00.js @@ -0,0 +1,244 @@ +import PanelPlayerComputer from "../../ui/panelPlayerComputer.js"; + +export default class LevelChurch00 { + constructor(_scene, _params) { + this.scene = _scene; + this.params = _params; + + this.scene.player = this.scene.playerWalk; + this.scene.cam = this.scene.camWalk; + + //this.scene.player.dir.pitch = 0; + + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.dance = { + anim: 0, + step: 0 + } + + this.corner = null; + this.church = null; + this.ship = null; + this.computer = null; + this.stationHallway = null; + this.stationLeft = null; + this.stationRight = null; + + this.triggerCorner = null; + this.triggerChurch = null; + + this.charRahy = this.scene.geometryController.loadModel("char rahy", "modCharacterDefaultHuman", { x: 886, y: 64, z: 176 }); + this.charRahy.quadData[0].setTexture("charSheetRahy", "rahyDanceFrame0000"); + this.charRahy.atlas = "charSheetRahy"; + this.charRahy.atlas8wayFrame = "rahyDanceFrame000"; + this.charRahy.scale({ x: 1.5, y: 1, z: 1 }); + this.charRahy.flags.draw = true; + this.charRahy.lookDir.yaw = Math.random() * (Math.PI * 2); + this.charRahy.setDrawMode(DRAWMODE.BILLBOARD); + this.charRahy.flags.is8way = true; + this.charRahy.flags.usesAtlas = true; + this.charRahy.depthMod = 16; + + this.charFoxxy = this.scene.geometryController.loadModel("char foxxy", "modCharacterDefaultHuman", { x: 887, y: 64, z: 242 }); + this.charFoxxy.quadData[0].setTexture("charSheetFoxxy", "foxxyDanceFrame0000"); + this.charFoxxy.atlas = "charSheetFoxxy"; + this.charFoxxy.atlas8wayFrame = "foxxyDanceFrame000"; + this.charFoxxy.scale({ x: 1.1, y: 1, z: 1 }); + this.charFoxxy.flags.draw = true; + this.charFoxxy.lookDir.yaw = Math.random() * (Math.PI * 2); + this.charFoxxy.setDrawMode(DRAWMODE.BILLBOARD); + this.charFoxxy.flags.is8way = true; + this.charFoxxy.flags.usesAtlas = true; + this.charFoxxy.depthMod = 16; + + this.charGlaze = this.scene.geometryController.loadModel("char glaze", "modCharacterDefaultHuman", { x: 861, y: 64, z: 207 }); + this.charGlaze.quadData[0].setTexture("charSheetGlaze", "glazeDanceFrame0000"); + this.charGlaze.atlas = "charSheetGlaze"; + this.charGlaze.atlas8wayFrame = "glazeDanceFrame000"; + this.charGlaze.scale({ x: 1.5, y: 1, z: 1 }); + this.charGlaze.flags.draw = true; + this.charGlaze.lookDir.yaw = Math.random() * (Math.PI * 2); + this.charGlaze.setDrawMode(DRAWMODE.BILLBOARD); + this.charGlaze.flags.is8way = true; + this.charGlaze.flags.usesAtlas = true; + this.charGlaze.depthMod = 16; + + this.charHog = this.scene.geometryController.loadModel("char hog", "modCharacterDefaultHuman", { x: 916, y: 64, z: 187 }); + this.charHog.quadData[0].setTexture("charSheetHog", "hogStandIdle0000"); + this.charHog.atlas = "charSheetHog"; + this.charHog.atlas8wayFrame = "hogStandIdle000"; + this.charHog.scale({ x: 1.5, y: 1, z: 1 }); + this.charHog.flags.draw = true; + this.charHog.lookDir.yaw = Math.random() * (Math.PI * 2); + this.charHog.setDrawMode(DRAWMODE.BILLBOARD); + this.charHog.flags.is8way = true; + this.charHog.flags.usesAtlas = true; + this.charHog.depthMod = 16; + + + this.charGuard = this.scene.geometryController.loadModel("char maleguard", "modCharacterDefaultHuman", { x: 865, y: 64, z: 320 }); + this.charGuard.quadData[0].setTexture("charSheetMaleguard", "maleguardStandIdle0000"); + this.charGuard.atlas = "charSheetMaleguard"; + this.charGuard.atlas8wayFrame = "maleguardStandIdle000"; + this.charGuard.scale({ x: 1.0, y: 1, z: 1 }); + this.charGuard.flags.draw = true; + this.charGuard.lookDir.yaw = Math.PI; + this.charGuard.setDrawMode(DRAWMODE.BILLBOARD); + this.charGuard.flags.is8way = true; + this.charGuard.flags.usesAtlas = true; + this.charGuard.depthMod = 16; + + this.josef = this.scene.geometryController.loadModel("char josef", "modCharacterDefaultHuman", { x: 886, y: 64, z: 374 }); + this.josef.quadData[0].setTexture("charSheetJosef", "josefStandIdle0000"); + this.josef.atlas = "charSheetJosef"; + this.josef.atlas8wayFrame = "josefStandIdle000"; + this.josef.scale({ x: 1.5, y: 1, z: 1 }); + this.josef.flags.draw = true; + this.josef.lookDir.yaw = Math.PI; + this.josef.setDrawMode(DRAWMODE.BILLBOARD); + this.josef.flags.is8way = true; + this.josef.flags.usesAtlas = true; + this.josef.depthMod = 16; + + this.booker = this.scene.geometryController.loadModel("char booker", "modCharacterDefaultHuman", { x: 887, y: 64, z: 278 }); + this.booker.quadData[0].setTexture("charSheetBooker", "bookerStandIdle0000"); + this.booker.atlas = "charSheetBooker"; + this.booker.atlas8wayFrame = "bookerStandIdle000"; + this.booker.scale({ x: 1.1, y: 1, z: 1 }); + this.booker.flags.draw = true; + this.booker.lookDir.yaw = Math.PI; + this.booker.setDrawMode(DRAWMODE.BILLBOARD); + this.booker.flags.is8way = true; + this.booker.flags.usesAtlas = true; + this.booker.depthMod = 16; + + this.createStation(); + this.createCorner(); + } + + update() { + this.dance.step += 1 * this.scene.dt; + this.dance.anim = Math.floor((this.dance.step * 0.02) % 2); + //this.charRahy.atlas8wayFrame = "rahyDanceFrame0" + String(this.dance.anim) + "0"; + this.charRahy.atlas8wayFrame = "rahyDanceFrame0" + String(Math.floor((this.dance.step * 0.02) % 2)) + "0"; + this.charRahy.lookDir.yaw += Math.PI * 0.0025; + + this.charFoxxy.atlas8wayFrame = "foxxyDanceFrame0" + String(Math.floor((this.dance.step * 0.02) % 2)) + "0"; + this.charFoxxy.lookDir.yaw += Math.PI * 0.0025; + + this.charGlaze.atlas8wayFrame = "glazeDanceFrame0" + String(Math.floor((this.dance.step * 0.02) % 2)) + "0"; + this.charGlaze.lookDir.yaw += Math.PI * 0.0025; + + this.charHog.atlas8wayFrame = "hogStandIdle0" + String(this.dance.anim) + "0"; + this.charHog.lookDir.yaw += Math.PI * 0.025; + } + + createStation() { + this.stationHallway = this.scene.geometryController.loadModel("station hallway", "modMetroStationCorridorT", { x: 0, y: 0, z: 64 }); + this.stationHallway.flags.draw = true; + + this.stationLeft = this.scene.geometryController.loadModel("station left", "modMetroStationDreamRight", { x: -256 + 12, y: -64 + 24, z: 432 }); + this.stationLeft.flags.draw = true; + this.stationLeft.rotateAroundAxis([0, -1, 0], Math.PI) + + //this.stationRight = this.scene.geometryController.loadModel("station right", "modMetroStationDreamRight", { x: 256-12, y: -64+24, z: 128+48-192 }); + //this.stationRight.flags.draw = true; + } + + destroyStation() { + this.scene.geometryController.destroyModelById(this.stationHallway.id); + this.scene.geometryController.destroyModelById(this.stationLeft.id); + //this.scene.geometryController.destroyModelById(this.stationRight.id); + this.stationHallway = null; + this.stationLeft = null; + //this.stationRight = null; + } + + createCorner() { + this.corner = this.scene.geometryController.loadModel("station corner", "modMetroStationArcadeCorner", { x: 120, y: 0, z: 208 }) + this.corner.flags.draw = true; + + //triggers + this.triggerChurch = this.scene.geometryController.loadModel("trigger delete / spawn room", "modTriggerWall1x1", { x: 322, y: 44, z: 209 }); + this.triggerChurch.scale({ x: 44, y: 64, z: 1 }); + this.triggerChurch.rotateAroundAxis([0, -1, 0], Math.PI * 0.5); + this.triggerChurch.flags.draw = true; + this.triggerChurch.trigger.isTrigger = true; + this.triggerChurch.trigger.onEnter = () => { + if (this.church === null) { + this.createChurch(); + this.destroyStation(); + } else { + this.destroyChurch(); + this.createStation(); + } + } + } + + destroyCorner() { + this.scene.geometryController.destroyModelById(this.corner.id); + this.scene.geometryController.destroyModelById(this.triggerChurch.id); + this.corner = null; + this.triggerChurch = null; + } + + createChurch() { + this.church = this.scene.geometryController.loadModel("arcade room 00", "modMetroStationArcadeRoom00", { x: 448, y: 64, z: 208 }) + this.church.flags.draw = true; + + this.ship = this.scene.geometryController.loadModel("ship", "modHoverCarWipeOutStyle", { x: 1092, y: 48 - 8 - 80, z: 208 }); + this.ship.flags.draw = true; + this.ship.deleteQuad(this.ship.quadData[this.ship.quadData.length - 1]); + this.ship.deleteQuad(this.ship.quadData[this.ship.quadData.length - 1]); + this.ship.deleteQuad(this.ship.quadData[this.ship.quadData.length - 1]); + this.ship.deleteQuad(this.ship.quadData[this.ship.quadData.length - 1]); + this.ship.rotateAroundAxis([0, -1, 0], Math.PI * -0.5) + this.ship.rotateAroundAxis([0, 0, 1], Math.PI * 0.4) + + this.computer = this.scene.geometryController.loadModel("apartement computer", "modComputer", { x: 1044, y: 48/*-12*/, z: 160 }); + this.computer.rotateAroundAxis([0, -1, 0], Math.PI * 0.76) + this.computer.depthMod = 20; + this.computer.flags.draw = true; + this.computer.data = { + useText: "use computer", + useRadius: 48 + } + this.computer.interactable = true; + this.computer.interact = () => { + if (this.scene.player.panel === null) { + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelPlayerComputer(this.scene); + } + } + + //triggers + this.triggerCorner = this.scene.geometryController.loadModel("trigger delete / spawn corner", "modTriggerWall1x1", { x: 531, y: 63, z: 209 }); + this.triggerCorner.scale({ x: 44, y: 64, z: 1 }); + this.triggerCorner.translateAndRotate({ x: 0, y: 0, z: 0 }, { yaw: Math.PI * 0.5, pitch: 0, roll: 0 }); + this.triggerCorner.flags.draw = true; + this.triggerCorner.trigger.isTrigger = true; + this.triggerCorner.trigger.onEnter = () => { + if (this.corner === null) { + this.createCorner(); + } else { + this.destroyCorner(); + } + } + } + + destroyChurch() { + this.scene.geometryController.destroyModelById(this.church.id); + this.scene.geometryController.destroyModelById(this.ship.id); + this.scene.geometryController.destroyModelById(this.computer.id); + + this.church = null; + this.ship = null; + this.computer = null; + } + + destroy() { + + } +} diff --git a/src/3d/levels/lvlChurch00old.js b/src/3d/levels/lvlChurch00old.js new file mode 100644 index 0000000..8c1931a --- /dev/null +++ b/src/3d/levels/lvlChurch00old.js @@ -0,0 +1,364 @@ +import PanelMetroDestinations from "../../ui/panelMetroDestinations.js"; +import PanelControlOptions from "../../ui/panelControlOptions.js"; +import PanelLevelname from "../../ui/panelLevelname.js"; +import PanelArcadeItch from "../../ui/panelArcadeItch.js"; + +export default class LevelArcade00 { + constructor(_scene) { + this.scene = _scene; + + //this.scene.player.jumpToPosition({ x: 26, y: 0, z: -22 }); + + //this.point = this.scene.geometryController.loadModel("point", "modDebugTile", { x: 0, y: 0, z: 100 }); + //this.point.flags.draw = true; + + this.speed = 1; + this.exterior = 0; //0 = false, 1 = true, 2 = dont bother anymore + + this.states = { + braking: 0, + standing: 1, + accelerating: 2 + } + this.state = this.states.braking; + + + //INIT STUFF + this.metrocars = []; + this.arches = []; + this.station = null; + this.corner = null; + this.room = null; + this.josef = null; + this.automats = []; + this.triggersSwitchMetro = []; + this.triggerRoom = null; + this.triggerTrain = null; + this.triggerCorner = null; + + this.createCorner(); + this.createTrain(); + } + + update() { + switch (this.state) { + case this.states.braking: + for (let m of this.metrocars) { + m.vibro += 0.02 * this.speed; + m.model.jumpToRotation({ yaw: m.rattle.yaw, pitch: m.rattle.pitch + (Math.sin(m.vibro) * 0.0051), roll: m.rattle.roll + (Math.sin(m.vibro) * 0.051) }) + m.model.translateAndRotate({ x: 0, y: 0, z: 10 * this.speed }); + } + + this.scene.player.pos.z += 10 * this.speed; + + if (this.speed > 0) { + this.speed -= 0.0025; + } else { + this.speed = 0; + for (let [i, m] of this.metrocars.entries()) { + let pos = { x: m.model.pos.x, y: m.model.pos.y, z: m.model.pos.z }; + //m.model.jumpToRotation({ yaw: 0, pitch: 0, roll: 0 }) + + let txtMod = ""; + if (i === 1 || i === 0) { txtMod = "NoDoors"; } + if (i === 3) { txtMod = "Front" } + if (i === 4) { txtMod = "Back" } + this.scene.geometryController.destroyModelById(m.model.id); + m.model = this.scene.geometryController.loadModel("Metrocar Interior" + String(i), "modMetroCarInterior" + txtMod, { x: pos.x, y: pos.y, z: pos.z }); + m.model.flags.draw = true; + } + + for (let a of this.arches) { + a.flags.draw = false; + } + + this.state = this.states.standing; + + if (this.scene.player.panel === null) { + this.scene.player.panel = new PanelLevelname(this.scene, "ARCADE"); + } + } + break; + case this.states.standing: + + break; + case this.states.accelerating: + for (let m of this.metrocars) { + m.vibro += 0.02 * this.speed; + m.model.jumpToRotation({ yaw: m.rattle.yaw, pitch: m.rattle.pitch + (Math.sin(m.vibro) * 0.0051), roll: m.rattle.roll + (Math.sin(m.vibro) * 0.051) }) + m.model.translateAndRotate({ x: 0, y: 0, z: 10 * this.speed }); + } + + this.scene.player.pos.z += 10 * this.speed; + + if (this.speed < 1) { + this.speed += 0.0025; + } else { + this.speed = 1; + + this.destroyCorner(); + this.destroyTrain(); + + if (this.scene.player.panel === null) { + this.scene.player.panel = new PanelLevelname(this.scene, "NAVIGATION"); + } + let p = { + x: this.scene.player.pos.x, + y: this.scene.player.pos.y, + z: this.scene.player.pos.z + }; + this.scene.player.jumpToPosition({ x: p.x, y: p.y, z: p.z - (3957.05365 + 66) }); + this.scene.loadLevel("lobby00", { fromStation: true }); + } + break; + default: + break; + } + } + + destroy() { + + } + + createCorner() { + this.corner = this.scene.geometryController.loadModel("station corner", "modMetroStationArcadeCorner", { x: 128, y: 0, z: 1829 }) + this.corner.flags.draw = true; + + //triggers + this.triggerRoom = this.scene.geometryController.loadModel("trigger delete / spawn room", "modTriggerWall1x1", { x: 330, y: 44, z: 1828 }); + this.triggerRoom.scale({ x: 44, y: 64, z: 1 }); + this.triggerRoom.translateAndRotate({ x: 0, y: 0, z: 0 }, { yaw: Math.PI * 0.5, pitch: 0, roll: 0 }); + //this.triggerRoom.flags.draw = true; + this.triggerRoom.trigger.isTrigger = true; + this.triggerRoom.trigger.onEnter = () => { + if (this.room === null) { + this.createRoom(); + } else { + this.destroyRoom(); + } + } + + this.triggerTrain = this.scene.geometryController.loadModel("trigger delete / spawn metro", "modTriggerWall1x1", { x: 322, y: 44, z: 1828 }); + this.triggerTrain.scale({ x: 44, y: 64, z: 1 }); + this.triggerTrain.translateAndRotate({ x: 0, y: 0, z: 0 }, { yaw: Math.PI * 0.5, pitch: 0, roll: 0 }); + //this.triggerTrain.flags.draw = true; + this.triggerTrain.trigger.isTrigger = true; + this.triggerTrain.trigger.onEnter = () => { + if (this.station === null) { + this.createTrain(false); + } else { + this.destroyTrain(); + } + } + } + + destroyCorner() { + this.scene.geometryController.destroyModelById(this.corner.id); + this.scene.geometryController.destroyModelById(this.triggerRoom.id); + this.scene.geometryController.destroyModelById(this.triggerTrain.id); + this.corner = null; + } + + createTrain(_init = true) { + //create and position interior cars + let txtInit = ["modMetroCarInterior", "modMetroCarInterior", "modMetroCarInterior", "modMetroCarInteriorFront", "modMetroCarInteriorBack"]; + let txtMod = ["modMetroCarExteriorNoDoors", "modMetroCarExteriorNoDoors", "modMetroCarExterior", "modMetroCarExterior", "modMetroCarExterior"]; + + this.metrocars.push({ + model: this.scene.geometryController.loadModel("Metrocar" + (_init === true ? "Interior" : "Exterior") + "3", _init === true ? txtInit[0] : txtMod[0], { x: 0, y: 0, z: (_init === false ? 2005 : 0) - 132 - 280 }), // NoDoors + rattle: { yaw: 0, pitch: 0, roll: 0 }, + vibro: Math.random() + }); + this.metrocars.push({ + model: this.scene.geometryController.loadModel("Metrocar" + (_init === true ? "Interior" : "Exterior") + "2", _init === true ? txtInit[1] : txtMod[1], { x: 0, y: 0, z: (_init === false ? 2005 : 0) - 132 }), // NoDoors + rattle: { yaw: 0, pitch: 0, roll: 0 }, + vibro: Math.random() + }); + this.metrocars.push({ + model: this.scene.geometryController.loadModel("Metrocar" + (_init === true ? "Interior" : "Exterior") + "1", _init === true ? txtInit[2] : txtMod[2], { x: 0, y: 0, z: (_init === false ? 2005 : 0) - 132 + 280 }), + rattle: { yaw: 0, pitch: 0, roll: 0 }, + vibro: Math.random() + }); + this.metrocars.push({ + model: this.scene.geometryController.loadModel("Metrocar" + (_init === true ? "Interior" : "Exterior") + "0", _init === true ? txtInit[3] : txtMod[3], { x: 0, y: 0, z: (_init === false ? 2005 : 0) - 132 + 280 + 280 }), + rattle: { yaw: 0, pitch: 0, roll: 0 }, + vibro: Math.random() + }); + this.metrocars.push({ + model: this.scene.geometryController.loadModel("Metrocar" + (_init === true ? "Interior" : "Exterior") + "4", _init === true ? txtInit[4] : txtMod[4], { x: 0, y: 0, z: (_init === false ? 2005 : 0) - 132 - 280 - 280 }), + rattle: { yaw: 0, pitch: 0, roll: 0 }, + vibro: Math.random() + }); + + //give new origin to all cars + for (let [i, m] of this.metrocars.entries()) { + if (i < 4) { + for (let q of m.model.quadData) { + q.pos.x = m.model.pos.x; + q.pos.y = m.model.pos.y; + q.pos.z = m.model.pos.z + 66; + } + for (let q of m.model.collisionData) { + q.pos.x = m.model.pos.x; + q.pos.y = m.model.pos.y; + q.pos.z = m.model.pos.z + 66; + } + } + m.model.jumpToRotation(m.rattle) + m.model.flags.draw = true; + } + + + for (let i = -1; i < 4; i++) { + this.arches.push(this.scene.geometryController.loadModel("lightarch", "modMetroTunnelLightarch", { x: 0, y: 16, z: 0 })) + this.arches[this.arches.length - 1].translateAndRotate({ x: 0, y: 0, z: 280 * i }); + this.arches[this.arches.length - 1].flags.draw = true; + this.arches[this.arches.length - 1].flags.collision = false; + + } + + this.station = this.scene.geometryController.loadModel("station Arcade", "modMetroStationArcade", { x: 0, y: 16, z: 2005 }) + this.station.flags.draw = true; + + //TRIGGER + this.triggersSwitchMetro.push(this.scene.geometryController.loadModel("trigger switch metro model 0", "modTriggerWall1x1", { x: 42, y: 0, z: 2005 - 66 })); + this.triggersSwitchMetro.push(this.scene.geometryController.loadModel("trigger switch metro model 1", "modTriggerWall1x1", { x: 42, y: 0, z: 2005 + 66 })); + this.triggersSwitchMetro.push(this.scene.geometryController.loadModel("trigger switch metro model 2", "modTriggerWall1x1", { x: 42, y: 0, z: 2005 - 280 - 66 })); + this.triggersSwitchMetro.push(this.scene.geometryController.loadModel("trigger switch metro model 3", "modTriggerWall1x1", { x: 42, y: 0, z: 2005 - 280 + 66 })); + for (let t of this.triggersSwitchMetro) { + t.scale({ x: 16, y: 32, z: 1 }); + t.translateAndRotate({ x: 0, y: 0, z: 0 }, { yaw: Math.PI * 0.5, pitch: 0, roll: 0 }); + if (_init === false) { + t.translateAndRotate({ x: -20, y: 0, z: 0 }); + } + //t.flags.draw = true; + t.trigger.isTrigger = true; + t.trigger.onEnter = () => { + if (this.exterior === 0) { + this.exterior = 1; + + for (let [i, m] of this.metrocars.entries()) { + let pos = { x: m.model.pos.x, y: m.model.pos.y, z: m.model.pos.z }; + m.rattle.yaw = m.model.dir.yaw; + m.rattle.pitch = m.model.dir.pitch; + m.rattle.roll = m.model.dir.roll; + this.scene.geometryController.destroyModelById(m.model.id); + + let txtMod = ""; + if (i === 1 || i === 0) { txtMod = "NoDoors"; } + m.model = this.scene.geometryController.loadModel("Metrocar Exterior" + String(i), "modMetroCarExterior" + txtMod, { x: pos.x, y: pos.y, z: pos.z }); + m.model.flags.draw = true; + } + + for (let tt of this.triggersSwitchMetro) { + tt.translateAndRotate({ x: -20, y: 0, z: 0 }) + } + console.log("load exterior of metro") + } else if (this.exterior === 1) { + this.exterior = 2; + + for (let [i, m] of this.metrocars.entries()) { + let pos = { x: m.model.pos.x, y: m.model.pos.y, z: m.model.pos.z }; + m.rattle.yaw = m.model.dir.yaw; + m.rattle.pitch = m.model.dir.pitch; + m.rattle.roll = m.model.dir.roll; + this.scene.geometryController.destroyModelById(m.model.id); + + let txtMod = ""; + if (i === 3) { txtMod = "Front" } + if (i === 4) { txtMod = "Back" } + m.model = this.scene.geometryController.loadModel("Metrocar Interior" + String(i), "modMetroCarInterior" + txtMod, { x: pos.x, y: pos.y, z: pos.z }); + m.model.flags.draw = true; + } + + //delete yourself to prevent spawning ext whiel inside + for (let t of this.triggersSwitchMetro) { + this.scene.geometryController.destroyModelById(t.id); + } + + this.state = this.states.accelerating; + } + } + } + + + + } + + destroyTrain() { + for (let m of this.metrocars) { + this.scene.geometryController.destroyModelById(m.model.id); + m.model = null; + } + this.metrocars = []; + + for (let a of this.arches) { + this.scene.geometryController.destroyModelById(a.id); + } + this.arches = []; + + for (let t of this.triggersSwitchMetro) { + this.scene.geometryController.destroyModelById(t.id); + } + this.triggersSwitchMetro = []; + + this.scene.geometryController.destroyModelById(this.station.id); + this.station = null; + + } + + createRoom() { + this.room = this.scene.geometryController.loadModel("arcade room 00", "modMetroStationArcadeRoom00", { x: 456, y: 64, z: 1829 }) + this.room.flags.draw = true; + + this.automats.push(this.scene.geometryController.loadModel("automat main", "modArcadeAutomat", { x: 1080, y: 48, z: 1829 })); + this.automats[0].translateAndRotate({ x: 0, y: 0, z: 0 }, { yaw: Math.PI, pitch: 0, roll: 0 }); + this.automats.push(this.scene.geometryController.loadModel("automat main screen", "modArcadeAutomatScreen", { x: 1080, y: 48, z: 1829 })); + this.automats[1].translateAndRotate({ x: 0, y: 0, z: 0 }, { yaw: Math.PI, pitch: 0, roll: 0 }); + this.automats[1].flags.draw = true; + this.automats[1].flags.collision = false; + this.automats[1].data = { + useText: "use arcade machine" + } + this.automats[1].interactable = true; + this.automats[1].interact = () => { + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelArcadeItch(this.scene); + } + for (let a of this.automats) { + a.flags.draw = true; + } + + this.josef = this.scene.geometryController.loadModel("character Josef", "modCharacterTestJosef", { x: 592, y: -32, z: 1829 }); + this.josef.flags.draw = true; + this.josef.setDrawMode(DRAWMODE.BILLBOARD); + + //triggers + this.triggerCorner = this.scene.geometryController.loadModel("trigger delete / spawn corner", "modTriggerWall1x1", { x: 539, y: 63, z: 1828 }); + this.triggerCorner.scale({ x: 44, y: 64, z: 1 }); + this.triggerCorner.translateAndRotate({ x: 0, y: 0, z: 0 }, { yaw: Math.PI * 0.5, pitch: 0, roll: 0 }); + //this.triggerCorner.flags.draw = true; + this.triggerCorner.trigger.isTrigger = true; + this.triggerCorner.trigger.onEnter = () => { + if (this.corner === null) { + this.createCorner(); + } else { + this.destroyCorner(); + } + } + } + + destroyRoom() { + this.scene.geometryController.destroyModelById(this.room.id); + this.scene.geometryController.destroyModelById(this.josef.id); + + for (let a of this.automats) { + this.scene.geometryController.destroyModelById(a.id); + } + this.automats = []; + + this.room = null; + } + + +} diff --git a/src/3d/levels/lvlDream00.js b/src/3d/levels/lvlDream00.js new file mode 100755 index 0000000..a15e921 --- /dev/null +++ b/src/3d/levels/lvlDream00.js @@ -0,0 +1,844 @@ +import GroupElevator from "../groups/grpElevator.js"; +//todo: remove this link after completing the station model IMPORTANT +import DataQuad from "../dataQuad.js"; +import PanelStopTrain from "../../ui/panelStopTrain.js"; +import ShipManager from "../racing/shipManager.js"; +import TrackBuilder from "../racing/trackBuilder.js"; + +export default class LevelDream00 { + constructor(_scene) { + this.scene = _scene; + + this.scene.player = this.scene.playerWalk; + this.scene.cam = this.scene.camWalk; + this.scene.cam.shadeModTarget = 0.125; + this.scene.cam.shadeMod = 0.001; + this.scene.cam.shadeModTarget = 0.04; + + //this.scene.player.dir.pitch = 0; + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + //fake track for the moving ships + this.trackBuilder = new TrackBuilder(this.scene, this); + this.aiShips = []; + this.aiShips.push(new ShipManager(this.scene, this, 0, false, false)); + this.aiShips.push(new ShipManager(this.scene, this, 1, false, false)); + this.trackBuilder.loadTrack(1997); + this.aiShips[1].setShipColor("Yellow"); + for (let ai of this.aiShips) { + ai.gondula.jumpToPosition({ x: -244, y: -40, z: -1280 }); + ai.shipAnchor.jumpToPosition({ x: -244, y: -40, z: -1280 }); + ai.ship.jumpToPosition({ x: -244, y: -40, z: -1280 }); + for (let l of ai.lensflares) { + l.jumpToPosition({ x: -244, y: -40, z: -1280 }); + } + for (let s of ai.swooshOrigins) { + s.jumpToPosition({ x: 0, y: 128, z: 0 }); + } + + ai.flightRadius = 56; + ai.ship.scale({ x: 0.75, y: 0.75, z: 0.75 }); + ai.setDraw(false); + ai.speed = 6; + } + this.aiShips[0].gondula.rotateAroundAxis([0, 0, 1], Math.PI); + this.aiShips[0].gondula.jumpToPosition({ x: -244, y: -40, z: -1280 - 256 }); + + this.elevator = new GroupElevator(this.scene, this, { x: 0, y: 0, z: 0 }); + this.elevator.setDraw(true); + + this.stationHallway = this.scene.geometryController.loadModel("station hallway", "modMetroStationCorridorT", { x: 0, y: 0, z: 64 }); + this.stationHallway.flags.draw = true; + + this.stationLeft = this.scene.geometryController.loadModel("station left", "modMetroStationDream", { x: -256 + 12, y: -64 + 24, z: 128 + 48 }); + this.stationLeft.flags.draw = true; + + this.stationRight = this.scene.geometryController.loadModel("station right", "modMetroStationDreamRight", { x: 256 - 12, y: -64 + 24, z: 128 + 48 - 192 }); + this.stationRight.flags.draw = true; + + this.metroStationCar = this.scene.geometryController.loadModel("station to car", "modMetroCarToStation", { x: -148, y: -64, z: 1006 }); + this.metroStationCar.flags.draw = true; + + this.metroStationCarMid = this.scene.geometryController.loadModel("station to car mid", "modMetroCarInterior", { x: -148, y: -64, z: 1006 + 280 }); + //this.metroStationCarMid.flags.draw = true; + + this.metroStationCarFront = this.scene.geometryController.loadModel("station to car front", "modMetroCarInteriorFront", { x: -148, y: -64, z: 1006 + 280 + 280 }); + //this.metroStationCarFront.flags.draw = true; + + this.metroComputer = this.scene.geometryController.loadModel("station to car computer", "modDebugTile", { x: -148, y: -64 - 20, z: 1006 + 280 + 280 + 270 }); + this.metroComputer.quadData[0].setTexture("atlasAll", "texInvisible"); + this.metroComputer.scale({ x: 0.8, y: 1, z: 1 }); + this.metroComputer.rotateAroundAxis([1, 0, 0], Math.PI * 0.5); + this.metroComputer.collisionData[0].points = [ + { x: -16, y: -20, z: 0 }, + { x: 16, y: -20, z: 0 }, + { x: 16, y: 8, z: 0 }, + { x: -16, y: 8, z: 0 }, + ]; + this.metroComputer.depthMod = 32; + this.metroComputer.flags.draw = true; + this.metroComputer.data = { + useText: "use computer", + useSprite: "sprInteract01", + useRadius: 36, + }; + this.metroComputer.interactable = true; + this.metroComputer.interact = () => { + //this.stopTrainTop(); + if (this.scene.player.panel === null) { + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelStopTrain(this.scene, this); + } + }; + + //this.scene.player.hideUI(); + //this.scene.player.setMode(PLAYERMODE.INTERACT); + //this.scene.player.panel = new PanelStopTrain(this.scene); + + this.fire = this.scene.geometryController.loadModel("burning fire", "modDebugTile", { x: -148, y: -132 + 16, z: 2036 }); + this.fire.flags.draw = false; + this.fire.setDrawMode(DRAWMODE.BILLBOARD); + this.fire.scale({ x: 4, y: 1, z: 4 }); + this.fire.rotateAroundAxis([1, 0, 0], Math.PI * 0.5); + this.fire.quadData[0].setTexture("atlasFire", "fire_02-0"); + this.fire.depthMod = 32; + this.fireAnim = { + current: 0, + max: 16, + spd: 0.05, + }; + + this.crashedShip = this.scene.geometryController.loadModel("crashed ship", "modHoverCarWipeOutStyle", { x: -148, y: -44, z: 2036 }); + this.crashedShip.flags.draw = false; + this.crashedShip.deleteQuad(this.crashedShip.quadData[this.crashedShip.quadData.length - 1]); + this.crashedShip.deleteQuad(this.crashedShip.quadData[this.crashedShip.quadData.length - 1]); + this.crashedShip.deleteQuad(this.crashedShip.quadData[this.crashedShip.quadData.length - 1]); + this.crashedShip.deleteQuad(this.crashedShip.quadData[this.crashedShip.quadData.length - 1]); + this.crashedShip.scale({ x: 0.75, y: 0.75, z: 0.75 }); + + //to be spawned to block off the way back to the elevator + this.fireBlocking = this.scene.geometryController.loadModel("burning fire blocking", "modDebugTile", { x: -130, y: -72, z: 200 }); + this.fireBlocking.flags.draw = false; + this.fireBlocking.flags.collision = false; + this.fireBlocking.setDrawMode(DRAWMODE.BILLBOARD); + this.fireBlocking.scale({ x: 4, y: 1, z: 4 }); + this.fireBlocking.rotateAroundAxis([1, 0, 0], Math.PI * 0.5); + this.fireBlocking.quadData[0].setTexture("atlasFire", "fire_02-0"); + this.fireBlocking.depthMod = 32; + + this.blockedPassage = this.scene.geometryController.loadModel("blocked Passage", "modDebugTile", { x: -140, y: -32, z: 200 }); + this.blockedPassage.flags.draw = false; + this.blockedPassage.flags.collision = false; + this.blockedPassage.scale({ x: 4, y: 1, z: 2 }); + this.blockedPassage.rotateAroundAxis([1, 0, 0], Math.PI * 0.5); + this.blockedPassage.rotateAroundAxis([0, 1, 0], Math.PI * 0.4); + this.blockedPassage.depthMod = 32; + + this.crashedShipBlocking = this.scene.geometryController.loadModel("crashed ship blocking", "modHoverCarWipeOutStyle", { x: -130, y: 0, z: 200 }); + this.crashedShipBlocking.flags.draw = false; + this.crashedShipBlocking.flags.collision = false; + this.crashedShipBlocking.deleteQuad(this.crashedShipBlocking.quadData[this.crashedShipBlocking.quadData.length - 1]); + this.crashedShipBlocking.deleteQuad(this.crashedShipBlocking.quadData[this.crashedShipBlocking.quadData.length - 1]); + this.crashedShipBlocking.deleteQuad(this.crashedShipBlocking.quadData[this.crashedShipBlocking.quadData.length - 1]); + this.crashedShipBlocking.deleteQuad(this.crashedShipBlocking.quadData[this.crashedShipBlocking.quadData.length - 1]); + this.crashedShipBlocking.scale({ x: 0.75, y: 0.75, z: 0.75 }); + + this.tunnelFront = []; + this.tunnelFront.push(this.scene.geometryController.loadModel("tunnel Front 0", "modMetroRailTunnelSegment", { x: -256 + 12, y: -64 + 24, z: 1008 - 64 })); + this.tunnelFront.push(this.scene.geometryController.loadModel("tunnel Front 1", "modMetroRailTunnelSegment", { x: -256 + 12, y: -64 + 24, z: 1008 - 64 + 256 })); + for (let t of this.tunnelFront) { + t.flags.draw = true; + t.depthMod = -32; + } + //fade to Black + for (let i = this.tunnelFront[1].quadData.length - 1; i > this.tunnelFront[1].quadData.length - 1 - 16; i--) { + this.tunnelFront[1].quadData[i].setTexture("atlasAll", "texMetalHangar07"); + } + //this.populateStationGeom(); + + this.tunnelBack = []; + this.tunnelBack.push(this.scene.geometryController.loadModel("tunnel Back 0", "modMetroRailTunnelSegment", { x: -256 + 12, y: -64 + 24, z: 112 })); + this.tunnelBack.push(this.scene.geometryController.loadModel("tunnel Back 1", "modMetroRailTunnelSegment", { x: -256 + 12, y: -64 + 24, z: 112 - 256 * 1 })); + this.tunnelBack.push(this.scene.geometryController.loadModel("tunnel Back 0", "modMetroRailTunnelSegment", { x: -256 + 12, y: -64 + 24, z: 112 - 256 * 2 })); + this.tunnelBack.push(this.scene.geometryController.loadModel("tunnel Back 1", "modMetroRailTunnelSegment", { x: -256 + 12, y: -64 + 24, z: 112 - 256 * 3 })); + this.tunnelBack.push(this.scene.geometryController.loadModel("tunnel Back 1", "modMetroRailTunnelSegment", { x: -256 + 12, y: -64 + 24, z: 112 - 256 * 4 })); + for (let [i, t] of this.tunnelBack.entries()) { + t.rotateAroundAxis([0, 1, 0], Math.PI); + if (i < 2) { + t.flags.draw = true; + } + t.depthMod = -32; + } + + this.tunnelTop = []; + for (let i = 0; i < 10; i++) { + this.tunnelTop.push(this.scene.geometryController.loadModel("tunnel Top" + String(i), "modMetroRailTunnelSegment", { x: -148, y: -128 + 24, z: 1112 + 256 * i })); + } + for (let [i, t] of this.tunnelTop.entries()) { + if (i > 0) { + t.depthMod = -64; + } else { + t.depthMod = -16; + } + } + + this.metroCars = []; + this.metroCars.push(this.scene.geometryController.loadModel("metro car 0", "modMetroCarExterior", { x: -256 + 12, y: 0, z: 176 + 280 * -2 })); + this.metroCars.push(this.scene.geometryController.loadModel("metro car 1", "modMetroCarExterior", { x: -256 + 12, y: 0, z: 176 + 280 * -1 })); + this.metroCars.push(this.scene.geometryController.loadModel("metro car 2", "modMetroCarExterior", { x: -256 + 12, y: 0, z: 176 + 280 * 0 })); + this.metroCars.push(this.scene.geometryController.loadModel("metro car 3", "modMetroCarExterior", { x: -256 + 12, y: 0, z: 176 + 280 * 1 })); + this.metroCars.push(this.scene.geometryController.loadModel("metro car 4", "modMetroCarExterior", { x: -256 + 12, y: 0, z: 176 + 280 * 2 })); + this.metroCars.push(this.scene.geometryController.loadModel("metro car 5", "modMetroCarExterior", { x: -256 + 12, y: 0, z: 176 + 280 * 3 })); + for (let m of this.metroCars) { + m.flags.draw = true; + } + + //shadows in the is8way + this.shadowNPCs = []; + + //Nosef + this.charNosef = this.scene.geometryController.loadModel("char nosef", "modCharacterDefaultHuman", { x: -220, y: 0, z: 366 }); + this.charNosef.quadData[0].setTexture("charSheetJosef", "josefStandIdle0100"); + this.charNosef.atlas = "charSheetJosef"; + this.charNosef.atlas8wayFrame = "josefStandIdle010"; + this.charNosef.scale({ x: 1.4, y: 1, z: 1 }); + this.charNosef.lookDir.yaw = Math.PI * 0.5; + this.charNosef.flags.draw = true; + this.charNosef.setDrawMode(DRAWMODE.BILLBOARD); + this.charNosef.flags.is8way = true; + this.charNosef.flags.usesAtlas = true; + this.charNosef.depthMod = 16; + this.charNosef.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 1, + conversation: { + fileName: "diaDream00Nosef00", + treePosition: 0, + } + } + this.charNosef.interact = () => { + //this.charNosef.lookDir.yaw = Math.atan2(this.scene.player.pos.x - this.charRoki.pos.x, this.scene.player.pos.z - this.charRoki.pos.z); + + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charNosef); + this.scene.player.conversationManager.setConversation(this.charNosef.data.conversation.fileName, this.charNosef.data.conversation.treePosition); + }; + + //barbara + this.charBarbara = this.scene.geometryController.loadModel("char barbara 00", "modCharacterDefaultHuman", { x: 0, y: -16, z: 256 - 8 }); + this.charBarbara.quadData[0].setTexture("hlBarabara", 0); + this.charBarbara.flags.draw = true; + this.charBarbara.setDrawMode(DRAWMODE.BILLBOARD); + this.charBarbara.depthMod = 16; + this.charBarbara.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaDream00Barbara01", + treePosition: 0, + }, + }; + this.charBarbara.interactable = true; + this.charBarbara.interact = () => { + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charBarbara); + this.scene.player.conversationManager.setConversation(this.charBarbara.data.conversation.fileName, this.charBarbara.data.conversation.treePosition); + }; + + this.charBeggar = this.scene.geometryController.loadModel("char beggar", "modCharacterDefaultHuman", { x: -148, y: 0, z: 441 }); + this.charBeggar.quadData[0].setTexture("beggar", 0); + this.charBeggar.scale({ x: 1.5, y: 0.5, z: 1 }); + this.charBeggar.flags.draw = true; + this.charBeggar.setDrawMode(DRAWMODE.BILLBOARD); + this.charBeggar.depthMod = 32; + this.charBeggar.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaDream00Beggar01", + treePosition: 0, + }, + }; + this.charBeggar.interactable = true; + this.charBeggar.interact = () => { + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charBeggar); + this.scene.player.conversationManager.setConversation(this.charBeggar.data.conversation.fileName, this.charBeggar.data.conversation.treePosition); + }; + + this.charRaceDirector = this.scene.geometryController.loadModel("charRaceDirector", "modCharacterDefaultHuman", { x: -173, y: -60, z: 1543 }); + this.charRaceDirector.quadData[0].setTexture("charSheetRaceDirector", "paulSitIdle00"); + this.charRaceDirector.atlas = "charSheetRaceDirector"; + this.charRaceDirector.atlas8wayFrame = "paulSitIdle0"; + this.charRaceDirector.scale({ x: 2, y: 1, z: 1 }); + //this.charRaceDirector.flags.draw = true; + this.charRaceDirector.lookDir.yaw = Math.PI * 1; + this.charRaceDirector.setDrawMode(DRAWMODE.BILLBOARD); + this.charRaceDirector.flags.is8way = true; + this.charRaceDirector.flags.usesAtlas = true; + this.charRaceDirector.depthMod = 16; + this.charRaceDirector.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaDream00RaceDirector00", + treePosition: 0, + }, + }; + this.charRaceDirector.interactable = true; + this.charRaceDirector.interact = () => { + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charRaceDirector); + this.scene.player.conversationManager.setConversation(this.charRaceDirector.data.conversation.fileName, this.charRaceDirector.data.conversation.treePosition); + }; + + //triggers + //trigger shade + //x : -112.59609141241174 y : 0 z : 205.2811558971969 + this.triggerShadeLight = this.scene.geometryController.loadModel("trigger shade", "modTriggerWall1x1", { x: -80, y: 0, z: 209 }); + this.triggerShadeLight.scale({ x: 32, y: 64, z: 1 }); + this.triggerShadeLight.rotateAroundAxis([0, 1, 0], Math.PI * 0.5); + //this.triggerShadeLight.flags.draw = true; + this.triggerShadeLight.depthMod = 32; + this.triggerShadeLight.trigger.isTrigger = true; + this.triggerShadeLight.trigger.onEnter = () => { + this.scene.cam.shadeModTarget = 0.04; + }; + this.triggerShadeDark = this.scene.geometryController.loadModel("trigger shade on", "modTriggerWall1x1", { x: -80 - 2, y: 0, z: 209 }); + this.triggerShadeDark.scale({ x: 32, y: 64, z: 1 }); + this.triggerShadeDark.rotateAroundAxis([0, 1, 0], Math.PI * 0.5); + //this.triggerShadeDark.flags.draw = true; + this.triggerShadeDark.depthMod = 32; + this.triggerShadeDark.trigger.isTrigger = true; + this.triggerShadeDark.trigger.onEnter = () => { + this.scene.cam.shadeModTarget = 0.125; + }; + + //trigger hallway + this.triggerHideHallway = this.scene.geometryController.loadModel("trigger hallway", "modTriggerWall1x1", { x: -160, y: 0, z: 360 + 2 }); + this.triggerHideHallway.scale({ x: 32, y: 64, z: 1 }); + //this.triggerHideHallway.flags.draw = true; + //this.triggerHideHallway.toggleDrawCollisions(); + this.triggerHideHallway.depthMod = 32; + this.triggerHideHallway.trigger.isTrigger = true; + this.triggerHideHallway.trigger.onEnter = () => { + this.drawHallway(false); + }; + this.triggerShowHallway = this.scene.geometryController.loadModel("trigger hallway on", "modTriggerWall1x1", { x: -160, y: 0, z: 360 }); + this.triggerShowHallway.scale({ x: 32, y: 64, z: 1 }); + //this.triggerShowHallway.flags.draw = true; + this.triggerShowHallway.depthMod = 32; + this.triggerShowHallway.trigger.isTrigger = true; + this.triggerShowHallway.trigger.onEnter = () => { + this.drawHallway(true); + }; + + //trigger tunnel + this.triggerHideTunnel = this.scene.geometryController.loadModel("trigger tunnel", "modTriggerWall1x1", { x: -151, y: -4, z: 914 + 2 }); + this.triggerHideTunnel.scale({ x: 32, y: 64, z: 1 }); + //this.triggerHideTunnel.flags.draw = true; + //this.triggerHideTunnel.toggleDrawCollisions(); + this.triggerHideTunnel.depthMod = 32; + this.triggerHideTunnel.trigger.isTrigger = true; + this.triggerHideTunnel.trigger.onEnter = () => { + this.drawTunnel(false); + this.drawStationCar(true); + }; + this.triggerShowTunnel = this.scene.geometryController.loadModel("trigger tunnel on", "modTriggerWall1x1", { x: -151, y: 0, z: 914 }); + this.triggerShowTunnel.scale({ x: 32, y: 64, z: 1 }); + //this.triggerShowTunnel.flags.draw = true; + //this.triggerShowTunnel.toggleDrawCollisions(); + this.triggerShowTunnel.depthMod = 32; + this.triggerShowTunnel.trigger.isTrigger = true; + this.triggerShowTunnel.trigger.onEnter = () => { + this.drawTunnel(true); + this.drawStationCar(false); + }; + + //trigger station + this.triggerHideStation = this.scene.geometryController.loadModel("trigger station", "modTriggerWall1x1", { x: -144, y: -64, z: 1244 + 2 }); + this.triggerHideStation.scale({ x: 32, y: 64, z: 1 }); + //this.triggerHideStation.flags.draw = true; + //this.triggerHideStation.toggleDrawCollisions(); + this.triggerHideStation.depthMod = 32; + this.triggerHideStation.trigger.isTrigger = true; + this.triggerHideStation.trigger.onEnter = () => { + this.drawStation(false); + }; + this.triggerShowStation = this.scene.geometryController.loadModel("trigger station on", "modTriggerWall1x1", { x: -144, y: -64, z: 1244 }); + this.triggerShowStation.scale({ x: 32, y: 64, z: 1 }); + //this.triggerShowStation.flags.draw = true; + //this.triggerShowStation.toggleDrawCollisions(); + this.triggerShowStation.depthMod = 32; + this.triggerShowStation.trigger.isTrigger = true; + this.triggerShowStation.trigger.onEnter = () => { + this.drawStation(true); + }; + + //flags + flagManager.setFlag("dream00hasKey", "false"); + //env var + this.metroSpeed = 2; + this.metroAnim = 0; + this.metroJumpPos = this.metroCars[this.metroCars.length - 1].pos.z + 280; + this.tunnelJumpPos = this.tunnelTop[1].pos.z - 256; + this.playerInTrain = false; + this.playerInTunnel = false; + this.playerRunningTime = 0; + this.puzzleProgress = 0; + this.fireAnim = { + current: 0, + max: 16, + spd: 0.05, + }; + } + + update() { + if (this.scene.soundManager.musicCalmLoop00.howlGroup.playing() === false) { + this.scene.soundManager.playSound(this.scene.soundManager.musicCalmLoop00); + } + + switch (this.puzzleProgress) { + case 0: + /* + main train is constantly moving with nosef, and moving train upstairs with a ship running in the tunnel + */ + if (this.playerInTrain === false) { + //endless moving metro and Josef + for (let m of this.metroCars) { + m.jumpToPosition({ x: m.pos.x, y: m.pos.y, z: m.pos.z + this.metroSpeed * this.scene.dt }); + } + if (this.metroCars[this.metroCars.length - 1].pos.z >= this.metroJumpPos) { + for (let m of this.metroCars) { + m.jumpToPosition({ x: m.pos.x, y: m.pos.y, z: m.pos.z - 280 }); + } + } + this.charNosef.jumpToPosition({ x: this.charNosef.pos.x, y: this.charNosef.pos.y, z: this.charNosef.pos.z + this.metroSpeed * this.scene.dt }); + if (this.charNosef.pos.z >= this.metroJumpPos) { + this.charNosef.jumpToPosition({ x: this.charNosef.pos.x, y: this.charNosef.pos.y, z: this.charNosef.pos.z - 280 * 7 - 70 }); + } + } + + if (this.playerInTrain === true) { + //move tunnel around train + for (let [i, t] of this.tunnelTop.entries()) { + if (i > 0) { + t.jumpToPosition({ x: t.pos.x, y: t.pos.y, z: t.pos.z - this.metroSpeed * this.scene.dt }); + } + } + if (this.tunnelTop[1].pos.z <= this.tunnelJumpPos) { + for (let [i, t] of this.tunnelTop.entries()) { + if (i > 0) { + t.jumpToPosition({ x: t.pos.x, y: t.pos.y, z: t.pos.z + 256 }); + } + } + } + this.metroAnim += 0.025 * this.scene.dt; + this.metroStationCarMid.rotateAroundAxis([0, 0, 1], Math.sin(Math.cos(this.metroAnim + 0.04) * -0.0005)); + this.metroStationCarFront.rotateAroundAxis([0, 0, 1], Math.sin(Math.cos(this.metroAnim) * 0.0005)); + + this.crashedShip.rotateAroundAxis([0, 0, 1], Math.sin(Math.cos(this.metroAnim) * -0.0025)); + } + break; + case 1: + /* + stopped upstairs train, and flickering fire + */ + //animate fire + this.fireAnim.current += this.fireAnim.spd * this.scene.dt; + if (this.fireAnim.current >= this.fireAnim.max) { + this.fireAnim.current -= this.fireAnim.max; + } + + if (this.playerInTrain === true) { + this.fire.quadData[0].setTexture("atlasFire", "fire_02-" + String(Math.floor(this.fireAnim.current))); + this.fire.quadData[0].clearQuads(); + this.fire.quadData[0].createQuad(); + } else { + this.fireBlocking.quadData[0].setTexture("atlasFire", "fire_02-" + String(Math.floor(this.fireAnim.current))); + this.fireBlocking.quadData[0].clearQuads(); + this.fireBlocking.quadData[0].createQuad(); + + if (this.scene.player.pos.y > 0) { + if (gl_vec3.dot(this.scene.player.transform.toVectorArray(this.scene.player.transform.forward), this.metroCars[this.metroCars.length - 1].transform.toVectorArray(this.metroCars[this.metroCars.length - 1].transform.forward),) < 0) { + //endlessly walking + if (this.metroCars[this.metroCars.length - 1].pos.z >= this.scene.player.pos.z + 32 + 280) { + for (let m of this.metroCars) { + m.jumpToPosition({ x: m.pos.x, y: m.pos.y, z: m.pos.z - this.metroSpeed * this.scene.dt }); + } + //this.charNosef.jumpToPosition({ x: this.charNosef.pos.x, y: this.charNosef.pos.y, z: this.charNosef.pos.z - (this.metroSpeed * this.scene.dt) }); + this.charNosef.jumpToPosition({ + x: this.metroCars[this.metroCars.length - 1].pos.x, + y: this.metroCars[this.metroCars.length - 1].pos.y, + z: this.metroCars[this.metroCars.length - 1].pos.z - 192, + }); + } + + if (this.scene.player.pos.z <= -375) { + this.playerRunningTime += 1; + console.log(this.playerRunningTime); + if (this.playerRunningTime >= 2) { + this.charNosef.interact(); + } + + this.scene.player.jumpToPosition({ x: this.scene.player.pos.x, y: this.scene.player.pos.y, z: this.scene.player.pos.z + 256 }); + for (let m of this.metroCars) { + m.jumpToPosition({ x: m.pos.x, y: m.pos.y, z: m.pos.z + 256 }); + } + this.charNosef.jumpToPosition({ x: this.charNosef.pos.x, y: this.charNosef.pos.y, z: this.charNosef.pos.z + 256 }); + } + } else { + if (this.scene.player.pos.z <= -958) { + this.startTunnelShips(); + } + } + } + } + break; + case 2: + for (let ai of this.aiShips) { + ai.updateDream(); + ai.gondula.rotateAroundAxis([0, 0, 1], 0.1 * this.scene.dt); + /*if(ai.gondula.pos.z > 768){ + ai.gondula.pos.z -= 2048; + }*/ + } + if (this.aiShips[0].gondula.pos.z > 1280) { + this.scene.player.jumpToPosition({ x: -144, y: 0, z: 160 }); + this.scene.loadLevel("playerApartement00", { fromElevator: false }); + } + break; + default: + break; + } + } + + createShadowNPCs() { + this.shadowNPCs.push(null); + } + + destroyShadowNPCs() { + for (let c of this.shadowNPCs) { + this.scene.geometryController.destroyModelById(c.id); + } + this.shadowNPCs = []; + } + + startTunnelShips() { + this.puzzleProgress = 2; + this.drawHallway(false); + this.drawTunnel(false); + this.drawStationCar(false); + this.stationLeft.flags.draw = false; + for (let m of this.metroCars) { + m.flags.draw = false; + } + + //start ships + for (let ai of this.aiShips) { + //r.flags.draw = true; + for (let s of ai.swooshOrigins) { + s.jumpToPosition({ x: 0, y: 0, z: 0 }); + } + ai.setDraw(true); + } + } + + stopTrainTop() { + this.scene.cameras.main.fadeFrom(500, 255, 255, 255, false, (_cam, _pct) => { }, this); + //burn ship + this.fire.flags.draw = true; + this.crashedShip.jumpToPosition({ x: -148, y: -84 + 16, z: 2036 }); + this.crashedShip.rotateAroundAxis([0, 0, 1], Math.PI * 0.8); + this.crashedShip.rotateAroundAxis(this.crashedShip.transform.toVectorArray(this.crashedShip.transform.up), Math.PI * -0.1); + //burn ship that blocks the entry + this.crashedShipBlocking.jumpToPosition({ x: -130, y: -24, z: 200 }); + this.crashedShipBlocking.rotateAroundAxis([0, 0, 1], Math.PI * -0.7); + this.crashedShipBlocking.rotateAroundAxis([0, 1, 0], Math.PI * -0.35); + this.crashedShipBlocking.rotateAroundAxis(this.crashedShipBlocking.transform.toVectorArray(this.crashedShipBlocking.transform.up), Math.PI * 0.1); + this.blockedPassage.flags.collision = true; + + //move main metro to its start position + this.metroComputer.interactable = false; + for (let [i, m] of this.metroCars.entries()) { + m.jumpToPosition({ x: m.pos.x, y: m.pos.y, z: this.metroJumpPos + 3 * 280 - i * 280 }); + } + this.metroCars[this.metroCars.length - 1].swapModelData("modMetroCarExteriorBack"); + for (let i = 3; i >= 0; i--) { + this.scene.geometryController.destroyModelById(this.metroCars[i].id); + this.metroCars.splice(i, 1); + } + this.charNosef.jumpToPosition({ x: this.metroCars[this.metroCars.length - 1].pos.x, y: this.charNosef.pos.y, z: this.metroCars[this.metroCars.length - 1].pos.z + 8 }); + this.charNosef.lookDir.yaw = Math.PI * 1; + + /*"actions": "IS8WAY charRaceDirector false SETTEXTURE charRaceDirector 0 charSheetRaceDirector paulStandPose00 SCALE charRaceDirector 0.75 1.25 1 JUMPTOPOSITIONRELATIVE charRaceDirector 0 0 -7", + modelId = this.scene.geometryController.models.filter((el) => { + return el.id === arr[1]; + })[0]; + modelId.quadData[arr[2]].setTexture(arr[3], arr[4], false);*/ + + if (this.charRaceDirector.flags.is8way === true) { + this.charRaceDirector.flags.is8way = false; + this.charRaceDirector.quadData[0].setTexture("charSheetRaceDirector", "paulStandPose02", false); + this.charRaceDirector.scale({ x: 0.75, y: 1.25, z: 1 }); + this.charRaceDirector.jumpToPosition({ x: this.charRaceDirector.pos.x + 0, y: this.charRaceDirector.pos.y + 0, z: this.charRaceDirector.pos.z - 7 }); + } + this.charRaceDirector.data.conversation.treePosition = 100; //red flag red flag + this.charBeggar.data.conversation.treePosition = 16; //do you have some coins? only + + this.puzzleProgress = 1; + } + + drawHallway(_bool) { + this.stationHallway.flags.draw = _bool; + this.stationRight.flags.draw = _bool; + this.elevator.setDraw(_bool); + } + + drawTunnel(_bool) { + for (let t of this.tunnelFront) { + t.flags.draw = _bool; + } + } + + drawStationCar(_bool) { + this.metroStationCarMid.flags.draw = _bool; + this.metroStationCarFront.flags.draw = _bool; + this.crashedShip.flags.draw = _bool; + for (let [i, t] of this.tunnelTop.entries()) { + if(i > 0){ + t.flags.draw = _bool; + } else { + t.flags.draw = true; + } + } + this.playerInTrain = _bool; + this.charRaceDirector.flags.draw = _bool; + } + + drawStation(_bool) { + this.stationLeft.flags.draw = _bool; + for (let m of this.metroCars) { + m.flags.draw = _bool; + } + for (let [i, t] of this.tunnelBack.entries()) { + if (this.puzzleProgress === 0) { + if (i < 2) { + t.flags.draw = _bool; + } + } else { + t.flags.draw = _bool; + } + } + + //only show after ship crashed + if (this.puzzleProgress >= 1) { + this.fireBlocking.flags.draw = _bool; + this.crashedShipBlocking.flags.draw = _bool; + } + } + + destroy() { } + + populateStationGeom() { + /* + //half scaled station ring models + let modelData = JSON.parse(JSON.stringify(this.scene.cache.json.get("modRingD512MetroStationStart"))); + for (let [i, q] of modelData.quadData.entries()) { + this.addQuadFromData(q, 0); + } + modelData = JSON.parse(JSON.stringify(this.scene.cache.json.get("modRingD512MetroStation"))); + for (let [i, q] of modelData.quadData.entries()) { + this.addQuadFromData(q, 256); + } + modelData = JSON.parse(JSON.stringify(this.scene.cache.json.get("modRingD512MetroStationEnd"))); + for (let [i, q] of modelData.quadData.entries()) { + this.addQuadFromData(q, 512); + } + this.stationLeft.scale({x: 0.5, y: 0.5, z: 0.5}); + */ + + //straight half scaled rail tunnel + let modelData = JSON.parse(JSON.stringify(this.scene.cache.json.get("modMetroRailTunnelSegment"))); + let textData = [ + [ + { texture: "atlasAll", frame: "texMetalHangar00" }, + { texture: "atlasAll", frame: "texMetalHangar00" }, + { texture: "atlasAll", frame: "texWallGrind03l" }, + { texture: "atlasAll", frame: "texMetroTunnelRails02" }, + { texture: "atlasAll", frame: "texMetroTunnelRails03" }, + { texture: "atlasAll", frame: "texWallGrind03r" }, + { texture: "atlasAll", frame: "texMetalHangar00" }, + { texture: "atlasAll", frame: "texMetalHangar00" }, + { texture: "atlasAll", frame: "texMetalHangar00" }, + { texture: "atlasAll", frame: "texMetalHangar00" }, + { texture: "atlasAll", frame: "texMetalHangar00" }, + { texture: "atlasAll", frame: "texWallGrind03l" }, + { texture: "atlasAll", frame: "texWallGrind03r" }, + { texture: "atlasAll", frame: "texMetalHangar00" }, + { texture: "atlasAll", frame: "texMetalHangar00" }, + { texture: "atlasAll", frame: "texMetalHangar00" }, + ], + [ + { texture: "atlasAll", frame: "texMetalHangarLight00" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texMetalDark04" }, + { texture: "atlasAll", frame: "texMetroTunnelRails02" }, + { texture: "atlasAll", frame: "texMetroTunnelRails03" }, + { texture: "atlasAll", frame: "texMetalDark04" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texMetalHangarLight00" }, + { texture: "atlasAll", frame: "texMetalDark04" }, + { texture: "atlasAll", frame: "texMetalDark04" }, + { texture: "atlasAll", frame: "texMetalDark04" }, + { texture: "atlasAll", frame: "texMetalDark04" }, + { texture: "atlasAll", frame: "texMetalDark04" }, + { texture: "atlasAll", frame: "texMetalDark04" }, + { texture: "atlasAll", frame: "texMetalDark04" }, + { texture: "atlasAll", frame: "texMetalDark04" }, + ], + [ + { texture: "atlasAll", frame: "texMetalHangar00" }, + { texture: "atlasAll", frame: "texMetalHangar00" }, + { texture: "atlasAll", frame: "texWallGrind03l" }, + { texture: "atlasAll", frame: "texMetroTunnelRails02" }, + { texture: "atlasAll", frame: "texMetroTunnelRails03" }, + { texture: "atlasAll", frame: "texWallGrind03r" }, + { texture: "atlasAll", frame: "texMetalHangar00" }, + { texture: "atlasAll", frame: "texMetalHangar00" }, + { texture: "atlasAll", frame: "texMetalHangar00" }, + { texture: "atlasAll", frame: "texMetalHangar00" }, + { texture: "atlasAll", frame: "texMetalHangar00" }, + { texture: "atlasAll", frame: "texWallGrind03l" }, + { texture: "atlasAll", frame: "texWallGrind03r" }, + { texture: "atlasAll", frame: "texMetalHangar00" }, + { texture: "atlasAll", frame: "texMetalHangar00" }, + { texture: "atlasAll", frame: "texMetalHangar00" }, + ], + + [ + { texture: "atlasAll", frame: "texWallGrind03l" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texMetroTunnelRails02" }, + { texture: "atlasAll", frame: "texMetroTunnelRails03" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texWallGrind03r" }, + { texture: "atlasAll", frame: "texBricksBrownEnd01" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrownEnd00" }, + ], + [ + { texture: "atlasAll", frame: "texWallGrind03l" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texMetroTunnelRails02" }, + { texture: "atlasAll", frame: "texMetroTunnelRails03" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texWallGrind03r" }, + { texture: "atlasAll", frame: "texBricksBrownEnd01" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrownEnd00" }, + ], + [ + { texture: "atlasAll", frame: "texWallGrind03l" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texMetroTunnelRails02" }, + { texture: "atlasAll", frame: "texMetroTunnelRails03" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texWallGrind03r" }, + { texture: "atlasAll", frame: "texBricksBrownEnd01" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrownEnd00" }, + ], + [ + { texture: "atlasAll", frame: "texWallGrind03l" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texMetroTunnelRails02" }, + { texture: "atlasAll", frame: "texMetroTunnelRails03" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texWallGrind03r" }, + { texture: "atlasAll", frame: "texBricksBrownEnd01" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrownEnd00" }, + ], + [ + { texture: "atlasAll", frame: "texWallGrind03l" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texMetroTunnelRails02" }, + { texture: "atlasAll", frame: "texMetroTunnelRails03" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texMetalDark03" }, + { texture: "atlasAll", frame: "texWallGrind03r" }, + { texture: "atlasAll", frame: "texBricksBrownEnd01" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrown00" }, + { texture: "atlasAll", frame: "texBricksBrownEnd00" }, + ], + ]; + for (let j = 1; j < 8; j++) { + modelData = JSON.parse(JSON.stringify(this.scene.cache.json.get("modMetroRailTunnelSegment"))); + for (let [i, q] of modelData.quadData.entries()) { + this.addQuadFromData(q, j * 32, textData[j][i].texture, textData[j][i].frame); + } + } + for (let i = 0; i < 16; i++) { + this.tunnelFront.quadData[i].setTexture(textData[0][i].texture, textData[0][i].frame); + } + //this.tunnelFront.scale({x: 0.5, y: 0.5, z: 0.5}); + } + + addQuadFromData(_q, _offset, _tex, _frame) { + let pos = { + x: _q.position.x + this.tunnelFront.pos.x, + y: _q.position.y + this.tunnelFront.pos.y, + z: _q.position.z + this.tunnelFront.pos.z, + }; + for (let p of _q.points) { + p.z += _offset; + } + if (_q.type !== "collisionQuad") { + let no = this.tunnelFront.quadData.length; + this.tunnelFront.quadData.push(new DataQuad(this.scene, this.tunnelFront.id, no, _q.type, pos, _q.points, _tex, _frame)); + } else { + let no = this.collisionData.length; + this.tunnelFront.collisionData.push(new DataQuad(this.scene, this.tunnelFront.id, no, _q.type, pos, _q.points, "none", 0)); + } + } +} diff --git a/src/3d/levels/lvlHangar00.js b/src/3d/levels/lvlHangar00.js new file mode 100755 index 0000000..3a7c4d8 --- /dev/null +++ b/src/3d/levels/lvlHangar00.js @@ -0,0 +1,684 @@ +import PanelWelcome from "../../ui/panelWelcome.js"; +import PanelWakeUp from "../../ui/panelWakeUp.js"; +import PanelIntroDemo from "../../ui/panelIntro.js"; +import PanelPlayerComputer from "../../ui/panelPlayerComputer.js"; +import PanelJoeComputer from "../../ui/panelJoeComputer.js"; +import PanelEnterShipDemo00 from "../../ui/panelEnterShipDemo00.js"; +import GroupElevator from "../groups/grpElevator.js"; +import PanelPainting from "../../ui/panelPainting.js"; + +export default class LevelHangar00 { + constructor(_scene, _params) { + this.scene = _scene; + this.params = _params; + if (this.params === null) { + this.params = { + startFromElevator: false, + showIntro: false, + }; + } + if (this.params.startFromElevator === undefined) { + this.params.startFromElevator = false; + } + if (this.params.showIntro === undefined) { + this.params.showIntro = false; + } + + //this.ref = this.scene.geometryController.loadModel("levelOrigin", "modDebugTile", { x: 0, y: 0, z: 0 }); + //this.ref.flags.draw = true; + + this.scene.player = this.scene.playerWalk; + this.scene.cam = this.scene.camWalk; + + //this.scene.player.dir.pitch = 0; + this.scene.player.eyeHeight = 24; + this.scene.player.setMoveMode(PLAYERMOVE.STAND); + if (this.params.startFromElevator === true) { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + } else { + this.scene.player.jumpToPosition({ x: 160, y: 56, z: 330 }); + } + + if (this.params.showIntro === true) { + this.scene.player.hideUI(); + //this.scene.player.panel = new PanelWakeUp(this.scene, "A new Contestant"); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelIntroDemo(this.scene); + } else { + this.scene.player.showUI(); + if (flagManager.getFlagById("demoProgress").value === "1") { + this.scene.player.hideUI(); + this.scene.player.panel = new PanelWakeUp(this.scene, "A new Contestant"); + } + } + + this.elevator = new GroupElevator(this.scene, this, { x: 0, y: 0, z: 0 }); + this.elevator.setDraw(true); + + this.hallway = this.scene.geometryController.loadModel("hallway", "modHangarHallway", { x: 0, y: 0, z: 96 - 36 }); + this.hallway.flags.draw = true; + + this.main = this.scene.geometryController.loadModel("main", "modHangarMain", { x: 48, y: 56, z: 96 + 188 }); + this.main.flags.draw = true; + + this.painting = this.scene.geometryController.loadModel("hallway painting", "modHallwayPainting", { x: 0, y: -24, z: 363 }); //364 + this.painting.depthMod = 16; + this.painting.flags.draw = true; + this.painting.data = { + useText: "use computer", + useRadius: 48, + }; + this.painting.interactable = true; + this.painting.interact = () => { + if (this.scene.player.panel === null) { + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelPainting(this.scene); + } + }; + + this.doorRight = this.scene.geometryController.loadModel("hangar door right", "modHangarDoor", { x: 224, y: -44, z: 96 + 236 }); + this.doorRight.flags.draw = true; + this.doorLeft = this.scene.geometryController.loadModel("hangar door left", "modHangarDoor", { x: 224, y: -44, z: 96 + 236 }); + this.doorLeft.flags.draw = true; + this.doorLeft.rotateAroundAxis([0, -1, 0], Math.PI); + /*console.log({ + x: this.doorRight.pos.x - this.main.pos.x, + y: this.doorRight.pos.y - this.main.pos.y, + z: this.doorRight.pos.z - this.main.pos.z + })*/ + + this.ship = this.scene.geometryController.loadModel("ship", "modHoverCarWipeOutStyle", { x: 208 + 16, y: 76 - 8, z: 288 + 32 }); + this.ship.flags.draw = true; + this.ship.deleteQuad(this.ship.quadData[this.ship.quadData.length - 1]); + this.ship.deleteQuad(this.ship.quadData[this.ship.quadData.length - 1]); + this.ship.deleteQuad(this.ship.quadData[this.ship.quadData.length - 1]); + this.ship.deleteQuad(this.ship.quadData[this.ship.quadData.length - 1]); + + this.shipInteractable = this.scene.geometryController.loadModel("ship interactable", "modShipInteractable", { + x: this.ship.pos.x, + y: this.ship.pos.y - 16, + z: this.ship.pos.z + 16, + }); + this.shipInteractable.flags.draw = true; + this.shipInteractable.data = { + useText: "enter ship", + useRadius: 48, + }; + this.shipInteractable.interactable = true; + this.shipInteractable.interact = () => { + if (flagManager.getFlagById("demoProgress").value === "1") { + this.charRoki.data.conversation.treePosition = 9; + this.charRoki.interact(); + } else { + if (this.scene.player.panel === null) { + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.setMoveMode(PLAYERMOVE.SHIP); + this.scene.player.panel = new PanelEnterShipDemo00(this.scene, this, { + x: this.scene.player.pos.x, + y: this.scene.player.pos.y, + z: this.scene.player.pos.z, + }); + + this.scene.player.jumpToPosition( + { + x: this.ship.pos.x + this.ship.transform.forward.x * 16 + this.ship.transform.up.x * 32, + y: this.ship.pos.y + this.ship.transform.forward.y * 16 + this.ship.transform.up.y * 32, + z: this.ship.pos.z + this.ship.transform.forward.z * 16 + this.ship.transform.up.z * 32, + }, + true, + ); + //todo: why no worky? + /* + this.scene.player.dir.yaw *= -1; + this.scene.player.dir.pitch *= -1; + this.scene.cam.setPositionAndRotation( + { x: this.scene.player.pos.x, y: this.scene.player.pos.y - this.scene.player.eyeHeight, z: this.scene.player.pos.z}, this.scene.player.dir.yaw * -1 + );*/ + + this.shipInteractable.interactable = false; + } + } + }; + + this.computer = this.scene.geometryController.loadModel("apartement computer", "modComputer", { x: 118, y: 60 - 12, z: 148 }); + this.computer.rotateAroundAxis([0, -1, 0], Math.PI * 0.76); + this.computer.depthMod = 20; + this.computer.flags.draw = true; + this.computer.data = { + useText: "use computer", + useRadius: 48, + }; + this.computer.interactable = true; + this.computer.interact = () => { + if (this.scene.player.panel === null) { + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelJoeComputer(this.scene); + } + }; + + //maybe we dont need it if addding hangar doors + this.tunnelbox = this.scene.geometryController.loadModel("lift shaft", "modRingD256HangarLift", { x: 224, y: -512, z: 96 + 188 - 16 }); + this.tunnelbox.flags.draw = true; + + this.leavingHangar = false; + this.toTrack = 0; + this.maxLaps = 5; + this.raceMode = 0; + this.hangarTick = 0; + this.liftOff = { + current: 0, + max: 0.5, + }; + + //characters + this.charMechanic = this.scene.geometryController.loadModel("char mechanic", "modCharacterDefaultHuman", { x: 224, y: 88, z: 271 }); + this.charMechanic.quadData[0].setTexture("charSheetRahyMechanic", "rahyMechanicSitIdle0000"); + this.charMechanic.atlas = "charSheetRahyMechanic"; + this.charMechanic.atlas8wayFrame = "rahyMechanicSitIdle010"; + this.charMechanic.scale({ x: 1.4, y: 0.8, z: 1 }); + this.charMechanic.flags.draw = true; + //this.charMechanic.lookDir.yaw = Math.PI * -0.5; + this.charMechanic.setDrawMode(DRAWMODE.BILLBOARD); + this.charMechanic.flags.is8way = true; + this.charMechanic.flags.usesAtlas = true; + this.charMechanic.depthMod = 16; + this.charMechanic.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaDemoHangarMechanic00", + treePosition: 99, + }, + }; + this.charMechanic.interactable = true; + this.charMechanic.interact = () => { + this.charMechanic.lookDir.yaw = Math.atan2(this.scene.player.pos.x - this.charMechanic.pos.x, this.scene.player.pos.z - this.charMechanic.pos.z); + + if (flagManager.getFlagById("desktopBackgroundJoe").value !== "0") { + this.charMechanic.data.conversation.treePosition = 12; + } + + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charMechanic); + this.scene.player.conversationManager.setConversation(this.charMechanic.data.conversation.fileName, this.charMechanic.data.conversation.treePosition); + }; + + this.charRoomba = this.scene.geometryController.loadModel("char roomba", "modCharacterDefaultHuman", { x: 86, y: 56, z: 376 }); + this.charRoomba.quadData[0].setTexture("roomba", 0); + this.charRoomba.scale({ x: 1, y: 0.25, z: 1 }); + this.charRoomba.flags.draw = true; + this.charRoomba.setDrawMode(DRAWMODE.BILLBOARD); + this.charRoomba.depthMod = 32; + this.charRoomba.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaHangar00Roomba00", + treePosition: 0, + }, + waypoints: [ + { x: 144, y: 56, z: 379 }, + { x: 138, y: 56, z: 282 }, + { x: 86, y: 56, z: 376 }, + ], + touchedTimes: 0, + }; + this.charRoomba.interactable = true; + this.charRoomba.interact = () => { + //this.scene.player.setMode(PLAYERMODE.DIALOGUE); + //this.scene.player.conversationManager.setNPC(this.charShop); + //this.scene.player.conversationManager.setConversation(this.charShop.data.conversation.fileName, this.charShop.data.conversation.treePosition); + this.charRoomba.data.touchedTimes += 1; + + if (this.charRoomba.data.touchedTimes >= 3) { + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charRoomba); + this.scene.player.conversationManager.setConversation(this.charRoomba.data.conversation.fileName, this.charRoomba.data.conversation.treePosition); + } + + for (let wp of this.charRoomba.data.waypoints) { + this.charRoomba.mover.targets.push({ + pos: { + x: wp.x, + y: wp.y, + z: wp.z, + spd: 0.1, + }, + dir: { + yaw: this.charRoomba.dir.yaw, + pitch: this.charRoomba.dir.pitch, + roll: this.charRoomba.dir.roll, + spd: 0.01, + }, + jump: false, + }); + } + this.charRoomba.mover.target = this.charRoomba.mover.targets[0]; + this.charRoomba.mover.isMoving = true; + }; + + this.objScrewdriver = null; + + /* + this.charDummy = this.scene.geometryController.loadModel("char dummy", "modCharacterDefaultHuman", { x: 23, y: 0, z: 340 }); + this.charDummy.flags.draw = true; + this.charDummy.lookDir.yaw = Math.PI * 0.5; + this.charDummy.setDrawMode(DRAWMODE.BILLBOARD); + this.charDummy.flags.is8way = true; + this.charDummy.depthMod = 16; + */ + //this.charRoki = this.scene.geometryController.loadModel("char roki", "modCharacterDefaultHuman", { x: 23, y: 0, z: 340 }); + this.charRoki = this.scene.geometryController.loadModel("charroki", "modCharacterDefaultHuman", { x: 23, y: 0, z: 316 }); + //this.charRoki.quadData[0].setTexture("turnaroundLarasheet00", 0); + this.charRoki.quadData[0].setTexture("charSheetRoki", "rokiStandIdle0000"); + this.charRoki.atlas = "charSheetRoki"; + this.charRoki.atlas8wayFrame = "rokiStandIdle010"; + this.charRoki.scale({ x: 1, y: 0.9, z: 1 }); + this.charRoki.flags.draw = true; + this.charRoki.lookDir.yaw = Math.PI * 0.5; + this.charRoki.setDrawMode(DRAWMODE.BILLBOARD); + this.charRoki.flags.is8way = true; + this.charRoki.flags.usesAtlas = true; + this.charRoki.depthMod = 16; + this.charRoki.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaDemoRoki00", + treePosition: 0, + }, + waypoints: [ + { x: 35, y: 56, z: 335 }, + { x: -160, y: 41, z: 296 }, + { x: -148, y: 22, z: 165 }, + { x: -142, y: 17, z: 124 }, + { x: -10, y: 0, z: 73 }, + { x: 0, y: 0, z: 0 }, + { x: 0, y: 0, z: -128 }, + ], + anim: 0, + }; + this.charRoki.interactable = true; + this.charRoki.interact = () => { + this.charRoki.lookDir.yaw = Math.atan2(this.scene.player.pos.x - this.charRoki.pos.x, this.scene.player.pos.z - this.charRoki.pos.z); + + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charRoki); + this.scene.player.conversationManager.setConversation(this.charRoki.data.conversation.fileName, this.charRoki.data.conversation.treePosition); + }; + this.charRoki.customActions.push(() => { + this.charRoki.atlas8wayFrame = "rokiWalkFrame000"; + this.charRoki.scale({ x: 1.5, y: 1, z: 1 }); + + //flagManager.setFlag("socialLevel", "00"); + //flagManager.setFlag("marketLevel", "00"); + + this.triggerHello = this.scene.geometryController.loadModel("triggerHello", "modTriggerWall1x1", { x: 32, y: 56, z: 332 }); + this.triggerHello.scale({ x: 36, y: 48, z: 1 }); + this.triggerHello.rotateAroundAxis([0, 1, 0], Math.PI * 0.35); + //this.triggerHello.flags.draw = true; + this.triggerHello.depthMod = 32; + this.triggerHello.trigger.isTrigger = true; + this.triggerHello.trigger.onEnter = () => { + this.charMechanic.data.conversation.fileName = "diaDemoHangarMechanic01"; + this.charMechanic.data.conversation.treePosition = 10; + this.scene.player.jumpToPosition({x: this.scene.player.pos.x + 2, y: this.scene.player.pos.y, z: this.scene.player.pos.z}, true) + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charMechanic); + this.scene.player.conversationManager.setConversation(this.charMechanic.data.conversation.fileName, this.charMechanic.data.conversation.treePosition); + this.triggerHello.trigger.triggered = false; + //this.scene.geometryController.destroyModelById("triggerHello"); + + this.scene.player.jumpToPosition( + { + x: this.scene.player.pos.x + 4, + y: this.scene.player.pos.y + 0, + z: this.scene.player.pos.z + 0, + }, + true, + ); + }; + + for (let wp of this.charRoki.data.waypoints) { + this.charRoki.mover.targets.push({ + pos: { + x: wp.x, + y: wp.y, + z: wp.z, + spd: 0.25, + }, + dir: { + yaw: this.charRoki.dir.yaw, + pitch: this.charRoki.dir.pitch, + roll: this.charRoki.dir.roll, + spd: 0.01, + }, + jump: false, + stopAfterWaypoint: false, + }); + } + this.charRoki.mover.target = this.charRoki.mover.targets[0]; + this.charRoki.mover.isMoving = true; + }); + + this.charRoki.customUpdate = () => { + if (this.charRoki.mover.isMoving === true) { + this.charRoki.data.anim += 0.1; + if (this.charRoki.data.anim >= 4) { + this.charRoki.data.anim -= 4; + } + this.charRoki.atlas8wayFrame = "rokiWalkFrame0" + String(Math.floor(this.charRoki.data.anim)) + "0"; + } + }; + + this.seat = this.scene.geometryController.loadModel("apartement seat", "modSeatBasic", { x: 94, y: 60, z: 170 }); + this.seat.depthMod = 5; + this.seat.flags.draw = true; + + /* + this.charRaceDirector = this.scene.geometryController.loadModel("charRaceDirector", "modCharacterDefaultHuman", { x: 41, y: 0, z: 299 }); + this.charRaceDirector.quadData[0].setTexture("charSheetRaceDirector", "paulStandIdle0000"); + this.charRaceDirector.atlas = "charSheetRaceDirector"; + this.charRaceDirector.atlas8wayFrame = "paulStandIdle010"; + this.charRaceDirector.scale({ x: 1, y: 1, z: 1 }); + this.charRaceDirector.flags.draw = true; + this.charRaceDirector.lookDir.yaw = Math.PI * 0.5; + this.charRaceDirector.setDrawMode(DRAWMODE.BILLBOARD); + this.charRaceDirector.flags.is8way = true; + this.charRaceDirector.flags.usesAtlas = true; + this.charRaceDirector.depthMod = 16; + */ + + /* + this.charScooter = this.scene.geometryController.loadModel("char scooter", "modCharacterDefaultHuman", { x: 84, y: 60, z: 173 }); + this.charScooter.quadData[0].setTexture("atlasCharScooter", "hannahSitIdle00"); + this.charScooter.atlas = "atlasCharScooter"; + this.charScooter.atlas8wayFrame = "hannahSitIdle0"; + this.charScooter.scale({x: 1.5, y: 1.2, z: 1}); + this.charScooter.flags.draw = true; + this.charScooter.lookDir.yaw = Math.PI * 0.5; + this.charScooter.setDrawMode(DRAWMODE.BILLBOARD); + this.charScooter.flags.is8way = true; + this.charScooter.flags.usesAtlas = true; + this.charScooter.depthMod = 16; + this.charScooter.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 12, + conversation: { + fileName: "diaDemoRoki00", + treePosition: 0 + } + } + this.charScooter.interactable = true; + this.charScooter.interact = () => { + this.charFoxxy.lookDir.yaw = Math.atan2(this.scene.player.pos.x - this.charScooter.pos.x, this.scene.player.pos.z - this.charScooter.pos.z); + + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charScooter); + this.scene.player.conversationManager.setConversation(this.charScooter.data.conversation.fileName, this.charScooter.data.conversation.treePosition); + } + */ + + //trigger + this.triggerHello = null; + + //ship flavour hud text when loading + this.txtChecklists = []; + this.txtChecklists.push( + this.scene.add + .bitmapText(this.scene.game.config.width * -0.5 + 16, this.scene.game.config.height * -0.5 + 16, "uiFont", "initalizing data", 14, 0) + .setOrigin(0, 0.5) + .setLetterSpacing(0), + ); + this.txtChecklists.push( + this.scene.add + .bitmapText(this.scene.game.config.width * -0.5 + 16, this.scene.game.config.height * -0.5 + 32, "uiFont", "Craft System ID: 089IYVU765EE", 14, 0) + .setOrigin(0, 0.5) + .setLetterSpacing(0), + ); + this.txtChecklists.push( + this.scene.add + .bitmapText(this.scene.game.config.width * -0.5 + 16, this.scene.game.config.height * -0.5 + 48, "uiFont", "Engine Subsystems Active", 14, 0) + .setOrigin(0, 0.5) + .setLetterSpacing(0), + ); + this.txtChecklists.push( + this.scene.add + .bitmapText(this.scene.game.config.width * -0.5 + 16, this.scene.game.config.height * -0.5 + 64, "uiFont", "Hyperdrive motor engaged", 14, 0) + .setOrigin(0, 0.5) + .setLetterSpacing(0), + ); + this.txtChecklists.push( + this.scene.add + .bitmapText(this.scene.game.config.width * -0.5 + 16, this.scene.game.config.height * -0.5 + 80, "uiFont", "Elevator clamp engaged", 14, 0) + .setOrigin(0, 0.5) + .setLetterSpacing(0), + ); + this.txtChecklists.push( + this.scene.add + .bitmapText(this.scene.game.config.width * -0.5 + 16, this.scene.game.config.height * -0.5 + 96, "uiFont", "Systems check complete", 14, 0) + .setOrigin(0, 0.5) + .setLetterSpacing(0), + ); + this.txtChecklists.push( + this.scene.add + .bitmapText(this.scene.game.config.width * -0.5 + 16, this.scene.game.config.height * -0.5 + 112, "uiFont", "Craft 100% functional", 14, 0) + .setOrigin(0, 0.5) + .setLetterSpacing(0), + ); + for (let t of this.txtChecklists) { + t.depth = 9999; + t.setTint(0x00ff00); //0xa7d254 //0x58a23c + t.alpha = 0; + } + + //flagManager.setFlag("desktopBackground", "0"); + if (flagManager.getFlagById("desktopBackground").value !== "0") { + this.charMechanic.data.conversation.treePosition = 12; + } + + switch (flagManager.getFlagById("demoProgress").value) { + case "0": //tutorial + //this.objScrewdriver = this.scene.geometryController.loadModel("object screwdriver", "modCharacterDefaultHuman", { x: 48, y: 44, z: 213 }); + this.objScrewdriver = this.scene.geometryController.loadModel("object screwdriver", "modCharacterDefaultHuman", { x: -2, y: 60, z: 178 }); + this.objScrewdriver.quadData[0].setTexture("atlasObjects", "texScrewdriver00"); + this.objScrewdriver.scale({ x: 1, y: 0.25, z: 1 }); + this.objScrewdriver.flags.draw = true; + this.objScrewdriver.flags.usesAtlas = true; + this.objScrewdriver.setDrawMode(DRAWMODE.BILLBOARD); + this.objScrewdriver.depthMod = 0; + this.objScrewdriver.interactable = true; + this.objScrewdriver.data = { + useText: "take tool", + useSprite: "sprInteract02", + useRadius: 48, + }; + this.objScrewdriver.interact = () => { + flagManager.setFlag("hangar00tool", "1"); + flagManager.removeFlag("hangar00noTool"); + this.scene.geometryController.destroyModelById("object screwdriver"); + }; + + this.triggerHello = this.scene.geometryController.loadModel("trigger hello", "modTriggerWall1x1", { x: 32, y: 56, z: 332 }); + this.triggerHello.scale({ x: 36, y: 48, z: 1 }); + this.triggerHello.rotateAroundAxis([0, 1, 0], Math.PI * 0.35); + //this.triggerHello.flags.draw = true; + this.triggerHello.depthMod = 32; + this.triggerHello.trigger.isTrigger = true; + this.triggerHello.trigger.onEnter = () => { + this.charMechanic.data.conversation.treePosition = 990; + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charMechanic); + this.scene.player.conversationManager.setConversation(this.charMechanic.data.conversation.fileName, this.charMechanic.data.conversation.treePosition); + this.scene.geometryController.destroyModelById("trigger hello"); + }; + + /* + //quicktest + this.charMechanic.jumpToPosition({ x: 94, y: 60, z: 170 }); + this.charMechanic.atlas8wayFrame = "rahyMechanicSitIdle000"; + this.charMechanic.scale({ x: 1.3, y: 1, z: 1 }); + this.charMechanic.lookDir.yaw = Math.PI * 0.75; + this.charMechanic.depthMod = 20; + */ + + break; + case "1": //bet on race + case "2": + //flagManager.setFlag("wonDemoRace", "true"); + this.charRoki.jumpToPosition({ x: 100, y: 56, z: 330 }); + this.charRoki.data.conversation.fileName = "diaDemoRoki00"; + this.charRoki.data.conversation.treePosition = 10; + + flagManager.removeFlag("hangar00noTool"); + this.charMechanic.jumpToPosition({ x: 94, y: 60, z: 170 }); + this.charMechanic.atlas8wayFrame = "rahyMechanicSitIdle000"; + this.charMechanic.scale({ x: 1.3, y: 1, z: 1 }); + this.charMechanic.lookDir.yaw = Math.PI * 0.75; + this.charMechanic.depthMod = 20; + if (this.charMechanic.data.conversation.treePosition === 99) { + this.charMechanic.data.conversation.fileName = "diaDemoHangarMechanic01"; + this.charMechanic.data.conversation.treePosition = 0; + } + + break; + case "3": //race out come open to apartement + //flagManager.setFlag("wonDemoRace", "true"); + this.charRoki.jumpToPosition({ x: 100, y: 56, z: 330 }); + this.charRoki.data.conversation.fileName = "diaDemoRoki00"; + this.charRoki.data.conversation.treePosition = 23; + if (flagManager.getFlagById("wonDemoRace").value === "true") { + this.charRoki.data.conversation.treePosition = 20; + } + + flagManager.removeFlag("hangar00noTool"); + this.charMechanic.jumpToPosition({ x: 94, y: 60, z: 170 }); + this.charMechanic.atlas8wayFrame = "rahyMechanicSitIdle000"; + this.charMechanic.scale({ x: 1.3, y: 1, z: 1 }); + this.charMechanic.lookDir.yaw = Math.PI * 0.75; + this.charMechanic.depthMod = 20; + if (this.charMechanic.data.conversation.treePosition === 99) { + this.charMechanic.data.conversation.fileName = "diaDemoHangarMechanic01"; + this.charMechanic.data.conversation.treePosition = 0; + } + break; + case "4": + if (this.charMechanic.data.conversation.treePosition === 99) { + this.charMechanic.data.conversation.fileName = "diaDemoHangarMechanic01"; + this.charMechanic.data.conversation.treePosition = 0; + } + this.charRoki.data.conversation.treePosition = 10; + break; + case "5": + this.charMechanic.interactable = false; + this.charRoki.interactable = false; + this.charRoki.jumpToPosition({ x: 1000, y: 5600, z: 3300 }); + break; + case "6": + this.charMechanic.interactable = false; + this.charRoki.interactable = false; + this.charRoki.jumpToPosition({ x: 1000, y: 5600, z: 3300 }); + break; + default: + break; + } + } + + update(_delta) { + if (this.leavingHangar === true) { + if (this.scene.soundManager.musicCalmLoop00.howlGroup.playing() === true) { + this.scene.soundManager.stopSound(this.scene.soundManager.musicCalmLoop00); + } + + this.hangarTick += this.scene.dt; + + //blend in checklist + let waitOffset = 100; + if (this.hangarTick > waitOffset) { + for (let i = 0; i < Math.min(this.txtChecklists.length, (this.hangarTick - waitOffset) / 100); i++) { + this.txtChecklists[i].alpha += 0.1 * this.scene.dt; + } + } + + if (this.doorRight.pos.x > 224 - 64) { + this.doorLeft.jumpToPosition( + { + x: this.doorLeft.pos.x + 0.1 * this.scene.dt, + y: this.doorLeft.pos.y, + z: this.doorLeft.pos.z, + }, + true, + ); + this.doorRight.jumpToPosition( + { + x: this.doorRight.pos.x - 0.1 * this.scene.dt, + y: this.doorRight.pos.y, + z: this.doorRight.pos.z, + }, + true, + ); + } + + if (this.ship.pos.y > -44 - 128) { + this.ship.jumpToPosition( + { + x: this.ship.pos.x, + y: this.ship.pos.y - this.liftOff.current * this.scene.dt, + z: this.ship.pos.z, + }, + true, + ); + this.scene.player.pos.y -= this.liftOff.current * this.scene.dt; //0.1 is interesting for a kind of cutscene and then wait for the ship in tunnel with the camera + if (this.liftOff.current < this.liftOff.max) { + this.liftOff.current += 0.001 * this.scene.dt; + this.liftOff.current = Math.min(1, this.liftOff.current); + } + } else { + //rotate game camera to fps camera and load track level + this.scene.playerGame.dir.yaw = this.scene.player.dir.yaw; //- (Math.PI * 0.5); + this.scene.playerGame.dir.pitch = this.scene.player.dir.pitch; // * -1; + this.scene.playerWalk.setVisibility(false); + + this.scene.loadLevel("quadRingsTest", { + track: this.toTrack, + maxLaps: this.maxLaps, + raceMode: this.raceMode, + startFromHangar: true, + playerShipModel: "modHoverCarWipeOutStyle", + }); + } + } else { + if (this.scene.soundManager.musicCalmLoop00.howlGroup.playing() === false) { + this.scene.soundManager.playSound(this.scene.soundManager.musicCalmLoop00); + } + } + } + + startSimulation() { + this.scene.playerGame.dir.yaw = this.scene.player.dir.yaw; //- (Math.PI * 0.5); + this.scene.playerGame.dir.pitch = this.scene.player.dir.pitch; // * -1; + this.scene.playerWalk.setVisibility(false); + + this.scene.loadLevel("quadRingsTest", { + track: this.toTrack, + maxLaps: this.maxLaps, + raceMode: this.raceMode, + startFromHangar: false, + playerShipModel: "modHoverCarWipeOutStyle", + }); + } + + destroy() { + for (let t of this.txtChecklists) { + t.destroy(); + } + this.txtChecklists = []; + } +} diff --git a/src/3d/levels/lvlHangar01.js b/src/3d/levels/lvlHangar01.js new file mode 100755 index 0000000..e254b70 --- /dev/null +++ b/src/3d/levels/lvlHangar01.js @@ -0,0 +1,492 @@ +import PanelWelcome from "../../ui/panelWelcome.js"; +import PanelWakeUp from "../../ui/panelWakeUp.js"; +import PanelIntroDemo from "../../ui/panelIntro.js"; +import PanelPlayerComputer from "../../ui/panelPlayerComputer.js"; +import PanelJoeComputer from "../../ui/panelJoeComputer.js"; +import PanelEnterShipDemo00 from "../../ui/panelEnterShipDemo00.js"; +import GroupElevator from "../groups/grpElevator.js"; +import PanelPainting from "../../ui/panelPainting.js"; + +export default class LevelHangar00 { + constructor(_scene, _params) { + this.scene = _scene; + this.params = _params; + if (this.params === null) { + this.params = { + startFromElevator: false, + showIntro: false, + }; + } + if (this.params.startFromElevator === undefined) { + this.params.startFromElevator = false; + } + if (this.params.showIntro === undefined) { + this.params.showIntro = false; + } + + //this.ref = this.scene.geometryController.loadModel("levelOrigin", "modDebugTile", { x: 0, y: 0, z: 0 }); + //this.ref.flags.draw = true; + + this.scene.player = this.scene.playerWalk; + this.scene.cam = this.scene.camWalk; + console.log(this.scene.player); + + //this.scene.player.dir.pitch = 0; + this.scene.player.eyeHeight = 24; + this.scene.player.setMoveMode(PLAYERMOVE.STAND); + if (this.params.startFromElevator === true) { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + } else { + this.scene.player.jumpToPosition({ x: 160, y: 56, z: 330 }); + } + + if (this.params.showIntro === true) { + this.scene.player.hideUI(); + //this.scene.player.panel = new PanelWakeUp(this.scene, "A new Contestant"); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelIntroDemo(this.scene); + } else { + this.scene.player.showUI(); + if (flagManager.getFlagById("demoProgress").value === "1") { + this.scene.player.hideUI(); + this.scene.player.panel = new PanelWakeUp(this.scene, "A new Contestant"); + } + } + + this.elevator = new GroupElevator(this.scene, this, { x: 0, y: 0, z: 0 }); + this.elevator.setDraw(true); + + this.hallway = this.scene.geometryController.loadModel("hallway", "modHangarHallway", { x: 0, y: 0, z: 96 - 36 }); + this.hallway.flags.draw = true; + + this.main = this.scene.geometryController.loadModel("main", "modHangarMain", { x: 48, y: 56, z: 96 + 188 }); + this.main.flags.draw = true; + + this.painting = this.scene.geometryController.loadModel("hallway painting", "modHallwayPainting", { x: 0, y: -24, z: 363 }); //364 + this.painting.depthMod = 16; + this.painting.flags.draw = true; + this.painting.data = { + useText: "use computer", + useRadius: 48, + }; + this.painting.interactable = true; + this.painting.interact = () => { + if (this.scene.player.panel === null) { + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelPainting(this.scene); + } + }; + + this.doorRight = this.scene.geometryController.loadModel("hangar door right", "modHangarDoor", { x: 224, y: -44, z: 96 + 236 }); + this.doorRight.flags.draw = true; + this.doorLeft = this.scene.geometryController.loadModel("hangar door left", "modHangarDoor", { x: 224, y: -44, z: 96 + 236 }); + this.doorLeft.flags.draw = true; + this.doorLeft.rotateAroundAxis([0, -1, 0], Math.PI); + /*console.log({ + x: this.doorRight.pos.x - this.main.pos.x, + y: this.doorRight.pos.y - this.main.pos.y, + z: this.doorRight.pos.z - this.main.pos.z + })*/ + + this.ship = this.scene.geometryController.loadModel("ship", "modHoverCarWipeOutStyle", { x: 208 + 16, y: 76 - 8, z: 288 + 32 }); + this.ship.flags.draw = true; + this.ship.deleteQuad(this.ship.quadData[this.ship.quadData.length - 1]); + this.ship.deleteQuad(this.ship.quadData[this.ship.quadData.length - 1]); + this.ship.deleteQuad(this.ship.quadData[this.ship.quadData.length - 1]); + this.ship.deleteQuad(this.ship.quadData[this.ship.quadData.length - 1]); + + this.shipInteractable = this.scene.geometryController.loadModel("ship interactable", "modShipInteractable", { + x: this.ship.pos.x, + y: this.ship.pos.y - 16, + z: this.ship.pos.z + 16, + }); + this.shipInteractable.flags.draw = true; + this.shipInteractable.data = { + useText: "enter ship", + useRadius: 48, + }; + this.shipInteractable.interactable = true; + this.shipInteractable.interact = () => { + if (this.scene.player.panel === null) { + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.setMoveMode(PLAYERMOVE.SHIP); + this.scene.player.panel = new PanelEnterShipDemo00(this.scene, this, { + x: this.scene.player.pos.x, + y: this.scene.player.pos.y, + z: this.scene.player.pos.z, + }); + + this.scene.player.jumpToPosition( + { + x: this.ship.pos.x + this.ship.transform.forward.x * 16 + this.ship.transform.up.x * 32, + y: this.ship.pos.y + this.ship.transform.forward.y * 16 + this.ship.transform.up.y * 32, + z: this.ship.pos.z + this.ship.transform.forward.z * 16 + this.ship.transform.up.z * 32, + }, + true, + ); + //todo: why no worky? + /* + this.scene.player.dir.yaw *= -1; + this.scene.player.dir.pitch *= -1; + this.scene.cam.setPositionAndRotation( + { x: this.scene.player.pos.x, y: this.scene.player.pos.y - this.scene.player.eyeHeight, z: this.scene.player.pos.z}, this.scene.player.dir.yaw * -1 + );*/ + + this.shipInteractable.interactable = false; + } + }; + + this.computer = this.scene.geometryController.loadModel("apartement computer", "modComputer", { x: 118, y: 60 - 12, z: 148 }); + this.computer.rotateAroundAxis([0, -1, 0], Math.PI * 0.76); + this.computer.depthMod = 20; + this.computer.flags.draw = true; + this.computer.data = { + useText: "use computer", + useRadius: 48, + }; + this.computer.interactable = true; + this.computer.interact = () => { + if (this.scene.player.panel === null) { + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelJoeComputer(this.scene); + } + }; + + //maybe we dont need it if addding hangar doors + this.tunnelbox = this.scene.geometryController.loadModel("lift shaft", "modRingD256HangarLift", { x: 224, y: -512, z: 96 + 188 - 16 }); + this.tunnelbox.flags.draw = true; + + this.leavingHangar = false; + this.toTrack = 0; + this.maxLaps = 5; + this.raceMode = 0; + this.hangarTick = 0; + this.liftOff = { + current: 0, + max: 0.5, + }; + + //characters + this.charMechanic = this.scene.geometryController.loadModel("char mechanic", "modCharacterDefaultHuman", { x: 224, y: 88, z: 271 }); + this.charMechanic.quadData[0].setTexture("charSheetRahyMechanic", "rahyMechanicSitIdle0000"); + this.charMechanic.atlas = "charSheetRahyMechanic"; + this.charMechanic.atlas8wayFrame = "rahyMechanicSitIdle010"; + this.charMechanic.scale({ x: 1.4, y: 0.8, z: 1 }); + this.charMechanic.flags.draw = true; + //this.charMechanic.lookDir.yaw = Math.PI * -0.5; + this.charMechanic.setDrawMode(DRAWMODE.BILLBOARD); + this.charMechanic.flags.is8way = true; + this.charMechanic.flags.usesAtlas = true; + this.charMechanic.depthMod = 16; + this.charMechanic.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaDemoHangarMechanic00", + treePosition: 99, + }, + }; + this.charMechanic.interactable = true; + this.charMechanic.interact = () => { + this.charMechanic.lookDir.yaw = Math.atan2(this.scene.player.pos.x - this.charMechanic.pos.x, this.scene.player.pos.z - this.charMechanic.pos.z); + + if (flagManager.getFlagById("desktopBackgroundJoe").value !== "0") { + this.charMechanic.data.conversation.treePosition = 12; + } + + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charMechanic); + this.scene.player.conversationManager.setConversation(this.charMechanic.data.conversation.fileName, this.charMechanic.data.conversation.treePosition); + }; + + this.charRoomba = this.scene.geometryController.loadModel("char roomba", "modCharacterDefaultHuman", { x: 86, y: 56, z: 376 }); + this.charRoomba.quadData[0].setTexture("roomba", 0); + this.charRoomba.scale({ x: 1, y: 0.25, z: 1 }); + this.charRoomba.flags.draw = true; + this.charRoomba.setDrawMode(DRAWMODE.BILLBOARD); + this.charRoomba.depthMod = 32; + this.charRoomba.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaHangar00Roomba00", + treePosition: 0, + }, + waypoints: [ + { x: 144, y: 56, z: 379 }, + { x: 138, y: 56, z: 282 }, + { x: 86, y: 56, z: 376 }, + ], + touchedTimes: 0 + }; + this.charRoomba.interactable = true; + this.charRoomba.interact = () => { + //this.scene.player.setMode(PLAYERMODE.DIALOGUE); + //this.scene.player.conversationManager.setNPC(this.charShop); + //this.scene.player.conversationManager.setConversation(this.charShop.data.conversation.fileName, this.charShop.data.conversation.treePosition); + this.charRoomba.data.touchedTimes += 1; + + if (this.charRoomba.data.touchedTimes >= 3) { + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charRoomba); + this.scene.player.conversationManager.setConversation(this.charRoomba.data.conversation.fileName, this.charRoomba.data.conversation.treePosition); + } + + for (let wp of this.charRoomba.data.waypoints) { + this.charRoomba.mover.targets.push({ + pos: { + x: wp.x, + y: wp.y, + z: wp.z, + spd: 0.1, + }, + dir: { + yaw: this.charRoomba.dir.yaw, + pitch: this.charRoomba.dir.pitch, + roll: this.charRoomba.dir.roll, + spd: 0.01, + }, + jump: false, + }); + } + this.charRoomba.mover.target = this.charRoomba.mover.targets[0]; + this.charRoomba.mover.isMoving = true; + + }; + + + //this.charRoki = this.scene.geometryController.loadModel("char roki", "modCharacterDefaultHuman", { x: 23, y: 0, z: 340 }); + this.charRoki = this.scene.geometryController.loadModel("char roki", "modCharacterDefaultHuman", { x: 23, y: 0, z: 316 }); + this.charRoki.quadData[0].setTexture("turnaroundLarasheet00", 0); + this.charRoki.scale({ x: 1, y: 0.9, z: 1 }); + this.charRoki.flags.draw = true; + this.charRoki.lookDir.yaw = Math.PI * 0.5; + this.charRoki.setDrawMode(DRAWMODE.BILLBOARD); + this.charRoki.flags.is8way = true; + this.charRoki.depthMod = 16; + this.charRoki.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaDemoRoki00", + treePosition: 0, + }, + }; + this.charRoki.interactable = true; + this.charRoki.interact = () => { + this.charRoki.lookDir.yaw = Math.atan2(this.scene.player.pos.x - this.charRoki.pos.x, this.scene.player.pos.z - this.charRoki.pos.z); + + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charRoki); + this.scene.player.conversationManager.setConversation(this.charRoki.data.conversation.fileName, this.charRoki.data.conversation.treePosition); + }; + + /* + this.charRaceDirector = this.scene.geometryController.loadModel("charRaceDirector", "modCharacterDefaultHuman", { x: 41, y: 0, z: 299 }); + this.charRaceDirector.quadData[0].setTexture("charSheetRaceDirector", "paulStandIdle0000"); + this.charRaceDirector.atlas = "charSheetRaceDirector"; + this.charRaceDirector.atlas8wayFrame = "paulStandIdle010"; + this.charRaceDirector.scale({ x: 1, y: 1, z: 1 }); + this.charRaceDirector.flags.draw = true; + this.charRaceDirector.lookDir.yaw = Math.PI * 0.5; + this.charRaceDirector.setDrawMode(DRAWMODE.BILLBOARD); + this.charRaceDirector.flags.is8way = true; + this.charRaceDirector.flags.usesAtlas = true; + this.charRaceDirector.depthMod = 16; + */ + + + + + + //trigger + + + //ship flavour hud text when loading + this.txtChecklists = []; + this.txtChecklists.push( + this.scene.add + .bitmapText(this.scene.game.config.width * -0.5 + 16, this.scene.game.config.height * -0.5 + 16, "uiFont", "initalizing data", 14, 0) + .setOrigin(0, 0.5) + .setLetterSpacing(0), + ); + this.txtChecklists.push( + this.scene.add + .bitmapText(this.scene.game.config.width * -0.5 + 16, this.scene.game.config.height * -0.5 + 32, "uiFont", "Craft System ID: 089IYVU765EE", 14, 0) + .setOrigin(0, 0.5) + .setLetterSpacing(0), + ); + this.txtChecklists.push( + this.scene.add + .bitmapText(this.scene.game.config.width * -0.5 + 16, this.scene.game.config.height * -0.5 + 48, "uiFont", "Engine Subsystems Active", 14, 0) + .setOrigin(0, 0.5) + .setLetterSpacing(0), + ); + this.txtChecklists.push( + this.scene.add + .bitmapText(this.scene.game.config.width * -0.5 + 16, this.scene.game.config.height * -0.5 + 64, "uiFont", "Hyperdrive motor engaged", 14, 0) + .setOrigin(0, 0.5) + .setLetterSpacing(0), + ); + this.txtChecklists.push( + this.scene.add + .bitmapText(this.scene.game.config.width * -0.5 + 16, this.scene.game.config.height * -0.5 + 80, "uiFont", "Elevator clamp engaged", 14, 0) + .setOrigin(0, 0.5) + .setLetterSpacing(0), + ); + this.txtChecklists.push( + this.scene.add + .bitmapText(this.scene.game.config.width * -0.5 + 16, this.scene.game.config.height * -0.5 + 96, "uiFont", "Systems check complete", 14, 0) + .setOrigin(0, 0.5) + .setLetterSpacing(0), + ); + this.txtChecklists.push( + this.scene.add + .bitmapText(this.scene.game.config.width * -0.5 + 16, this.scene.game.config.height * -0.5 + 112, "uiFont", "Craft 100% functional", 14, 0) + .setOrigin(0, 0.5) + .setLetterSpacing(0), + ); + for (let t of this.txtChecklists) { + t.depth = 9999; + t.setTint(0x00ff00); //0xa7d254 //0x58a23c + t.alpha = 0; + } + + //flagManager.setFlag("desktopBackground", "0"); + if (flagManager.getFlagById("desktopBackground").value !== "0") { + this.charMechanic.data.conversation.treePosition = 12; + } + + switch (flagManager.getFlagById("demoProgress").value) { + case "0": + break; + case "1": + //flagManager.setFlag("wonDemoRace", "true"); + this.charRoki.jumpToPosition({ x: 100, y: 56, z: 330 }); + this.charRoki.data.conversation.fileName = "diaDemoRoki00"; + this.charRoki.data.conversation.treePosition = 9; + if (flagManager.getFlagById("wonDemoRace").value === "true") { + this.charRoki.data.conversation.treePosition = 6; + } + + if (this.charMechanic.data.conversation.treePosition === 99) { + this.charMechanic.data.conversation.fileName = "diaDemoHangarMechanic01"; + this.charMechanic.data.conversation.treePosition = 0; + } + break; + case "2": + if (this.charMechanic.data.conversation.treePosition === 99) { + this.charMechanic.data.conversation.fileName = "diaDemoHangarMechanic01"; + this.charMechanic.data.conversation.treePosition = 0; + } + this.charRoki.data.conversation.treePosition = 10; + break; + case "3": + if (this.charMechanic.data.conversation.treePosition === 99) { + this.charMechanic.data.conversation.fileName = "diaDemoHangarMechanic01"; + this.charMechanic.data.conversation.treePosition = 0; + } + this.charRoki.data.conversation.treePosition = 10; + break; + default: + break; + } + } + + update(_delta) { + if (this.leavingHangar === true) { + if (this.scene.soundManager.musicCalmLoop00.howlGroup.playing() === true) { + this.scene.soundManager.stopSound(this.scene.soundManager.musicCalmLoop00); + } + + this.hangarTick += this.scene.dt; + + //blend in checklist + let waitOffset = 100; + if (this.hangarTick > waitOffset) { + for (let i = 0; i < Math.min(this.txtChecklists.length, (this.hangarTick - waitOffset) / 100); i++) { + this.txtChecklists[i].alpha += 0.1 * this.scene.dt; + } + } + + if (this.doorRight.pos.x > 224 - 64) { + this.doorLeft.jumpToPosition( + { + x: this.doorLeft.pos.x + 0.1 * this.scene.dt, + y: this.doorLeft.pos.y, + z: this.doorLeft.pos.z, + }, + true, + ); + this.doorRight.jumpToPosition( + { + x: this.doorRight.pos.x - 0.1 * this.scene.dt, + y: this.doorRight.pos.y, + z: this.doorRight.pos.z, + }, + true, + ); + } + + if (this.ship.pos.y > -44 - 128) { + this.ship.jumpToPosition( + { + x: this.ship.pos.x, + y: this.ship.pos.y - this.liftOff.current * this.scene.dt, + z: this.ship.pos.z, + }, + true, + ); + this.scene.player.pos.y -= this.liftOff.current * this.scene.dt; //0.1 is interesting for a kind of cutscene and then wait for the ship in tunnel with the camera + if (this.liftOff.current < this.liftOff.max) { + this.liftOff.current += 0.001 * this.scene.dt; + this.liftOff.current = Math.min(1, this.liftOff.current); + } + } else { + //rotate game camera to fps camera and load track level + this.scene.playerGame.dir.yaw = this.scene.player.dir.yaw; //- (Math.PI * 0.5); + this.scene.playerGame.dir.pitch = this.scene.player.dir.pitch; // * -1; + this.scene.playerWalk.setVisibility(false); + + this.scene.loadLevel("quadRingsTest", { + track: this.toTrack, + maxLaps: this.maxLaps, + raceMode: this.raceMode, + startFromHangar: true, + playerShipModel: "modHoverCarWipeOutStyle", + }); + } + } else { + if (this.scene.soundManager.musicCalmLoop00.howlGroup.playing() === false) { + this.scene.soundManager.playSound(this.scene.soundManager.musicCalmLoop00); + } + } + } + + startSimulation() { + this.scene.playerGame.dir.yaw = this.scene.player.dir.yaw; //- (Math.PI * 0.5); + this.scene.playerGame.dir.pitch = this.scene.player.dir.pitch; // * -1; + this.scene.playerWalk.setVisibility(false); + + this.scene.loadLevel("quadRingsTest", { + track: this.toTrack, + maxLaps: this.maxLaps, + raceMode: this.raceMode, + startFromHangar: false, + playerShipModel: "modHoverCarWipeOutStyle", + }); + } + + destroy() { + for (let t of this.txtChecklists) { + t.destroy(); + } + this.txtChecklists = []; + } +} diff --git a/src/3d/levels/lvlMarketsquareApartements00.js b/src/3d/levels/lvlMarketsquareApartements00.js new file mode 100755 index 0000000..5c37b01 --- /dev/null +++ b/src/3d/levels/lvlMarketsquareApartements00.js @@ -0,0 +1,525 @@ +import PanelWelcome from "../../ui/panelWelcome.js"; +import GroupElevator from "../groups/grpElevator.js"; +import PanelLoungeRoundtable00 from "../../ui/panelLoungeRoundtable00.js"; + +export default class LevelMarketsquareApartements00 { + constructor(_scene, _params) { + this.scene = _scene; + + //this.ref = this.scene.geometryController.loadModel("levelOrigin", "modDebugTile", { x: 0, y: 0, z: 0 }); + //this.ref.flags.draw = true; + + this.scene.player = this.scene.playerWalk; + this.scene.cam = this.scene.camWalk; + + //this.scene.player.dir.pitch = 0; + + this.elevator = null; + if (_params.lounge === false) { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + this.elevator = new GroupElevator(this.scene, this, { x: 0, y: 0, z: 0 }); + } else { + this.scene.player.jumpToPosition({ x: 0, y: -76, z: 0 }); + this.elevator = new GroupElevator(this.scene, this, { x: 0, y: -76, z: 0 }); + } + this.elevator.setDraw(true); + + this.elevatorRoom = this.scene.geometryController.loadModel("elevatorRoom", "modElevatorRoom", { x: 0, y: 0, z: 96 }); + this.elevatorRoom.flags.draw = true; + + this.square = this.scene.geometryController.loadModel("square", "modMarketsquareApartements", { x: -320, y: -16, z: 96 }); + this.square.flags.draw = true; + + this.staircase = this.scene.geometryController.loadModel("staircase", "modMarketsquareStaircase", { x: -320 - 128, y: -16, z: 96 + 400 }); + this.staircase.flags.draw = true; + + this.lounge = this.scene.geometryController.loadModel("drivers lounge", "modLounge", { x: -144, y: -72, z: 304 }); + this.lounge.flags.draw = true; + + this.loungeTables = []; + let tp = { x: this.lounge.pos.x, y: this.lounge.pos.y, z: this.lounge.pos.z }; + this.loungeTables.push(this.scene.geometryController.loadModel("lounge table 0", "modCafeTableRound", { x: tp.x + 36, y: tp.y, z: tp.z - 58 })); + this.loungeTables.push(this.scene.geometryController.loadModel("lounge table 1", "modCafeTableRound", { x: tp.x + 80, y: tp.y, z: tp.z - 58 })); + this.loungeTables.push(this.scene.geometryController.loadModel("lounge table 2", "modCafeTableRound", { x: tp.x + 120, y: tp.y, z: tp.z - 58 })); + this.loungeTables.push(this.scene.geometryController.loadModel("lounge table 3", "modCafeTableRound", { x: tp.x + 36, y: tp.y, z: tp.z + 58 + 32 })); + this.loungeTables.push(this.scene.geometryController.loadModel("lounge table 4", "modCafeTableRound", { x: tp.x + 80, y: tp.y, z: tp.z + 58 + 32 })); + this.loungeTables.push(this.scene.geometryController.loadModel("lounge table 5", "modCafeTableRound", { x: tp.x + 120, y: tp.y, z: tp.z + 58 + 32 })); + for (let t of this.loungeTables) { + t.depthMod = 8; + t.flags.draw = true; + } + this.loungeTables[1].data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaDemoTableround00", + treePosition: 0, + }, + }; + this.loungeTables[1].interactable = true; + this.loungeTables[1].interact = () => { + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelLoungeRoundtable00(this.scene, this, this.loungeTables[1].data.conversation.treePosition); + }; + flagManager.setFlag("00joseftable", "false"); + let tarr = [this.loungeTables[0], this.loungeTables[3], this.loungeTables[4], this.loungeTables[5]]; + for (let t of tarr) { + t.interactable = true; + t.interact = () => { + let r = Math.floor(Math.random() * 3); + let vx = t.pos.z >= 300 ? -1 : 1; + let ryaw = -0.1 + Math.random() * 0.2; + //jump to a random of 3 positions around table, mirrored x and complicated z ternary + this.scene.player.jumpToPosition({ x: t.pos.x - (r === 2 ? 10 : r === 1 ? 10 : 0), y: t.pos.y, z: t.pos.z - (r === 0 ? 10 * vx : 0) }); + /* + setTimeout(() => { + if (r === 0) { + if (vx === 1) { + this.scene.player.dir.yaw = Math.PI * (-0.5 + ryaw); + } else { + this.scene.player.dir.yaw = Math.PI * (0.5 + ryaw); + } + } else if (r === 1) { + this.scene.player.dir.yaw = Math.PI * (1 + ryaw); + } else { + this.scene.player.dir.yaw = Math.PI * (0 + ryaw); + } + }, 1); + */ + this.scene.player.setMoveMode(PLAYERMOVE.SIT); + + if (flagManager.getFlagById("00joseftable").value === "true") { + if (t.pos.z >= 300) { + this.scene.player.conversationManager.interpret("ADDWAYPOINT charJosef -15 -72 368 0.5 0".split(" ")); //-15 -72 368 + } else { + this.scene.player.conversationManager.interpret("ADDWAYPOINT charJosef -15 -72 276 0.5 0".split(" ")); //-15 -72 276 + } + this.scene.player.conversationManager.interpret(("ADDWAYPOINT charJosef " + String(t.pos.x + 16 * vx) + " -64 " + String(t.pos.z) + " 0.5 0").split(" ")); + //this.scene.player.conversationManager.interpret(("ADDWAYPOINT espresso " + String(t.pos.x) + " -76 " + String(t.pos.z) + " 0.1 1").split(" ")); + + this.josef.data.conversation.treePosition = 9; + this.josef.interact = () => { + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + //this.scene.player.conversationManager.interpret(("ADDWAYPOINT espresso " + String(t.pos.x) + " -76 " + String(t.pos.z) + " 0.1 1").split(" ")); + this.espresso.jumpToPosition({ x: t.pos.x, y: -76, z: t.pos.z }); + this.scene.player.conversationManager.setNPC(this.josef); + this.scene.player.conversationManager.setConversation(this.josef.data.conversation.fileName, this.josef.data.conversation.treePosition); + }; + } + }; + } + tarr = [this.loungeTables[2]]; + for (let t of tarr) { + t.interactable = true; + t.interact = () => { + let r = Math.floor(Math.random() * 3); + let vx = t.pos.z >= 300 ? -1 : 1; + let ryaw = -0.1 + Math.random() * 0.2; + //jump to a random of 3 positions around table, mirrored x and complicated z ternary + this.scene.player.jumpToPosition({ x: t.pos.x - (r === 2 ? 10 : r === 1 ? 10 : 0), y: t.pos.y, z: t.pos.z - (r === 0 ? 10 * vx : 0) }); + + this.charRoki.interact(); + }; + } + + //characters + this.charJosef = this.scene.geometryController.loadModel("charJosef", "modCharacterDefaultHuman", { x: -14, y: -72, z: 320 }); + this.charJosef.quadData[0].setTexture("charSheetJosef", "josefStandIdle0100"); + this.charJosef.atlas = "charSheetJosef"; + this.charJosef.atlas8wayFrame = "josefStandIdle010"; + this.charJosef.scale({ x: 1.4, y: 1, z: 1 }); + this.charJosef.lookDir.yaw = Math.PI * -0.5; + this.charJosef.flags.draw = true; + this.charJosef.setDrawMode(DRAWMODE.BILLBOARD); + this.charJosef.flags.is8way = true; + this.charJosef.flags.usesAtlas = true; + this.charJosef.depthMod = 16; + this.charJosef.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaTestJosef", + treePosition: 0, + }, + }; + this.charJosef.interactable = true; + this.charJosef.interact = () => { + this.charJosef.lookDir.yaw = Math.atan2(this.scene.player.pos.x - this.charJosef.pos.x, this.scene.player.pos.z - this.charJosef.pos.z); + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charJosef); + this.scene.player.conversationManager.setConversation(this.charJosef.data.conversation.fileName, this.charJosef.data.conversation.treePosition); + }; + + this.charGlaze = this.scene.geometryController.loadModel("char glaze", "modCharacterDefaultHuman", { x: -36, y: -72, z: 366 }); + this.charGlaze.quadData[0].setTexture("charSheetGlaze", "glazeStandIdle0000"); + this.charGlaze.atlas = "charSheetGlaze"; + this.charGlaze.atlas8wayFrame = "glazeStandIdle000"; + this.charGlaze.lookDir.yaw = Math.PI * -0.5; + this.charGlaze.flags.draw = true; + this.charGlaze.setDrawMode(DRAWMODE.BILLBOARD); + this.charGlaze.flags.is8way = true; + this.charGlaze.flags.usesAtlas = true; + this.charGlaze.depthMod = 16; + this.charGlaze.data = { + useText: "listen to conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaMarketsquare00Glaze00", + treePosition: 0, + }, + }; + this.charGlaze.interactable = true; + this.charGlaze.interact = () => { + //this.charVip.lookDir.yaw = Math.atan2(this.scene.player.pos.x - this.charVip.pos.x, this.scene.player.pos.z - this.charVip.pos.z); + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charGlaze); + this.scene.player.conversationManager.setConversation(this.charGlaze.data.conversation.fileName, this.charGlaze.data.conversation.treePosition); + }; + + this.charBonez = this.scene.geometryController.loadModel("char bonez", "modCharacterDefaultHuman", { x: -63, y: -72, z: 360 }); + this.charBonez.quadData[0].setTexture("charSheetBonez", "bonezStandIdle00"); + this.charBonez.atlas = "charSheetBonez"; + this.charBonez.atlas8wayFrame = "bonezStandIdle0"; + this.charBonez.scale({ x: 1.25, y: 1, z: 1 }); + this.charBonez.lookDir.yaw = Math.PI * 0.5; + this.charBonez.flags.draw = true; + this.charBonez.setDrawMode(DRAWMODE.BILLBOARD); + this.charBonez.flags.is8way = true; + this.charBonez.flags.usesAtlas = true; + this.charBonez.depthMod = 16; + + //Roki + this.charRoki = this.scene.geometryController.loadModel("charRoki", "modCharacterDefaultHuman", { x: -11, y: -72, z: 244 }); + this.charRoki.quadData[0].setTexture("charSheetRoki", "rokiWalkFrame0000"); + this.charRoki.atlas = "charSheetRoki"; + this.charRoki.atlas8wayFrame = "rokiSitIdle0"; + this.charRoki.scale({ x: 1.25, y: 0.9, z: 1 }); + this.charRoki.flags.draw = true; + this.charRoki.lookDir.yaw = Math.PI * -0.5; + this.charRoki.setDrawMode(DRAWMODE.BILLBOARD); + this.charRoki.flags.is8way = true; + this.charRoki.flags.usesAtlas = true; + this.charRoki.depthMod = 8; + this.charRoki.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaMarketsquare00Roki00", + treePosition: 0, + }, + }; + if (flagManager.getFlagById("wonDemoRace").value === "false") { + this.charRoki.data.conversation.treePosition = 1; + } + this.charRoki.interact = () => { + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charRoki); + this.scene.player.conversationManager.setConversation(this.charRoki.data.conversation.fileName, this.charRoki.data.conversation.treePosition); + }; + + //talking table + this.charScooter = this.scene.geometryController.loadModel("char scooter", "modCharacterDefaultHuman", { x: -50, y: -72, z: 246 }); + this.charScooter.quadData[0].setTexture("charSheetScooter", "HannahWalkFrame0000"); + this.charScooter.atlas = "charSheetScooter"; + this.charScooter.atlas8wayFrame = "hannahSitIdle0"; + this.charScooter.scale({ x: 1.5, y: 1, z: 1 }); + this.charScooter.flags.draw = true; + this.charScooter.lookDir.yaw = Math.PI * -0.5; + this.charScooter.setDrawMode(DRAWMODE.BILLBOARD); + this.charScooter.flags.is8way = true; + this.charScooter.flags.usesAtlas = true; + this.charScooter.depthMod = 8; + + this.charRahy = this.scene.geometryController.loadModel("char rahy", "modCharacterDefaultHuman", { x: -78, y: -72, z: 246 }); + this.charRahy.quadData[0].setTexture("charSheetRahy", "rahySitIdle00"); + this.charRahy.atlas = "charSheetRahy"; + this.charRahy.atlas8wayFrame = "rahySitIdle0"; + this.charRahy.scale({ x: 1.5, y: 1, z: 1 }); + this.charRahy.flags.draw = true; + this.charRahy.lookDir.yaw = Math.PI * 0.5; + this.charRahy.setDrawMode(DRAWMODE.BILLBOARD); + this.charRahy.flags.is8way = true; + this.charRahy.flags.usesAtlas = true; + this.charRahy.depthMod = 4; + + //this.charHog = this.scene.geometryController.loadModel("char hog", "modCharacterDefaultHuman", { x: -84, y: -72, z: 260 }); + this.charHog = this.scene.geometryController.loadModel("char hog", "modCharacterDefaultHuman", { x: -64, y: -72, z: 232 }); + this.charHog.quadData[0].setTexture("charSheetHog", "hogStandIdle0000"); + this.charHog.atlas = "charSheetHog"; + this.charHog.atlas8wayFrame = "hogStandIdle000"; + this.charHog.scale({ x: 1.75, y: 1, z: 1 }); + this.charHog.flags.draw = true; + //this.charHog.lookDir.yaw = Math.PI * 0.75; + this.charHog.lookDir.yaw = Math.PI * 0; + this.charHog.setDrawMode(DRAWMODE.BILLBOARD); + this.charHog.flags.is8way = true; + this.charHog.flags.usesAtlas = true; + this.charHog.depthMod = 16; + + this.espresso = this.scene.geometryController.loadModel("espresso", "modCharacterDefaultHuman", { x: -64, y: -280, z: 1670 }); + this.espresso.quadData[0].setTexture("atlasObjects", "objEspresso00"); + this.espresso.scale({ x: 0.5, y: 0.25, z: 1 }); + this.espresso.flags.draw = true; + this.espresso.flags.usesAtlas = true; + this.espresso.setDrawMode(DRAWMODE.BILLBOARD); + this.espresso.depthMod = 0; + this.espresso.interactable = true; + this.espresso.data = { + useText: "drink", + useSprite: "sprInteract02", + useRadius: 48, + }; + this.espresso.interact = () => { + //this.scene.geometryController.destroyModelById("espresso"); + this.espresso.jumpToPosition({ x: -64, y: -280, z: 1670 }, true); + }; + /* + this.objScrewdriver = this.scene.geometryController.loadModel("object screwdriver", "modCharacterDefaultHuman", { x: -2, y: 60, z: 178 }); + this.objScrewdriver.quadData[0].setTexture("atlasObjects", "texScrewdriver00"); + this.objScrewdriver.scale({ x: 1, y: 0.25, z: 1 }); + this.objScrewdriver.flags.draw = true; + this.objScrewdriver.flags.usesAtlas = true; + this.objScrewdriver.setDrawMode(DRAWMODE.BILLBOARD); + this.objScrewdriver.depthMod = 0; + this.objScrewdriver.interactable = true; + this.objScrewdriver.data = { + useText: "take tool", + useSprite: "sprInteract02", + useRadius: 48, + }; + this.objScrewdriver.interact = () => { + flagManager.setFlag("hangar00tool", "1"); + flagManager.removeFlag("hangar00noTool"); + this.scene.geometryController.destroyModelById("object screwdriver"); + }; + + this.cafeTables.push(this.scene.geometryController.loadModel("cafe table 00", "modCafeTableRound", { x: 10, y: -64, z: 1592 })); + this.cafeTables.push(this.scene.geometryController.loadModel("cafe table 01", "modCafeTableRound", { x: 10, y: -64, z: 1636 })); + this.cafeTables.push(this.scene.geometryController.loadModel("cafe table 02", "modCafeTableRound", { x: 10, y: -64, z: 1676 })); + this.cafeTables.push(this.scene.geometryController.loadModel("cafe table 03", "modCafeTableRound", { x: -140, y: -64, z: 1592 })); + this.cafeTables.push(this.scene.geometryController.loadModel("cafe table 04", "modCafeTableRound", { x: -140, y: -64, z: 1636 })); + this.cafeTables.push(this.scene.geometryController.loadModel("cafe table 05", "modCafeTableRound", { x: -140, y: -64, z: 1676 })); + for(let t of this.cafeTables){ + t.flags.draw = true; + t.interactable = true; + t.interact = () => { + let r = Math.floor(Math.random() * 3); + let vx = t.pos.x >= 0 ? -1 : 1; + let ryaw = -0.1 + (Math.random() * 0.2); + //jump to a random of 3 positions around table, mirrored x and complicated z ternary + this.scene.player.jumpToPosition({ x: t.pos.x - (r === 0 ? (10 * vx) : 0), y: t.pos.y, z: t.pos.z - (r === 2 ? 10 : (r === 1 ? -10 : 0)) }); + setTimeout(() => { + if(r === 0){ + if(vx === 1){ + this.scene.player.dir.yaw = Math.PI * (-0.5 + ryaw); + }else{ + this.scene.player.dir.yaw = Math.PI * (0.5 + ryaw); + } + }else if(r === 1){ + this.scene.player.dir.yaw = Math.PI * (1 + ryaw); + }else{ + this.scene.player.dir.yaw = Math.PI * (0 + ryaw); + } + }, 1); + this.scene.player.setMoveMode(PLAYERMOVE.SIT); + + if(flagManager.getFlagById("00joseftable").value === "true"){ + if(t.pos.x >= 0){ + this.scene.player.conversationManager.interpret(("ADDWAYPOINT Josef -16 -64 1686 0.5 0").split(" ")); + }else{ + this.scene.player.conversationManager.interpret(("ADDWAYPOINT Josef -112 -64 1686 0.5 0").split(" ")); + } + this.scene.player.conversationManager.interpret(("ADDWAYPOINT Josef " + String(t.pos.x + (16 * vx)) + " -64 " + String(t.pos.z) + " 0.5 0").split(" ")); + //this.scene.player.conversationManager.interpret(("ADDWAYPOINT espresso " + String(t.pos.x) + " -76 " + String(t.pos.z) + " 0.1 1").split(" ")); + + this.josef.data.conversation.treePosition = 5; + this.josef.interact = () => { + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.interpret(("ADDWAYPOINT espresso " + String(t.pos.x) + " -76 " + String(t.pos.z) + " 0.1 1").split(" ")); + this.scene.player.conversationManager.setNPC(this.josef); + this.scene.player.conversationManager.setConversation(this.josef.data.conversation.fileName, this.josef.data.conversation.treePosition); + } + } + } + } + */ + + //barbara + this.charBarbara = this.scene.geometryController.loadModel("char barbara 00", "modCharacterDefaultHuman", { x: 208, y: -72 - 16, z: 288 }); + this.charBarbara.quadData[0].setTexture("hlBarabara", 0); + this.charBarbara.flags.draw = true; + this.charBarbara.setDrawMode(DRAWMODE.BILLBOARD); + this.charBarbara.depthMod = 16; + + //market + this.charVip = this.scene.geometryController.loadModel("char vip", "modCharacterDefaultHuman", { x: -333, y: -16, z: 107 }); + this.charVip.quadData[0].setTexture("charSheetGlaze", "vipStandIdle00"); + this.charVip.atlas = "charSheetVip"; + this.charVip.atlas8wayFrame = "vipStandIdle0"; + this.charVip.lookDir.yaw = Math.PI; + this.charVip.flags.draw = true; + this.charVip.setDrawMode(DRAWMODE.BILLBOARD); + this.charVip.flags.is8way = true; + this.charVip.flags.usesAtlas = true; + this.charVip.depthMod = 16; + this.charVip.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaMarketsquare00Vip00", + treePosition: 0, + }, + }; + this.charVip.interactable = true; + this.charVip.interact = () => { + this.charVip.lookDir.yaw = Math.atan2(this.scene.player.pos.x - this.charVip.pos.x, this.scene.player.pos.z - this.charVip.pos.z); + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charVip); + this.scene.player.conversationManager.setConversation(this.charVip.data.conversation.fileName, this.charVip.data.conversation.treePosition); + }; + + /*this.charMoritz = this.scene.geometryController.loadModel("char moritz", "modCharacterDefaultHuman", { x: -300, y: -16, z: 112 }); + this.charMoritz.quadData[0].setTexture("turnaroundMoritz00", 0); + this.charMoritz.lookDir.yaw = Math.PI * 0.5; + this.charMoritz.flags.draw = true; + this.charMoritz.setDrawMode(DRAWMODE.BILLBOARD); + this.charMoritz.flags.is8way = true; + this.charMoritz.depthMod = 16;*/ + + this.charJay = this.scene.geometryController.loadModel("char jay", "modCharacterDefaultHuman", { x: -300, y: -16, z: 112 }); + this.charJay.quadData[0].setTexture("charSheetJay", "jayStandIdle0000"); + this.charJay.atlas = "charSheetJay"; + this.charJay.atlas8wayFrame = "jayStandIdle000"; + this.charJay.lookDir.yaw = Math.PI * 0.8; + this.charJay.flags.draw = true; + this.charJay.setDrawMode(DRAWMODE.BILLBOARD); + this.charJay.flags.is8way = true; + this.charJay.flags.usesAtlas = true; + this.charJay.depthMod = 16; + this.charJay.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaMarketsquare00Jay00", + treePosition: 0, + }, + }; + this.charJay.interactable = true; + this.charJay.interact = () => { + this.charJay.lookDir.yaw = Math.atan2(this.scene.player.pos.x - this.charJay.pos.x, this.scene.player.pos.z - this.charJay.pos.z); + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charJay); + this.scene.player.conversationManager.setConversation(this.charJay.data.conversation.fileName, this.charJay.data.conversation.treePosition); + }; + + this.charRoomba = this.scene.geometryController.loadModel("char roomba", "modCharacterDefaultHuman", { x: -288, y: -16, z: 176 }); + this.charRoomba.quadData[0].setTexture("roomba", 0); + this.charRoomba.scale({ x: 1, y: 0.25, z: 1 }); + this.charRoomba.flags.draw = true; + this.charRoomba.setDrawMode(DRAWMODE.BILLBOARD); + this.charRoomba.depthMod = 32; + this.charRoomba.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaMarketsquare00Roomba00", + treePosition: 0, + }, + }; + this.charRoomba.interactable = true; + this.charRoomba.interact = () => { + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charRoomba); + this.scene.player.conversationManager.setConversation(this.charRoomba.data.conversation.fileName, this.charRoomba.data.conversation.treePosition); + }; + + this.charShop = this.scene.geometryController.loadModel("charBooker", "modCharacterDefaultHuman", { x: -372, y: -16, z: 445 }); + this.charShop.quadData[0].setTexture("charSheetBooker", "bookerStandIdle0000"); + this.charShop.atlas = "charSheetBooker"; + this.charShop.atlas8wayFrame = "bookerStandIdle000"; + this.charShop.lookDir.yaw = Math.PI; + this.charShop.flags.draw = true; + this.charShop.setDrawMode(DRAWMODE.BILLBOARD); + this.charShop.flags.is8way = true; + this.charShop.flags.usesAtlas = true; + this.charShop.depthMod = 0; + this.charShop.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaMarketsquare00Booker00", + treePosition: 0, + }, + }; + this.charShop.interactable = true; + this.charShop.interact = () => { + this.charShop.lookDir.yaw = Math.atan2(this.scene.player.pos.x - this.charShop.pos.x, this.scene.player.pos.z - this.charShop.pos.z); + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charShop); + this.scene.player.conversationManager.setConversation(this.charShop.data.conversation.fileName, this.charShop.data.conversation.treePosition); + }; + + this.charJason = this.scene.geometryController.loadModel("char jason", "modCharacterDefaultHuman", { x: 35, y: 0, z: 97 }); + this.charJason.quadData[0].setTexture("charSheetJasonguard", "jasonguardStandPose00"); + this.charJason.atlas = "charSheetJasonguard"; + this.charJason.atlas8wayFrame = "jasonguardStandPose0"; + this.charJason.lookDir.yaw = Math.PI * -0.5; + this.charJason.flags.draw = true; + this.charJason.setDrawMode(DRAWMODE.BILLBOARD); + this.charJason.flags.is8way = true; + this.charJason.flags.usesAtlas = true; + this.charJason.depthMod = 16; + this.charJason.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaMarketsquare00Jay00", + treePosition: 0, + }, + }; + this.charJason.interactable = true; + this.charJason.interact = () => { + this.charJason.lookDir.yaw = Math.atan2(this.scene.player.pos.x - this.charJason.pos.x, this.scene.player.pos.z - this.charJason.pos.z); + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charJason); + this.scene.player.conversationManager.setConversation(this.charJason.data.conversation.fileName, this.charJason.data.conversation.treePosition); + }; + + //trigger + //trigger elevator to follow player + this.triggerElevatorDown = this.scene.geometryController.loadModel("trigger elevator down", "modTriggerWall1x1", { x: -160, y: 0, z: 4 }); + this.triggerElevatorDown.scale({ x: 32, y: 32, z: 1 }); + this.triggerElevatorDown.rotateAroundAxis([0, -1, 0], Math.PI * 0.5); + this.triggerElevatorDown.depthMod = 32; + this.triggerElevatorDown.trigger.isTrigger = true; + this.triggerElevatorDown.trigger.onEnter = () => { + this.elevator.setPosition({ x: 0, y: 0, z: 0 }); + }; + + this.triggerElevatorUp = this.scene.geometryController.loadModel("trigger elevator down", "modTriggerWall1x1", { x: 26, y: -80, z: 232 }); + this.triggerElevatorUp.scale({ x: 32, y: 32, z: 1 }); + this.triggerElevatorUp.depthMod = 32; + this.triggerElevatorUp.trigger.isTrigger = true; + this.triggerElevatorUp.trigger.onEnter = () => { + this.elevator.setPosition({ x: 0, y: -76, z: 0 }); + }; + } + + update(_delta) { + if (this.scene.soundManager.musicCalmLoop00.howlGroup.playing() === false) { + this.scene.soundManager.playSound(this.scene.soundManager.musicCalmLoop00); + } + } + + destroy() { } +} diff --git a/src/3d/levels/lvlMenu3d.js b/src/3d/levels/lvlMenu3d.js new file mode 100644 index 0000000..de4e3b9 --- /dev/null +++ b/src/3d/levels/lvlMenu3d.js @@ -0,0 +1,478 @@ +import PanelTunnelMainMenu from "../../ui/panelTunnelMainMenu.js"; +import PanelTunnelSelector from "../../ui/panelTunnelSelector.js"; +import ShipManager from "../racing/shipManager.js"; +import TrackBuilder from "../racing/trackBuilder.js"; + +export default class LevelMenu3d { + constructor(_scene, _params) { + this.scene = _scene; + this.params = _params; + + this.states = { + main: 0, + shipSelection: 1, + trackSelection: 2, + options: 3, + credits: 4, + }; + this.state = this.states.main; + + flagManager.setFlag("playingStory", "0"); + flagManager.setFlag("playingDemo", "0"); + + this.actions = []; + + /*this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.scene.player.setVisibility(false);*/ + + if (this.scene.soundManager.musicCalmLoop00.howlGroup.playing() === true) { + this.scene.soundManager.stopSound(this.scene.soundManager.musicCalmLoop00); + } + + this.mainMusic = this.scene.soundManager.musicMenu01; + this.scene.soundManager.playSound(this.mainMusic); + /*//INFO test audio for layered music + this.mainMusic = [ + this.scene.soundManager.musicBassLoop00, + this.scene.soundManager.musicSynthLoop00, + this.scene.soundManager.musicPianoLoop00, + this.scene.soundManager.musicRythmLoop00 + ]; + this.scene.soundManager.fadeMusicLayer(this.mainMusic, 0, 1, 0);*/ + + //this.scene.player.jumpToPosition({ x: 0, y: 0, z: -128 }); + //this.scene.player.dir.pitch = 0; + this.scene.player = this.scene.playerGame; + this.scene.cam = this.scene.camGame; + this.scene.player.setMode(PLAYERMODE.INTERACT); + //console.log(this.scene.player.panel); + this.scene.player.panel = new PanelTunnelMainMenu(this.scene, this); + //this.scene.player.panel = new PanelTunnelSelector(this.scene, this); + + //fake track for the moving ships ["modHoverCarWipeOutStyle",/* "modHoverCarF1",*/ "modHoverCarTinnemann00", "modHoverCarHapton00"]; + this.trackBuilder = new TrackBuilder(this.scene, this); + this.trackBuilder.loadTrack(9999); + + this.trackPreview = new TrackBuilder(this.scene, this); + this.trackPreview.loadTrack(9999, true); + + this.speed = { + idle: 6, + switching: 16, + }; + + this.aiShips = []; + this.aiShips.push(new ShipManager(this.scene, this, 0, false, false, "modHoverCarWipeOutStyle")); + this.aiShips[0].name = "Arashi"; + this.aiShips[0].character = this.scene.characters.filter(el => el.name === "Roki")[0]; + this.aiShips.push(new ShipManager(this.scene, this, 1, false, false, "modHoverCarF1")); + this.aiShips[1].setShipColor("Yellow"); + this.aiShips[1].name = "Daito"; + this.aiShips[1].character = this.scene.characters.filter(el => el.name === "Foxxy")[0]; + this.aiShips.push(new ShipManager(this.scene, this, 2, false, false, "modHoverCarTinnemann00")); + this.aiShips[2].setShipColor("Blue"); + this.aiShips[2].name = "Tinnemann"; + this.aiShips[2].character = this.scene.characters.filter(el => el.name === "Glaze")[0]; + this.aiShips.push(new ShipManager(this.scene, this, 3, false, false, "modHoverCarHapton00")); + this.aiShips[3].setShipColor("Green"); + this.aiShips[3].name = "Hampton"; + this.aiShips[3].character = this.scene.characters.filter(el => el.name === "Jo")[0]; + + this.aiShips.push(new ShipManager(this.scene, this, 2, false, false, "modHoverCarHapton00")); + this.aiShips[4].setShipColor("Blue"); + this.aiShips[4].name = "Unknown"; + this.aiShips[4].character = this.scene.characters.filter(el => el.name === "Bonez")[0]; + + this.aiShips.push(new ShipManager(this.scene, this, 0, false, false, "modHoverCarWipeOutStyle")); + this.aiShips[5].setShipColor("Red"); + this.aiShips[5].name = "Arashi"; + this.aiShips[5].character = this.scene.characters.filter(el => el.name === "Hog")[0]; + this.aiShips.push(new ShipManager(this.scene, this, 1, false, false, "modHoverCarF1")); + this.aiShips[6].setShipColor("Yellow"); + this.aiShips[6].name = "Daito"; + this.aiShips[6].character = this.scene.characters.filter(el => el.name === "Roach")[0]; + this.aiShips.push(new ShipManager(this.scene, this, 2, false, false, "modHoverCarTinnemann00")); + this.aiShips[7].setShipColor("Blue"); + this.aiShips[7].name = "Tinnemann"; + this.aiShips[7].character = this.scene.characters.filter(el => el.name === "Jay")[0]; + this.aiShips.push(new ShipManager(this.scene, this, 3, false, false, "modHoverCarHapton00")); + this.aiShips[8].setShipColor("Blue"); + this.aiShips[8].name = "Hampton"; + this.aiShips[8].character = this.scene.characters.filter(el => el.name === "Scooter")[0]; + + this.aiShips.push(new ShipManager(this.scene, this, 3, false, false, "modHoverCarF1")); + this.aiShips[9].setShipColor("Green"); + this.aiShips[9].name = "Unknown"; + this.aiShips[9].character = this.scene.characters.filter(el => el.name === "Director")[0]; + + //blackout locked ships to be silhuetted + for (let ai of this.aiShips) { + if (ai.character.locked === true) { + for (let q of ai.ship.quadData) { + q.setTexture("atlasAll", "flatPal00Black"); + } + } + } + + this.trackIds = [0, 1, 2, 3, 4]; + this.trackSelected = Math.floor(Math.random() * this.trackIds.length); + + //camera ship + this.cameraShip = new ShipManager(this.scene, this, 0, false, false, "modHoverCarWipeOutStyle"); + this.cameraShip.setDraw(false); + this.cameraShip.speed = this.speed.idle; + + //todo: speed up when changing ships to rotate through them + //this.aiShips.push(new ShipManager(this.scene, this, 1, false, false)); + this.shipSelected = 0; + this.playerShip = this.aiShips[0]; + + for (let ai of this.aiShips) { + //ai.setDraw(false); + ai.speed = this.speed.idle; + + ai.splineId = this.trackBuilder.spline.length - 30; + let jp = this.trackBuilder.spline[ai.splineId]; + ai.gondula.jumpToPosition({ x: jp.x, y: jp.y, z: jp.z }); + } + + //INFO done in the menu + //this.scene.player.setVisibility(false); + + this.camRig = this.scene.geometryController.loadModel("hoverShip", "modDebugTile", { x: 0, y: 64, z: 256 }); + + this.camOffset = { + pos: { x: 0, y: 0, z: 0 }, + dir: { yaw: 3.64, pitch: 0.12, roll: 0, spd: { yaw: 0.04, pitch: 0.04, roll: 0.04 } }, + target: { + pos: { x: 0, y: 0, z: 0 }, + dir: { yaw: 3.64, pitch: 0.12, roll: 0, spd: { yaw: 0.04, pitch: 0.04, roll: 0.04 } }, + }, + step: { + pos: { x: 0, y: 0, z: 0 }, + dir: { yaw: 0, pitch: 0, roll: 0, spd: { yaw: 0.04, pitch: 0.04, roll: 0.04 } }, + }, + }; + this.lerper = 0; + + this.camPositions = { + main: { + pos: { x: 0, y: 0, z: 0 }, + dir: { yaw: 0, pitch: 0, roll: 0, spd: { yaw: 0.04, pitch: 0.04, roll: 0.04 } }, + fixed: true, + }, + back: { + pos: { x: 0, y: 0, z: 0 }, + dir: { yaw: Math.PI, pitch: 0.12, roll: 0, spd: { yaw: 0.04, pitch: 0.04, roll: 0.04 } }, + fixed: true, + }, + trackSelection: { + pos: { x: 0, y: 0, z: 0 }, + //dir: { yaw: 3.64, pitch: 0.12, roll: 0, spd: { yaw: 0.04, pitch: 0.04, roll: 0.04 }}, + dir: { yaw: Math.PI * -0.95, pitch: -1.5, roll: 0, spd: { yaw: 0.04, pitch: 0.04, roll: 0.04 } }, + fixed: true, + }, + shipSelection: { + pos: { x: 0, y: 0, z: 0 }, + //dir: { yaw: 3.64, pitch: 0.12, roll: 0, spd: { yaw: 0.04, pitch: 0.04, roll: 0.04 }}, + dir: { yaw: Math.PI * -0.95, pitch: 0.12, roll: 0, spd: { yaw: 0.04, pitch: 0.04, roll: 0.04 } }, + fixed: true, + }, + options: { + pos: { x: 0, y: 0, z: 0 }, + dir: { yaw: Math.PI * -0.5, pitch: 0, roll: 0, spd: { yaw: 0.04, pitch: 0.04, roll: 0.04 } }, + fixed: true, + }, + }; + this.handControlled = false; + //this.scene.player.setMode(PLAYERMODE.LOOK); + + this.graphics = this.scene.add.graphics(); + this.graphics.depth = 9999; + this.graphics.lineStyle(1, 0xffffff, 1); //0x00e436 + this.graphics.beginPath(); + this.graphics.moveTo(0, this.scene.game.config.height * -0.5 + 16); + this.graphics.lineTo(0, this.scene.game.config.height * 0.5 - 16); + this.graphics.strokePath(); + this.graphics.beginPath(); + this.graphics.moveTo(this.scene.game.config.width * -0.5 + 16, 0); + this.graphics.lineTo(this.scene.game.config.width * 0.5 - 16, 0); + this.graphics.strokePath(); + this.graphics.alpha = 0; + + this.camOffset.dir.yaw = this.camPositions.main.dir.yaw; + this.camOffset.dir.pitch = this.camPositions.main.dir.pitch; + this.camOffset.pos.x = this.cameraShip.ship.pos.x + this.scene.cam.transform.forward.x * -256 + this.cameraShip.ship.transform.up.x * 112; + this.camOffset.pos.y = this.cameraShip.ship.pos.y + this.scene.cam.transform.forward.y * -256 + this.cameraShip.ship.transform.up.y * 112; + this.camOffset.pos.z = this.cameraShip.ship.pos.z + this.scene.cam.transform.forward.z * -256 + this.cameraShip.ship.transform.up.z * 112; + + this.calculateLerpStep(); + + this.handInteracted = false; + } + + update(_delta) { + //try to start music + if (this.handInteracted === false && this.scene.hand.pressed === true) { + this.handInteracted = true; + } + //old one layered music track + if (this.mainMusic.howlGroup.playing() === false && this.handInteracted === true) { + this.scene.soundManager.playSound(this.mainMusic); + } + /*//INFO test audio for layered music + if(this.mainMusic[0].howlGroup.playing() === false && this.handInteracted === true){ + this.scene.soundManager.playLayeredMusic(this.mainMusic); + this.scene.soundManager.fadeMusicLayer(this.mainMusic, 0, 1, 0); + } + */ + + //this.calculateLerpStep(); //<--somehow calculating this all the time works to move the camera with the track and lerp between the camera points + this.calculateTarget(); + + if (this.lerper > 0) { + this.lerper -= 1 * this.scene.dt; //0.1 + if (this.lerper <= 0) { + this.lerper = 0; + + if (this.actions.length > 0) { + this.actions[this.actions.length - 1](); + } + } + } + + this.camOffset.dir.yaw = this.camOffset.target.dir.yaw + this.camOffset.step.dir.yaw * this.lerper; + this.camOffset.dir.pitch = this.camOffset.target.dir.pitch + this.camOffset.step.dir.pitch * this.lerper; + this.camOffset.pos.x = this.camOffset.target.pos.x + this.camOffset.step.pos.x * this.lerper; + this.camOffset.pos.y = this.camOffset.target.pos.y + this.camOffset.step.pos.y * this.lerper; + this.camOffset.pos.z = this.camOffset.target.pos.z + this.camOffset.step.pos.z * this.lerper; + + //toggle Tunnel rings based on distance + let frontLimit = Math.min(60, this.trackBuilder.spline.length); //60 + let rearLimit = Math.min(62, this.trackBuilder.spline.length - 1); //59 + for (let i = 0; i < frontLimit; i++) { + let fsid = this.cameraShip.splineId + i; + if (fsid >= this.trackBuilder.spline.length) { + fsid -= this.trackBuilder.spline.length; + } + if (this.trackBuilder.spline[fsid].model !== null) { + this.trackBuilder.spline[fsid].model.flags.draw = true; + } + + if (this.trackBuilder.spline[this.cameraShip.splineId].model !== null) { + this.trackBuilder.spline[this.cameraShip.splineId].model.flags.draw = true; + } + } + for (let i = 0; i < rearLimit; i++) { + let rsid = this.cameraShip.splineId - i; + if (rsid < 0) { + rsid += this.trackBuilder.spline.length; + } + if (i < rearLimit - 3) { + if (this.trackBuilder.spline[rsid].model !== null) { + this.trackBuilder.spline[rsid].model.flags.draw = true; + } + } else { + if (this.trackBuilder.spline[rsid].model !== null) { + this.trackBuilder.spline[rsid].model.flags.draw = false; + } + } + } + + //auto move ship and camera + this.cameraShip.updateSelection(_delta); + //stop current playerShip at camera + let ai = this.playerShip; + let stopSplineId = this.cameraShip.splineId - 3; + if (stopSplineId < 0) { + stopSplineId += this.trackBuilder.spline.length; + } + let d = eud.distance( + [ai.gondula.pos.x, ai.gondula.pos.y, ai.gondula.pos.z], + [this.trackBuilder.spline[stopSplineId].x, this.trackBuilder.spline[stopSplineId].y, this.trackBuilder.spline[stopSplineId].z], + ); + if (d <= this.scene.dt * ai.speed) { + //stop current playerShip + ai.speed = this.speed.idle; + } + //update AI ships + for (let ai of this.aiShips) { + ai.updateSelection(_delta); + //jump ship back to start when moving out of frame + let stopSplineId = this.cameraShip.splineId + 4; + if (stopSplineId > this.trackBuilder.spline.length - 1) { + stopSplineId -= this.trackBuilder.spline.length; + } + if (ai.splineId === stopSplineId) { + let targetId = this.cameraShip.splineId - 30; + if (targetId < 0) { + targetId += this.trackBuilder.spline.length; + } + ai.jumpToSplineId(targetId); + ai.speed = this.speed.idle; + } + } + + this.camRig.transform.up.x = this.cameraShip.ship.transform.up.x; + this.camRig.transform.up.y = this.cameraShip.ship.transform.up.y; + this.camRig.transform.up.z = this.cameraShip.ship.transform.up.z; + this.camRig.transform.right.x = this.cameraShip.ship.transform.right.x; + this.camRig.transform.right.y = this.cameraShip.ship.transform.right.y; + this.camRig.transform.right.z = this.cameraShip.ship.transform.right.z; + this.camRig.transform.forward.x = this.cameraShip.ship.transform.forward.x; + this.camRig.transform.forward.y = this.cameraShip.ship.transform.forward.y; + this.camRig.transform.forward.z = this.cameraShip.ship.transform.forward.z; + + if (this.handControlled === true) { + if (this.scene.hand.vel.x !== 0) { + this.camOffset.dir.yaw += this.scene.hand.vel.x * this.scene.player.dir.spd.yaw; + } + if (this.scene.hand.vel.y !== 0) { + this.camOffset.dir.pitch += this.scene.hand.vel.y * this.scene.player.dir.spd.pitch; + } + this.camOffset.dir.pitch = Math.max(-HALFPI, Math.min(HALFPI, this.camOffset.dir.pitch)); + console.log(this.camOffset.dir.yaw.toFixed(2) + " - " + this.camOffset.dir.roll.toFixed(2) + " - " + this.camOffset.dir.pitch.toFixed(2)); + } else { + //previously this.calculateTarget and without .target. before + } + + this.scene.player.jumpToPosition( + { + //: this.cameraShip.ship.pos.x + (this.scene.cam.transform.forward.x * -256) + (this.cameraShip.ship.transform.up.x * 32), + //: this.cameraShip.ship.pos.y + (this.scene.cam.transform.forward.y * -256) + (this.cameraShip.ship.transform.up.y * 32), + //: this.cameraShip.ship.pos.z + (this.scene.cam.transform.forward.z * -256) + (this.cameraShip.ship.transform.up.z * 32) + x: this.camOffset.pos.x, + y: this.camOffset.pos.y, + z: this.camOffset.pos.z, + }, + true, + ); + + this.camRig.rotateAroundAxis(this.cameraShip.gondula.transform.toVectorArray(this.camRig.transform.up), this.camOffset.dir.yaw); + this.camRig.rotateAroundAxis(this.cameraShip.gondula.transform.toVectorArray(this.camRig.transform.right), this.camOffset.dir.pitch); + + let rotFactor = 0.5; + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo( + targetRot, + this.scene.cam.transform.toVectorArray(this.scene.cam.transform.right), + this.scene.cam.transform.toVectorArray(this.camRig.transform.right), //cameraShip.ship for rotation with ship + ); + let rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.scene.cam.transform.rotationQuat, targetRot, rotFactor); + this.scene.cam.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo( + targetRot, + this.scene.cam.transform.toVectorArray(this.scene.cam.transform.up), + this.scene.cam.transform.toVectorArray(this.camRig.transform.up), //cameraShip.ship for rotation with ship + ); + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.scene.cam.transform.rotationQuat, targetRot, rotFactor); + this.scene.cam.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo( + targetRot, + this.scene.cam.transform.toVectorArray(this.scene.cam.transform.forward), + this.scene.cam.transform.toVectorArray(this.camRig.transform.forward), //cameraShip.ship for rotation with ship + ); + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.scene.cam.transform.rotationQuat, targetRot, rotFactor); + this.scene.cam.rotateByQuaternion(rot); + } + + makeBtnNFS(_btn) { + _btn.colors.out = 0x1d2b53; + _btn.textColors.out = 0xfff1e8; + _btn.textColors.on = 0x00e436; + _btn.useOtherTextColor = true; + _btn.colorInState(_btn.state); + _btn.sprite.alpha = 0.5; + } + + calculateLerpStep() { + this.calculateTarget(); + + this.camOffset.step.dir.yaw = (this.camOffset.dir.yaw - this.camOffset.target.dir.yaw) * 0.01; + this.camOffset.step.dir.pitch = (this.camOffset.dir.pitch - this.camOffset.target.dir.pitch) * 0.01; + this.camOffset.step.pos.x = (this.camOffset.pos.x - this.camOffset.target.pos.x) * 0.01; + this.camOffset.step.pos.y = (this.camOffset.pos.y - this.camOffset.target.pos.y) * 0.01; + this.camOffset.step.pos.z = (this.camOffset.pos.z - this.camOffset.target.pos.z) * 0.01; + } + + calculateTarget() { + switch (this.state) { + case this.states.main: + this.camOffset.target.dir.yaw = this.camPositions.main.dir.yaw; + this.camOffset.target.dir.pitch = this.camPositions.main.dir.pitch; + this.camOffset.target.pos.x = this.cameraShip.ship.pos.x + this.scene.cam.transform.forward.x * -1 + this.cameraShip.ship.transform.up.x * 112; + this.camOffset.target.pos.y = this.cameraShip.ship.pos.y + this.scene.cam.transform.forward.y * -1 + this.cameraShip.ship.transform.up.y * 112; + this.camOffset.target.pos.z = this.cameraShip.ship.pos.z + this.scene.cam.transform.forward.z * -1 + this.cameraShip.ship.transform.up.z * 112; + break; + case this.states.shipSelection: + this.camOffset.target.dir.yaw = this.camPositions.shipSelection.dir.yaw; + this.camOffset.target.dir.pitch = this.camPositions.shipSelection.dir.pitch; + //this.camOffset.target.pos.x = this.cameraShip.ship.pos.x + (this.scene.cam.transform.forward.x * -128) + (this.cameraShip.ship.transform.up.x * 32); + //this.camOffset.target.pos.y = this.cameraShip.ship.pos.y + (this.scene.cam.transform.forward.y * -128) + (this.cameraShip.ship.transform.up.y * 32); + //this.camOffset.target.pos.z = this.cameraShip.ship.pos.z + (this.scene.cam.transform.forward.z * -128) + (this.cameraShip.ship.transform.up.z * 32); + + this.camOffset.target.pos.x = + this.cameraShip.ship.pos.x + this.scene.cam.transform.forward.x * -1 + this.cameraShip.ship.transform.up.x * 32 + this.cameraShip.ship.transform.right.x * 32; + this.camOffset.target.pos.y = + this.cameraShip.ship.pos.y + this.scene.cam.transform.forward.y * -1 + this.cameraShip.ship.transform.up.y * 32 + this.cameraShip.ship.transform.right.y * 32; + this.camOffset.target.pos.z = + this.cameraShip.ship.pos.z + this.scene.cam.transform.forward.z * -1 + this.cameraShip.ship.transform.up.z * 32 + this.cameraShip.ship.transform.right.z * 32; + + //this.camOffset.target.dir.yaw += (this.scene.hand.pos.x * this.scene.player.dir.spd.yaw) * 0.01; + //this.camOffset.target.dir.yaw = Math.max(this.camOffset.dir.yaw - HALFPI, Math.min(this.camOffset.dir.yaw + HALFPI, this.camOffset.target.dir.yaw)); + //this.camOffset.target.dir.pitch += (this.scene.hand.pos.y * this.scene.player.dir.spd.pitch) * 0.01; + //this.camOffset.target.dir.pitch = Math.max(this.camOffset.dir.pitch - HALFPI, Math.min(this.camOffset.dir.pitch + HALFPI, this.camOffset.target.dir.pitch)); + break; + case this.states.trackSelection: + this.camOffset.target.dir.yaw = this.camPositions.trackSelection.dir.yaw; + this.camOffset.target.dir.pitch = this.camPositions.trackSelection.dir.pitch; + this.camOffset.target.pos.x = + this.cameraShip.ship.pos.x + this.scene.cam.transform.forward.x * -1 + this.cameraShip.ship.transform.up.x * 32 + this.cameraShip.ship.transform.right.x * 32; + this.camOffset.target.pos.y = + this.cameraShip.ship.pos.y + this.scene.cam.transform.forward.y * -1 + this.cameraShip.ship.transform.up.y * 32 + this.cameraShip.ship.transform.right.y * 32; + this.camOffset.target.pos.z = + this.cameraShip.ship.pos.z + this.scene.cam.transform.forward.z * -1 + this.cameraShip.ship.transform.up.z * 32 + this.cameraShip.ship.transform.right.z * 32; + break; + case this.states.options: + this.camOffset.target.dir.yaw = this.camPositions.options.dir.yaw; + this.camOffset.target.dir.pitch = this.camPositions.options.dir.pitch; + this.camOffset.target.pos.x = + this.cameraShip.ship.pos.x + this.scene.cam.transform.forward.x * -1 + this.cameraShip.ship.transform.up.x * 32 + this.cameraShip.ship.transform.right.x * 32; + this.camOffset.target.pos.y = + this.cameraShip.ship.pos.y + this.scene.cam.transform.forward.y * -1 + this.cameraShip.ship.transform.up.y * 32 + this.cameraShip.ship.transform.right.y * 32; + this.camOffset.target.pos.z = + this.cameraShip.ship.pos.z + this.scene.cam.transform.forward.z * -1 + this.cameraShip.ship.transform.up.z * 32 + this.cameraShip.ship.transform.right.z * 32; + break; + default: + this.camOffset.target.dir.yaw = this.camPositions.main.dir.yaw; + this.camOffset.target.dir.pitch = this.camPositions.main.dir.pitch; + this.camOffset.target.pos.x = this.cameraShip.ship.pos.x + this.scene.cam.transform.forward.x * -256 + this.cameraShip.ship.transform.up.x * 32; + this.camOffset.target.pos.y = this.cameraShip.ship.pos.y + this.scene.cam.transform.forward.y * -256 + this.cameraShip.ship.transform.up.y * 32; + this.camOffset.target.pos.z = this.cameraShip.ship.pos.z + this.scene.cam.transform.forward.z * -256 + this.cameraShip.ship.transform.up.z * 32; + break; + } + } + + quitToMenu() { + this.scene.player = this.scene.playerWalk; + this.scene.cam = this.scene.camWalk; + + this.scene.player.setVisibility(true); + } + + destroy(_toWalk = false) { + this.graphics.destroy(); + + if (_toWalk === true) { + this.quitToMenu(); + } + } +} diff --git a/src/3d/levels/lvlModelbuilder.js b/src/3d/levels/lvlModelbuilder.js new file mode 100755 index 0000000..90a476b --- /dev/null +++ b/src/3d/levels/lvlModelbuilder.js @@ -0,0 +1,261 @@ +export default class LevelModelbuilder { + constructor(_scene) { + this.scene = _scene; + + this.scene.player.jumpToPosition({ x: 0, y: 0, z: -128 }, true); + this.scene.editor.toggleEditor(); + + //this.scene.cameras.main.setBackgroundColor(0x00ff00); + + + this.leg0 = this.scene.geometryController.loadModel("legality 0", "modLegalityBox", { x: 0, y: 0, z: 0 }); + //this.leg0.flags.draw = true; + this.leg0.depthMod = -64; + this.leg0.flags.ignoreRaycast = true; + + this.car0 = this.scene.geometryController.loadModel("car Hampton", "modHoverCarHapton00", { x: 0, y: 0, z: 0 }); + this.car0.flags.draw = true; + + this.car0 = this.scene.geometryController.loadModel("car Tinnemann", "modHoverCarTinnemann00", { x: 512, y: 0, z: 512 }); + this.car0.flags.draw = true; + + this.car1 = this.scene.geometryController.loadModel("car Arashi", "modHoverCarWipeOutStyle", { x: 512, y: 0, z: 0 }); + this.car1.flags.draw = true; + + this.car1 = this.scene.geometryController.loadModel("car Daito", "modHoverCarF1", { x: 512, y: 0, z: -512 }); + this.car1.flags.draw = true; + + + //this.smiley = this.scene.geometryController.loadModel("smiley", "modRacingPickup", { x: 0, y: 0, z: 256 }); + //this.smiley.flags.draw = true; + + //this.smiley.setDrawMode(DRAWMODE.BILLBOARD); + //this.smiley.scale({ x: 32, y: 32, z: 1 }); + // + // modObstMetalDoorMirrored + //this.door = this.scene.geometryController.loadModel("door", "modObstMetalDoorMirrored", { x: 0, y: -128, z: 256 }); + //this.door.flags.draw = true; + + //main + /* + let radius = 128; + let shipRadius = 256 + 64; + let toX = Math.cos(Math.PI * 0.5) * radius; + let toY = Math.sin(Math.PI * 0.5) * radius; + + //pilots + // player + this.charMoritz = this.scene.geometryController.loadModel("char moritz", "modCharacterDefaultHuman", { x: toX - 4, y: 0, z: toY }); + this.charMoritz.quadData[0].setTexture("turnaroundMoritz00", 0); + this.charMoritz.lookDir.yaw = Math.PI * 1; + this.charMoritz.flags.draw = true; + this.charMoritz.setDrawMode(DRAWMODE.BILLBOARD); + this.charMoritz.flags.is8way = true; + this.charMoritz.depthMod = 16; + + this.charRoki = this.scene.geometryController.loadModel("char roki", "modCharacterDefaultHuman", { x: toX + 4, y: 0, z: toY }); + this.charRoki.quadData[0].setTexture("charSheetRoki", "rokiStandIdle0000"); + this.charRoki.atlas = "charSheetRoki"; + this.charRoki.atlas8wayFrame = "rokiStandIdle010"; + this.charRoki.scale({ x: 1, y: 0.9, z: 1 }); + this.charRoki.flags.draw = true; + this.charRoki.lookDir.yaw = Math.PI * 1; + this.charRoki.setDrawMode(DRAWMODE.BILLBOARD); + this.charRoki.flags.is8way = true; + this.charRoki.flags.usesAtlas = true; + this.charRoki.depthMod = 16; + + + toX = Math.cos(Math.PI * 0.5) * shipRadius; + toY = Math.sin(Math.PI * 0.5) * shipRadius; + this.car0 = this.scene.geometryController.loadModel("car Arashi", "modHoverCarWipeOutStyle", { x: toX, y: 0, z: toY }); + this.car0.rotateAroundAxis([0, 0, 1], Math.PI * -0.15); + this.car0.rotateAroundAxis([0, -1, 0], Math.PI * 0.75); + this.car0.flags.draw = true; + + + // Daito + toX = Math.cos(Math.PI * 0.55) * radius; + toY = Math.sin(Math.PI * 0.55) * radius; + this.charGlaze = this.scene.geometryController.loadModel("char glaze", "modCharacterDefaultHuman", { x: toX - 4, y: 0, z: toY }); + this.charGlaze.quadData[0].setTexture("charSheetGlaze", "glazeStandIdle0000"); + this.charGlaze.atlas = "charSheetGlaze"; + this.charGlaze.atlas8wayFrame = "glazeStandIdle010"; + this.charGlaze.lookDir.yaw = Math.PI * 1; + this.charGlaze.flags.draw = true; + this.charGlaze.setDrawMode(DRAWMODE.BILLBOARD); + this.charGlaze.flags.is8way = true; + this.charGlaze.flags.usesAtlas = true; + this.charGlaze.depthMod = 16; + + this.charFoxxy = this.scene.geometryController.loadModel("char foxxy", "modCharacterDefaultHuman", { x: toX + 4, y: 0, z: toY }); + this.charFoxxy.quadData[0].setTexture("charSheetFoxxy", "foxxyStandIdle0000"); + this.charFoxxy.atlas = "charSheetFoxxy"; + this.charFoxxy.atlas8wayFrame = "foxxyStandIdle000"; + this.charFoxxy.scale({ x: 1.45, y: 0.95, z: 1 }); + this.charFoxxy.flags.draw = true; + this.charFoxxy.lookDir.yaw = Math.PI * 1; + this.charFoxxy.setDrawMode(DRAWMODE.BILLBOARD); + this.charFoxxy.flags.is8way = true; + this.charFoxxy.flags.usesAtlas = true; + this.charFoxxy.depthMod = 16; + + // Tinnemann + toX = Math.cos(Math.PI * 0.45) * radius; + toY = Math.sin(Math.PI * 0.45) * radius; + this.charHog = this.scene.geometryController.loadModel("char hog", "modCharacterDefaultHuman", { x: toX - 4, y: 0, z: toY }); + this.charHog.quadData[0].setTexture("charSheetHog", "hogStandIdle0000"); + this.charHog.atlas = "charSheetHog"; + this.charHog.atlas8wayFrame = "hogStandIdle000"; + this.charHog.scale({ x: 1.75, y: 1, z: 1 }); + this.charHog.flags.draw = true; + this.charHog.lookDir.yaw = Math.PI * 1; + this.charHog.setDrawMode(DRAWMODE.BILLBOARD); + this.charHog.flags.is8way = true; + this.charHog.flags.usesAtlas = true; + this.charHog.depthMod = 16; + + this.charRahy = this.scene.geometryController.loadModel("char rahy", "modCharacterDefaultHuman", { x: toX + 4, y: 0, z: toY }); + this.charRahy.quadData[0].setTexture("charSheetRahy", "rahyStandIdle0"); + this.charRahy.atlas = "charSheetRahy"; + this.charRahy.atlas8wayFrame = "rahyStandIdle0"; + this.charRahy.scale({ x: 1.5, y: 1, z: 1 }); + this.charRahy.flags.draw = true; + this.charRahy.lookDir.yaw = Math.PI * 1; + this.charRahy.setDrawMode(DRAWMODE.BILLBOARD); + this.charRahy.flags.is8way = true; + this.charRahy.flags.usesAtlas = true; + this.charRahy.depthMod = 16; + + // Hampton + toX = Math.cos(Math.PI * 0.6) * radius; + toY = Math.sin(Math.PI * 0.6) * radius; + this.charJojo = this.scene.geometryController.loadModel("char jojo", "modCharacterDefaultHuman", { x: toX - 4, y: 0, z: toY }); + this.charJojo.quadData[0].setTexture("charSheetJo", "joStandIdle0000"); + this.charJojo.atlas = "charSheetJo"; + this.charJojo.atlas8wayFrame = "joStandIdle000"; + this.charJojo.scale({ x: 1.3, y: 0.92, z: 1 }); + this.charJojo.flags.draw = true; + this.charJojo.lookDir.yaw = Math.PI * 1; + this.charJojo.setDrawMode(DRAWMODE.BILLBOARD); + this.charJojo.flags.is8way = true; + this.charJojo.flags.usesAtlas = true; + this.charJojo.depthMod = 16; + + this.charScooter = this.scene.geometryController.loadModel("char scooter", "modCharacterDefaultHuman", { x: toX + 4, y: 0, z: toY }); + this.charScooter.quadData[0].setTexture("charSheetScooter", "HannahStandIdle00"); + this.charScooter.atlas = "charSheetScooter"; + this.charScooter.atlas8wayFrame = "hannahStandIdle0"; + this.charScooter.scale({ x: 1, y: 1, z: 1 }); + this.charScooter.flags.draw = true; + this.charScooter.lookDir.yaw = Math.PI * 1; + this.charScooter.setDrawMode(DRAWMODE.BILLBOARD); + this.charScooter.flags.is8way = true; + this.charScooter.flags.usesAtlas = true; + this.charScooter.depthMod = 16; + + // Arashi + toX = Math.cos(Math.PI * 0.4) * radius; + toY = Math.sin(Math.PI * 0.4) * radius; + this.charJay = this.scene.geometryController.loadModel("char jay", "modCharacterDefaultHuman", { x: toX - 4, y: 0, z: toY }); + this.charJay.quadData[0].setTexture("charSheetJay", "jayStandIdle0000"); + this.charJay.atlas = "charSheetJay"; + this.charJay.atlas8wayFrame = "jayStandIdle000"; + this.charJay.scale({ x: 0.95, y: 1, z: 1 }); + this.charJay.lookDir.yaw = Math.PI * 1; + this.charJay.flags.draw = true; + this.charJay.setDrawMode(DRAWMODE.BILLBOARD); + this.charJay.flags.is8way = true; + this.charJay.flags.usesAtlas = true; + this.charJay.depthMod = 16; + + this.charBonez = this.scene.geometryController.loadModel("char bonez", "modCharacterDefaultHuman", { x: toX + 4, y: 0, z: toY }); + this.charBonez.quadData[0].setTexture("charSheetBonez", "bonezStandIdle00"); + this.charBonez.atlas = "charSheetBonez"; + this.charBonez.atlas8wayFrame = "bonezStandIdle0"; + this.charBonez.scale({ x: 1.25, y: 1, z: 1 }); + this.charBonez.lookDir.yaw = Math.PI * 1; + this.charBonez.flags.draw = true; + this.charBonez.setDrawMode(DRAWMODE.BILLBOARD); + this.charBonez.flags.is8way = true; + this.charBonez.flags.usesAtlas = true; + this.charBonez.depthMod = 16; + + + + //extras + this.charShop = this.scene.geometryController.loadModel("char shop", "modCharacterDefaultHuman", { x: 256, y: 0, z: 0 }); + this.charShop.quadData[0].setTexture("charSheetBooker", "bookerStandIdle0000"); + this.charShop.atlas = "charSheetBooker"; + this.charShop.atlas8wayFrame = "bookerStandIdle000"; + this.charShop.lookDir.yaw = Math.PI * 1; + this.charShop.flags.draw = true; + this.charShop.setDrawMode(DRAWMODE.BILLBOARD); + this.charShop.flags.is8way = true; + this.charShop.flags.usesAtlas = true; + this.charShop.depthMod = 16; + + this.charVip = this.scene.geometryController.loadModel("char vip", "modCharacterDefaultHuman", { x: 256, y: 0, z: 0 }); + this.charVip.quadData[0].setTexture("charSheetGlaze", "vipStandIdle00"); + this.charVip.atlas = "charSheetVip"; + this.charVip.atlas8wayFrame = "vipStandIdle0"; + this.charVip.lookDir.yaw = Math.PI * 1; + this.charVip.flags.draw = true; + this.charVip.setDrawMode(DRAWMODE.BILLBOARD); + this.charVip.flags.is8way = true; + this.charVip.flags.usesAtlas = true; + this.charVip.depthMod = 16; + + this.charJosef = this.scene.geometryController.loadModel("char josef", "modCharacterDefaultHuman", { x: 256, y: 0, z: 0 }); + this.charJosef.quadData[0].setTexture("charSheetJosef", "josefStandIdle0100"); + this.charJosef.atlas = "charSheetJosef"; + this.charJosef.atlas8wayFrame = "josefStandIdle010"; + this.charJosef.scale({ x: 1.4, y: 1, z: 1 }); + this.charJosef.lookDir.yaw = Math.PI * 1; + this.charJosef.flags.draw = true; + this.charJosef.setDrawMode(DRAWMODE.BILLBOARD); + this.charJosef.flags.is8way = true; + this.charJosef.flags.usesAtlas = true; + this.charJosef.depthMod = 16; + + this.charMechanic = this.scene.geometryController.loadModel("char mechanic", "modCharacterDefaultHuman", { x: 256, y: 0, z: 0 }); + this.charMechanic.quadData[0].setTexture("charSheetRahyMechanic", "rahyMechanicSitIdle0000"); + this.charMechanic.atlas = "charSheetRahyMechanic"; + this.charMechanic.atlas8wayFrame = "rahyMechanicSitIdle010"; + this.charMechanic.scale({ x: 1.4, y: 0.8, z: 1 }); + this.charMechanic.flags.draw = true; + this.charMechanic.lookDir.yaw = Math.PI * 1; + this.charMechanic.setDrawMode(DRAWMODE.BILLBOARD); + this.charMechanic.flags.is8way = true; + this.charMechanic.flags.usesAtlas = true; + this.charMechanic.depthMod = 16; + + this.charRaceDirector = this.scene.geometryController.loadModel("charRaceDirector", "modCharacterDefaultHuman", { x: 256, y: 0, z: 0 }); + this.charRaceDirector.quadData[0].setTexture("charSheetRaceDirector", "paulStandIdle0000"); + this.charRaceDirector.atlas = "charSheetRaceDirector"; + this.charRaceDirector.atlas8wayFrame = "paulStandIdle000"; + this.charRaceDirector.scale({ x: 1, y: 1, z: 1 }); + this.charRaceDirector.flags.draw = true; + this.charRaceDirector.lookDir.yaw = Math.PI * 1; + this.charRaceDirector.setDrawMode(DRAWMODE.BILLBOARD); + this.charRaceDirector.flags.is8way = true; + this.charRaceDirector.flags.usesAtlas = true; + this.charRaceDirector.depthMod = 16; + + */ + } + + update() { + + } + + destroy() { + + } + + createNewModel() { + this.model = this.scene.geometryController.loadModel("model" + String(this.models.length), "modDebugTile", { x: Math.floor(this.scene.player.pos.x / 16) * 16, y: Math.floor(this.scene.player.pos.y / 16) * 16, z: Math.floor(this.scene.player.pos.z / 16) * 16 }); + this.model.flags.draw = true; + } + +} diff --git a/src/3d/levels/lvlPlayerApartement00.js b/src/3d/levels/lvlPlayerApartement00.js new file mode 100755 index 0000000..e3d8877 --- /dev/null +++ b/src/3d/levels/lvlPlayerApartement00.js @@ -0,0 +1,267 @@ +import PanelPlayerComputer from "../../ui/panelPlayerComputer.js"; +import PanelWakeUp from "../../ui/panelWakeUp.js"; +import PanelWelcome from "../../ui/panelWelcome.js"; +import GroupElevator from "../groups/grpElevator.js"; + +export default class LevelPlayerApartement00 { + constructor(_scene, _params = { fromElevator: true }) { + this.scene = _scene; + this.params = _params; + /*if (this.params === null) { + this.params = { fromElevator: true }; + }*/ + + this.scene.player = this.scene.playerWalk; + this.scene.cam = this.scene.camWalk; + + this.wakeUpAnim = { + roll: Math.PI * -0.002, + pitch: 0, + yaw: 0, + go: false, + finished: false, + }; + + this.dance = { + anim: 0, + step: 0, + }; + + //coming from dream + if (this.params.fromElevator === false) { + //this.scene.player.dir.pitch = 0; + this.scene.player.jumpToPosition({ x: -133, y: 0, z: 163 }); + this.scene.player.setMoveMode(PLAYERMOVE.LIE); + this.scene.player.spd.normal = 0; + this.scene.player.spd.sprint = 0; + this.scene.player.modDir.roll = Math.PI * 0.5; + this.scene.player.hideUI(); + //this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelWakeUp(this.scene); + } else { + } + + if (this.scene.soundManager.musicCalmLoop00.howlGroup.playing() === true) { + this.scene.soundManager.stopSound(this.scene.soundManager.musicCalmLoop00); + } + + this.elevator = new GroupElevator(this.scene, this, { x: 0, y: 0, z: 0 }); + this.elevator.setDraw(true); + + this.apartement = this.scene.geometryController.loadModel("apartement", "modPlayerApartement", { x: -48, y: 0, z: 128 }); + this.apartement.flags.draw = true; + + this.computer = this.scene.geometryController.loadModel("apartement computer", "modComputer", { x: -80, y: -12, z: 256 }); + this.computer.depthMod = 20; + this.computer.flags.draw = true; + this.computer.data = { + useText: "use computer", + useRadius: 48, + }; + this.computer.interactable = true; + this.computer.interact = () => { + if (this.scene.player.panel === null) { + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.setMoveMode(PLAYERMOVE.SIT); + this.scene.player.panel = new PanelPlayerComputer(this.scene); + } + }; + + this.seat = this.scene.geometryController.loadModel("apartement seat", "modSeatBasic", { x: -80, y: 0, z: 223 }); + this.seat.depthMod = 20; + this.seat.flags.draw = true; + + this.mirrorX = -168 * 2; + + this.charMoritz = this.scene.geometryController.loadModel("char moritz", "modCharacterDefaultHuman", { x: -300, y: -16, z: 112 }); + this.charMoritz.quadData[0].setTexture("turnaroundMoritz00", 0); + this.charMoritz.lookDir.yaw = 0; + this.charMoritz.flags.draw = true; + //this.charMoritz.setDrawMode(DRAWMODE.BILLBOARD); + //this.charMoritz.flags.is8way = true; + this.charMoritz.depthMod = 16; + if (this.params !== null) { + if (this.params.fromElevator === true) { + this.charMoritz.setDrawMode(DRAWMODE.BILLBOARD); + this.charMoritz.flags.is8way = true; + } + } + + this.talkMoritz = this.scene.geometryController.loadModel("trigger shade", "modTriggerWall1x1", { x: -170, y: -16, z: 91 }); + this.talkMoritz.scale({ x: 8, y: 16, z: 1 }); + this.talkMoritz.rotateAroundAxis([0, 1, 0], Math.PI * 0.5); + for (let i = 0; i < 4; i++) { + this.talkMoritz.quadData[0].points[i].x = this.talkMoritz.collisionData[0].points[i].x; + this.talkMoritz.quadData[0].points[i].y = this.talkMoritz.collisionData[0].points[i].y; + this.talkMoritz.quadData[0].points[i].z = this.talkMoritz.collisionData[0].points[i].z; + } + this.talkMoritz.quadData[0].setTexture("atlasAll", "texInvisible"); + this.talkMoritz.flags.draw = true; + this.talkMoritz.depthMod = 32; + this.talkMoritz.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaApartement00Moritz00", + treePosition: 0, + }, + }; + this.talkMoritz.interactable = true; + this.talkMoritz.interact = () => { + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.talkMoritz); + this.scene.player.conversationManager.setConversation(this.talkMoritz.data.conversation.fileName, this.talkMoritz.data.conversation.treePosition); + }; + + /* + this.charRaceDirector = this.scene.geometryController.loadModel("char race director", "modCharacterDefaultHuman", { x: -80, y: 0, z: 230 }); + this.charRaceDirector.quadData[0].setTexture("charSheetRaceDirector", "paulSitIdle00"); + this.charRaceDirector.atlas = "charSheetRaceDirector"; + this.charRaceDirector.atlas8wayFrame = "paulSitIdle0"; + this.charRaceDirector.scale({ x: 2, y: 1, z: 1 }); + this.charRaceDirector.flags.draw = true; + //this.charRaceDirector.setDrawMode(DRAWMODE.BILLBOARD); + //this.charRaceDirector.flags.is8way = true; + this.charRaceDirector.flags.usesAtlas = true; + this.charRaceDirector.depthMod = 16; + this.charRaceDirector.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaDemoHangarMechanic00", + treePosition: 99 + } + } + + this.charRahy = this.scene.geometryController.loadModel("char rahy", "modCharacterDefaultHuman", { x: -50, y: 0, z: 192 }); + this.charRahy.quadData[0].setTexture("charSheetRahy", "rahyDanceFrame0000"); + this.charRahy.atlas = "charSheetRahy"; + this.charRahy.atlas8wayFrame = "rahyDanceFrame000"; + this.charRahy.scale({ x: 1.5, y: 1, z: 1 }); + this.charRahy.flags.draw = true; + this.charRahy.lookDir.yaw = Math.PI * 0.5; + //this.charRahy.setDrawMode(DRAWMODE.BILLBOARD); //because of wakeup anim disable in the beginning + //this.charRahy.flags.is8way = true; + this.charRahy.flags.usesAtlas = true; + this.charRahy.depthMod = 16; + + this.charBonez = this.scene.geometryController.loadModel("char bonez", "modCharacterDefaultHuman", { x: -20, y: 0, z: 192 }); + this.charBonez.quadData[0].setTexture("charSheetBonez", "bonezStandIdle00"); + this.charBonez.atlas = "charSheetBonez"; + this.charBonez.atlas8wayFrame = "bonezStandIdle0"; + this.charBonez.scale({ x: 1, y: 1, z: 1 }); + this.charBonez.flags.draw = true; + this.charBonez.lookDir.yaw = Math.PI * 0.25; + //this.charBonez.setDrawMode(DRAWMODE.BILLBOARD); + //this.charBonez.flags.is8way = true; + this.charBonez.flags.usesAtlas = true; + this.charBonez.depthMod = 16; + + this.charScooter = this.scene.geometryController.loadModel("char scooter", "modCharacterDefaultHuman", { x: -28, y: 0, z: 210 }); + this.charScooter.quadData[0].setTexture("charSheetScooter", "HannahWalkFrame0000"); + this.charScooter.atlas = "charSheetScooter"; + this.charScooter.atlas8wayFrame = "HannahWalkFrame000"; + this.charScooter.scale({ x: 1, y: 1, z: 1 }); + this.charScooter.flags.draw = true; + this.charScooter.lookDir.yaw = Math.PI * 0.25; + //this.charScooter.setDrawMode(DRAWMODE.BILLBOARD); + //this.charScooter.flags.is8way = true; + this.charScooter.flags.usesAtlas = true; + this.charScooter.depthMod = 16; + + this.charHog = this.scene.geometryController.loadModel("char hog", "modCharacterDefaultHuman", { x: -20, y: 0, z: 120 }); + this.charHog.quadData[0].setTexture("charSheetHog", "hogStandIdle0000"); + this.charHog.atlas = "charSheetHog"; + this.charHog.atlas8wayFrame = "hogStandIdle000"; + this.charHog.scale({ x: 1.75, y: 1, z: 1 }); + this.charHog.flags.draw = true; + this.charHog.lookDir.yaw = Math.PI * 0.75; + //this.charHog.setDrawMode(DRAWMODE.BILLBOARD); + //this.charHog.flags.is8way = true; + this.charHog.flags.usesAtlas = true; + this.charHog.depthMod = 16; + */ + } + + update() { + this.charMoritz.jumpToPosition( + { + x: this.mirrorX - this.scene.player.pos.x, + y: this.scene.player.pos.y, + z: this.scene.player.pos.z, + }, + true, + ); + this.charMoritz.lookDir.yaw = this.scene.player.dir.yaw; + + this.talkMoritz.jumpToPosition({ + x: this.talkMoritz.pos.x, + y: this.talkMoritz.pos.y, + z: Math.max(64, Math.min(this.scene.player.pos.z, 120)), + }); + + if (this.wakeUpAnim.go === true) { + //wake up + if (this.scene.player.dir.roll > 0) { + this.scene.player.modDir.roll = this.wakeUpAnim.roll; + } else { + if (this.scene.player.dir.roll !== 0) { + this.scene.player.modDir.roll = -this.scene.player.dir.roll; + } + if (this.scene.player.dir.roll === 0 && this.charMoritz.debug.mode !== DRAWMODE.BILLBOARD) { + this.charMoritz.setDrawMode(DRAWMODE.BILLBOARD); + this.charMoritz.flags.is8way = true; + //console.log(this.charMoritz.pos.y); + + /* + this.charRaceDirector.setDrawMode(DRAWMODE.BILLBOARD); + this.charRaceDirector.flags.is8way = true; + this.charRahy.setDrawMode(DRAWMODE.BILLBOARD); + this.charRahy.flags.is8way = true; + this.charBonez.setDrawMode(DRAWMODE.BILLBOARD); + this.charBonez.flags.is8way = true; + this.charHog.setDrawMode(DRAWMODE.BILLBOARD); + this.charHog.flags.is8way = true; + this.charScooter.setDrawMode(DRAWMODE.BILLBOARD); + this.charScooter.flags.is8way = true; + */ + + this.scene.player.spd.normal = this.scene.player.spd.orig.normal; + this.scene.player.spd.sprint = this.scene.player.spd.orig.sprint; + + this.wakeUpAnim.finished = true; + } + } + } else { + if (this.params !== null) { + if (this.params.fromElevator === false) { + this.wakeUpAnim.go = true; + } + } + } + + if (this.wakeUpAnim.finished === true) { + /* + this.dance.step += 1 * this.scene.dt; + this.dance.anim = Math.floor((this.dance.step * 0.02) % 2); + //this.charRahy.atlas8wayFrame = "rahyDanceFrame0" + String(this.dance.anim) + "0"; + this.charRahy.atlas8wayFrame = "rahyWalkFrame0" + String(Math.floor((this.dance.step * 0.02) % 4)) + "0"; + this.charRahy.lookDir.yaw += Math.PI * 0.0025; + + this.charBonez.atlas8wayFrame = "bonezWalkFrame0" + String(Math.floor((this.dance.step * 0.02) % 4)) + "0"; + this.charBonez.lookDir.yaw += Math.PI * 0.0025; + + this.charScooter.atlas8wayFrame = "hannahWalkFrame0" + String(Math.floor((this.dance.step * 0.02) % 4)) + "0"; + this.charScooter.lookDir.yaw += Math.PI * 0.0025; + + this.charHog.atlas8wayFrame = "hogStandIdle0" + String(this.dance.anim) + "0"; + this.charHog.lookDir.yaw += Math.PI * 0.025; + */ + } + } + + destroy() {} +} diff --git a/src/3d/levels/lvlQuadRingsTest.js b/src/3d/levels/lvlQuadRingsTest.js new file mode 100755 index 0000000..a12e723 --- /dev/null +++ b/src/3d/levels/lvlQuadRingsTest.js @@ -0,0 +1,2292 @@ +import GL_Vec3 from "../../additionalMath/gl_vec3.js"; +import PanelEndOfRace from "../../ui/panelEndOfRace.js"; +import PanelEndOfCanyon from "../../ui/panelEndOfCanyon.js"; +import PanelEscapeMenu from "../../ui/panelEscapeMenu.js"; +import PanelRaceTutorial from "../../ui/panelRaceTutorial.js"; +import PanelWelcome from "../../ui/panelWelcome.js"; +import UI from "../../ui/racing/ui.js"; +import ShipManager from "../racing/shipManager.js"; +import TrackBuilder from "../racing/trackBuilder.js"; +import Transform from "../transform.js"; + +export default class LevelQuadRingsTest { + constructor(_scene, _params) { + this.scene = _scene; + this.params = _params; + this.startFromHangar = this.params.startFromHangar; //set false if switching track without going back to hangar + + this.states = { + startFromHangar: 0, + countDown: 1, + race: 2, + pause: 3, + //finished: 4,//maybe not needed as race and pause needs to happen still + }; + this.state = this.states.countDown; + + this.raceModes = { + hotlap: 0, //get the best time (practice?) + timetrial: 1, //arcade timer runs down and gets extra time when passing checkpoints or collected + obstacle: 2, //gain points by near misses + qualifying: 3, //three laps to set the fastest time + qualifyingTraffic: 4, //same as above but with enemies that could impede you + grandprix: 5, //normal race against the ai + canyon: 6, //1v1 rack up points as the hunter by slipstreaming, lose them when being hunted + knockout: 7, //each lap or after a timer, the last position is elimated + hunt: 8, //runout the enemies (sprint track?) + passthebomb: 9, //pass the bomb by slipstream to someone before the timer runs out + crazy: 10, //each lap you have to crack a harder time + overtake: 11, //get pointns for each overtake within a time, + tutorial: 99, + }; + this.raceMode = this.params.raceMode !== undefined ? this.params.raceMode : 5; + //this.raceMode = this.raceModes.canyon;//hotlap grandprix canyon + this.raceModeData = {}; + + this.maxLaps = this.params.maxLaps !== undefined ? this.params.maxLaps : 5; + this.stopAfterRingId = this.params.stopAfterRingId !== undefined ? this.params.stopAfterRingId : 0; + + this.countdown = { + current: Date.now(), + start: Date.now(), + texts: ["THREE", "TWO", "ONE", "GO!", ""], + step: 0, + knockout: 0, + go: false, + }; + this.finishedRace = false; + this.grid = []; + + this.tutorialStep = -1; + this.tutorialHoldVar = 0; + this.tutorialHoldVarMax = 500; + + //this.scene.player.jumpToPosition({ x: 0, y: 0, z: -128 }); + //this.scene.player.dir.pitch = 0; + + this.scene.player = this.scene.playerGame; + this.scene.cam = this.scene.camGame; + + /* + console.log("--DATA--") + console.log(this.scene.player); + console.log(this.scene.player.id); + console.log(this.scene.player.mode); + console.log(this.scene.player.moveMode); + */ + //INFOif no difference try locking the mouse / well maybe unlocking? + + //this.scene.player.setMode(PLAYERMODE.INTERACT); + //this.scene.player.panel = new PanelWelcome(this.scene); + + this.trackBuilder = new TrackBuilder(this.scene, this); + this.ui = new UI(this.scene, this); + + this.camRig = this.scene.geometryController.loadModel("hoverShip", "modDebugTile", { x: 0, y: 64, z: 256 }); + this.camRig.quadDate = []; + //this.camRig.flags.draw = true; + + this.playerShip = new ShipManager(this.scene, this, 999, true, false, this.params.playerShipModel); + this.playerShip.name = "Player"; + this.playerShip.ship.data = { + slipstreamLength: 2024, + name: "Player" + }; + this.playerIsShip = true; + this.ui.registerShip(this.playerShip); + this.aiShips = []; + switch (this.raceMode) { + case this.raceModes.hotlap: + case this.raceModes.timetrial: + case this.raceModes.obstacle: + case this.raceModes.qualifying: + break; + case this.raceModes.qualifyingTraffic: + case this.raceModes.grandprix: + case this.raceModes.knockout: + case this.raceModes.passthebomb: + let names = ["Bonez", "Foxxy", "Glaze", "Roki", "Hog", "Roach", "Scooter", "Jay"]; + //let names = ["Jay", "Jay", "Jay", "Jay", "Jay", "Jay", "Jay", "Jay"]; + let colors = ["Yellow", "Blue", "Green", "Red"]; + for (let i = 0; i < 7; i++) { + this.aiShips.push(new ShipManager(this.scene, this, i, false, true)); + this.aiShips[this.aiShips.length - 1].autopilot = true; + this.aiShips[this.aiShips.length - 1].ai.prefRoll = Math.random() > 0.5 ? -1 : 1; + this.aiShips[this.aiShips.length - 1].speedMax += -0.5 + Math.random() * 2; + this.aiShips[this.aiShips.length - 1].rollAcceleration += Math.random() * 0.01; + this.aiShips[this.aiShips.length - 1].acceleration += Math.random() * 0.01; + this.aiShips[this.aiShips.length - 1].setShipColor(colors[i % 4]); + this.aiShips[this.aiShips.length - 1].name = names[i]; + this.aiShips[this.aiShips.length - 1].ship.data = { + slipstreamLength: 2024, + name: names[i] + }; + //add ship to the ui (minimap) + //this.ui.registerShip(this.aiShips[this.aiShips.length - 1]); + } + break; + case this.raceModes.canyon: + this.aiShips.push(new ShipManager(this.scene, this, 0, false, true, "modHoverCarTinnemann00")); + this.aiShips[this.aiShips.length - 1].autopilot = true; + this.aiShips[this.aiShips.length - 1].ai.prefRoll = Math.random() > 0.5 ? -1 : 1; + //this.aiShips[this.aiShips.length - 1].speedMax += -0.5 + (Math.random() * 2); + //this.aiShips[this.aiShips.length - 1].speedMax += 1; + this.aiShips[this.aiShips.length - 1].rollAcceleration += 0.01; + this.aiShips[this.aiShips.length - 1].rollSpeedMax += 0.1; + this.aiShips[this.aiShips.length - 1].rollSpeedMin -= 0.1; + this.aiShips[this.aiShips.length - 1].acceleration += 0.01; + this.aiShips[this.aiShips.length - 1].setShipColor("Yellow"); + this.aiShips[this.aiShips.length - 1].name = "Roki"; + this.aiShips[this.aiShips.length - 1].ship.data = { + slipstreamLength: 2024, + name: "Roki" + }; + //add ship to the ui (minimap) + //this.ui.registerShip(this.aiShips[this.aiShips.length - 1]); + + this.raceModeData = { + playerIsHunter: true, + points: { + overall: 0, + rounds: [0, 0] + } + } + break; + case this.raceModes.hunt: + break; + case this.raceModes.crazy: + break; + case this.raceModes.tutorial: + this.aiShips.push(new ShipManager(this.scene, this, 0, false, true, "modHoverCarTinnemann00")); //modHoverCarWipeOutStyle + this.aiShips[this.aiShips.length - 1].autopilot = true; + this.aiShips[this.aiShips.length - 1].ai.prefRoll = Math.random() > 0.5 ? -1 : 1; + //this.aiShips[this.aiShips.length - 1].speedMax = 8; + this.aiShips[this.aiShips.length - 1].rollAcceleration += Math.random() * 0.01; + this.aiShips[this.aiShips.length - 1].acceleration += Math.random() * 0.01; + this.aiShips[this.aiShips.length - 1].setShipColor("Yellow"); + this.aiShips[this.aiShips.length - 1].name = "Roki"; + this.aiShips[this.aiShips.length - 1].ship.data = { + slipstreamLength: 2024, + name: "Roki", + conversation: { + fileName: "diaDemoRaceTutorial", + treePosition: 0, + }, + }; + //add ship to the ui (minimap) + //this.ui.registerShip(this.aiShips[this.aiShips.length - 1]); + break; + default: + break; + } + + for (let ai of this.aiShips) { + ai.character = this.scene.characters.filter(el => el.name === ai.name)[0]; + this.ui.registerShip(ai); + } + + this.camOffset = { + pos: { x: 0, y: 0, z: 0 }, + dir: { yaw: 0, pitch: 0, roll: 0, spd: { yaw: 0.04, pitch: 0.04, roll: 0.04 } }, + target: { + pos: { x: 0, y: 0, z: 0 }, + dir: { yaw: 0, pitch: 0, roll: 0, spd: { yaw: 0.04, pitch: 0.04, roll: 0.04 } }, + }, + virtualMouse: { + delta: { x: 0, y: 0 }, + lastPos: { x: 0, y: 0 }, + pos: { x: 0, y: 0 }, + }, + }; + + this.situation = { + actions: { + hit: { //player bumping into ai + who: "", + priority: 0, + time: 0 + }, slipstream: { //player slipstreaming ai + who: "", + priority: 0, + time: 0 + }, slipstreamed: { //ai slipstreaming behind player + who: "", + priority: 0, + time: 0 + }, gainPosition: { //player overtakes ai + who: "", + priority: 0, + time: 0 + }, loosePosition: { //ai overtakes player + who: "", + priority: 0, + time: 0 + }, mishap: { //player crashes near ai + who: "", + priority: 0, + time: 0 + }, win: { //ai wins + who: "", + priority: 1, + time: 0 + }, loose: { //player wins / rival looses + who: "", + priority: 0, + time: 0 + } + } + } + + //IMPORTANT for building models + //this.toModel = this.createDefaultRing(); + this.toModel = this.scene.geometryController.loadModel("ring DEFAULT", "modRingD64R128RoundCanyon", { x: -512, y: 0, z: 0 }); + this.toModel.flags.draw = true; + /*for(let j = 1 ; j < 8 ; j++){ + for(let i = 0; i < 20 ; i++){ + let q = this.toModel.quadData[i]; + this.toModel.addQuadFromData({ + type: "quad", + frame: q.frame, + texture: "atlasAll", + position: { x: 0, y: 0, z: 0 }, + points: [ + {//hinten rechts + x: q.points[0].x, + y: q.points[0].y, + z: q.points[0].z + (j * 64) + 0 + },{//hinten links + x: q.points[1].x, + y: q.points[1].y, + z: q.points[1].z + (j * 64) + 0 + },{//vorne links + x: q.points[2].x, + y: q.points[2].y, + z: q.points[2].z + (j * 64) + 0 + },{//vorne rechts + x: q.points[3].x, + y: q.points[3].y, + z: q.points[3].z + (j * 64) + 0 + } + ] + }); + } + }*/ + + this.helpModel0 = this.scene.geometryController.loadModel("ring DEFAULT help 0", "modRingD64R128RoundCanyon", { x: -512, y: 0, z: 64 }); + this.helpModel0.flags.draw = true; + this.helpModel1 = this.scene.geometryController.loadModel("ring DEFAULT help 1", "modRingD64R128RoundCanyon", { x: -512, y: 0, z: 128 }); + this.helpModel1.flags.draw = true; + //this.helpModel2 = this.scene.geometryController.loadModel("ring DEFAULT help 2", "modRingD64R128", { x: -512, y: 0, z: 128 + 64 }); + //this.helpModel2.flags.draw = true; + + //this.helpModel3 = this.scene.geometryController.loadModel("ring DEFAULT help 3", "modRingD64R128", { x: -512, y: 0, z: 128 + 128 }); + //this.helpModel3.flags.draw = true; + //this.helpModel4 = this.scene.geometryController.loadModel("ring DEFAULT help 4", "modRingD64R128", { x: -512, y: 0, z: 128 + 192}); + //this.helpModel4.flags.draw = true; + // + //this.helpModel5 = this.scene.geometryController.loadModel("ring DEFAULT help 5", "modRingD64R128", { x: -512, y: 0, z: 320 + 64 }); + //this.helpModel5.flags.draw = true; + //this.helpModel6 = this.scene.geometryController.loadModel("ring DEFAULT help 6", "modRingD64R128", { x: -512, y: 0, z: 320 + 128 }); + //this.helpModel6.flags.draw = true; + //this.helpModel7 = this.scene.geometryController.loadModel("ring DEFAULT help 7", "modRingD64R128", { x: -512, y: 0, z: 320 + 192 }); + //this.helpModel7.flags.draw = true; + //this.helpModel1.rotateAroundAxis([0, 0, 1], Math.PI * 0.25) + //this.helpModel2 = this.scene.geometryController.loadModel("ring DEFAULT help 3", "modRingD64R128Quadrat", { x: -512, y: 0, z: 128+64 }); + //this.helpModel2.flags.draw = true; + + //preload Textures + let textureArray0 = this.trackBuilder.textureArrays.canyon[0]; + let textureArray1 = this.trackBuilder.textureArrays.canyon[0]; + let textureArray2 = this.trackBuilder.textureArrays.canyon[0]; + //let textureArray3 = this.trackBuilder.textureArrays.darkMetalRing[0]; + for(let [i, t] of textureArray0.entries()){this.toModel.quadData[i].setTexture(t.texture, t.frame);} + for(let [i, t] of textureArray1.entries()){this.helpModel0.quadData[i].setTexture(t.texture, t.frame);} + for(let [i, t] of textureArray2.entries()){this.helpModel1.quadData[i].setTexture(t.texture, t.frame);} + //for(let [i, t] of textureArray3.entries()){this.helpModel2.quadData[i].setTexture(t.texture, t.frame);} + + //IMPORTANT end of builder + + //debug change track + this.scene.keys.m.on( + "up", + (_key, _event) => { + if (this.scene.editor.enabled === false) { + let tid = this.trackBuilder.currentTrackId + 1; + if (tid >= 4) { + tid = 0; + } + this.loadTrack(tid); + + //restart all ships + for (let ai of this.aiShips) { + ai.lapTimes = []; + ai.fastestLap = 0; + ai.last.fastestLap = 0; + } + this.playerShip.lapTimes = []; + this.playerShip.fastestLap = 0; + this.playerShip.last.fastestLap = 0; + this.playerShip.autopilot = false; + this.ui.show(); + + this.finishedRace = false; + } + }, + this, + ); + + //get in and out of craft + this.scene.keys.z.on( + "up", + (_key, _event) => { + if (this.scene.editor.enabled === false) { + this.playerIsShip = !this.playerIsShip; + if (this.playerIsShip === false) { + this.scene.player = this.scene.playerWalk; + this.scene.cam = this.scene.camWalk; + + //this.scene.player.jumpToPosition({ x: 304, y: 512 - 56, z: -160 }); + this.scene.player.jumpToPosition({ x: this.playerShip.shipAnchor.pos.x, y: this.playerShip.shipAnchor.pos.y, z: this.playerShip.shipAnchor.pos.z }); + this.scene.player.dir.pitch = 0; + } else { + this.scene.player = this.scene.playerGame; + this.scene.cam = this.scene.camGame; + } + } + }, + this, + ); + + //toggle autopilot + this.scene.keys.space.on( + "up", + (_key, _event) => { + if (this.scene.editor.enabled === false) { + this.playerShip.autopilot = !this.playerShip.autopilot; + } + }, + this, + ); + + //hide all models + for (let s of this.trackBuilder.spline) { + if (s.model !== null) { + s.model.flags.draw = false; + } + } + + //debug laoding screen + this.graLoading = this.scene.add.graphics(); + this.graLoading.fillStyle(0x000000, 0.9); + this.graLoading.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + this.graLoading.depth = 9998; + this.graLoading.alpha = 0; + this.txtLoading = this.scene.add.bitmapText(0, 0, "uiFont", "LOADING TRACK", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.txtLoading.depth = 9999; + this.txtLoading.alpha = 0; + + this.testCounter = 0; + this.testPic = 0; + + //add hangar + this.hangarDoorLeft = this.scene.geometryController.loadModel("hangar door left", "modHangarDoor", { x: -64, y: 468 - 1, z: 128 }); // x: 48, y: 56, z: 96 + 188 + this.hangarDoorLeft.flags.draw = true; + this.hangarDoorRight = this.scene.geometryController.loadModel("hangar door right", "modHangarDoor", { x: 64, y: 468 - 1, z: 128 }); // x: 48, y: 56, z: 96 + 188 + this.hangarDoorRight.flags.draw = true; + this.hangarDoorRight.rotateAroundAxis([0, -1, 0], Math.PI); + this.hangarMain = this.scene.geometryController.loadModel("hangar main", "modHangarMain", { x: -176, y: 568, z: 128 - 48 }); + this.hangarMain.flags.draw = true; + + //jump down id you start from hangar + if (this.startFromHangar === true) { + this.state = this.states.startFromHangar; + + //INFO hacky way of preventing lookaround instead of pitching + this.scene.player.setMode(PLAYERMODE.INTERACT); + + this.playerShip.splineId = 1; + //let splg = this.trackBuilder.spline[this.playerShip.splineId]; + this.playerShip.gondula.jumpToPosition({ x: 0, y: 0 + 468 - 128 - 96, z: 64 }); + this.playerShip.shipAnchor.jumpToPosition({ x: this.playerShip.gondula.pos.x, y: this.playerShip.gondula.pos.y + 96, z: this.playerShip.gondula.pos.z }, true); + this.playerShip.ship.jumpToPosition({ x: this.playerShip.gondula.pos.x, y: this.playerShip.gondula.pos.y + 96, z: this.playerShip.gondula.pos.z }, true); + + //this.scene.editor.toggleEditor(); + } else { + //this.playerShip.camera = this.playerShip.cameras.thirdPersonFollow; + this.playerShip.camera = OPTIONS.config.preferredCam; + //INFO this code is also used in listenToSwitchCamera + if (this.playerShip.camera === 1 || this.playerShip.camera === 2) { + if (this.playerShip.ship.flags.draw === true) { + this.playerShip.ship.flags.draw = false; + this.playerShip.ship.flags.drawn = false; + for (let q of this.playerShip.ship.quadData) { + q.clearQuads(); + } + //this.playerShip.ship.depthMod = -100000; + } + } else { + if (this.playerShip.ship.flags.draw === false) { + this.playerShip.ship.flags.draw = true; + } + //this.playerShip.ship.depthMod = 48; + } + } + + this.state = this.states.startFromHangar; + if (this.params.startFromHangar === false) { + this.state = this.states.countDown; + } + //todo: this lags a lot when loading in (because of the tracklength actually) but its not elegant wwhen coming from the hangar and not moving smoothly + this.loadTrack(9999); + setTimeout(() => { + this.loadTrack(this.params.track); + if (this.params.startFromHangar === false) { + this.state = this.states.countDown; + } + }, 10); + + /* + setInterval(() => { + console.log(this.countdown.step + " : " + this.countdown.current); + }, 1000); + */ + + //prepare music tracks in custom race + this.musicTracks = [this.scene.soundManager.musicAcidLoop00, this.scene.soundManager.musicAcidLoop01]; + this.musicTrack = this.musicTracks[Math.floor(Math.random() * this.musicTracks.length)]; + } + + update(_delta) { + this.ui.txtDelta.setText(String(this.scene.dt.toFixed(2))); + + this.resetSituation(); + + if (this.musicTrack.howlGroup.playing() === false) { + this.scene.soundManager.playSound(this.musicTrack); + } + + //general update + this.playerShip.update(); + //setup pos arr + if (this.finishedRace === false) { + this.grid = []; + this.grid.push(this.playerShip); + } + for (let ai of this.aiShips) { + ai.update(); + if (this.finishedRace === false) { + this.grid.push(ai); + } + } + if (this.finishedRace === false) { + let positionPrevious = this.playerShip.position; + this.grid.sort((a, b) => { + return b.raceProgress - a.raceProgress; + }); + for (let [i, shipManager] of this.grid.entries()) { + shipManager.position = i; + } + + if (this.playerShip.position !== -1) { + let positionChange = this.playerShip.position - positionPrevious; + if (positionChange < 0 && this.playerShip.position < this.grid.length - 1) {//gained position(s) + this.situation.actions.gainPosition.who = this.grid[this.playerShip.position + 1].ship.data.name; + //console.log(this.situation.actions.gainPosition.who) + this.situation.actions.gainPosition.priority += 1; + } + if (positionChange > 0 && this.playerShip.position > 0) {//lost positions + this.situation.actions.loosePosition.who = this.grid[this.playerShip.position - 1].ship.data.name; + //console.log(this.situation.actions.loosePosition.who) + this.situation.actions.loosePosition.priority += 1; + } + } + } + + + + //update ui for laptimes and position + this.ui.txtLapTime.setText("LAP: " + timeToLapTime(this.playerShip.elapsedTime)); + if (this.playerShip.position > -1) { + let affix = "th"; + if (this.playerShip.position === 0) { + affix = "ST"; + } + if (this.playerShip.position === 1) { + affix = "ND"; + } + if (this.playerShip.position === 2) { + affix = "RD"; + } + this.ui.txtLapPos.setText("POS: " + String(this.playerShip.position + 1) + affix); + } + + if (this.scene.player === this.scene.playerGame) { + if (this.hangarDoorRight.pos.x > 0) { + this.hangarDoorLeft.jumpToPosition({ x: Math.min(0, this.hangarDoorLeft.pos.x + 0.1 * this.scene.dt), y: this.hangarDoorLeft.pos.y, z: this.hangarDoorLeft.pos.z }, true); + this.hangarDoorRight.jumpToPosition( + { x: Math.max(0, this.hangarDoorRight.pos.x - 0.1 * this.scene.dt), y: this.hangarDoorRight.pos.y, z: this.hangarDoorRight.pos.z }, + true, + ); + } else { + this.scene.geometryController.destroyModelById(this.hangarMain.id); + this.scene.geometryController.destroyModelById(this.hangarDoorLeft.id); + this.scene.geometryController.destroyModelById(this.hangarDoorRight.id); + } + + switch (this.state) { + case this.states.startFromHangar: + if (this.trackBuilder.spline.length > 0) { + this.updateFromHangar(); + } + break; + case this.states.countDown: + //INFO: this prevents it crashing when loading in "directly" to a race + if (this.trackBuilder.spline.length > 0) { + this.updateCountDown(); + } + break; + case this.states.race: + if (this.trackBuilder.spline.length > 0) { + this.updateRacing(); + + //update tutorial if in tutorial obviously + if (this.raceMode === this.raceModes.tutorial) { + this.updateTutorial(); + } else if (this.raceMode === this.raceModes.canyon) { + if (this.finishedRace === false) { + this.updateCanyon(); + } + } + + //if (this.scene.quartJustChanged === true) { + this.assessSituation(); + //} + } + break; + default: + break; + } + } else { + //todo: use the ui.hide function when exiting craft + /* + this.ui.txtBestLapTime.alpha = 0; + this.ui.txtLastLapTime.alpha = 0; + this.ui.txtLapTime.alpha = 0; + this.ui.txtDelta.alpha = 0; + this.ui.txtHelper.alpha = 0; + */ + } + //this.scene.player.jumpToPosition({ x: this.ref.pos.x + (this.ref.transform.forward.x * -128), y: this.ref.pos.y + (this.ref.transform.forward.y * -128), z: this.ref.pos.z + (this.ref.transform.forward.z * -128) }, true); + + this.ui.update(_delta); + if (INPUTS.btnStickLeft.justPressed === true && this.scene.player.panel === null && this.scene.paused === false) { + this.ui.toggleVisibility(); + } + + if (this.scene.keys.escape.isDown || INPUTS.btnStart.justPressed) { + if (this.scene.player.panel === null) { + //todo: fix auto clicking on back when it was oopen once and the mosue is still on the back button position (locked) + /*if(this.scene.input.mouse.locked === true){ + this.scene.hand.setMouseLock(false); + }*/ + this.ui.hide(); + + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelEscapeMenu(this.scene, this, this.state); + + this.scene.paused = true; + this.state = this.states.pause; + //todo stop engine sound + this.scene.soundManager.stopSound(this.scene.soundManager.engineSound); + //this.scene.soundManager.stopSound(this.scene.soundManager.engineRotorSound); + this.scene.soundManager.stopSound(this.scene.soundManager.scrapeSound); + this.scene.soundManager.stopSound(this.scene.soundManager.heatWarningSound); + } + } + + //hide ui for editor and photomode usage + if (this.state !== this.states.pause) { + if (this.scene.editor.enabled === true) { + this.ui.hide(); + } else { + if (this.finishedRace === false && this.raceMode !== this.raceModes.tutorial) { + this.ui.show(); + } + } + } + } + + updateFromHangar() { + this.listenToSwitchCamera(); + this.toggleDrawByViewDistance(); + + this.playerShip.updateFromHangar(); + for (let ai of this.aiShips) { + ai.updateFromHangar(); + } + //console.log(this.playerShip.gondula.pos.y) + if (this.playerShip.gondula.pos.y <= 0) { + this.playerShip.camera = this.playerShip.cameras.thirdPersonFollow; + //this.state = this.states.countDown; + } + + this.moveCamera(); + } + + updateCountDown() { + //count down + if (this.countdown.step < 5) { + if (this.countdown.step < 4) { + this.ui.txtCountdown.alpha -= this.ui.txtCountdown.alpha * (0.05 * this.scene.dt); + } else { + //fade GO out slower then the numbers + this.ui.txtCountdown.alpha -= this.ui.txtCountdown.alpha * (0.01 * this.scene.dt); + } + + //stall countdown if coming from hangar, to ensure that the player arrives in the tunnel + if (this.playerShip.gondula.pos.y < 100) { + //todo: make this a eud distance from ref spline + this.countdown.current = Date.now() - this.countdown.start; + } else { + this.countdown.start = Date.now(); + } + //check if a second has passed and show countdown + if (this.countdown.current - this.countdown.step * 1000 >= 1000) { + this.ui.txtCountdown.setText(this.countdown.texts[this.countdown.step]); + this.ui.txtCountdown.alpha = 1; + + this.countdown.step += 1; + this.scene.soundManager.playSpecificSound(this.scene.soundManager.raceAnnouncer, this.countdown.step); + if (this.countdown.step === 4) { + this.state = this.states.race; + + if (this.raceMode === this.raceModes.tutorial && this.tutorialStep === -1) { + this.cycleTutorial(); + } + } + } + } + + this.listenToSwitchCamera(); + this.toggleDrawByViewDistance(); + if (this.startFromHangar === true) { + this.playerShip.updateFromHangar(); + for (let ai of this.aiShips) { + ai.updateFromHangar(); + } + let d = eud.distance( + [this.playerShip.gondula.pos.x, this.playerShip.gondula.pos.y, this.playerShip.gondula.pos.z], + [this.trackBuilder.spline[this.playerShip.splineId].x, this.trackBuilder.spline[this.playerShip.splineId].y, this.trackBuilder.spline[this.playerShip.splineId].z], + ); + if (d <= this.scene.dt) { + this.playerShip.camera = this.playerShip.cameras.thirdPersonFollow; + //this.state = this.states.countDown; + } + } else { + if (this.trackBuilder.spline.length > 0) { + this.playerShip.updateRacing(); + for (let ai of this.aiShips) { + ai.updateRacing(); + } + } + } + + //move camera + this.moveCamera(); + } + + updateRacing() { + //finish count down + if (this.countdown.step < 5) { + this.ui.txtCountdown.alpha -= this.ui.txtCountdown.alpha * (0.01 * this.scene.dt); + + this.countdown.current = Date.now() - this.countdown.start; + if (this.countdown.current - this.countdown.step * 1000 >= 1000) { + this.ui.txtCountdown.setText(this.countdown.texts[this.countdown.step]); + this.ui.txtCountdown.alpha = 1; + + this.countdown.step += 1; + if (this.countdown.step === 5) { + this.ui.txtCountdown.alpha = 0; + } + } + } + + //listen to input + this.listenToSwitchCamera(); + + //how many rings should be rendered! viewdist + this.toggleDrawByViewDistance(); + + for (let o of this.trackBuilder.obstacles) { + if (o.flags.update === true) { + o.update(); + } + } + + this.playerShip.updateRacing(); + for (let ai of this.aiShips) { + ai.updateRacing(); + } + + //update player ui + if (this.playerShip.temp >= 999) { + this.ui.txtLower.setText("!!!OVERHEAT WARNING!!!"); + } else { + this.ui.txtLower.setText(""); + } + + //this.ui.txtHelper.setText("SPD: " + String(this.playerShip.speed.toFixed(2)) + " BON: " + String(this.playerShip.speedBonus.toFixed(2)) + " TMP: " + String(Math.floor(this.playerShip.temp)) + " ID: " + String(zeroPad(this.playerShip.splineId, 6))); + this.ui.txtHelper.setText( + "BON: " + String(this.playerShip.speedBonus.toFixed(2)) + " TMP: " + String(Math.floor(this.playerShip.temp)) + " ID: " + String(zeroPad(this.playerShip.splineId, 6)), + ); + this.ui.txtTachoSpd.setText(String(Math.floor(this.playerShip.speed * 10)) + " SPD"); + //this.ui.tachoHighlight.x = (this.scene.game.config.width * -0.5) + 16 - 133 + Math.min(133, (133 * (this.playerShip.speed / this.playerShip.speedMax))); + this.ui.tachoHighlight.x = + this.scene.game.config.width * -0.5 + 16 - 133 + Math.min(133, 133 * ((this.playerShip.speed + 0) / (this.playerShip.speedMax + this.playerShip.speedBonus))); + //ref: (this.speed + this.speedBonus) / (this.speedMax + this.speedBonus) + this.ui.tachoOverspeed.x = + this.scene.game.config.width * -0.5 + + 16 - + 133 + + Math.min(133, 133 * ((this.playerShip.speed + this.playerShip.speedBonus) / (this.playerShip.speedMax + this.playerShip.speedBonus))); + + let curveDelta = this.playerShip.last.curveAmt - this.playerShip.curveAmt; + //this.ui.txtLower.setText("AMT: " + String(this.playerShip.curveAmt.toFixed(4)) + " DEL: " + String(curveDelta.toFixed(4)) + " GOD: " + String(curveDelta < 0)); + + //sign for rad (roll of ship / gondula relative to track ring transform) + let sig = 1; + if (this.playerShip.angleToTrackMod >= 0) { + sig = 1; + } else { + sig = -1; + } + //get player rotation on track - a pi/8 offset for the 16 segments of the collision circles + let rad = (this.playerShip.angleToTrack * -1 + 1) * sig * (Math.PI * 0.5) - 0.39269; + //console.log(rad) + + this.ui.txtLower.setText("AMT: " + String(this.playerShip.curveAmt.toFixed(4)) + " DEL: " + String(curveDelta.toFixed(4)) + " RAD: " + String(rad)); + + //push all obstacles in range to lit array with their 0-15 range of roll + if (this.scene.quartJustChanged === true) { + let lit = []; + for (let o of this.trackBuilder.obstacles) { + if (o.data.id < this.playerShip.splineId + 99 && o.data.id >= this.playerShip.splineId && o.data.ignoreRadar === false) { + let dist = Math.floor(((o.data.id - this.playerShip.splineId) / 100) * 6); + if (dist > 5) { + dist -= 6; + } + if (dist < 0) { + dist += 6; + } + //todo: add rolls inbetween obstacle and player to the calculation + let diff = rad - (o.data.roll === undefined ? o.data.angle : o.data.angle + o.data.roll); + let toSeg = Math.floor((diff + Math.PI) / (Math.PI / 8)); + //add offset and additional blockers + if (toSeg > 15) { + toSeg -= 16; + } + if (toSeg < 0) { + toSeg += 16; + } + //console.log(toSeg) + lit.push({ obstacle: o, diff: diff, seg: toSeg, dist: dist }); + } + } + for (let q of this.ui.dangerCirclets) { + for (let s of q) { + s.alpha = 0; + } + } + for (let l of lit) { + //console.log(l.seg, l.dist) + if (l.seg >= 0 && l.seg < 16 && l.dist >= 0 && l.dist <= 5) { + let tos = []; + tos.push(l.seg); + tos[0] += l.obstacle.data.collisionRadar.offset; + for (let a of l.obstacle.data.collisionRadar.additionals) { + tos.push(tos[0] + a); + } + for (let t of tos) { + let tCorrected = t; + if (tCorrected > 15) { + tCorrected -= 16; + } + if (tCorrected < 0) { + tCorrected += 16; + } + this.ui.dangerCirclets[tCorrected][l.dist].alpha = 1; + } + + //let s = this.ui.dangerCirclets[l.seg][l.dist]; + //s.alpha = 1; + } + } + } + + this.ui.pitchLimit.y = this.ui.pitchPosY + 64 - 32 * this.playerShip.curveAmt - 32 * this.playerShip.pitch.current; + + //ship sound + if (this.state !== this.states.pause) { + if (this.scene.soundManager.engineSound.howlGroup.playing() === false) { + this.scene.soundManager.playSound(this.scene.soundManager.engineSound); + //this.scene.soundManager.playSound(this.scene.soundManager.engineRotorSound); + } else { + this.scene.soundManager.engineSound.howlGroup.rate(0.1 + 0.9 * Math.min(1, this.playerShip.speed / this.playerShip.speedMax)); + //this.scene.soundManager.engineRotorSound.howlGroup.rate(0.1 + (0.9 * Math.min(1, (this.playerShip.speed + this.playerShip.speedBonus) / (this.playerShip.speedMax + this.playerShip.speedBonus)))); + } + if (this.playerShip.scraping === true && this.finishedRace === false) { + if (this.scene.soundManager.scrapeSound.howlGroup.playing() === false) { + this.scene.soundManager.playSound(this.scene.soundManager.scrapeSound); + } + } else { + this.scene.soundManager.stopSound(this.scene.soundManager.scrapeSound); + } + if (this.playerShip.temp >= 900 && this.finishedRace === false) { + if (this.scene.soundManager.heatWarningSound.howlGroup.playing() === false) { + this.scene.soundManager.playSound(this.scene.soundManager.heatWarningSound); + } + } else { + this.scene.soundManager.stopSound(this.scene.soundManager.heatWarningSound); + } + } + + //move camera + this.moveCamera(); + + /* INFO keep an eye out for this if its buggy when not used also the function nthat hides it + if(this.finishedRace === false){ + this.ui.txtBestLapTime.alpha = 1; + this.ui.txtLastLapTime.alpha = 1; + this.ui.txtLapTime.alpha = 1; + this.ui.txtDelta.alpha = 1; + this.ui.txtHelper.alpha = 1; + } + */ + } + + updateCanyon() { + //console.log(this.playerShip.splineId - this.aiShips[0].splineId); - points = behind + + if (this.raceModeData.playerIsHunter === true) { + let playerBehind = true; + let amt = this.playerShip.splineId - this.aiShips[0].splineId; + if (this.aiShips[0].crossedFinish === false) { + amt -= this.trackBuilder.spline.length; + } + if (this.playerShip.lapTimes.length === this.aiShips[0].lapTimes.length) { + if (amt > 0) { + playerBehind = false; + } + amt += 40; + if (this.playerShip.slipstreaming === true) { + amt *= 1.5; + } + if (playerBehind === false) { + amt *= 2; + } + } else { + amt = 0; + } + if (amt < 0) { + amt = 0; + } + amt = Math.floor(amt); + this.raceModeData.points.overall += amt; + this.raceModeData.points.rounds[0] += amt; + + this.ui.txtBestLapTime.setText(""); + this.ui.txtLastLapTime.setText(`DLT: ${amt}`); + this.ui.txtLapTime.setText(`PTS: ${this.raceModeData.points.overall}`); + } else { + let playerBehind = false; + let amt = this.aiShips[0].splineId - this.playerShip.splineId; + if (this.playerShip.crossedFinish === false) { + amt -= this.trackBuilder.spline.length; + } + if (this.playerShip.lapTimes.length === this.aiShips[0].lapTimes.length) { + if (amt > 0) { + playerBehind = true; + } + amt += 40; + if (this.aiShips[0].slipstreaming === true) { + amt *= 1.5; + } + if (playerBehind === true) { + amt *= 2; + } + } else { + amt = 0; + } + if (amt < 0) { + amt = 0; + } + amt = Math.floor(amt); + this.raceModeData.points.overall -= amt; + this.raceModeData.points.rounds[1] += amt; + + this.ui.txtBestLapTime.setText(""); + this.ui.txtLastLapTime.setText(`DLT: ${amt}`); + this.ui.txtLapTime.setText(`PTS: ${this.raceModeData.points.overall}`); + } + + if (this.aiShips[0].splineId - this.playerShip.splineId > 44) { + this.aiShips[0].speedMax *= 0.9; + } else { + this.aiShips[0].speedMax = 16; + } + } + + startNewCanyon() { + this.ui.txtBestLapTime.setText(`POT: ${this.raceModeData.points.overall}`); + + if (this.playerShip.lapTimes.length >= this.maxLaps) { + this.finishedRace = true; + } + + if (this.finishedRace === false) { + //pause and show mid result, result screen will soft restart the race for second round + this.state = this.states.pause; + this.scene.soundManager.stopSound(this.scene.soundManager.engineSound); + //this.scene.soundManager.stopSound(this.scene.soundManager.engineRotorSound); + this.scene.soundManager.stopSound(this.scene.soundManager.scrapeSound); + this.scene.soundManager.stopSound(this.scene.soundManager.heatWarningSound); + + this.ui.hide(); + //show mid results + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelEndOfCanyon(this.scene, this, this.state); + } + + if (this.finishedRace === true && this.scene.player.panel === null) { + //end for real now + this.playerShip.autopilot = true; + this.ui.hide(); + + //show end results + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelEndOfCanyon(this.scene, this, this.state); + + //if is demo? + if (this.raceModeData.points.overall > 0) { + //you won the race + flagManager.setFlag("wonDemoRace", "true"); + } + flagManager.setFlag("demoProgress", "3"); + } + } + + startNewLap() { + this.ui.txtLastLapTime.setText("LST: " + timeToLapTime(this.playerShip.elapsedTime)); + + let newRecord = false; + let finalLap = false; + if (this.playerShip.lapTimes.length + 1 === this.maxLaps) { + finalLap = true; + } + if (this.playerShip.lapTimes.length >= this.maxLaps) { + this.finishedRace = true; + } + + let r = this.playerShip.lapTimes[this.playerShip.fastestLap]; + let lapNo = this.playerShip.fastestLap + 1; + this.ui.txtBestLapTime.setText("BST: " + timeToLapTime(r.time) + " [L" + lapNo + "]"); + + if (this.playerShip.fastestLap !== this.playerShip.last.fastestLap) { + newRecord = true; + } + + //make the correct sound (new record, finallap, knockedout etc) + if (newRecord === true && finalLap === false) { + this.scene.soundManager.playSpecificSound(this.scene.soundManager.raceAnnouncer, 0); + } + if (finalLap === true) { + this.scene.soundManager.playSpecificSound(this.scene.soundManager.raceAnnouncer, 5); + } + + // + if (this.finishedRace === true && this.scene.player.panel === null) { + this.playerShip.autopilot = true; + this.ui.hide(); + + //show end results + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelEndOfRace(this.scene, this, this.state); + + if (this.raceMode === this.raceModes.canyon) { + if (this.playerShip.position === 0) { + //you won the race + flagManager.setFlag("wonDemoRace", "true"); + } + flagManager.setFlag("demoProgress", "1"); + } + + //this.scene.paused = true; + //this.state = this.states.pause; + //this.scene.soundManager.stopSound(this.scene.soundManager.engineSound); + } + } + + listenToSwitchCamera() { + if (INPUTS.btnY.justReleased) { + if (this.scene.editor.enabled === false) { + this.playerShip.camera += 1; + if (this.playerShip.camera >= 4) { + this.playerShip.camera = 0; + } + //hide ship if in pov cams + if (this.playerShip.camera === 1 || this.playerShip.camera === 2) { + if (this.playerShip.ship.flags.draw === true) { + this.playerShip.ship.flags.draw = false; + this.playerShip.ship.flags.drawn = false; + for (let q of this.playerShip.ship.quadData) { + q.clearQuads(); + } + //this.playerShip.ship.depthMod = -100000; + } + } else { + if (this.playerShip.ship.flags.draw === false) { + this.playerShip.ship.flags.draw = true; + } + //this.playerShip.ship.depthMod = 48; + } + OPTIONS.config.preferredCam = this.playerShip.camera; + } + } + } + + toggleDrawByViewDistance() { + let frontLimit = Math.min(60, this.trackBuilder.spline.length); //60 + let rearLimit = Math.min(62, this.trackBuilder.spline.length - 1); //59 + for (let i = 0; i < frontLimit; i++) { + let fsid = this.playerShip.splineId + i; + if (fsid >= this.trackBuilder.spline.length) { + fsid -= this.trackBuilder.spline.length; + } + if (this.trackBuilder.spline[fsid].model !== null) { + this.trackBuilder.spline[fsid].model.flags.draw = true; + } + + if (this.trackBuilder.spline[this.playerShip.splineId].model !== null) { + this.trackBuilder.spline[this.playerShip.splineId].model.flags.draw = true; + } + } + for (let i = 0; i < rearLimit; i++) { + let rsid = this.playerShip.splineId - i; + if (rsid < 0) { + rsid += this.trackBuilder.spline.length; + } + if (i < rearLimit - 3) { + if (this.trackBuilder.spline[rsid].model !== null) { + this.trackBuilder.spline[rsid].model.flags.draw = true; + } + } else { + if (this.trackBuilder.spline[rsid].model !== null) { + this.trackBuilder.spline[rsid].model.flags.draw = false; + } + } + } + } + + moveCamera() { + let gamepad = null; + gamepad = navigator.getGamepads()[Math.max(0, gamepadsConnected - 1)]; + if (gamepad === undefined) { + gamepad = null; + } + + //this.scene.cam.zoom = 800 - (this.playerShip.speed * 10); + if (this.playerShip.speed + 1 >= this.playerShip.speedMax) { + //todo: find better way to show speed when super fast and especially when slipstreaming and dodging closely + //this.scene.cam.fov = 2.5 + Math.min(2, 2 - (this.playerShip.speedMax - this.playerShip.speed)); + if (this.scene.cam.fov < 3) { + this.scene.cam.fov += 0.1 * this.scene.dt; + this.scene.cam.fov = Math.min(3, this.scene.cam.fov); + } else { + this.scene.cam.fov -= 0.01 * this.scene.dt; + this.scene.cam.fov = Math.max(2.5, this.scene.cam.fov); + } + } else { + if (this.scene.cam.fov > 2.5) { + this.scene.cam.fov -= 0.1 * this.scene.dt; + this.scene.cam.fov = Math.max(2.5, this.scene.cam.fov); + } + } + switch (this.playerShip.camera) { + case this.playerShip.cameras.thirdPersonFollow: + this.scene.player.jumpToPosition( + { + x: + this.playerShip.shipAnchor.pos.x + + this.playerShip.shipAnchor.transform.forward.x * -160 + + this.playerShip.shipAnchor.transform.up.x * (48 - (this.playerShip.flightRadiusUpperLimit - this.playerShip.flightRadius)), + y: + this.playerShip.shipAnchor.pos.y + + this.playerShip.shipAnchor.transform.forward.y * -160 + + this.playerShip.shipAnchor.transform.up.y * (48 - (this.playerShip.flightRadiusUpperLimit - this.playerShip.flightRadius)), + z: + this.playerShip.shipAnchor.pos.z + + this.playerShip.shipAnchor.transform.forward.z * -160 + + this.playerShip.shipAnchor.transform.up.z * (48 - (this.playerShip.flightRadiusUpperLimit - this.playerShip.flightRadius)), + }, + true, + ); + /*this.scene.player.jumpToPosition({ + x: this.playerShip.gondula.pos.x + (this.playerShip.shipAnchor.transform.forward.x * -128) + (this.playerShip.shipAnchor.transform.up.x * -64), + y: this.playerShip.gondula.pos.y + (this.playerShip.shipAnchor.transform.forward.y * -128) + (this.playerShip.shipAnchor.transform.up.y * -64), + z: this.playerShip.gondula.pos.z + (this.playerShip.shipAnchor.transform.forward.z * -128) + (this.playerShip.shipAnchor.transform.up.z * -64) + }, true);*/ + break; + case this.playerShip.cameras.firstPersonCockpit: //todo: pin the camera better to cockpit and do smth about the ship model + this.scene.player.jumpToPosition( + { + x: this.playerShip.ship.pos.x + this.playerShip.ship.transform.forward.x * 16 + this.playerShip.ship.transform.up.x * 32, + y: this.playerShip.ship.pos.y + this.playerShip.ship.transform.forward.y * 16 + this.playerShip.ship.transform.up.y * 32, + z: this.playerShip.ship.pos.z + this.playerShip.ship.transform.forward.z * 16 + this.playerShip.ship.transform.up.z * 32, + }, + true, + ); + break; + case this.playerShip.cameras.firstPersonBumper: + this.scene.player.jumpToPosition( + { + x: + this.playerShip.gondula.pos.x + + this.playerShip.gondula.transform.forward.x * 72 + + this.playerShip.ship.transform.up.x * 8 + + this.playerShip.gondula.transform.up.x * -this.playerShip.flightRadius, + y: + this.playerShip.gondula.pos.y + + this.playerShip.gondula.transform.forward.y * 72 + + this.playerShip.ship.transform.up.y * 8 + + this.playerShip.gondula.transform.up.y * -this.playerShip.flightRadius, + z: + this.playerShip.gondula.pos.z + + this.playerShip.gondula.transform.forward.z * 72 + + this.playerShip.ship.transform.up.z * 8 + + this.playerShip.gondula.transform.up.z * -this.playerShip.flightRadius, + }, + true, + ); + break; + case this.playerShip.cameras.thirdPersonOrbit: + this.scene.player.jumpToPosition( + { + x: this.playerShip.shipAnchor.pos.x + this.scene.cam.transform.forward.x * -128 + this.playerShip.shipAnchor.transform.up.x * 32, + y: this.playerShip.shipAnchor.pos.y + this.scene.cam.transform.forward.y * -128 + this.playerShip.shipAnchor.transform.up.y * 32, + z: this.playerShip.shipAnchor.pos.z + this.scene.cam.transform.forward.z * -128 + this.playerShip.shipAnchor.transform.up.z * 32, + }, + true, + ); + break; + default: + this.scene.player.jumpToPosition( + { + x: this.playerShip.shipAnchor.pos.x + this.playerShip.shipAnchor.transform.forward.x * -128 + this.playerShip.shipAnchor.transform.up.x * 32, + y: this.playerShip.shipAnchor.pos.y + this.playerShip.shipAnchor.transform.forward.y * -128 + this.playerShip.shipAnchor.transform.up.y * 32, + z: this.playerShip.shipAnchor.pos.z + this.playerShip.shipAnchor.transform.forward.z * -128 + this.playerShip.shipAnchor.transform.up.z * 32, + }, + true, + ); + break; + } + + /* + //old direct sometimes jittery but working method + this.scene.cam.transform.up.x = this.playerShip.shipAnchor.transform.up.x; + this.scene.cam.transform.up.y = this.playerShip.shipAnchor.transform.up.y; + this.scene.cam.transform.up.z = this.playerShip.shipAnchor.transform.up.z; + this.scene.cam.transform.right.x = this.playerShip.shipAnchor.transform.right.x; + this.scene.cam.transform.right.y = this.playerShip.shipAnchor.transform.right.y; + this.scene.cam.transform.right.z = this.playerShip.shipAnchor.transform.right.z; + this.scene.cam.transform.forward.x = this.playerShip.shipAnchor.transform.forward.x; + this.scene.cam.transform.forward.y = this.playerShip.shipAnchor.transform.forward.y; + this.scene.cam.transform.forward.z = this.playerShip.shipAnchor.transform.forward.z; + + //this.camOffset.dir.yaw += ((this.scene.player.dir.yaw - this.camOffset.dir.yaw) * 0.1); + //this.camOffset.dir.pitch += ((this.scene.player.dir.pitch - this.camOffset.dir.pitch) * 0.1); + this.camOffset.dir.yaw = this.scene.player.dir.yaw; + this.camOffset.dir.pitch = this.scene.player.dir.pitch; + this.scene.cam.rotateAroundAxis(this.playerShip.gondula.transform.toVectorArray(this.scene.cam.transform.up), this.camOffset.dir.yaw * -1); + this.scene.cam.rotateAroundAxis(this.playerShip.gondula.transform.toVectorArray(this.scene.cam.transform.right), this.camOffset.dir.pitch); + */ + //INFO IMPORTANT move camRig vorher und slerp cam to rig + //this coulod maybe work!! //todo: keep an eye on that - using .ship. instead of anchor seems cool but a bit too exagerated + this.camRig.transform.up.x = this.playerShip.ship.transform.up.x; + this.camRig.transform.up.y = this.playerShip.ship.transform.up.y; + this.camRig.transform.up.z = this.playerShip.ship.transform.up.z; + this.camRig.transform.right.x = this.playerShip.shipAnchor.transform.right.x; + this.camRig.transform.right.y = this.playerShip.shipAnchor.transform.right.y; + this.camRig.transform.right.z = this.playerShip.shipAnchor.transform.right.z; + this.camRig.transform.forward.x = this.playerShip.ship.transform.forward.x; + this.camRig.transform.forward.y = this.playerShip.ship.transform.forward.y; + this.camRig.transform.forward.z = this.playerShip.ship.transform.forward.z; + + if (this.playerShip.camera === this.playerShip.cameras.thirdPersonOrbit) { + //todo: this should be only working when in specific camera and ui be hidden or reacting + //scene.hand.vel is never not 0 if mouse is locked (always when gamepad is connected) + /*if(this.scene.hand.vel.x !== 0){ + this.camOffset.dir.yaw += ((this.scene.hand.vel.x) * this.scene.player.dir.spd.yaw); + } + if(this.scene.hand.vel.y !== 0){ + this.camOffset.dir.pitch += ((this.scene.hand.vel.y) * this.scene.player.dir.spd.pitch); + }*/ + this.camOffset.virtualMouse.delta.x = 0; + this.camOffset.virtualMouse.delta.y = 0; + //let velocity = {delta: {x: 0, y: 0}, lastPos: {x: 0, y: 0}} + if (this.scene.hand.useControllerMouse === false) { + this.camOffset.virtualMouse.pos.x = this.scene.hand.pos.x; + this.camOffset.virtualMouse.pos.y = this.scene.hand.pos.y; + this.camOffset.virtualMouse.delta.x = this.scene.hand.pos.x - this.camOffset.virtualMouse.lastPos.x; + this.camOffset.virtualMouse.delta.y = this.scene.hand.pos.y - this.camOffset.virtualMouse.lastPos.y; + this.camOffset.virtualMouse.lastPos.x = this.scene.hand.pos.x; //gets ignotred because of reset so velocity needs to be somethign in the cam rig or smth like that + this.camOffset.virtualMouse.lastPos.y = this.scene.hand.pos.y; + } else { + //gamepad + //console.log(INPUTS.stickRight.vertical) + if (gamepad !== null) { + //todo INFO + if options enabled gamepad control + //let sra = Math.abs(INPUTS.stickRight.vertical); + //let sla = Math.abs(INPUTS.stickLeft.vertical); + //this.keyInput.pitch = (sra > sla ? (INPUTS.stickRight.vertical * -1) : (INPUTS.stickLeft.vertical * -1)); + + this.camOffset.virtualMouse.delta.x = INPUTS.stickRight.horizontal * -1; + this.camOffset.virtualMouse.delta.y = INPUTS.stickRight.vertical * -1; + } + } + + if (this.camOffset.virtualMouse.delta.x !== 0) { + this.camOffset.dir.yaw += this.camOffset.virtualMouse.delta.x * this.scene.player.dir.spd.yaw; + } + if (this.camOffset.virtualMouse.delta.y !== 0) { + this.camOffset.dir.pitch += this.camOffset.virtualMouse.delta.y * this.scene.player.dir.spd.pitch; + } + } else { + this.camOffset.dir.yaw = 0; + this.camOffset.dir.pitch = 0; + } + //try to look ahead of corner + if (this.playerShip.camera === this.playerShip.cameras.firstPersonBumper) { + this.camOffset.target.dir.pitch = this.playerShip.curveAmt * -0.5; + } else if (this.playerShip.camera === this.playerShip.cameras.thirdPersonFollow) { + this.camOffset.target.dir.pitch = this.playerShip.curveAmt * -0.25; + } else { + this.camOffset.target.dir.pitch = 0; + } + this.camOffset.dir.pitch += (this.camOffset.target.dir.pitch - this.camOffset.dir.pitch) * 0.1; + + this.camOffset.dir.pitch = Math.max(-HALFPI, Math.min(HALFPI, this.camOffset.dir.pitch)); + this.camRig.rotateAroundAxis(this.playerShip.gondula.transform.toVectorArray(this.camRig.transform.up), this.camOffset.dir.yaw); + this.camRig.rotateAroundAxis(this.playerShip.gondula.transform.toVectorArray(this.camRig.transform.right), this.camOffset.dir.pitch); + + let rotFactor = 0.5; + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo( + targetRot, + this.scene.cam.transform.toVectorArray(this.scene.cam.transform.right), + this.scene.cam.transform.toVectorArray(this.camRig.transform.right), //playerShip.ship for rotation with ship + ); + let rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.scene.cam.transform.rotationQuat, targetRot, rotFactor); + this.scene.cam.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo( + targetRot, + this.scene.cam.transform.toVectorArray(this.scene.cam.transform.up), + this.scene.cam.transform.toVectorArray(this.camRig.transform.up), //playerShip.ship for rotation with ship + ); + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.scene.cam.transform.rotationQuat, targetRot, rotFactor); + this.scene.cam.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo( + targetRot, + this.scene.cam.transform.toVectorArray(this.scene.cam.transform.forward), + this.scene.cam.transform.toVectorArray(this.camRig.transform.forward), //playerShip.ship for rotation with ship + ); + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.scene.cam.transform.rotationQuat, targetRot, rotFactor); + this.scene.cam.rotateByQuaternion(rot); + + /*//todo: find a way to also move the camera after all the smooth to track rotation. Currently that does not work as intended... + //new method that tries to blend cam rig rotation with always rotating to ship anchor w/o overrides that tween back and forth to infinity and beyond + let rotFactor = 0.05; + + let targetRot = [0, 0, 0, 0]; + //let out = [0, 0, 0]; + //out = gl_vec3.cross(out, this.scene.cam.transform.toVectorArray(this.scene.cam.transform.forward), this.scene.cam.transform.toVectorArray(this.camRig.transform.up)), + targetRot = gl_quat.rotationTo(targetRot, + this.scene.cam.transform.toVectorArray( this.scene.cam.transform.right), + //out, + this.scene.cam.transform.toVectorArray( this.playerShip.shipAnchor.transform.right) //playerShip.ship for rotation with ship + ) + let rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.scene.cam.transform.rotationQuat, targetRot, rotFactor); + this.scene.cam.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + //out = [0, 0, 0]; + //out = gl_vec3.cross(out, this.scene.cam.transform.toVectorArray(this.scene.cam.transform.right), this.scene.cam.transform.toVectorArray(this.camRig.transform.forward)), + targetRot = gl_quat.rotationTo(targetRot, + this.scene.cam.transform.toVectorArray( this.scene.cam.transform.up), + //out, + this.scene.cam.transform.toVectorArray( this.playerShip.shipAnchor.transform.up) //playerShip.ship for rotation with ship + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.scene.cam.transform.rotationQuat, targetRot, rotFactor); + this.scene.cam.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + //out = [0, 0, 0]; + //out = gl_vec3.cross(out, this.scene.cam.transform.toVectorArray(this.scene.cam.transform.up), this.scene.cam.transform.toVectorArray(this.camRig.transform.right)), + targetRot = gl_quat.rotationTo(targetRot, + this.scene.cam.transform.toVectorArray( this.scene.cam.transform.forward), + //out, + this.scene.cam.transform.toVectorArray( this.playerShip.shipAnchor.transform.forward) //playerShip.ship for rotation with ship + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.scene.cam.transform.rotationQuat, targetRot, rotFactor); + this.scene.cam.rotateByQuaternion(rot); + + + //this.camRig.transform.up.x = this.scene.cam.transform.up.x; + //this.camRig.transform.up.y = this.scene.cam.transform.up.y; + //this.camRig.transform.up.z = this.scene.cam.transform.up.z; + //this.camRig.transform.right.x = this.scene.cam.transform.right.x; + //this.camRig.transform.right.y = this.scene.cam.transform.right.y; + //this.camRig.transform.right.z = this.scene.cam.transform.right.z; + //this.camRig.transform.forward.x = this.scene.cam.transform.forward.x; + //this.camRig.transform.forward.y = this.scene.cam.transform.forward.y; + //this.camRig.transform.forward.z = this.scene.cam.transform.forward.z; + + //this.camOffset.dir.yaw = this.scene.player.dir.yaw; + //this.camOffset.dir.pitch = this.scene.player.dir.pitch; + //this.camRig.rotateAroundAxis(this.playerShip.gondula.transform.toVectorArray(this.camRig.transform.up), this.camOffset.dir.yaw); + //this.camRig.rotateAroundAxis(this.playerShip.gondula.transform.toVectorArray(this.camRig.transform.right), this.camOffset.dir.pitch); + + //this.scene.cam.rotateAroundAxis(this.playerShip.gondula.transform.toVectorArray(this.scene.cam.transform.up), this.camOffset.dir.yaw * -1); + //this.scene.cam.rotateAroundAxis(this.playerShip.gondula.transform.toVectorArray(this.scene.cam.transform.right), this.camOffset.dir.pitch); + */ + } + + assessSituation() { + //let who = ""; + let action = null; + + if (this.situation.actions.win.who !== "") { + action = this.situation.actions.win; + let character = this.aiShips.filter(el => el.name === action.who)[0].character; + this.ui.addReaction("charSheetExpressions", character.reactions.cheer[Math.floor(Math.random() * character.reactions.cheer.length)], character); + } else if (this.situation.actions.loose.who !== "") { + action = this.situation.actions.loose; + let character = this.aiShips.filter(el => el.name === action.who)[0].character; + this.ui.addReaction("charSheetExpressions", character.reactions.angry[Math.floor(Math.random() * character.reactions.angry.length)], character); + } else if (this.situation.actions.hit.who !== "") { + action = this.situation.actions.hit; + let character = this.aiShips.filter(el => el.name === action.who)[0].character; + this.ui.addReaction("charSheetExpressions", character.reactions.hit[Math.floor(Math.random() * character.reactions.hit.length)], character); + } else if (this.situation.actions.gainPosition.who !== "") { + action = this.situation.actions.gainPosition; + let character = this.aiShips.filter(el => el.name === action.who)[0].character; + this.ui.addReaction("charSheetExpressions", character.reactions.angry[Math.floor(Math.random() * character.reactions.angry.length)], character); + } else if (this.situation.actions.loosePosition.who !== "") { + action = this.situation.actions.loosePosition; + let character = this.aiShips.filter(el => el.name === action.who)[0].character; + this.ui.addReaction("charSheetExpressions", character.reactions.haha[Math.floor(Math.random() * character.reactions.haha.length)], character); + } else if (this.situation.actions.slipstream.who !== "") { + action = this.situation.actions.slipstream; + let character = this.aiShips.filter(el => el.name === action.who)[0].character; + this.ui.addReaction("charSheetExpressions", character.reactions.thinking[Math.floor(Math.random() * character.reactions.thinking.length)], character); + } else if (this.situation.actions.slipstreamed.who !== "") { + action = this.situation.actions.slipstreamed; + let character = this.aiShips.filter(el => el.name === action.who)[0].character; + this.ui.addReaction("charSheetExpressions", character.reactions.taunt[Math.floor(Math.random() * character.reactions.taunt.length)], character); + } else if (this.situation.actions.mishap.who !== "") { + action = this.situation.actions.mishap; + let character = this.aiShips.filter(el => el.name === action.who)[0].character; + this.ui.addReaction("charSheetExpressions", character.reactions.haha[Math.floor(Math.random() * character.reactions.haha.length)], character); + } + + /* + who = this.situation.actions.hit.who; + let actions = [ + this.situation.actions.hit, + this.situation.actions.gainPosition, + this.situation.actions.loosePosition, + this.situation.actions.mishap, + this.situation.actions.slipstream, + this.situation.actions.slipstreamed, + this.situation.actions.win, + this.situation.actions.loose + ] + actions = actions.sort((a, b) => { a.priority - b.priority }); + console.log(actions[0].priority); + + if (actions[0].priority > 0) { + who = actions[0].who; + if (who !== "") { + if (actions[0] == this.situation.actions.hit) { + console.log("hit someone") + let character = this.aiShips.filter(el => el.name === who)[0].character; + this.ui.addReaction("charSheetExpressions", character.reactions.hit[Math.floor(Math.random() * character.reactions.hit.length)]); + } else if (actions[0] == this.situation.actions.gainPosition) { + console.log("gained a position") + } else { + console.log(actions[0]); + } + } + } + */ + } + + resetSituation() { + this.situation = { + actions: { + hit: { //player bumping into ai + who: "", + priority: 0, + time: 0 + }, slipstream: { //player slipstreaming ai + who: "", + priority: 0, + time: 0 + }, slipstreamed: { //ai slipstreaming behind player + who: "", + priority: 0, + time: 0 + }, gainPosition: { //player overtakes ai + who: "", + priority: 0, + time: 0 + }, loosePosition: { //ai overtakes player + who: "", + priority: 0, + time: 0 + }, mishap: { //player crashes near ai + who: "", + priority: 0, + time: 0 + }, win: { //ai wins + who: "", + priority: 0, + time: 0 + }, loose: { //player wins / rival looses + who: "", + priority: 0, + time: 0 + } + } + } + } + + loadTrack(_track = 0, _pos = 7) { + this.graLoading.alpha = 1; + this.txtLoading.alpha = 1; + setTimeout(() => { + this.trackBuilder.loadTrack(_track); + + if (this.raceMode === this.raceModes.canyon) { + if (this.raceModeData.playerIsHunter === true) { + this.playerShip.restartOnFromSplineId(1); + this.aiShips[0].restartOnFromSplineId((0 + 1) * 5 + 1, Math.PI * 0.25 * (0 + 1)); + } else { + this.playerShip.restartOnFromSplineId((0 + 1) * 5 + 1, Math.PI * 0.25 * (0 + 1)); + this.aiShips[0].restartOnFromSplineId(1); + } + } else { + //normal racing + this.playerShip.restartOnFromSplineId(1); + for (let [i, ai] of this.aiShips.entries()) { + ai.restartOnFromSplineId((i + 1) * 5 + 1, Math.PI * 0.25 * (i + 1)); + } + } + + + /* + this.playerShip.splineId = 0; + let splg = this.trackBuilder.spline[this.playerShip.splineId]; + this.playerShip.gondula.jumpToPosition({x: splg.x, y: splg.y, z: splg.z}); + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.playerShip.gondula.transform.toVectorArray( this.playerShip.gondula.transform.forward), + [0, 0, 1] + ) + this.playerShip.gondula.rotateByQuaternion(targetRot); + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.playerShip.gondula.transform.toVectorArray( this.playerShip.gondula.transform.right), + [1, 0, 0] + ) + this.playerShip.gondula.rotateByQuaternion(targetRot); + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.playerShip.gondula.transform.toVectorArray( this.playerShip.gondula.transform.up), + [0, -1, 0] + ) + this.playerShip.gondula.rotateByQuaternion(targetRot); + this.playerShip.speed = 0; + */ + + this.graLoading.alpha = 0; + this.txtLoading.alpha = 0; + + this.countdown.start = Date.now(); + this.countdown.current = Date.now() - this.countdown.start; + this.countdown.step = 0; + this.countdown.go = false; + this.state = this.states.countDown; + }, 10); + } + + updateTutorial() { + switch (this.tutorialStep) { + case 0: + this.playerShip.speed = 0; + this.playerShip.input.roll = 0; + this.aiShips[0].speed = 0; + this.aiShips[0].input.roll = 0; + break; + case 1: //just rolling and checking pitch HEAT ZONE + this.playerShip.speed = 0; + //this.playerShip.input.roll = 0; + this.playerShip.rollSpeedMax = 1; + this.playerShip.rollSpeedMin = -1; + this.aiShips[0].speed = 0; + this.aiShips[0].input.roll = 0; + this.aiShips[0].rollSpeedMax = 1; + this.aiShips[0].rollSpeedMin = -1; + + //console.log(this.playerShip.distToPerfectPitch) + if (this.playerShip.distToPerfectPitch > 0 && this.playerShip.distToPerfectPitch < 32) { + this.tutorialHoldVar += this.scene.dt; + if (this.tutorialHoldVar >= this.tutorialHoldVarMax) { + this.cycleTutorial(); + } + } else { + if (this.tutorialHoldVar > 0) { + this.tutorialHoldVar -= this.scene.dt; + } + } + //console.log(this.tutorialHoldVar) + break; + case 2: + this.playerShip.speed = 0; + this.playerShip.input.roll = 0; + this.aiShips[0].speed = 0; + this.aiShips[0].input.roll = 0; + break; + case 3: + if (this.aiShips[0].splineId - this.playerShip.splineId > 44) { + this.aiShips[0].speed = 0; + } + break; + case 4: + this.playerShip.speed = 0; + this.playerShip.input.roll = 0; + this.aiShips[0].speed = 0; + this.aiShips[0].input.roll = 0; + break; + case 5: //sllipstreaming + if (this.aiShips[0].splineId - this.playerShip.splineId > 44) { + this.aiShips[0].speed = 0; + } + if (this.aiShips[0].splineId - this.playerShip.splineId < -20) { + if (this.tutorialHoldVar > 10) { + //this.tutorialHoldVar += 4 * this.scene.dt; + //if (this.tutorialHoldVar >= this.tutorialHoldVarMax * 0.25) { + this.cycleTutorial(); + //} + } + } + if (this.playerShip.slipstreaming === true) { + this.aiShips[0].speedMax = 14; + + this.tutorialHoldVar += 1 * this.scene.dt; + if (this.tutorialHoldVar >= this.tutorialHoldVarMax) { + this.cycleTutorial(); + } + } else { + this.aiShips[0].speedMax = 12; + if (this.tutorialHoldVar > 0) { + this.tutorialHoldVar -= 0.1 * this.scene.dt; + } + } + break; + case 6: + break; + case 7://free time trial + //catch up and wait mechanic + if (this.aiShips[0].splineId - this.playerShip.splineId > 44) { + this.aiShips[0].speedMax = 5; + } else if (this.aiShips[0].splineId - this.playerShip.splineId < -44) { + this.aiShips[0].speedMax = 18; + } else { + this.aiShips[0].speedMax = 16; + } + + this.playerShip.temp *= 0.5; + if (this.playerShip.lapTimes.length >= 1) { + this.cycleTutorial(); + } + break; + case 8: + break; + /* + case 99: //speedcheck + if (Math.floor(this.playerShip.speed * 10) >= 200) { + this.tutorialHoldVar += this.scene.dt; + if (this.playerShip.scraping === false && this.tutorialHoldVar > 300) { + this.cycleTutorial(); + } + } + break; + case 5: + //this.playerShip.speed = 0; + //this.playerShip.input.roll = 0; + //this.aiShips[0].speed = 0; + //this.aiShips[0].input.roll = 0; + //this.aiShips[0].input.pitch = 0; + if (this.aiShips[0].splineId - this.playerShip.splineId > 44) { + this.aiShips[0].speed = 0; + } + if (this.playerShip.slipstreaming === true) { + this.tutorialHoldVar += 1 * this.scene.dt; + if (this.tutorialHoldVar >= this.tutorialHoldVarMax) { + this.cycleTutorial(); + } + } else { + if (this.tutorialHoldVar > 0) { + this.tutorialHoldVar -= 0.1 * this.scene.dt; + } + } + break; + */ + /* + case 993://how to slipstream + if (this.aiShips[0].splineId - this.playerShip.splineId > 44) { + this.aiShips[0].speed = 0; + } + + if (this.playerShip.position === 0 && this.aiShips[0].splineId - this.playerShip.splineId < -10 && this.playerShip.slipsteamTime > 30) { + this.cycleTutorial(); + } + break; + case 5: + if (this.aiShips[0].splineId - this.playerShip.splineId > 44) { + this.aiShips[0].speed = 0; + } + + if (this.playerShip.position === 1 && this.aiShips[0].splineId - this.playerShip.splineId > 20) { + this.cycleTutorial(); + } + break; + */ + default: + console.log(`could not find step ${this.tutorialStep} in tutorial update`); + this.cycleTutorial(); + break; + } + } + + cycleTutorial() { + /* + 0. look at your pitch + 1. speedcheck to 200 for X seconds / keep in speedzone for X seconds + 3. playground 1 / gather coins at shown ideal line (small but curve map with at least a hump not only a circle - 180 right, up down, 180 right straight) + (X. jump to start again) or at least let Roki show up in front of you + ---maybe go back to hangar? + 4. follow in slipstream for X seconds in same map that you played around + 5. overtake (2 times?) throug slipstream + */ + this.tutorialStep += 1; + console.log(`tutorial step ${this.tutorialStep}`); + switch (this.tutorialStep) { + case 0: //how to accelerate + this.ui.txtProgress.setText(""); + //start conversation + this.ui.hide(); + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelRaceTutorial(this.scene, this, this.state, this.tutorialStep); + //this.scene.paused = true; + //this.state = this.states.pause; + this.playerShip.speedMax = 1; + this.playerShip.speed = 0; + this.playerShip.rollSpeedMax = 0.1; + this.playerShip.rollSpeedMin = -0.1; + this.playerShip.autopilot = true; + + this.aiShips[0].speedMax = 1; + this.playerShip.speed = 0; + this.aiShips[0].rollSpeedMax = 0.1; + this.aiShips[0].rollSpeedMin = -0.1; + break; + case 1: + this.ui.txtProgress.setText("keep pitch indicator in the white HEAT ZONE"); + this.playerShip.autopilot = false; + break; + case 2: //start collectathon 1 //how to slipstream + this.ui.txtProgress.setText(""); + //start conversation + this.ui.hide(); + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelRaceTutorial(this.scene, this, this.state, this.tutorialStep); + + this.playerShip.speedMax = 1; + this.playerShip.rollSpeedMax = 0.1; + this.playerShip.rollSpeedMin = -0.1; + this.playerShip.autopilot = true; + + this.aiShips[0].speedMax = 1; + this.aiShips[0].rollSpeedMax = 0.1; + this.aiShips[0].rollSpeedMin = -0.1; + + this.trackBuilder.createObstacles(this.trackBuilder.currentTrackId, [ + /*{sp: this.trackBuilder.spline[50], angle: Math.PI * 0.25, radius: 0, model: "modObstSteam", name: "steam 0"}, + {sp: this.trackBuilder.spline[50], angle: Math.PI * 0.75, radius: 0, model: "modObstSteam", name: "steam 1"}, + {sp: this.trackBuilder.spline[50], angle: Math.PI * -0.25, radius: 0, model: "modObstSteam", name: "steam 2"}, + {sp: this.trackBuilder.spline[50], angle: Math.PI * -0.75, radius: 0, model: "modObstSteam", name: "steam 3"}*/ + { sp: this.trackBuilder.spline[0], angle: Math.PI * 0.5, radius: 100, model: "modRacingPickup", name: "token 0" }, + { sp: this.trackBuilder.spline[20], angle: Math.PI * 0.5, radius: 100, model: "modRacingPickup", name: "token 1" }, + { sp: this.trackBuilder.spline[40], angle: Math.PI * 0.5, radius: 100, model: "modRacingPickup", name: "token 2" }, + { sp: this.trackBuilder.spline[60], angle: Math.PI * 0.5, radius: 100, model: "modRacingPickup", name: "token 3" }, + { sp: this.trackBuilder.spline[80], angle: Math.PI * 0.5, radius: 100, model: "modRacingPickup", name: "token 4" }, + + { sp: this.trackBuilder.spline[100], angle: Math.PI * 0.25, radius: 100, model: "modRacingPickup", name: "token 5" }, + { sp: this.trackBuilder.spline[120], angle: Math.PI * 0, radius: 100, model: "modRacingPickup", name: "token 6" }, + { sp: this.trackBuilder.spline[140], angle: Math.PI * -0.25, radius: 100, model: "modRacingPickup", name: "token 7" }, + + { sp: this.trackBuilder.spline[160], angle: Math.PI * -0.5, radius: 100, model: "modRacingPickup", name: "token 10" }, + { sp: this.trackBuilder.spline[180], angle: Math.PI * -0.5, radius: 100, model: "modRacingPickup", name: "token 11" }, + { sp: this.trackBuilder.spline[200], angle: Math.PI * -0.5, radius: 100, model: "modRacingPickup", name: "token 12" }, + { sp: this.trackBuilder.spline[220], angle: Math.PI * -0.5, radius: 100, model: "modRacingPickup", name: "token 13" }, + { sp: this.trackBuilder.spline[240], angle: Math.PI * -0.5, radius: 100, model: "modRacingPickup", name: "token 14" }, + + { sp: this.trackBuilder.spline[260], angle: Math.PI * -0.25, radius: 100, model: "modRacingPickup", name: "token 15" }, + { sp: this.trackBuilder.spline[280], angle: Math.PI * 0, radius: 100, model: "modRacingPickup", name: "token 16" }, + { sp: this.trackBuilder.spline[300], angle: Math.PI * 0.25, radius: 100, model: "modRacingPickup", name: "token 17" }, + ]); + + this.tutorialHoldVar = 0; + this.tutorialHoldVarMax = 16; + for (let o of this.trackBuilder.obstacles) { + o.data.ignoreRadar = false; + o.trigger.isTrigger = true; + o.updateTrigger = () => { + if (o.trigger.other.name === "Player") { + this.scene.geometryController.destroyModelById(o.id); + this.scene.soundManager.playSound(this.scene.soundManager.computerStartSound); + + this.tutorialHoldVar += 1; + this.ui.txtProgress.setText(`${this.tutorialHoldVar} of 16 token`); + o.data.ignoreRadar = true; + console.log(this.tutorialHoldVar); + if (this.tutorialHoldVar >= this.tutorialHoldVarMax) { + this.cycleTutorial(); + } + } + }; + } + break; + /*case 99: + this.playerShip.speedMax = 16; + this.playerShip.rollSpeedMax = 1; + this.playerShip.rollSpeedMin = -1; + this.playerShip.autopilot = false; + this.ui.show(); + + this.aiShips[0].speedMax = 16; + this.aiShips[0].rollSpeedMax = 1; + this.aiShips[0].rollSpeedMin = -1; + break;*/ + case 3: + console.log("tutorial cycled to 3! free to race and collect the coins"); + + this.ui.txtProgress.setText(`${this.tutorialHoldVar} of 16 token`); + + this.playerShip.speedMax = 12; + this.playerShip.rollSpeedMax = 1; + this.playerShip.rollSpeedMin = -1; + this.playerShip.autopilot = false; + this.ui.show(); + + this.aiShips[0].speedMax = 11; + this.aiShips[0].rollSpeedMax = 1; + this.aiShips[0].rollSpeedMin = -1; + break; + case 4: + this.ui.txtProgress.setText(""); + + console.log("tutorial for slipstream / overtake"); + //start conversation + this.ui.hide(); + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelRaceTutorial(this.scene, this, this.state, this.tutorialStep); + + this.playerShip.speedMax = 1; + this.playerShip.rollSpeedMax = 0.1; + this.playerShip.rollSpeedMin = -0.1; + this.playerShip.autopilot = true; + + this.aiShips[0].speedMax = 1; + this.aiShips[0].rollSpeedMax = 0.1; + this.aiShips[0].rollSpeedMin = -0.1; + + break; + case 5: + console.log("go slipstreaming"); + this.ui.txtProgress.setText("stay in Roki's SLIPSTREAM"); + + this.playerShip.speedMax = 14; + this.playerShip.rollSpeedMax = 1; + this.playerShip.rollSpeedMin = -1; + this.playerShip.autopilot = false; + this.playerShip.crashPoints = 0; + this.ui.show(); + + this.aiShips[0].speedMax = 13; + this.aiShips[0].rollSpeedMax = 1; + this.aiShips[0].rollSpeedMin = -1; + this.aiShips[0].pitch.max = 0.75; + this.aiShips[0].pitch.min = -0.75; + + this.tutorialHoldVar = 0; + this.tutorialHoldVarMax = 1000; + + this.startFromHangar = false; + this.params.startFromHangar = false; + this.loadTrack(9001); + + //restart all ships + for (let ai of this.aiShips) { + ai.lapTimes = []; + ai.fastestLap = 0; + ai.last.fastestLap = 0; + } + this.playerShip.lapTimes = []; + this.playerShip.fastestLap = 0; + this.playerShip.last.fastestLap = 0; + this.playerShip.autopilot = false; + this.ui.show(); + + this.finishedRace = false; + this.maxLaps = 9999; + break; + case 6: + console.log("tutorial for end"); + this.ui.txtProgress.setText(""); + + if (this.playerShip.crashPoints > 0) { + this.aiShips[0].ship.data.conversation.treePosition = 15; + } + if (this.aiShips[0].splineId - this.playerShip.splineId < -20) { + this.aiShips[0].ship.data.conversation.treePosition = 22; + if (this.playerShip.crashPoints > 0) { + this.aiShips[0].ship.data.conversation.treePosition = 21; + } + } + this.playerShip.crashPoints = 0; + + //start conversation + this.ui.hide(); + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelRaceTutorial(this.scene, this, this.state, this.tutorialStep); + + this.playerShip.speedMax = 1; + this.playerShip.rollSpeedMax = 0.1; + this.playerShip.rollSpeedMin = -0.1; + this.playerShip.autopilot = true; + + this.aiShips[0].speedMax = 1.5; + this.aiShips[0].rollSpeedMax = 0.1; + this.aiShips[0].rollSpeedMin = -0.1; + this.aiShips[0].pitch.max = 1; + this.aiShips[0].pitch.min = -1; + + + + + break; + case 7: + console.log("free time trial"); + + this.playerShip.speedMax = 16; + this.playerShip.rollSpeedMax = 1; + this.playerShip.rollSpeedMin = -1; + this.playerShip.autopilot = false; + this.playerShip.crashPoints = 0; + this.ui.show(); + + this.aiShips[0].speedMax = 16; + this.aiShips[0].rollSpeedMax = 1; + this.aiShips[0].rollSpeedMin = -1; + this.aiShips[0].pitch.max = 1; + this.aiShips[0].pitch.min = -1; + + this.startFromHangar = false; + this.params.startFromHangar = false; + this.loadTrack(9002); + + //restart all ships + for (let ai of this.aiShips) { + ai.lapTimes = []; + ai.fastestLap = 0; + ai.last.fastestLap = 0; + } + this.playerShip.lapTimes = []; + this.playerShip.fastestLap = 0; + this.playerShip.last.fastestLap = 0; + this.playerShip.autopilot = false; + this.ui.show(); + + this.finishedRace = false; + this.maxLaps = 99; + + /* +console.log("tutorial end after slipstream"); + +//start conversation +this.ui.hide(); +this.scene.player.hideUI(); +this.scene.player.setMode(PLAYERMODE.INTERACT); +this.scene.player.panel = new PanelRaceTutorial(this.scene, this, this.state, this.tutorialStep); + +this.playerShip.speedMax = 1; +this.playerShip.rollSpeedMax = 0.1; +this.playerShip.rollSpeedMin = -0.1; +this.playerShip.autopilot = true; + +this.aiShips[0].speedMax = 1; +this.aiShips[0].rollSpeedMax = 0.1; +this.aiShips[0].rollSpeedMin = -0.1; +*/ + + break; + case 8: + + //start conversation + this.ui.hide(); + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelRaceTutorial(this.scene, this, this.state, this.tutorialStep); + + this.playerShip.speedMax = 1; + this.playerShip.rollSpeedMax = 0.1; + this.playerShip.rollSpeedMin = -0.1; + this.playerShip.autopilot = true; + + this.aiShips[0].speedMax = 1; + this.aiShips[0].rollSpeedMax = 0.1; + this.aiShips[0].rollSpeedMin = -0.1; + + /* + this.playerShip.autopilot = true; + this.ui.hide(); + + //show end results + this.maxLaps = -1; + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelEndOfRace(this.scene, this, this.state); + + if (this.raceMode === this.raceModes.tutorial) { + if (this.playerShip.position === 0) { + //you won the race + flagManager.setFlag("wonDemoRace", "true"); + } + flagManager.setFlag("demoProgress", "1"); + } + */ + break; + /*/ + case 94://resolve slipstream + if (this.playerShip.crashPoints > 0) { + this.playerShip.crashPoints = 0; + this.aiShips[0].ship.data.conversation.treePosition = 8; + } + //start conversation + this.ui.hide(); + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelRaceTutorial(this.scene, this, this.state, this.tutorialStep); + + this.playerShip.speedMax = 1; + this.playerShip.rollSpeedMax = 0.1; + this.playerShip.rollSpeedMin = -0.1; + this.playerShip.autopilot = true; + + this.aiShips[0].speedMax = 1; + this.aiShips[0].rollSpeedMax = 0.1; + this.aiShips[0].rollSpeedMin = -0.1; + break; + case 5://fall back to second + this.playerShip.speedMax = 10; + this.playerShip.rollSpeedMax = 1; + this.playerShip.rollSpeedMin = -1; + this.playerShip.autopilot = false; + this.ui.show(); + + this.aiShips[0].speedMax = 16; + this.aiShips[0].rollSpeedMax = 1; + this.aiShips[0].rollSpeedMin = -1; + break; + case 6://show extra controls and object avoid + if (this.playerShip.crashPoints > 0) { + this.playerShip.crashPoints = 0; + this.aiShips[0].ship.data.conversation.treePosition = 8; + } + //start conversation + this.ui.hide(); + this.scene.player.hideUI(); + this.scene.player.setMode(PLAYERMODE.INTERACT); + this.scene.player.panel = new PanelRaceTutorial(this.scene, this, this.state, this.tutorialStep); + + this.playerShip.speedMax = 1; + this.playerShip.rollSpeedMax = 0.1; + this.playerShip.rollSpeedMin = -0.1; + this.playerShip.autopilot = true; + + this.aiShips[0].speedMax = 1; + this.aiShips[0].rollSpeedMax = 0.1; + this.aiShips[0].rollSpeedMin = -0.1; + break; + case 7://fall back to second + this.playerShip.speedMax = 16; + this.playerShip.rollSpeedMax = 1; + this.playerShip.rollSpeedMin = -1; + this.playerShip.autopilot = false; + this.ui.show(); + + this.aiShips[0].speedMax = 18; + this.aiShips[0].rollSpeedMax = 1; + this.aiShips[0].rollSpeedMin = -1; + + this.startFromHangar = false; + this.params.startFromHangar = false; + this.loadTrack(0); + + //restart all ships + for (let ai of this.aiShips) { + ai.lapTimes = []; + ai.fastestLap = 0; + ai.last.fastestLap = 0; + } + this.playerShip.lapTimes = []; + this.playerShip.fastestLap = 0; + this.playerShip.last.fastestLap = 0; + this.playerShip.autopilot = false; + this.ui.show(); + + this.finishedRace = false; + this.maxLaps = 3; + break;*/ + default: + console.log(`could not find tutorial step ${this.tutorialStep}`); + break; + } + } + + createDefaultRing() { + //first Ring Test + let ring = this.scene.geometryController.loadModel("ring DEFAULT", "modDebugTile", { x: 0, y: 0, z: 0 }); + ring.flags.draw = true; + let ringPts = []; + let r = 128; + let iter = 0; + for (let i = 0; i < Math.PI * 2; i += Math.PI / 8) { + let xx = Math.cos(i) * r; + let yy = Math.sin(i) * r; + ringPts.push({ x: xx, y: yy, z: 0 }); + iter += 1; + } + //console.log(ringPts) + let texture = "sprDebugTexture"; + for (let i = 0; i < ringPts.length - 1; i++) { + ring.addQuadFromData({ + //this.scene, this.id, no, _q.type, pos, _q.points, _q.texture, _q.frame + type: "quad", + frame: texture, + texture: "atlasAll", + position: { x: 0, y: 0, z: 0 }, + points: [ + { + //hinten rechts + x: ringPts[i].x, + y: ringPts[i].y, + z: -this.trackBuilder.ringDeepness, + }, + { + //hinten links + x: ringPts[i + 1].x, + y: ringPts[i + 1].y, + z: -this.trackBuilder.ringDeepness, + }, + { + //vorne links + x: ringPts[i + 1].x, + y: ringPts[i + 1].y, + z: 0, + }, + { + //vorne rechts + x: ringPts[i].x, + y: ringPts[i].y, + z: 0, + }, + ], + }); + } + ring.addQuadFromData({ + type: "quad", + frame: texture, + texture: "atlasAll", + position: { x: 0, y: 0, z: 0 }, + points: [ + { + x: ringPts[ringPts.length - 1].x, + y: ringPts[ringPts.length - 1].y, + z: -this.trackBuilder.ringDeepness, + }, + { + x: ringPts[0].x, + y: ringPts[0].y, + z: -this.trackBuilder.ringDeepness, + }, + { + x: ringPts[0].x, + y: ringPts[0].y, + z: 0, + }, + { + x: ringPts[ringPts.length - 1].x, + y: ringPts[ringPts.length - 1].y, + z: 0, + }, + ], + }); + + //outer Ring + + ringPts = []; + iter = 0; + r = 256; + for (let i = 0; i < Math.PI * 2; i += Math.PI / 8) { + let xx = Math.cos(i) * r; + let yy = Math.sin(i) * r; + ringPts.push({ x: xx, y: yy, z: 0 }); + iter += 1; + } + texture = "sprDebugTexture"; + for (let i = 0; i < ringPts.length - 1; i++) { + ring.addQuadFromData({ + //this.scene, this.id, no, _q.type, pos, _q.points, _q.texture, _q.frame + type: "quad", + frame: texture, + texture: "atlasAll", + position: { x: 0, y: 0, z: 0 }, + points: [ + { + //hinten rechts + x: ringPts[i].x, + y: ringPts[i].y, + z: -this.trackBuilder.ringDeepness, + }, + { + //hinten links + x: ringPts[i + 1].x, + y: ringPts[i + 1].y, + z: -this.trackBuilder.ringDeepness, + }, + { + //vorne links + x: ringPts[i + 1].x, + y: ringPts[i + 1].y, + z: 0, + }, + { + //vorne rechts + x: ringPts[i].x, + y: ringPts[i].y, + z: 0, + }, + ], + }); + } + ring.addQuadFromData({ + type: "quad", + frame: texture, + texture: "atlasAll", + position: { x: 0, y: 0, z: 0 }, + points: [ + { + x: ringPts[ringPts.length - 1].x, + y: ringPts[ringPts.length - 1].y, + z: -this.trackBuilder.ringDeepness, + }, + { + x: ringPts[0].x, + y: ringPts[0].y, + z: -this.trackBuilder.ringDeepness, + }, + { + x: ringPts[0].x, + y: ringPts[0].y, + z: 0, + }, + { + x: ringPts[ringPts.length - 1].x, + y: ringPts[ringPts.length - 1].y, + z: 0, + }, + ], + }); + + /* + ring.addQuadFromData({ + type: "collisionQuad", + position: { x: 0, y: 0, z: 0 }, + points: [ + {//hinten rechts + x: 128, + y: 128, + z: -this.trackBuilder.ringDeepness + },{//hinten links + x: -128, + y: 128, + z: -this.trackBuilder.ringDeepness + },{//vorne links + x: -128, + y: 128, + z: 0 + },{//vorne rechts + x: 128, + y: 128, + z: 0 + } + ] + }); + */ + + //ring.deleteQuad(ring.quadData[0]) + + return ring; + } + + destroy() { + this.ui.destroy(); + this.trackBuilder.clearTrack(); + this.playerShip.destroy(); + for (let ai of this.aiShips) { + ai.destroy(); + } + } +} diff --git a/src/3d/levels/lvlRaceDirectorOffice00.js b/src/3d/levels/lvlRaceDirectorOffice00.js new file mode 100755 index 0000000..469a184 --- /dev/null +++ b/src/3d/levels/lvlRaceDirectorOffice00.js @@ -0,0 +1,81 @@ +import PanelWelcome from "../../ui/panelWelcome.js"; +import GroupElevator from "../groups/grpElevator.js"; + +export default class LevelRaceDirectorOffice00 { + constructor(_scene, _params) { + this.scene = _scene; + + //this.ref = this.scene.geometryController.loadModel("levelOrigin", "modDebugTile", { x: 0, y: 0, z: 0 }); + //this.ref.flags.draw = true; + + this.scene.player = this.scene.playerWalk; + this.scene.cam = this.scene.camWalk; + + //this.scene.player.dir.pitch = 0; + + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + this.elevator = new GroupElevator(this.scene, this, { x: 0, y: 0, z: 0 }); + this.elevator.setDraw(true); + + this.officeRoom = this.scene.geometryController.loadModel("officeRoom", "modRaceDirectorOfficeRoom", { x: 0, y: 0, z: 96 }); + this.officeRoom.flags.draw = true; + + this.charGuard = this.scene.geometryController.loadModel("charMaleguard", "modCharacterDefaultHuman", { x: 0, y: 0, z: 158 }); + this.charGuard.quadData[0].setTexture("charSheetMaleguard", "maleguardStandIdle0000"); + this.charGuard.atlas = "charSheetMaleguard"; + this.charGuard.atlas8wayFrame = "maleguardStandIdle000"; + this.charGuard.scale({ x: 1.0, y: 1, z: 1 }); + this.charGuard.flags.draw = true; + this.charGuard.lookDir.yaw = Math.PI; + this.charGuard.setDrawMode(DRAWMODE.BILLBOARD); + this.charGuard.flags.is8way = true; + this.charGuard.flags.usesAtlas = true; + this.charGuard.depthMod = 16; + this.charGuard.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaOffice00Guard00", + treePosition: 0, + }, + }; + this.charGuard.interactable = true; + this.charGuard.interact = () => { + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charGuard); + this.scene.player.conversationManager.setConversation(this.charGuard.data.conversation.fileName, this.charGuard.data.conversation.treePosition); + }; + + this.charRaceDirector = this.scene.geometryController.loadModel("charRaceDirector", "modCharacterDefaultHuman", { x: -24, y: 0, z: 317 }); + this.charRaceDirector.quadData[0].setTexture("charSheetRaceDirector", "paulStandIdle0000"); + this.charRaceDirector.atlas = "charSheetRaceDirector"; + this.charRaceDirector.atlas8wayFrame = "paulStandIdle000"; + this.charRaceDirector.scale({ x: 1, y: 1, z: 1 }); + this.charRaceDirector.flags.draw = true; + this.charRaceDirector.lookDir.yaw = Math.PI * 1; + this.charRaceDirector.setDrawMode(DRAWMODE.BILLBOARD); + this.charRaceDirector.flags.is8way = true; + this.charRaceDirector.flags.usesAtlas = true; + this.charRaceDirector.depthMod = 16; + this.charRaceDirector.data = { + useText: "start conversation", + useSprite: "sprInteract02", + useRadius: 48, + conversation: { + fileName: "diaDemoDreamRaceDirector00", + treePosition: 0, + }, + }; + this.charRaceDirector.interactable = true; + this.charRaceDirector.interact = () => { + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.charRaceDirector); + this.scene.player.conversationManager.setConversation(this.charRaceDirector.data.conversation.fileName, this.charRaceDirector.data.conversation.treePosition); + }; + } + + update(_delta) {} + + destroy() {} +} diff --git a/src/3d/model.js b/src/3d/model.js new file mode 100755 index 0000000..ead67c6 --- /dev/null +++ b/src/3d/model.js @@ -0,0 +1,1012 @@ +import DataQuad from "./dataQuad.js"; +import Transform from "./transform.js"; + +export default class Model { + constructor(_scene, _geometryController, _id, _modelDataJson, _pos) { + this.scene = _scene; + this.geometryController = _geometryController; + this.id = _id; + this.modelData = JSON.parse(JSON.stringify(this.scene.cache.json.get(_modelDataJson))); + this.pos = { + x: _pos.x, + y: _pos.y, + z: _pos.z, + }; + this.dir = { + yaw: 0, + pitch: 0, + roll: 0, + }; + this.lookDir = { + yaw: 0, + pitch: 0, + roll: 0, + }; + + this.transform = new Transform(); + this.transform.pos.x = this.pos.x; + this.transform.pos.y = this.pos.y; + this.transform.pos.z = this.pos.z; + + this.trigger = { + isTrigger: false, + triggered: false, + once: false, + keep: 0, //this is 0 if the trigger is not triggered, 1 onOverlap and will be 2 in update (0 if its already 2 to get onExit recognition) + onEnter: () => {}, + onExit: () => {}, + onOverlap: () => {}, + other: null, //reference to object that triggered this is to be set custom in trigger event if wanted to be used + }; + + this.data = {}; + this.interactable = false; + this.interact = () => {}; + this.action = () => {}; + this.customActions = []; + this.customUpdate = () => {}; + this.customDestroy = () => {}; + + this.mover = { + isMoving: false, + target: { + pos: { + x: this.pos.x, + y: this.pos.y, + z: this.pos.z, + spd: 0.01, + }, + dir: { + yaw: this.dir.yaw, + pitch: this.dir.pitch, + roll: this.dir.roll, + spd: 0.01, + }, + onReachedWaypoint: () => {}, + loops: false, + wait: 0, + stopAfterWaypoint: false, + moveWithRotation: false, + }, + jump: false, + targets: [], + }; + this.depthMod = 0; + + this.quadData = []; + for (let [i, q] of this.modelData.quadData.entries()) { + this.addQuadFromData(q); + } + + this.collisionData = []; + for (let [i, q] of this.modelData.collisionData.entries()) { + let pos = { + x: q.position.x + this.pos.x, + y: q.position.y + this.pos.y, + z: q.position.z + this.pos.z, + }; + this.collisionData.push(new DataQuad(this.scene, this.id, i, q.type, pos, q.points, "none", 0)); + } + + this.debug = { + drawCollisions: false, + collisionGraphics: this.scene.add.graphics(), + mode: 0, + }; + this.debug.collisionGraphics.depth = 10000; + + this.flags = { + draw: false, + drawn: false, + update: true, + collision: true, + is8way: false, + usesAtlas: false, + ignoreRaycast: false, + }; + + this.atlas = null; + this.atlas8wayFrame = ""; + } + + update() { + if (this.mover.isMoving) { + let finishedMoving = true; + let finishedTurning = true; + + let d = eud.distance([this.pos.x, this.pos.y, this.pos.z], [this.mover.target.pos.x, this.mover.target.pos.y, this.mover.target.pos.z]); + //console.log(d) + if (d > this.mover.target.pos.spd * this.scene.dt) { + finishedMoving = false; + //console.log("moving") + } else { + if (this.mover.targets.length > 0) { + //console.log("getting to next target") + //todo: add arg and check to readd reached target back to array (loop target) + this.mover.target = { + pos: { + x: this.mover.targets[0].pos.x, + y: this.mover.targets[0].pos.y, + z: this.mover.targets[0].pos.z, + spd: this.mover.targets[0].pos.spd, + }, + dir: { + yaw: this.mover.targets[0].dir.yaw, + pitch: this.mover.targets[0].dir.pitch, + roll: this.mover.targets[0].dir.roll, + spd: this.mover.targets[0].dir.spd, + }, + jump: this.mover.targets[0].jump, + stopAfterWaypoint: this.mover.targets[0].stopAfterWaypoint, + }; + + if (this.mover.targets[0].stopAfterWaypoint === false) { + //console.log("stio after waypoint = false") + this.mover.isMoving = true; + finishedMoving = false; + finishedTurning = false; + } else { + this.mover.isMoving = false; + } + + //this.mover.isMoving = true; + this.mover.targets.splice(0, 1); + } + + //console.log("finished moving") + } + + if (finishedMoving === false || finishedTurning === false) { + //target relative to pos + let targetVec = [this.mover.target.pos.x - this.pos.x, this.mover.target.pos.y - this.pos.y, this.mover.target.pos.z - this.pos.z]; + targetVec = gl_vec3.normalize(targetVec, targetVec); + //rotate towards target + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, this.transform.toVectorArray(this.transform.forward), targetVec); + + this.lookDir.yaw = Phaser.Math.Angle.Between(this.pos.x, this.pos.z, this.mover.target.pos.x, this.mover.target.pos.z) * -1 + Math.PI * 0.5; + //this.rotateByQuaternion(targetRot);//todo: rotation doesnt work quite right atm, probably due to targetRot calc + //INFO: mover could maybe hold a transform for the rot (even for pos) + this.jumpToPosition({ + x: this.pos.x + targetVec[0] * this.mover.target.pos.spd * this.scene.dt, + y: this.pos.y + targetVec[1] * this.mover.target.pos.spd * this.scene.dt, + z: this.pos.z + targetVec[2] * this.mover.target.pos.spd * this.scene.dt, + }); + } else { + //todo: check to be only false if no waypoints are left + this.mover.isMoving = false; + } + } + + //fill this function when creating the model + this.customUpdate(); + + //try to reset the trigger and check if onExit needs to be fired + if (this.trigger.keep === 1) { + this.trigger.keep = 2; + } else if (this.trigger.keep === 2) { + this.trigger.keep = 0; + this.trigger.triggered = false; + this.trigger.onExit(); + //console.log("exit") + } + + //clear quads and stop drawing if draw has been set to false in the meantime (eg out of view (set int geometry controller)) + if (this.flags.drawn === true && this.flags.draw === false) { + this.flags.drawn = false; + for (let q of this.quadData) { + q.clearQuads(); + } + } + } + + translate(_offset = { x: 0, y: 0, z: 0 }) { + this.pos.x += _offset.x; + this.pos.y += _offset.y; + this.pos.z += _offset.z; + for (let q of this.quadData) { + q.pos.x += _offset.x; + q.pos.y += _offset.y; + q.pos.z += _offset.z; + } + for (let q of this.collisionData) { + q.pos.x += _offset.x; + q.pos.y += _offset.y; + q.pos.z += _offset.z; + } + } + + translateAndRotate(_offset, _dir = { yaw: 0, pitch: 0, roll: 0 }, _p = { x: 0, y: 0, z: 0 }) { + this.dir.yaw += _dir.yaw; + this.dir.pitch += _dir.pitch; + this.dir.roll += _dir.roll; + for (let q of this.quadData) { + for (let [i, p] of q.points.entries()) { + let outXZ = rti.rotateY([0, 0, 0], [p.x, p.y, p.z], [q.pos.x - this.pos.x, q.pos.y - this.pos.y, q.pos.z - this.pos.z], _dir.yaw); + let nx = outXZ[0]; + let ny = outXZ[1]; + let nz = outXZ[2]; + let outYZ = rti.rotateX([0, 0, 0], [nx, ny, nz], [q.pos.x - this.pos.x, q.pos.y - this.pos.y, q.pos.z - this.pos.z], _dir.pitch); + nx = outYZ[0]; + ny = outYZ[1]; + nz = outYZ[2]; + let outXY = rti.rotateZ([0, 0, 0], [nx, ny, nz], [q.pos.x - this.pos.x, q.pos.y - this.pos.y, q.pos.z - this.pos.z], _dir.roll); + p.x = outXY[0]; + p.y = outXY[1]; + p.z = outXY[2]; + } + } + for (let q of this.collisionData) { + for (let [i, p] of q.points.entries()) { + let outXZ = rti.rotateY([0, 0, 0], [p.x, p.y, p.z], [q.pos.x - this.pos.x, q.pos.y - this.pos.y, q.pos.z - this.pos.z], _dir.yaw); + let nx = outXZ[0]; + let ny = outXZ[1]; + let nz = outXZ[2]; + let outYZ = rti.rotateX([0, 0, 0], [nx, ny, nz], [q.pos.x - this.pos.x, q.pos.y - this.pos.y, q.pos.z - this.pos.z], _dir.pitch); + nx = outYZ[0]; + ny = outYZ[1]; + nz = outYZ[2]; + let outXY = rti.rotateZ([0, 0, 0], [nx, ny, nz], [q.pos.x - this.pos.x, q.pos.y - this.pos.y, q.pos.z - this.pos.z], _dir.roll); + p.x = outXY[0]; + p.y = outXY[1]; + p.z = outXY[2]; + } + } + //translate + this.pos.x += _offset.x; + this.pos.y += _offset.y; + this.pos.z += _offset.z; + for (let q of this.quadData) { + q.pos.x += _offset.x; + q.pos.y += _offset.y; + q.pos.z += _offset.z; + } + for (let q of this.collisionData) { + q.pos.x += _offset.x; + q.pos.y += _offset.y; + q.pos.z += _offset.z; + } + } + + translateAndRotateAroundAxis(_offset, _axisArr = [[0, 1, 0]], _dirs = [0]) { + console.warn("translateAndRotateAroundAxis not yet implemented"); + } + + rotateToMatchTargetVector(_startVector, _targetVector) { + /*//google ai lying to me + let diffVec = new Float32Array(3) + gl_rvaa.AIOvec3subtract(diffVec, _targetVector, _startVector) + let diffVecNorm = [0, 0, 0] + gl_rvaa.AIOvec3normalize(diffVecNorm, diffVec) + */ + //todo: do with gl_quat.slerp!!!! + let crosVec = new Float32Array(3); + gl_rvaa.AIOvec3cross(crosVec, _startVector, _targetVector); + let angle = gl_rvaa.AIOvec3dot(_startVector, _targetVector); + + this.rotateAroundAxis(crosVec, angle); + } + + applyQuat(_quat) { + //INFO doees not work yet + this.transform.rotationQuat = [_quat[0], _quat[1], _quat[2], _quat[3]]; + //this.applyTransformToVisuals(this.transform.rotationQuat); + //this.rotateAroundAxis([this.transform.up.x, this.transform.up.y, this.transform.up.z], 0) + + //create a matrix from transform rotationQuat + let rotMatrix = gl_rvaa.AIOmat3create(); + gl_rvaa.AIOmat3fromQuat(rotMatrix, this.transform.rotationQuat); + } + + rotateByQuaternion(_quat) { + //rotate vertices by quaternion + for (let [j, q] of this.quadData.entries()) { + for (let [i, p] of q.points.entries()) { + let opts = [p.x, p.y, p.z]; + let npts = this.getRotatedVectorByQuaternion(opts, _quat); + p.x = npts[0]; + p.y = npts[1]; + p.z = npts[2]; + } + } + for (let [j, q] of this.collisionData.entries()) { + for (let [i, p] of q.points.entries()) { + let opts = [p.x, p.y, p.z]; + let npts = this.getRotatedVectorByQuaternion(opts, _quat); + p.x = npts[0]; + p.y = npts[1]; + p.z = npts[2]; + } + } + + //rotate local axis around quaternion + let opts = [this.transform.forward.x, this.transform.forward.y, this.transform.forward.z]; + let npts = this.getRotatedVectorByQuaternion(opts, _quat); + this.transform.forward.x = npts[0]; + this.transform.forward.y = npts[1]; + this.transform.forward.z = npts[2]; + this.transform.forward = gl_rvaa.AIOvec3normalize(this.transform.forward, this.transform.forward); + + opts = [this.transform.right.x, this.transform.right.y, this.transform.right.z]; + npts = this.getRotatedVectorByQuaternion(opts, _quat); + this.transform.right.x = npts[0]; + this.transform.right.y = npts[1]; + this.transform.right.z = npts[2]; + this.transform.right = gl_rvaa.AIOvec3normalize(this.transform.right, this.transform.right); + + opts = [this.transform.up.x, this.transform.up.y, this.transform.up.z]; + npts = this.getRotatedVectorByQuaternion(opts, _quat); + this.transform.up.x = npts[0]; + this.transform.up.y = npts[1]; + this.transform.up.z = npts[2]; + this.transform.up = gl_rvaa.AIOvec3normalize(this.transform.up, this.transform.up); + } + + getRotatedVectorByQuaternion(_vector, _quat) { + let u = [_quat[0], _quat[1], _quat[2]]; + let s = _quat[3]; + + //let cros = gl_rvaa.AIOvec3cross([0, 0, 0], u, _vector) + //return 2 * gl_rvaa.AIOvec3dot(u, _vector) * u + (s*s - gl_rvaa.AIOvec3dot(u, u)) * _vector + 2 * s * gl_rvaa.AIOvec3cross(u, u, _vector); + let dot0 = gl_rvaa.AIOvec3dot(u, _vector); + let vec0 = [2 * dot0 * u[0], 2 * dot0 * u[1], 2 * dot0 * u[2]]; + let dot1 = gl_rvaa.AIOvec3dot(u, u); + let vec1 = [(s * s - dot1) * _vector[0], (s * s - dot1) * _vector[1], (s * s - dot1) * _vector[2]]; + let cro0 = gl_rvaa.AIOvec3cross(u, u, _vector); + let vec2 = [2 * s * cro0[0], 2 * s * cro0[1], 2 * s * cro0[2]]; + let vet = [vec0[0] + vec1[0] + vec2[0], vec0[1] + vec1[1] + vec2[1], vec0[2] + vec1[2] + vec2[2]]; + return vet; + } + + rotateAroundAxis(_axis, _angle) { + // credi @Lewa helpdesk + + //INFO maybe set the rotation of the rotationQuat to the new forward, up and right vectors with (gl_quat.setAxis(out, view, right, up)) + + //turn the transform rotationQuat around axis and angle + //let totrans = gl_rvaa.AIOquatcreate(); + let totrans = gl_rvaa.AIOquatCreateFromAngleAxis(_axis[0], _axis[1], _axis[2], _angle); + let tempQuat = [0, 0, 0, 1]; + gl_rvaa.AIOquatmultiply(tempQuat, this.transform.rotationQuat, totrans); + + //create a matrix from transform rotationQuat + let rotMatrix = gl_rvaa.AIOmat3create(); + gl_rvaa.AIOmat3fromQuat(rotMatrix, tempQuat); + + //turn all point vectors around that matrix + for (let q of this.quadData) { + for (let [i, p] of q.points.entries()) { + let npts = [p.x, p.y, p.z]; + gl_rvaa.AIOvec3multiplyWithMatrix(npts, [p.x, p.y, p.z], rotMatrix); + p.x = npts[0]; + p.y = npts[1]; + p.z = npts[2]; + } + } + for (let q of this.collisionData) { + for (let [i, p] of q.points.entries()) { + let npts = [p.x, p.y, p.z]; + gl_rvaa.AIOvec3multiplyWithMatrix(npts, [p.x, p.y, p.z], rotMatrix); + p.x = npts[0]; + p.y = npts[1]; + p.z = npts[2]; + } + } + + let npts = [this.transform.forward.x, this.transform.forward.y, this.transform.forward.z]; + gl_rvaa.AIOvec3multiplyWithMatrix(npts, [this.transform.forward.x, this.transform.forward.y, this.transform.forward.z], rotMatrix); + this.transform.forward.x = npts[0]; + this.transform.forward.y = npts[1]; + this.transform.forward.z = npts[2]; + this.transform.forward = gl_rvaa.AIOvec3normalize(this.transform.forward, this.transform.forward); + + npts = [this.transform.right.x, this.transform.right.y, this.transform.right.z]; + gl_rvaa.AIOvec3multiplyWithMatrix(npts, [this.transform.right.x, this.transform.right.y, this.transform.right.z], rotMatrix); + this.transform.right.x = npts[0]; + this.transform.right.y = npts[1]; + this.transform.right.z = npts[2]; + this.transform.right = gl_rvaa.AIOvec3normalize(this.transform.right, this.transform.right); + + npts = [this.transform.up.x, this.transform.up.y, this.transform.up.z]; + gl_rvaa.AIOvec3multiplyWithMatrix(npts, [this.transform.up.x, this.transform.up.y, this.transform.up.z], rotMatrix); + this.transform.up.x = npts[0]; + this.transform.up.y = npts[1]; + this.transform.up.z = npts[2]; + this.transform.up = gl_rvaa.AIOvec3normalize(this.transform.up, this.transform.up); + + //todo this might be weird + //this.transform.resetRotationQuat(); + + //normalize to prevent weird rotations + this.transform.normalizeRotationQuat(); + } + + applyTransformToVisuals(_quat) { + //todo: wie obige function apply transmatrix to model + } + + rotateAroundAxisOld(_axisArr = [[0, 1, 0]], _dirs = [0]) { + //_axisArr is an array of all the axis you want to rotate (eg [forward, right, worldup] (or just [[0, 1, 0]] as worldup)) + //to save iteration through the for loop as you have to iteerate through all points and you need to define the order of axis operations + for (let q of this.quadData) { + for (let [i, p] of q.points.entries()) { + let np = { x: p.x, y: p.y, z: p.z }; + for (let [j, a] of _axisArr.entries()) { + //returns something but it does not really align with my axis and is addative + //let q = gl_quat.setAxisAngle(gl_quat.create(), [a[0], a[1], a[2]], _dirs[j]); + //let out = gl_vec3.transformQuat([0, 0, 0], [p.x, p.y, p.z], q); + + let out = gl_rvaa.AIOrotateVectorAboutAxis([np.x, np.y, np.z], a, _dirs[j]); + //returns 0 for some reaseon + np.x = out[0]; + np.y = out[1]; + np.z = out[2]; + } + p.x = np.x; + p.y = np.y; + p.z = np.z; + } + } + /* + for (let q of this.collisionData) { + for (let [i, p] of q.points.entries()) { + for(let [j, a] of _axisArr.entries()){ + let out = gl_rvaa.rotateVectorAboutAxis([p.x, p.y, p.z], [a.x, a.y, a.z], _dirs[j]); + p.x = out[0]; + p.y = out[1]; + p.z = out[2]; + } + } + }*/ + //this makes sense only if you always send three axis (up, right, forward) + //this.dir.yaw = _dirs[0]; + //this.dir.pitch = _dirs[1] !== undefined ? _dirs[1] : this.dir.pitch; + //this.dir.roll = _dirs[2] !== undefined ? _dirs[2] : this.dir.roll; + } + + jumpToRotation(_dir = { yaw: 0, pitch: 0, roll: 0 }, _p = { x: 0, y: 0, z: 0 }) { + for (let q of this.quadData) { + for (let [i, p] of q.points.entries()) { + let outXZ = rti.rotateY([0, 0, 0], [p.x, p.y, p.z], [q.pos.x - this.pos.x, q.pos.y - this.pos.y, q.pos.z - this.pos.z], _dir.yaw - this.dir.yaw); + let nx = outXZ[0]; + let ny = outXZ[1]; + let nz = outXZ[2]; + let outYZ = rti.rotateX([0, 0, 0], [nx, ny, nz], [q.pos.x - this.pos.x, q.pos.y - this.pos.y, q.pos.z - this.pos.z], _dir.pitch - this.dir.pitch); + nx = outYZ[0]; + ny = outYZ[1]; + nz = outYZ[2]; + let outXY = rti.rotateZ([0, 0, 0], [nx, ny, nz], [q.pos.x - this.pos.x, q.pos.y - this.pos.y, q.pos.z - this.pos.z], _dir.roll - this.dir.roll); + p.x = outXY[0]; + p.y = outXY[1]; + p.z = outXY[2]; + } + } + for (let q of this.collisionData) { + for (let [i, p] of q.points.entries()) { + let outXZ = rti.rotateY([0, 0, 0], [p.x, p.y, p.z], [q.pos.x - this.pos.x, q.pos.y - this.pos.y, q.pos.z - this.pos.z], _dir.yaw - this.dir.yaw); + let nx = outXZ[0]; + let ny = outXZ[1]; + let nz = outXZ[2]; + let outYZ = rti.rotateX([0, 0, 0], [nx, ny, nz], [q.pos.x - this.pos.x, q.pos.y - this.pos.y, q.pos.z - this.pos.z], _dir.pitch - this.dir.pitch); + nx = outYZ[0]; + ny = outYZ[1]; + nz = outYZ[2]; + let outXY = rti.rotateZ([0, 0, 0], [nx, ny, nz], [q.pos.x - this.pos.x, q.pos.y - this.pos.y, q.pos.z - this.pos.z], _dir.roll - this.dir.roll); + p.x = outXY[0]; + p.y = outXY[1]; + p.z = outXY[2]; + } + } + this.dir.yaw = _dir.yaw; + this.dir.pitch = _dir.pitch; + this.dir.roll = _dir.roll; + } + + scale(_scale) { + for (let q of this.quadData) { + for (let [i, p] of q.points.entries()) { + p.x *= _scale.x; + p.y *= _scale.y; + p.z *= _scale.z; + } + } + for (let q of this.collisionData) { + for (let [i, p] of q.points.entries()) { + p.x *= _scale.x; + p.y *= _scale.y; + p.z *= _scale.z; + } + } + } + + jumpToPosition(_pos) { + this.pos.x = _pos.x; + this.pos.y = _pos.y; + this.pos.z = _pos.z; + for (let q of this.quadData) { + q.pos.x = _pos.x; + q.pos.y = _pos.y; + q.pos.z = _pos.z; + } + for (let q of this.collisionData) { + q.pos.x = _pos.x; + q.pos.y = _pos.y; + q.pos.z = _pos.z; + } + } + + setDrawMode(_mode) { + /* + D3D: 0, + D2D: 1, + NOSCALE2D: 2, + BILLBOARD: 3 + */ + this.debug.mode = _mode; + /*if(this.debug.mode === DRAWMODE.D2D){ + for(let q of this.quadData){ + q.clearQuads(); + q.createQuad(); + } + }*/ + } + + drawFromMatrix(_from, _matrix) { + this.flags.drawn = true; + this.flags.draw = true; + for (let q of this.quadData) { + if (this.debug.mode === DRAWMODE.D3D) { + q.calculate3dFromMatrix(_from, _matrix); + q.depth += this.depthMod; + q.draw(); + } else if (this.debug.mode === DRAWMODE.D2D) { + //todo + } else if (this.debug.mode === DRAWMODE.BILLBOARD) { + //todo 8 way sprites for characters and lensflares etc her + } else { + } + } + if (this.debug.drawCollisions === true) { + this.debug.collisionGraphics.clear(); + this.debug.collisionGraphics.lineStyle(1, 0x00e436); + for (let q of this.collisionData) { + q.calculate3dFromMatrix(_from, _matrix); + this.debug.collisionGraphics.beginPath(); + + this.debug.collisionGraphics.moveTo(q.screenCoords[0].x, q.screenCoords[0].y); + this.debug.collisionGraphics.lineTo(q.screenCoords[1].x, q.screenCoords[1].y); + this.debug.collisionGraphics.moveTo(q.screenCoords[1].x, q.screenCoords[1].y); + this.debug.collisionGraphics.lineTo(q.screenCoords[2].x, q.screenCoords[2].y); + this.debug.collisionGraphics.moveTo(q.screenCoords[2].x, q.screenCoords[2].y); + this.debug.collisionGraphics.lineTo(q.screenCoords[0].x, q.screenCoords[0].y); + this.debug.collisionGraphics.moveTo(q.screenCoords[0].x, q.screenCoords[0].y); + this.debug.collisionGraphics.lineTo(q.screenCoords[3].x, q.screenCoords[3].y); + this.debug.collisionGraphics.moveTo(q.screenCoords[3].x, q.screenCoords[3].y); + this.debug.collisionGraphics.lineTo(q.screenCoords[2].x, q.screenCoords[2].y); + + //this.debug.collisionGraphics.closePath(); + this.debug.collisionGraphics.strokePath(); + } + } + } + + drawFromQuat(_from, _quat) { + this.flags.drawn = true; + this.flags.draw = true; + + //rotate model if billboarding is enabled, before calculating the 3d part and drawing + if (this.debug.mode === DRAWMODE.BILLBOARD) { + //todo: this might only work for the fps controller not when rolled with 6dof + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, this.transform.toVectorArray(this.transform.right), this.scene.cam.transform.toVectorArray(this.scene.cam.transform.right)); + this.rotateByQuaternion(targetRot); + } else if (this.debug.mode === DRAWMODE.BILLBOARD3D) { + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, this.transform.toVectorArray(this.transform.right), this.scene.cam.transform.toVectorArray(this.scene.cam.transform.right)); + this.rotateByQuaternion(targetRot); + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, this.transform.toVectorArray(this.transform.up), this.scene.cam.transform.toVectorArray(this.scene.cam.transform.up)); + this.rotateByQuaternion(targetRot); + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, this.transform.toVectorArray(this.transform.forward), this.scene.cam.transform.toVectorArray(this.scene.cam.transform.forward)); + this.rotateByQuaternion(targetRot); + } + + for (let q of this.quadData) { + if (this.debug.mode === DRAWMODE.D3D) { + q.calculate3dFromQuat(_from, _quat); + q.depth += this.depthMod; + q.draw(); + } else if (this.debug.mode === DRAWMODE.D2D) { + q.calculate3dFromQuat(_from, _quat, false); + q.drawNo3dFromQuat(_from, _quat, true); + } else if (this.debug.mode === DRAWMODE.BILLBOARD) { + //set image data according to own and camera direction + if (this.flags.is8way === true) { + //todo: this might only work for the fps controller not when rolled with 6dof + let nDir = normAngle(this.lookDir.yaw - this.scene.player.dir.yaw * -1 + Math.PI * 0.125); + let f = Math.floor((nDir / Math.PI) * 4) + 4; + if (this.flags.usesAtlas === true) { + if (q.frame[q.frame - 1] !== this.atlas8wayFrame) { + q.setTexture(this.atlas, this.atlas8wayFrame + String(f), false); + } + } else { + if (q.frame !== f) { + q.frame = f; + q.setTexture(q.texture, q.frame, false); + } + } + } else { + } + //INFO rotate all quads facing the camera (this is dowe first on the whole model not individual quats) + // + q.calculate3dFromQuat(_from, _quat, true); + q.depth += this.depthMod; + q.draw(); + } else if (this.debug.mode === DRAWMODE.BILLBOARD3D) { + q.calculate3dFromQuat(_from, _quat, true); + q.depth += this.depthMod; + q.draw(); + } else { + q.calculate3dFromQuat(_from, _quat); + q.depth += this.depthMod; + q.drawNo3dFromQuat(_from, _quat, false); + } + } + if (this.debug.drawCollisions === true) { + this.debug.collisionGraphics.clear(); + this.debug.collisionGraphics.lineStyle(1, 0x00e436); + for (let q of this.collisionData) { + q.calculate3dFromQuat(_from, _quat); + this.debug.collisionGraphics.beginPath(); + + this.debug.collisionGraphics.moveTo(q.screenCoords[0].x, q.screenCoords[0].y); + this.debug.collisionGraphics.lineTo(q.screenCoords[1].x, q.screenCoords[1].y); + this.debug.collisionGraphics.moveTo(q.screenCoords[1].x, q.screenCoords[1].y); + this.debug.collisionGraphics.lineTo(q.screenCoords[2].x, q.screenCoords[2].y); + this.debug.collisionGraphics.moveTo(q.screenCoords[2].x, q.screenCoords[2].y); + this.debug.collisionGraphics.lineTo(q.screenCoords[0].x, q.screenCoords[0].y); + this.debug.collisionGraphics.moveTo(q.screenCoords[0].x, q.screenCoords[0].y); + this.debug.collisionGraphics.lineTo(q.screenCoords[3].x, q.screenCoords[3].y); + this.debug.collisionGraphics.moveTo(q.screenCoords[3].x, q.screenCoords[3].y); + this.debug.collisionGraphics.lineTo(q.screenCoords[2].x, q.screenCoords[2].y); + + //this.debug.collisionGraphics.closePath(); + this.debug.collisionGraphics.strokePath(); + } + } + } + + draw(_from, _dir) { + this.flags.drawn = true; + this.flags.draw = true; + for (let q of this.quadData) { + if (this.debug.mode === DRAWMODE.D3D) { + q.calculate3d(_from, _dir); + q.depth += this.depthMod; + q.draw(); + } else if (this.debug.mode === DRAWMODE.D2D) { + q.calculate3d(_from, _dir, false); + q.drawNo3d(_from, _dir, true); + } else if (this.debug.mode === DRAWMODE.BILLBOARD) { + //set image data according to own and camera direction + if (this.flags.is8way === true) { + let nDir = normAngle(this.lookDir.yaw - _dir.yaw + Math.PI * 0.125); + let f = Math.floor((nDir / Math.PI) * 4) + 4; + if (q.frame !== f) { + q.frame = f; + q.setTexture(q.texture, q.frame, false); + } + } + //rotate all quads facing the camera + this.translateAndRotate( + { + x: 0, + y: 0, + z: 0, + }, + { + yaw: _dir.yaw * -1 - this.dir.yaw, + pitch: 0, + roll: 0, + }, + ); + q.calculate3d(_from, _dir, true); + q.depth += this.depthMod; + q.draw(); + } else { + q.calculate3d(_from, _dir); + q.depth += this.depthMod; + q.drawNo3d(_from, _dir, false); + } + } + if (this.debug.drawCollisions === true) { + this.debug.collisionGraphics.clear(); + this.debug.collisionGraphics.lineStyle(1, 0x00e436); + for (let q of this.collisionData) { + q.calculate3d(_from, _dir); + this.debug.collisionGraphics.beginPath(); + + this.debug.collisionGraphics.moveTo(q.screenCoords[0].x, q.screenCoords[0].y); + this.debug.collisionGraphics.lineTo(q.screenCoords[1].x, q.screenCoords[1].y); + this.debug.collisionGraphics.moveTo(q.screenCoords[1].x, q.screenCoords[1].y); + this.debug.collisionGraphics.lineTo(q.screenCoords[2].x, q.screenCoords[2].y); + this.debug.collisionGraphics.moveTo(q.screenCoords[2].x, q.screenCoords[2].y); + this.debug.collisionGraphics.lineTo(q.screenCoords[0].x, q.screenCoords[0].y); + this.debug.collisionGraphics.moveTo(q.screenCoords[0].x, q.screenCoords[0].y); + this.debug.collisionGraphics.lineTo(q.screenCoords[3].x, q.screenCoords[3].y); + this.debug.collisionGraphics.moveTo(q.screenCoords[3].x, q.screenCoords[3].y); + this.debug.collisionGraphics.lineTo(q.screenCoords[2].x, q.screenCoords[2].y); + + //this.debug.collisionGraphics.closePath(); + this.debug.collisionGraphics.strokePath(); + } + } + } + + addQuadFromData(_q) { + let pos = { + x: _q.position.x + this.pos.x, + y: _q.position.y + this.pos.y, + z: _q.position.z + this.pos.z, + }; + if (_q.type !== "collisionQuad") { + let no = this.quadData.length; + this.quadData.push(new DataQuad(this.scene, this.id, no, _q.type, pos, _q.points, _q.texture, _q.frame)); + } else { + let no = this.collisionData.length; + this.collisionData.push(new DataQuad(this.scene, this.id, no, _q.type, pos, _q.points, "none", 0)); + } + } + + deleteQuad(_q, _isCollisionQuad) { + if (_isCollisionQuad === true) { + for (let i = this.collisionData.length - 1; i >= 0; i--) { + if (this.collisionData[i].runNo === _q.runNo) { + this.collisionData[i].destroy(); + this.collisionData.splice(i, 1); + } + } + //this.collisionData[_q.runNo].destroy(); + //this.collisionData.splice(_q.runNo, 1); + } else { + for (let i = this.quadData.length - 1; i >= 0; i--) { + if (this.quadData[i].runNo === _q.runNo) { + this.quadData[i].destroy(); + this.quadData.splice(i, 1); + } + } + //this.quadData[_q.runNo].destroy(); + //this.quadData.splice(_q.runNo, 1); + } + } + + alignToGrid(_grid = 1) { + for (let q of this.quadData) { + for (let p of q.points) { + p.x = Math.round(p.x / _grid) * _grid; + p.y = Math.round(p.y / _grid) * _grid; + p.z = Math.round(p.z / _grid) * _grid; + } + } + + for (let q of this.collisionData) { + for (let p of q.points) { + p.x = Math.round(p.x / _grid) * _grid; + p.y = Math.round(p.y / _grid) * _grid; + p.z = Math.round(p.z / _grid) * _grid; + } + } + } + + toggleDrawCollisions() { + this.debug.drawCollisions = !this.debug.drawCollisions; + if (this.debug.drawCollisions === false) { + this.debug.collisionGraphics.clear(); + } + } + + getScreenBounds() { + let x1 = this.scene.right; + let y1 = this.scene.bottom; + let x2 = this.scene.left; + let y2 = this.scene.top; + for (let q of this.quadData) { + for (let sc of q.screenCoords) { + x1 = Math.min(x1, sc.x); + y1 = Math.min(y1, sc.y); + x2 = Math.max(x2, sc.x); + y2 = Math.max(y2, sc.y); + } + } + return { + p0: { + x: x1, + y: y1, + }, + p1: { + x: x2, + y: y2, + }, + }; + } + + getWorldPositionOfQuad(_quad) { + let ret = []; + for (let p of _quad.points) { + ret.push({ + x: p.x - this.pos.x, + y: p.y - this.pos.y, + z: p.z - this.pos.z, + }); + } + ret.push({ x: 0, y: 0, z: 0 }); //to be filled by position + return ret; + } + + swapModelData(_modelDataJson) { + //todo: get old transform data to rotate it in xyz to correct rotaton + this.destroy(); + this.modelData = JSON.parse(JSON.stringify(this.scene.cache.json.get(_modelDataJson))); + //add new + this.quadData = []; + for (let [i, q] of this.modelData.quadData.entries()) { + this.addQuadFromData(q); + } + + this.collisionData = []; + for (let [i, q] of this.modelData.collisionData.entries()) { + let pos = { + x: q.position.x + this.pos.x, + y: q.position.y + this.pos.y, + z: q.position.z + this.pos.z, + }; + this.collisionData.push(new DataQuad(this.scene, this.id, i, q.type, pos, q.points, "none", 0)); + } + } + + swapModelDataOld(_modelDataJson) { + //todo: this wont work well with the new quaternion rotations + this.destroy(); + this.modelData = JSON.parse(JSON.stringify(this.scene.cache.json.get(_modelDataJson))); + //add new + this.quadData = []; + for (let [i, q] of this.modelData.quadData.entries()) { + this.addQuadFromData(q); + } + + this.collisionData = []; + for (let [i, q] of this.modelData.collisionData.entries()) { + let pos = { + x: q.position.x + this.pos.x, + y: q.position.y + this.pos.y, + z: q.position.z + this.pos.z, + }; + this.collisionData.push(new DataQuad(this.scene, this.id, i, q.type, pos, q.points, "none", 0)); + } + + //move and rotate to old position + //this.translateAndRotate({ x: 0, y: 0, z: 0 }, { yaw: this.dir.yaw, roll: 0, pitch: 0 }); + let _dir = this.dir; + for (let q of this.quadData) { + for (let [i, p] of q.points.entries()) { + let outXZ = rti.rotateY([0, 0, 0], [p.x, p.y, p.z], [q.pos.x - this.pos.x, q.pos.y - this.pos.y, q.pos.z - this.pos.z], _dir.yaw); + let nx = outXZ[0]; + let ny = outXZ[1]; + let nz = outXZ[2]; + let outYZ = rti.rotateX([0, 0, 0], [nx, ny, nz], [q.pos.x - this.pos.x, q.pos.y - this.pos.y, q.pos.z - this.pos.z], _dir.pitch); + nx = outYZ[0]; + ny = outYZ[1]; + nz = outYZ[2]; + let outXY = rti.rotateZ([0, 0, 0], [nx, ny, nz], [q.pos.x - this.pos.x, q.pos.y - this.pos.y, q.pos.z - this.pos.z], _dir.roll); + p.x = outXY[0]; + p.y = outXY[1]; + p.z = outXY[2]; + } + } + for (let q of this.collisionData) { + for (let [i, p] of q.points.entries()) { + let outXZ = rti.rotateY([0, 0, 0], [p.x, p.y, p.z], [q.pos.x - this.pos.x, q.pos.y - this.pos.y, q.pos.z - this.pos.z], _dir.yaw); + let nx = outXZ[0]; + let ny = outXZ[1]; + let nz = outXZ[2]; + let outYZ = rti.rotateX([0, 0, 0], [nx, ny, nz], [q.pos.x - this.pos.x, q.pos.y - this.pos.y, q.pos.z - this.pos.z], _dir.pitch); + nx = outYZ[0]; + ny = outYZ[1]; + nz = outYZ[2]; + let outXY = rti.rotateZ([0, 0, 0], [nx, ny, nz], [q.pos.x - this.pos.x, q.pos.y - this.pos.y, q.pos.z - this.pos.z], _dir.roll); + p.x = outXY[0]; + p.y = outXY[1]; + p.z = outXY[2]; + } + } + } + + log() { + let logobj = { + name: this.modelData.name, + quadData: [], + collisionData: [], + }; + //add quad Data from model + for (let q of this.quadData) { + let pts = []; + for (let p of q.points) { + pts.push({ + x: p.x, // + this.pos.x, + y: p.y, // + this.pos.y, + z: p.z, // + this.pos.z + }); + } + logobj.quadData.push({ + type: q.type, + texture: q.texture, + frame: q.frame, + position: { + x: q.pos.x - this.pos.x, + y: q.pos.y - this.pos.y, + z: q.pos.z - this.pos.z, + }, + points: pts, + }); + } + //add collision Data from model + for (let q of this.collisionData) { + let pts = []; + for (let p of q.points) { + pts.push({ + x: p.x, // + this.pos.x, + y: p.y, // + this.pos.y, + z: p.z, // + this.pos.z + }); + } + logobj.collisionData.push({ + type: "collisionQuad", + position: { + x: q.pos.x - this.pos.x, + y: q.pos.y - this.pos.y, + z: q.pos.z - this.pos.z, + }, + points: pts, + }); + } + //log model for saving + console.log(JSON.stringify(logobj)); + } + + logTextures() { + let logObj = []; + for (let q of this.quadData) { + logObj.push({ texture: q.texture, frame: q.frame }); + } + //log model atlas and texture + console.log(JSON.stringify(logObj)); + } + + updateTrigger() { + if (this.trigger.triggered === false) { + this.trigger.triggered = true; + this.trigger.onEnter(); + //console.log("enter") + } else { + this.trigger.onOverlap(); + this.trigger.keep = 1; + //console.log("overlap") + } + } + + destroy() { + this.customDestroy(); + + for (let i = this.quadData.length - 1; i >= 0; i--) { + this.quadData[i].destroy(); + this.quadData.splice(i, 1); + } + for (let i = this.collisionData.length - 1; i >= 0; i--) { + this.collisionData[i].destroy(); + this.collisionData.splice(i, 1); + } + this.debug.collisionGraphics.clear(); + this.debug.collisionGraphics.destroy(); + } +} diff --git a/src/3d/player3d.js b/src/3d/player3d.js new file mode 100755 index 0000000..27b4303 --- /dev/null +++ b/src/3d/player3d.js @@ -0,0 +1,690 @@ +import ConversationManager from "../ui/conversationManager.js"; +import PanelInventory from "../ui/panelInventory.js"; + +export class Player3d { + constructor(_scene) { + this.scene = _scene; + this.pos = { + x: 0, + y: 0, + z: 0, + to: { + jump: false, + x: 0, + y: 0, + z: 0, + }, + last: { + x: 0, + y: 0, + z: 0 + } + } + this.dir = { + yaw: 0, + pitch: 0, + roll: 0, + spd: { + yaw: 0.04, + pitch: 0.04, + roll: 0.04 + } + } + this.vel = { + x: 0, + y: 0, + z: 0 + } + this.eyeHeight = 24;//24 + this.stepHeight = 9; + this.collisionRadius = 12; + this.spd = { + normal: 2, + sprint: 3 + } + + this.gravity = { + x: 0, + y: 0,//0.1 + z: 0, + grounded: false, + terminal: 4 + } + + this.mode = PLAYERMODE.LOOK; + this.moveMode = PLAYERMOVE.STAND; + this.isMoving = false; + this.showUsing = false; + + this.lowerHint = this.scene.add.bitmapText(0, (this.scene.game.config.height * 0.4), "uiFont", "", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.lowerHint.depth = 9999; + this.useBox = this.scene.add.graphics({x: 0, y: 0.5}); + this.useBox.depth = 9999; + this.useBoxAnim = 0; + this.useSprite = this.scene.add.sprite(0, 0, "sprInteract01"); + this.useSprite.depth = 9999; + this.useSprite.alpha = 0; + + /* + this.debugOrientPitch = this.scene.add.bitmapText(0, (this.scene.game.config.height * -0.4), "segoeUI_16", "", 16, 0).setOrigin(0.5).setLetterSpacing(1); + this.debugOrientPitch.depth = 9999; + this.debugOrientYaw = this.scene.add.bitmapText(0, (this.scene.game.config.height * -0.4) + 32, "segoeUI_16", "", 16, 0).setOrigin(0.5).setLetterSpacing(1); + this.debugOrientYaw.depth = 9999; + */ + + this.itemSprite = null; + this.inventory = { + position: 0, + items: [ + {flag: "00hasHand", asset: null, atlas: null}, + // { flag: "00hasRevolver", asset: "itemRevolver", atlas: null }, + // { flag: "00hasCigarettes", asset: "itemCigarettes00", atlas: "atlasItems"}, + // { flag: "00hasKeycard", asset: "itemKeycard", atlas: "atlasItems" } + ] + } + + this.panel = null; + this.conversation = null; + this.conversationManager = new ConversationManager(this.scene); + + this.anim = { + frame: 0, + end: 3, + start: 0, + frames: ["sprFPSwalk_0", "sprFPSwalk_1", "sprFPSwalk_2", "sprFPSwalk_3"] + } + + this.stepSounds = []; + for(let i = 0 ; i < 8 ; i++){ + this.stepSounds.push(SOUNDS.stepsHallway.play("step" + String(i))); + SOUNDS.stepsHallway.stop(this.stepSounds[i]); + } + this.muteTimer = setTimeout(() => {}, 10); + } + + update() { + if (this.pos.to.jump === true) { + this.pos.x = this.pos.to.x; + this.pos.y = this.pos.to.y; + this.pos.z = this.pos.to.z; + this.pos.to.jump = false; + } + + this.dir.yaw = normAngle(this.dir.yaw); + + if(this.scene.editor.enabled === false){ + if (this.showUsing === false) { + + } else { + + } + + if (this.moveMode === PLAYERMOVE.SIT) { + + } + //scroll inventory + + if(this.scene.hand.wheel !== 0){ + this.inventory.position = Math.max(0, Math.min(this.inventory.position + this.scene.hand.wheel, this.inventory.items.length - 1)); + + let entry = this.inventory.items[this.inventory.position]; + console.log(entry.asset, entry.atlas) + this.setItemSprite(entry.asset, entry.atlas); + } + + + + //footsteps + if(this.isMoving === true){ + if (eud.distance([this.pos.x, this.pos.y, this.pos.z], [this.pos.last.x, this.pos.last.y, this.pos.last.z]) > 16) { + this.travelLength += 16; + this.pos.last.x = this.pos.x; + this.pos.last.y = this.pos.y; + this.pos.last.z = this.pos.z; + //if (this.gravity.grounded === true){ + if (Math.abs(this.vel.y) < 1) { + //this.sndStep.volume = (0.5 + (Math.random() * 0.5)) * OPTIONS.sfx; + //this.sndStep.play(); + //console.log("step") + for(let s of this.stepSounds){ + SOUNDS.stepsHallway.stop(s); + } + SOUNDS.stepsHallway.stop(); + let r = this.stepSounds[Math.floor(Math.random() * this.stepSounds.length)]; + SOUNDS.stepsHallway.play(r); + clearTimeout(this.muteTimer); + this.muteTimer = setTimeout(() => { + for (let s of this.stepSounds) { + SOUNDS.stepsHallway.stop(s); + } + SOUNDS.stepsHallway.stop(); + }, 600); + //SOUNDS.stepsHallway.volume((0.5 + (Math.random() * 0.5)) * OPTIONS.sfx, r); + //let sndId = SOUNDS.stepsHallway.play("step" + String(Math.floor(Math.random() * 8))); + //SOUNDS.stepsHallway.volume((0.5 + (Math.random() * 0.5)) * OPTIONS.sfx, sndId); + } + } + }else{ + + } + + if (this.panel !== null) { + this.panel.update(); + } + + if (this.conversation !== null) { + if (this.mode === PLAYERMODE.DIALOGUE) { + this.conversation.update(); + } + } + + this.conversationManager.update(); + } + + //this.debugOrientPitch.setText(this.dir.pitch); + //this.debugOrientYaw.setText(this.dir.yaw); + } + + jumpToPosition(_pos, _immediately = false) { + //use this to set a neew position even if the collision checks have moved the position around differently + //eg if a collision in x resolves in a trigger jumping the player, but collision resolve in z afterwards would reset that + this.pos.to.jump = true; + this.pos.to.x = _pos.x; + this.pos.to.y = _pos.y; + this.pos.to.z = _pos.z; + + if (_immediately === true) { + this.pos.x = this.pos.to.x; + this.pos.y = this.pos.to.y; + this.pos.z = this.pos.to.z; + this.pos.to.jump = false; + } + } + + setMode(_mode) { + this.mode = _mode; + switch (_mode) { + case PLAYERMODE.LOOK: + this.showUI(); + break; + case PLAYERMODE.INTERACT: + this.scene.hand.setMouseLock(false); + this.hideUI(); + break; + case PLAYERMODE.DIALOGUE: + this.scene.hand.setMouseLock(false); + this.hideUI(); + break; + default: + break; + } + } + + setMoveMode(_mode){ + if(_mode !== this.moveMode){ + this.moveMode = _mode; + switch(this.moveMode){ + case PLAYERMOVE.STAND://stand still - not stand up + this.end = 0; + break; + case PLAYERMOVE.SIT: + this.eyeHeight = 20; + this.end = 0; + break; + case PLAYERMOVE.WALK: + case PLAYERMOVE.RUN: + this.eyeHeight = 24;//32 + this.anim.frames = ["sprFPSwalk_0", "sprFPSwalk_1", "sprFPSwalk_2", "sprFPSwalk_3"]; + this.anim.end = 3; + break; + default: + break; + } + } + } + + setHintText(_text) { + this.lowerHint.setText(_text); + } + + setUseSprite(_spr = "sprInteract01"){ + this.useSprite.setTexture(_spr); + } + + setUseBox(_rect) { + this.showUsing = true; + this.useBox.clear(); + let th = 6; + + //draw faint scanlines + this.useBox.lineStyle(3, 0xffffff, 0.25);//0x00e436 + this.useBox.beginPath(); + for (let y = _rect.p0.y; y < _rect.p1.y; y++) { + if ((Math.floor(this.scene.game.config.height + y)) % th === Math.floor(this.useBoxAnim)) { + this.useBox.moveTo(_rect.p0.x, y); + this.useBox.lineTo(_rect.p1.x, y); + } + } + this.useBox.strokePath(); + + //draw box outline + this.useBox.lineStyle(1, 0xffffff, 1);//0x00e436 + this.useBox.beginPath(); + this.useBox.moveTo(_rect.p0.x, _rect.p0.y); + this.useBox.lineTo(_rect.p1.x, _rect.p0.y); + this.useBox.moveTo(_rect.p1.x, _rect.p0.y); + this.useBox.lineTo(_rect.p1.x, _rect.p1.y); + this.useBox.moveTo(_rect.p1.x, _rect.p1.y); + this.useBox.lineTo(_rect.p0.x, _rect.p1.y); + this.useBox.moveTo(_rect.p0.x, _rect.p1.y); + this.useBox.lineTo(_rect.p0.x, _rect.p0.y); + this.useBox.strokePath(); + + //advance useBoxAnim to let the scanlines roll + this.useBoxAnim += 0.5; + if (this.useBoxAnim >= th) { + this.useBoxAnim = 0; + } + + this.useBox.alpha = 1; + this.useSprite.alpha = 1;//maybe not show this + } + + scrollInventory(_amt){ + this.inventory.position = Math.max(0, Math.min(this.inventory.position + _amt, this.inventory.items.length - 1)); + } + + setItemSprite(_asset = null, _atlas = null){ + if(this.itemSprite !== null){ + this.itemSprite.destroy(); + } + + if(_asset !== null){ + if(_atlas === null){ + _atlas = _asset; + _asset = 0; + } + this.itemSprite = this.scene.add.sprite(0, (this.scene.game.config.height * 0.5) - 32, _atlas, _asset); + this.itemSprite.depth = 1000; + } + } + + clearUseBox() { + this.showUsing = false; + this.useBox.clear(); + this.useSprite.alpha = 0; + } + + hideUI(){ + this.clearUseBox(); + this.setHintText(""); + this.lowerHint.alpha = 0; + } + + showUI(){ + if (this.moveMode !== PLAYERMOVE.SIT) { + //this.bodySprite.alpha = 1; + } + this.lowerHint.alpha = 1; + } + + gameControls(){ + let wantToMove = false; + + this.keyboardLook(); + if(this.mode === PLAYERMODE.LOOK){ + if(this.scene.hand.mouselock === false){ + this.scene.hand.setMouseLock(true); + } + this.mouseLook(); + + if(globalOrientation.alpha !== null){ + this.orientationLook(); + } + if (isMobile === true) { + this.touchLook(); + } + } + + this.dir.pitch = Math.max(-HALFPI, Math.min(HALFPI ,this.dir.pitch)); + + let toPos = { + x: this.pos.x, + y: this.pos.y, + z: this.pos.z + } + + if (Math.abs(INPUTS.stickLeft.horizontal) > 0.1) { + toPos.z -= (Math.cos(this.dir.yaw + HALFPI) * INPUTS.stickLeft.horizontal) * this.spd.normal; + toPos.x += (Math.sin(this.dir.yaw + HALFPI) * INPUTS.stickLeft.horizontal) * this.spd.normal; + wantToMove = true; + } + if (Math.abs(INPUTS.stickLeft.vertical) > 0.1) { + toPos.z -= (Math.cos(this.dir.yaw) * INPUTS.stickLeft.vertical) * (INPUTS.btnTriggerLeft.pressed ? this.spd.sprint : this.spd.normal); + toPos.x += (Math.sin(this.dir.yaw) * INPUTS.stickLeft.vertical) * (INPUTS.btnTriggerLeft.pressed ? this.spd.sprint : this.spd.normal); + wantToMove = true; + } + //touch controls move + if (isMobile === true) { + if (this.scene.hand.pressed === true) { + if (this.scene.hand.start.y > this.scene.game.config.height * -0.4 && this.scene.hand.start.y < this.scene.game.config.height * 0.4) { + if (this.scene.hand.start.x > this.scene.game.config.width * -0.33 && this.scene.hand.start.x < this.scene.game.config.width * 0.33) { + let amt = Math.max(-1, Math.min(1, (this.scene.hand.pos.y - this.scene.hand.start.y) * 0.01)); + if (this.hand.pos.y > 0) { + INPUTS.btnTriggerLeft.pressed = true; + } else { + INPUTS.btnTriggerLeft.pressed = false; + } + toPos.z -= (Math.cos(this.dir.yaw) * amt) * (INPUTS.btnTriggerLeft.pressed ? this.spd.sprint : this.spd.normal); + toPos.x += (Math.sin(this.dir.yaw) * amt) * (INPUTS.btnTriggerLeft.pressed ? this.spd.sprint : this.spd.normal); + wantToMove = true; + if (this.scene.hand.pos.y < this.scene.game.config.height * -0.1) {//also jump + if (this.vel.y === 0) { + this.vel.y = -2; + this.pos.y += this.vel.y; + } + } + } + } + } + } + + if (INPUTS.btnShoulderRight.pressed) { + this.pos.y -= 1; + } + if (INPUTS.btnShoulderLeft.pressed) { + this.pos.y += 1; + } + + //try to interact on mobile + let touchInteract = false; + if (isMobile === true) { + if (this.scene.hand.justReleased === true) { + if (this.scene.hand.start.y < this.scene.game.config.height * -0.4 || this.scene.hand.start.y > this.scene.game.config.height * 0.4) { + touchInteract = true; + } + } + } + + if (INPUTS.btnA.justReleased || this.scene.input.mouse.locked === true ? this.scene.hand.justReleased : false || touchInteract === true) { + //alert("wanted to interact") + } + + let returnColl = []; + returnColl = this.scene.geometryController.update( + [ + {//check ground at player position + pos: { + x: this.pos.x, + y: this.pos.y + this.eyeHeight, + z: this.pos.z + }, + dir: { + x: 0, + y: 1, + z: 0 + }, + hit: [] + }, {//check wall colllision global x axis + pos: { + x: toPos.x, + y: toPos.y - this.stepHeight, + z: toPos.z + }, + dir: { + x: 1, + y: 0, + z: 0 + }, + hit: [] + }, {//check wall colllision global z axis + pos: { + x: toPos.x, + y: toPos.y - this.stepHeight, + z: toPos.z + }, + dir: { + x: 0, + y: 0, + z: 1 + }, + hit: [] + } + ] + ); + /*if(this.scene.input.activePointer.isDown){ + console.log(returnColl); + }*/ + + //resolve collision with ground + if (returnColl[0].hit.length > 0) { + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[0].hit[0]; + for (let [i, n] of returnColl[0].hit.entries()) { + let d = Phaser.Math.Distance.Between(0, this.pos.y - this.stepHeight, 0, returnColl[0].hit[i].pt[1]); + if (d < dist) { + dist = d; + nearestHit = returnColl[0].hit[i]; + } + } + //returnColl[input point and direction].hit[nearest = 0].pt[coord x,y,z] + //teleport to ground + if(nearestHit.model.trigger.isTrigger === false){ + if(dist <= this.stepHeight){ + this.vel.y = 0; + this.pos.y = nearestHit.pt[1]; + }else{ + if (this.vel.y < this.gravity.terminal) { + this.vel.y += this.gravity.y; + } + this.pos.y += this.vel.y; + } + }else{ + nearestHit.model.updateTrigger(); + } + } + + //resolve hit in global x axis + if(returnColl[1].hit.length > 0){ + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[1].hit[0]; + for(let [i, n] of returnColl[1].hit.entries()){ + let d = Phaser.Math.Distance.Between(this.pos.x, this.pos.z, returnColl[1].hit[i].pt[0], returnColl[1].hit[i].pt[2]); + if(d < dist){ + dist = d; + nearestHit = returnColl[1].hit[i]; + } + } + if(dist < this.collisionRadius){ + //only move if you move away from the wall + if ((toPos.x < this.pos.x && this.pos.x < nearestHit.pt[0]) || (toPos.x > this.pos.x && this.pos.x > nearestHit.pt[0]) || nearestHit.model.trigger.isTrigger === true){ + this.pos.x = toPos.x; + if (nearestHit.model.trigger.isTrigger === true){ + nearestHit.model.updateTrigger(); + } + } + }else{ + //be free to move cause yoou are far away from wall + this.pos.x = toPos.x; + } + }else{ + //move because there is nothing out there + this.pos.x = toPos.x; + } + + if (returnColl[2].hit.length > 0) { + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[2].hit[0]; + for (let [i, n] of returnColl[2].hit.entries()) { + let d = Phaser.Math.Distance.Between(this.pos.x, this.pos.z, returnColl[2].hit[i].pt[0], returnColl[2].hit[i].pt[2]); + if (d < dist) { + dist = d; + nearestHit = returnColl[2].hit[i]; + } + } + if (dist < this.collisionRadius) { + //only move if you move away from the wall + if ((toPos.z < this.pos.z && this.pos.z < nearestHit.pt[2]) || (toPos.z > this.pos.z && this.pos.z > nearestHit.pt[2]) || nearestHit.model.trigger.isTrigger === true) { + this.pos.z = toPos.z; + if (nearestHit.model.trigger.isTrigger === true) { + nearestHit.model.updateTrigger(); + } + } + }else{ + //be free to move cause yoou are far away from wall + this.pos.z = toPos.z; + } + }else{ + //move because there is nothing out there + this.pos.z = toPos.z; + } + + this.isMoving = wantToMove; + if (wantToMove === true){ + this.setMoveMode(PLAYERMOVE.WALK); + if (INPUTS.btnTriggerLeft.pressed === true){ + this.setMoveMode(PLAYERMOVE.RUN); + } + }else{ + if(this.moveMode !== PLAYERMOVE.SIT){ + this.setMoveMode(PLAYERMOVE.STAND); + } + } + + //open menu + if (INPUTS.btnStart.justPressed === true){ + this.setMode(PLAYERMODE.INTERACT); + //this.panel = new PanelControlOptions(this); + this.panel = new PanelWelcome(this); + } + + //look for models to interact with at center of screen if player click the mouse + let hits = []; + //hits = this.geometryController.getQuadsFromScreenspaceAt(this.input.activePointer.worldX, this.input.activePointer.worldY, false); + hits = this.scene.geometryController.getQuadsFromScreenspaceAt(0, 0, false); + if (hits.length > 0) { + hits = hits.sort((a, b) => a.depth - b.depth); + //if(hits[hits.length - 1].depth > -64){//interaction radius (moved that into eud.distance 7 lines lower) + this.scene.modelName = hits[hits.length - 1].modelId; + //this.debugTxt.setText(this.modelName); + + let model = this.scene.geometryController.getModelById(this.scene.modelName = hits[hits.length - 1].modelId); + if (model.interactable === true){ + if (eud.distance([this.pos.x, this.pos.y, this.pos.z], [model.pos.x, model.pos.y, model.pos.z]) < 24){ + this.setHintText(model.data.useText !== undefined ? model.data.useText : "click to use"); + this.setUseSprite(model.data.useSprite !== undefined ? model.data.useSprite : "sprInteract01"); + this.setUseBox(model.getScreenBounds()); + + if (isMobile === true) { + if (this.scene.hand.justReleased === true) { + if (this.scene.hand.lastPressedTime < 30) { + model.interact(); + } + } + } else { + if (this.scene.hand.justReleased || INPUTS.btnA.justReleased) { + model.interact(); + } + } + }else{ + this.setHintText(""); + this.clearUseBox(); + } + + }else{ + this.setHintText(""); + this.clearUseBox(); + } + } + + if (this.scene.hand.justReleased) { + if(this.scene.input.mouse.locked === false){ + this.scene.hand.setMouseLock(true); + } + //this.cam.zoomTween.restart(); + //log the playre position as a helper for manual object positioning in level files + if(this.scene.keys.q.isDown){ + console.log(this); + } + } + } + + keyboardLook(){ + if (this.scene.cursors.up.isDown) { + this.dir.pitch += this.dir.spd.pitch; + } + if (this.scene.cursors.down.isDown) { + this.dir.pitch -= this.dir.spd.pitch; + } + if (this.scene.cursors.right.isDown) { + if(this.scene.keys.q.isDown){ + this.dir.roll -= this.dir.spd.roll; + }else{ + this.dir.yaw -= this.dir.spd.yaw; + } + } + if (this.scene.cursors.left.isDown) { + if (this.scene.keys.q.isDown) { + this.dir.roll += this.dir.spd.roll; + } else { + this.dir.yaw += this.dir.spd.yaw; + } + } + } + + mouseLook(){ + if(this.scene.hand.vel.x !== 0){ + //this.dir.yaw = prevCamDir.yaw; + this.dir.yaw -= ((this.scene.hand.vel.x) * this.dir.spd.yaw); + } + if(this.scene.hand.vel.y !== 0){ + //this.dir.pitch = prevCamDir.pitch; + this.dir.pitch += ((this.scene.hand.vel.y) * this.dir.spd.pitch); + } + } + + orientationLook(){ + let arr = [globalOrientation.alpha, globalOrientation.beta, globalOrientation.gamma]; + for(let [i, a] of arr.entries()){ + if(a === null){ + arr[i] = 0; + } + //if(a >= 180){a -= 360} + //if(a < -180){a += 360} + arr[i] = a * Math.PI / 180; + } + + //this.dir.pitch = (arr[1] * -1) + (Math.PI * 0.5); + //this.dir.yaw = (arr[0]); + + let rotation = getEulerAngles(getRotationMatrix(globalOrientation.alpha, globalOrientation.beta, globalOrientation.gamma)); + let degtorad = Math.PI / 180; + + let toYaw = offsetOrientation.yaw - (rotation[2] * degtorad) + let toPitch = offsetOrientation.pitch - ((rotation[1] * degtorad) * -1); + + this.dir.yaw -= toYaw; + this.dir.pitch -= toPitch; + + offsetOrientation.yaw = (rotation[2] * degtorad); + offsetOrientation.pitch = ((rotation[1] * degtorad) * -1); + } + + touchLook() { + if (this.scene.hand.pressed === true) { + if (this.scene.hand.start.y > this.scene.game.config.height * -0.4 && this.scene.hand.start.y < this.scene.game.config.height * 0.4) { + if (this.scene.hand.pos.y > 0) { + let amt = (this.scene.hand.pos.x - this.scene.hand.start.x) * 0.0005; + this.dir.yaw -= amt; + } + if (this.scene.hand.start.x < this.scene.game.config.width * -0.33 || this.scene.hand.start.x > this.scene.game.config.width * 0.33) { + let amt = (this.scene.hand.pos.y - this.scene.hand.start.y) * 0.0005; + this.dir.pitch += amt; + } + } + } + } +} \ No newline at end of file diff --git a/src/3d/player6dof.js b/src/3d/player6dof.js new file mode 100755 index 0000000..1ac3052 --- /dev/null +++ b/src/3d/player6dof.js @@ -0,0 +1,1349 @@ +import ConversationManager from "../ui/conversationManager.js"; +import PanelInventory from "../ui/panelInventory.js"; +import Transform from "./transform.js"; + +export class Player6dof { + constructor(_scene, _id) { + this.scene = _scene; + this.id = _id; + this.pos = { + x: 0, + y: 0, + z: 0, + to: { + jump: false, + x: 0, + y: 0, + z: 0, + }, + last: { + x: 0, + y: 0, + z: 0 + } + } + this.dir = { + yaw: 0, + pitch: 0, + roll: 0, + spd: { + yaw: 0.04, + pitch: 0.04, + roll: 0.04 + } + } + this.modDir = { + yaw: 0, + pitch: 0, + roll: 0, + } + this.vel = { + x: 0, + y: 0, + z: 0 + } + this.eyeHeight = 24;//24 + this.stepHeight = 9; + this.collisionRadius = 12; + this.spd = { + normal: 1, + sprint: 2, + orig: { + normal: 1, + sprint: 2 + } + } + + this.lookTarget = {x: 0, y: 0, z: 0} + + this.gravity = { + x: 0, + y: 0.05, + z: 0, + grounded: false, + terminal: 4 + } + + this.mode = PLAYERMODE.LOOK; + this.moveMode = PLAYERMOVE.STAND; + this.isMoving = false; + this.showUsing = false; + + this.lowerHint = this.scene.add.bitmapText(0, (this.scene.game.config.height * 0.4), "uiFont", "", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.lowerHint.depth = 9999; + this.useBox = this.scene.add.graphics({ x: 0, y: 0.5 }); + this.useBox.depth = 9999; + this.useBoxAnim = 0; + this.useSprite = this.scene.add.sprite(0, 0, "atlasUi", "sprInteract01"); + this.useSprite.depth = 9999; + this.useSprite.alpha = 0; + + this.itemSprite = null; + this.inventory = { + position: 0, + items: [ + { flag: "00hasHand", asset: null, atlas: null }, + // { flag: "00hasRevolver", asset: "itemRevolver", atlas: null }, + // { flag: "00hasCigarettes", asset: "itemCigarettes00", atlas: "atlasItems"}, + // { flag: "00hasKeycard", asset: "itemKeycard", atlas: "atlasItems" } + ] + } + + + this.bodySprite = this.scene.add.sprite(0, 0, "atlasFps", "fps_tex_128_walk_0"); + this.bodySprite.depth = 998; + this.bodySprite.setScale(4); + this.bodySprite.alpha = 0; + this.handSprite = this.scene.add.sprite(0, 0, "atlasFps", "fps_tex_128_use_point"); + this.handSprite.depth = 999; + this.handSprite.setScale(4); + this.handSprite.alpha = 0; + this.useFpsBody = false; + + this.travelLength = 0; + + this.panel = null; + this.conversation = null; + this.conversationManager = new ConversationManager(this.scene); + + this.anim = { + frame: 0, + end: 3, + start: 0, + frames: ["fps_tex_128_walk_0", "fps_tex_128_walk_1", "fps_tex_128_walk_2", "fps_tex_128_walk_3"] + } + + this.transform = new Transform(); + } + + update() { + if (this.pos.to.jump === true) { + this.pos.x = this.pos.to.x; + this.pos.y = this.pos.to.y; + this.pos.z = this.pos.to.z; + this.pos.to.jump = false; + } + + this.dir.yaw = normAngle(this.dir.yaw); + + if (this.scene.editor.enabled === false) { + if (this.useFpsBody === true) { + this.bodySprite.y = (this.scene.game.config.height * 0.5) + Math.cos(Math.max(0, this.dir.pitch) * 2) * 192; + if (this.showUsing === false) { + this.handSprite.y = (this.scene.game.config.height * 0.5) + Math.sin(this.dir.pitch * 1) * 192; + } else { + this.handSprite.y = 128; + } + + if (this.moveMode === PLAYERMOVE.SIT) { + + } + + //scroll inventory + /*if(this.scene.hand.wheel !== 0){ + this.inventory.position = Math.max(0, Math.min(this.inventory.position + this.scene.hand.wheel, this.inventory.items.length - 1)); + + let entry = this.inventory.items[this.inventory.position]; + console.log(entry.asset, entry.atlas) + this.setItemSprite(entry.asset, entry.atlas); + }*/ + + //footsteps + if (this.isMoving === true) { + if (eud.distance([this.pos.x, this.pos.y, this.pos.z], [this.pos.last.x, this.pos.last.y, this.pos.last.z]) > 16) { + this.travelLength += 16; + this.pos.last.x = this.pos.x; + this.pos.last.y = this.pos.y; + this.pos.last.z = this.pos.z; + //if (this.gravity.grounded === true){ + if (Math.abs(this.vel.y) < 1) { + if (Math.floor(this.travelLength) % 64 === 0) { + this.scene.soundManager.playRandomSound(this.scene.soundManager.stepSound); + } + + this.anim.frame += 1; + if (this.anim.frame > this.anim.end) { + this.anim.frame = this.anim.start; + } + this.bodySprite.setTexture("atlasFps", this.anim.frames[this.anim.frame]); + } + } + } else { + //show inventory on click if looking down + + if(this.dir.pitch > Math.PI * 0.4){ + if (this.bodySprite.texture.key !== "fps_tex_128_inventory"){//frame? + this.bodySprite.setTexture("atlasFps", "fps_tex_128_inventory"); + } + this.setHintText("open Inventory"); + if (this.scene.hand.justReleased === true && this.panel === null) { + this.setMode(PLAYERMODE.INTERACT); + this.panel = new PanelInventory(this.scene, {items: null}); + } + }else{ + //this.setHintText(""); + //todo might need to be different if there is a sitting inventory + if (this.bodySprite.texture.key === "fps_tex_128_inventory") {//frame? + this.setHintText(""); + } + if (this.bodySprite.texture.key !== this.anim.frames[this.anim.frame]){//frame? + this.bodySprite.setTexture("atlasFps", this.anim.frames[this.anim.frame]); + } + } + + } + } + + + if (this.panel !== null) { + this.panel.update(); + } + + if (this.conversation !== null) { + if (this.mode === PLAYERMODE.DIALOGUE) { + this.conversation.update(); + } + } + + this.conversationManager.update(); + + //console.log(this.dir.pitch + " - " + this.scene.cam.dir.pitch) + } + + + } + + jumpToPosition(_pos, _immediately = false) { + //use this to set a neew position even if the collision checks have moved the position around differently + //eg if a collision in x resolves in a trigger jumping the player, but collision resolve in z afterwards would reset that + this.pos.to.jump = true; + this.pos.to.x = _pos.x; + this.pos.to.y = _pos.y; + this.pos.to.z = _pos.z; + + if (_immediately === true) { + this.pos.x = this.pos.to.x; + this.pos.y = this.pos.to.y; + this.pos.z = this.pos.to.z; + this.pos.to.jump = false; + } + } + + setMode(_mode) { + this.mode = _mode; + switch (_mode) { + case PLAYERMODE.LOOK: + this.showUI(); + break; + case PLAYERMODE.INTERACT: + this.scene.hand.setMouseLock(false); + this.hideUI(); + break; + case PLAYERMODE.DIALOGUE: + this.scene.hand.setMouseLock(false); + this.hideUI(); + break; + case PLAYERMODE.SHIP: + + break; + default: + break; + } + } + + setMoveMode(_mode) { + if (_mode !== this.moveMode) { + this.moveMode = _mode; + switch (this.moveMode) { + case PLAYERMOVE.STAND://stand still - not stand up + this.end = 0; + if (this.useFpsBody === true) { + this.bodySprite.setTexture("atlasFps", this.anim.frames[0]); + this.bodySprite.alpha = 1; + } + break; + case PLAYERMOVE.SIT: + this.eyeHeight = 20; + this.end = 0; + if (this.useFpsBody === true) { + this.bodySprite.setTexture("atlasFps", this.anim.frames[0]); + this.bodySprite.alpha = 0; + } + break; + case PLAYERMOVE.LIE: + this.eyeHeight = 18; + this.end = 0; + if (this.useFpsBody === true) { + this.bodySprite.setTexture("atlasFps", this.anim.frames[0]); + this.bodySprite.alpha = 0; + } + break; + case PLAYERMOVE.WALK: + case PLAYERMOVE.RUN: + this.eyeHeight = 24;//32 + if (this.useFpsBody === true) { + this.anim.frames = ["fps_tex_128_walk_0", "fps_tex_128_walk_1", "fps_tex_128_walk_2", "fps_tex_128_walk_3"]; + this.anim.end = 3; + this.bodySprite.alpha = 1; + } + break; + default: + break; + case PLAYERMOVE.SHIP: + this.eyeHeight = 0; + break; + } + } + } + + setHintText(_text) { + this.lowerHint.setText(_text); + } + + setUseSprite(_spr = "sprInteract01", _atl = "atlasUi") { + this.useSprite.setTexture(_atl, _spr); + } + + setUseBox(_rect) { + this.showUsing = true; + this.useBox.clear(); + let th = 6; + + //draw faint scanlines + this.useBox.lineStyle(3, 0xffffff, 0.25);//0x00e436 + this.useBox.beginPath(); + for (let y = _rect.p0.y; y < _rect.p1.y; y++) { + if ((Math.floor(this.scene.game.config.height + y)) % th === Math.floor(this.useBoxAnim)) { + this.useBox.moveTo(_rect.p0.x, y); + this.useBox.lineTo(_rect.p1.x, y); + } + } + this.useBox.strokePath(); + + //draw box outline + this.useBox.lineStyle(1, 0xffffff, 1);//0x00e436 + this.useBox.beginPath(); + this.useBox.moveTo(_rect.p0.x, _rect.p0.y); + this.useBox.lineTo(_rect.p1.x, _rect.p0.y); + this.useBox.moveTo(_rect.p1.x, _rect.p0.y); + this.useBox.lineTo(_rect.p1.x, _rect.p1.y); + this.useBox.moveTo(_rect.p1.x, _rect.p1.y); + this.useBox.lineTo(_rect.p0.x, _rect.p1.y); + this.useBox.moveTo(_rect.p0.x, _rect.p1.y); + this.useBox.lineTo(_rect.p0.x, _rect.p0.y); + this.useBox.strokePath(); + + //advance useBoxAnim to let the scanlines roll + this.useBoxAnim += 0.25 * this.scene.dt; + if (this.useBoxAnim >= th) { + this.useBoxAnim = 0; + } + + this.useBox.alpha = 1; + this.useSprite.alpha = 1;//maybe not show this + + if (this.useFpsBody === true) { + this.handSprite.setTexture("atlasFps", "fps_tex_128_use"); + } + } + + clearUseBox() { + this.showUsing = false; + this.useBox.clear(); + this.useSprite.alpha = 0; + if (this.useFpsBody === true) { + this.handSprite.setTexture("atlasFps", "fps_tex_128_use_point"); + } + } + + hideUI() { + if (this.useFpsBody === true) { + this.bodySprite.alpha = 0; + this.handSprite.alpha = 0; + } + this.clearUseBox(); + this.setHintText(""); + this.lowerHint.alpha = 0; + } + + showUI() { + if (this.useFpsBody === true) { + if (this.moveMode !== PLAYERMOVE.SIT) { + this.bodySprite.alpha = 1; + } + this.handSprite.alpha = 1; + } + this.lowerHint.alpha = 1; + } + + setVisibility(_bool) { + this.isVisible = _bool; + if (this.isVisible === true) { + this.bodySprite.alpha = 1; + this.handSprite.alpha = 1; + } else { + this.bodySprite.alpha = 0; + this.handSprite.alpha = 0; + } + } + + gameControls6dof() { + //this.keyboardLook(); + if (this.mode === PLAYERMODE.LOOK) { + if (this.scene.hand.mouselock === false) { + this.scene.hand.setMouseLock(true); + } + this.mouseLook(); + + if (globalOrientation.alpha !== null) { + this.orientationLook(); + } + if (isMobile === true) { + //this.touchLook(); + } + } + + this.dir.pitch = Math.max(-HALFPI, Math.min(HALFPI, this.dir.pitch)); + + + //move and collision was here + + + if (this.scene.hand.justReleased || INPUTS.btnA.justReleased) {//newor + if (this.mode === PLAYERMODE.LOOK) { + if (this.scene.input.mouse.locked === false) { + this.scene.hand.setMouseLock(true); + } + } + //this.cam.zoomTween.restart(); + //log the playre position as a helper for manual object positioning in level files + if (this.scene.keys.q.isDown) { + console.log(this); + } + } + } + + gameControlsFps() { + //camera controls + //looking + let toDir = { + yaw: this.modDir.yaw, + pitch: this.modDir.pitch, + roll: this.modDir.roll + } + if (this.scene.cursors.up.isDown) { + toDir.pitch += this.dir.spd.pitch /** this.scene.dt */; + } + if (this.scene.cursors.down.isDown) { + toDir.pitch -= this.dir.spd.pitch /** this.scene.dt */; + } + if (this.scene.cursors.right.isDown) { + if (this.scene.keys.q.isDown) { + toDir.roll -= this.dir.spd.roll /** this.scene.dt */; + } else { + toDir.yaw -= this.dir.spd.yaw /** this.scene.dt */; + } + } + if (this.scene.cursors.left.isDown) { + if (this.scene.keys.q.isDown) { + toDir.roll += this.dir.spd.roll /** this.scene.dt */; + } else { + toDir.yaw += this.dir.spd.yaw /** this.scene.dt */; + } + } + + if (this.mode === PLAYERMODE.LOOK) { + if (this.scene.hand.mouselock === false) { + this.scene.hand.setMouseLock(true); + } + if (this.scene.hand.vel.x !== 0) { + //this.dir.yaw = prevCamDir.yaw; + toDir.yaw -= ((this.scene.hand.vel.x) * this.dir.spd.yaw /** this.scene.dt */); + } + if (this.scene.hand.vel.y !== 0) { + //this.dir.pitch = prevCamDir.pitch; + toDir.pitch += ((this.scene.hand.vel.y) * this.dir.spd.pitch /** this.scene.dt */); + } + + if (globalOrientation.alpha !== null) { + let retdir = this.orientationLook(); + toDir.yaw -= retdir.yaw; + toDir.pitch -= retdir.pitch; + } + if (isMobile === true) { + let retdir = this.touchLook(); + toDir.yaw -= retdir.yaw; + toDir.pitch -= retdir.pitch; + } + } + + this.dir.yaw += toDir.yaw /** this.scene.dt*/; + this.dir.roll += toDir.roll /** this.scene.dt*/; + + if (this.dir.pitch + toDir.pitch < HALFPI && this.dir.pitch + toDir.pitch > -HALFPI) { + this.dir.pitch += toDir.pitch /** this.scene.dt*/; + this.dir.pitch = Math.max(-HALFPI, Math.min(HALFPI, this.dir.pitch)); + } else { + toDir.pitch = 0; + } + + + this.rotateAroundAxis(this.transform.toVectorArray(this.transform.up), toDir.yaw /** this.scene.dt*/ * -1); + + this.scene.cam.rotateAroundAxis(this.scene.cam.transform.toVectorArray(this.transform.up), (toDir.yaw /** this.scene.dt*/ * -1)); + this.scene.cam.rotateAroundAxis(this.scene.cam.transform.toVectorArray(this.transform.right), (toDir.pitch /** this.scene.dt*/)); + this.scene.cam.rotateAroundAxis(this.scene.cam.transform.toVectorArray(this.scene.cam.transform.forward), (toDir.roll /** this.scene.dt*/)); + + /* //does check if level, but does not know if angle is above or below the horizon + let horizonUp = [0, -1, 0]; + let myUp = [this.scene.cam.transform.up.x, this.scene.cam.transform.up.y, this.scene.cam.transform.up.z]; + let angleToHorizon = gl_vec3.dot(horizonUp, myUp); + //console.log(Math.floor(angleToHorizon * 100)); + */ + + /* //needs history of movement to check if angleToForward gets bigger (turning towards the target) + let horizonFw = [0, 0, -1]; + let myFw = [this.scene.cam.transform.forward.x, this.scene.cam.transform.forward.y, this.scene.cam.transform.forward.z]; + let angleToForward = gl_vec3.dot(horizonFw, myFw); + //console.log(Math.floor(angleToForward * 100)) + */ + + this.transform.up.x = 0; + this.transform.up.y = -1; + this.transform.up.z = 0; + + //walking + let wantToMove = false; + let toPos = { + x: this.pos.x, + y: this.pos.y, + z: this.pos.z + } + let ogPos = { + x: this.pos.x, + y: this.pos.y, + z: this.pos.z + } + let spd = 3; + //console.log(INPUTS.triggerLeft.amount) todo trigger left is still on ship controls + if (INPUTS.btnShoulderLeft.pressed === true || INPUTS.btnTriggerLeft.pressed === true /*|| INPUTS.triggerLeft.amount > 0*/) { + spd = this.spd.sprint; + } else { + spd = this.spd.normal; + } + //stick and keyboard move + if (Math.abs(INPUTS.stickLeft.horizontal) > 0.1) { + //todo make sprint only go forward? + toPos.x += (this.transform.right.x * (spd * INPUTS.stickLeft.horizontal)) * this.scene.dt; + toPos.y += (this.transform.right.y * (spd * INPUTS.stickLeft.horizontal)) * this.scene.dt; + toPos.z += (this.transform.right.z * (spd * INPUTS.stickLeft.horizontal)) * this.scene.dt; + wantToMove = true; + } + if (Math.abs(INPUTS.stickLeft.vertical) > 0.1) { + toPos.x += (this.transform.forward.x * (-spd * INPUTS.stickLeft.vertical)) * this.scene.dt; + toPos.y += (this.transform.forward.y * (-spd * INPUTS.stickLeft.vertical)) * this.scene.dt; + toPos.z += (this.transform.forward.z * (-spd * INPUTS.stickLeft.vertical)) * this.scene.dt; + wantToMove = true; + } + //touch controls move + if (isMobile === true) { + if (this.scene.hand.pressed === true) { + if (this.scene.hand.start.y > this.scene.game.config.height * -0.4 && this.scene.hand.start.y < this.scene.game.config.height * 0.4) { + if (this.scene.hand.start.x > this.scene.game.config.width * -0.33 && this.scene.hand.start.x < this.scene.game.config.width * 0.33) { + let amt = Math.max(-1, Math.min(1, (this.scene.hand.pos.y - this.scene.hand.start.y) * 0.01)); + if (this.scene.hand.pos.y > 0) { + INPUTS.btnTriggerLeft.pressed = true; + spd = this.spd.sprint; + } else { + INPUTS.btnTriggerLeft.pressed = false; + spd = this.spd.normal; + } + //toPos.z -= (Math.cos(this.dir.yaw) * amt) * (INPUTS.btnTriggerLeft.pressed ? this.spd.sprint : this.spd.normal); + //toPos.x += (Math.sin(this.dir.yaw) * amt) * (INPUTS.btnTriggerLeft.pressed ? this.spd.sprint : this.spd.normal); + toPos.x += (this.transform.forward.x * (-spd * amt)) * this.scene.dt; + toPos.y += (this.transform.forward.y * (-spd * amt)) * this.scene.dt; + toPos.z += (this.transform.forward.z * (-spd * amt)) * this.scene.dt; + wantToMove = true; + if (this.scene.hand.pos.y < this.scene.game.config.height * -0.1) {//also jump + if (this.gravity.grounded === true) { + this.vel.y = -1; + } + } + } + } + } + } + + + //jump + //if (this.scene.keys.space.isDown) { + if (INPUTS.btnShoulderRight.pressed) { + /*this.pos.x += this.transform.up.x * spd; + this.pos.y += this.transform.up.y * spd; + this.pos.z += this.transform.up.z * spd;*/ + if (this.gravity.grounded === true) { + this.vel.y = -0.5; + } + } + if (this.scene.keys.c.isDown) { + /*this.pos.x += this.transform.up.x * -spd; + this.pos.y += this.transform.up.y * -spd; + this.pos.z += this.transform.up.z * -spd;*/ + } + + if (this.moveMode !== PLAYERMOVE.SHIP) { + this.pos.y += this.vel.y * this.scene.dt; + } + + //try to interact on mobile + let touchInteract = false; + if (isMobile === true) { + if (this.scene.hand.justReleased === true) { + if (this.scene.hand.start.y < this.scene.game.config.height * -0.4 || this.scene.hand.start.y > this.scene.game.config.height * 0.4) { + touchInteract = true; + } + } + } + + if (INPUTS.btnA.justReleased || this.scene.input.mouse.locked === true ? this.scene.hand.justReleased : false || touchInteract === true) { + //alert("wanted to interact") + } + + if (this.moveMode !== PLAYERMOVE.SHIP) { + //collide with world + let returnColl = []; + returnColl = this.scene.geometryController.update( + [ + {//check ground at player position + pos: { + x: this.pos.x, + y: this.pos.y + this.eyeHeight, + z: this.pos.z + }, + dir: { + x: 0, + y: 1, + z: 0 + }, + hit: [] + }, {//check wall colllision global x axis + pos: { + x: toPos.x, + y: toPos.y - this.stepHeight, + z: toPos.z + }, + dir: { + x: 1,//this.transform.right.x, + y: 0,//this.transform.right.y, + z: 0//this.transform.right.z + }, + hit: [] + }, {//check wall colllision global z axis + pos: { + x: toPos.x, + y: toPos.y - this.stepHeight, + z: toPos.z + }, + dir: { + x: 0,//this.transform.forward.x, + y: 0,//this.transform.forward.y, + z: 1//this.transform.forward.z + }, + hit: [] + } + ] + ); + /*if(this.scene.input.activePointer.isDown){ + console.log(returnColl); + }*/ + + //resolve collision with ground + if (returnColl[0].hit.length > 0) { + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[0].hit[0]; + for (let [i, n] of returnColl[0].hit.entries()) { + let d = Phaser.Math.Distance.Between(0, this.pos.y - this.stepHeight, 0, returnColl[0].hit[i].pt[1]); + if (d < dist) { + dist = d; + nearestHit = returnColl[0].hit[i]; + } + } + //returnColl[input point and direction].hit[nearest = 0].pt[coord x,y,z] + //teleport to ground + if (nearestHit.model.trigger.isTrigger === false) { + if (dist <= this.stepHeight) { + this.vel.y = 0; + this.pos.y = nearestHit.pt[1]; + this.gravity.grounded = true; + } else { + if (this.vel.y < this.gravity.terminal) { + this.vel.y += this.gravity.y * this.scene.dt; + } + this.pos.y += this.vel.y * this.scene.dt; + this.gravity.grounded = false; + } + } else { + nearestHit.model.updateTrigger(); + } + } + + //resolve hit in global x axis + if (returnColl[1].hit.length > 0) { + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[1].hit[0]; + for (let [i, n] of returnColl[1].hit.entries()) { + let d = Phaser.Math.Distance.Between(this.pos.x, this.pos.z, returnColl[1].hit[i].pt[0], returnColl[1].hit[i].pt[2]); + if (d < dist) { + dist = d; + nearestHit = returnColl[1].hit[i]; + } + } + if (dist < this.collisionRadius) { + //only move if you move away from the wall + if ((toPos.x < this.pos.x && this.pos.x < nearestHit.pt[0]) || (toPos.x > this.pos.x && this.pos.x > nearestHit.pt[0]) || nearestHit.model.trigger.isTrigger === true) { + this.pos.x = toPos.x; + if (nearestHit.model.trigger.isTrigger === true) { + nearestHit.model.updateTrigger(); + } + } + } else { + //be free to move cause yoou are far away from wall + this.pos.x = toPos.x; + } + } else { + //move because there is nothing out there + this.pos.x = toPos.x; + } + + if (returnColl[2].hit.length > 0) { + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[2].hit[0]; + for (let [i, n] of returnColl[2].hit.entries()) { + let d = Phaser.Math.Distance.Between(this.pos.x, this.pos.z, returnColl[2].hit[i].pt[0], returnColl[2].hit[i].pt[2]); + if (d < dist) { + dist = d; + nearestHit = returnColl[2].hit[i]; + } + } + if (dist < this.collisionRadius) { + //only move if you move away from the wall + if ((toPos.z < this.pos.z && this.pos.z < nearestHit.pt[2]) || (toPos.z > this.pos.z && this.pos.z > nearestHit.pt[2]) || nearestHit.model.trigger.isTrigger === true) { + this.pos.z = toPos.z; + if (nearestHit.model.trigger.isTrigger === true) { + nearestHit.model.updateTrigger(); + } + } + } else { + //be free to move cause yoou are far away from wall + this.pos.z = toPos.z; + } + } else { + //move because there is nothing out there + this.pos.z = toPos.z; + } + } + + this.isMoving = wantToMove; + if (this.moveMode === PLAYERMOVE.SHIP) { + this.isMoving = false; + wantToMove = false; + } + + if (wantToMove === true) { + this.setMoveMode(PLAYERMOVE.WALK); + if (INPUTS.btnTriggerLeft.pressed === true) { + this.setMoveMode(PLAYERMOVE.RUN); + } + } else { + if (this.moveMode !== PLAYERMOVE.SIT && this.moveMode !== PLAYERMOVE.SHIP) { + this.setMoveMode(PLAYERMOVE.STAND); + } + } + + //open menu + /*if (INPUTS.btnStart.justPressed === true){ + this.setMode(PLAYERMODE.INTERACT); + //this.panel = new PanelControlOptions(this); + //this.panel = new PanelWelcome(this); + alert("open menu") + }*/ + + if (this.mode !== PLAYERMODE.INTERACT) { + //look for models to interact with at center of screen if player click the mouse + let hits = []; + //hits = this.geometryController.getQuadsFromScreenspaceAt(this.input.activePointer.worldX, this.input.activePointer.worldY, false); + hits = this.scene.geometryController.getQuadsFromScreenspaceAt(0, 0, false); + if (hits.length > 0) { + hits = hits.sort((a, b) => a.depth - b.depth); + //if(hits[hits.length - 1].depth > -64){//interaction radius (moved that into eud.distance 7 lines lower) + this.scene.modelName = hits[hits.length - 1].modelId; + //this.debugTxt.setText(this.modelName); + //console.log(this.scene.modelName) + + let model = this.scene.geometryController.getModelById(this.scene.modelName = hits[hits.length - 1].modelId); + if (model.interactable === true) { + if (eud.distance([this.pos.x, this.pos.y, this.pos.z], [model.pos.x, model.pos.y, model.pos.z]) < (model.data.useRadius !== undefined ? model.data.useRadius : 24)) { + this.setHintText(model.data.useText !== undefined ? model.data.useText : "click to use"); + this.setUseSprite(model.data.useSprite !== undefined ? model.data.useSprite : "sprInteract01"); + this.setUseBox(model.getScreenBounds()); + + if (isMobile === true) { + if (this.scene.hand.justReleased === true) { + if (this.scene.hand.lastPressedTime < 30) { + model.interact(); + } + } + } else { + if (this.scene.hand.justReleased || INPUTS.btnA.justReleased) { + model.interact(); + } + } + } else { + this.setHintText(""); + this.clearUseBox(); + } + + } else { + this.setHintText(""); + this.clearUseBox(); + } + } + } + + //input via mouse + if (this.scene.hand.justReleased || INPUTS.btnA.justReleased) {//newor + if (this.mode === PLAYERMODE.LOOK) { + if (this.scene.input.mouse.locked === false && this.panel === null) { + this.scene.hand.setMouseLock(true); + } + } + //this.cam.zoomTween.restart(); + //log the playre position as a helper for manual object positioning in level files + if (this.scene.keys.q.isDown) { + console.log(this); + } + } + + //refresh mod vars + this.modDir.yaw = 0; + this.modDir.pitch = 0; + this.modDir.roll = 0; + } + + lookAt(_target = {x: 0, y: 0, z: 0}) { + //camera controls + //looking + let toDir = { + yaw: this.modDir.yaw, + pitch: this.modDir.pitch, + roll: this.modDir.roll + } + + //toDir.yaw += this.dir.spd.yaw; + + this.dir.yaw += toDir.yaw; + this.dir.roll += toDir.roll; + + if (this.dir.pitch + toDir.pitch < HALFPI && this.dir.pitch + toDir.pitch > -HALFPI) { + this.dir.pitch += toDir.pitch; + this.dir.pitch = Math.max(-HALFPI, Math.min(HALFPI, this.dir.pitch)); + } else { + toDir.pitch = 0; + } + + + this.rotateAroundAxis(this.transform.toVectorArray(this.transform.up), toDir.yaw * -1); + + this.scene.cam.rotateAroundAxis(this.scene.cam.transform.toVectorArray(this.transform.up), (toDir.yaw * -1)); + this.scene.cam.rotateAroundAxis(this.scene.cam.transform.toVectorArray(this.transform.right), (toDir.pitch)); + this.scene.cam.rotateAroundAxis(this.scene.cam.transform.toVectorArray(this.scene.cam.transform.forward), (toDir.roll)); + + /* //does check if level, but does not know if angle is above or below the horizon + let horizonUp = [0, -1, 0]; + let myUp = [this.scene.cam.transform.up.x, this.scene.cam.transform.up.y, this.scene.cam.transform.up.z]; + let angleToHorizon = gl_vec3.dot(horizonUp, myUp); + //console.log(Math.floor(angleToHorizon * 100)); + */ + + /* //needs history of movement to check if angleToForward gets bigger (turning towards the target) + let horizonFw = [0, 0, -1]; + let myFw = [this.scene.cam.transform.forward.x, this.scene.cam.transform.forward.y, this.scene.cam.transform.forward.z]; + let angleToForward = gl_vec3.dot(horizonFw, myFw); + //console.log(Math.floor(angleToForward * 100)) + */ + + this.transform.up.x = 0; + this.transform.up.y = -1; + this.transform.up.z = 0; + } + + gameControls() { + let wantToMove = false; + + this.keyboardLook(); + if (this.mode === PLAYERMODE.LOOK) { + if (this.scene.hand.mouselock === false) { + this.scene.hand.setMouseLock(true); + } + this.mouseLook(); + + if (globalOrientation.alpha !== null) { + this.orientationLook(); + } + if (isMobile === true) { + this.touchLook(); + } + } + + this.dir.pitch = Math.max(-HALFPI, Math.min(HALFPI, this.dir.pitch)); + + let toPos = { + x: this.pos.x, + y: this.pos.y, + z: this.pos.z + } + + if (Math.abs(INPUTS.stickLeft.horizontal) > 0.1) { + toPos.z -= (Math.cos(this.dir.yaw + HALFPI) * INPUTS.stickLeft.horizontal) * this.spd.normal; + toPos.x += (Math.sin(this.dir.yaw + HALFPI) * INPUTS.stickLeft.horizontal) * this.spd.normal; + wantToMove = true; + } + if (Math.abs(INPUTS.stickLeft.vertical) > 0.1) { + toPos.z -= (Math.cos(this.dir.yaw) * INPUTS.stickLeft.vertical) * (INPUTS.btnTriggerLeft.pressed ? this.spd.sprint : this.spd.normal); + toPos.x += (Math.sin(this.dir.yaw) * INPUTS.stickLeft.vertical) * (INPUTS.btnTriggerLeft.pressed ? this.spd.sprint : this.spd.normal); + wantToMove = true; + } + //touch controls move + if (isMobile === true) { + if (this.scene.hand.pressed === true) { + if (this.scene.hand.start.y > this.scene.game.config.height * -0.4 && this.scene.hand.start.y < this.scene.game.config.height * 0.4) { + if (this.scene.hand.start.x > this.scene.game.config.width * -0.33 && this.scene.hand.start.x < this.scene.game.config.width * 0.33) { + let amt = Math.max(-1, Math.min(1, (this.scene.hand.pos.y - this.scene.hand.start.y) * 0.01)); + if (this.hand.pos.y > 0) { + INPUTS.btnTriggerLeft.pressed = true; + } else { + INPUTS.btnTriggerLeft.pressed = false; + } + toPos.z -= (Math.cos(this.dir.yaw) * amt) * (INPUTS.btnTriggerLeft.pressed ? this.spd.sprint : this.spd.normal); + toPos.x += (Math.sin(this.dir.yaw) * amt) * (INPUTS.btnTriggerLeft.pressed ? this.spd.sprint : this.spd.normal); + wantToMove = true; + if (this.scene.hand.pos.y < this.scene.game.config.height * -0.1) {//also jump + if (this.vel.y === 0) { + this.vel.y = -2; + this.pos.y += this.vel.y; + } + } + } + } + } + } + + if (INPUTS.btnShoulderRight.pressed) { + this.pos.y -= 1; + } + if (INPUTS.btnShoulderLeft.pressed) { + this.pos.y += 1; + } + + //try to interact on mobile + let touchInteract = false; + if (isMobile === true) { + if (this.scene.hand.justReleased === true) { + if (this.scene.hand.start.y < this.scene.game.config.height * -0.4 || this.scene.hand.start.y > this.scene.game.config.height * 0.4) { + touchInteract = true; + } + } + } + + if (INPUTS.btnA.justReleased || this.scene.input.mouse.locked === true ? this.scene.hand.justReleased : false || touchInteract === true) { + //alert("wanted to interact") + } + + let returnColl = []; + returnColl = this.scene.geometryController.update( + [ + {//check ground at player position + pos: { + x: this.pos.x, + y: this.pos.y + this.eyeHeight, + z: this.pos.z + }, + dir: { + x: 0, + y: 1, + z: 0 + }, + hit: [] + }, {//check wall colllision global x axis + pos: { + x: toPos.x, + y: toPos.y - this.stepHeight, + z: toPos.z + }, + dir: { + x: 1, + y: 0, + z: 0 + }, + hit: [] + }, {//check wall colllision global z axis + pos: { + x: toPos.x, + y: toPos.y - this.stepHeight, + z: toPos.z + }, + dir: { + x: 0, + y: 0, + z: 1 + }, + hit: [] + } + ] + ); + /*if(this.scene.input.activePointer.isDown){ + console.log(returnColl); + }*/ + + //resolve collision with ground + if (returnColl[0].hit.length > 0) { + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[0].hit[0]; + for (let [i, n] of returnColl[0].hit.entries()) { + let d = Phaser.Math.Distance.Between(0, this.pos.y - this.stepHeight, 0, returnColl[0].hit[i].pt[1]); + if (d < dist) { + dist = d; + nearestHit = returnColl[0].hit[i]; + } + } + //returnColl[input point and direction].hit[nearest = 0].pt[coord x,y,z] + //teleport to ground + if (nearestHit.model.trigger.isTrigger === false) { + if (dist <= this.stepHeight) { + this.vel.y = 0; + this.pos.y = nearestHit.pt[1]; + } else { + if (this.vel.y < this.gravity.terminal) { + this.vel.y += this.gravity.y; + } + this.pos.y += this.vel.y; + } + } else { + nearestHit.model.updateTrigger(); + } + } + + //resolve hit in global x axis + if (returnColl[1].hit.length > 0) { + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[1].hit[0]; + for (let [i, n] of returnColl[1].hit.entries()) { + let d = Phaser.Math.Distance.Between(this.pos.x, this.pos.z, returnColl[1].hit[i].pt[0], returnColl[1].hit[i].pt[2]); + if (d < dist) { + dist = d; + nearestHit = returnColl[1].hit[i]; + } + } + if (dist < this.collisionRadius) { + //only move if you move away from the wall + if ((toPos.x < this.pos.x && this.pos.x < nearestHit.pt[0]) || (toPos.x > this.pos.x && this.pos.x > nearestHit.pt[0]) || nearestHit.model.trigger.isTrigger === true) { + this.pos.x = toPos.x; + if (nearestHit.model.trigger.isTrigger === true) { + nearestHit.model.updateTrigger(); + } + } + } else { + //be free to move cause yoou are far away from wall + this.pos.x = toPos.x; + } + } else { + //move because there is nothing out there + this.pos.x = toPos.x; + } + + if (returnColl[2].hit.length > 0) { + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[2].hit[0]; + for (let [i, n] of returnColl[2].hit.entries()) { + let d = Phaser.Math.Distance.Between(this.pos.x, this.pos.z, returnColl[2].hit[i].pt[0], returnColl[2].hit[i].pt[2]); + if (d < dist) { + dist = d; + nearestHit = returnColl[2].hit[i]; + } + } + if (dist < this.collisionRadius) { + //only move if you move away from the wall + if ((toPos.z < this.pos.z && this.pos.z < nearestHit.pt[2]) || (toPos.z > this.pos.z && this.pos.z > nearestHit.pt[2]) || nearestHit.model.trigger.isTrigger === true) { + this.pos.z = toPos.z; + if (nearestHit.model.trigger.isTrigger === true) { + nearestHit.model.updateTrigger(); + } + } + } else { + //be free to move cause yoou are far away from wall + this.pos.z = toPos.z; + } + } else { + //move because there is nothing out there + this.pos.z = toPos.z; + } + + this.isMoving = wantToMove; + if (wantToMove === true) { + this.setMoveMode(PLAYERMOVE.WALK); + if (INPUTS.btnTriggerLeft.pressed === true) { + this.setMoveMode(PLAYERMOVE.RUN); + } + } else { + if (this.moveMode !== PLAYERMOVE.SIT) { + this.setMoveMode(PLAYERMOVE.STAND); + } + } + + //open menu + if (INPUTS.btnStart.justPressed === true) { + this.setMode(PLAYERMODE.INTERACT); + //this.panel = new PanelControlOptions(this); + this.panel = new PanelWelcome(this); + } + + //look for models to interact with at center of screen if player click the mouse + let hits = []; + //hits = this.geometryController.getQuadsFromScreenspaceAt(this.input.activePointer.worldX, this.input.activePointer.worldY, false); + hits = this.scene.geometryController.getQuadsFromScreenspaceAt(0, 0, false); + if (hits.length > 0) { + hits = hits.sort((a, b) => a.depth - b.depth); + //if(hits[hits.length - 1].depth > -64){//interaction radius (moved that into eud.distance 7 lines lower) + this.scene.modelName = hits[hits.length - 1].modelId; + //this.debugTxt.setText(this.modelName); + + let model = this.scene.geometryController.getModelById(this.scene.modelName = hits[hits.length - 1].modelId); + if (model.interactable === true) { + if (eud.distance([this.pos.x, this.pos.y, this.pos.z], [model.pos.x, model.pos.y, model.pos.z]) < 24) { + this.setHintText(model.data.useText !== undefined ? model.data.useText : "click to use"); + this.setUseSprite(model.data.useSprite !== undefined ? model.data.useSprite : "sprInteract01"); + this.setUseBox(model.getScreenBounds()); + + if (isMobile === true) { + if (this.scene.hand.justReleased === true) { + if (this.scene.hand.lastPressedTime < 30) { + model.interact(); + } + } + } else { + if (this.scene.hand.justReleased || INPUTS.btnA.justReleased) { + model.interact(); + } + } + } else { + this.setHintText(""); + this.clearUseBox(); + } + + } else { + this.setHintText(""); + this.clearUseBox(); + } + } + + if (this.scene.hand.justReleased || INPUTS.btnA.justReleased) {//newor + if (this.mode === PLAYERMODE.LOOK) { + if (this.scene.input.mouse.locked === false) { + this.scene.hand.setMouseLock(true); + } + } + //this.cam.zoomTween.restart(); + //log the playre position as a helper for manual object positioning in level files + if (this.scene.keys.q.isDown) { + console.log(this); + } + } + } + + keyboardLook() { + if (this.scene.cursors.up.isDown) { + this.dir.pitch += this.dir.spd.pitch; + } + if (this.scene.cursors.down.isDown) { + this.dir.pitch -= this.dir.spd.pitch; + } + if (this.scene.cursors.right.isDown) { + if (this.scene.keys.q.isDown) { + this.dir.roll -= this.dir.spd.roll; + } else { + this.dir.yaw -= this.dir.spd.yaw; + } + } + if (this.scene.cursors.left.isDown) { + if (this.scene.keys.q.isDown) { + this.dir.roll += this.dir.spd.roll; + } else { + this.dir.yaw += this.dir.spd.yaw; + } + } + } + + mouseLook() { + if (this.scene.hand.vel.x !== 0) { + //this.dir.yaw = prevCamDir.yaw; + this.dir.yaw -= ((this.scene.hand.vel.x) * this.dir.spd.yaw); + } + if (this.scene.hand.vel.y !== 0) { + //this.dir.pitch = prevCamDir.pitch; + this.dir.pitch += ((this.scene.hand.vel.y) * this.dir.spd.pitch); + } + } + + orientationLook() { + let arr = [globalOrientation.alpha, globalOrientation.beta, globalOrientation.gamma]; + for (let [i, a] of arr.entries()) { + if (a === null) { + arr[i] = 0; + } + //if(a >= 180){a -= 360} + //if(a < -180){a += 360} + arr[i] = a * Math.PI / 180; + } + + //this.dir.pitch = (arr[1] * -1) + (Math.PI * 0.5); + //this.dir.yaw = (arr[0]); + + let rotation = getEulerAngles(getRotationMatrix(globalOrientation.alpha, globalOrientation.beta, globalOrientation.gamma)); + let degtorad = Math.PI / 180; + + let toYaw = offsetOrientation.yaw - (rotation[2] * degtorad) + let toPitch = offsetOrientation.pitch - ((rotation[1] * degtorad) * -1); + + this.dir.yaw -= toYaw; + this.dir.pitch -= toPitch; + + offsetOrientation.yaw = (rotation[2] * degtorad); + offsetOrientation.pitch = ((rotation[1] * degtorad) * -1); + + return { yaw: toYaw, pitch: toPitch } + } + + touchLook() { + let toYaw = 0; + let toPitch = 0; + + if (this.scene.hand.pressed === true) { + if (this.scene.hand.start.y > this.scene.game.config.height * -0.4 && this.scene.hand.start.y < this.scene.game.config.height * 0.4) { + if (this.scene.hand.pos.y > 0) { + let amt = (this.scene.hand.pos.x - this.scene.hand.start.x) * 0.0005; + this.dir.yaw -= amt; + toYaw = amt; + } + if (this.scene.hand.start.x < this.scene.game.config.width * -0.33 || this.scene.hand.start.x > this.scene.game.config.width * 0.33) { + let amt = (this.scene.hand.pos.y - this.scene.hand.start.y) * 0.0005; + this.dir.pitch += amt; + toPitch = amt; + } + } + } + + return { yaw: toYaw, pitch: toPitch } + } + + rotateByQuaternion(_quat) { + //rotate local axis around quaternion + let opts = [this.transform.forward.x, this.transform.forward.y, this.transform.forward.z]; + let npts = this.getRotatedVectorByQuaternion(opts, _quat); + this.transform.forward.x = npts[0]; + this.transform.forward.y = npts[1]; + this.transform.forward.z = npts[2]; + this.transform.forward = gl_rvaa.AIOvec3normalize(this.transform.forward, this.transform.forward); + + opts = [this.transform.right.x, this.transform.right.y, this.transform.right.z]; + npts = this.getRotatedVectorByQuaternion(opts, _quat); + this.transform.right.x = npts[0]; + this.transform.right.y = npts[1]; + this.transform.right.z = npts[2]; + this.transform.right = gl_rvaa.AIOvec3normalize(this.transform.right, this.transform.right); + + opts = [this.transform.up.x, this.transform.up.y, this.transform.up.z]; + npts = this.getRotatedVectorByQuaternion(opts, _quat); + this.transform.up.x = npts[0]; + this.transform.up.y = npts[1]; + this.transform.up.z = npts[2]; + this.transform.up = gl_rvaa.AIOvec3normalize(this.transform.up, this.transform.up); + } + + getRotatedVectorByQuaternion(_vector, _quat) { + let u = [_quat[0], _quat[1], _quat[2]]; + let s = _quat[3]; + + //let cros = gl_rvaa.AIOvec3cross([0, 0, 0], u, _vector) + //return 2 * gl_rvaa.AIOvec3dot(u, _vector) * u + (s*s - gl_rvaa.AIOvec3dot(u, u)) * _vector + 2 * s * gl_rvaa.AIOvec3cross(u, u, _vector); + let dot0 = gl_rvaa.AIOvec3dot(u, _vector); + let vec0 = [ + 2 * dot0 * u[0], + 2 * dot0 * u[1], + 2 * dot0 * u[2] + ]; + let dot1 = gl_rvaa.AIOvec3dot(u, u); + let vec1 = [ + (s * s - dot1) * _vector[0], + (s * s - dot1) * _vector[1], + (s * s - dot1) * _vector[2] + ] + let cro0 = gl_rvaa.AIOvec3cross(u, u, _vector); + let vec2 = [ + 2 * s * cro0[0], + 2 * s * cro0[1], + 2 * s * cro0[2] + ] + let vet = [ + vec0[0] + vec1[0] + vec2[0], + vec0[1] + vec1[1] + vec2[1], + vec0[2] + vec1[2] + vec2[2] + ] + return vet; + } + + rotateAroundAxis(_axis, _angle) { + // credi @Lewa helpdesk + + //INFO maybe set the rotation of the rotationQuat to the new forward, up and right vectors with (gl_quat.setAxis(out, view, right, up)) + + //turn the transform rotationQuat around axis and angle + //let totrans = gl_rvaa.AIOquatcreate(); + let totrans = gl_rvaa.AIOquatCreateFromAngleAxis(_axis[0], _axis[1], _axis[2], _angle) + let tempQuat = [0, 0, 0, 1]; + gl_rvaa.AIOquatmultiply(tempQuat, this.transform.rotationQuat, totrans); + + //create a matrix from transform rotationQuat + let rotMatrix = gl_rvaa.AIOmat3create() + gl_rvaa.AIOmat3fromQuat(rotMatrix, tempQuat) + + let npts = [this.transform.forward.x, this.transform.forward.y, this.transform.forward.z]; + gl_rvaa.AIOvec3multiplyWithMatrix(npts, [this.transform.forward.x, this.transform.forward.y, this.transform.forward.z], rotMatrix) + this.transform.forward.x = npts[0]; + this.transform.forward.y = npts[1]; + this.transform.forward.z = npts[2]; + this.transform.forward = gl_rvaa.AIOvec3normalize(this.transform.forward, this.transform.forward); + + npts = [this.transform.right.x, this.transform.right.y, this.transform.right.z]; + gl_rvaa.AIOvec3multiplyWithMatrix(npts, [this.transform.right.x, this.transform.right.y, this.transform.right.z], rotMatrix) + this.transform.right.x = npts[0]; + this.transform.right.y = npts[1]; + this.transform.right.z = npts[2]; + this.transform.right = gl_rvaa.AIOvec3normalize(this.transform.right, this.transform.right); + + npts = [this.transform.up.x, this.transform.up.y, this.transform.up.z]; + gl_rvaa.AIOvec3multiplyWithMatrix(npts, [this.transform.up.x, this.transform.up.y, this.transform.up.z], rotMatrix) + this.transform.up.x = npts[0]; + this.transform.up.y = npts[1]; + this.transform.up.z = npts[2]; + this.transform.up = gl_rvaa.AIOvec3normalize(this.transform.up, this.transform.up); + + //normalize to prevent weird rotations + this.transform.normalizeRotationQuat(); + } +} diff --git a/src/3d/playerEuler.js b/src/3d/playerEuler.js new file mode 100755 index 0000000..13eeaf3 --- /dev/null +++ b/src/3d/playerEuler.js @@ -0,0 +1,742 @@ +import ConversationManager from "../ui/conversationManager.js"; +import PanelInventory from "../ui/panelInventory.js"; + +export class PlayerEuler { + /* + ALERTINFOIMPORTANT + this is the old FPS controller with Euler Angles + use player3d for a vector based FPS controls + */ + constructor(_scene) { + this.scene = _scene; + this.pos = { + x: 0, + y: 0, + z: 0, + to: { + jump: false, + x: 0, + y: 0, + z: 0, + }, + last: { + x: 0, + y: 0, + z: 0 + } + } + this.dir = { + yaw: 0, + pitch: 0, + roll: 0, + spd: { + yaw: 0.04, + pitch: 0.04, + roll: 0.04 + } + } + this.vel = { + x: 0, + y: 0, + z: 0 + } + this.eyeHeight = 24;//24 + this.stepHeight = 9; + this.collisionRadius = 12; + this.spd = { + normal: 2, + sprint: 3 + } + + this.gravity = { + x: 0, + y: 0.1, + z: 0, + grounded: false, + terminal: 4 + } + + this.mode = PLAYERMODE.LOOK; + this.moveMode = PLAYERMOVE.STAND; + this.isMoving = false; + this.showUsing = false; + + this.lowerHint = this.scene.add.bitmapText(0, (this.scene.game.config.height * 0.4), "uiFont", "", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.lowerHint.depth = 9999; + this.useBox = this.scene.add.graphics({x: 0, y: 0.5}); + this.useBox.depth = 9999; + this.useBoxAnim = 0; + this.useSprite = this.scene.add.sprite(0, 0, "sprInteract01"); + this.useSprite.depth = 9999; + this.useSprite.alpha = 0; + + /* + this.debugOrientPitch = this.scene.add.bitmapText(0, (this.scene.game.config.height * -0.4), "segoeUI_16", "", 16, 0).setOrigin(0.5).setLetterSpacing(1); + this.debugOrientPitch.depth = 9999; + this.debugOrientYaw = this.scene.add.bitmapText(0, (this.scene.game.config.height * -0.4) + 32, "segoeUI_16", "", 16, 0).setOrigin(0.5).setLetterSpacing(1); + this.debugOrientYaw.depth = 9999; + */ + + this.itemSprite = null; + this.inventory = { + position: 0, + items: [ + {flag: "00hasHand", asset: null, atlas: null}, + // { flag: "00hasRevolver", asset: "itemRevolver", atlas: null }, + // { flag: "00hasCigarettes", asset: "itemCigarettes00", atlas: "atlasItems"}, + // { flag: "00hasKeycard", asset: "itemKeycard", atlas: "atlasItems" } + ] + } + + this.bodySprite = this.scene.add.sprite(0, 0, "sprFPSwalk_0"); + this.bodySprite.depth = 998; + this.bodySprite.setScale(4); + this.handSprite = this.scene.add.sprite(0, 0, "sprFPSpoint"); + this.handSprite.depth = 999; + this.handSprite.setScale(4); + + this.panel = null; + this.conversation = null; + this.conversationManager = new ConversationManager(this.scene); + + this.anim = { + frame: 0, + end: 3, + start: 0, + frames: ["sprFPSwalk_0", "sprFPSwalk_1", "sprFPSwalk_2", "sprFPSwalk_3"] + } + + this.stepSounds = []; + for(let i = 0 ; i < 8 ; i++){ + this.stepSounds.push(SOUNDS.stepsHallway.play("step" + String(i))); + SOUNDS.stepsHallway.stop(this.stepSounds[i]); + } + this.muteTimer = setTimeout(() => {}, 10); + } + + update() { + if (this.pos.to.jump === true) { + this.pos.x = this.pos.to.x; + this.pos.y = this.pos.to.y; + this.pos.z = this.pos.to.z; + this.pos.to.jump = false; + } + + this.dir.yaw = normAngle(this.dir.yaw); + + if(this.scene.editor.enabled === false){ + this.bodySprite.y = (this.scene.game.config.height * 0.5) + Math.cos(Math.max(0, this.dir.pitch) * 2) * 192; + if (this.showUsing === false) { + this.handSprite.y = (this.scene.game.config.height * 0.5) + Math.sin(this.dir.pitch * 1) * 192; + } else { + this.handSprite.y = 128; + } + + if (this.moveMode === PLAYERMOVE.SIT) { + + } + //scroll inventory + + if(this.scene.hand.wheel !== 0){ + this.inventory.position = Math.max(0, Math.min(this.inventory.position + this.scene.hand.wheel, this.inventory.items.length - 1)); + + let entry = this.inventory.items[this.inventory.position]; + console.log(entry.asset, entry.atlas) + this.setItemSprite(entry.asset, entry.atlas); + } + + + + //footsteps + if(this.isMoving === true){ + if (eud.distance([this.pos.x, this.pos.y, this.pos.z], [this.pos.last.x, this.pos.last.y, this.pos.last.z]) > 16) { + this.travelLength += 16; + this.pos.last.x = this.pos.x; + this.pos.last.y = this.pos.y; + this.pos.last.z = this.pos.z; + //if (this.gravity.grounded === true){ + if (Math.abs(this.vel.y) < 1) { + //this.sndStep.volume = (0.5 + (Math.random() * 0.5)) * OPTIONS.sfx; + //this.sndStep.play(); + //console.log("step") + for(let s of this.stepSounds){ + SOUNDS.stepsHallway.stop(s); + } + SOUNDS.stepsHallway.stop(); + let r = this.stepSounds[Math.floor(Math.random() * this.stepSounds.length)]; + SOUNDS.stepsHallway.play(r); + clearTimeout(this.muteTimer); + this.muteTimer = setTimeout(() => { + for (let s of this.stepSounds) { + SOUNDS.stepsHallway.stop(s); + } + SOUNDS.stepsHallway.stop(); + }, 600); + //SOUNDS.stepsHallway.volume((0.5 + (Math.random() * 0.5)) * OPTIONS.sfx, r); + //let sndId = SOUNDS.stepsHallway.play("step" + String(Math.floor(Math.random() * 8))); + //SOUNDS.stepsHallway.volume((0.5 + (Math.random() * 0.5)) * OPTIONS.sfx, sndId); + + this.anim.frame += 1; + if (this.anim.frame > this.anim.end) { + this.anim.frame = this.anim.start; + } + this.bodySprite.setTexture(this.anim.frames[this.anim.frame]); + } + } + }else{ + //show inventory on click if looking down + /* + if(this.dir.pitch > Math.PI * 0.4){ + if (this.bodySprite.texture.key !== "sprFPSinventory"){ + this.bodySprite.setTexture("sprFPSinventory"); + } + this.setHintText("Inventory"); + if (this.scene.hand.justReleased === true && this.panel === null) { + this.setMode(PLAYERMODE.INTERACT); + this.panel = new PanelInventory(this.scene, {items: null}); + } + }else{ + //this.setHintText(""); + //todo might need to be different if there is a sitting inventory + if (this.bodySprite.texture.key === "sprFPSinventory") { + this.setHintText(""); + } + if (this.bodySprite.texture.key !== this.anim.frames[this.anim.frame]){ + this.bodySprite.setTexture(this.anim.frames[this.anim.frame]); + } + } + */ + } + + if (this.panel !== null) { + this.panel.update(); + } + + if (this.conversation !== null) { + if (this.mode === PLAYERMODE.DIALOGUE) { + this.conversation.update(); + } + } + + this.conversationManager.update(); + } + + //this.debugOrientPitch.setText(this.dir.pitch); + //this.debugOrientYaw.setText(this.dir.yaw); + } + + jumpToPosition(_pos, _immediately = false) { + //use this to set a neew position even if the collision checks have moved the position around differently + //eg if a collision in x resolves in a trigger jumping the player, but collision resolve in z afterwards would reset that + this.pos.to.jump = true; + this.pos.to.x = _pos.x; + this.pos.to.y = _pos.y; + this.pos.to.z = _pos.z; + + if (_immediately === true) { + this.pos.x = this.pos.to.x; + this.pos.y = this.pos.to.y; + this.pos.z = this.pos.to.z; + this.pos.to.jump = false; + } + } + + setMode(_mode) { + this.mode = _mode; + switch (_mode) { + case PLAYERMODE.LOOK: + this.showUI(); + break; + case PLAYERMODE.INTERACT: + this.scene.hand.setMouseLock(false); + this.hideUI(); + break; + case PLAYERMODE.DIALOGUE: + this.scene.hand.setMouseLock(false); + this.hideUI(); + break; + default: + break; + } + } + + setMoveMode(_mode){ + if(_mode !== this.moveMode){ + this.moveMode = _mode; + switch(this.moveMode){ + case PLAYERMOVE.STAND://stand still - not stand up + this.end = 0; + this.bodySprite.setTexture(this.anim.frames[0]); + this.bodySprite.alpha = 1; + break; + case PLAYERMOVE.SIT: + this.eyeHeight = 20; + this.end = 0; + this.bodySprite.setTexture(this.anim.frames[0]); + this.bodySprite.alpha = 0; + break; + case PLAYERMOVE.WALK: + case PLAYERMOVE.RUN: + this.eyeHeight = 24;//32 + this.anim.frames = ["sprFPSwalk_0", "sprFPSwalk_1", "sprFPSwalk_2", "sprFPSwalk_3"]; + this.anim.end = 3; + this.bodySprite.alpha = 1; + break; + default: + break; + } + } + } + + setHintText(_text) { + this.lowerHint.setText(_text); + } + + setUseSprite(_spr = "sprInteract01"){ + this.useSprite.setTexture(_spr); + } + + setUseBox(_rect) { + this.showUsing = true; + this.useBox.clear(); + let th = 6; + + //draw faint scanlines + this.useBox.lineStyle(3, 0xffffff, 0.25);//0x00e436 + this.useBox.beginPath(); + for (let y = _rect.p0.y; y < _rect.p1.y; y++) { + if ((Math.floor(this.scene.game.config.height + y)) % th === Math.floor(this.useBoxAnim)) { + this.useBox.moveTo(_rect.p0.x, y); + this.useBox.lineTo(_rect.p1.x, y); + } + } + this.useBox.strokePath(); + + //draw box outline + this.useBox.lineStyle(1, 0xffffff, 1);//0x00e436 + this.useBox.beginPath(); + this.useBox.moveTo(_rect.p0.x, _rect.p0.y); + this.useBox.lineTo(_rect.p1.x, _rect.p0.y); + this.useBox.moveTo(_rect.p1.x, _rect.p0.y); + this.useBox.lineTo(_rect.p1.x, _rect.p1.y); + this.useBox.moveTo(_rect.p1.x, _rect.p1.y); + this.useBox.lineTo(_rect.p0.x, _rect.p1.y); + this.useBox.moveTo(_rect.p0.x, _rect.p1.y); + this.useBox.lineTo(_rect.p0.x, _rect.p0.y); + this.useBox.strokePath(); + + //advance useBoxAnim to let the scanlines roll + this.useBoxAnim += 0.5; + if (this.useBoxAnim >= th) { + this.useBoxAnim = 0; + } + + this.useBox.alpha = 1; + this.useSprite.alpha = 1;//maybe not show this + + this.handSprite.setTexture("sprFPSuse"); + } + + scrollInventory(_amt){ + this.inventory.position = Math.max(0, Math.min(this.inventory.position + _amt, this.inventory.items.length - 1)); + } + + setItemSprite(_asset = null, _atlas = null){ + if(this.itemSprite !== null){ + this.itemSprite.destroy(); + } + + if(_asset !== null){ + if(_atlas === null){ + _atlas = _asset; + _asset = 0; + } + this.itemSprite = this.scene.add.sprite(0, (this.scene.game.config.height * 0.5) - 32, _atlas, _asset); + this.itemSprite.depth = 1000; + } + } + + clearUseBox() { + this.showUsing = false; + this.useBox.clear(); + this.useSprite.alpha = 0; + this.handSprite.setTexture("sprFPSpoint"); + } + + hideUI(){ + this.bodySprite.alpha = 0; + this.handSprite.alpha = 0; + this.clearUseBox(); + this.setHintText(""); + this.lowerHint.alpha = 0; + } + + showUI(){ + if (this.moveMode !== PLAYERMOVE.SIT) { + this.bodySprite.alpha = 1; + } + this.handSprite.alpha = 1; + this.lowerHint.alpha = 1; + } + + gameControls(){ + let wantToMove = false; + + this.keyboardLook(); + if(this.mode === PLAYERMODE.LOOK){ + if(this.scene.hand.mouselock === false){ + this.scene.hand.setMouseLock(true); + } + this.mouseLook(); + + if(globalOrientation.alpha !== null){ + this.orientationLook(); + } + if (isMobile === true) { + this.touchLook(); + } + } + + this.dir.pitch = Math.max(-HALFPI, Math.min(HALFPI ,this.dir.pitch)); + + let toPos = { + x: this.pos.x, + y: this.pos.y, + z: this.pos.z + } + + if (Math.abs(INPUTS.stickLeft.horizontal) > 0.1) { + toPos.z -= (Math.cos(this.dir.yaw + HALFPI) * INPUTS.stickLeft.horizontal) * this.spd.normal; + toPos.x += (Math.sin(this.dir.yaw + HALFPI) * INPUTS.stickLeft.horizontal) * this.spd.normal; + wantToMove = true; + } + if (Math.abs(INPUTS.stickLeft.vertical) > 0.1) { + toPos.z -= (Math.cos(this.dir.yaw) * INPUTS.stickLeft.vertical) * (INPUTS.btnTriggerLeft.pressed ? this.spd.sprint : this.spd.normal); + toPos.x += (Math.sin(this.dir.yaw) * INPUTS.stickLeft.vertical) * (INPUTS.btnTriggerLeft.pressed ? this.spd.sprint : this.spd.normal); + wantToMove = true; + } + //touch controls move + if (isMobile === true) { + if (this.scene.hand.pressed === true) { + if (this.scene.hand.start.y > this.scene.game.config.height * -0.4 && this.scene.hand.start.y < this.scene.game.config.height * 0.4) { + if (this.scene.hand.start.x > this.scene.game.config.width * -0.33 && this.scene.hand.start.x < this.scene.game.config.width * 0.33) { + let amt = Math.max(-1, Math.min(1, (this.scene.hand.pos.y - this.scene.hand.start.y) * 0.01)); + if (this.hand.pos.y > 0) { + INPUTS.btnTriggerLeft.pressed = true; + } else { + INPUTS.btnTriggerLeft.pressed = false; + } + toPos.z -= (Math.cos(this.dir.yaw) * amt) * (INPUTS.btnTriggerLeft.pressed ? this.spd.sprint : this.spd.normal); + toPos.x += (Math.sin(this.dir.yaw) * amt) * (INPUTS.btnTriggerLeft.pressed ? this.spd.sprint : this.spd.normal); + wantToMove = true; + if (this.scene.hand.pos.y < this.scene.game.config.height * -0.1) {//also jump + if (this.vel.y === 0) { + this.vel.y = -2; + this.pos.y += this.vel.y; + } + } + } + } + } + } + + if (INPUTS.btnShoulderRight.pressed) { + this.pos.y -= 1; + } + if (INPUTS.btnShoulderLeft.pressed) { + this.pos.y += 1; + } + + //try to interact on mobile + let touchInteract = false; + if (isMobile === true) { + if (this.scene.hand.justReleased === true) { + if (this.scene.hand.start.y < this.scene.game.config.height * -0.4 || this.scene.hand.start.y > this.scene.game.config.height * 0.4) { + touchInteract = true; + } + } + } + + if (INPUTS.btnA.justReleased || this.scene.input.mouse.locked === true ? this.scene.hand.justReleased : false || touchInteract === true) { + //alert("wanted to interact") + } + + let returnColl = []; + returnColl = this.scene.geometryController.update( + [ + {//check ground at player position + pos: { + x: this.pos.x, + y: this.pos.y + this.eyeHeight, + z: this.pos.z + }, + dir: { + x: 0, + y: 1, + z: 0 + }, + hit: [] + }, {//check wall colllision global x axis + pos: { + x: toPos.x, + y: toPos.y - this.stepHeight, + z: toPos.z + }, + dir: { + x: 1, + y: 0, + z: 0 + }, + hit: [] + }, {//check wall colllision global z axis + pos: { + x: toPos.x, + y: toPos.y - this.stepHeight, + z: toPos.z + }, + dir: { + x: 0, + y: 0, + z: 1 + }, + hit: [] + } + ] + ); + /*if(this.scene.input.activePointer.isDown){ + console.log(returnColl); + }*/ + + //resolve collision with ground + if (returnColl[0].hit.length > 0) { + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[0].hit[0]; + for (let [i, n] of returnColl[0].hit.entries()) { + let d = Phaser.Math.Distance.Between(0, this.pos.y - this.stepHeight, 0, returnColl[0].hit[i].pt[1]); + if (d < dist) { + dist = d; + nearestHit = returnColl[0].hit[i]; + } + } + //returnColl[input point and direction].hit[nearest = 0].pt[coord x,y,z] + //teleport to ground + if(nearestHit.model.trigger.isTrigger === false){ + if(dist <= this.stepHeight){ + this.vel.y = 0; + this.pos.y = nearestHit.pt[1]; + }else{ + if (this.vel.y < this.gravity.terminal) { + this.vel.y += this.gravity.y; + } + this.pos.y += this.vel.y; + } + }else{ + nearestHit.model.updateTrigger(); + } + } + + //resolve hit in global x axis + if(returnColl[1].hit.length > 0){ + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[1].hit[0]; + for(let [i, n] of returnColl[1].hit.entries()){ + let d = Phaser.Math.Distance.Between(this.pos.x, this.pos.z, returnColl[1].hit[i].pt[0], returnColl[1].hit[i].pt[2]); + if(d < dist){ + dist = d; + nearestHit = returnColl[1].hit[i]; + } + } + if(dist < this.collisionRadius){ + //only move if you move away from the wall + if ((toPos.x < this.pos.x && this.pos.x < nearestHit.pt[0]) || (toPos.x > this.pos.x && this.pos.x > nearestHit.pt[0]) || nearestHit.model.trigger.isTrigger === true){ + this.pos.x = toPos.x; + if (nearestHit.model.trigger.isTrigger === true){ + nearestHit.model.updateTrigger(); + } + } + }else{ + //be free to move cause yoou are far away from wall + this.pos.x = toPos.x; + } + }else{ + //move because there is nothing out there + this.pos.x = toPos.x; + } + + if (returnColl[2].hit.length > 0) { + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[2].hit[0]; + for (let [i, n] of returnColl[2].hit.entries()) { + let d = Phaser.Math.Distance.Between(this.pos.x, this.pos.z, returnColl[2].hit[i].pt[0], returnColl[2].hit[i].pt[2]); + if (d < dist) { + dist = d; + nearestHit = returnColl[2].hit[i]; + } + } + if (dist < this.collisionRadius) { + //only move if you move away from the wall + if ((toPos.z < this.pos.z && this.pos.z < nearestHit.pt[2]) || (toPos.z > this.pos.z && this.pos.z > nearestHit.pt[2]) || nearestHit.model.trigger.isTrigger === true) { + this.pos.z = toPos.z; + if (nearestHit.model.trigger.isTrigger === true) { + nearestHit.model.updateTrigger(); + } + } + }else{ + //be free to move cause yoou are far away from wall + this.pos.z = toPos.z; + } + }else{ + //move because there is nothing out there + this.pos.z = toPos.z; + } + + this.isMoving = wantToMove; + if (wantToMove === true){ + this.setMoveMode(PLAYERMOVE.WALK); + if (INPUTS.btnTriggerLeft.pressed === true){ + this.setMoveMode(PLAYERMOVE.RUN); + } + }else{ + if(this.moveMode !== PLAYERMOVE.SIT){ + this.setMoveMode(PLAYERMOVE.STAND); + } + } + + //open menu + if (INPUTS.btnStart.justPressed === true){ + this.setMode(PLAYERMODE.INTERACT); + //this.panel = new PanelControlOptions(this); + this.panel = new PanelWelcome(this); + } + + + //look for models to interact with at center of screen if player click the mouse + let hits = []; + //hits = this.geometryController.getQuadsFromScreenspaceAt(this.input.activePointer.worldX, this.input.activePointer.worldY, false); + hits = this.scene.geometryController.getQuadsFromScreenspaceAt(0, 0, false); + if (hits.length > 0) { + hits = hits.sort((a, b) => a.depth - b.depth); + //if(hits[hits.length - 1].depth > -64){//interaction radius (moved that into eud.distance 7 lines lower) + this.scene.modelName = hits[hits.length - 1].modelId; + //this.debugTxt.setText(this.modelName); + + let model = this.scene.geometryController.getModelById(this.scene.modelName = hits[hits.length - 1].modelId); + if (model.interactable === true){ + if (eud.distance([this.pos.x, this.pos.y, this.pos.z], [model.pos.x, model.pos.y, model.pos.z]) < 24){ + this.setHintText(model.data.useText !== undefined ? model.data.useText : "click to use"); + this.setUseSprite(model.data.useSprite !== undefined ? model.data.useSprite : "sprInteract01"); + this.setUseBox(model.getScreenBounds()); + + if (isMobile === true) { + if (this.scene.hand.justReleased === true) { + if (this.scene.hand.lastPressedTime < 30) { + model.interact(); + } + } + } else { + if (this.scene.hand.justReleased || INPUTS.btnA.justReleased) { + model.interact(); + } + } + }else{ + this.setHintText(""); + this.clearUseBox(); + } + + }else{ + this.setHintText(""); + this.clearUseBox(); + } + } + + if (this.scene.hand.justReleased) { + if(this.scene.input.mouse.locked === false){ + this.scene.hand.setMouseLock(true); + } + //this.cam.zoomTween.restart(); + //log the playre position as a helper for manual object positioning in level files + if(this.scene.keys.q.isDown){ + console.log(this); + } + } + } + + keyboardLook(){ + if (this.scene.cursors.up.isDown) { + this.dir.pitch += this.dir.spd.pitch; + } + if (this.scene.cursors.down.isDown) { + this.dir.pitch -= this.dir.spd.pitch; + } + if (this.scene.cursors.right.isDown) { + if(this.scene.keys.q.isDown){ + this.dir.roll -= this.dir.spd.roll; + }else{ + this.dir.yaw -= this.dir.spd.yaw; + } + } + if (this.scene.cursors.left.isDown) { + if (this.scene.keys.q.isDown) { + this.dir.roll += this.dir.spd.roll; + } else { + this.dir.yaw += this.dir.spd.yaw; + } + } + } + + mouseLook(){ + if(this.scene.hand.vel.x !== 0){ + //this.dir.yaw = prevCamDir.yaw; + this.dir.yaw -= ((this.scene.hand.vel.x) * this.dir.spd.yaw); + } + if(this.scene.hand.vel.y !== 0){ + //this.dir.pitch = prevCamDir.pitch; + this.dir.pitch += ((this.scene.hand.vel.y) * this.dir.spd.pitch); + } + } + + orientationLook(){ + let arr = [globalOrientation.alpha, globalOrientation.beta, globalOrientation.gamma]; + for(let [i, a] of arr.entries()){ + if(a === null){ + arr[i] = 0; + } + //if(a >= 180){a -= 360} + //if(a < -180){a += 360} + arr[i] = a * Math.PI / 180; + } + + //this.dir.pitch = (arr[1] * -1) + (Math.PI * 0.5); + //this.dir.yaw = (arr[0]); + + let rotation = getEulerAngles(getRotationMatrix(globalOrientation.alpha, globalOrientation.beta, globalOrientation.gamma)); + let degtorad = Math.PI / 180; + + let toYaw = offsetOrientation.yaw - (rotation[2] * degtorad) + let toPitch = offsetOrientation.pitch - ((rotation[1] * degtorad) * -1); + + this.dir.yaw -= toYaw; + this.dir.pitch -= toPitch; + + offsetOrientation.yaw = (rotation[2] * degtorad); + offsetOrientation.pitch = ((rotation[1] * degtorad) * -1); + } + + touchLook() { + if (this.scene.hand.pressed === true) { + if (this.scene.hand.start.y > this.scene.game.config.height * -0.4 && this.scene.hand.start.y < this.scene.game.config.height * 0.4) { + if (this.scene.hand.pos.y > 0) { + let amt = (this.scene.hand.pos.x - this.scene.hand.start.x) * 0.0005; + this.dir.yaw -= amt; + } + if (this.scene.hand.start.x < this.scene.game.config.width * -0.33 || this.scene.hand.start.x > this.scene.game.config.width * 0.33) { + let amt = (this.scene.hand.pos.y - this.scene.hand.start.y) * 0.0005; + this.dir.pitch += amt; + } + } + } + } +} \ No newline at end of file diff --git a/src/3d/racing/shipManager.js b/src/3d/racing/shipManager.js new file mode 100644 index 0000000..f31fff2 --- /dev/null +++ b/src/3d/racing/shipManager.js @@ -0,0 +1,2048 @@ +export default class ShipManager { + constructor(_scene, _level, _id, _isPlayer = true, _isAI = false, _modelFile = null) { + this.scene = _scene; + this.level = _level; + this.id = _id; + this.isPlayer = _isPlayer; + this.isAI = _isAI; + this.modelFile = _modelFile; + this.name = "Player"; + this.character = null; + // + this.splineId = 0; + this.cameraSplineId = 0; + this.targetSplineId = 0; + this.referenceSplineId = 0; + this.bonusSplineId = 0; + this.temp = 0; + this.autopilot = false; + this.curveAmt = 0; + this.speedFactor = 0; + this.distToPerfectPitch = 0; + this.overSpeed = false; + this.scraping = false; + this.scrapingTime = 0; + this.overTemp = false; + this.position = -1; + this.raceProgress = 0; // = lap * trackleng + spline ID for position calculation + this.ignoreFinish = true;//ignore first finish line crossing and maybe also after the race when autppilot just drives you around + this.crossedFinish = true; + this.progressFinish = false;//add an offset to raceProgress when on the Start Finish Straight but not crossed the line yet + this.ignoreProgress = true; + //flightvars + this.flightRadius = 112; + this.flightRadiusLowerLimit = 32;//-112 + 32; + this.flightRadiusUpperLimit = 112; + this.speed = 0; + this.speedNormalized = 0; + this.speedMax = 16; + this.speedBonus = 0; + this.nearmissBoost = 1.5; + this.nearmissBoostCooldown = 0; + + this.slipstreaming = false; + this.slipstreamBoost = 1.1; + this.slipstreamTarget = null; + this.slipstreamLasting = 0; + this.slipsteamTime = 0; + + this.jumping = false; + this.jumpingLasting = 0; + + this.crashPoints = 0; + + this.wobble = { + pos: { + x: 0, + y: 0, + z: 0, + }, + dir: { + yaw: 0, + pitch: 0, + roll: 0 + } + } + + this.acceleration = 0.1; + this.deceleration = -0.05; + this.brakes = -0.2; + this.rollSpeed = 0; + this.rollSpeedMax = 1; + this.rollSpeedMin = -1; + this.rollAcceleration = 0.05; + this.rollDeceleration = 0.2; + this.angleToTrack = 0; + this.angleToTrackMod = 1; + this.targetModel = null; + this.pitch = { + current: 0, + target: 0, + delta: 0, + acceleration: 0.1, + deceleration: 0.05, + min: -1, + max: 1 + } + this.last = { + speedBonus: 0, + curveAmt: 0, + input: { + spd: 0, + roll: 0, + pitch: 0 + }, + keyInput: { + spd: 0, + roll: 0, + pitch: 0 + }, + fastestLap: 0 + } + this.ai = { + prefRoll: 1, + flippedRoll: 0, + lastRollGood: false, + lastGoodPrefRoll: 1, + waitRoll: 0, + curveRec: -9999, + curveSample: 0, + navStates: { + seek: 0, + wait: 1, + dodge: 2, + follow: 3, + cooling: 4 + }, + navState: 0, + aggression: 0, + + } + //camera + this.cameras = { + thirdPersonFollow: 0, + firstPersonCockpit: 1, + firstPersonBumper: 2, + thirdPersonOrbit: 3 + } + this.camera = this.cameras.firstPersonCockpit; + this.cameraFovs = [2.5, 3, 3.5, 4.5, 5]; + this.cameraFovEscalation = 0; + this.cameraSplineId = 0; + //input + this.input = { + spd: 0, + roll: 0, + rollSpd: 0.1, + pitch: 0, + previous: { + spd: 0, + roll: 0, + pitch: 0 + } + } + this.keyInput = { + spd: 0, + roll: 0, + rollSpd: 0.1, + pitch: 0, + previous: { + spd: 0, + roll: 0, + pitch: 0 + } + } + + this.gondula = this.scene.geometryController.loadModel("hoverShip gondula " + String(this.id), "modDebugTile", { x: 0, y: 0, z: 0 }); //modDebugArrow + //this.gondula.flags.draw = true; + + this.shipAnchor = this.scene.geometryController.loadModel("hoverShip anchor " + String(this.id), "modDebugTile", { x: 0, y: 96, z: 0 }); //modDebugArrow + //this.shipAnchor.flags.draw = true; + + let models = ["modHoverCarWipeOutStyle", "modHoverCarF1", "modHoverCarTinnemann00", "modHoverCarHapton00"]; + if (this.modelFile !== null) { + models = [this.modelFile] + } + this.ship = this.scene.geometryController.loadModel("hoverShip model " + String(this.id), models[Math.floor(Math.random() * models.length)], { x: 0, y: 96, z: 0 });//modHoverCarF1 modHoverCarWipeOutStyle + this.ship.flags.draw = true; + this.ship.depthMod = 48; + this.addCollisionBox(); + + this.shipAnchor.jumpToPosition({ + x: (this.gondula.pos.x + (this.gondula.transform.up.x * -this.flightRadius)), + y: (this.gondula.pos.y + (this.gondula.transform.up.y * -this.flightRadius)), + z: (this.gondula.pos.z + (this.gondula.transform.up.z * -this.flightRadius)) + }); + + //thrusters + this.thrusters = []; + for (let q of this.ship.quadData) { + if (q.frame === "texGlowSquareWhite00") { + this.thrusters.push(q); + } + } + + //lensflare + this.lensflares = []; + this.lensflares.push(this.scene.geometryController.loadModel("hovership lensflare " + String(this.id), "modLensflare", { x: 0, y: 0, z: 0 })); + this.lensflares[this.lensflares.length - 1].flags.draw = true; + this.lensflares[this.lensflares.length - 1].setDrawMode(DRAWMODE.BILLBOARD3D); + this.lensflares[this.lensflares.length - 1].depthMod = 64; + this.lensflares[this.lensflares.length - 1].quadData[0].alpha = 0.2; + + //trails + this.trails = []; + this.swooshOrigins = []; + this.shipSwooshOrigins = []; + this.trailLength = 10; + for (let q of this.ship.quadData) { + if (q.frame === "sprDebugTexture") { + this.shipSwooshOrigins.push(q); + this.swooshOrigins.push(this.scene.geometryController.loadModel("trail " + String(this.id) + " " + this.swooshOrigins.length, "modDebugTile", { x: 0, y: 0, z: 0 })); + this.swooshOrigins[this.swooshOrigins.length - 1].flags.draw = true; + this.swooshOrigins[this.swooshOrigins.length - 1].depthMod = 128;//todo: this causes issues + this.trails.push([this.swooshOrigins[this.swooshOrigins.length - 1].quadData[0]]); + + this.trails[this.trails.length - 1][0].setTexture("atlasAll", "flatPal00White"); + this.trails[this.trails.length - 1][0].alpha = 0.8; + //hide debug trail position on ship + this.shipSwooshOrigins[this.shipSwooshOrigins.length - 1].alpha = 0; + } + } + for (let j = 0; j < this.swooshOrigins.length; j++) {//<- number of swoosh Origins on ship (eg both wing tips) + let q = this.trails[j][0]; + for (let i = 0; i < this.trailLength; i++) { + this.swooshOrigins[j].addQuadFromData({ + type: q.type, + texture: q.texture, + frame: q.frame, + position: { + x: q.pos.x - this.swooshOrigins[j].pos.x, + y: q.pos.y - this.swooshOrigins[j].pos.y, + z: q.pos.z - this.swooshOrigins[j].pos.z, + }, + points: [ + { + x: q.points[0].x, + y: q.points[0].y, + z: q.points[0].z, + }, { + x: q.points[1].x, + y: q.points[1].y, + z: q.points[1].z, + }, { + x: q.points[2].x, + y: q.points[2].y, + z: q.points[2].z, + }, { + x: q.points[3].x, + y: q.points[3].y, + z: q.points[3].z, + } + ] + }); + this.trails[j].push(this.swooshOrigins[j].quadData[this.swooshOrigins[j].quadData.length - 1]); + this.swooshOrigins[j].quadData[this.swooshOrigins[j].quadData.length - 1].alpha = 1 - (i / (this.trailLength + 1)); + } + } + //init trail history + this.shipTrailHistory = []; + for (let [j, t] of this.trails.entries()) { + this.shipTrailHistory.push([]); + for (let q of t) { + this.shipTrailHistory[j].push(this.ship.getWorldPositionOfQuad(this.shipSwooshOrigins[j])); + } + } + this.trailTicker = 0; + + + //times + this.startTime = Date.now(); + this.elapsedTime = Date.now() - this.startTime; + this.lapTimes = []; + this.fastestLap = 0; + } + + setShipColor(_color) { + for (let q of this.ship.quadData) { + if (q.texture === "atlasPlating") { + let frame = q.frame; + // t e x P l a t i n g R e d 0 0 + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + let prStr = frame.substr(0, 10); + let nuStr = frame.substr(13, 2); + q.setTexture(q.texture, prStr + _color + nuStr); + } + } + } + + setShipModel(_file, _color = "Red") { + this.scene.geometryController.destroyModelById(this.ship.id); + this.ship = this.scene.geometryController.loadModel("hoverShip model " + String(this.id), _file, { x: 0, y: 96, z: 0 }); + this.ship.flags.draw = true; + this.ship.depthMod = 48; + this.addCollisionBox(); + + this.setShipColor(_color); + } + + destroy() { + this.scene.geometryController.destroyModelById(this.ship.id); + } + + addCollisionBox(_type = 0) { + switch (_type) { + case 0: + this.ship.addQuadFromData({ + type: "collisionQuad", + position: { + x: 0, y: 0, z: 0 + }, points: [{ + x: -24, y: 0 + 0, z: -64 + }, { + x: 24, y: 0 + 0, z: -64 + }, { + x: 24, y: -32 - 0, z: -64 + }, { + x: -24, y: -32 - 0, z: -64 + }] + }) + break; + default: + break; + } + } + + update() { + this.elapsedTime = Date.now() - this.startTime; + + //normalize transform + /* + this.gondula.transform.forward = gl_vec3.normalize(this.gondula.transform.forward, this.gondula.transform.forward); + this.gondula.transform.right = gl_vec3.normalize(this.gondula.transform.right, this.gondula.transform.right); + this.gondula.transform.up = gl_vec3.normalize(this.gondula.transform.up, this.gondula.transform.up); + + this.shipAnchor.transform.forward = gl_vec3.normalize(this.shipAnchor.transform.forward, this.shipAnchor.transform.forward); + this.shipAnchor.transform.right = gl_vec3.normalize(this.shipAnchor.transform.right, this.shipAnchor.transform.right); + this.shipAnchor.transform.up = gl_vec3.normalize(this.shipAnchor.transform.up, this.shipAnchor.transform.up); + + this.ship.transform.forward = gl_vec3.normalize(this.ship.transform.forward, this.ship.transform.forward); + this.ship.transform.right = gl_vec3.normalize(this.ship.transform.right, this.ship.transform.right); + this.ship.transform.up = gl_vec3.normalize(this.ship.transform.up, this.ship.transform.up); + */ + + /* + for(let [i, t] of this.trails.entries()){ + this.shipTrailHistory.push([]); + for(let q of t){ + this.shipTrailHistory[i].push(this.ship.getWorldPositionOfQuad(q)); + } + } + */ + //TODO breaks bc spline id 0-44 is not next lap yyet + this.raceProgress = (this.lapTimes.length * this.level.trackBuilder.spline.length) + this.splineId; + if (this.progressFinish === true) { + this.raceProgress += this.level.trackBuilder.spline.length; + } + } + + updateFromHangar() { + //if(this.gondula.pos.y > 0){ + //also change in lvlHangar if speed upwards changes + //this.gondula.jumpToPosition({x: this.gondula.pos.x, y: this.gondula.pos.y - (0.5 * this.scene.dt), z: this.gondula.pos.z}, true); + + //this is also in racing + this.cameraSplineId = this.splineId - 5; + if (this.cameraSplineId < 0) { + this.cameraSplineId += this.level.trackBuilder.spline.length; + } + this.targetSplineId = this.splineId + 1;//INFO looking further down with higher speed? + while (this.targetSplineId >= this.level.trackBuilder.spline.length) { + this.targetSplineId -= this.level.trackBuilder.spline.length; + } + let splineRef = this.level.trackBuilder.spline[this.targetSplineId]; + //until here in racing + + //move gonudla and ship + //todo: why do the enemies fly further? is this not fuzzy enough? + let d = eud.distance([this.gondula.pos.x, this.gondula.pos.y, this.gondula.pos.z], [this.level.trackBuilder.spline[this.splineId].x, this.level.trackBuilder.spline[this.splineId].y, this.level.trackBuilder.spline[this.splineId].z]); + //if(this.isPlayer === true){ + //console.log(d) + //} + if (d >= this.scene.dt) { + let spd = 0.5 * this.scene.dt; + this.gondula.jumpToPosition({ x: this.gondula.pos.x + (this.gondula.transform.up.x * spd), y: this.gondula.pos.y + (this.gondula.transform.up.y * spd), z: this.gondula.pos.z + (this.gondula.transform.up.z * spd) }, true); + this.shipAnchor.jumpToPosition({ x: this.gondula.pos.x + (this.gondula.transform.up.x * -96), y: this.gondula.pos.y + (this.gondula.transform.up.y * -96), z: this.gondula.pos.z + (this.gondula.transform.up.z * -96) }, true); + this.ship.jumpToPosition({ x: this.gondula.pos.x + (this.gondula.transform.up.x * -96), y: this.gondula.pos.y + (this.gondula.transform.up.y * -96), z: this.gondula.pos.z + (this.gondula.transform.up.z * -96) }, true); + } + + //this is also in racing + let posFactor = 0.25 * this.scene.dt;// 0.5 //Math.max(0.01, ((this.speed + this.speedBonus) / (this.speedMax + this.speedBonus))) * 0.5;//todo: at max speed it still jitters + let rotFactor = 0.05 * this.scene.dt; + //rotate ship Anchor to Gondula + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.shipAnchor.transform.toVectorArray(this.shipAnchor.transform.forward), + this.shipAnchor.transform.toVectorArray(splineRef.transform.forward) + ) + let rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.shipAnchor.transform.rotationQuat, targetRot, rotFactor); + this.shipAnchor.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.shipAnchor.transform.toVectorArray(this.shipAnchor.transform.right), + this.shipAnchor.transform.toVectorArray(this.gondula.transform.right) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.shipAnchor.transform.rotationQuat, targetRot, rotFactor); + this.shipAnchor.rotateByQuaternion(rot); + + //move and rotate ship model to actual ship anchor point + this.ship.jumpToPosition({ x: this.shipAnchor.pos.x, y: this.shipAnchor.pos.y, z: this.shipAnchor.pos.z }); + //rotate ship to Gondula + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.ship.transform.toVectorArray(this.ship.transform.forward), + this.ship.transform.toVectorArray(splineRef.transform.forward) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.ship.transform.rotationQuat, targetRot, rotFactor); + this.ship.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.ship.transform.toVectorArray(this.ship.transform.right), + this.ship.transform.toVectorArray(this.gondula.transform.right) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.ship.transform.rotationQuat, targetRot, rotFactor); + this.ship.rotateByQuaternion(rot); + //until here + //} + } + + updateRacing() { + + let invertedSpeedFactor = 1 - this.speedFactor;//(this.speed / (this.speedMax + this.speedBonus)); + + this.cameraSplineId = this.splineId - 5; + if (this.cameraSplineId < 0) { + this.cameraSplineId += this.level.trackBuilder.spline.length; + } + this.targetSplineId = this.splineId + 1;//INFO looking further down with higher speed? + while (this.targetSplineId >= this.level.trackBuilder.spline.length) { + this.targetSplineId -= this.level.trackBuilder.spline.length; + } + let splineRef = this.level.trackBuilder.spline[this.targetSplineId]; + + this.bonusSplineId = this.splineId + 5; + while (this.bonusSplineId >= this.level.trackBuilder.spline.length) { + this.bonusSplineId -= this.level.trackBuilder.spline.length; + } + + let bonusRef = this.level.trackBuilder.spline[this.bonusSplineId]; + + this.input.spd = 0; + this.input.roll = 0; + this.input.pitch = 0; + if (this.level.state === this.level.states.race) { + if (this.autopilot === false) { + this.inputPlayer(); + } else { + this.inputAI(bonusRef); + } + } + + if (this.slipstreamLasting <= 0) { + this.slipstreaming = false; + } else { + this.slipstreamLasting -= this.scene.dt; + this.slipsteamTime += this.scene.dt; + } + this.slipstreamTarget = null; + + if (this.jumpingLasting <= 0) { + this.jumping = false; + } else { + this.jumpingLasting -= this.scene.dt; + } + + if (this.nearmissBoostCooldown >= 0) { + this.nearmissBoostCooldown -= this.scene.dt; + if (this.nearmissBoostCooldown <= 0) { + //console.log("COOLDOWNED") + } + } + + this.last.speedBonus = this.speedBonus; + this.last.input.roll = this.input.roll; + this.last.curveAmt = this.curveAmt; + + //check Collisions + let collCheckArr = [ + {//check forward of ship + pos: { + x: this.ship.pos.x, + y: this.ship.pos.y, + z: this.ship.pos.z + }, + dir: { + x: this.shipAnchor.transform.forward.x, + y: this.shipAnchor.transform.forward.y, + z: this.shipAnchor.transform.forward.z + }, + hit: [] + }, {//check forward right of ship for booster + pos: { + x: this.ship.pos.x + (this.shipAnchor.transform.right.x * 48), + y: this.ship.pos.y + (this.shipAnchor.transform.right.y * 48), + z: this.ship.pos.z + (this.shipAnchor.transform.right.z * 48) + }, + dir: { + x: this.shipAnchor.transform.forward.x, + y: this.shipAnchor.transform.forward.y, + z: this.shipAnchor.transform.forward.z + }, + hit: [] + }, {//check forward left of ship for booster + pos: { + x: this.ship.pos.x + (this.shipAnchor.transform.right.x * -48), + y: this.ship.pos.y + (this.shipAnchor.transform.right.y * -48), + z: this.ship.pos.z + (this.shipAnchor.transform.right.z * -48) + }, + dir: { + x: this.shipAnchor.transform.forward.x, + y: this.shipAnchor.transform.forward.y, + z: this.shipAnchor.transform.forward.z + }, + hit: [] + }, {//check slipstream with curve amt + pos: { + x: this.ship.pos.x, + y: this.ship.pos.y, + z: this.ship.pos.z + }, + dir: { + x: this.shipAnchor.transform.forward.x + (this.shipAnchor.transform.up.x * this.curveAmt), + y: this.shipAnchor.transform.forward.y + (this.shipAnchor.transform.up.y * this.curveAmt), + z: this.shipAnchor.transform.forward.z + (this.shipAnchor.transform.up.z * this.curveAmt) + }, + hit: [] + } + ]; + //push stuff to collide with + let toCollideWith = []; + for (let o of this.level.trackBuilder.obstacles) { + if (o.data.id + 1 > this.splineId) { + toCollideWith.push(o); + } + //if (o.flags.update === true){ + //o.update(); + //} + } + for (let s of this.level.aiShips) { + if (s.id !== this.id) { + if (s.splineId > this.splineId) { + toCollideWith.push(s.ship); + } + } + } + if (this.isPlayer === false) { + if (this.level.playerShip.splineId > this.splineId) { + toCollideWith.push(this.level.playerShip.ship); + } + } + for (let m of toCollideWith) { + //if (m.flags.update === true){ + // m.update(); + //} + for (let q of m.collisionData) { + for (let c of collCheckArr) { + let hitData = this.scene.geometryController.collide(q, c); + if (hitData.pt !== null) { + hitData.model = m; + c.hit.push(hitData); + } + } + } + } + let alreadyColliding = false; + let distSpeed = this.speed * 2; + /*if (this.isPlayer === true) { + console.log(distSpeed) + }*/ + //let avoids = [0, 0, 0]; + let returnColl = collCheckArr; + //resolve collision with forward + if (returnColl[0].hit.length > 0) { + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[0].hit[0]; + for (let [i, n] of returnColl[0].hit.entries()) { + let d = eud.distance([this.ship.pos.x, this.ship.pos.y, this.ship.pos.z], returnColl[0].hit[i].pt) + if (d < dist) { + dist = d; + nearestHit = returnColl[0].hit[i]; + } + } + if (dist < 2048) { + //slipstreaming? //todo: set dist < slipstream wake / distance of that object (maybe additional check within 1024m) + if (nearestHit.model.data.slipstreamLength !== undefined) { + if (dist < nearestHit.model.data.slipstreamLength) { + //console.log(`slipstreaming: ${Math.floor(dist)}`); + this.slipstreaming = true; + this.slipstreamTarget = nearestHit.model; + this.slipstreamLasting = 60 * 3; + //TODO let the AI know you are slipstreaming + if (this.isPlayer === true) { + this.level.situation.actions.slipstream.who = nearestHit.model.data.name; + this.level.situation.actions.slipstream.priority += 1; + } else { + if (this.slipstreamTarget.data.name === "Player") {//"Player" // TODO does not work as of yet + this.level.situation.actions.slipstreamed.who = this.ship.data.name; + this.level.situation.actions.slipstream.priority += 1; + } + } + } + } + } + if (dist < 128 + distSpeed) { + alreadyColliding = true; + if (nearestHit.model.trigger.isTrigger === false) { + //console.log(returnColl[0]); + + if (this.speed > 0 && this.isPlayer) { + this.scene.soundManager.playRandomSound(this.scene.soundManager.bumpSound); + } + + this.crashPoints += 1; + + this.speed *= 0.75;//= 0; + if (this.speed <= 1) { + this.speed = 0; + } + this.input.spd = 0; + if (nearestHit.model.data.roll !== undefined && nearestHit.model.data.roll !== 0) { + this.input.roll = nearestHit.model.data.roll * 2; + } + if (this.isPlayer) { + //console.log(nearestHit.model.data.name); + if (nearestHit.model.data.name !== undefined) { + //set ui.racerReaction to hitted pilot + this.level.situation.actions.hit.who = nearestHit.model.data.name; + this.level.situation.actions.hit.priority += 2; + //let character = this.level.aiShips.filter(el => el.name === nearestHit.model.data.name)[0].character; + //this.level.ui.addReaction("charSheetExpressions", character.reactions.hit[Math.floor(Math.random() * character.reactions.hit.length)]); + } + } + + } else { + nearestHit.model.trigger.other = this; + nearestHit.model.updateTrigger(); + } + } + } + //check booster only if collision free in front (0) + if (alreadyColliding === false) { + //resolve collision with forward right and then left of ship for boost + for (let j = 1; j < 3; j++) { + if (returnColl[j].hit.length > 0) { + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[j].hit[0]; + for (let [i, n] of returnColl[j].hit.entries()) { + let d = eud.distance([returnColl[j].pos.x, returnColl[j].pos.y, returnColl[j].pos.z], returnColl[j].hit[i].pt) + if (d < dist) { + dist = d; + nearestHit = returnColl[j].hit[i]; + } + } + /*if(dist < 1024){ + avoids[j] = 1; + }*/ + if (dist < 128) { + if (nearestHit.model.trigger.isTrigger === false) { + if (this.speed > (this.speedMax * 0.25) && this.input.spd >= 0 && this.nearmissBoostCooldown <= 0) { + this.input.spd = 1; + this.speed = this.speed * this.nearmissBoost;//this.speedMax * this.nearmissBoost; + this.speed = Math.min(this.speed, this.speedMax * this.nearmissBoost); + + this.nearmissBoostCooldown = 60; + if (this.isPlayer === true) { + if (this.scene.cam.fov < 3.5) {//todo: find a good value for the boost effect + this.scene.cam.fov += 1 * this.scene.dt; + this.scene.cam.fov = Math.min(this.scene.cam.fov, 3.5); + } + //sound + this.scene.soundManager.playRandomSound(this.scene.soundManager.swooshSound); + } + } + } else { + //nearestHit.model.updateTrigger(); + } + } + } + } + //check if slipstreaming with curve calculated + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[3].hit[0]; + for (let [i, n] of returnColl[3].hit.entries()) { + let d = eud.distance([this.ship.pos.x, this.ship.pos.y, this.ship.pos.z], returnColl[3].hit[i].pt) + if (d < dist) { + dist = d; + nearestHit = returnColl[3].hit[i]; + } + } + if (dist < 2048) { + //slipstreaming? //todo: set dist < slipstream wake / distance of that object (maybe additional check within 1024m) + if (nearestHit.model.data.slipstreamLength !== undefined) { + if (dist < nearestHit.model.data.slipstreamLength) { + //console.log(`slipstreaming: ${Math.floor(dist)}`); + this.slipstreaming = true; + this.slipstreamTarget = nearestHit.model; + this.slipstreamLasting = 60 * 3; + } + } + } + } + + //find pitch to track to set bonus + let upVec = [//was gonudla before, but could work well with ship + bonusRef.x + (this.ship.transform.forward.x * 10) + (this.ship.transform.up.x * 10), + bonusRef.y + (this.ship.transform.forward.y * 10) + (this.ship.transform.up.y * 10), + bonusRef.z + (this.ship.transform.forward.z * 10) + (this.ship.transform.up.z * 10) + ] + let doVec = [ + bonusRef.x + (this.ship.transform.forward.x * 10) + (this.ship.transform.up.x * -10), + bonusRef.y + (this.ship.transform.forward.y * 10) + (this.ship.transform.up.y * -10), + bonusRef.z + (this.ship.transform.forward.z * 10) + (this.ship.transform.up.z * -10) + ] + let upDist = eud.distance(upVec, [bonusRef.x + (bonusRef.transform.forward.x), bonusRef.y + (bonusRef.transform.forward.y), bonusRef.z + (bonusRef.transform.forward.z)]); + let doDist = eud.distance(doVec, [bonusRef.x + (bonusRef.transform.forward.x), bonusRef.y + (bonusRef.transform.forward.y), bonusRef.z + (bonusRef.transform.forward.z)]); + let bonusAmt = (doDist - upDist); + bonusAmt = Math.max(-1, Math.min(bonusAmt, 1)); + let flingAmt = (doDist - upDist); + flingAmt = Math.max(-1, Math.min(flingAmt, 1)); + if (this.jumping === true) { + flingAmt -= 1 * this.speedFactor; + if (this.isPlayer) { + } + } + //INFO reference : this.ui.pitchLimit.y = 64 - (32 * this.playerShip.curveAmt) - (32 * this.playerShip.pitch.current) + //bonusAmt = 64 - (32 * this.playerShip.curveAmt) - (32 * this.playerShip.pitch.current)//<<< 32 is cooling in theory + this.distToPerfectPitch = 64 - (32 * this.curveAmt) - (32 * this.pitch.current) - (this.pitch.current * 32); + this.distToPerfectPitch = Math.max(-64, Math.min(this.distToPerfectPitch, 64)); + //console.log(this.distToPerfectPitch) //todo: this might be stupid ^^^^ + //this way <0 is heating >0 is cooling ~0 is speed gain zoon? + //bonusAmt = ((((this.distToPerfectPitch - 32) / 64) ) * -1); + bonusAmt = ((this.distToPerfectPitch / 64) * -1) + 0.5 + this.curveAmt;//INFO bot of these two lines dont quite work as intended - no jumping - too fast, too hot weird + + //scraping? + if (this.distToPerfectPitch <= 0) { + if (this.speed > 0) { + this.scraping = true; + this.scrapingTime += this.scene.dt * 0.001; + } + bonusAmt = Math.max(-8, this.scrapingTime * -1); + } else { + this.scraping = false; + this.scrapingTime = 0; + } + + if (this.slipstreaming === true) { + bonusAmt += this.slipstreamBoost; + } + + //move away from ideal height + //this.flightRadius += (bonusAmt * (this.speed * 0.25)) * this.scene.dt; + this.flightRadius += (flingAmt * (this.speed * 0.25)) * this.scene.dt; + //if(this.temp > 500){ + // this.flightRadius -= 10; + //} + let calmer = 1 * this.scene.dt; + this.flightRadius = Math.max(this.flightRadiusLowerLimit, Math.min(this.flightRadius + (calmer * Math.max(0.1, this.speedFactor)), this.flightRadiusUpperLimit)); + if (this.flightRadius >= this.flightRadiusUpperLimit) { + this.jumping = false; + } + this.speedBonus = this.speedMax * bonusAmt; + //this.speedBonus += 8;//INFO neutral on a streaight is -8 atm, +8 and making the bonus less aggressive could be helpful in general for a less twitchy feel + + + //find pitch to track from gondula to set navigation + upVec = [ + bonusRef.x + (this.gondula.transform.forward.x * 1) + (this.gondula.transform.up.x * 1), + bonusRef.y + (this.gondula.transform.forward.y * 1) + (this.gondula.transform.up.y * 1), + bonusRef.z + (this.gondula.transform.forward.z * 1) + (this.gondula.transform.up.z * 1) + ] + doVec = [ + bonusRef.x + (this.gondula.transform.forward.x * 1) + (this.gondula.transform.up.x * -1), + bonusRef.y + (this.gondula.transform.forward.y * 1) + (this.gondula.transform.up.y * -1), + bonusRef.z + (this.gondula.transform.forward.z * 1) + (this.gondula.transform.up.z * -1) + ] + upDist = eud.distance(upVec, [bonusRef.x + (bonusRef.transform.forward.x * 320), bonusRef.y + (bonusRef.transform.forward.y * 320), bonusRef.z + (bonusRef.transform.forward.z * 320)]); + doDist = eud.distance(doVec, [bonusRef.x + (bonusRef.transform.forward.x * 320), bonusRef.y + (bonusRef.transform.forward.y * 320), bonusRef.z + (bonusRef.transform.forward.z * 320)]); + let curveAmt = (doDist - upDist); + //curveAmt = Math.max(-1, Math.min(curveAmt * 0.005, 1)); + this.curveAmt = curveAmt; + + //apply sppeed and move accordingly + if (this.input.spd !== 0) { + if (this.speed > this.speedMax + this.speedBonus) { + this.input.spd = (this.acceleration * -2); + } + this.speed += this.input.spd; + this.speed = Math.max(0, this.speed); + //this.speed = Math.max(0, Math.min(this.speed, this.speedMax + this.speedBonus)); + + //console.log(splineRef) + //use right axis if you need roll as well, but if using forward, you just follow the track as intended any you can roll on your own later + let targetVec = [splineRef.x - this.gondula.pos.x, splineRef.y - this.gondula.pos.y, splineRef.z - this.gondula.pos.z]; + targetVec = gl_vec3.normalize(targetVec, targetVec); + + let targetRot = [0, 0, 0, 0]; + //console.log(targetVec) + targetRot = gl_quat.rotationTo(targetRot, + this.gondula.transform.toVectorArray(this.gondula.transform.forward), + //this.gondula.transform.toVectorArray( splineRef.transform.forward) + targetVec + ) + let rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.gondula.transform.rotationQuat, targetRot, 0.5); + this.gondula.rotateByQuaternion(rot); + + //this.gondula.rotateByQuaternion(targetRot); + //move gondula forward by spd + this.gondula.jumpToPosition({ + x: this.gondula.pos.x + ((targetVec[0] * this.speed) * this.scene.dt), + y: this.gondula.pos.y + ((targetVec[1] * this.speed) * this.scene.dt), + z: this.gondula.pos.z + ((targetVec[2] * this.speed) * this.scene.dt) + }); + + let criticalSpeed = (1 * this.speed) * this.scene.dt; + /*if(this.isPlayer === true){ + if(criticalSpeed >= 64){ + console.log(criticalSpeed); + }; + }*/ + + //check if reached target + let d = gl_vec3.distance(this.gondula.transform.toVectorArray(this.gondula.pos), [splineRef.x, splineRef.y, splineRef.z]); + //console.log(d) + if (d <= 64 /*this.speed * 1*/ /*64*/) { + let amt = Math.floor(criticalSpeed / 64) + 1; //jumjp further if speed exceeds the distance between splines + this.splineId += amt; + if (this.splineId >= this.level.trackBuilder.spline.length) { + this.splineId -= this.level.trackBuilder.spline.length; + this.crossedFinish = false; + } + if (this.splineId >= 0 && this.crossedFinish === false) { + //add length of track to raceProgress to prevent false positions + this.progressFinish = true; + } + if (this.splineId >= 44 && this.crossedFinish === false) { + if (this.ignoreFinish === false) { + this.crossedFinish = true; + this.progressFinish = false; + this.startNewLap(); + } else { + this.ignoreFinish = false; + } + } + //console.log("next point: " + String(this.splineId) + " / " + String(this.level.trackBuilder.spline.length)) + } + } + + + + //INFO original temp calc + if (this.speed > this.speedMax && this.slipstreaming === false) { + this.temp += 0.5 * this.scene.dt; + if (this.speedBonus < 3) { + if (this.scraping === false) { + this.temp -= 0.75 * this.scene.dt; + } + } + } else { + if (this.scraping === false) { + this.temp -= 1.1 * this.scene.dt; + } + } + + if (this.scraping === true) { + this.temp += (Math.max(0, Math.min(1, this.speed / this.speedMax)) * 1) * this.scene.dt; + } + + + this.temp = Math.max(0, Math.min(this.temp, 999)); + if (this.temp >= 999) { + this.speedBonus = 0; + } else { + } + + this.speedNormalized = this.speed / this.speedMax; + + + //roll the ship + if (this.input.roll !== 0) { + let kir = Math.abs(this.input.roll); + if (this.input.roll > 0) { + if (this.rollSpeed < this.rollSpeedMax) { + this.rollSpeed += this.rollAcceleration * this.scene.dt; + this.rollSpeed = Math.min(this.rollSpeed, this.rollSpeedMax * kir); + } + } + if (this.input.roll < 0) { + if (this.rollSpeed > this.rollSpeedMin) { + this.rollSpeed -= this.rollAcceleration * this.scene.dt; + this.rollSpeed = Math.max(this.rollSpeed, this.rollSpeedMin * kir); + } + } + } else { + if (this.rollSpeed < 0) { + this.rollSpeed += this.rollDeceleration * this.scene.dt; + this.rollSpeed = Math.min(this.rollSpeed, 0); + } + if (this.rollSpeed > 0) { + this.rollSpeed -= this.rollDeceleration * this.scene.dt; + this.rollSpeed = Math.max(this.rollSpeed, 0); + } + } + + if (this.scene.numkeys.nine.isDown) { + if (this.flightRadius > this.flightRadiusLowerLimit) { + this.flightRadius -= 1 * this.scene.dt; + } + } + if (this.scene.numkeys.three.isDown) { + //if(this.flightRadius < this.flightRadiusUpperLimit){ + this.flightRadius += 1 * this.scene.dt; + //} + } + + this.speedFactor = Math.max(0, Math.min((this.speed + this.speedBonus) / (this.speedMax + this.speedBonus), 1)); + if (this.speed > this.speedMax) { + this.overSpeed = true; + } else { + this.overSpeed = false; + } + //visual rotatons based on input + //INFO: ALERT //todo: rotateAroundAxis fucks up the heatzone indicator (distToPerfectPitch) and moving the ship (currently out commented and indented) is the crazy crashout + //todo: at least with pitchditch it might be broken maybe more + //INFO //todo: clamping pitch.current (and the visual heatzone indicator (pitchLimit) prevents hiccups, but might be a pflaster solution) + this.gondula.rotateAroundAxis(this.gondula.transform.toVectorArray(this.gondula.transform.forward), (Math.PI * 0.01) * (this.rollSpeed) * this.scene.dt); + //let ship look a bit ahead of corner on input + this.shipAnchor.rotateAroundAxis(this.gondula.transform.toVectorArray(this.gondula.transform.up), (Math.PI * 0.01) * (this.rollSpeed) * this.scene.dt); + this.ship.rotateAroundAxis(this.ship.transform.toVectorArray(this.ship.transform.forward), ((Math.PI * 0.005 * this.speedFactor)) * (this.rollSpeed) * this.scene.dt); + this.pitch.target = Math.max(this.pitch.min, Math.min(this.keyInput.pitch, this.pitch.max)); + this.pitch.delta = this.pitch.target - this.pitch.current; + this.pitch.current += this.pitch.delta * this.scene.dt; + this.pitch.current = Math.max(-1, Math.min(this.pitch.current, 1)); + let pitchditch = this.pitch.current * 0.01; + this.ship.rotateAroundAxis(this.ship.transform.toVectorArray(this.ship.transform.right), pitchditch); + //roll ship for cool drifting effect + this.ship.rotateAroundAxis(this.shipAnchor.transform.toVectorArray(this.shipAnchor.transform.forward), (Math.PI * -0.0075) * (this.rollSpeed) * this.scene.dt); + //experimentalthis.ship.rotateAroundAxis(this.shipAnchor.transform.toVectorArray(this.shipAnchor.transform.up), (Math.PI * 0.025) * (this.rollSpeed) * this.scene.dt); + + + //move Ship to gondula + let posFactor = 0.25 * this.scene.dt; // 0.5 //Math.max(0.01, ((this.speed + this.speedBonus) / (this.speedMax + this.speedBonus))) * 0.5;//todo: at max speed it still jitters + let rotFactor = 0.05 * this.scene.dt; //0.1 //Math.max(0.01, ((this.speed + this.speedBonus) / (this.speedMax + this.speedBonus)) * 0.1); + + if (this.speed < 0.01) { + //posFactor = 0.5; + //rotFactor = 0.1; + } + let deltaPos = { + x: ((this.gondula.pos.x + (this.gondula.transform.up.x * -this.flightRadius))) - this.shipAnchor.pos.x, + y: ((this.gondula.pos.y + (this.gondula.transform.up.y * -this.flightRadius))) - this.shipAnchor.pos.y, + z: ((this.gondula.pos.z + (this.gondula.transform.up.z * -this.flightRadius))) - this.shipAnchor.pos.z + } + this.shipAnchor.jumpToPosition({ + x: this.shipAnchor.pos.x + (deltaPos.x * posFactor), + y: this.shipAnchor.pos.y + (deltaPos.y * posFactor), + z: this.shipAnchor.pos.z + (deltaPos.z * posFactor) + }); + //rotate ship Anchor to Gondula + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.shipAnchor.transform.toVectorArray(this.shipAnchor.transform.forward), + this.shipAnchor.transform.toVectorArray(splineRef.transform.forward) + ) + let rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.shipAnchor.transform.rotationQuat, targetRot, rotFactor); + this.shipAnchor.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.shipAnchor.transform.toVectorArray(this.shipAnchor.transform.right), + this.shipAnchor.transform.toVectorArray(this.gondula.transform.right) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.shipAnchor.transform.rotationQuat, targetRot, rotFactor); + this.shipAnchor.rotateByQuaternion(rot); + + //move and rotate ship model to actual ship anchor point + let jitterPos = { x: 0, y: 0, z: 0 } + if (this.scraping === true) { + //todo: play scrape audio of player + let jitterMod = (this.speed / this.speedMax); + //jitterMod *= jitterMod; + if (jitterMod < 0) { + jitterMod = 0; + } + if (jitterMod > 1) { + jitterMod = 1; + } + jitterPos = { x: -(1 + (Math.random() * 2)) * jitterMod, y: -(3 + (Math.random() * 6)) * jitterMod, z: (-1 + (Math.random() * 2)) * jitterMod } + //(Math.max(0, Math.min(1, this.speed / this.speedMax)) * 1) * this.scene.dt; + } + this.ship.jumpToPosition({ x: this.shipAnchor.pos.x + jitterPos.x, y: this.shipAnchor.pos.y + jitterPos.y, z: this.shipAnchor.pos.z + jitterPos.z }); + //rotate ship to Gondula + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.ship.transform.toVectorArray(this.ship.transform.forward), + this.ship.transform.toVectorArray(splineRef.transform.forward) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.ship.transform.rotationQuat, targetRot, rotFactor); + this.ship.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.ship.transform.toVectorArray(this.ship.transform.right), + this.ship.transform.toVectorArray(this.gondula.transform.right) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.ship.transform.rotationQuat, targetRot, rotFactor); + this.ship.rotateByQuaternion(rot); + + //show ship trail + /*let tipL = { + x: this.ship.quadData[this.ship.quadData.length - 1].points[0].x + ((this.gondula.transform.forward.x * (1 + (-56 * (this.speed / this.speedMax)))) + (this.gondula.transform.right.x * 0) + (this.gondula.transform.up.x * -2)), + y: this.ship.quadData[this.ship.quadData.length - 1].points[0].y + ((this.gondula.transform.forward.y * (1 + (-56 * (this.speed / this.speedMax)))) + (this.gondula.transform.right.y * 0) + (this.gondula.transform.up.y * -2)), + z: this.ship.quadData[this.ship.quadData.length - 1].points[0].z + ((this.gondula.transform.forward.z * (1 + (-56 * (this.speed / this.speedMax)))) + (this.gondula.transform.right.z * 0) + (this.gondula.transform.up.z * -2)) + } + let tipR = { + x: this.ship.quadData[this.ship.quadData.length - 1].points[1].x + ((this.gondula.transform.forward.x * (1 + (-56 * (this.speed / this.speedMax)))) + (this.gondula.transform.right.x * 0) + (this.gondula.transform.up.x * -2)), + y: this.ship.quadData[this.ship.quadData.length - 1].points[1].y + ((this.gondula.transform.forward.y * (1 + (-56 * (this.speed / this.speedMax)))) + (this.gondula.transform.right.y * 0) + (this.gondula.transform.up.y * -2)), + z: this.ship.quadData[this.ship.quadData.length - 1].points[1].z + ((this.gondula.transform.forward.z * (1 + (-56 * (this.speed / this.speedMax)))) + (this.gondula.transform.right.z * 0) + (this.gondula.transform.up.z * -2)) + } + this.ship.quadData[this.ship.quadData.length - 1].points[3] = tipL; + this.ship.quadData[this.ship.quadData.length - 1].points[2] = tipR; + this.ship.quadData[this.ship.quadData.length - 2].points[3] = tipL; + this.ship.quadData[this.ship.quadData.length - 2].points[2] = tipR;*/ + for (let t of this.thrusters) { + //todo: get the saved original position of the vertex to move and add the move vector to keep the shape of the thruster to keep a cone shape + t.points[3].x = t.points[0].x + (this.gondula.transform.forward.x * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[3].y = t.points[0].y + (this.gondula.transform.forward.y * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[3].z = t.points[0].z + (this.gondula.transform.forward.z * (1 + (-56 * (this.speed / this.speedMax)))); + + t.points[2].x = t.points[1].x + (this.gondula.transform.forward.x * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[2].y = t.points[1].y + (this.gondula.transform.forward.y * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[2].z = t.points[1].z + (this.gondula.transform.forward.z * (1 + (-56 * (this.speed / this.speedMax)))); + } + + this.lensflares[this.lensflares.length - 1].jumpToPosition({ + x: this.ship.pos.x + (this.ship.transform.forward.x * -66) + (this.ship.transform.up.x * 22), + y: this.ship.pos.y + (this.ship.transform.forward.y * -66) + (this.ship.transform.up.y * 22), + z: this.ship.pos.z + (this.ship.transform.forward.z * -66) + (this.ship.transform.up.z * 22), + }, true); + this.lensflares[this.lensflares.length - 1].quadData[0].alpha = 1 * this.speedFactor;//0.2 + + //todo: save an array of previous tip positions (part of the model) and let quads dynamically stretch over them to form a growing trail + /*for(let t of this.trails){ + for(let i = t.length -1 ; i >= 0 ; i--){ + let p = t[i]; + p.points[3] = p.points[0]; + p.points[2] = p.points[1]; + } + }*/ + /*//my origin points + this.trails[0][0].points[0] + this.trails[0][0].points[1] + this.trails[1][0].points[0] + this.trails[1][0].points[1] + */ + + + this.trailTicker -= this.scene.dt; + for (let [j, t] of this.trails.entries()) { + if (this.trailTicker <= 0) { + for (let i = t.length - 1; i > 0; i--) { + this.shipTrailHistory[j][i] = this.shipTrailHistory[j][i - 1] + } + } + this.shipTrailHistory[j][0] = this.ship.getWorldPositionOfQuad(this.shipSwooshOrigins[j]); + for (let p of this.shipTrailHistory[j][0]) { + p.x += this.ship.pos.x; + p.y += this.ship.pos.y; + p.z += this.ship.pos.z; + } + } + + for (let [j, t] of this.trails.entries()) {//each trail + //this.swooshOrigins[j].jumpToPosition(this.ship.pos); + if (this.trailTicker <= 0) { + for (let i = t.length - 1; i > 0; i--) {//each trail quad / saved position + let q = t[i];//each quad + //jump end of trailpart to timesaved position + q.points[3].x = this.shipTrailHistory[j][i][0].x + this.shipTrailHistory[j][i][4].x; + q.points[3].y = this.shipTrailHistory[j][i][0].y + this.shipTrailHistory[j][i][4].y; + q.points[3].z = this.shipTrailHistory[j][i][0].z + this.shipTrailHistory[j][i][4].z; + q.points[2].x = this.shipTrailHistory[j][i][1].x + this.shipTrailHistory[j][i][4].x; + q.points[2].y = this.shipTrailHistory[j][i][1].y + this.shipTrailHistory[j][i][4].y; + q.points[2].z = this.shipTrailHistory[j][i][1].z + this.shipTrailHistory[j][i][4].z; + + //jump start of trailpart to timesaved previous position + q.points[0].x = this.shipTrailHistory[j][i - 1][0].x + this.shipTrailHistory[j][i - 1][4].x; + q.points[0].y = this.shipTrailHistory[j][i - 1][0].y + this.shipTrailHistory[j][i - 1][4].y; + q.points[0].z = this.shipTrailHistory[j][i - 1][0].z + this.shipTrailHistory[j][i - 1][4].z; + q.points[1].x = this.shipTrailHistory[j][i - 1][1].x + this.shipTrailHistory[j][i - 1][4].x; + q.points[1].y = this.shipTrailHistory[j][i - 1][1].y + this.shipTrailHistory[j][i - 1][4].y; + q.points[1].z = this.shipTrailHistory[j][i - 1][1].z + this.shipTrailHistory[j][i - 1][4].z; + } + } + //correct first trail part that is connected to the ship + //jump end of trailpart to timesaved position + t[0].points[3].x = this.shipTrailHistory[j][1][0].x + this.shipTrailHistory[j][1][4].x; + t[0].points[3].y = this.shipTrailHistory[j][1][0].y + this.shipTrailHistory[j][1][4].y; + t[0].points[3].z = this.shipTrailHistory[j][1][0].z + this.shipTrailHistory[j][1][4].z; + t[0].points[2].x = this.shipTrailHistory[j][1][1].x + this.shipTrailHistory[j][1][4].x; + t[0].points[2].y = this.shipTrailHistory[j][1][1].y + this.shipTrailHistory[j][1][4].y; + t[0].points[2].z = this.shipTrailHistory[j][1][1].z + this.shipTrailHistory[j][1][4].z; + + t[0].points[0].x = this.shipTrailHistory[j][0][0].x + this.shipTrailHistory[j][0][4].x; + t[0].points[0].y = this.shipTrailHistory[j][0][0].y + this.shipTrailHistory[j][0][4].y; + t[0].points[0].z = this.shipTrailHistory[j][0][0].z + this.shipTrailHistory[j][0][4].z; + t[0].points[1].x = this.shipTrailHistory[j][0][1].x + this.shipTrailHistory[j][0][4].x; + t[0].points[1].y = this.shipTrailHistory[j][0][1].y + this.shipTrailHistory[j][0][4].y; + t[0].points[1].z = this.shipTrailHistory[j][0][1].z + this.shipTrailHistory[j][0][4].z; + } + if (this.trailTicker <= 0) { + this.trailTicker = this.speed * 0.25; + } + + //after moving setters + let ref = this.level.trackBuilder.spline[this.splineId]; + if (ref.model !== null) { + //console.log(ref) + this.targetModel = ref.model; + //console.log(this.level.trackBuilder.spline[this.splineId]);//model.transfrom .roll .obstacles + //console.log(shipRight[0]) + } + if (this.targetModel !== null) { + let trackRight = [this.targetModel.transform.right.x, this.targetModel.transform.right.y, this.targetModel.transform.right.z]; + let shipRight = [this.gondula.transform.right.x, this.gondula.transform.right.y, this.gondula.transform.right.z]; + this.angleToTrack = gl_vec3.dot(trackRight, shipRight); + //console.log(this.angleToTrack) gondula + let trackUp = [this.targetModel.transform.up.x, this.targetModel.transform.up.y, this.targetModel.transform.up.z]; + let shipUp = [this.gondula.transform.up.x, this.gondula.transform.up.y, this.gondula.transform.up.z]; + this.angleToTrackMod = gl_vec3.dot(trackUp, shipRight); + } + + //todo: positional sound here + } + + updateDream() { + let splineRef = this.level.trackBuilder.spline[0]; + + this.gondula.jumpToPosition({ + x: this.gondula.pos.x, + y: this.gondula.pos.y, + z: this.gondula.pos.z + ((1 * this.speed) * this.scene.dt) + }); + + //move Ship to gondula + let posFactor = 0.25 * this.scene.dt;// 0.5 //Math.max(0.01, ((this.speed + this.speedBonus) / (this.speedMax + this.speedBonus))) * 0.5;//todo: at max speed it still jitters + let rotFactor = 0.05 * this.scene.dt;//0.1 //Math.max(0.01, ((this.speed + this.speedBonus) / (this.speedMax + this.speedBonus)) * 0.1); + + if (this.speed < 0.01) { + //posFactor = 0.5; + //rotFactor = 0.1; + } + let deltaPos = { + x: ((this.gondula.pos.x + (this.gondula.transform.up.x * -this.flightRadius))) - this.shipAnchor.pos.x, + y: ((this.gondula.pos.y + (this.gondula.transform.up.y * -this.flightRadius))) - this.shipAnchor.pos.y, + z: ((this.gondula.pos.z + (this.gondula.transform.up.z * -this.flightRadius))) - this.shipAnchor.pos.z + } + this.shipAnchor.jumpToPosition({ + x: this.shipAnchor.pos.x + (deltaPos.x * posFactor), + y: this.shipAnchor.pos.y + (deltaPos.y * posFactor), + z: this.shipAnchor.pos.z + (deltaPos.z * posFactor) + }); + + //rotate ship Anchor to Gondula + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.shipAnchor.transform.toVectorArray(this.shipAnchor.transform.forward), + this.shipAnchor.transform.toVectorArray(splineRef.transform.forward) + ) + let rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.shipAnchor.transform.rotationQuat, targetRot, rotFactor); + this.shipAnchor.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.shipAnchor.transform.toVectorArray(this.shipAnchor.transform.right), + this.shipAnchor.transform.toVectorArray(this.gondula.transform.right) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.shipAnchor.transform.rotationQuat, targetRot, rotFactor); + this.shipAnchor.rotateByQuaternion(rot); + + //move and rotate ship model to actual ship anchor point + this.ship.jumpToPosition({ x: this.shipAnchor.pos.x, y: this.shipAnchor.pos.y, z: this.shipAnchor.pos.z }); + //rotate ship to Gondula + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.ship.transform.toVectorArray(this.ship.transform.forward), + this.ship.transform.toVectorArray(splineRef.transform.forward) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.ship.transform.rotationQuat, targetRot, rotFactor); + this.ship.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.ship.transform.toVectorArray(this.ship.transform.right), + this.ship.transform.toVectorArray(this.gondula.transform.right) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.ship.transform.rotationQuat, targetRot, rotFactor); + this.ship.rotateByQuaternion(rot); + + for (let t of this.thrusters) { + //todo: get the saved original position of the vertex to move and add the move vector to keep the shape of the thruster to keep a cone shape + t.points[3].x = t.points[0].x + (this.gondula.transform.forward.x * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[3].y = t.points[0].y + (this.gondula.transform.forward.y * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[3].z = t.points[0].z + (this.gondula.transform.forward.z * (1 + (-56 * (this.speed / this.speedMax)))); + + t.points[2].x = t.points[1].x + (this.gondula.transform.forward.x * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[2].y = t.points[1].y + (this.gondula.transform.forward.y * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[2].z = t.points[1].z + (this.gondula.transform.forward.z * (1 + (-56 * (this.speed / this.speedMax)))); + } + + this.lensflares[this.lensflares.length - 1].jumpToPosition({ + x: this.ship.pos.x + (this.ship.transform.forward.x * -66) + (this.ship.transform.up.x * 22), + y: this.ship.pos.y + (this.ship.transform.forward.y * -66) + (this.ship.transform.up.y * 22), + z: this.ship.pos.z + (this.ship.transform.forward.z * -66) + (this.ship.transform.up.z * 22), + }, true); + this.lensflares[this.lensflares.length - 1].quadData[0].alpha = 1 * this.speedFactor;//0.2 + + this.trailTicker -= this.scene.dt; + for (let [j, t] of this.trails.entries()) { + if (this.trailTicker <= 0) { + for (let i = t.length - 1; i > 0; i--) { + this.shipTrailHistory[j][i] = this.shipTrailHistory[j][i - 1] + } + } + this.shipTrailHistory[j][0] = this.ship.getWorldPositionOfQuad(this.shipSwooshOrigins[j]); + for (let p of this.shipTrailHistory[j][0]) { + p.x += this.ship.pos.x; + p.y += this.ship.pos.y; + p.z += this.ship.pos.z; + } + } + + for (let [j, t] of this.trails.entries()) {//each trail + //this.swooshOrigins[j].jumpToPosition(this.ship.pos); + if (this.trailTicker <= 0) { + for (let i = t.length - 1; i > 0; i--) {//each trail quad / saved position + let q = t[i];//each quad + //jump end of trailpart to timesaved position + q.points[3].x = this.shipTrailHistory[j][i][0].x + this.shipTrailHistory[j][i][4].x; + q.points[3].y = this.shipTrailHistory[j][i][0].y + this.shipTrailHistory[j][i][4].y; + q.points[3].z = this.shipTrailHistory[j][i][0].z + this.shipTrailHistory[j][i][4].z; + q.points[2].x = this.shipTrailHistory[j][i][1].x + this.shipTrailHistory[j][i][4].x; + q.points[2].y = this.shipTrailHistory[j][i][1].y + this.shipTrailHistory[j][i][4].y; + q.points[2].z = this.shipTrailHistory[j][i][1].z + this.shipTrailHistory[j][i][4].z; + + //jump start of trailpart to timesaved previous position + q.points[0].x = this.shipTrailHistory[j][i - 1][0].x + this.shipTrailHistory[j][i - 1][4].x; + q.points[0].y = this.shipTrailHistory[j][i - 1][0].y + this.shipTrailHistory[j][i - 1][4].y; + q.points[0].z = this.shipTrailHistory[j][i - 1][0].z + this.shipTrailHistory[j][i - 1][4].z; + q.points[1].x = this.shipTrailHistory[j][i - 1][1].x + this.shipTrailHistory[j][i - 1][4].x; + q.points[1].y = this.shipTrailHistory[j][i - 1][1].y + this.shipTrailHistory[j][i - 1][4].y; + q.points[1].z = this.shipTrailHistory[j][i - 1][1].z + this.shipTrailHistory[j][i - 1][4].z; + } + } + //correct first trail part that is connected to the ship + //jump end of trailpart to timesaved position + t[0].points[3].x = this.shipTrailHistory[j][1][0].x + this.shipTrailHistory[j][1][4].x; + t[0].points[3].y = this.shipTrailHistory[j][1][0].y + this.shipTrailHistory[j][1][4].y; + t[0].points[3].z = this.shipTrailHistory[j][1][0].z + this.shipTrailHistory[j][1][4].z; + t[0].points[2].x = this.shipTrailHistory[j][1][1].x + this.shipTrailHistory[j][1][4].x; + t[0].points[2].y = this.shipTrailHistory[j][1][1].y + this.shipTrailHistory[j][1][4].y; + t[0].points[2].z = this.shipTrailHistory[j][1][1].z + this.shipTrailHistory[j][1][4].z; + + t[0].points[0].x = this.shipTrailHistory[j][0][0].x + this.shipTrailHistory[j][0][4].x; + t[0].points[0].y = this.shipTrailHistory[j][0][0].y + this.shipTrailHistory[j][0][4].y; + t[0].points[0].z = this.shipTrailHistory[j][0][0].z + this.shipTrailHistory[j][0][4].z; + t[0].points[1].x = this.shipTrailHistory[j][0][1].x + this.shipTrailHistory[j][0][4].x; + t[0].points[1].y = this.shipTrailHistory[j][0][1].y + this.shipTrailHistory[j][0][4].y; + t[0].points[1].z = this.shipTrailHistory[j][0][1].z + this.shipTrailHistory[j][0][4].z; + } + if (this.trailTicker <= 0) { + this.trailTicker = this.speed * 0.25; + } + } + + updateSelection(_delta, _slerpAmt = -1) { + this.targetSplineId = this.splineId + 1;//INFO looking further down with higher speed? + while (this.targetSplineId >= this.level.trackBuilder.spline.length) { + this.targetSplineId -= this.level.trackBuilder.spline.length; + } + let splineRef = this.level.trackBuilder.spline[this.targetSplineId]; + + let targetVec = [splineRef.x - this.gondula.pos.x, splineRef.y - this.gondula.pos.y, splineRef.z - this.gondula.pos.z]; + targetVec = gl_vec3.normalize(targetVec, targetVec); + + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.gondula.transform.toVectorArray(this.gondula.transform.forward), + targetVec + ) + this.gondula.rotateByQuaternion(targetRot); + //move gondula forward by spd + this.gondula.jumpToPosition({ + x: this.gondula.pos.x + ((targetVec[0] * this.speed) * this.scene.dt), + y: this.gondula.pos.y + ((targetVec[1] * this.speed) * this.scene.dt), + z: this.gondula.pos.z + ((targetVec[2] * this.speed) * this.scene.dt) + }); + + //check if reached target + let d = gl_vec3.distance(this.gondula.transform.toVectorArray(this.gondula.pos), [splineRef.x, splineRef.y, splineRef.z]); + if (d <= 64) { + //let amt = Math.floor(criticalSpeed/64) + 1; //jumjp further if speed exceeds the distance between splines + this.splineId += 1//amt; + if (this.splineId >= this.level.trackBuilder.spline.length) { + this.splineId -= this.level.trackBuilder.spline.length; + } + } + + //move Ship to gondula + let posFactor = 0.25 * this.scene.dt;// 0.5 //Math.max(0.01, ((this.speed + this.speedBonus) / (this.speedMax + this.speedBonus))) * 0.5;//todo: at max speed it still jitters + let rotFactor = 0.015 * this.scene.dt;//0.1 //Math.max(0.01, ((this.speed + this.speedBonus) / (this.speedMax + this.speedBonus)) * 0.1); + + if (this.speed < 0.01) { + //posFactor = 0.5; + //rotFactor = 0.1; + } + + if (_slerpAmt > 0) { + posFactor = 1; + rotFactor = 1; + } + + let deltaPos = { + x: ((this.gondula.pos.x + (this.gondula.transform.up.x * -this.flightRadius))) - this.shipAnchor.pos.x, + y: ((this.gondula.pos.y + (this.gondula.transform.up.y * -this.flightRadius))) - this.shipAnchor.pos.y, + z: ((this.gondula.pos.z + (this.gondula.transform.up.z * -this.flightRadius))) - this.shipAnchor.pos.z + } + this.shipAnchor.jumpToPosition({ + x: this.shipAnchor.pos.x + (deltaPos.x * posFactor), + y: this.shipAnchor.pos.y + (deltaPos.y * posFactor), + z: this.shipAnchor.pos.z + (deltaPos.z * posFactor) + }); + + //rotate ship Anchor to Gondula + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.shipAnchor.transform.toVectorArray(this.shipAnchor.transform.forward), + this.shipAnchor.transform.toVectorArray(splineRef.transform.forward) + ) + let rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.shipAnchor.transform.rotationQuat, targetRot, rotFactor); + this.shipAnchor.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.shipAnchor.transform.toVectorArray(this.shipAnchor.transform.right), + this.shipAnchor.transform.toVectorArray(this.gondula.transform.right) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.shipAnchor.transform.rotationQuat, targetRot, rotFactor); + this.shipAnchor.rotateByQuaternion(rot); + + //move and rotate ship model to actual ship anchor point + this.ship.jumpToPosition({ x: this.shipAnchor.pos.x, y: this.shipAnchor.pos.y, z: this.shipAnchor.pos.z }); + //rotate ship to Gondula + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.ship.transform.toVectorArray(this.ship.transform.forward), + this.ship.transform.toVectorArray(splineRef.transform.forward) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.ship.transform.rotationQuat, targetRot, rotFactor); + this.ship.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.ship.transform.toVectorArray(this.ship.transform.right), + this.ship.transform.toVectorArray(this.gondula.transform.right) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.ship.transform.rotationQuat, targetRot, rotFactor); + this.ship.rotateByQuaternion(rot); + + for (let t of this.thrusters) { + //todo: get the saved original position of the vertex to move and add the move vector to keep the shape of the thruster to keep a cone shape + t.points[3].x = t.points[0].x + (this.gondula.transform.forward.x * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[3].y = t.points[0].y + (this.gondula.transform.forward.y * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[3].z = t.points[0].z + (this.gondula.transform.forward.z * (1 + (-56 * (this.speed / this.speedMax)))); + + t.points[2].x = t.points[1].x + (this.gondula.transform.forward.x * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[2].y = t.points[1].y + (this.gondula.transform.forward.y * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[2].z = t.points[1].z + (this.gondula.transform.forward.z * (1 + (-56 * (this.speed / this.speedMax)))); + } + + this.lensflares[this.lensflares.length - 1].jumpToPosition({ + x: this.ship.pos.x + (this.ship.transform.forward.x * -66) + (this.ship.transform.up.x * 22), + y: this.ship.pos.y + (this.ship.transform.forward.y * -66) + (this.ship.transform.up.y * 22), + z: this.ship.pos.z + (this.ship.transform.forward.z * -66) + (this.ship.transform.up.z * 22), + }, true); + this.lensflares[this.lensflares.length - 1].quadData[0].alpha = 1 * this.speedFactor;//0.2 + + this.trailTicker -= this.scene.dt; + for (let [j, t] of this.trails.entries()) { + if (this.trailTicker <= 0) { + for (let i = t.length - 1; i > 0; i--) { + this.shipTrailHistory[j][i] = this.shipTrailHistory[j][i - 1] + } + } + this.shipTrailHistory[j][0] = this.ship.getWorldPositionOfQuad(this.shipSwooshOrigins[j]); + for (let p of this.shipTrailHistory[j][0]) { + p.x += this.ship.pos.x; + p.y += this.ship.pos.y; + p.z += this.ship.pos.z; + } + } + + for (let [j, t] of this.trails.entries()) {//each trail + //this.swooshOrigins[j].jumpToPosition(this.ship.pos); + if (this.trailTicker <= 0) { + for (let i = t.length - 1; i > 0; i--) {//each trail quad / saved position + let q = t[i];//each quad + //jump end of trailpart to timesaved position + q.points[3].x = this.shipTrailHistory[j][i][0].x + this.shipTrailHistory[j][i][4].x; + q.points[3].y = this.shipTrailHistory[j][i][0].y + this.shipTrailHistory[j][i][4].y; + q.points[3].z = this.shipTrailHistory[j][i][0].z + this.shipTrailHistory[j][i][4].z; + q.points[2].x = this.shipTrailHistory[j][i][1].x + this.shipTrailHistory[j][i][4].x; + q.points[2].y = this.shipTrailHistory[j][i][1].y + this.shipTrailHistory[j][i][4].y; + q.points[2].z = this.shipTrailHistory[j][i][1].z + this.shipTrailHistory[j][i][4].z; + + //jump start of trailpart to timesaved previous position + q.points[0].x = this.shipTrailHistory[j][i - 1][0].x + this.shipTrailHistory[j][i - 1][4].x; + q.points[0].y = this.shipTrailHistory[j][i - 1][0].y + this.shipTrailHistory[j][i - 1][4].y; + q.points[0].z = this.shipTrailHistory[j][i - 1][0].z + this.shipTrailHistory[j][i - 1][4].z; + q.points[1].x = this.shipTrailHistory[j][i - 1][1].x + this.shipTrailHistory[j][i - 1][4].x; + q.points[1].y = this.shipTrailHistory[j][i - 1][1].y + this.shipTrailHistory[j][i - 1][4].y; + q.points[1].z = this.shipTrailHistory[j][i - 1][1].z + this.shipTrailHistory[j][i - 1][4].z; + } + } + //correct first trail part that is connected to the ship + //jump end of trailpart to timesaved position + t[0].points[3].x = this.shipTrailHistory[j][1][0].x + this.shipTrailHistory[j][1][4].x; + t[0].points[3].y = this.shipTrailHistory[j][1][0].y + this.shipTrailHistory[j][1][4].y; + t[0].points[3].z = this.shipTrailHistory[j][1][0].z + this.shipTrailHistory[j][1][4].z; + t[0].points[2].x = this.shipTrailHistory[j][1][1].x + this.shipTrailHistory[j][1][4].x; + t[0].points[2].y = this.shipTrailHistory[j][1][1].y + this.shipTrailHistory[j][1][4].y; + t[0].points[2].z = this.shipTrailHistory[j][1][1].z + this.shipTrailHistory[j][1][4].z; + + t[0].points[0].x = this.shipTrailHistory[j][0][0].x + this.shipTrailHistory[j][0][4].x; + t[0].points[0].y = this.shipTrailHistory[j][0][0].y + this.shipTrailHistory[j][0][4].y; + t[0].points[0].z = this.shipTrailHistory[j][0][0].z + this.shipTrailHistory[j][0][4].z; + t[0].points[1].x = this.shipTrailHistory[j][0][1].x + this.shipTrailHistory[j][0][4].x; + t[0].points[1].y = this.shipTrailHistory[j][0][1].y + this.shipTrailHistory[j][0][4].y; + t[0].points[1].z = this.shipTrailHistory[j][0][1].z + this.shipTrailHistory[j][0][4].z; + } + if (this.trailTicker <= 0) { + this.trailTicker = this.speed * 0.25; + } + } + + setDraw(_bool) { + this.ship.flags.draw = _bool + for (let l of this.lensflares) { + l.flags.draw = _bool; + } + for (let s of this.swooshOrigins) { + s.flags.draw = _bool; + } + } + + startNewLap() { + //save and show last laptime + this.lapTimes.push({ + time: this.elapsedTime, + position: this.position + }); + //this.last.lapTime = this.elapsedTime + + //find fastest laptime + this.last.fastestLap = this.fastestLap; + let r = (60 * 60) * 1000; + for (let [i, l] of this.lapTimes.entries()) { + if (l.time < r) { + r = l.time; + this.fastestLap = i; + } + } + + if (this.isPlayer === true) { + if (this.level.raceMode === this.level.raceModes.canyon) { + this.level.raceModeData.playerIsHunter = !this.level.raceModeData.playerIsHunter; + this.level.startNewCanyon(); + } else { + this.level.startNewLap(); + } + } + + //start new lap time + this.startTime = Date.now(); + this.elapsedTime = Date.now() - this.startTime; + } + + restartOnFromSplineId(_splineId, _roll = 0) { + this.splineId = _splineId; + let splg = this.level.trackBuilder.spline[this.splineId]; + this.gondula.jumpToPosition({ x: splg.x, y: splg.y, z: splg.z }); + + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.gondula.transform.toVectorArray(this.gondula.transform.forward), + [0, 0, 1] + ) + this.gondula.rotateByQuaternion(targetRot); + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.gondula.transform.toVectorArray(this.gondula.transform.right), + [1, 0, 0] + ) + this.gondula.rotateByQuaternion(targetRot); + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.gondula.transform.toVectorArray(this.gondula.transform.up), + [0, -1, 0] + ) + this.gondula.rotateByQuaternion(targetRot); + + this.gondula.rotateAroundAxis(this.gondula.transform.toVectorArray(this.gondula.transform.forward), _roll); + + this.speed = 0; + + + //start from hangar? + if (this.level.startFromHangar === true) { + this.gondula.jumpToPosition({ x: this.gondula.pos.x + (this.gondula.transform.up.x * -244), y: this.gondula.pos.y + (this.gondula.transform.up.y * -244), z: this.gondula.pos.z + (this.gondula.transform.up.z * -244) });//y 468-128-96 init start + this.shipAnchor.jumpToPosition({ x: this.gondula.pos.x + (this.gondula.transform.up.x * -96), y: this.gondula.pos.y + (this.gondula.transform.up.y * -96), z: this.gondula.pos.z + (this.gondula.transform.up.z * -96) }, true); + this.ship.jumpToPosition({ x: this.gondula.pos.x + (this.gondula.transform.up.x * -96), y: this.gondula.pos.y + (this.gondula.transform.up.y * -96), z: this.gondula.pos.z + (this.gondula.transform.up.z * -96) }, true); + } + } + + jumpToSplineId(_splineId, _roll = 0) { + this.splineId = _splineId; + let splg = this.level.trackBuilder.spline[this.splineId]; + this.gondula.jumpToPosition({ x: splg.x, y: splg.y, z: splg.z }); + + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.gondula.transform.toVectorArray(this.gondula.transform.forward), + [0, 0, 1] + ) + this.gondula.rotateByQuaternion(targetRot); + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.gondula.transform.toVectorArray(this.gondula.transform.right), + [1, 0, 0] + ) + this.gondula.rotateByQuaternion(targetRot); + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.gondula.transform.toVectorArray(this.gondula.transform.up), + [0, -1, 0] + ) + this.gondula.rotateByQuaternion(targetRot); + + this.gondula.rotateAroundAxis(this.gondula.transform.toVectorArray(this.gondula.transform.forward), _roll); + + this.speed = 0; + + + //start from hangar? + if (this.level.startFromHangar === true) { + this.gondula.jumpToPosition({ x: this.gondula.pos.x + (this.gondula.transform.up.x * -244), y: this.gondula.pos.y + (this.gondula.transform.up.y * -244), z: this.gondula.pos.z + (this.gondula.transform.up.z * -244) });//y 468-128-96 init start + this.shipAnchor.jumpToPosition({ x: this.gondula.pos.x + (this.gondula.transform.up.x * -96), y: this.gondula.pos.y + (this.gondula.transform.up.y * -96), z: this.gondula.pos.z + (this.gondula.transform.up.z * -96) }, true); + this.ship.jumpToPosition({ x: this.gondula.pos.x + (this.gondula.transform.up.x * -96), y: this.gondula.pos.y + (this.gondula.transform.up.y * -96), z: this.gondula.pos.z + (this.gondula.transform.up.z * -96) }, true); + } + } + + inputPlayer() { + + let gamepad = null; + gamepad = navigator.getGamepads()[Math.max(0, gamepadsConnected - 1)]; + if (gamepad === undefined) { + gamepad = null; + } + + this.keyInput.spd = 0; + //this.keyInput.roll = 0; + this.keyInput.pitch = 0; + + //acceleration + if (INPUTS.triggerRight.amount > 0.1) { + this.input.spd = this.acceleration; + this.keyInput.spd = 1; + } else { + this.input.spd = this.deceleration; + if (INPUTS.triggerLeft.amount > 0.1) {//redundant? + this.keyInput.spd = -1; + } + } + if (INPUTS.triggerLeft.amount > 0.1) { + this.input.spd = this.brakes; + this.keyInput.spd = -1; + } + + //pitch with mouse //todo: pitch also with gamepad + if (this.scene.hand.useControllerMouse === false) { + this.keyInput.pitch = Math.max(-1, Math.min(this.scene.hand.pos.y * 0.01, 1)); + } else { + //gamepad + //console.log(INPUTS.stickRight.vertical) + if (gamepad !== null) { //todo INFO + if options enabled gamepad control + let sra = Math.abs(INPUTS.stickRight.vertical); + let sla = Math.abs(INPUTS.stickLeft.vertical); + this.keyInput.pitch = (sra > sla ? (INPUTS.stickRight.vertical * -1) : (INPUTS.stickLeft.vertical * -1)); + } + } + + //if (this.keyInput.pitch <= -0.5 && this.jumping === false) { + if (this.jumping === false) { + if (this.keyInput.pitch - this.keyInput.previous.pitch < -0.5) { + this.jumping = true; + this.jumpingLasting = 30; + } + } + + + //instant acceleration with bonus + //todo: slipstreaming is the same, but without better acceleration + /* + if(this.scene.keys.space.isDown){ + this.input.spd = 1; + this.speedBonus = 4; + this.speed += 4; + this.speed = Math.min(this.speedMax + this.speedBonus, this.speed); + this.speed = this.speedMax + this.speedBonus; + }else{ + this.speedBonus = 0; + } + */ + + //roll + if (this.scene.hand.useControllerMouse === false) { + if (INPUTS.stickLeft.horizontal !== 0) { + if (INPUTS.stickLeft.horizontal > 0) { + if (this.keyInput.roll < 1) { + this.keyInput.roll += 0.02 * this.scene.dt; + this.keyInput.roll = Math.min(this.keyInput.roll, 1); + } + } + if (INPUTS.stickLeft.horizontal < 0) { + if (this.keyInput.roll > -1) { + this.keyInput.roll -= 0.02 * this.scene.dt; + this.keyInput.roll = Math.max(this.keyInput.roll, -1); + } + } + } else { + if (this.keyInput.roll < 0) { + this.keyInput.roll += 0.1 * this.scene.dt; + this.keyInput.roll = Math.min(this.keyInput.roll, 0); + } + if (this.keyInput.roll > 0) { + this.keyInput.roll -= 0.1 * this.scene.dt; + this.keyInput.roll = Math.max(this.keyInput.roll, 0); + } + } + this.input.roll = this.keyInput.roll; + } else { + this.input.roll = Math.abs(INPUTS.stickLeft.horizontal) > 0.2 ? INPUTS.stickLeft.horizontal : 0; + } + + + if (this.scene.hand.pressed === true && isMobile === true) { + //todo: maybe only look around with touch when touching in upper area + let hAmt = (this.scene.hand.pos.x - this.scene.hand.start.x) * 0.005; + if (hAmt > 0.05 || hAmt < 0.05) { + this.input.roll += hAmt; + } + this.input.roll = Math.max(-1, Math.min(1, this.input.roll)); + + let vAmt = (this.scene.hand.pos.y - this.scene.hand.start.y) * 0.005; + if (vAmt > 0.05) { + this.input.spd = this.brakes; + this.keyInput.spd = -1; + this.keyInput.pitch = -1; + } else { + this.input.spd = this.acceleration; + this.keyInput.spd = 1; + this.keyInput.pitch = 1; + } + + this.scene.hand.start.x = this.scene.hand.pos.x; + //this.scene.hand.start.y = this.scene.hand.pos.y; + } + if (this.scene.hand.pressed === false && isMobile === true) { + this.input.spd = this.deceleration; + this.keyInput.spd = -1; + } + + //let curveDelta = Math.max(-1, Math.min((this.last.curveAmt - this.curveAmt), 1)); + /*if(this.curveAmt > this.ai.curveRec){ + this.ai.curveRec = this.curveAmt; + console.log("new rec"); + }else if(this.curveAmt < this.ai.curveRec){ + console.log("wrong dir") + this.ai.curveRec = -9999; + }*/ + //if(Math.abs(curveDelta) > 0.12){ + //console.log(curveDelta) //true is good + //} + //console.log(this.curveAmt) + //console.log(this.last.speedBonus - this.speedBonus) + //console.log(this.curveAmt > this.last.curveAmt) + //console.log(this.last.curveAmt - this.curveAmt) + // + + this.keyInput.previous.pitch = this.keyInput.pitch; + this.keyInput.previous.spd = this.keyInput.spd; + this.keyInput.previous.roll = this.keyInput.roll; + } + + inputAI(_bonusRef) { + //dumb forward + this.input.spd = this.acceleration; + this.keyInput.spd = 1; + //this.input.roll = 0; + //this.keyInput.pitch = 0; + + let keyThink = { + spd: 0, + roll: 0, + pitch: 0 + } + + + + let avoid = [0, 0, 0] + //check Collisions + let collCheckArr = [ + {//check forward of ship + pos: { + x: this.shipAnchor.pos.x, + y: this.shipAnchor.pos.y, + z: this.shipAnchor.pos.z + }, + dir: { + x: this.shipAnchor.transform.forward.x, + y: this.shipAnchor.transform.forward.y, + z: this.shipAnchor.transform.forward.z + }, + hit: [] + }, {//check forward right of ship for booster + pos: { + x: this.shipAnchor.pos.x + (this.shipAnchor.transform.right.x * 48), + y: this.shipAnchor.pos.y + (this.shipAnchor.transform.right.y * 48), + z: this.shipAnchor.pos.z + (this.shipAnchor.transform.right.z * 48) + }, + dir: { + x: this.shipAnchor.transform.forward.x, + y: this.shipAnchor.transform.forward.y, + z: this.shipAnchor.transform.forward.z + }, + hit: [] + }, {//check forward left of ship for booster + pos: { + x: this.shipAnchor.pos.x + (this.shipAnchor.transform.right.x * -48), + y: this.shipAnchor.pos.y + (this.shipAnchor.transform.right.y * -48), + z: this.shipAnchor.pos.z + (this.shipAnchor.transform.right.z * -48) + }, + dir: { + x: this.shipAnchor.transform.forward.x, + y: this.shipAnchor.transform.forward.y, + z: this.shipAnchor.transform.forward.z + }, + hit: [] + } + ]; + let toCollideWith = []; + for (let o of this.level.trackBuilder.obstacles) { + if (o.data.id + 1 > this.splineId) { + if (o.trigger.isTrigger === false) { + toCollideWith.push(o); + } + } + } + for (let m of toCollideWith) { + if (m.flags.update === true) { + //m.update(); + //INFOalready updated in the actual update + } + for (let q of m.collisionData) { + for (let c of collCheckArr) { + let hitData = this.scene.geometryController.collide(q, c); + if (hitData.pt !== null) { + hitData.model = m; + c.hit.push(hitData); + } + } + } + } + let alreadyColliding = false; + let returnColl = collCheckArr; + //resolve collision with forward + if (returnColl[0].hit.length > 0) { + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[0].hit[0]; + for (let [i, n] of returnColl[0].hit.entries()) { + let d = eud.distance([this.shipAnchor.pos.x, this.shipAnchor.pos.y, this.shipAnchor.pos.z], returnColl[0].hit[i].pt) + if (d < dist) { + dist = d; + nearestHit = returnColl[0].hit[i]; + } + } + if (dist < 2024) { + avoid[0] = dist; + } + if (dist < 128) { + alreadyColliding = true; + if (nearestHit.model.trigger.isTrigger === false) { + //console.log(returnColl[0]); + /* + if(this.speed > 0){ + this.scene.soundManager.playRandomSound(this.scene.soundManager.bumpSound); + } + + this.input.spd = 0; + this.speed = 0; + if(nearestHit.model.data.roll !== undefined){ + this.input.roll = nearestHit.model.data.roll * 2; + }*/ + + } else { + //nearestHit.model.updateTrigger(); + } + } + } + //check booster only if collision free + if (alreadyColliding === false) { + //resolve collision with forward right and then left of ship for boost + for (let j = 1; j < 3; j++) { + if (returnColl[j].hit.length > 0) { + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[j].hit[0]; + for (let [i, n] of returnColl[j].hit.entries()) { + let d = eud.distance([returnColl[j].pos.x, returnColl[j].pos.y, returnColl[j].pos.z], returnColl[j].hit[i].pt) + if (d < dist) { + dist = d; + nearestHit = returnColl[j].hit[i]; + } + } + if (dist < 2024) { + avoid[j] = dist; + } + if (dist < 128) { + if (nearestHit.model.trigger.isTrigger === false) { + /*if(this.speed > (this.speedMax * 0.25) && this.input.spd >= 0){ + this.input.spd = 1; + this.speed = this.speedMax * this.nearmissBoost; + if(this.isPlayer === true){ + if(this.scene.cam.fov < 3.5){//todo: find a good value for the boost effect + this.scene.cam.fov += 1 * this.scene.dt; + this.scene.cam.fov = Math.min(this.scene.cam.fov, 3.5); + } + //sound + this.scene.soundManager.playRandomSound(this.scene.soundManager.swooshSound); + } + }*/ + } else { + //nearestHit.model.updateTrigger(); + } + } + } + } + } + + //switch to dodge mode if obstacle comes up + if (avoid[0] > 0 || avoid[1] > 0 || avoid[2] > 0) { + this.ai.navState = this.ai.navStates.dodge; + } + + //smaller than 0 delta is good + let curveDelta = this.last.curveAmt - this.curveAmt;//Math.max(-1, Math.min((this.last.curveAmt - this.curveAmt) , 1)); + let speedDelta = this.last.speedBonus - this.speedBonus; + //cooling strategy? + /*if(curveDelta > 0){ + this.input.roll = -curveDelta; + }*/ + + /* + //todo: best one yet + this.input.roll = this.ai.prefRoll; + if(curveDelta > 0){ + if(this.ai.waitRoll <= 0){ + this.ai.prefRoll *= -1; + this.input.roll = 0; + //wait a bit until switching roll direction again + if(this.curveAmt > 0.01){ + this.ai.waitRoll = 1; + }else{ + this.ai.waitRoll = 15; + } + }else{ + this.ai.waitRoll -= 1 * this.scene.dt; + } + } + */ + switch (this.ai.navState) { + case this.ai.navStates.seek: + //todo: works okay-ish but still gets overpowered by curveAmt delta fluctuations when already on right track or halfway between good or bad + //todo: because the fluctuation values are as small as a roll would be + + if (this.curveAmt > this.ai.curveRec) { + this.ai.curveRec = this.curveAmt; + //this.input.roll = this.ai.prefRoll; + keyThink.roll = this.ai.prefRoll; + this.ai.lastGoodPrefRoll = this.ai.prefRoll; + //console.log(curveDelta) + } + if (curveDelta > 0 && curveDelta < 0.003) { + //console.log("flipping") + //this.ai.prefRoll *= -1; + this.ai.prefRoll = this.ai.lastGoodPrefRoll * -1; + } + if (this.curveAmt < 0) { + this.ai.curveRec = -9999; + //console.log("wrong side") + } else { + this.ai.waitRoll -= 1 * this.scene.dt; + if (this.ai.waitRoll <= 0) { + this.ai.waitRoll = 30; + this.ai.curveRec = -9999; + } + } + this.aiFindPitch(); + + break; + case this.ai.navStates.wait: + this.ai.waitRoll -= 1 * this.scene.dt; + if (this.ai.waitRoll <= 0 || curveDelta >= 2) { + if (curveDelta > 2) { + //console.log("curve changed > seek"); + } + this.ai.navState = this.ai.navStates.seek; + this.ai.curveRec = -9999; + } + this.aiFindPitch(); + break; + case this.ai.navStates.dodge: + //dodge + let finishedDodging = true; + if (avoid[0] > 0) {//middle + //this.input.roll = this.ai.prefRoll; + keyThink.roll = this.ai.prefRoll; + if (avoid[0] < 1024) { + this.input.spd = this.brakes; + } else { + this.input.spd = this.deceleration; + } + this.keyInput.spd = -1; + this.aiFindPitch(false);//this.keyInput.pitch = -1; + //console.log("collision happening or imminent") + finishedDodging = false; + } + else if (avoid[1] > 0) {//right + //this.input.roll = -1; + keyThink.roll = -1; + this.ai.prefRoll = -1; + this.input.spd = this.acceleration; + this.keyInput.spd = 1; + this.aiFindPitch();//this.keyInput.pitch = 1; + //console.log("left") + finishedDodging = false; + } + else if (avoid[2] > 0) {//left + //this.input.roll = 1; + keyThink.roll = 1; + this.ai.prefRoll = 1; + this.input.spd = this.acceleration; + this.keyInput.spd = 1; + this.aiFindPitch();//this.keyInput.pitch = 1; + //console.log("right") + finishedDodging = false; + } + if (finishedDodging === true) { + this.ai.navState = this.ai.navStates.seek; + } + break; + default: + break; + } + + + this.aiFindRoll(keyThink.roll); + } + + aiFindRoll(_thinkRoll) { + if (_thinkRoll !== 0) { + if (_thinkRoll > 0) { + if (this.keyInput.roll < 1) { + this.keyInput.roll += 0.02 * this.scene.dt; + this.keyInput.roll = Math.min(this.keyInput.roll, 1); + } + } + if (_thinkRoll < 0) { + if (this.keyInput.roll > -1) { + this.keyInput.roll -= 0.02 * this.scene.dt; + this.keyInput.roll = Math.max(this.keyInput.roll, -1); + } + } + } else { + if (this.keyInput.roll < 0) { + this.keyInput.roll += 0.1 * this.scene.dt; + this.keyInput.roll = Math.min(this.keyInput.roll, 0); + } + if (this.keyInput.roll > 0) { + this.keyInput.roll -= 0.1 * this.scene.dt; + this.keyInput.roll = Math.max(this.keyInput.roll, 0); + } + } + this.input.roll = this.keyInput.roll; + } + + aiFindPitch(_allowHeat = true) { + //let distToPerfectPitchPlanned = 64 - (32 * this.curveAmt) - (32 * this.pitch.current) - (this.pitch.current * 32); + //this.distToPerfectPitch = Math.max(-64, Math.min(distToPerfectPitchPlanned, 64)); + + if (_allowHeat === true) { + if (this.distToPerfectPitch > 1) { + this.keyInput.pitch += 0.001 * this.scene.dt; + } else { + this.keyInput.pitch -= 0.01 * this.scene.dt; + } + } else { + if (this.distToPerfectPitch > 32) { + this.keyInput.pitch += 0.001 * this.scene.dt; + } else { + this.keyInput.pitch -= 0.01 * this.scene.dt; + } + } + } +} diff --git a/src/3d/racing/shipManagerBackup.js b/src/3d/racing/shipManagerBackup.js new file mode 100644 index 0000000..69c34b0 --- /dev/null +++ b/src/3d/racing/shipManagerBackup.js @@ -0,0 +1,1663 @@ +export default class ShipManager{ + constructor(_scene, _level, _id, _isPlayer = true, _isAI = false, _modelFile = null){ + this.scene = _scene; + this.level = _level; + this.id = _id; + this.isPlayer = _isPlayer; + this.isAI = _isAI; + this.modelFile = _modelFile; + this.name = "Player"; + // + this.splineId = 0; + this.cameraSplineId = 0; + this.targetSplineId = 0; + this.referenceSplineId = 0; + this.bonusSplineId = 0; + this.temp = 0; + this.autopilot = false; + this.curveAmt = 0; + this.speedFactor = 0; + this.overSpeed = false; + //flightvars + this.flightRadius = 112; + this.flightRadiusLowerLimit = 32;//-112 + 32; + this.flightRadiusUpperLimit = 112; + this.speed = 0; + this.speedNormalized = 0; + this.speedMax = 16; + this.speedBonus = 0; + this.nearmissBoost = 1.5; + this.slipstreaming = false; + this.slipstreamBoost = 1.1; + this.acceleration = 0.1; + this.deceleration = -0.05; + this.brakes = -0.2; + this.rollSpeed = 0; + this.rollSpeedMax = 1; + this.rollSpeedMin = -1; + this.rollAcceleration = 0.1; + this.rollDeceleration = 0.1; + this.pitch = { + current: 0, + target: 0, + delta: 0, + acceleration: 0.1, + deceleration: 0.05, + min: -1, + max: 1 + } + this.last = { + speedBonus: 0, + curveAmt: 0, + input: { + spd: 0, + roll: 0, + pitch: 0 + }, + keyInput: { + spd: 0, + roll: 0, + pitch: 0 + } + } + this.ai = { + prefRoll: 1, + flippedRoll: 0, + lastRollGood: false, + lastGoodPrefRoll: 1, + waitRoll: 0, + curveRec: -9999, + curveSample: 0, + navStates: { + seek: 0, + wait: 1, + dodge: 2, + follow: 3, + cooling: 4 + }, + navState: 0, + aggression: 0, + + } + //camera + this.cameras = { + thirdPersonFollow: 0, + firstPersonCockpit: 1, + firstPersonBumper: 2, + thirdPersonOrbit: 3 + } + this.camera = this.cameras.firstPersonCockpit; + this.cameraFovs = [2.5, 3, 3.5, 4.5, 5]; + this.cameraFovEscalation = 0; + this.cameraSplineId = 0; + //input + this.input = { + spd: 0, + roll: 0, + pitch: 0 + } + this.keyInput = { + spd: 0, + roll: 0, + pitch: 0 + } + + this.gondula = this.scene.geometryController.loadModel("hoverShip gondula " + String(this.id), "modDebugArrow", { x: 0, y: 0, z: 0 }); + //this.gondula.flags.draw = true; + + this.shipAnchor = this.scene.geometryController.loadModel("hoverShip anchor " + String(this.id), "modDebugArrow", { x: 0, y: 96, z: 0 }); + //this.shipAnchor.flags.draw = true; + + let models = ["modHoverCarWipeOutStyle",/* "modHoverCarF1",*/ "modHoverCarTinnemann00", "modHoverCarHapton00"]; + if(this.modelFile !== null){ + models = [this.modelFile] + } + this.ship = this.scene.geometryController.loadModel("hoverShip model " + String(this.id), models[Math.floor(Math.random() * models.length)], { x: 0, y: 96, z: 0 });//modHoverCarF1 modHoverCarWipeOutStyle + this.ship.flags.draw = true; + this.ship.depthMod = 48; + this.addCollisionBox(); + + this.shipAnchor.jumpToPosition({ + x: (this.gondula.pos.x + (this.gondula.transform.up.x * -this.flightRadius)), + y: (this.gondula.pos.y + (this.gondula.transform.up.y * -this.flightRadius)), + z: (this.gondula.pos.z + (this.gondula.transform.up.z * -this.flightRadius)) + }); + + //thrusters + this.thrusters = []; + for(let q of this.ship.quadData){ + if(q.frame === "texGlowSquareWhite00"){ + this.thrusters.push(q); + } + } + + //lensflare + this.lensflares = []; + this.lensflares.push(this.scene.geometryController.loadModel("hovership lensflare " + String(this.id), "modLensflare", { x: 0, y: 0, z: 0 })); + this.lensflares[this.lensflares.length - 1].flags.draw = true; + this.lensflares[this.lensflares.length - 1].setDrawMode(DRAWMODE.BILLBOARD3D); + this.lensflares[this.lensflares.length - 1].depthMod = 64; + this.lensflares[this.lensflares.length - 1].quadData[0].alpha = 0.2; + + //trails + this.trails = []; + this.swooshOrigins = []; + this.shipSwooshOrigins = []; + this.trailLength = 10; + for(let q of this.ship.quadData){ + if(q.frame === "sprDebugTexture"){ + this.shipSwooshOrigins.push(q); + this.swooshOrigins.push(this.scene.geometryController.loadModel("trail " + String(this.id) + " " + this.swooshOrigins.length, "modDebugTile", { x: 0, y: 0, z: 0 })); + this.swooshOrigins[this.swooshOrigins.length - 1].flags.draw = true; + this.swooshOrigins[this.swooshOrigins.length - 1].depthMod = 128;//todo: this causes issues + this.trails.push([this.swooshOrigins[this.swooshOrigins.length - 1].quadData[0]]); + + this.trails[this.trails.length - 1][0].setTexture("atlasAll", "flatPal00White"); + this.trails[this.trails.length - 1][0].alpha = 0.8; + //hide debug trail position on ship + this.shipSwooshOrigins[this.shipSwooshOrigins.length - 1].alpha = 0; + } + } + for(let j = 0 ; j < this.swooshOrigins.length ; j++){//<- number of swoosh Origins on ship (eg both wing tips) + let q = this.trails[j][0]; + for(let i = 0 ; i < this.trailLength ; i++){ + this.swooshOrigins[j].addQuadFromData({ + type: q.type, + texture: q.texture, + frame: q.frame, + position: { + x: q.pos.x - this.swooshOrigins[j].pos.x, + y: q.pos.y - this.swooshOrigins[j].pos.y, + z: q.pos.z - this.swooshOrigins[j].pos.z, + }, + points: [ + { + x: q.points[0].x, + y: q.points[0].y, + z: q.points[0].z, + }, { + x: q.points[1].x, + y: q.points[1].y, + z: q.points[1].z, + }, { + x: q.points[2].x, + y: q.points[2].y, + z: q.points[2].z, + }, { + x: q.points[3].x, + y: q.points[3].y, + z: q.points[3].z, + } + ] + }); + this.trails[j].push(this.swooshOrigins[j].quadData[this.swooshOrigins[j].quadData.length -1]); + this.swooshOrigins[j].quadData[this.swooshOrigins[j].quadData.length -1].alpha = 1 - (i/(this.trailLength+1)); + } + } + //init trail history + this.shipTrailHistory = []; + for(let [j, t] of this.trails.entries()){ + this.shipTrailHistory.push([]); + for(let q of t){ + this.shipTrailHistory[j].push(this.ship.getWorldPositionOfQuad(this.shipSwooshOrigins[j])); + } + } + this.trailTicker = 0; + + + //times + this.startTime = Date.now(); + this.elapsedTime = Date.now() - this.startTime; + this.lapTimes = []; + } + + setShipColor(_color){ + for(let q of this.ship.quadData){ + if(q.texture === "atlasPlating"){ + let frame = q.frame; + // t e x P l a t i n g R e d 0 0 + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + let prStr = frame.substr(0, 10); + let nuStr = frame.substr(13, 2); + q.setTexture(q.texture, prStr + _color + nuStr); + } + } + } + + setShipModel(_file, _color = "Red"){ + this.geometryController.destroyModelById(this.ship.id); + this.ship = this.scene.geometryController.loadModel("hoverShip model " + String(this.id), _file, { x: 0, y: 96, z: 0 }); + this.ship.flags.draw = true; + this.ship.depthMod = 48; + this.addCollisionBox(); + + this.setShipColor(_color); + } + + addCollisionBox(_type = 0){ + switch(_type){ + case 0: + this.ship.addQuadFromData({ + type:"collisionQuad", + position: { + x:0, y:0, z:0 + },points:[{ + x:-24, y:16-16, z: -64 + },{ + x:24, y:16-16, z: -64 + },{ + x:24, y:-16-16, z: -64 + },{ + x:-24, y:-16-16, z: -64 + }] + }) + break; + default: + break; + } + } + + update(){ + this.elapsedTime = Date.now() - this.startTime; + + /* + for(let [i, t] of this.trails.entries()){ + this.shipTrailHistory.push([]); + for(let q of t){ + this.shipTrailHistory[i].push(this.ship.getWorldPositionOfQuad(q)); + } + } + */ + } + + updateFromHangar(){ + //if(this.gondula.pos.y > 0){ + //also change in lvlHangar if speed upwards changes + //this.gondula.jumpToPosition({x: this.gondula.pos.x, y: this.gondula.pos.y - (0.5 * this.scene.dt), z: this.gondula.pos.z}, true); + + //this is also in racing + this.cameraSplineId = this.splineId - 5; + if(this.cameraSplineId < 0){ + this.cameraSplineId += this.level.trackBuilder.spline.length; + } + this.targetSplineId = this.splineId + 1;//INFO looking further down with higher speed? + while(this.targetSplineId >= this.level.trackBuilder.spline.length){ + this.targetSplineId -= this.level.trackBuilder.spline.length; + } + let splineRef = this.level.trackBuilder.spline[this.targetSplineId]; + //until here in racing + + //move gonudla and ship + //todo: why do the enemies fly further? is this not fuzzy enough? + let d = eud.distance( [this.gondula.pos.x, this.gondula.pos.y, this.gondula.pos.z], [this.level.trackBuilder.spline[this.splineId].x, this.level.trackBuilder.spline[this.splineId].y, this.level.trackBuilder.spline[this.splineId].z]); + //if(this.isPlayer === true){ + //console.log(d) + //} + if(d >= this.scene.dt){ + let spd = 0.5 * this.scene.dt; + this.gondula.jumpToPosition({x: this.gondula.pos.x + (this.gondula.transform.up.x * spd), y: this.gondula.pos.y + (this.gondula.transform.up.y * spd), z: this.gondula.pos.z + (this.gondula.transform.up.z * spd)}, true); + this.shipAnchor.jumpToPosition({x: this.gondula.pos.x + (this.gondula.transform.up.x * -96), y: this.gondula.pos.y + (this.gondula.transform.up.y * -96), z: this.gondula.pos.z + (this.gondula.transform.up.z * -96)}, true); + this.ship.jumpToPosition({x: this.gondula.pos.x + (this.gondula.transform.up.x * -96), y: this.gondula.pos.y + (this.gondula.transform.up.y * -96), z: this.gondula.pos.z + (this.gondula.transform.up.z * -96)}, true); + } + + //this is also in racing + let posFactor = 0.25 * this.scene.dt;// 0.5 //Math.max(0.01, ((this.speed + this.speedBonus) / (this.speedMax + this.speedBonus))) * 0.5;//todo: at max speed it still jitters + let rotFactor = 0.05 * this.scene.dt; + //rotate ship Anchor to Gondula + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.shipAnchor.transform.toVectorArray( this.shipAnchor.transform.forward), + this.shipAnchor.transform.toVectorArray( splineRef.transform.forward) + ) + let rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.shipAnchor.transform.rotationQuat, targetRot, rotFactor); + this.shipAnchor.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.shipAnchor.transform.toVectorArray( this.shipAnchor.transform.right), + this.shipAnchor.transform.toVectorArray( this.gondula.transform.right) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.shipAnchor.transform.rotationQuat, targetRot, rotFactor); + this.shipAnchor.rotateByQuaternion(rot); + + //move and rotate ship model to actual ship anchor point + this.ship.jumpToPosition({ x: this.shipAnchor.pos.x, y: this.shipAnchor.pos.y, z: this.shipAnchor.pos.z }); + //rotate ship to Gondula + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.ship.transform.toVectorArray( this.ship.transform.forward), + this.ship.transform.toVectorArray( splineRef.transform.forward) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.ship.transform.rotationQuat, targetRot, rotFactor); + this.ship.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.ship.transform.toVectorArray( this.ship.transform.right), + this.ship.transform.toVectorArray( this.gondula.transform.right) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.ship.transform.rotationQuat, targetRot, rotFactor); + this.ship.rotateByQuaternion(rot); + //until here + //} + } + + updateRacing(){ + this.cameraSplineId = this.splineId - 5; + if(this.cameraSplineId < 0){ + this.cameraSplineId += this.level.trackBuilder.spline.length; + } + this.targetSplineId = this.splineId + 1;//INFO looking further down with higher speed? + while(this.targetSplineId >= this.level.trackBuilder.spline.length){ + this.targetSplineId -= this.level.trackBuilder.spline.length; + } + let splineRef = this.level.trackBuilder.spline[this.targetSplineId]; + + this.bonusSplineId = this.splineId + 5; + while(this.bonusSplineId >= this.level.trackBuilder.spline.length){ + this.bonusSplineId -= this.level.trackBuilder.spline.length; + } + + let bonusRef = this.level.trackBuilder.spline[this.bonusSplineId]; + + this.input.spd = 0; + this.input.roll = 0; + this.input.pitch = 0; + if(this.level.state === this.level.states.race){ + if(this.autopilot === false){ + this.inputPlayer(); + }else{ + this.inputAI(bonusRef); + } + } + + this.last.speedBonus = this.speedBonus; + this.last.input.roll = this.input.roll; + this.last.curveAmt = this.curveAmt; + + //check Collisions + let collCheckArr = [ + {//check forward of ship + pos: { + x: this.shipAnchor.pos.x, + y: this.shipAnchor.pos.y, + z: this.shipAnchor.pos.z + }, + dir: { + x: this.shipAnchor.transform.forward.x, + y: this.shipAnchor.transform.forward.y, + z: this.shipAnchor.transform.forward.z + }, + hit: [] + },{//check forward right of ship for booster + pos: { + x: this.shipAnchor.pos.x + (this.shipAnchor.transform.right.x * 48), + y: this.shipAnchor.pos.y + (this.shipAnchor.transform.right.y * 48), + z: this.shipAnchor.pos.z + (this.shipAnchor.transform.right.z * 48) + }, + dir: { + x: this.shipAnchor.transform.forward.x, + y: this.shipAnchor.transform.forward.y, + z: this.shipAnchor.transform.forward.z + }, + hit: [] + },{//check forward left of ship for booster + pos: { + x: this.shipAnchor.pos.x + (this.shipAnchor.transform.right.x * -48), + y: this.shipAnchor.pos.y + (this.shipAnchor.transform.right.y * -48), + z: this.shipAnchor.pos.z + (this.shipAnchor.transform.right.z * -48) + }, + dir: { + x: this.shipAnchor.transform.forward.x, + y: this.shipAnchor.transform.forward.y, + z: this.shipAnchor.transform.forward.z + }, + hit: [] + } + ]; + let toCollideWith = []; + for(let o of this.level.trackBuilder.obstacles){ + if(o.data.id+1 > this.splineId){ + toCollideWith.push(o); + } + //if (o.flags.update === true){ + //o.update(); + //} + } + for(let s of this.level.aiShips){ + if(s.id !== this.id){ + if(s.splineId > this.splineId){ + toCollideWith.push(s.ship); + } + } + } + if(this.isPlayer === false){ + if(this.level.playerShip.splineId > this.splineId){ + toCollideWith.push(this.level.playerShip.ship); + } + } + for(let m of toCollideWith){ + //if (m.flags.update === true){ + // m.update(); + //} + for (let q of m.collisionData){ + for(let c of collCheckArr){ + let hitData = this.scene.geometryController.collide(q, c); + if(hitData.pt !== null){ + hitData.model = m; + c.hit.push(hitData); + } + } + } + } + let alreadyColliding = false; + //let avoids = [0, 0, 0]; + let returnColl = collCheckArr; + //resolve collision with forward + if (returnColl[0].hit.length > 0) { + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[0].hit[0]; + for (let [i, n] of returnColl[0].hit.entries()) { + let d = eud.distance([this.shipAnchor.pos.x, this.shipAnchor.pos.y, this.shipAnchor.pos.z], returnColl[0].hit[i].pt) + if (d < dist) { + dist = d; + nearestHit = returnColl[0].hit[i]; + } + } + /*if(dist < 1024){ + avoids[0] = 1; + }*/ + if(dist < 128){ + alreadyColliding = true; + if(nearestHit.model.trigger.isTrigger === false){ + //console.log(returnColl[0]); + + if(this.speed > 0 && this.isPlayer){ + this.scene.soundManager.playRandomSound(this.scene.soundManager.bumpSound); + } + + this.input.spd = 0; + this.speed = 0; + if(nearestHit.model.data.roll !== undefined){ + this.input.roll = nearestHit.model.data.roll * 2; + } + + }else{ + nearestHit.model.trigger.other = this; + nearestHit.model.updateTrigger(); + } + } + } + //check booster only if collision free + if(alreadyColliding === false){ + //resolve collision with forward right and then left of ship for boost + for(let j = 1 ; j < 3 ; j++){ + if (returnColl[j].hit.length > 0) { + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[j].hit[0]; + for (let [i, n] of returnColl[j].hit.entries()) { + let d = eud.distance([returnColl[j].pos.x, returnColl[j].pos.y, returnColl[j].pos.z], returnColl[j].hit[i].pt) + if (d < dist) { + dist = d; + nearestHit = returnColl[j].hit[i]; + } + } + /*if(dist < 1024){ + avoids[j] = 1; + }*/ + if(dist < 128){ + if(nearestHit.model.trigger.isTrigger === false){ + if(this.speed > (this.speedMax * 0.25) && this.input.spd >= 0){ + this.input.spd = 1; + this.speed = this.speedMax * this.nearmissBoost; + if(this.isPlayer === true){ + if(this.scene.cam.fov < 3.5){//todo: find a good value for the boost effect + this.scene.cam.fov += 1 * this.scene.dt; + this.scene.cam.fov = Math.min(this.scene.cam.fov, 3.5); + } + //sound + this.scene.soundManager.playRandomSound(this.scene.soundManager.swooshSound); + } + } + }else{ + //nearestHit.model.updateTrigger(); + } + } + } + } + } + + //find pitch to track to set bonus + let upVec = [//was gonudla before, but could work well with ship + bonusRef.x + (this.ship.transform.forward.x * 10) + (this.ship.transform.up.x * 10), + bonusRef.y + (this.ship.transform.forward.y * 10) + (this.ship.transform.up.y * 10), + bonusRef.z + (this.ship.transform.forward.z * 10) + (this.ship.transform.up.z * 10) + ] + let doVec = [ + bonusRef.x + (this.ship.transform.forward.x * 10) + (this.ship.transform.up.x * -10), + bonusRef.y + (this.ship.transform.forward.y * 10) + (this.ship.transform.up.y * -10), + bonusRef.z + (this.ship.transform.forward.z * 10) + (this.ship.transform.up.z * -10) + ] + let upDist = eud.distance(upVec, [bonusRef.x + (bonusRef.transform.forward.x), bonusRef.y + (bonusRef.transform.forward.y), bonusRef.z + (bonusRef.transform.forward.z)]); + let doDist = eud.distance(doVec, [bonusRef.x + (bonusRef.transform.forward.x), bonusRef.y + (bonusRef.transform.forward.y), bonusRef.z + (bonusRef.transform.forward.z)]); + let bonusAmt = (doDist - upDist); + bonusAmt = Math.max(-1, Math.min(bonusAmt, 1)); + + //move away from ideal height + this.flightRadius += (bonusAmt * (this.speed * 0.25)) * this.scene.dt; + //todo: maybe find a way to loose grip when too hot and reduce speed that way + //if(this.temp > 500){ + // this.flightRadius -= 10; + //} + let calmer = 1 * this.scene.dt; + this.flightRadius = Math.max(this.flightRadiusLowerLimit, Math.min(this.flightRadius + calmer, this.flightRadiusUpperLimit)); + this.speedBonus = this.speedMax * bonusAmt; + + + //find pitch to track from gondula to set navigation + upVec = [ + bonusRef.x + (this.gondula.transform.forward.x * 1) + (this.gondula.transform.up.x * 1), + bonusRef.y + (this.gondula.transform.forward.y * 1) + (this.gondula.transform.up.y * 1), + bonusRef.z + (this.gondula.transform.forward.z * 1) + (this.gondula.transform.up.z * 1) + ] + doVec = [ + bonusRef.x + (this.gondula.transform.forward.x * 1) + (this.gondula.transform.up.x * -1), + bonusRef.y + (this.gondula.transform.forward.y * 1) + (this.gondula.transform.up.y * -1), + bonusRef.z + (this.gondula.transform.forward.z * 1) + (this.gondula.transform.up.z * -1) + ] + upDist = eud.distance(upVec, [bonusRef.x + (bonusRef.transform.forward.x * 320), bonusRef.y + (bonusRef.transform.forward.y * 320), bonusRef.z + (bonusRef.transform.forward.z * 320)]); + doDist = eud.distance(doVec, [bonusRef.x + (bonusRef.transform.forward.x * 320), bonusRef.y + (bonusRef.transform.forward.y * 320), bonusRef.z + (bonusRef.transform.forward.z * 320)]); + let curveAmt = (doDist - upDist); + //curveAmt = Math.max(-1, Math.min(curveAmt * 0.005, 1)); + this.curveAmt = curveAmt; + + //apply sppeed and move accordingly + if(this.input.spd !== 0){ + if(this.speed > this.speedMax + this.speedBonus){ + this.input.spd = (this.acceleration * -2); + } + this.speed += this.input.spd; + this.speed = Math.max(0, this.speed); + //this.speed = Math.max(0, Math.min(this.speed, this.speedMax + this.speedBonus)); + + //console.log(splineRef) + //use right axis if you need roll as well, but if using forward, you just follow the track as intended any you can roll on your own later + let targetVec = [splineRef.x - this.gondula.pos.x, splineRef.y - this.gondula.pos.y, splineRef.z - this.gondula.pos.z]; + targetVec = gl_vec3.normalize(targetVec, targetVec); + + let targetRot = [0, 0, 0, 0]; + //console.log(targetVec) + targetRot = gl_quat.rotationTo(targetRot, + this.gondula.transform.toVectorArray( this.gondula.transform.forward), + //this.gondula.transform.toVectorArray( splineRef.transform.forward) + targetVec + ) + //let rot = [0, 0, 0, 0]; + //rot = gl_quat.slerp(rot, this.gondula.transform.rotationQuat, targetRot, 0.01); + this.gondula.rotateByQuaternion(targetRot); + //move gondula forward by spd + this.gondula.jumpToPosition({ + x: this.gondula.pos.x + ((targetVec[0] * this.speed) * this.scene.dt), + y: this.gondula.pos.y + ((targetVec[1] * this.speed) * this.scene.dt), + z: this.gondula.pos.z + ((targetVec[2] * this.speed) * this.scene.dt) + }); + + let criticalSpeed = (1* this.speed) * this.scene.dt; + /*if(this.isPlayer === true){ + if(criticalSpeed >= 64){ + console.log(criticalSpeed); + }; + }*/ + + //check if reached target + let d = gl_vec3.distance(this.gondula.transform.toVectorArray( this.gondula.pos), [splineRef.x, splineRef.y, splineRef.z]); + //console.log(d) + if(d <= 64 /*this.speed * 1*/ /*64*/){ + let amt = Math.floor(criticalSpeed/64) + 1; //jumjp further if speed exceeds the distance between splines + this.splineId += amt; + if(this.splineId >= this.level.trackBuilder.spline.length){ + this.splineId -= this.level.trackBuilder.spline.length; + this.startNewLap(); + } + //console.log("next point: " + String(this.splineId) + " / " + String(this.level.trackBuilder.spline.length)) + } + } + + if(this.speed > this.speedMax && this.slipstreaming === false){ + this.temp += 1 * this.scene.dt;; + if(this.speedBonus < 3){ + this.temp -= 1.5 * this.scene.dt;; + } + }else{ + this.temp -= 1.1 * this.scene.dt;; + } + + this.temp = Math.max(0, Math.min(this.temp, 999)); + + if(this.temp >= 999){ + this.speedBonus = 0; + }else{ + } + + this.speedNormalized = this.speed / this.speedMax; + + + //roll the ship + if(this.input.roll !== 0){ + if(this.input.roll > 0){ + if(this.rollSpeed < this.rollSpeedMax){ + this.rollSpeed += this.rollAcceleration * this.scene.dt; + this.rollSpeed = Math.min(this.rollSpeed, this.rollSpeedMax); + } + } + if(this.input.roll < 0){ + if(this.rollSpeed > this.rollSpeedMin){ + this.rollSpeed -= this.rollAcceleration * this.scene.dt; + this.rollSpeed = Math.max(this.rollSpeed, this.rollSpeedMin); + } + } + }else{ + if(this.rollSpeed < 0){ + this.rollSpeed += this.rollDeceleration * this.scene.dt; + this.rollSpeed = Math.min(this.rollSpeed, 0); + } + if(this.rollSpeed > 0){ + this.rollSpeed -= this.rollDeceleration * this.scene.dt; + this.rollSpeed = Math.max(this.rollSpeed, 0); + } + } + + if(this.scene.numkeys.nine.isDown){ + if(this.flightRadius > this.flightRadiusLowerLimit){ + this.flightRadius -= 1 * this.scene.dt; + } + } + if(this.scene.numkeys.three.isDown){ + //if(this.flightRadius < this.flightRadiusUpperLimit){ + this.flightRadius += 1 * this.scene.dt; + //} + } + + this.speedFactor = Math.max(0, Math.min( (this.speed + this.speedBonus) / (this.speedMax + this.speedBonus) , 1)); + if(this.speed > this.speedMax){ + this.overSpeed = true; + }else{ + this.overSpeed = false; + } + //visual rotatons based on input + this.gondula.rotateAroundAxis(this.gondula.transform.toVectorArray(this.gondula.transform.forward), (Math.PI * 0.01) * (this.rollSpeed) * this.scene.dt); + //this.shipAnchor.rotateAroundAxis(this.gondula.transform.toVectorArray(this.gondula.transform.forward), (Math.PI * 0.01) * this.rollSpeed); + //let ship look a bit ahead of corner on input + this.shipAnchor.rotateAroundAxis(this.gondula.transform.toVectorArray(this.gondula.transform.up), (Math.PI * 0.01) * (this.rollSpeed) * this.scene.dt); + this.ship.rotateAroundAxis(this.ship.transform.toVectorArray(this.ship.transform.forward), ((Math.PI * 0.005 * this.speedFactor)) * (this.rollSpeed) * this.scene.dt); + //let pitchditch = (this.keyInput.spd * (this.speed / this.speedMax)) * (Math.PI * 0.001); + //this.ship.rotateAroundAxis(this.ship.transform.toVectorArray(this.ship.transform.right), pitchditch); + + if(this.keyInput.pitch > 0){ + this.pitch.target = this.pitch.max; + }else if(this.keyInput.pitch < 0){ + this.pitch.target = this.pitch.min; + }else{ + this.pitch.target = 0; + } + this.pitch.delta = this.pitch.target - this.pitch.current; + this.pitch.current += this.pitch.delta * this.scene.dt; + let pitchditch = this.pitch.current * 0.01; + this.ship.rotateAroundAxis(this.ship.transform.toVectorArray(this.ship.transform.right), pitchditch); + //roll ship for cool drifting effect + this.ship.rotateAroundAxis(this.shipAnchor.transform.toVectorArray(this.shipAnchor.transform.forward), (Math.PI * -0.025) * (this.rollSpeed)); + + + //move Ship to gondula + let posFactor = 0.25 * this.scene.dt; // 0.5 //Math.max(0.01, ((this.speed + this.speedBonus) / (this.speedMax + this.speedBonus))) * 0.5;//todo: at max speed it still jitters + let rotFactor = 0.05 * this.scene.dt; //0.1 //Math.max(0.01, ((this.speed + this.speedBonus) / (this.speedMax + this.speedBonus)) * 0.1); + + if(this.speed < 0.01){ + //posFactor = 0.5; + //rotFactor = 0.1; + } + let deltaPos = { + x: ((this.gondula.pos.x + (this.gondula.transform.up.x * -this.flightRadius))) - this.shipAnchor.pos.x, + y: ((this.gondula.pos.y + (this.gondula.transform.up.y * -this.flightRadius))) - this.shipAnchor.pos.y, + z: ((this.gondula.pos.z + (this.gondula.transform.up.z * -this.flightRadius))) - this.shipAnchor.pos.z + } + this.shipAnchor.jumpToPosition({ + x: this.shipAnchor.pos.x + (deltaPos.x * posFactor), + y: this.shipAnchor.pos.y + (deltaPos.y * posFactor), + z: this.shipAnchor.pos.z + (deltaPos.z * posFactor) + }); + //rotate ship Anchor to Gondula + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.shipAnchor.transform.toVectorArray( this.shipAnchor.transform.forward), + this.shipAnchor.transform.toVectorArray( splineRef.transform.forward) + ) + let rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.shipAnchor.transform.rotationQuat, targetRot, rotFactor); + this.shipAnchor.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.shipAnchor.transform.toVectorArray( this.shipAnchor.transform.right), + this.shipAnchor.transform.toVectorArray( this.gondula.transform.right) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.shipAnchor.transform.rotationQuat, targetRot, rotFactor); + this.shipAnchor.rotateByQuaternion(rot); + + //move and rotate ship model to actual ship anchor point + this.ship.jumpToPosition({ x: this.shipAnchor.pos.x, y: this.shipAnchor.pos.y, z: this.shipAnchor.pos.z }); + //rotate ship to Gondula + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.ship.transform.toVectorArray( this.ship.transform.forward), + this.ship.transform.toVectorArray( splineRef.transform.forward) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.ship.transform.rotationQuat, targetRot, rotFactor); + this.ship.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.ship.transform.toVectorArray( this.ship.transform.right), + this.ship.transform.toVectorArray( this.gondula.transform.right) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.ship.transform.rotationQuat, targetRot, rotFactor); + this.ship.rotateByQuaternion(rot); + + //show ship trail + /*let tipL = { + x: this.ship.quadData[this.ship.quadData.length - 1].points[0].x + ((this.gondula.transform.forward.x * (1 + (-56 * (this.speed / this.speedMax)))) + (this.gondula.transform.right.x * 0) + (this.gondula.transform.up.x * -2)), + y: this.ship.quadData[this.ship.quadData.length - 1].points[0].y + ((this.gondula.transform.forward.y * (1 + (-56 * (this.speed / this.speedMax)))) + (this.gondula.transform.right.y * 0) + (this.gondula.transform.up.y * -2)), + z: this.ship.quadData[this.ship.quadData.length - 1].points[0].z + ((this.gondula.transform.forward.z * (1 + (-56 * (this.speed / this.speedMax)))) + (this.gondula.transform.right.z * 0) + (this.gondula.transform.up.z * -2)) + } + let tipR = { + x: this.ship.quadData[this.ship.quadData.length - 1].points[1].x + ((this.gondula.transform.forward.x * (1 + (-56 * (this.speed / this.speedMax)))) + (this.gondula.transform.right.x * 0) + (this.gondula.transform.up.x * -2)), + y: this.ship.quadData[this.ship.quadData.length - 1].points[1].y + ((this.gondula.transform.forward.y * (1 + (-56 * (this.speed / this.speedMax)))) + (this.gondula.transform.right.y * 0) + (this.gondula.transform.up.y * -2)), + z: this.ship.quadData[this.ship.quadData.length - 1].points[1].z + ((this.gondula.transform.forward.z * (1 + (-56 * (this.speed / this.speedMax)))) + (this.gondula.transform.right.z * 0) + (this.gondula.transform.up.z * -2)) + } + this.ship.quadData[this.ship.quadData.length - 1].points[3] = tipL; + this.ship.quadData[this.ship.quadData.length - 1].points[2] = tipR; + this.ship.quadData[this.ship.quadData.length - 2].points[3] = tipL; + this.ship.quadData[this.ship.quadData.length - 2].points[2] = tipR;*/ + for(let t of this.thrusters){ + //todo: get the saved original position of the vertex to move and add the move vector to keep the shape of the thruster to keep a cone shape + t.points[3].x = t.points[0].x + (this.gondula.transform.forward.x * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[3].y = t.points[0].y + (this.gondula.transform.forward.y * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[3].z = t.points[0].z + (this.gondula.transform.forward.z * (1 + (-56 * (this.speed / this.speedMax)))); + + t.points[2].x = t.points[1].x + (this.gondula.transform.forward.x * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[2].y = t.points[1].y + (this.gondula.transform.forward.y * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[2].z = t.points[1].z + (this.gondula.transform.forward.z * (1 + (-56 * (this.speed / this.speedMax)))); + } + + this.lensflares[this.lensflares.length - 1].jumpToPosition({ + x: this.ship.pos.x + (this.ship.transform.forward.x * -66) + (this.ship.transform.up.x * 22), + y: this.ship.pos.y + (this.ship.transform.forward.y * -66) + (this.ship.transform.up.y * 22), + z: this.ship.pos.z + (this.ship.transform.forward.z * -66) + (this.ship.transform.up.z * 22), + }, true); + this.lensflares[this.lensflares.length - 1].quadData[0].alpha = 1 * this.speedFactor;//0.2 + + //todo: save an array of previous tip positions (part of the model) and let quads dynamically stretch over them to form a growing trail + /*for(let t of this.trails){ + for(let i = t.length -1 ; i >= 0 ; i--){ + let p = t[i]; + p.points[3] = p.points[0]; + p.points[2] = p.points[1]; + } + }*/ + /*//my origin points + this.trails[0][0].points[0] + this.trails[0][0].points[1] + this.trails[1][0].points[0] + this.trails[1][0].points[1] + */ + + + this.trailTicker -= this.scene.dt; + for(let [j, t] of this.trails.entries()){ + if(this.trailTicker <= 0){ + for(let i = t.length - 1 ; i > 0 ; i--){ + this.shipTrailHistory[j][i] = this.shipTrailHistory[j][i-1] + } + } + this.shipTrailHistory[j][0] = this.ship.getWorldPositionOfQuad(this.shipSwooshOrigins[j]); + for(let p of this.shipTrailHistory[j][0]){ + p.x += this.ship.pos.x; + p.y += this.ship.pos.y; + p.z += this.ship.pos.z; + } + } + + for(let [j, t] of this.trails.entries()){//each trail + //this.swooshOrigins[j].jumpToPosition(this.ship.pos); + if(this.trailTicker <= 0){ + for(let i = t.length -1 ; i > 0 ; i--){//each trail quad / saved position + let q = t[i];//each quad + //jump end of trailpart to timesaved position + q.points[3].x = this.shipTrailHistory[j][i][0].x + this.shipTrailHistory[j][i][4].x; + q.points[3].y = this.shipTrailHistory[j][i][0].y + this.shipTrailHistory[j][i][4].y; + q.points[3].z = this.shipTrailHistory[j][i][0].z + this.shipTrailHistory[j][i][4].z; + q.points[2].x = this.shipTrailHistory[j][i][1].x + this.shipTrailHistory[j][i][4].x; + q.points[2].y = this.shipTrailHistory[j][i][1].y + this.shipTrailHistory[j][i][4].y; + q.points[2].z = this.shipTrailHistory[j][i][1].z + this.shipTrailHistory[j][i][4].z; + + //jump start of trailpart to timesaved previous position + q.points[0].x = this.shipTrailHistory[j][i-1][0].x + this.shipTrailHistory[j][i-1][4].x; + q.points[0].y = this.shipTrailHistory[j][i-1][0].y + this.shipTrailHistory[j][i-1][4].y; + q.points[0].z = this.shipTrailHistory[j][i-1][0].z + this.shipTrailHistory[j][i-1][4].z; + q.points[1].x = this.shipTrailHistory[j][i-1][1].x + this.shipTrailHistory[j][i-1][4].x; + q.points[1].y = this.shipTrailHistory[j][i-1][1].y + this.shipTrailHistory[j][i-1][4].y; + q.points[1].z = this.shipTrailHistory[j][i-1][1].z + this.shipTrailHistory[j][i-1][4].z; + } + } + //correct first trail part that is connected to the ship + //jump end of trailpart to timesaved position + t[0].points[3].x = this.shipTrailHistory[j][1][0].x + this.shipTrailHistory[j][1][4].x; + t[0].points[3].y = this.shipTrailHistory[j][1][0].y + this.shipTrailHistory[j][1][4].y; + t[0].points[3].z = this.shipTrailHistory[j][1][0].z + this.shipTrailHistory[j][1][4].z; + t[0].points[2].x = this.shipTrailHistory[j][1][1].x + this.shipTrailHistory[j][1][4].x; + t[0].points[2].y = this.shipTrailHistory[j][1][1].y + this.shipTrailHistory[j][1][4].y; + t[0].points[2].z = this.shipTrailHistory[j][1][1].z + this.shipTrailHistory[j][1][4].z; + + t[0].points[0].x = this.shipTrailHistory[j][0][0].x + this.shipTrailHistory[j][0][4].x; + t[0].points[0].y = this.shipTrailHistory[j][0][0].y + this.shipTrailHistory[j][0][4].y; + t[0].points[0].z = this.shipTrailHistory[j][0][0].z + this.shipTrailHistory[j][0][4].z; + t[0].points[1].x = this.shipTrailHistory[j][0][1].x + this.shipTrailHistory[j][0][4].x; + t[0].points[1].y = this.shipTrailHistory[j][0][1].y + this.shipTrailHistory[j][0][4].y; + t[0].points[1].z = this.shipTrailHistory[j][0][1].z + this.shipTrailHistory[j][0][4].z; + } + if(this.trailTicker <= 0){ + this.trailTicker = this.speed * 0.25; + } + + //todo: positional sound here + } + + updateDream(){ + let splineRef = this.level.trackBuilder.spline[0]; + + this.gondula.jumpToPosition({ + x: this.gondula.pos.x, + y: this.gondula.pos.y, + z: this.gondula.pos.z + ((1 * this.speed) * this.scene.dt) + }); + + //move Ship to gondula + let posFactor = 0.25 * this.scene.dt;// 0.5 //Math.max(0.01, ((this.speed + this.speedBonus) / (this.speedMax + this.speedBonus))) * 0.5;//todo: at max speed it still jitters + let rotFactor = 0.05 * this.scene.dt;//0.1 //Math.max(0.01, ((this.speed + this.speedBonus) / (this.speedMax + this.speedBonus)) * 0.1); + + if(this.speed < 0.01){ + //posFactor = 0.5; + //rotFactor = 0.1; + } + let deltaPos = { + x: ((this.gondula.pos.x + (this.gondula.transform.up.x * -this.flightRadius))) - this.shipAnchor.pos.x, + y: ((this.gondula.pos.y + (this.gondula.transform.up.y * -this.flightRadius))) - this.shipAnchor.pos.y, + z: ((this.gondula.pos.z + (this.gondula.transform.up.z * -this.flightRadius))) - this.shipAnchor.pos.z + } + this.shipAnchor.jumpToPosition({ + x: this.shipAnchor.pos.x + (deltaPos.x * posFactor), + y: this.shipAnchor.pos.y + (deltaPos.y * posFactor), + z: this.shipAnchor.pos.z + (deltaPos.z * posFactor) + }); + + //rotate ship Anchor to Gondula + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.shipAnchor.transform.toVectorArray( this.shipAnchor.transform.forward), + this.shipAnchor.transform.toVectorArray( splineRef.transform.forward) + ) + let rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.shipAnchor.transform.rotationQuat, targetRot, rotFactor); + this.shipAnchor.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.shipAnchor.transform.toVectorArray( this.shipAnchor.transform.right), + this.shipAnchor.transform.toVectorArray( this.gondula.transform.right) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.shipAnchor.transform.rotationQuat, targetRot, rotFactor); + this.shipAnchor.rotateByQuaternion(rot); + + //move and rotate ship model to actual ship anchor point + this.ship.jumpToPosition({ x: this.shipAnchor.pos.x, y: this.shipAnchor.pos.y, z: this.shipAnchor.pos.z }); + //rotate ship to Gondula + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.ship.transform.toVectorArray( this.ship.transform.forward), + this.ship.transform.toVectorArray( splineRef.transform.forward) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.ship.transform.rotationQuat, targetRot, rotFactor); + this.ship.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.ship.transform.toVectorArray( this.ship.transform.right), + this.ship.transform.toVectorArray( this.gondula.transform.right) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.ship.transform.rotationQuat, targetRot, rotFactor); + this.ship.rotateByQuaternion(rot); + + for(let t of this.thrusters){ + //todo: get the saved original position of the vertex to move and add the move vector to keep the shape of the thruster to keep a cone shape + t.points[3].x = t.points[0].x + (this.gondula.transform.forward.x * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[3].y = t.points[0].y + (this.gondula.transform.forward.y * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[3].z = t.points[0].z + (this.gondula.transform.forward.z * (1 + (-56 * (this.speed / this.speedMax)))); + + t.points[2].x = t.points[1].x + (this.gondula.transform.forward.x * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[2].y = t.points[1].y + (this.gondula.transform.forward.y * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[2].z = t.points[1].z + (this.gondula.transform.forward.z * (1 + (-56 * (this.speed / this.speedMax)))); + } + + this.lensflares[this.lensflares.length - 1].jumpToPosition({ + x: this.ship.pos.x + (this.ship.transform.forward.x * -66) + (this.ship.transform.up.x * 22), + y: this.ship.pos.y + (this.ship.transform.forward.y * -66) + (this.ship.transform.up.y * 22), + z: this.ship.pos.z + (this.ship.transform.forward.z * -66) + (this.ship.transform.up.z * 22), + }, true); + this.lensflares[this.lensflares.length - 1].quadData[0].alpha = 1 * this.speedFactor;//0.2 + + this.trailTicker -= this.scene.dt; + for(let [j, t] of this.trails.entries()){ + if(this.trailTicker <= 0){ + for(let i = t.length - 1 ; i > 0 ; i--){ + this.shipTrailHistory[j][i] = this.shipTrailHistory[j][i-1] + } + } + this.shipTrailHistory[j][0] = this.ship.getWorldPositionOfQuad(this.shipSwooshOrigins[j]); + for(let p of this.shipTrailHistory[j][0]){ + p.x += this.ship.pos.x; + p.y += this.ship.pos.y; + p.z += this.ship.pos.z; + } + } + + for(let [j, t] of this.trails.entries()){//each trail + //this.swooshOrigins[j].jumpToPosition(this.ship.pos); + if(this.trailTicker <= 0){ + for(let i = t.length -1 ; i > 0 ; i--){//each trail quad / saved position + let q = t[i];//each quad + //jump end of trailpart to timesaved position + q.points[3].x = this.shipTrailHistory[j][i][0].x + this.shipTrailHistory[j][i][4].x; + q.points[3].y = this.shipTrailHistory[j][i][0].y + this.shipTrailHistory[j][i][4].y; + q.points[3].z = this.shipTrailHistory[j][i][0].z + this.shipTrailHistory[j][i][4].z; + q.points[2].x = this.shipTrailHistory[j][i][1].x + this.shipTrailHistory[j][i][4].x; + q.points[2].y = this.shipTrailHistory[j][i][1].y + this.shipTrailHistory[j][i][4].y; + q.points[2].z = this.shipTrailHistory[j][i][1].z + this.shipTrailHistory[j][i][4].z; + + //jump start of trailpart to timesaved previous position + q.points[0].x = this.shipTrailHistory[j][i-1][0].x + this.shipTrailHistory[j][i-1][4].x; + q.points[0].y = this.shipTrailHistory[j][i-1][0].y + this.shipTrailHistory[j][i-1][4].y; + q.points[0].z = this.shipTrailHistory[j][i-1][0].z + this.shipTrailHistory[j][i-1][4].z; + q.points[1].x = this.shipTrailHistory[j][i-1][1].x + this.shipTrailHistory[j][i-1][4].x; + q.points[1].y = this.shipTrailHistory[j][i-1][1].y + this.shipTrailHistory[j][i-1][4].y; + q.points[1].z = this.shipTrailHistory[j][i-1][1].z + this.shipTrailHistory[j][i-1][4].z; + } + } + //correct first trail part that is connected to the ship + //jump end of trailpart to timesaved position + t[0].points[3].x = this.shipTrailHistory[j][1][0].x + this.shipTrailHistory[j][1][4].x; + t[0].points[3].y = this.shipTrailHistory[j][1][0].y + this.shipTrailHistory[j][1][4].y; + t[0].points[3].z = this.shipTrailHistory[j][1][0].z + this.shipTrailHistory[j][1][4].z; + t[0].points[2].x = this.shipTrailHistory[j][1][1].x + this.shipTrailHistory[j][1][4].x; + t[0].points[2].y = this.shipTrailHistory[j][1][1].y + this.shipTrailHistory[j][1][4].y; + t[0].points[2].z = this.shipTrailHistory[j][1][1].z + this.shipTrailHistory[j][1][4].z; + + t[0].points[0].x = this.shipTrailHistory[j][0][0].x + this.shipTrailHistory[j][0][4].x; + t[0].points[0].y = this.shipTrailHistory[j][0][0].y + this.shipTrailHistory[j][0][4].y; + t[0].points[0].z = this.shipTrailHistory[j][0][0].z + this.shipTrailHistory[j][0][4].z; + t[0].points[1].x = this.shipTrailHistory[j][0][1].x + this.shipTrailHistory[j][0][4].x; + t[0].points[1].y = this.shipTrailHistory[j][0][1].y + this.shipTrailHistory[j][0][4].y; + t[0].points[1].z = this.shipTrailHistory[j][0][1].z + this.shipTrailHistory[j][0][4].z; + } + if(this.trailTicker <= 0){ + this.trailTicker = this.speed * 0.25; + } + } + + updateSelection(_delta, _slerpAmt = -1){ + this.targetSplineId = this.splineId + 1;//INFO looking further down with higher speed? + while(this.targetSplineId >= this.level.trackBuilder.spline.length){ + this.targetSplineId -= this.level.trackBuilder.spline.length; + } + let splineRef = this.level.trackBuilder.spline[this.targetSplineId]; + + let targetVec = [splineRef.x - this.gondula.pos.x, splineRef.y - this.gondula.pos.y, splineRef.z - this.gondula.pos.z]; + targetVec = gl_vec3.normalize(targetVec, targetVec); + + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.gondula.transform.toVectorArray( this.gondula.transform.forward), + targetVec + ) + this.gondula.rotateByQuaternion(targetRot); + //move gondula forward by spd + this.gondula.jumpToPosition({ + x: this.gondula.pos.x + ((targetVec[0] * this.speed) * this.scene.dt), + y: this.gondula.pos.y + ((targetVec[1] * this.speed) * this.scene.dt), + z: this.gondula.pos.z + ((targetVec[2] * this.speed) * this.scene.dt) + }); + + //check if reached target + let d = gl_vec3.distance(this.gondula.transform.toVectorArray( this.gondula.pos), [splineRef.x, splineRef.y, splineRef.z]); + if(d <= 64){ + //let amt = Math.floor(criticalSpeed/64) + 1; //jumjp further if speed exceeds the distance between splines + this.splineId += 1//amt; + if(this.splineId >= this.level.trackBuilder.spline.length){ + this.splineId -= this.level.trackBuilder.spline.length; + } + } + + //move Ship to gondula + let posFactor = 0.25 * this.scene.dt;// 0.5 //Math.max(0.01, ((this.speed + this.speedBonus) / (this.speedMax + this.speedBonus))) * 0.5;//todo: at max speed it still jitters + let rotFactor = 0.015 * this.scene.dt;//0.1 //Math.max(0.01, ((this.speed + this.speedBonus) / (this.speedMax + this.speedBonus)) * 0.1); + + if(this.speed < 0.01){ + //posFactor = 0.5; + //rotFactor = 0.1; + } + + if(_slerpAmt > 0){ + posFactor = 1; + rotFactor = 1; + } + + let deltaPos = { + x: ((this.gondula.pos.x + (this.gondula.transform.up.x * -this.flightRadius))) - this.shipAnchor.pos.x, + y: ((this.gondula.pos.y + (this.gondula.transform.up.y * -this.flightRadius))) - this.shipAnchor.pos.y, + z: ((this.gondula.pos.z + (this.gondula.transform.up.z * -this.flightRadius))) - this.shipAnchor.pos.z + } + this.shipAnchor.jumpToPosition({ + x: this.shipAnchor.pos.x + (deltaPos.x * posFactor), + y: this.shipAnchor.pos.y + (deltaPos.y * posFactor), + z: this.shipAnchor.pos.z + (deltaPos.z * posFactor) + }); + + //rotate ship Anchor to Gondula + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.shipAnchor.transform.toVectorArray( this.shipAnchor.transform.forward), + this.shipAnchor.transform.toVectorArray( splineRef.transform.forward) + ) + let rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.shipAnchor.transform.rotationQuat, targetRot, rotFactor); + this.shipAnchor.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.shipAnchor.transform.toVectorArray( this.shipAnchor.transform.right), + this.shipAnchor.transform.toVectorArray( this.gondula.transform.right) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.shipAnchor.transform.rotationQuat, targetRot, rotFactor); + this.shipAnchor.rotateByQuaternion(rot); + + //move and rotate ship model to actual ship anchor point + this.ship.jumpToPosition({ x: this.shipAnchor.pos.x, y: this.shipAnchor.pos.y, z: this.shipAnchor.pos.z }); + //rotate ship to Gondula + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.ship.transform.toVectorArray( this.ship.transform.forward), + this.ship.transform.toVectorArray( splineRef.transform.forward) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.ship.transform.rotationQuat, targetRot, rotFactor); + this.ship.rotateByQuaternion(rot); + + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.ship.transform.toVectorArray( this.ship.transform.right), + this.ship.transform.toVectorArray( this.gondula.transform.right) + ) + rot = [0, 0, 0, 0]; + rot = gl_quat.slerp(rot, this.ship.transform.rotationQuat, targetRot, rotFactor); + this.ship.rotateByQuaternion(rot); + + for(let t of this.thrusters){ + //todo: get the saved original position of the vertex to move and add the move vector to keep the shape of the thruster to keep a cone shape + t.points[3].x = t.points[0].x + (this.gondula.transform.forward.x * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[3].y = t.points[0].y + (this.gondula.transform.forward.y * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[3].z = t.points[0].z + (this.gondula.transform.forward.z * (1 + (-56 * (this.speed / this.speedMax)))); + + t.points[2].x = t.points[1].x + (this.gondula.transform.forward.x * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[2].y = t.points[1].y + (this.gondula.transform.forward.y * (1 + (-56 * (this.speed / this.speedMax)))); + t.points[2].z = t.points[1].z + (this.gondula.transform.forward.z * (1 + (-56 * (this.speed / this.speedMax)))); + } + + this.lensflares[this.lensflares.length - 1].jumpToPosition({ + x: this.ship.pos.x + (this.ship.transform.forward.x * -66) + (this.ship.transform.up.x * 22), + y: this.ship.pos.y + (this.ship.transform.forward.y * -66) + (this.ship.transform.up.y * 22), + z: this.ship.pos.z + (this.ship.transform.forward.z * -66) + (this.ship.transform.up.z * 22), + }, true); + this.lensflares[this.lensflares.length - 1].quadData[0].alpha = 1 * this.speedFactor;//0.2 + + this.trailTicker -= this.scene.dt; + for(let [j, t] of this.trails.entries()){ + if(this.trailTicker <= 0){ + for(let i = t.length - 1 ; i > 0 ; i--){ + this.shipTrailHistory[j][i] = this.shipTrailHistory[j][i-1] + } + } + this.shipTrailHistory[j][0] = this.ship.getWorldPositionOfQuad(this.shipSwooshOrigins[j]); + for(let p of this.shipTrailHistory[j][0]){ + p.x += this.ship.pos.x; + p.y += this.ship.pos.y; + p.z += this.ship.pos.z; + } + } + + for(let [j, t] of this.trails.entries()){//each trail + //this.swooshOrigins[j].jumpToPosition(this.ship.pos); + if(this.trailTicker <= 0){ + for(let i = t.length -1 ; i > 0 ; i--){//each trail quad / saved position + let q = t[i];//each quad + //jump end of trailpart to timesaved position + q.points[3].x = this.shipTrailHistory[j][i][0].x + this.shipTrailHistory[j][i][4].x; + q.points[3].y = this.shipTrailHistory[j][i][0].y + this.shipTrailHistory[j][i][4].y; + q.points[3].z = this.shipTrailHistory[j][i][0].z + this.shipTrailHistory[j][i][4].z; + q.points[2].x = this.shipTrailHistory[j][i][1].x + this.shipTrailHistory[j][i][4].x; + q.points[2].y = this.shipTrailHistory[j][i][1].y + this.shipTrailHistory[j][i][4].y; + q.points[2].z = this.shipTrailHistory[j][i][1].z + this.shipTrailHistory[j][i][4].z; + + //jump start of trailpart to timesaved previous position + q.points[0].x = this.shipTrailHistory[j][i-1][0].x + this.shipTrailHistory[j][i-1][4].x; + q.points[0].y = this.shipTrailHistory[j][i-1][0].y + this.shipTrailHistory[j][i-1][4].y; + q.points[0].z = this.shipTrailHistory[j][i-1][0].z + this.shipTrailHistory[j][i-1][4].z; + q.points[1].x = this.shipTrailHistory[j][i-1][1].x + this.shipTrailHistory[j][i-1][4].x; + q.points[1].y = this.shipTrailHistory[j][i-1][1].y + this.shipTrailHistory[j][i-1][4].y; + q.points[1].z = this.shipTrailHistory[j][i-1][1].z + this.shipTrailHistory[j][i-1][4].z; + } + } + //correct first trail part that is connected to the ship + //jump end of trailpart to timesaved position + t[0].points[3].x = this.shipTrailHistory[j][1][0].x + this.shipTrailHistory[j][1][4].x; + t[0].points[3].y = this.shipTrailHistory[j][1][0].y + this.shipTrailHistory[j][1][4].y; + t[0].points[3].z = this.shipTrailHistory[j][1][0].z + this.shipTrailHistory[j][1][4].z; + t[0].points[2].x = this.shipTrailHistory[j][1][1].x + this.shipTrailHistory[j][1][4].x; + t[0].points[2].y = this.shipTrailHistory[j][1][1].y + this.shipTrailHistory[j][1][4].y; + t[0].points[2].z = this.shipTrailHistory[j][1][1].z + this.shipTrailHistory[j][1][4].z; + + t[0].points[0].x = this.shipTrailHistory[j][0][0].x + this.shipTrailHistory[j][0][4].x; + t[0].points[0].y = this.shipTrailHistory[j][0][0].y + this.shipTrailHistory[j][0][4].y; + t[0].points[0].z = this.shipTrailHistory[j][0][0].z + this.shipTrailHistory[j][0][4].z; + t[0].points[1].x = this.shipTrailHistory[j][0][1].x + this.shipTrailHistory[j][0][4].x; + t[0].points[1].y = this.shipTrailHistory[j][0][1].y + this.shipTrailHistory[j][0][4].y; + t[0].points[1].z = this.shipTrailHistory[j][0][1].z + this.shipTrailHistory[j][0][4].z; + } + if(this.trailTicker <= 0){ + this.trailTicker = this.speed * 0.25; + } + } + + setDraw(_bool){ + this.ship.flags.draw = _bool + for(let l of this.lensflares){ + l.flags.draw = _bool; + } + for(let s of this.swooshOrigins){ + s.flags.draw = _bool; + } + } + + startNewLap(){ + //save and show last laptime + this.lapTimes.push(this.elapsedTime); + //this.last.lapTime = this.elapsedTime + if(this.isPlayer === true){ + this.level.startNewLap(); + } + + //start new lap time + this.startTime = Date.now(); + this.elapsedTime = Date.now() - this.startTime; + } + + restartOnFromSplineId(_splineId, _roll = 0){ + this.splineId = _splineId; + let splg = this.level.trackBuilder.spline[this.splineId]; + this.gondula.jumpToPosition({x: splg.x, y: splg.y, z: splg.z}); + + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.gondula.transform.toVectorArray( this.gondula.transform.forward), + [0, 0, 1] + ) + this.gondula.rotateByQuaternion(targetRot); + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.gondula.transform.toVectorArray( this.gondula.transform.right), + [1, 0, 0] + ) + this.gondula.rotateByQuaternion(targetRot); + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.gondula.transform.toVectorArray( this.gondula.transform.up), + [0, -1, 0] + ) + this.gondula.rotateByQuaternion(targetRot); + + this.gondula.rotateAroundAxis(this.gondula.transform.toVectorArray(this.gondula.transform.forward), _roll); + + this.speed = 0; + + + //start from hangar? + if(this.level.startFromHangar === true){ + this.gondula.jumpToPosition({x: this.gondula.pos.x + (this.gondula.transform.up.x * -244), y: this.gondula.pos.y + (this.gondula.transform.up.y * -244), z: this.gondula.pos.z + (this.gondula.transform.up.z * -244)});//y 468-128-96 init start + this.shipAnchor.jumpToPosition({x: this.gondula.pos.x + (this.gondula.transform.up.x * -96), y: this.gondula.pos.y + (this.gondula.transform.up.y * -96), z: this.gondula.pos.z + (this.gondula.transform.up.z * -96)}, true); + this.ship.jumpToPosition({x: this.gondula.pos.x + (this.gondula.transform.up.x * -96), y: this.gondula.pos.y + (this.gondula.transform.up.y * -96), z: this.gondula.pos.z + (this.gondula.transform.up.z * -96)}, true); + } + } + + jumpToSplineId(_splineId, _roll = 0){ + this.splineId = _splineId; + let splg = this.level.trackBuilder.spline[this.splineId]; + this.gondula.jumpToPosition({x: splg.x, y: splg.y, z: splg.z}); + + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.gondula.transform.toVectorArray( this.gondula.transform.forward), + [0, 0, 1] + ) + this.gondula.rotateByQuaternion(targetRot); + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.gondula.transform.toVectorArray( this.gondula.transform.right), + [1, 0, 0] + ) + this.gondula.rotateByQuaternion(targetRot); + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + this.gondula.transform.toVectorArray( this.gondula.transform.up), + [0, -1, 0] + ) + this.gondula.rotateByQuaternion(targetRot); + + this.gondula.rotateAroundAxis(this.gondula.transform.toVectorArray(this.gondula.transform.forward), _roll); + + this.speed = 0; + + + //start from hangar? + if(this.level.startFromHangar === true){ + this.gondula.jumpToPosition({x: this.gondula.pos.x + (this.gondula.transform.up.x * -244), y: this.gondula.pos.y + (this.gondula.transform.up.y * -244), z: this.gondula.pos.z + (this.gondula.transform.up.z * -244)});//y 468-128-96 init start + this.shipAnchor.jumpToPosition({x: this.gondula.pos.x + (this.gondula.transform.up.x * -96), y: this.gondula.pos.y + (this.gondula.transform.up.y * -96), z: this.gondula.pos.z + (this.gondula.transform.up.z * -96)}, true); + this.ship.jumpToPosition({x: this.gondula.pos.x + (this.gondula.transform.up.x * -96), y: this.gondula.pos.y + (this.gondula.transform.up.y * -96), z: this.gondula.pos.z + (this.gondula.transform.up.z * -96)}, true); + } + } + + inputPlayer(){ + //acceleration + + this.keyInput.spd = 0; + this.keyInput.pitch = 0; + if(INPUTS.triggerRight.amount > 0.1){ + this.input.spd = this.acceleration; + this.keyInput.spd = 1; + this.keyInput.pitch = 1; + }else{ + this.input.spd = this.deceleration; + if(INPUTS.triggerLeft.amount > 0.1){//redundant? + this.keyInput.spd = -1; + } + } + if(INPUTS.triggerLeft.amount > 0.1){ + this.input.spd = this.brakes; + this.keyInput.spd = -1; + this.keyInput.pitch = -1; + } + //instant acceleration with bonus + //todo: slipstreaming is the same, but without better acceleration + /* + if(this.scene.keys.space.isDown){ + this.input.spd = 1; + this.speedBonus = 4; + this.speed += 4; + this.speed = Math.min(this.speedMax + this.speedBonus, this.speed); + this.speed = this.speedMax + this.speedBonus; + }else{ + this.speedBonus = 0; + } + */ + + //roll + this.input.roll = Math.abs(INPUTS.stickLeft.horizontal) > 0.1 ? INPUTS.stickLeft.horizontal : 0; + + if (this.scene.hand.pressed === true && isMobile === true) { + //todo: maybe only look around with touch when touching in upper area + let hAmt = (this.scene.hand.pos.x - this.scene.hand.start.x) * 0.005; + if(hAmt > 0.05 || hAmt < 0.05){ + this.input.roll += hAmt; + } + this.input.roll = Math.max(-1, Math.min(1, this.input.roll)); + + let vAmt = (this.scene.hand.pos.y - this.scene.hand.start.y) * 0.005; + if(vAmt > 0.05){ + this.input.spd = this.brakes; + this.keyInput.spd = -1; + this.keyInput.pitch = -1; + }else{ + this.input.spd = this.acceleration; + this.keyInput.spd = 1; + this.keyInput.pitch = 1; + } + + this.scene.hand.start.x = this.scene.hand.pos.x; + //this.scene.hand.start.y = this.scene.hand.pos.y; + } + if(this.scene.hand.pressed === false && isMobile === true){ + this.input.spd = this.deceleration; + this.keyInput.spd = -1; + } + + let curveDelta = Math.max(-1, Math.min((this.last.curveAmt - this.curveAmt) , 1)); + /*if(this.curveAmt > this.ai.curveRec){ + this.ai.curveRec = this.curveAmt; + console.log("new rec"); + }else if(this.curveAmt < this.ai.curveRec){ + console.log("wrong dir") + this.ai.curveRec = -9999; + }*/ + //if(Math.abs(curveDelta) > 0.12){ + //console.log(curveDelta) //true is good + //} + //console.log(this.curveAmt) + //console.log(this.last.speedBonus - this.speedBonus) + //console.log(this.curveAmt > this.last.curveAmt) + //console.log(this.last.curveAmt - this.curveAmt) + } + + inputAI(_bonusRef){ + //dumb forward + this.input.spd = this.acceleration; + this.keyInput.spd = 1; + this.keyInput.pitch = 1; + + /* //manual gas for testing + this.input.spd = 0; + this.keyInput.spd = 0; + this.keyInput.pitch = 0; + if(INPUTS.triggerRight.amount > 0.1){ + this.input.spd = this.acceleration; + this.keyInput.spd = 1; + this.keyInput.pitch = 1; + }else{ + this.input.spd = this.deceleration; + if(INPUTS.triggerLeft.amount > 0.1){//redundant? + this.keyInput.spd = -1; + } + } + if(INPUTS.triggerLeft.amount > 0.1){ + this.input.spd = this.brakes; + this.keyInput.spd = -1; + this.keyInput.pitch = -1; + } + */ + + this.input.roll = 0; + + let avoid = [0, 0, 0] + //check Collisions + let collCheckArr = [ + {//check forward of ship + pos: { + x: this.shipAnchor.pos.x, + y: this.shipAnchor.pos.y, + z: this.shipAnchor.pos.z + }, + dir: { + x: this.shipAnchor.transform.forward.x, + y: this.shipAnchor.transform.forward.y, + z: this.shipAnchor.transform.forward.z + }, + hit: [] + },{//check forward right of ship for booster + pos: { + x: this.shipAnchor.pos.x + (this.shipAnchor.transform.right.x * 48), + y: this.shipAnchor.pos.y + (this.shipAnchor.transform.right.y * 48), + z: this.shipAnchor.pos.z + (this.shipAnchor.transform.right.z * 48) + }, + dir: { + x: this.shipAnchor.transform.forward.x, + y: this.shipAnchor.transform.forward.y, + z: this.shipAnchor.transform.forward.z + }, + hit: [] + },{//check forward left of ship for booster + pos: { + x: this.shipAnchor.pos.x + (this.shipAnchor.transform.right.x * -48), + y: this.shipAnchor.pos.y + (this.shipAnchor.transform.right.y * -48), + z: this.shipAnchor.pos.z + (this.shipAnchor.transform.right.z * -48) + }, + dir: { + x: this.shipAnchor.transform.forward.x, + y: this.shipAnchor.transform.forward.y, + z: this.shipAnchor.transform.forward.z + }, + hit: [] + } + ]; + let toCollideWith = []; + for(let o of this.level.trackBuilder.obstacles){ + if(o.data.id+1 > this.splineId){ + if(o.trigger.isTrigger === false){ + toCollideWith.push(o); + } + } + } + for(let m of toCollideWith){ + if (m.flags.update === true){ + //m.update(); + //INFOalready updated in the actual update + } + for (let q of m.collisionData){ + for(let c of collCheckArr){ + let hitData = this.scene.geometryController.collide(q, c); + if(hitData.pt !== null){ + hitData.model = m; + c.hit.push(hitData); + } + } + } + } + let alreadyColliding = false; + let returnColl = collCheckArr; + //resolve collision with forward + if (returnColl[0].hit.length > 0) { + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[0].hit[0]; + for (let [i, n] of returnColl[0].hit.entries()) { + let d = eud.distance([this.shipAnchor.pos.x, this.shipAnchor.pos.y, this.shipAnchor.pos.z], returnColl[0].hit[i].pt) + if (d < dist) { + dist = d; + nearestHit = returnColl[0].hit[i]; + } + } + if(dist < 2024){ + avoid[0] = dist; + } + if(dist < 128){ + alreadyColliding = true; + if(nearestHit.model.trigger.isTrigger === false){ + //console.log(returnColl[0]); + /* + if(this.speed > 0){ + this.scene.soundManager.playRandomSound(this.scene.soundManager.bumpSound); + } + + this.input.spd = 0; + this.speed = 0; + if(nearestHit.model.data.roll !== undefined){ + this.input.roll = nearestHit.model.data.roll * 2; + }*/ + + }else{ + //nearestHit.model.updateTrigger(); + } + } + } + //check booster only if collision free + if(alreadyColliding === false){ + //resolve collision with forward right and then left of ship for boost + for(let j = 1 ; j < 3 ; j++){ + if (returnColl[j].hit.length > 0) { + //filter relevant = nearest hit + let dist = 9999; + let nearestHit = returnColl[j].hit[0]; + for (let [i, n] of returnColl[j].hit.entries()) { + let d = eud.distance([returnColl[j].pos.x, returnColl[j].pos.y, returnColl[j].pos.z], returnColl[j].hit[i].pt) + if (d < dist) { + dist = d; + nearestHit = returnColl[j].hit[i]; + } + } + if(dist < 2024){ + avoid[j] = dist; + } + if(dist < 128){ + if(nearestHit.model.trigger.isTrigger === false){ + /*if(this.speed > (this.speedMax * 0.25) && this.input.spd >= 0){ + this.input.spd = 1; + this.speed = this.speedMax * this.nearmissBoost; + if(this.isPlayer === true){ + if(this.scene.cam.fov < 3.5){//todo: find a good value for the boost effect + this.scene.cam.fov += 1 * this.scene.dt; + this.scene.cam.fov = Math.min(this.scene.cam.fov, 3.5); + } + //sound + this.scene.soundManager.playRandomSound(this.scene.soundManager.swooshSound); + } + }*/ + }else{ + //nearestHit.model.updateTrigger(); + } + } + } + } + } + + //switch to dodge mode if obstacle comes up + if(avoid[0] > 0 || avoid[1] > 0 || avoid[2] > 0){ + this.ai.navState = this.ai.navStates.dodge; + } + + //smaller than 0 delta is good + let curveDelta = this.last.curveAmt - this.curveAmt;//Math.max(-1, Math.min((this.last.curveAmt - this.curveAmt) , 1)); + let speedDelta = this.last.speedBonus - this.speedBonus; + //cooling strategy? + /*if(curveDelta > 0){ + this.input.roll = -curveDelta; + }*/ + + /* + //todo: best one yet + this.input.roll = this.ai.prefRoll; + if(curveDelta > 0){ + if(this.ai.waitRoll <= 0){ + this.ai.prefRoll *= -1; + this.input.roll = 0; + //wait a bit until switching roll direction again + if(this.curveAmt > 0.01){ + this.ai.waitRoll = 1; + }else{ + this.ai.waitRoll = 15; + } + }else{ + this.ai.waitRoll -= 1 * this.scene.dt; + } + } + */ + switch(this.ai.navState){ + case this.ai.navStates.seek: + //todo: works okay-ish but still gets overpowered by curveAmt delta fluctuations when already on right track or halfway between good or bad + //todo: because the fluctuation values are as small as a roll would be + + if(this.curveAmt > this.ai.curveRec){ + this.ai.curveRec = this.curveAmt; + this.input.roll = this.ai.prefRoll; + this.ai.lastGoodPrefRoll = this.ai.prefRoll; + //console.log(curveDelta) + } + if(curveDelta > 0 && curveDelta < 0.003){ + //console.log("flipping") + //this.ai.prefRoll *= -1; + this.ai.prefRoll = this.ai.lastGoodPrefRoll * -1; + } + if(this.curveAmt < 0){ + this.ai.curveRec = -9999; + //console.log("wrong side") + }else{ + this.ai.waitRoll -= 1 * this.scene.dt; + if(this.ai.waitRoll <= 0){ + this.ai.waitRoll = 30; + this.ai.curveRec = -9999; + } + } + + break; + case this.ai.navStates.wait: + this.ai.waitRoll -= 1 * this.scene.dt; + if(this.ai.waitRoll <= 0 || curveDelta >= 2){ + if(curveDelta > 2){ + //console.log("curve changed > seek"); + } + this.ai.navState = this.ai.navStates.seek; + this.ai.curveRec = -9999; + } + break; + case this.ai.navStates.dodge: + //dodge + let finishedDodging = true; + if(avoid[0] > 0){ + this.input.roll = this.ai.prefRoll; + if(avoid[0] < 1024){ + this.input.spd = this.brakes; + }else{ + this.input.spd = this.deceleration; + } + this.keyInput.spd = -1; + this.keyInput.pitch = -1; + //console.log("collision happening or imminent") + finishedDodging = false; + } + else if(avoid[1] > 0){ + this.input.roll = -1; + this.ai.prefRoll = -1; + this.input.spd = this.acceleration; + this.keyInput.spd = 1; + this.keyInput.pitch = 1; + //console.log("left") + finishedDodging = false; + } + else if(avoid[2] > 0){ + this.input.roll = 1; + this.ai.prefRoll = 1; + this.input.spd = this.acceleration; + this.keyInput.spd = 1; + this.keyInput.pitch = 1; + //console.log("right") + finishedDodging = false; + } + if(finishedDodging === true){ + this.ai.navState = this.ai.navStates.seek; + } + break; + default: + break; + } + + + + } +} \ No newline at end of file diff --git a/src/3d/racing/trackBuilder.js b/src/3d/racing/trackBuilder.js new file mode 100644 index 0000000..5b053a6 --- /dev/null +++ b/src/3d/racing/trackBuilder.js @@ -0,0 +1,2145 @@ + +import Transform from "../transform.js"; + +export default class TrackBuilder { + constructor(_scene, _level) { + this.scene = _scene; + this.level = _level; + + this.ref = this.scene.geometryController.loadModel("debug Arrow", "modDebugArrow", { x: 0, y: 0, z: 0 }); + //this.ref.flags.draw = true; + + this.currentTrackId = 0; + this.ringDeepness = 64; + + this.spline = []; + this.rings = []; + this.obstacles = []; + //add fresh spline points but set the future directions + + /* + 80 rings of ringDeepness 64 complete a circle when pitch is Math.PI * -0.025; + */ + + this.textureArrays = { + fullColor: [ + [{ "texture": "atlasAll", "frame": "flatPal00Black" }, { "texture": "atlasAll", "frame": "flatPal00Black" }, { "texture": "atlasAll", "frame": "flatPal00Black" }, { "texture": "atlasAll", "frame": "flatPal00Black" }, { "texture": "atlasAll", "frame": "flatPal00Black" }, { "texture": "atlasAll", "frame": "flatPal00Black" }, { "texture": "atlasAll", "frame": "flatPal00Black" }, { "texture": "atlasAll", "frame": "flatPal00Black" }, { "texture": "atlasAll", "frame": "flatPal00Black" }, { "texture": "atlasAll", "frame": "flatPal00Black" }, { "texture": "atlasAll", "frame": "flatPal00Black" }, { "texture": "atlasAll", "frame": "flatPal00Black" }, { "texture": "atlasAll", "frame": "flatPal00Black" }, { "texture": "atlasAll", "frame": "flatPal00Black" }, { "texture": "atlasAll", "frame": "flatPal00Black" }, { "texture": "atlasAll", "frame": "flatPal00Black" }], + [{ "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }], + //green grid + [{ "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }], + //green racing line + [{ "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix01l" }, { "texture": "atlasAll", "frame": "matrix01r" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }], + //green racing line and red grid + [{ "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix01l" }, { "texture": "atlasAll", "frame": "matrix01r" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00red" }, { "texture": "atlasAll", "frame": "matrix00red" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }], + //translucent blue and red grid + [{ "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00greenblue" }, { "texture": "atlasAll", "frame": "matrix00greenblue" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00red" }, { "texture": "atlasAll", "frame": "matrix00red" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }, { "texture": "atlasAll", "frame": "matrix00" }] + ], + metalRoad: [ + //todo: missed the blue white lights + [{ "texture": "atlasAll", "frame": "scaffolding02Gangway-2" }, { "texture": "atlasAll", "frame": "flatPal00Brown" }, { "texture": "atlasAll", "frame": "flatPal00Brown" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }, { "texture": "atlasAll", "frame": "flatPal00Brown" }, { "texture": "atlasAll", "frame": "flatPal00Brown" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-1" }, { "texture": "atlasAll", "frame": "texWallGrind01l" }, { "texture": "atlasAll", "frame": "texMetroPlatformWall02" }, { "texture": "atlasAll", "frame": "texMetroPlatformWall02" }, { "texture": "atlasAll", "frame": "texWallGrind01r" }, { "texture": "atlasAll", "frame": "texWallGrind01l" }, { "texture": "atlasAll", "frame": "texMetroPlatformWall02" }, { "texture": "atlasAll", "frame": "texMetroPlatformWall02" }, { "texture": "atlasAll", "frame": "texWallGrind01r" }] + ], + canyonBoth: [ + [{ "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt01r" }, { "texture": "atlasAll", "frame": "texDirt01l" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt01r" }, { "texture": "atlasAll", "frame": "texDirt01l" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }], + [{ "texture": "atlasAll", "frame": "scaffolding02-6" }, { "texture": "atlasAll", "frame": "scaffolding02-7" }, { "texture": "atlasAll", "frame": "texBricksBrownEnd02" }, { "texture": "atlasAll", "frame": "texDirt01r" }, { "texture": "atlasAll", "frame": "texDirt01l" }, { "texture": "atlasAll", "frame": "texBricksBrownEnd03" }, { "texture": "atlasAll", "frame": "scaffolding02-4" }, { "texture": "atlasAll", "frame": "scaffolding02-5" }, { "texture": "atlasAll", "frame": "scaffolding02-6" }, { "texture": "atlasAll", "frame": "scaffolding02-7" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt01r" }, { "texture": "atlasAll", "frame": "texDirt01l" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "scaffolding02-4" }, { "texture": "atlasAll", "frame": "scaffolding02-5" }], + [{"texture":"atlasAll","frame":"scaffolding02-10"},{"texture":"atlasAll","frame":"scaffolding02-11"},{"texture":"atlasAll","frame":"texBricksBrownEnd02"},{"texture":"atlasAll","frame":"texDirt01r"},{"texture":"atlasAll","frame":"texDirt01l"},{"texture":"atlasAll","frame":"texBricksBrownEnd03"},{"texture":"atlasAll","frame":"scaffolding02-8"},{"texture":"atlasAll","frame":"scaffolding02-9"},{"texture":"atlasAll","frame":"scaffolding02-10"},{"texture":"atlasAll","frame":"scaffolding02-11"},{"texture":"atlasAll","frame":"texDirt00"},{"texture":"atlasAll","frame":"texDirt01r"},{"texture":"atlasAll","frame":"texDirt01l"},{"texture":"atlasAll","frame":"texDirt00"},{"texture":"atlasAll","frame":"scaffolding02-8"},{"texture":"atlasAll","frame":"scaffolding02-9"}], + [{"texture":"atlasAll","frame":"texBricksBrown00"},{"texture":"atlasAll","frame":"texBricksBrown00"},{"texture":"atlasAll","frame":"texBricksBrownEnd02"},{"texture":"atlasAll","frame":"texDirt01r"},{"texture":"atlasAll","frame":"texDirt01l"},{"texture":"atlasAll","frame":"texBricksBrownEnd03"},{"texture":"atlasAll","frame":"texBricksBrown00"},{"texture":"atlasAll","frame":"texBricksBrown00"},{"texture":"atlasAll","frame":"scaffolding02Gangway-9"},{"texture":"atlasAll","frame":"texMetalHangar00"},{"texture":"atlasAll","frame":"texMetalHangar00"},{"texture":"atlasAll","frame":"texMetalHangar07l"},{"texture":"atlasAll","frame":"texMetalHangar07r"},{"texture":"atlasAll","frame":"texMetalHangar00"},{"texture":"atlasAll","frame":"texMetalHangar00"},{"texture":"atlasAll","frame":"scaffolding02Gangway-6"}] + ], + canyon: [ + [{ "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt01r" }, { "texture": "atlasAll", "frame": "texDirt01l" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }], + [{ "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-8" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark06" }, { "texture": "atlasAll", "frame": "texMetalDark06" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-11" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt01r" }, { "texture": "atlasAll", "frame": "texDirt01l" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }, { "texture": "atlasAll", "frame": "texDirt00" }], + [{"texture":"atlasAll","frame":"texDirt00"},{"texture":"atlasAll","frame":"scaffolding02Gangway-8"},{"texture":"atlasAll","frame":"texMetalDark04"},{"texture":"atlasAll","frame":"texMetalDark06"},{"texture":"atlasAll","frame":"texMetalDark06"},{"texture":"atlasAll","frame":"texMetalDark04"},{"texture":"atlasAll","frame":"scaffolding02Gangway-11"},{"texture":"atlasAll","frame":"texDirt00"},{"texture":"atlasAll","frame":"texDirt00"},{"texture":"atlasAll","frame":"texDirt00"},{"texture":"atlasAll","frame":"texDirt00"},{"texture":"atlasAll","frame":"texDirt01r"},{"texture":"atlasAll","frame":"texDirt01l"},{"texture":"atlasAll","frame":"texDirt00"},{"texture":"atlasAll","frame":"texDirt00"},{"texture":"atlasAll","frame":"texDirt00"}] + ], + darkMetalRing: [ + [{ "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texMetroPlatformWall05" }, { "texture": "atlasAll", "frame": "texMetroPlatformWall05" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }], + [{ "texture": "atlasAll", "frame": "texWallGrind03Ar" }, { "texture": "atlasAll", "frame": "texWallGrind03Al" }, { "texture": "atlasAll", "frame": "texWallGrind03Ar" }, { "texture": "atlasAll", "frame": "texWallGrind03Al" }, { "texture": "atlasAll", "frame": "texWallGrind03Ar" }, { "texture": "atlasAll", "frame": "texWallGrind03Al" }, { "texture": "atlasAll", "frame": "texWallGrind03Ar" }, { "texture": "atlasAll", "frame": "texWallGrind03Al" }, { "texture": "atlasAll", "frame": "texWallGrind03Ar" }, { "texture": "atlasAll", "frame": "texWallGrind03Al" }, { "texture": "atlasAll", "frame": "texWallGrind03Ar" }, { "texture": "atlasAll", "frame": "texWallGrind03Al" }, { "texture": "atlasAll", "frame": "texWallGrind03Ar" }, { "texture": "atlasAll", "frame": "texWallGrind03Al" }, { "texture": "atlasAll", "frame": "texWallGrind03Ar" }, { "texture": "atlasAll", "frame": "texWallGrind03Al" }], + [{ "texture": "atlasAll", "frame": "texWallGrind03rArrow" }, { "texture": "atlasAll", "frame": "texWallGrind03Al" }, { "texture": "atlasAll", "frame": "texWallGrind03Ar" }, { "texture": "atlasAll", "frame": "texWallGrind03Al" }, { "texture": "atlasAll", "frame": "texWallGrind03Ar" }, { "texture": "atlasAll", "frame": "texWallGrind03Al" }, { "texture": "atlasAll", "frame": "texWallGrind03Ar" }, { "texture": "atlasAll", "frame": "texWallGrind03lArrow" }, { "texture": "atlasAll", "frame": "texWallGrind03rArrow" }, { "texture": "atlasAll", "frame": "texWallGrind03Al" }, { "texture": "atlasAll", "frame": "texWallGrind03Ar" }, { "texture": "atlasAll", "frame": "texWallGrind03Al" }, { "texture": "atlasAll", "frame": "texWallGrind03Ar" }, { "texture": "atlasAll", "frame": "texWallGrind03Al" }, { "texture": "atlasAll", "frame": "texWallGrind03Ar" }, { "texture": "atlasAll", "frame": "texWallGrind03lArrow" }] + ], + darkMetalArrows: [ + [{ "texture": "atlasAll", "frame": "darkMetalArrows-2" }, { "texture": "atlasAll", "frame": "darkMetalArrows-3" }, { "texture": "atlasAll", "frame": "darkMetalArrows-0" }, { "texture": "atlasAll", "frame": "darkMetalArrows-1" }, { "texture": "atlasAll", "frame": "darkMetalArrows-2" }, { "texture": "atlasAll", "frame": "darkMetalArrows-3" }, { "texture": "atlasAll", "frame": "darkMetalArrows-0" }, { "texture": "atlasAll", "frame": "darkMetalArrows-1" }, { "texture": "atlasAll", "frame": "darkMetalArrows-2" }, { "texture": "atlasAll", "frame": "darkMetalArrows-3" }, { "texture": "atlasAll", "frame": "darkMetalArrows-0" }, { "texture": "atlasAll", "frame": "darkMetalArrows-1" }, { "texture": "atlasAll", "frame": "darkMetalArrows-2" }, { "texture": "atlasAll", "frame": "darkMetalArrows-3" }, { "texture": "atlasAll", "frame": "darkMetalArrows-0" }, { "texture": "atlasAll", "frame": "darkMetalArrows-1" }], + [{ "texture": "atlasAll", "frame": "darkMetalArrows-6" }, { "texture": "atlasAll", "frame": "darkMetalArrows-7" }, { "texture": "atlasAll", "frame": "darkMetalArrows-4" }, { "texture": "atlasAll", "frame": "darkMetalArrows-5" }, { "texture": "atlasAll", "frame": "darkMetalArrows-6" }, { "texture": "atlasAll", "frame": "darkMetalArrows-7" }, { "texture": "atlasAll", "frame": "darkMetalArrows-4" }, { "texture": "atlasAll", "frame": "darkMetalArrows-5" }, { "texture": "atlasAll", "frame": "darkMetalArrows-6" }, { "texture": "atlasAll", "frame": "darkMetalArrows-7" }, { "texture": "atlasAll", "frame": "darkMetalArrows-4" }, { "texture": "atlasAll", "frame": "darkMetalArrows-5" }, { "texture": "atlasAll", "frame": "darkMetalArrows-6" }, { "texture": "atlasAll", "frame": "darkMetalArrows-7" }, { "texture": "atlasAll", "frame": "darkMetalArrows-4" }, { "texture": "atlasAll", "frame": "darkMetalArrows-5" }], + [{ "texture": "atlasAll", "frame": "darkMetalArrows-10" }, { "texture": "atlasAll", "frame": "darkMetalArrows-11" }, { "texture": "atlasAll", "frame": "darkMetalArrows-8" }, { "texture": "atlasAll", "frame": "darkMetalArrows-9" }, { "texture": "atlasAll", "frame": "darkMetalArrows-10" }, { "texture": "atlasAll", "frame": "darkMetalArrows-11" }, { "texture": "atlasAll", "frame": "darkMetalArrows-8" }, { "texture": "atlasAll", "frame": "darkMetalArrows-9" }, { "texture": "atlasAll", "frame": "darkMetalArrows-10" }, { "texture": "atlasAll", "frame": "darkMetalArrows-11" }, { "texture": "atlasAll", "frame": "darkMetalArrows-8" }, { "texture": "atlasAll", "frame": "darkMetalArrows-9" }, { "texture": "atlasAll", "frame": "darkMetalArrows-10" }, { "texture": "atlasAll", "frame": "darkMetalArrows-11" }, { "texture": "atlasAll", "frame": "darkMetalArrows-8" }, { "texture": "atlasAll", "frame": "darkMetalArrows-9" }] + ], + startFinish: [ + [{ "texture": "atlasAll", "frame": "texStartFinish02" }, { "texture": "atlasAll", "frame": "texStartFinish03" }, { "texture": "atlasAll", "frame": "texStartFinish02" }, { "texture": "atlasAll", "frame": "texStartFinish03" }, { "texture": "atlasAll", "frame": "texStartFinish02" }, { "texture": "atlasAll", "frame": "texStartFinish03" }, { "texture": "atlasAll", "frame": "texStartFinish02" }, { "texture": "atlasAll", "frame": "texStartFinish03" }, { "texture": "atlasAll", "frame": "texStartFinish02" }, { "texture": "atlasAll", "frame": "texStartFinish03" }, { "texture": "atlasAll", "frame": "texStartFinish02" }, { "texture": "atlasAll", "frame": "texStartFinish03" }, { "texture": "atlasAll", "frame": "texStartFinish02" }, { "texture": "atlasAll", "frame": "texStartFinish03" }, { "texture": "atlasAll", "frame": "texStartFinish02" }, { "texture": "atlasAll", "frame": "texStartFinish03" }], + [{ "texture": "atlasAll", "frame": "texStartFinish03" }, { "texture": "atlasAll", "frame": "texStartFinish02" }, { "texture": "atlasAll", "frame": "texStartFinish05" }, { "texture": "atlasAll", "frame": "texStartFinish04" }, { "texture": "atlasAll", "frame": "texStartFinish05" }, { "texture": "atlasAll", "frame": "texStartFinish04" }, { "texture": "atlasAll", "frame": "texStartFinish03" }, { "texture": "atlasAll", "frame": "texStartFinish02" }, { "texture": "atlasAll", "frame": "texStartFinish03" }, { "texture": "atlasAll", "frame": "texStartFinish02" }, { "texture": "atlasAll", "frame": "texStartFinish03" }, { "texture": "atlasAll", "frame": "texStartFinish02" }, { "texture": "atlasAll", "frame": "texStartFinish03" }, { "texture": "atlasAll", "frame": "texStartFinish02" }, { "texture": "atlasAll", "frame": "texStartFinish03" }, { "texture": "atlasAll", "frame": "texStartFinish02" }] + ], + metroMetalRing: [ + [{ "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texMetroTunnelRails02" }, { "texture": "atlasAll", "frame": "texMetroTunnelRails03" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarLight00" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetroTunnelRails02" }, { "texture": "atlasAll", "frame": "texMetroTunnelRails03" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangarLight00" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }] + ], + metroRail: [ + [{ "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetroTunnelRails02" }, { "texture": "atlasAll", "frame": "texMetroTunnelRails03" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texBricksBrownEnd01" }, { "texture": "atlasAll", "frame": "texBricksBrown00" }, { "texture": "atlasAll", "frame": "texBricksBrown00" }, { "texture": "atlasAll", "frame": "texBricksBrown00" }, { "texture": "atlasAll", "frame": "texBricksBrown00" }, { "texture": "atlasAll", "frame": "texBricksBrown00" }, { "texture": "atlasAll", "frame": "texBricksBrown00" }, { "texture": "atlasAll", "frame": "texBricksBrownEnd00" }], + [{ "texture": "atlasAll", "frame": "texWallGrind09r" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetroTunnelRails02" }, { "texture": "atlasAll", "frame": "texMetroTunnelRails03" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texWallGrind09l" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "texWallGrind01r" }, { "texture": "atlasAll", "frame": "texWallGrind01l" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }] + ], + metroBlade: [ + [{ "texture": "atlasObstacles", "frame": "obstMetroLight0000" }, { "texture": "atlasObstacles", "frame": "obstMetroLight0100" }, { "texture": "atlasObstacles", "frame": "obstMetroLight0200" }, { "texture": "atlasObstacles", "frame": "obstMetroLight0300" }], + [{ "texture": "atlasObstacles", "frame": "obstMetroLightShort0000" }, { "texture": "atlasObstacles", "frame": "obstMetroLightShort0100" }, { "texture": "atlasObstacles", "frame": "obstMetroLightShort0200" }, { "texture": "atlasObstacles", "frame": "obstMetroLightShort0300" }] + ], + metroVentBlade: [ + [{ "texture": "atlasObstacles", "frame": "texAirVentRotor01" }, { "texture": "atlasObstacles", "frame": "obstDarkDoor0000" }, { "texture": "atlasObstacles", "frame": "obstDarkDoor0000" }, { "texture": "atlasObstacles", "frame": "obstDarkDoor0000" }], + [{ "texture": "atlasObstacles", "frame": "texAirVentRotor01" }, { "texture": "atlasObstacles", "frame": "obstDarkDoor0000" }, { "texture": "atlasObstacles", "frame": "obstDarkDoor0000" }, { "texture": "atlasObstacles", "frame": "obstDarkDoor0000" }] + ], + energySlide: [ + [{ "texture": "atlasAll", "frame": "texMetalHangar01" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texMetroPlatformWall05" }, { "texture": "atlasAll", "frame": "texMetroPlatformWall05" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }, { "texture": "atlasAll", "frame": "texMetalHangar01" }, { "texture": "atlasAll", "frame": "texEnergy00" }, { "texture": "atlasAll", "frame": "texEnergy00" }, { "texture": "atlasAll", "frame": "texEnergy00" }, { "texture": "atlasAll", "frame": "texEnergy00" }, { "texture": "atlasAll", "frame": "texEnergy00" }, { "texture": "atlasAll", "frame": "texEnergy00" }, { "texture": "atlasAll", "frame": "texEnergy00" }, { "texture": "atlasAll", "frame": "texEnergy00" }] + ], + sewer: [ + [{ "texture": "atlasAll", "frame": "texBricksBrownEnd03" }, { "texture": "atlasAll", "frame": "texBricksBrown00" }, { "texture": "atlasAll", "frame": "texBricksBrown00" }, { "texture": "atlasAll", "frame": "texBricksBrownEnd00" }, { "texture": "atlasAll", "frame": "texBricksBrownEnd01" }, { "texture": "atlasAll", "frame": "texBricksBrown00" }, { "texture": "atlasAll", "frame": "texBricksBrown00" }, { "texture": "atlasAll", "frame": "texBricksBrownEnd02" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind02l" }, { "texture": "atlasAll", "frame": "texWallGrind02r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind02l" }, { "texture": "atlasAll", "frame": "texWallGrind02r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }], + [{ "texture": "atlasAll", "frame": "texBricksBrownEnd03" }, { "texture": "atlasAll", "frame": "texBricksBrown00" }, { "texture": "atlasAll", "frame": "texBricksBrown00" }, { "texture": "atlasAll", "frame": "texBricksBrownEnd00" }, { "texture": "atlasAll", "frame": "texBricksBrownEnd01" }, { "texture": "atlasAll", "frame": "texBricksBrown00" }, { "texture": "atlasAll", "frame": "texBricksBrown00" }, { "texture": "atlasAll", "frame": "texBricksBrownEnd02" }, { "texture": "atlasAll", "frame": "texMetalHangarLight00" }, { "texture": "atlasAll", "frame": "texWallGrind02l" }, { "texture": "atlasAll", "frame": "texWallGrind02r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind02l" }, { "texture": "atlasAll", "frame": "texWallGrind02r" }, { "texture": "atlasAll", "frame": "texMetalHangarLight00" }], + [{ "texture": "atlasAll", "frame": "texBricksBrownEnd03" }, { "texture": "atlasAll", "frame": "texBricksBrown00" }, { "texture": "atlasAll", "frame": "texBricksBrown00" }, { "texture": "atlasAll", "frame": "texBricksBrownEnd00" }, { "texture": "atlasAll", "frame": "texBricksBrownEnd01" }, { "texture": "atlasAll", "frame": "texBricksBrown00" }, { "texture": "atlasAll", "frame": "texBricksBrown00" }, { "texture": "atlasAll", "frame": "texBricksBrownEnd02" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind02l" }, { "texture": "atlasAll", "frame": "texWallGrind02r" }, { "texture": "atlasAll", "frame": "texMetalHangarLight00" }, { "texture": "atlasAll", "frame": "texMetalHangarLight00" }, { "texture": "atlasAll", "frame": "texWallGrind02l" }, { "texture": "atlasAll", "frame": "texWallGrind02r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }] + ], + atom: [ + [{ "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind12l" }, { "texture": "atlasAll", "frame": "texWallGrind10r" }, { "texture": "atlasAll", "frame": "texWallGrind10l" }, { "texture": "atlasAll", "frame": "texWallGrind12r" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }, { "texture": "atlasAll", "frame": "flatPal00Brown" }, { "texture": "atlasAll", "frame": "flatPal00Brown" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }, { "texture": "atlasAll", "frame": "flatPal00Brown" }, { "texture": "atlasAll", "frame": "flatPal00Brown" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }, { "texture": "atlasAll", "frame": "texMetalHangar10" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }], + [{ "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind12l" }, { "texture": "atlasAll", "frame": "texWallGrind10r" }, { "texture": "atlasAll", "frame": "texWallGrind10l" }, { "texture": "atlasAll", "frame": "texWallGrind12r" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }, { "texture": "atlasAll", "frame": "texWallAtom00r" }, { "texture": "atlasAll", "frame": "flatPal00Brown" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }, { "texture": "atlasAll", "frame": "flatPal00Brown" }, { "texture": "atlasAll", "frame": "texWallAtom00l" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }, { "texture": "atlasAll", "frame": "texMetalHangar10" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }], + [{ "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind12l" }, { "texture": "atlasAll", "frame": "texWallGrind10r" }, { "texture": "atlasAll", "frame": "texWallGrind10l" }, { "texture": "atlasAll", "frame": "texWallGrind12r" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }, { "texture": "atlasAll", "frame": "flatPal00Brown" }, { "texture": "atlasAll", "frame": "flatPal00Brown" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }, { "texture": "atlasAll", "frame": "flatPal00Brown" }, { "texture": "atlasAll", "frame": "flatPal00Brown" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }], + [{ "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind12l" }, { "texture": "atlasAll", "frame": "texWallGrind10r" }, { "texture": "atlasAll", "frame": "texWallGrind10l" }, { "texture": "atlasAll", "frame": "texWallGrind12r" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }, { "texture": "atlasAll", "frame": "texWallAtom00r" }, { "texture": "atlasAll", "frame": "flatPal00Brown" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }, { "texture": "atlasAll", "frame": "flatPal00Brown" }, { "texture": "atlasAll", "frame": "texWallAtom00l" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }] + ], + atomRing: [ + [{ "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind12l" }, { "texture": "atlasAll", "frame": "texWallGrind10r" }, { "texture": "atlasAll", "frame": "texWallGrind10l" }, { "texture": "atlasAll", "frame": "texWallGrind12r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar10" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }], + [{ "texture": "atlasAll", "frame": "texWallAtom00l" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }, { "texture": "atlasAll", "frame": "texWallGrind12l" }, { "texture": "atlasAll", "frame": "texWallGrind10r" }, { "texture": "atlasAll", "frame": "texWallGrind10l" }, { "texture": "atlasAll", "frame": "texWallGrind12r" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }, { "texture": "atlasAll", "frame": "texWallAtom00r" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }, { "texture": "atlasAll", "frame": "texMetalHangar10" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }], + [{ "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind12l" }, { "texture": "atlasAll", "frame": "texWallGrind10r" }, { "texture": "atlasAll", "frame": "texWallGrind10l" }, { "texture": "atlasAll", "frame": "texWallGrind12r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }], + [{ "texture": "atlasAll", "frame": "texWallAtom00l" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }, { "texture": "atlasAll", "frame": "texWallGrind12l" }, { "texture": "atlasAll", "frame": "texWallGrind10r" }, { "texture": "atlasAll", "frame": "texWallGrind10l" }, { "texture": "atlasAll", "frame": "texWallGrind12r" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }, { "texture": "atlasAll", "frame": "texWallAtom00r" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }] + ], + vent: [ + [{ "texture": "atlasAll", "frame": "texWallVent00" }, { "texture": "atlasAll", "frame": "texWallGrind09r" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallVent02" }, { "texture": "atlasAll", "frame": "texWallVent03" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind09l" }, { "texture": "atlasAll", "frame": "texWallVent01" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "texWallVent07" }, { "texture": "atlasAll", "frame": "texWallVent06" }, { "texture": "atlasAll", "frame": "texWallVent04" }, { "texture": "atlasAll", "frame": "texWallVent05" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "texWallVent07" }, { "texture": "atlasAll", "frame": "texWallVent06" }, { "texture": "atlasAll", "frame": "texWallVent04" }, { "texture": "atlasAll", "frame": "texWallVent05" }] + ], + ventRing: [ + [{ "texture": "atlasAll", "frame": "texWallVent00" }, { "texture": "atlasAll", "frame": "texWallGrind09r" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallVent02" }, { "texture": "atlasAll", "frame": "texWallVent03" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind09l" }, { "texture": "atlasAll", "frame": "texWallVent01" }, { "texture": "atlasAll", "frame": "texWallGrind09r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind09l" }, { "texture": "atlasAll", "frame": "texWallVent07" }, { "texture": "atlasAll", "frame": "texWallVent06" }, { "texture": "atlasAll", "frame": "texWallVent04" }, { "texture": "atlasAll", "frame": "texWallVent05" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarLight00" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texWallVent02" }, { "texture": "atlasAll", "frame": "texWallVent03" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangarLight00" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texWallVent07" }, { "texture": "atlasAll", "frame": "texWallVent06" }, { "texture": "atlasAll", "frame": "texWallVent04" }, { "texture": "atlasAll", "frame": "texWallVent05" }] + ], + ventDoor: [ + [{ "texture": "atlasObstacles", "frame": "obstVentDoor0100" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0000" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0000" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0400" }, { "texture": "atlasObstacles", "frame": "obstDarkDoor0300" }, { "texture": "atlasObstacles", "frame": "obstDarkDoor0300" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0700" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0700" }, { "texture": "atlasObstacles", "frame": "obstDarkDoor0300" }, { "texture": "atlasObstacles", "frame": "obstDarkDoor0300" }, { "texture": "atlasObstacles", "frame": "obstDarkDoor0300" }, { "texture": "atlasObstacles", "frame": "obstDarkDoor0300" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0200" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0300" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0300" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0600" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0600" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0500" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0800" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0600" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0600" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0600" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0600" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0800" }], + [{ "texture": "atlasObstacles", "frame": "obstVentDoor0101" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0300" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0300" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0401" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0600" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0600" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0701" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0701" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0600" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0600" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0600" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0600" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0201" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0301" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0301" }, { "texture": "atlasObstacles", "frame": "obstDarkDoor0300" }, { "texture": "atlasObstacles", "frame": "obstDarkDoor0300" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0501" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0801" }, { "texture": "atlasObstacles", "frame": "obstDarkDoor0300" }, { "texture": "atlasObstacles", "frame": "obstDarkDoor0300" }, { "texture": "atlasObstacles", "frame": "obstDarkDoor0300" }, { "texture": "atlasObstacles", "frame": "obstDarkDoor0300" }, { "texture": "atlasObstacles", "frame": "obstVentDoor0801" }] + ], + lab: [ + [{ "texture": "atlasAll", "frame": "texWallGrind01" }, { "texture": "atlasAll", "frame": "texWallLab00ru" }, { "texture": "atlasAll", "frame": "texWallVent03" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallVent02" }, { "texture": "atlasAll", "frame": "texWallLab00lu" }, { "texture": "atlasAll", "frame": "texWallGrind01" }, { "texture": "atlasAll", "frame": "texWallLab00ru" }, { "texture": "atlasAll", "frame": "texWallLab00lu" }, { "texture": "atlasAll", "frame": "texWallGrind01" }, { "texture": "atlasAll", "frame": "texWallLab00ru" }, { "texture": "atlasAll", "frame": "texWallLab00lu" }, { "texture": "atlasAll", "frame": "texWallGrind01" }, { "texture": "atlasAll", "frame": "texWallLab00ru" }, { "texture": "atlasAll", "frame": "texWallLab00lu" }], + [{ "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "texWallGrind01r" }, { "texture": "atlasAll", "frame": "texWallVent03" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallVent02" }, { "texture": "atlasAll", "frame": "texWallGrind01l" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "texWallGrind01r" }, { "texture": "atlasAll", "frame": "texWallGrind01l" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "texWallGrind01r" }, { "texture": "atlasAll", "frame": "texWallGrind01l" }, { "texture": "atlasAll", "frame": "flatPal00White" }, { "texture": "atlasAll", "frame": "texWallGrind01r" }, { "texture": "atlasAll", "frame": "texWallGrind01l" }], + [{ "texture": "atlasAll", "frame": "texWallGrind01d" }, { "texture": "atlasAll", "frame": "texWallLab00rd" }, { "texture": "atlasAll", "frame": "texWallVent03" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallVent02" }, { "texture": "atlasAll", "frame": "texWallLab00ld" }, { "texture": "atlasAll", "frame": "texWallGrind01d" }, { "texture": "atlasAll", "frame": "texWallLab00rd" }, { "texture": "atlasAll", "frame": "texWallLab00ld" }, { "texture": "atlasAll", "frame": "texWallGrind01d" }, { "texture": "atlasAll", "frame": "texWallLab00rd" }, { "texture": "atlasAll", "frame": "texWallLab00ld" }, { "texture": "atlasAll", "frame": "texWallGrind01d" }, { "texture": "atlasAll", "frame": "texWallLab00rd" }, { "texture": "atlasAll", "frame": "texWallLab00ld" }] + ], + labRing: [ + [{ "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallVent03" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallVent02" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarLight00" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texWallVent03" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallVent02" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangarLight00" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }] + ], + garden: [ + [{ "texture": "atlasAll", "frame": "texMetalHangar01" }, { "texture": "atlasAll", "frame": "texMetalHangar01" }, { "texture": "atlasAll", "frame": "texMetalHangar01" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }, { "texture": "atlasAll", "frame": "texMetalHangar01" }, { "texture": "atlasAll", "frame": "texMetalHangar01" }, { "texture": "atlasAll", "frame": "texMetalHangar01" }, { "texture": "atlasAll", "frame": "texMetalHangar01" }, { "texture": "atlasAll", "frame": "texMetalHangar01" }, { "texture": "atlasAll", "frame": "texMetalHangar01" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }, { "texture": "atlasAll", "frame": "texMetalHangar01" }, { "texture": "atlasAll", "frame": "texMetalHangar01" }, { "texture": "atlasAll", "frame": "texMetalHangar01" }, { "texture": "atlasAll", "frame": "texElevatorLight01" }, { "texture": "atlasAll", "frame": "texElevatorLight01" }, { "texture": "atlasAll", "frame": "texElevatorLight01" }, { "texture": "atlasAll", "frame": "texElevatorLight01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }] + ], + gardenRing: [ + [{ "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texElevatorLight01" }, { "texture": "atlasAll", "frame": "texElevatorLight01" }, { "texture": "atlasAll", "frame": "texElevatorLight01" }, { "texture": "atlasAll", "frame": "texElevatorLight01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }], + [{ "texture": "atlasAll", "frame": "texMetalDark05r" }, { "texture": "atlasAll", "frame": "texMetalDark05r" }, { "texture": "atlasAll", "frame": "texMetalDark05r" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texMetalDark05r" }, { "texture": "atlasAll", "frame": "texMetalDark05r" }, { "texture": "atlasAll", "frame": "texMetalDark05r" }, { "texture": "atlasAll", "frame": "texMetalDark05r" }, { "texture": "atlasAll", "frame": "texMetalDark05r" }, { "texture": "atlasAll", "frame": "texMetalDark05r" }, { "texture": "atlasAll", "frame": "texMetalDark05r" }, { "texture": "atlasAll", "frame": "texMetalDark05r" }, { "texture": "atlasAll", "frame": "texMetalDark05r" }, { "texture": "atlasAll", "frame": "texMetalDark05r" }, { "texture": "atlasAll", "frame": "texMetalDark05r" }, { "texture": "atlasAll", "frame": "texElevatorLight01" }, { "texture": "atlasAll", "frame": "texElevatorLight01" }, { "texture": "atlasAll", "frame": "texElevatorLight01" }, { "texture": "atlasAll", "frame": "texElevatorLight01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texWallGrind05r" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texWallGrind05l" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }, { "texture": "atlasAll", "frame": "texBush01" }] + ], + glass: [ + [{ "texture": "atlasAll", "frame": "texMetalHangar10" }, { "texture": "atlasAll", "frame": "texGlass01" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texPadding02" }, { "texture": "atlasAll", "frame": "texPadding02" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texGlass01" }, { "texture": "atlasAll", "frame": "texMetalHangar10" }, { "texture": "atlasAll", "frame": "texGlass01" }, { "texture": "atlasAll", "frame": "texGlass01" }, { "texture": "atlasAll", "frame": "texGlass01" }, { "texture": "atlasAll", "frame": "texGlass01" }, { "texture": "atlasAll", "frame": "texGlass01" }, { "texture": "atlasAll", "frame": "texGlass01" }, { "texture": "atlasAll", "frame": "texGlass01" }, { "texture": "atlasAll", "frame": "texGlass01" }] + ], + glassRing: [ + [{ "texture": "atlasAll", "frame": "texMetalDark02" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texPadding02" }, { "texture": "atlasAll", "frame": "texPadding02" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalDark02" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarLight02" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texWallGrind03l" }, { "texture": "atlasAll", "frame": "texPadding02" }, { "texture": "atlasAll", "frame": "texPadding02" }, { "texture": "atlasAll", "frame": "texWallGrind03r" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangarLight02" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }] + ], + scaffolding: [ + [{ "texture": "atlasAll", "frame": "scaffolding02-2" }, { "texture": "atlasAll", "frame": "scaffolding02-3" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-0" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-1" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-2" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-3" }, { "texture": "atlasAll", "frame": "scaffolding02-0" }, { "texture": "atlasAll", "frame": "scaffolding02-1" }, { "texture": "atlasAll", "frame": "scaffolding02-2" }, { "texture": "atlasAll", "frame": "scaffolding02-3" }, { "texture": "atlasAll", "frame": "scaffolding02-0" }, { "texture": "atlasAll", "frame": "scaffolding02-1" }, { "texture": "atlasAll", "frame": "scaffolding02-2" }, { "texture": "atlasAll", "frame": "scaffolding02-3" }, { "texture": "atlasAll", "frame": "scaffolding02-0" }, { "texture": "atlasAll", "frame": "scaffolding02-1" }], + [{ "texture": "atlasAll", "frame": "scaffolding02-6" }, { "texture": "atlasAll", "frame": "scaffolding02-7" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-4" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-5" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-6" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-7" }, { "texture": "atlasAll", "frame": "scaffolding02-4" }, { "texture": "atlasAll", "frame": "scaffolding02-5" }, { "texture": "atlasAll", "frame": "scaffolding02-6" }, { "texture": "atlasAll", "frame": "scaffolding02-7" }, { "texture": "atlasAll", "frame": "scaffolding02-4" }, { "texture": "atlasAll", "frame": "scaffolding02-5" }, { "texture": "atlasAll", "frame": "scaffolding02-6" }, { "texture": "atlasAll", "frame": "scaffolding02-7" }, { "texture": "atlasAll", "frame": "scaffolding02-4" }, { "texture": "atlasAll", "frame": "scaffolding02-5" }], + [{ "texture": "atlasAll", "frame": "scaffolding02-10" }, { "texture": "atlasAll", "frame": "scaffolding02-11" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-8" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-9" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-10" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-11" }, { "texture": "atlasAll", "frame": "scaffolding02-8" }, { "texture": "atlasAll", "frame": "scaffolding02-9" }, { "texture": "atlasAll", "frame": "scaffolding02-10" }, { "texture": "atlasAll", "frame": "scaffolding02-11" }, { "texture": "atlasAll", "frame": "scaffolding02-8" }, { "texture": "atlasAll", "frame": "scaffolding02-9" }, { "texture": "atlasAll", "frame": "scaffolding02-10" }, { "texture": "atlasAll", "frame": "scaffolding02-11" }, { "texture": "atlasAll", "frame": "scaffolding02-8" }, { "texture": "atlasAll", "frame": "scaffolding02-9" }], + [{ "texture": "atlasAll", "frame": "scaffolding02-14" }, { "texture": "atlasAll", "frame": "scaffolding02-15" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-12" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-13" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-14" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-15" }, { "texture": "atlasAll", "frame": "scaffolding02-12" }, { "texture": "atlasAll", "frame": "scaffolding02-13" }, { "texture": "atlasAll", "frame": "scaffolding02-14" }, { "texture": "atlasAll", "frame": "scaffolding02-15" }, { "texture": "atlasAll", "frame": "scaffolding02-12" }, { "texture": "atlasAll", "frame": "scaffolding02-13" }, { "texture": "atlasAll", "frame": "scaffolding02-14" }, { "texture": "atlasAll", "frame": "scaffolding02-15" }, { "texture": "atlasAll", "frame": "scaffolding02-12" }, { "texture": "atlasAll", "frame": "scaffolding02-13" }] + ], + scaffoldingLight: [ + [{ "texture": "atlasAll", "frame": "scaffolding02-2" }, { "texture": "atlasAll", "frame": "scaffolding02-3" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-0" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-1" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-2" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-3" }, { "texture": "atlasAll", "frame": "scaffolding02-0" }, { "texture": "atlasAll", "frame": "scaffolding02-1" }, { "texture": "atlasAll", "frame": "scaffolding02-2" }, { "texture": "atlasAll", "frame": "scaffolding02-3" }, { "texture": "atlasAll", "frame": "scaffolding02-0" }, { "texture": "atlasAll", "frame": "scaffolding02-1" }, { "texture": "atlasAll", "frame": "scaffolding02-2" }, { "texture": "atlasAll", "frame": "scaffolding02-3" }, { "texture": "atlasAll", "frame": "scaffolding02-0" }, { "texture": "atlasAll", "frame": "scaffolding02-1" }], + [{ "texture": "atlasAll", "frame": "scaffolding02Light-6" }, { "texture": "atlasAll", "frame": "scaffolding02-7" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-4" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-5" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-6" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-7" }, { "texture": "atlasAll", "frame": "scaffolding02-4" }, { "texture": "atlasAll", "frame": "scaffolding02Light-5" }, { "texture": "atlasAll", "frame": "scaffolding02Light-6" }, { "texture": "atlasAll", "frame": "scaffolding02-7" }, { "texture": "atlasAll", "frame": "scaffolding02-4" }, { "texture": "atlasAll", "frame": "scaffolding02Light-5" }, { "texture": "atlasAll", "frame": "scaffolding02Light-6" }, { "texture": "atlasAll", "frame": "scaffolding02-7" }, { "texture": "atlasAll", "frame": "scaffolding02-4" }, { "texture": "atlasAll", "frame": "scaffolding02Light-5" }], + [{ "texture": "atlasAll", "frame": "scaffolding02Light-10" }, { "texture": "atlasAll", "frame": "scaffolding02-11" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-8" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-9" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-10" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-11" }, { "texture": "atlasAll", "frame": "scaffolding02-8" }, { "texture": "atlasAll", "frame": "scaffolding02Light-9" }, { "texture": "atlasAll", "frame": "scaffolding02Light-10" }, { "texture": "atlasAll", "frame": "scaffolding02-11" }, { "texture": "atlasAll", "frame": "scaffolding02-8" }, { "texture": "atlasAll", "frame": "scaffolding02Light-9" }, { "texture": "atlasAll", "frame": "scaffolding02Light-10" }, { "texture": "atlasAll", "frame": "scaffolding02-11" }, { "texture": "atlasAll", "frame": "scaffolding02-8" }, { "texture": "atlasAll", "frame": "scaffolding02Light-9" }], + [{ "texture": "atlasAll", "frame": "scaffolding02-14" }, { "texture": "atlasAll", "frame": "scaffolding02-15" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-12" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-13" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-14" }, { "texture": "atlasAll", "frame": "scaffolding02Gangway-15" }, { "texture": "atlasAll", "frame": "scaffolding02-12" }, { "texture": "atlasAll", "frame": "scaffolding02-13" }, { "texture": "atlasAll", "frame": "scaffolding02-14" }, { "texture": "atlasAll", "frame": "scaffolding02-15" }, { "texture": "atlasAll", "frame": "scaffolding02-12" }, { "texture": "atlasAll", "frame": "scaffolding02-13" }, { "texture": "atlasAll", "frame": "scaffolding02-14" }, { "texture": "atlasAll", "frame": "scaffolding02-15" }, { "texture": "atlasAll", "frame": "scaffolding02-12" }, { "texture": "atlasAll", "frame": "scaffolding02-13" }] + ], + scaffoldingEmpty: [ + [{ "texture": "atlasAll", "frame": "scaffolding02-2" }, { "texture": "atlasAll", "frame": "scaffolding02-3" }, { "texture": "atlasAll", "frame": "scaffolding02-0" }, { "texture": "atlasAll", "frame": "scaffolding02-1" }, { "texture": "atlasAll", "frame": "scaffolding02-2" }, { "texture": "atlasAll", "frame": "scaffolding02-3" }, { "texture": "atlasAll", "frame": "scaffolding02-0" }, { "texture": "atlasAll", "frame": "scaffolding02-1" }, { "texture": "atlasAll", "frame": "scaffolding02-2" }, { "texture": "atlasAll", "frame": "scaffolding02-3" }, { "texture": "atlasAll", "frame": "scaffolding02-0" }, { "texture": "atlasAll", "frame": "scaffolding02-1" }, { "texture": "atlasAll", "frame": "scaffolding02-2" }, { "texture": "atlasAll", "frame": "scaffolding02-3" }, { "texture": "atlasAll", "frame": "scaffolding02-0" }, { "texture": "atlasAll", "frame": "scaffolding02-1" }], + [{ "texture": "atlasAll", "frame": "scaffolding02-6" }, { "texture": "atlasAll", "frame": "scaffolding02-7" }, { "texture": "atlasAll", "frame": "scaffolding02-4" }, { "texture": "atlasAll", "frame": "scaffolding02-5" }, { "texture": "atlasAll", "frame": "scaffolding02-6" }, { "texture": "atlasAll", "frame": "scaffolding02-7" }, { "texture": "atlasAll", "frame": "scaffolding02-4" }, { "texture": "atlasAll", "frame": "scaffolding02-5" }, { "texture": "atlasAll", "frame": "scaffolding02-6" }, { "texture": "atlasAll", "frame": "scaffolding02-7" }, { "texture": "atlasAll", "frame": "scaffolding02-4" }, { "texture": "atlasAll", "frame": "scaffolding02-5" }, { "texture": "atlasAll", "frame": "scaffolding02-6" }, { "texture": "atlasAll", "frame": "scaffolding02-7" }, { "texture": "atlasAll", "frame": "scaffolding02-4" }, { "texture": "atlasAll", "frame": "scaffolding02-5" }], + [{ "texture": "atlasAll", "frame": "scaffolding02-10" }, { "texture": "atlasAll", "frame": "scaffolding02-11" }, { "texture": "atlasAll", "frame": "scaffolding02-8" }, { "texture": "atlasAll", "frame": "scaffolding02-9" }, { "texture": "atlasAll", "frame": "scaffolding02-10" }, { "texture": "atlasAll", "frame": "scaffolding02-11" }, { "texture": "atlasAll", "frame": "scaffolding02-8" }, { "texture": "atlasAll", "frame": "scaffolding02-9" }, { "texture": "atlasAll", "frame": "scaffolding02-10" }, { "texture": "atlasAll", "frame": "scaffolding02-11" }, { "texture": "atlasAll", "frame": "scaffolding02-8" }, { "texture": "atlasAll", "frame": "scaffolding02-9" }, { "texture": "atlasAll", "frame": "scaffolding02-10" }, { "texture": "atlasAll", "frame": "scaffolding02-11" }, { "texture": "atlasAll", "frame": "scaffolding02-8" }, { "texture": "atlasAll", "frame": "scaffolding02-9" }], + [{ "texture": "atlasAll", "frame": "scaffolding02-14" }, { "texture": "atlasAll", "frame": "scaffolding02-15" }, { "texture": "atlasAll", "frame": "scaffolding02-12" }, { "texture": "atlasAll", "frame": "scaffolding02-13" }, { "texture": "atlasAll", "frame": "scaffolding02-14" }, { "texture": "atlasAll", "frame": "scaffolding02-15" }, { "texture": "atlasAll", "frame": "scaffolding02-12" }, { "texture": "atlasAll", "frame": "scaffolding02-13" }, { "texture": "atlasAll", "frame": "scaffolding02-14" }, { "texture": "atlasAll", "frame": "scaffolding02-15" }, { "texture": "atlasAll", "frame": "scaffolding02-12" }, { "texture": "atlasAll", "frame": "scaffolding02-13" }, { "texture": "atlasAll", "frame": "scaffolding02-14" }, { "texture": "atlasAll", "frame": "scaffolding02-15" }, { "texture": "atlasAll", "frame": "scaffolding02-12" }, { "texture": "atlasAll", "frame": "scaffolding02-13" }] + ], + pipelineYellowStraight: [ + //normal + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }], + //with small yellow pipes on top + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }], + //with white checkers + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite00" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }], + //white checkers + usual pipes + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite00" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }] + ], + pipelineYellowEnd: [ + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03r" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02r" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }] + ], + pipelineYellowStart: [ + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02r" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03r" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }] + ], + pipelineYellowZigzag: [ + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }] + ], + pipelineYellowPattern: [ + //kinda knitted + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }], + //big arrow forward (backwards is cooler to drive through) + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }], + //bbig arrow backwarsd + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }] + + ], + pipelineYellowSpiral: [ + //short dense + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }], + //long scarse + [{ "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }], + [{ "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }] + ], + pipelineYellowRing: [ + [{ "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03r" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }], + [{ "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02r" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite00" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite00" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }], + //yellow zebra stripes + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }] + ], + pipelineYellowFill: [ + //yellow full ring with zebra at the bottom + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }], + //fillstart + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }], + [{ "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar02" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark05" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }], + //fill end to yellow ring again + [{ "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark02" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark05" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark05" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }], + [{ "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark00" }, { "texture": "atlasAll", "frame": "texMetalDark05" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalDark02" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalHangarLight00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }], + //random filling for length + [{ "texture": "atlasAll", "frame": "texMetalDark02" }, { "texture": "atlasAll", "frame": "texMetalHangar02" }, { "texture": "atlasAll", "frame": "texMetalHangar00" }, { "texture": "atlasAll", "frame": "texMetalDark00" }, { "texture": "atlasAll", "frame": "texMetalDark00" }, { "texture": "atlasAll", "frame": "texMetalDark02" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark05" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark04" }], + [{ "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangarLight02" }, { "texture": "atlasAll", "frame": "texMetalDark05" }, { "texture": "atlasAll", "frame": "texMetalDark00" }, { "texture": "atlasAll", "frame": "texMetalDark00" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark00" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark05" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }], + //variation probably not fittting but somehow looking cool inbetween rings + [{ "texture": "atlasAll", "frame": "texMetalDark02" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark05" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark04" }], + [{ "texture": "atlasAll", "frame": "texMetalDark03" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalDark00" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalDark04" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalDark05" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }] + ], + yellowArrows: [ + //yellow and white with light + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite03l" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02l" }, { "texture": "atlasAll", "frame": "texMetalHangarLight00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite04" }, { "texture": "atlasAll", "frame": "texMetalHangarLight00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintlineWhite02l" }], + //only yellow + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline03l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline04" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }], + [{ "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01l" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline01r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline00" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02r" }, { "texture": "atlasAll", "frame": "texMetalHangarPaintline02l" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }, { "texture": "atlasAll", "frame": "texMetalHangar08" }] + ] + } + } + + destroy() { + this.clearTrack(); + } + + clearTrack() { + this.scene.geometryController.destroyModelById(this.ref.id); + + this.spline = []; + for (let r of this.rings) { + this.scene.geometryController.destroyModelById(r.id); + } + this.rings = []; + for (let o of this.obstacles) { + this.scene.geometryController.destroyModelById(o.id); + } + this.obstacles = []; + + this.ref = this.scene.geometryController.loadModel("debug Arrow", "modDebugArrow", { x: 0, y: 0, z: 0 }); + } + + loadTrack(_id = 0, _dataOnly = false) { + this.clearTrack(); + this.currentTrackId = _id; + + let ty = 0; + let tp = 0; + let tr = 0; + let amt = 0; + let a = 0; + let ay = 0; + let ap = 0; + let ar = 0; + let obstSpots = []; + switch (_id) { + case 0://METRO LOOP + ty = 0; + tp = 0; + tr = 0; + + this.createStartTunnel(); + + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, 0, 0, "Start", "modRingD64R128", this.textureArrays.metroRail[0]); + } + this.addSpline(1, 0, 0, 0, "Start", "modRingD64R128", this.textureArrays.metroMetalRing[0]); + this.addSpline(1, 0, 0, 0, "Start", "modRingD64R128", this.textureArrays.metroMetalRing[1]); + this.addSpline(1, 0, 0, 0, "Start", "modRingD64R128", this.textureArrays.metroMetalRing[0]); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, 0, 0, "Start", "modRingD64R128", this.textureArrays.metroRail[0]); + } + + for (let i = 0; i < 4; i++) { + this.addSpline(1, Math.PI * 0.025, 0, 0, "Right", "modRingD64R128", this.textureArrays.metroMetalRing[0]); + this.addSpline(1, Math.PI * 0.025, 0, 0, "Right", "modRingD64R128", this.textureArrays.metroMetalRing[1]); + this.addSpline(1, Math.PI * 0.025, 0, 0, "Right", "modRingD64R128", this.textureArrays.metroMetalRing[0]); + this.addSpline(7, Math.PI * 0.025, 0, 0, "Right", "modRingD64R128", this.textureArrays.metroRail[0]); + } + + this.addSpline(1, 0, 0, 0, "Station Enter", "modRingD64R128", this.textureArrays.metroMetalRing[0]); + this.addSpline(1, 0, 0, 0, "Station Enter", "modRingD64R128", this.textureArrays.metroMetalRing[1]); + this.addSpline(1, 0, 0, 0, "Station Enter", "modRingD64R128", this.textureArrays.metroMetalRing[0]); + this.addSpline(1, 0, 0, 0, "Station Enter", "modRingD64R128", this.textureArrays.metroRail[0], false); + + this.addSpline(1, 0, 0, 0, "Backstraight Station", "modRingD512MetroStationStart", null, false); + this.addSpline(7, 0, 0, 0, "Backstraight Station", null, null, false); + this.addSpline(1, 0, 0, 0, "Backstraight Station", "modRingD512MetroStation", null, false); + this.addSpline(7, 0, 0, 0, "Backstraight Station", null, null, false); + this.addSpline(1, 0, 0, 0, "Backstraight Station", "modRingD512MetroStation", null, false); + this.addSpline(7, 0, 0, 0, "Backstraight Station", null, null, false); + this.addSpline(1, 0, 0, 0, "Backstraight Station", "modRingD512MetroStationEnd", null, false); + this.addSpline(7, 0, 0, 0, "Backstraight Station", null, null, false); + + this.addSpline(1, 0, 0, 0, "Station Exit", "modRingD64R128", this.textureArrays.metroRail[0]); + this.addSpline(1, 0, 0, 0, "Station Exit", "modRingD64R128", this.textureArrays.metroMetalRing[0]); + this.addSpline(1, 0, 0, 0, "Station Exit", "modRingD64R128", this.textureArrays.metroMetalRing[1]); + this.addSpline(1, 0, 0, 0, "Station Exit", "modRingD64R128", this.textureArrays.metroMetalRing[0]); + + for (let i = 0; i < 8; i++) { + this.addSpline(1, 0, 0, 0, "BackStraight", "modRingD64R128CoreStart", this.textureArrays.ventRing[0]); + this.addSpline(1, 0, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[1]); + this.addSpline(1, 0, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[0]); + this.addSpline(6, 0, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.vent[0]); + } + this.addSpline(1, 0, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[0]); + this.addSpline(1, 0, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[1]); + this.addSpline(1, 0, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[0]); + this.addSpline(5, 0, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.vent[0]); + this.addSpline(1, 0, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[0]); + this.addSpline(1, 0, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[1]); + this.addSpline(1, 0, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[0]); + + //up tilt + this.addSpline(7, 0, Math.PI * -0.025, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.vent[0]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[0]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[1]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[0]); + + //garden right + for (let i = 0; i < 4; i++) { + this.addSpline(1, Math.PI * 0.025, 0, 0, "Right", "modRingD64R128GardenStart", this.textureArrays.gardenRing[0]); + this.addSpline(1, Math.PI * 0.025, 0, 0, "Right", "modRingD64R128Garden", this.textureArrays.gardenRing[1]); + this.addSpline(6, Math.PI * 0.025, 0, 0, "Right", "modRingD64R128Garden", this.textureArrays.garden[0]); + this.addSpline(1, Math.PI * 0.025, 0, 0, "Right", "modRingD64R128Garden", this.textureArrays.gardenRing[1]); + this.addSpline(1, Math.PI * 0.025, 0, 0, "Right", "modRingD64R128GardenEnd", this.textureArrays.gardenRing[0]); + } + //tostart + this.addSpline(1, 0, Math.PI * -0.025, 0, "to Start", "modRingD64R128", this.textureArrays.metroMetalRing[0]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "to Start", "modRingD64R128", this.textureArrays.metroMetalRing[1]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "to Start", "modRingD64R128", this.textureArrays.metroMetalRing[0]); + this.addSpline(7, 0, Math.PI * -0.025, 0, "to ", "modRingD64R128", this.textureArrays.metroRail[0]); + for (let i = 0; i < 3; i++) { + this.addSpline(1, 0, 0, 0, "to Start", "modRingD64R128", this.textureArrays.metroMetalRing[0]); + this.addSpline(1, 0, 0, 0, "to Start", "modRingD64R128", this.textureArrays.metroMetalRing[1]); + this.addSpline(1, 0, 0, 0, "to Start", "modRingD64R128", this.textureArrays.metroMetalRing[0]); + this.addSpline(7, 0, 0, 0, "to Start", "modRingD64R128", this.textureArrays.metroRail[0]); + } + + this.addSpline(1, 0, 0, 0, "Test", "modRingD64R128Lab", this.textureArrays.labRing[0]); + this.addSpline(1, 0, 0, 0, "Test", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, 0, 0, "Test", "modRingD64R128", this.textureArrays.labRing[0]); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, 0, 0, "Test", "modRingD64R128Lab", this.textureArrays.lab[i % 3]); + } + this.addSpline(1, 0, 0, 0, "Test", "modRingD64R128Lab", this.textureArrays.labRing[0]); + this.addSpline(1, 0, 0, 0, "Test", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, 0, 0, "Test", "modRingD64R128", this.textureArrays.labRing[0]); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, 0, 0, "Test", "modRingD64R128Lab", this.textureArrays.lab[i % 3]); + } + this.addSpline(1, 0, 0, 0, "Test", "modRingD64R128Lab", this.textureArrays.labRing[0]); + this.addSpline(1, 0, 0, 0, "Test", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, 0, 0, "Test", "modRingD64R128", this.textureArrays.labRing[0]); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, 0, 0, "Test", "modRingD64R128Lab", this.textureArrays.lab[i % 3]); + } + this.addSpline(1, 0, 0, 0, "Test", "modRingD64R128Lab", this.textureArrays.labRing[0]); + this.addSpline(1, 0, 0, 0, "Test", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, 0, 0, "Test", "modRingD64R128", this.textureArrays.labRing[0]); + + this.addSpline(4, 0, 0, 0, "Start - Finish", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + + this.spline[this.spline.length - 1].stitch = false; + + //obstaccles + obstSpots = [ + //blades + { sp: this.spline[139], angle: (Math.PI / 1.5) * 0, radius: 0, model: "modObstVentBlade", name: "blade 0 0" }, + { sp: this.spline[139], angle: (Math.PI / 1.5) * 1, radius: 0, model: "modObstVentBlade", name: "blade 0 1" }, + { sp: this.spline[139], angle: (Math.PI / 1.5) * 2, radius: 0, model: "modObstVentBlade", name: "blade 0 2" }, + { sp: this.spline[231], angle: (Math.PI / 1.5) * 0, radius: 0, model: "modObstVentBlade", name: "blade 1 0" }, + { sp: this.spline[231], angle: (Math.PI / 1.5) * 1, radius: 0, model: "modObstVentBladeDestroyed", name: "blade 1 1" }, + { sp: this.spline[231], angle: (Math.PI / 1.5) * 2, radius: 0, model: "modObstVentBlade", name: "blade 1 2" }, + //other objects + { sp: this.spline[60], angle: 0, radius: 0, model: "modObstMetroBlade", name: "blade lights 0" }, + { sp: this.spline[271], angle: Math.PI * 0.5, radius: 0, model: "modObstMetalDoorMirrored", name: "door 0" }, + { sp: this.spline[311], angle: 0, radius: 40, model: "modObstMetalDoorMirrored", name: "door 1" }, + { sp: this.spline[311], angle: Math.PI, radius: 40, model: "modObstMetalDoorMirrored", name: "door 2" }, + { sp: this.spline[156], angle: Math.PI * 0.25, radius: 0, model: "modObstVentDoor", name: "door 3" }, + { sp: this.spline[176], angle: Math.PI * 1.25, radius: 0, model: "modObstVentDoor", name: "door 4" }, + //steam + { sp: this.spline[50], angle: Math.PI * 0.25, radius: 0, model: "modObstSteam", name: "steam 0" }, + { sp: this.spline[50], angle: Math.PI * 0.75, radius: 0, model: "modObstSteam", name: "steam 1" }, + { sp: this.spline[50], angle: Math.PI * -0.25, radius: 0, model: "modObstSteam", name: "steam 2" }, + { sp: this.spline[50], angle: Math.PI * -0.75, radius: 0, model: "modObstSteam", name: "steam 3" } + ] + break; + case 1://ATOMIC SEWERS + ty = 0; + tp = 0; + tr = 0; + + this.createStartTunnel(); + + //atom start + this.addSpline(1, 0, 0, 0, "Start", "modRingD64R128Core", this.textureArrays.atomRing[0]); + + for (let j = 0; j < 2; j++) { + for (let i = 0; i < 7; i++) { + this.addSpline(1, 0, 0, 0, "Start", "modRingD64R128Core", this.textureArrays.atom[0]); + } + this.addSpline(1, 0, 0, 0, "Start", "modRingD64R128Core", this.textureArrays.atomRing[0]); + this.addSpline(1, 0, 0, 0, "Start", "modRingD64R128Core", this.textureArrays.atomRing[1]); + this.addSpline(1, 0, 0, 0, "Start", "modRingD64R128Core", this.textureArrays.atomRing[0]); + } + + for (let i = 0; i < 7; i++) { + this.addSpline(1, 0, Math.PI * 0.025, 0, "first downslope", "modRingD64R128Core", this.textureArrays.atom[0]); + } + this.addSpline(1, 0, Math.PI * 0.025, 0, "first downslope", "modRingD64R128Core", this.textureArrays.atomRing[0]); + this.addSpline(1, 0, Math.PI * 0.025, 0, "first downslope", "modRingD64R128Core", this.textureArrays.atomRing[1]); + this.addSpline(1, 0, Math.PI * 0.025, 0, "first downslope", "modRingD64R128Core", this.textureArrays.atomRing[0]); + + for (let i = 0; i < 7; i++) { + this.addSpline(1, 0, Math.PI * -0.025, 0, "first downslope", "modRingD64R128Core", this.textureArrays.atom[0]); + } + this.addSpline(1, 0, Math.PI * -0.025, 0, "first downslope", "modRingD64R128Core", this.textureArrays.atomRing[0]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "first downslope", "modRingD64R128Core", this.textureArrays.atomRing[1]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "first downslope", "modRingD64R128Core", this.textureArrays.atomRing[0]); + + for (let i = 0; i < 7; i++) { + this.addSpline(1, Math.PI * -0.025, 0, 0, "first left kink", "modRingD64R128Core", this.textureArrays.atom[0]); + } + this.addSpline(1, Math.PI * -0.025, 0, 0, "first left kink", "modRingD64R128Core", this.textureArrays.atomRing[0]); + this.addSpline(1, Math.PI * -0.025, 0, 0, "first left kink", "modRingD64R128Core", this.textureArrays.atomRing[1]); + this.addSpline(1, Math.PI * -0.025, 0, 0, "first left kink", "modRingD64R128Core", this.textureArrays.atomRing[0]); + + //first atom room + for (let j = 0; j < 2; j++) { + for (let i = 0; i < 7; i++) { + this.addSpline(1, 0, 0, 0, "Sewer Room 01", "modRingD64R128AtomRoom", this.textureArrays.atom[0]); + } + this.addSpline(1, 0, 0, 0, "Sewer Room 01", "modRingD64R128AtomRoom01", this.textureArrays.atomRing[0]); + this.addSpline(1, 0, 0, 0, "Sewer Room 01", "modRingD64R128AtomRoom", this.textureArrays.atomRing[1]); + this.addSpline(1, 0, 0, 0, "Sewer Room 01", "modRingD64R128AtomRoom02", this.textureArrays.atomRing[0]); + } + + for (let j = 0; j < 2; j++) { + for (let i = 0; i < 7; i++) { + this.addSpline(1, 0, Math.PI * -0.025, 0, "Sewer Loop Onramp", "modRingD64R128Core", this.textureArrays.atom[0]); + } + this.addSpline(1, 0, Math.PI * -0.025, 0, "Sewer Loop Onramp", "modRingD64R128Core", this.textureArrays.atomRing[0]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "Sewer Loop Onramp", "modRingD64R128Core", this.textureArrays.atomRing[1]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "Sewer Loop Onramp", "modRingD64R128Core", this.textureArrays.atomRing[0]); + } + + for (let j = 0; j < 6; j++) { + for (let i = 0; i < 7; i++) { + this.addSpline(1, 0, Math.PI * 0.025, 0, "Sewer Loop", "modRingD64R128AtomRoom", this.textureArrays.atom[0]); + } + this.addSpline(1, 0, Math.PI * 0.025, 0, "Sewer Loop", "modRingD64R128AtomRoom01", this.textureArrays.atomRing[0]); + this.addSpline(1, 0, Math.PI * 0.025, 0, "Sewer Loop", "modRingD64R128AtomRoom", this.textureArrays.atomRing[1]); + this.addSpline(1, 0, Math.PI * 0.025, 0, "Sewer Loop", "modRingD64R128AtomRoom02", this.textureArrays.atomRing[0]); + } + + for (let j = 0; j < 4; j++) { + for (let i = 0; i < 7; i++) { + this.addSpline(1, 0, 0, Math.PI * -0.025, "Sewer Corkscrew", "modRingD64R128Core", this.textureArrays.atom[0]); + } + this.addSpline(1, 0, 0, Math.PI * -0.025, "Sewer Corkscrew", "modRingD64R128Core", this.textureArrays.atomRing[0]); + this.addSpline(1, 0, 0, Math.PI * -0.025, "Sewer Corkscrew", "modRingD64R128Core", this.textureArrays.atomRing[1]); + this.addSpline(1, 0, 0, Math.PI * -0.025, "Sewer Corkscrew", "modRingD64R128Core", this.textureArrays.atomRing[0]); + } + + for (let j = 0; j < 2; j++) { + for (let i = 0; i < 7; i++) { + this.addSpline(1, 0, 0, 0, "Sewer Corkscrew", "modRingD64R128Core", this.textureArrays.atom[0]); + } + this.addSpline(1, 0, 0, 0, "Sewer Corkscrew", "modRingD64R128Core", this.textureArrays.atomRing[0]); + this.addSpline(1, 0, 0, 0, "Sewer Corkscrew", "modRingD64R128Core", this.textureArrays.atomRing[1]); + this.addSpline(1, 0, 0, 0, "Sewer Corkscrew", "modRingD64R128Core", this.textureArrays.atomRing[0]); + } + + for (let i = 0; i < 7; i++) { + this.addSpline(1, Math.PI * 0.025, 0, 0, "kink left again", "modRingD64R128Core", this.textureArrays.atom[0]); + } + this.addSpline(1, Math.PI * 0.025, 0, 0, "kink left again", "modRingD64R128Core", this.textureArrays.atomRing[0]); + this.addSpline(1, Math.PI * 0.025, 0, 0, "kink left again", "modRingD64R128Core", this.textureArrays.atomRing[1]); + this.addSpline(1, Math.PI * 0.025, 0, 0, "kink left again", "modRingD64R128Core", this.textureArrays.atomRing[0]); + + //ribbed atom room + for (let j = 0; j < 6; j++) { + for (let i = 0; i < 7; i++) { + this.addSpline(1, 0, 0, 0, "backstraight", "modRingD64R128AtomRoom", this.textureArrays.atom[0]); + } + this.addSpline(1, 0, 0, 0, "backstraight", "modRingD64R128AtomRoom", this.textureArrays.atomRing[0]); + this.addSpline(1, 0, 0, 0, "backstraight", "modRingD64R128Core", this.textureArrays.atomRing[1]); + this.addSpline(1, 0, 0, 0, "backstraight", "modRingD64R128Core", this.textureArrays.atomRing[0]); + } + + this.addSpline(25, 0, 0, 0, "backstraight", "modRingD64R128", this.textureArrays.sewer[0]); + + //lab upward + for (let j = 0; j < 2; j++) { + this.addSpline(1, 0, Math.PI * -0.025, 0, "Test", "modRingD64R128Lab", this.textureArrays.labRing[0]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "Test", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "Test", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "Test", "modRingD64R128", this.textureArrays.labRing[0]); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, Math.PI * -0.025, 0, "Test", "modRingD64R128Lab", this.textureArrays.lab[i % 3]); + } + } + + for (let j = 0; j < 2; j++) { + this.addSpline(1, 0, 0, Math.PI * -0.025, "Lab Spiral", "modRingD64R128Lab", this.textureArrays.labRing[0]); + this.addSpline(1, 0, 0, Math.PI * -0.025, "Lab Spiral", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, 0, Math.PI * -0.025, "Lab Spiral", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, 0, Math.PI * -0.025, "Lab Spiral", "modRingD64R128", this.textureArrays.labRing[0]); + for (let i = 0; i < 12; i++) { + this.addSpline(1, 0, 0, Math.PI * -0.025, "Lab Spiral", "modRingD64R128Lab", this.textureArrays.lab[i % 3]); + } + } + this.addSpline(1, 0, 0, Math.PI * -0.025, "Lab Spiral", "modRingD64R128Lab", this.textureArrays.labRing[0]); + this.addSpline(1, 0, 0, Math.PI * -0.025, "Lab Spiral", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, 0, Math.PI * -0.025, "Lab Spiral", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, 0, Math.PI * -0.025, "Lab Spiral", "modRingD64R128", this.textureArrays.labRing[0]); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, 0, Math.PI * -0.025, "Lab Spiral", "modRingD64R128Lab", this.textureArrays.lab[i % 3]); + } + + //lab 180 + for (let j = 0; j < 4; j++) { + this.addSpline(1, 0, Math.PI * -0.025, 0, "Lab 180", "modRingD64R128Lab", this.textureArrays.labRing[0]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "Lab 180", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "Lab 180", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "Lab 180", "modRingD64R128", this.textureArrays.labRing[0]); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, Math.PI * -0.025, 0, "Lab 180", "modRingD64R128Lab", this.textureArrays.lab[i % 3]); + } + } + + for (let j = 0; j < 2; j++) { + this.addSpline(1, 0, 0, 0, "Lab 180", "modRingD64R128Lab", this.textureArrays.labRing[0]); + this.addSpline(1, 0, 0, 0, "Lab 180", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, 0, 0, "Lab 180", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, 0, 0, "Lab 180", "modRingD64R128", this.textureArrays.labRing[0]); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, 0, 0, "Lab Spiral", "modRingD64R128Lab", this.textureArrays.lab[i % 3]); + } + } + + //reenter serwer + for (let j = 0; j < 2; j++) { + this.addSpline(7, 0, 0, 0, "kink left again", "modRingD64R128Core", this.textureArrays.atom[0]); + this.addSpline(1, 0, 0, 0, "kink left again", "modRingD64R128Core", this.textureArrays.atomRing[0]); + this.addSpline(1, 0, 0, 0, "kink left again", "modRingD64R128Core", this.textureArrays.atomRing[1]); + this.addSpline(1, 0, 0, 0, "kink left again", "modRingD64R128Core", this.textureArrays.atomRing[0]); + } + + for (let j = 0; j < 2; j++) { + for (let i = 0; i < 7; i++) { + this.addSpline(1, 0, Math.PI * -0.025, 0, "kink left again", "modRingD64R128Core", this.textureArrays.atom[0]); + } + this.addSpline(1, 0, Math.PI * -0.025, 0, "kink left again", "modRingD64R128Core", this.textureArrays.atomRing[0]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "kink left again", "modRingD64R128Core", this.textureArrays.atomRing[1]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "kink left again", "modRingD64R128Core", this.textureArrays.atomRing[0]); + } + + this.addSpline(9, 0, Math.PI * -0.022, 0, "second downslope", "modRingD64R128Core", this.textureArrays.atom[0]); + this.addSpline(9, 0, Math.PI * 0.022, 0, "second downslope", "modRingD64R128Core", this.textureArrays.atom[0]); + + for (let i = 0; i < 6; i++) { + this.addSpline(1, Math.PI * -0.025, 0, 0, "second left kink", "modRingD64R128AtomRoom", this.textureArrays.atom[0]); + } + this.addSpline(1, Math.PI * -0.025, 0, 0, "second left kink", "modRingD64R128AtomRoom01", this.textureArrays.atomRing[0]); + this.addSpline(1, Math.PI * -0.025, 0, 0, "second left kink", "modRingD64R128AtomRoom", this.textureArrays.atomRing[1]); + this.addSpline(1, Math.PI * -0.025, 0, 0, "second left kink", "modRingD64R128AtomRoom02", this.textureArrays.atomRing[0]); + + for (let i = 0; i < 8; i++) { + this.addSpline(1, Math.PI * 0.025, 0, 0, "second left kink", "modRingD64R128AtomRoom", this.textureArrays.atom[0]); + } + this.addSpline(1, 0, 0, 0, "second left kink", "modRingD64R128AtomRoom01", this.textureArrays.atomRing[0]); + this.addSpline(1, 0, 0, 0, "second left kink", "modRingD64R128AtomRoom", this.textureArrays.atomRing[1]); + this.addSpline(1, 0, 0, 0, "second left kink", "modRingD64R128CoreEnd", this.textureArrays.atomRing[1]); + + + this.addSpline(1, 0, 0, 0, "Start - Finish", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + this.addSpline(3, Math.PI * 0.025, 0, 0, "Start - Finish", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + + //this.spline[this.spline.length - 1].stitch = false; + + //obstaccles + obstSpots = [ + { sp: this.spline[44], angle: 0, radius: 0, model: "modObst3x3Door", name: "warn 0" }, + { sp: this.spline[43], angle: Math.PI * 0.025, radius: 76, model: "modObstMetalDoorMirrored", name: "door 0" }, + { sp: this.spline[43], angle: Math.PI * 0.5, radius: 0, model: "modObstMetroBlade", name: "blade 0" }, + { sp: this.spline[324], angle: 0, radius: 80, model: "modObstMetalDoorMirrored", name: "door 1" }, + { sp: this.spline[324], angle: Math.PI * 0.5, radius: 0, model: "modObstMetroBlade", name: "blade 1" }, + { sp: this.spline[471], angle: Math.PI * 0.075, radius: 80, model: "modObstMetalDoorMirrored", name: "door 2" }, + { sp: this.spline[471], angle: Math.PI * 0.5, radius: 0, model: "modObstMetroBlade", name: "blade 2" }, + { sp: this.spline[549], angle: Math.PI * 0.1, radius: 80, model: "modObstMetalDoorMirrored", name: "door 3" }, + { sp: this.spline[549], angle: Math.PI * 0.5, radius: 0, model: "modObstMetroBlade", name: "blade 3" }, + ] + + break; + case 2://CONSTRUCTION + ty = 0; + tp = 0; + tr = 0; + + this.createStartTunnel(); + + for (let i = 0; i < 4; i++) { this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128Octagon", this.textureArrays.scaffoldingLight[i % 4]); } + for (let i = 0; i < 12; i++) { this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128Octagon", this.textureArrays.scaffolding[i % 4]); } + for (let i = 0; i < 4; i++) { this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128Octagon", this.textureArrays.scaffoldingLight[i % 4]); } + //loopdiloop + for (let i = 0; i < 20; i++) { + this.addSpline(1, 0, Math.PI * -0.025, 0, "Loopdiloop", "modRingD64R128Octagon", this.textureArrays.scaffolding[i % 4]); + } + for (let i = 0; i < 40; i++) { + this.addSpline(1, Math.PI * -0.025, 0, 0, "Loopdiloop", "modRingD64R128Octagon", this.textureArrays.scaffolding[i % 4]); + } + for (let i = 0; i < 20; i++) { + this.addSpline(1, 0, Math.PI * 0.025, 0, "Loopdiloop", "modRingD64R128Octagon", this.textureArrays.scaffolding[i % 4]); + } + //loop + for (let i = 0; i < 80; i++) { + this.addSpline(1, 0, Math.PI * -0.025, 0, "Loop", "modRingD64R128Octagon", this.textureArrays.scaffolding[i % 4], true, { right: 5, up: 0, forward: 0 }); + //this.addSpline(1, 0, Math.PI * -0.025, 0, "Loop", "modRingD64R128RoundCanyon", this.textureArrays.canyon[1], true, { right: 5, up: 0, forward: 0 }); + } + //180 right + for (let i = 0; i < 40; i++) { + this.addSpline(1, Math.PI * 0.025, 0, 0, "180 Right", "modRingD64R128Quadrat", this.textureArrays.scaffolding[i % 4]); + //this.addSpline(1, Math.PI * 0.025, 0, 0, "180 Right", "modRingD64R128RoundCanyon", this.textureArrays.canyon[1]); + } + for (let i = 0; i < 3; i++) { + this.addSpline(1, 0, 0, 0, "180 Right End", "modRingD64R128Quadrat", this.textureArrays.scaffoldingEmpty[i % 4]); + } + this.spline[this.spline.length - 1].stitch = false + this.addSpline(1, 0, 0, Math.PI, "180 Right End", "modRingD64R128Quadrat", this.textureArrays.scaffoldingEmpty[3]); + + //dip in + this.addSpline(10, 0, Math.PI * 0.025, 0, "BackStraight", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + + //Underwater tunnel + this.addSpline(7, 0, Math.PI * -0.025, 0, "underwater tunnel", "modRingD64R128", this.textureArrays.glass[0]); + for (let i = 0; i < 3; i++) { + this.addSpline(1, 0, Math.PI * -0.025, 0, "underwater tunnel", "modRingD64R128", this.textureArrays.glassRing[i % 2]); + } + + for (let j = 0; j < 10; j++) { + this.addSpline(7, 0, 0, 0, "underwater tunnel", "modRingD64R128", this.textureArrays.glass[0]); + for (let i = 0; i < 3; i++) { + this.addSpline(1, 0, 0, 0, "underwater tunnel", "modRingD64R128", this.textureArrays.glassRing[i % 2]); + } + } + this.addSpline(5, 0, 0, 0, "underwater tunnel", "modRingD64R128", this.textureArrays.glass[0]); + + for (let j = 0; j < 3; j++) { + //180 back + this.addSpline(7, Math.PI * -0.025, 0, 0, "underwater tunnel", "modRingD64R128", this.textureArrays.glass[0]); + for (let i = 0; i < 3; i++) { + this.addSpline(1, Math.PI * -0.025, 0, 0, "underwater tunnel", "modRingD64R128", this.textureArrays.glassRing[i % 2]); + } + } + + this.addSpline(7, 0, Math.PI * -0.025, 0, "underwater tunnel dip", "modRingD64R128", this.textureArrays.glass[0]); + for (let i = 0; i < 3; i++) { + this.addSpline(1, 0, Math.PI * -0.025, 0, "underwater tunnel dip", "modRingD64R128", this.textureArrays.glassRing[i % 2]); + } + + //dip out + this.addSpline(10, 0, Math.PI * 0.025, 0, "dip out of tunnel", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + + //loop + this.addSpline(80, 0, Math.PI * -0.025, 0, "loop", "modRingD64R128", this.textureArrays.energySlide[0], true, { right: 5, up: 0, forward: 0 }); + + for (let i = 0; i < 10; i++) { + this.addSpline(1, Math.PI * -0.025, 0, 0, "Start Straight", "modRingD64R128Quadrat", this.textureArrays.scaffolding[i % 4]); + } + + for (let i = 2; i < 26; i++) {//24 length + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128Quadrat", this.textureArrays.scaffolding[i % 4]); + } + + this.addSpline(1, 0, 0, 0, "BackStraight", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + + //this.spline[this.spline.length - 1].stitch = false; + + obstSpots = []; + /*for(let i = 244 ; i < 363 ; i++){ + //obstSpots.push({sp: this.spline[i], angle: 0, radius: 0, model: "modObstWatertunnelCollar", name: "warn 0water" + String(i)},) + }*/ + break; + case 3://PIPELINE + ty = 0; + tp = 0; + tr = 0; + + this.createStartTunnel(); + + for (let i = 0; i < 2; i++) { + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowStraight[0]); + for (let j = 0; j < 4; j++) { + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowPattern[4]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowPattern[5]); + } + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowStraight[1]); + + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[1 + Math.floor(Math.random() * 2)]); + + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[3 + Math.floor(Math.random() * 2)]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[0]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[1 + Math.floor(Math.random() * 2)]); + + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[3 + Math.floor(Math.random() * 2)]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[0]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[1 + Math.floor(Math.random() * 2)]); + + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[3 + Math.floor(Math.random() * 2)]); + + for (let j = 0; j < 4; j++) { + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowPattern[4]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowPattern[5]); + } + } + + //large 180 R + for (let i = 0; i < 2; i++) { + a = Math.PI / 80; + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowStraight[0]); + for (let j = 0; j < 4; j++) { + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowPattern[4]); + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowPattern[5]); + } + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowStraight[1]); + + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowFill[1 + Math.floor(Math.random() * 2)]); + + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowFill[3 + Math.floor(Math.random() * 2)]); + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowFill[0]); + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowFill[1 + Math.floor(Math.random() * 2)]); + + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowFill[3 + Math.floor(Math.random() * 2)]); + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowFill[0]); + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowFill[1 + Math.floor(Math.random() * 2)]); + + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowFill[3 + Math.floor(Math.random() * 2)]); + + for (let j = 0; j < 4; j++) { + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowPattern[4]); + this.addSpline(1, a, 0, 0, "180R", "modRingD64R128", this.textureArrays.pipelineYellowPattern[5]); + } + } + + //short spiral + this.addSpline(2, 0, 0, 0, "Spiral", "modRingD64R128", this.textureArrays.pipelineYellowStraight[0]); + for (let i = 0; i < 16; i++) { + this.addSpline(1, 0, 0, 0, "Spiral", "modRingD64R128", this.textureArrays.pipelineYellowSpiral[0]); + this.addSpline(1, 0, 0, 0, "Spiral", "modRingD64R128", this.textureArrays.pipelineYellowSpiral[1]); + } + this.addSpline(2, 0, 0, 0, "Spiral", "modRingD64R128", this.textureArrays.pipelineYellowStraight[0]); + + //down kicker + for (let i = 0; i < 7; i++) { + this.addSpline(1, 0, Math.PI * 0.025, 0, "first downslope", "modRingD64R128", this.textureArrays.pipelineYellowRing[i % 2]); + } + this.addSpline(1, 0, Math.PI * 0.025, 0, "first downslope", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + this.addSpline(1, 0, Math.PI * 0.025, 0, "first downslope", "modRingD64R128", this.textureArrays.darkMetalRing[1]); + this.addSpline(1, 0, Math.PI * 0.025, 0, "first downslope", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + + this.addSpline(1, 0, Math.PI * -0.025, 0, "first downslope", "modRingD64R128CoreStart", this.textureArrays.atom[0]); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, Math.PI * -0.025, 0, "first downslope", "modRingD64R128Core", this.textureArrays.atom[0]); + } + this.addSpline(1, 0, Math.PI * -0.025, 0, "first downslope", "modRingD64R128Core", this.textureArrays.atomRing[0]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "first downslope", "modRingD64R128Core", this.textureArrays.atomRing[1]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "first downslope", "modRingD64R128Core", this.textureArrays.atomRing[0]); + + //straight + for (let j = 0; j < 2; j++) { + this.addSpline(7, 0, 0, 0, "small straight", "modRingD64R128Core", this.textureArrays.atom[0]); + this.addSpline(1, 0, 0, 0, "small straight", "modRingD64R128Core", this.textureArrays.atomRing[0]); + this.addSpline(1, 0, 0, 0, "small straight", "modRingD64R128Core", this.textureArrays.atomRing[1]); + this.addSpline(1, 0, 0, 0, "small straight", "modRingD64R128Core", this.textureArrays.atomRing[0]); + } + + //90 left down + for (let j = 0; j < 2; j++) { + a = Math.PI / 40; + this.addSpline(7, -a, 0, 0, "90 left", "modRingD64R128Core", this.textureArrays.atom[0], true, { right: 0, up: 7, forward: 0 }); + this.addSpline(1, -a, 0, 0, "90 left", "modRingD64R128Core", this.textureArrays.atomRing[0], true, { right: 0, up: 7, forward: 0 }); + this.addSpline(1, -a, 0, 0, "90 left", "modRingD64R128Core", this.textureArrays.atomRing[1], true, { right: 0, up: 7, forward: 0 }); + this.addSpline(1, -a, 0, 0, "90 left", "modRingD64R128Core", this.textureArrays.atomRing[0], true, { right: 0, up: 7, forward: 0 }); + } + + for (let j = 0; j < 16; j++) { + a = Math.PI / 320; + for (let i = 0; i < 6; i++) { + this.addSpline(1, a, 0, 0, "long right kink", "modRingD64R128AtomRoom", this.textureArrays.atom[0]); + } + this.addSpline(1, a, 0, 0, "long right kink", "modRingD64R128AtomRoom01", this.textureArrays.atomRing[0]); + this.addSpline(1, a, 0, 0, "long right kink", "modRingD64R128AtomRoom", this.textureArrays.atomRing[1]); + this.addSpline(1, a, 0, 0, "long right kink", "modRingD64R128AtomRoom02", this.textureArrays.atomRing[0]); + } + + + //up kicker + for (let i = 0; i < 7; i++) { + this.addSpline(1, 0, Math.PI * -0.025, 0, "kicker up", "modRingD64R128Core", this.textureArrays.atom[0]); + } + this.addSpline(1, 0, Math.PI * -0.025, 0, "kicker up", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "kicker up", "modRingD64R128", this.textureArrays.darkMetalRing[1]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "kicker up", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + for (let i = 0; i < 7; i++) { + this.addSpline(1, 0, Math.PI * 0.025, 0, "kicker up", "modRingD64R128", this.textureArrays.pipelineYellowRing[i % 2]); + } + this.addSpline(1, 0, Math.PI * 0.025, 0, "kicker up", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + this.addSpline(1, 0, Math.PI * 0.025, 0, "kicker up", "modRingD64R128", this.textureArrays.darkMetalRing[1]); + this.addSpline(1, 0, Math.PI * 0.025, 0, "kicker up", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + + + //long pipeline straight + for (let i = 0; i < 2; i++) { + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[1 + Math.floor(Math.random() * 2)]); + + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[3 + Math.floor(Math.random() * 2)]); + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[0]); + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[1 + Math.floor(Math.random() * 2)]); + + for (let j = 0; j < 3; j++) { + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + } + + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[3 + Math.floor(Math.random() * 2)]); + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[0]); + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[1 + Math.floor(Math.random() * 2)]); + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + } + + //short spiral + this.addSpline(2, 0, 0, 0, "Spiral", "modRingD64R128", this.textureArrays.pipelineYellowStraight[0]); + for (let i = 0; i < 16; i++) { + this.addSpline(1, 0, 0, 0, "Spiral", "modRingD64R128", this.textureArrays.pipelineYellowSpiral[0]); + this.addSpline(1, 0, 0, 0, "Spiral", "modRingD64R128", this.textureArrays.pipelineYellowSpiral[1]); + } + this.addSpline(2, 0, 0, 0, "Spiral", "modRingD64R128", this.textureArrays.pipelineYellowStraight[0]); + + //90R long + for (let i = 0; i < 4; i++) { + a = Math.PI / 80 + this.addSpline(1, a, 0, 0, "90R", "modRingD64R128", this.textureArrays.pipelineYellowStraight[0]); + for (let j = 0; j < 4; j++) { + this.addSpline(1, a, 0, 0, "90R", "modRingD64R128", this.textureArrays.pipelineYellowPattern[4]); + this.addSpline(1, a, 0, 0, "90R", "modRingD64R128", this.textureArrays.pipelineYellowPattern[5]); + } + this.addSpline(1, a, 0, 0, "90R", "modRingD64R128", this.textureArrays.pipelineYellowStraight[1]); + } + + + //straight + for (let i = 0; i < 2; i++) { + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[1 + Math.floor(Math.random() * 2)]); + + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[3 + Math.floor(Math.random() * 2)]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[0]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[1 + Math.floor(Math.random() * 2)]); + + for (let j = 0; j < 3; j++) { + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + } + + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[3 + Math.floor(Math.random() * 2)]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[0]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[1 + Math.floor(Math.random() * 2)]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + } + + + //90R long + for (let i = 0; i < 8; i++) { + a = Math.PI / 160 + this.addSpline(1, a, 0, 0, "90R", "modRingD64R128", this.textureArrays.pipelineYellowStraight[0]); + for (let j = 0; j < 4; j++) { + this.addSpline(1, a, 0, 0, "90R", "modRingD64R128", this.textureArrays.pipelineYellowPattern[4]); + this.addSpline(1, a, 0, 0, "90R", "modRingD64R128", this.textureArrays.pipelineYellowPattern[5]); + } + this.addSpline(1, a, 0, 0, "90R", "modRingD64R128", this.textureArrays.pipelineYellowStraight[1]); + } + + + //short spiral + this.addSpline(2, 0, 0, 0, "Spiral", "modRingD64R128", this.textureArrays.pipelineYellowStraight[0]); + for (let i = 0; i < 16; i++) { + this.addSpline(1, 0, 0, 0, "Spiral", "modRingD64R128", this.textureArrays.pipelineYellowSpiral[0]); + this.addSpline(1, 0, 0, 0, "Spiral", "modRingD64R128", this.textureArrays.pipelineYellowSpiral[1]); + } + this.addSpline(2, 0, 0, 0, "Spiral", "modRingD64R128", this.textureArrays.pipelineYellowStraight[0]); + + //lr kicker + for (let i = 0; i < 7; i++) { + this.addSpline(1, Math.PI * -0.025, 0, 0, "kicker up", "modRingD64R128", this.textureArrays.pipelineYellowRing[i % 2]); + } + this.addSpline(1, Math.PI * -0.025, 0, 0, "kicker up", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + this.addSpline(1, Math.PI * -0.025, 0, 0, "kicker up", "modRingD64R128", this.textureArrays.darkMetalRing[1]); + this.addSpline(1, Math.PI * -0.025, 0, 0, "kicker up", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + for (let i = 0; i < 7; i++) { + this.addSpline(1, Math.PI * 0.025, 0, 0, "kicker up", "modRingD64R128", this.textureArrays.pipelineYellowRing[i % 2]); + } + this.addSpline(1, Math.PI * 0.025, 0, 0, "kicker up", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + this.addSpline(1, Math.PI * 0.025, 0, 0, "kicker up", "modRingD64R128", this.textureArrays.darkMetalRing[1]); + this.addSpline(1, Math.PI * 0.025, 0, 0, "kicker up", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + + //to finish + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + + + //down kicker + for (let i = 0; i < 7; i++) { + this.addSpline(1, 0, Math.PI * 0.025, 0, "first downslope", "modRingD64R128", this.textureArrays.pipelineYellowRing[i % 2]); + } + this.addSpline(1, 0, Math.PI * 0.025, 0, "first downslope", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + this.addSpline(1, 0, Math.PI * 0.025, 0, "first downslope", "modRingD64R128", this.textureArrays.darkMetalRing[1]); + this.addSpline(1, 0, Math.PI * 0.025, 0, "first downslope", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + + this.addSpline(1, 0, Math.PI * -0.025, 0, "first downslope", "modRingD64R128CoreStart", this.textureArrays.atom[0]); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, Math.PI * -0.025, 0, "first downslope", "modRingD64R128Core", this.textureArrays.atom[0]); + } + this.addSpline(1, 0, Math.PI * -0.025, 0, "first downslope", "modRingD64R128Core", this.textureArrays.atomRing[0]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "first downslope", "modRingD64R128Core", this.textureArrays.atomRing[1]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "first downslope", "modRingD64R128Core", this.textureArrays.atomRing[0]); + + for (let j = 0; j < 3; j++) { + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, 0, 0, "long right kink", "modRingD64R128AtomRoom", this.textureArrays.atom[0]); + } + this.addSpline(1, 0, 0, 0, "long right kink", "modRingD64R128AtomRoom01", this.textureArrays.atomRing[0]); + this.addSpline(1, 0, 0, 0, "long right kink", "modRingD64R128AtomRoom", this.textureArrays.atomRing[1]); + this.addSpline(1, 0, 0, 0, "long right kink", "modRingD64R128AtomRoom02", this.textureArrays.atomRing[0]); + } + + //up kicker + for (let i = 0; i < 7; i++) { + this.addSpline(1, 0, Math.PI * -0.025, 0, "kicker up", "modRingD64R128Core", this.textureArrays.atom[0]); + } + this.addSpline(1, 0, Math.PI * -0.025, 0, "kicker up", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "kicker up", "modRingD64R128", this.textureArrays.darkMetalRing[1]); + this.addSpline(1, 0, Math.PI * -0.025, 0, "kicker up", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + for (let i = 0; i < 7; i++) { + this.addSpline(1, 0, Math.PI * 0.025, 0, "kicker up", "modRingD64R128", this.textureArrays.pipelineYellowRing[i % 2]); + } + this.addSpline(1, 0, Math.PI * 0.025, 0, "kicker up", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + this.addSpline(1, 0, Math.PI * 0.025, 0, "kicker up", "modRingD64R128", this.textureArrays.darkMetalRing[1]); + this.addSpline(1, 0, Math.PI * 0.025, 0, "kicker up", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + + //end corrrection + this.addSpline(40, Math.PI * -0.025, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[0]); + this.addSpline(60, Math.PI * -0.02, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[0]); + this.addSpline(10, Math.PI * 0.025, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[0], true, { right: 16, up: 0, forward: 0 }); + + //end + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowStraight[0], true, { right: 0, up: -8, forward: 0 }); + for (let j = 0; j < 4; j++) { + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowPattern[4], true, { right: 0, up: -8, forward: 0 }); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowPattern[5], true, { right: 0, up: -8, forward: 0 }); + } + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowStraight[1], true, { right: 0, up: -8, forward: 0 }); + + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[1 + Math.floor(Math.random() * 2)], true, { right: 0, up: -8, forward: 0 }); + + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)], true, { right: 0, up: -8, forward: 0 }); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)], true, { right: 0, up: -8, forward: 0 }); + + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[3 + Math.floor(Math.random() * 2)], true, { right: 0, up: -8, forward: 0 }); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[0], true, { right: 0, up: -8, forward: 0 }); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[1 + Math.floor(Math.random() * 2)], true, { right: 0, up: -8, forward: 0 }); + + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[3]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowRing[2]); + + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[3 + Math.floor(Math.random() * 2)]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[0]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[1 + Math.floor(Math.random() * 2)]); + + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.pipelineYellowFill[5 + Math.floor(Math.random() * 2)]); + + //end ring + this.addSpline(1, 0, 0, 0, "first downslope", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + this.addSpline(1, 0, 0, 0, "first downslope", "modRingD64R128", this.textureArrays.darkMetalRing[1]); + this.addSpline(1, 0, 0, 0, "first downslope", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + + //this.spline[this.spline.length - 1].stitch = false; + + //obstaccles + obstSpots = [ + { sp: this.spline[115], angle: Math.PI * 0.5, radius: 0, model: "modObstMetalDoorMirrored", name: "door 0" }, + { sp: this.spline[249], angle: Math.PI * 0.025, radius: 64, model: "modObstMetalDoorMirrored", name: "door 1" }, + { sp: this.spline[450], angle: Math.PI * 0, radius: 128, model: "modObstMetalDoorMirrored", name: "door 2" }, + { sp: this.spline[855], angle: Math.PI * 0.025, radius: 96, model: "modObstMetalDoorMirrored", name: "door 3" }, + //{ sp: this.spline[900], angle: Math.PI * 0, radius: 78, model: "modObstMetalDoorMirrored", name: "door 4" }, + + { sp: this.spline[660], angle: Math.PI * 0, radius: 16, model: "modObstMetalDoorMirrored", name: "door 4" }, + + { sp: this.spline[249], angle: Math.PI * 0.5, radius: 0, model: "modObstMetroBlade", name: "blade 0" }, + { sp: this.spline[450], angle: Math.PI * 0.5, radius: 0, model: "modObstMetroBlade", name: "blade 1" }, + { sp: this.spline[855], angle: Math.PI * 0.5, radius: 0, model: "modObstMetroBlade", name: "blade 2" }, + { sp: this.spline[900], angle: Math.PI * 0.05, radius: 0, model: "modObstMetroBlade", name: "blade 3" }, + + //{ sp: this.spline[43], angle: Math.PI * 0.5, radius: 0, model: "modObstMetroBlade", name: "blade 0" }, + // + //{ sp: this.spline[44], angle: 0, radius: 0, model: "modObst3x3Door", name: "warn 0" }, + //{ sp: this.spline[43], angle: Math.PI * 0.025, radius: 76, model: "modObstMetalDoorMirrored", name: "door 0" }, + //{ sp: this.spline[43], angle: Math.PI * 0.5, radius: 0, model: "modObstMetroBlade", name: "blade 0" }, + //{ sp: this.spline[324], angle: 0, radius: 80, model: "modObstMetalDoorMirrored", name: "door 1" }, + //{ sp: this.spline[324], angle: Math.PI * 0.5, radius: 0, model: "modObstMetroBlade", name: "blade 1" }, + //{ sp: this.spline[471], angle: Math.PI * 0.075, radius: 80, model: "modObstMetalDoorMirrored", name: "door 2" }, + //{ sp: this.spline[471], angle: Math.PI * 0.5, radius: 0, model: "modObstMetroBlade", name: "blade 2" }, + //{ sp: this.spline[549], angle: Math.PI * 0.1, radius: 80, model: "modObstMetalDoorMirrored", name: "door 3" }, + //{ sp: this.spline[549], angle: Math.PI * 0.5, radius: 0, model: "modObstMetroBlade", name: "blade 3" }, + ] + break; + case 4: //canyon oval + ty = 0; + tp = 0; + tr = 0; + this.createStartTunnel(); + + for (let j = 0; j < 2; j++) { + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128Lab", this.textureArrays.labRing[0]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.labRing[0]); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128Lab", this.textureArrays.lab[i % 3]); + } + } + + this.addSpline(1, Math.PI * 0.05, 0, 0, "Start Kink", "modRingD64R128Lab", this.textureArrays.labRing[0]); + this.addSpline(1, Math.PI * 0.05, 0, 0, "Start Kink", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, Math.PI * 0.05, 0, 0, "Start Kink", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, Math.PI * 0.05, 0, 0, "Start Kink", "modRingD64R128", this.textureArrays.labRing[0]); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, 0, 0, "Start Kink", "modRingD64R128", this.textureArrays.metalRoad[0]); + } + + for (let i = 0; i < 40; i++) { + this.addSpline(1, 0, 0, 0, "Ramp Down", "modRingD64R128", this.textureArrays.metalRoad[0], true, { right: 0, up: 0, forward: 0 }); + } + for (let i = 0; i < 40; i++) { + this.addSpline(1, -Math.PI * 0.0025, 0, 0, "Ramp Down", "modRingD64R128", this.textureArrays.metalRoad[0], true, { right: 0, up: -7, forward: 0 }); + } + for (let i = 0; i < 20; i++) { + this.addSpline(1, 0, 0, 0, "Ramp Down", "modRingD64R128", this.textureArrays.metalRoad[0], true, { right: 0, up: -i*0.5, forward: 0 }); + } + for (let i = 0; i < 40; i++) { + this.addSpline(1, -Math.PI * 0.0035, 0, 0, "Ramp Down", "modRingD64R128", this.textureArrays.metalRoad[0], true, { right: 0, up: i*0.5, forward: 0 }); + } + + //start of canyon + this.addSpline(40, 0, 0, 0, "Canyon Entry", "modRingD64R128RoundCanyon", this.textureArrays.canyon[0], true, { right: 0, up: 0, forward: 0 }); + + for (let i = 0; i < 12; i++) { + this.addSpline(17, Math.PI * 0.005, 0, 0, "Canyon Curve", "modRingD64R128RoundCanyon", this.textureArrays.canyon[0], true, { right: 0, up: 0, forward: 0 }); + this.addSpline(1, Math.PI * 0.005, 0, 0, "Back Canyon", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + this.addSpline(1, Math.PI * 0.005, 0, 0, "Back Canyon", "modRingD64R128", this.textureArrays.darkMetalRing[1]); + this.addSpline(1, Math.PI * 0.005, 0, 0, "Back Canyon", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + } + this.addSpline(13, Math.PI * 0.005, 0, 0, "Canyon Curve", "modRingD64R128RoundCanyon", this.textureArrays.canyon[0], true, { right: 0, up: 0, forward: 0 }); + this.addSpline(1, Math.PI * 0.005, 0, 0, "Back Canyon", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + this.addSpline(1, Math.PI * 0.005, 0, 0, "Back Canyon", "modRingD64R128", this.textureArrays.darkMetalRing[1]); + this.addSpline(1, Math.PI * 0.005, 0, 0, "Back Canyon", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + + for (let i = 0; i < 20; i++) { + this.addSpline(1, Math.PI * -0.0025, 0, 0, "Canyon Exit", "modRingD64R128RoundCanyon", this.textureArrays.canyon[0], true, { right: 0, up: 0, forward: 0 }); + } + + /*for (let i = 0; i < 40; i++) { + this.addSpline(1, Math.PI * -0.003, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.metalRoad[0], true, { right: 0, up: 0, forward: 0 }); + }*/ + this.addSpline(1, Math.PI * -0.003, 0, 0, "BackStraight", "modRingD64R128CoreStart", this.textureArrays.ventRing[0]); + this.addSpline(1, Math.PI * -0.003, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[1]); + this.addSpline(1, Math.PI * -0.003, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[0]); + this.addSpline(7, Math.PI * -0.003, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.vent[0]); + for (let i = 0; i < 3; i++){ + this.addSpline(1, Math.PI * -0.003, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[0]); + this.addSpline(1, Math.PI * -0.003, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[1]); + this.addSpline(1, Math.PI * -0.003, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[0]); + this.addSpline(7, Math.PI * -0.003, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.vent[0]); + } + + //back straight + for (let j = 0; j < 2; j++) { + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128Lab", this.textureArrays.labRing[0]); + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, 0, 0, "Back Straight", "modRingD64R128", this.textureArrays.labRing[0]); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, 0, 0, "Lab Spiral", "modRingD64R128Lab", this.textureArrays.lab[i % 3]); + } + } + this.addSpline(1, 0, Math.PI * 0.02, 0, "Back Straight", "modRingD64R128Lab", this.textureArrays.labRing[0]); + this.addSpline(1, 0, Math.PI * 0.02, 0, "Back Straight", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, Math.PI * 0.02, 0, "Back Straight", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, Math.PI * 0.02, 0, "Back Straight", "modRingD64R128", this.textureArrays.labRing[0]); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, Math.PI * 0.02, 0, "Lab Spiral", "modRingD64R128Lab", this.textureArrays.lab[i % 3]); + } + this.addSpline(1, 0, Math.PI * -0.02, 0, "Back Straight", "modRingD64R128Lab", this.textureArrays.labRing[0]); + this.addSpline(1, 0, Math.PI * -0.02, 0, "Back Straight", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, Math.PI * -0.02, 0, "Back Straight", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, Math.PI * -0.02, 0, "Back Straight", "modRingD64R128", this.textureArrays.labRing[0]); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, Math.PI * -0.02, 0, "Lab Spiral", "modRingD64R128Lab", this.textureArrays.lab[i % 3]); + } + + //back canyon + //this.addSpline(40, Math.PI * -0.003, 0, 0, "Back Canyon", "modRingD64R128RoundCanyon", this.textureArrays.canyon[0]); + for (let i = 0; i < 4; i++){ + this.addSpline(7, Math.PI * -0.003, 0, 0, "Back Canyon", "modRingD64R128RoundCanyon", this.textureArrays.canyon[0]); + this.addSpline(1, Math.PI * -0.003, 0, 0, "Back Canyon", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + this.addSpline(1, Math.PI * -0.003, 0, 0, "Back Canyon", "modRingD64R128", this.textureArrays.darkMetalRing[1]); + this.addSpline(1, Math.PI * -0.003, 0, 0, "Back Canyon", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + } + + this.addSpline(7, Math.PI * -0.001, 0, 0, "Back Canyon", "modRingD64R128RoundCanyon", this.textureArrays.canyon[0]); + this.addSpline(1, Math.PI * -0.001, 0, 0, "Back Canyon", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + this.addSpline(1, Math.PI * -0.001, 0, 0, "Back Canyon", "modRingD64R128", this.textureArrays.darkMetalRing[1]); + this.addSpline(1, Math.PI * -0.001, 0, 0, "Back Canyon", "modRingD64R128", this.textureArrays.darkMetalRing[0]); + + //this.addSpline(40, Math.PI * -0.004, 0, 0, "Back Canyon", "modRingD64R128RoundCanyon", this.textureArrays.canyon[0]); + for (let i = 0; i < 2; i++){ + this.addSpline(16, Math.PI * -0.004, 0, 0, "Back Canyon", "modRingD64R128RoundCanyon", this.textureArrays.canyon[0]); + this.addSpline(1, Math.PI * -0.004, 0, 0, "Loopdiloop", "modRingD64R128Octagon", this.textureArrays.scaffoldingLight[0]); + this.addSpline(1, Math.PI * -0.004, 0, 0, "Loopdiloop", "modRingD64R128Octagon", this.textureArrays.scaffoldingLight[1]); + this.addSpline(1, Math.PI * -0.004, 0, 0, "Loopdiloop", "modRingD64R128Octagon", this.textureArrays.scaffoldingLight[2]); + this.addSpline(1, Math.PI * -0.004, 0, 0, "Loopdiloop", "modRingD64R128Octagon", this.textureArrays.scaffoldingLight[3]); + } + + //this.addSpline(128, Math.PI * 0.004, 0, 0, "Back Canyon", "modRingD64R128RoundCanyon", this.textureArrays.canyon[0]); + for (let i = 0; i < 6; i++){ + this.addSpline(16, Math.PI * 0.004, 0, 0, "Back Canyon", "modRingD64R128RoundCanyon", this.textureArrays.canyon[0]); + this.addSpline(1, Math.PI * 0.004, 0, 0, "Loopdiloop", "modRingD64R128Octagon", this.textureArrays.scaffoldingLight[0]); + this.addSpline(1, Math.PI * 0.004, 0, 0, "Loopdiloop", "modRingD64R128Octagon", this.textureArrays.scaffoldingLight[1]); + this.addSpline(1, Math.PI * 0.004, 0, 0, "Loopdiloop", "modRingD64R128Octagon", this.textureArrays.scaffoldingLight[2]); + this.addSpline(1, Math.PI * 0.004, 0, 0, "Loopdiloop", "modRingD64R128Octagon", this.textureArrays.scaffoldingLight[3]); + } + this.addSpline(8, Math.PI * 0.004, 0, 0, "Back Canyon", "modRingD64R128RoundCanyon", this.textureArrays.canyon[0]); + + //second vent + this.addSpline(1, 0, 0, 0, "BackStraight", "modRingD64R128CoreStart", this.textureArrays.ventRing[0]); + this.addSpline(1, 0, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[1]); + this.addSpline(1, 0, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[0]); + this.addSpline(7, 0, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.vent[0]); + for (let i = 0; i < 7; i++) { + this.addSpline(1, 0, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[0]); + this.addSpline(1, 0, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[1]); + this.addSpline(1, 0, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.ventRing[0]); + this.addSpline(7, 0, 0, 0, "BackStraight", "modRingD64R128Core", this.textureArrays.vent[0]); + } + this.addSpline(1, 0, 0, 0, "BackStraight", "modRingD64R128CoreStart", this.textureArrays.ventRing[0]); + + for (let i = 0; i < 80; i++) { + this.addSpline(1, Math.PI * 0.0075, 0, 0, "Back", "modRingD64R128", this.textureArrays.metalRoad[0], true, { right: 0, up: 0, forward: 0 }); + } + + for (let j = 0; j < 2; j++) { + this.addSpline(1, Math.PI * 0.006, 0, 0, "Start Straight", "modRingD64R128Lab", this.textureArrays.labRing[0], true, { right: 0, up: 1, forward: 0 }); + this.addSpline(1, Math.PI * 0.006, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.labRing[1], true, { right: 0, up: 1, forward: 0 }); + this.addSpline(1, Math.PI * 0.006, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.labRing[1], true, { right: 0, up: 1, forward: 0 }); + this.addSpline(1, Math.PI * 0.006, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.labRing[0], true, { right: 0, up: 1, forward: 0 }); + for (let i = 0; i < 6; i++) { + this.addSpline(1, Math.PI * 0.006, 0, 0, "Start Straight", "modRingD64R128Lab", this.textureArrays.lab[i % 3], true, { right: 0, up: 1, forward: 0 }); + } + } + + for (let j = 0; j < 2; j++) { + this.addSpline(1, 0, Math.PI * -0.004, 0, "Back Straight", "modRingD64R128Lab", this.textureArrays.labRing[0]); + this.addSpline(1, 0, Math.PI * -0.004, 0, "Back Straight", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, Math.PI * -0.004, 0, "Back Straight", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, Math.PI * -0.004, 0, "Back Straight", "modRingD64R128", this.textureArrays.labRing[0]); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, Math.PI * -0.004, 0, "Lab Spiral", "modRingD64R128Lab", this.textureArrays.lab[i % 3]); + } + } + for (let j = 0; j < 2; j++) { + this.addSpline(1, 0, Math.PI * 0.004, 0, "Back Straight", "modRingD64R128Lab", this.textureArrays.labRing[0]); + this.addSpline(1, 0, Math.PI * 0.004, 0, "Back Straight", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, Math.PI * 0.004, 0, "Back Straight", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, Math.PI * 0.004, 0, "Back Straight", "modRingD64R128", this.textureArrays.labRing[0]); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, Math.PI * 0.004, 0, "Lab Spiral", "modRingD64R128Lab", this.textureArrays.lab[i % 3]); + } + } + + for (let j = 0; j < 2; j++) { + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128Lab", this.textureArrays.labRing[0], true, { right: 3.2, up: 0, forward: 0 }); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.labRing[1], true, { right: 3.2, up: 0, forward: 0 }); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.labRing[1], true, { right: 3.2, up: 0, forward: 0 }); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.labRing[0], true, { right: 3.2, up: 0, forward: 0 }); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128Lab", this.textureArrays.lab[i % 3], true, { right: 3.2, up: 0, forward: 0 }); + } + } + for (let j = 0; j < 3; j++) { + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128Lab", this.textureArrays.labRing[0]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.labRing[1]); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.labRing[0]); + for (let i = 0; i < 6; i++) { + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128Lab", this.textureArrays.lab[i % 3]); + } + } + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128Lab", this.textureArrays.labRing[0], true, { right: 0, up: 4, forward: 0 }); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.labRing[1], true, { right: 0, up: 4, forward: 0 }); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.labRing[1], true, { right: 0, up: 4, forward: 0 }); + this.addSpline(1, 0, 0, 0, "Start Straight", "modRingD64R128", this.textureArrays.labRing[0], true, { right: 0, up: 4, forward: 0 }); + + this.addSpline(3, 0, 0, 0, "Back", "modRingD64R128", this.textureArrays.metalRoad[0], true, { right: 0, up: 4, forward: 0 }); + + //end + this.spline[this.spline.length - 1].stitch = false; + + obstSpots = [ + //blades + { sp: this.spline[527], angle: (Math.PI / 1.5) * 0, radius: 0, model: "modObstVentBlade", name: "blade 0 0" }, + { sp: this.spline[527], angle: (Math.PI / 1.5) * 1, radius: 0, model: "modObstVentBlade", name: "blade 0 1" }, + { sp: this.spline[527], angle: (Math.PI / 1.5) * 2, radius: 0, model: "modObstVentBlade", name: "blade 0 2" }, + { sp: this.spline[569], angle: (Math.PI / 1.5) * 0, radius: 0, model: "modObstVentBlade", name: "blade 1 0" }, + { sp: this.spline[569], angle: (Math.PI / 1.5) * 1, radius: 0, model: "modObstVentBladeDestroyed", name: "blade 1 1" }, + { sp: this.spline[569], angle: (Math.PI / 1.5) * 2, radius: 0, model: "modObstVentBlade", name: "blade 1 2" }, + { sp: this.spline[827], angle: (Math.PI / 1.5) * 0, radius: 0, model: "modObstVentBlade", name: "blade 2 0" }, + { sp: this.spline[827], angle: (Math.PI / 1.5) * 1, radius: 0, model: "modObstVentBlade", name: "blade 2 1" }, + { sp: this.spline[827], angle: (Math.PI / 1.5) * 2, radius: 0, model: "modObstVentBlade", name: "blade 2 2" }, + { sp: this.spline[908], angle: (Math.PI / 1.5) * 0, radius: 0, model: "modObstVentBlade", name: "blade 3 0" }, + { sp: this.spline[908], angle: (Math.PI / 1.5) * 1, radius: 0, model: "modObstVentBlade", name: "blade 3 1" }, + { sp: this.spline[908], angle: (Math.PI / 1.5) * 2, radius: 0, model: "modObstVentBlade", name: "blade 3 2" }, + //other objects + { sp: this.spline[73], angle: Math.PI * 0.5, radius: 0, model: "modObstMetroBlade", name: "blade lights 0" }, + + { sp: this.spline[113], angle: Math.PI * -0.5, radius: 80, model: "modObstMetalDoorMirrored", name: "door 0" }, + { sp: this.spline[113], angle: Math.PI * 0.5, radius: 20, model: "modObstMetalDoorMirrored", name: "door 0" }, + { sp: this.spline[153], angle: Math.PI * -0.25, radius: 40, model: "modObstMetalDoorMirrored", name: "door 0" }, + { sp: this.spline[153], angle: Math.PI * 0.75, radius: 140, model: "modObstMetalDoorMirrored", name: "door 0" }, + { sp: this.spline[173], angle: Math.PI * -0.5, radius: 80, model: "modObstMetalDoorMirrored", name: "door 0" }, + { sp: this.spline[173], angle: Math.PI * 0.5, radius: 60, model: "modObstMetalDoorMirrored", name: "door 0" }, + + { sp: this.spline[1050], angle: Math.PI * -0.5, radius: 0, model: "modObstMetalDoorMirrored", name: "door 0" }, + + { sp: this.spline[212], angle: Math.PI * 0, radius: 0, model: "modObstMetalDoorMirrored", name: "door 0" }, + ]; + + break; + case 5: //huge oval + ty = 0; + tp = 0; + tr = 0; + + this.createStartTunnel(); + + //ramp down + for (let i = 0; i < 80; i++) { + //this.addSpline(1, Math.PI * 0.025, 0, 0, "Ramp Down", "modRingD64R128", this.textureArrays.darkMetalArrows[i % 3], true, { right: 0, up: -7, forward: 0 }); + this.addSpline(1, Math.PI * 0.025, 0, 0, "Ramp Down", "modRingD64R128RoundCanyonBoth", this.textureArrays.canyon[0], true, { right: 0, up: -7, forward: 0 }); + } + + //huge oval much fun + + for (let i = 0; i < 1024; i++) { + this.addSpline(1, Math.PI / 1024, 0, 0, "Bendyway", "modRingD64R128RoundCanyonBoth", i%10 < 2 ? this.textureArrays.canyon[1 + (i%2)] : this.textureArrays.canyon[0]); + } + + this.addSpline(44, 0, 0, 0, "Back straight", "modRingD64R128", this.textureArrays.darkMetalRing[1]); + + for (let i = 0; i < 1024; i++) { + this.addSpline(1, Math.PI / 1024, 0, 0, "Bendyway", "modRingD64R128", this.textureArrays.darkMetalRing[i % 3]); + } + + //ramp up + for (let i = 0; i < 80; i++) { + this.addSpline(1, Math.PI * 0.025, 0, 0, "Ramp Down", "modRingD64R128", this.textureArrays.darkMetalArrows[i % 3], true, { right: 0, up: 7, forward: 0 }); + } + + /* + for(let i = 0 ; i < 1024 ; i++){ + this.addSpline(1, Math.PI * 0.05, 0, 0, "Bendyway", "modRingD64R128", this.textureArrays.energySlide[0], true, {right: 0, up: 7, forward: 0}); + } + */ + + this.spline[this.spline.length - 1].stitch = false; + + obstSpots = []; + break; + case 55: //blank oval + ty = 0; + tp = 0; + tr = 0; + + this.createStartTunnel(); + + //ramp down + for (let i = 0; i < 80; i++) { + this.addSpline(1, Math.PI * 0.025, 0, 0, "Ramp Down", "modRingD64R128", this.textureArrays.fullColor[2], true, { right: 0, up: -7, forward: 0 }); + } + + //huge oval much fun + + for (let i = 0; i < 1024; i++) { + this.addSpline(1, Math.PI / 1024, 0, 0, "Bendyway", "modRingD64R128", this.textureArrays.fullColor[2]); + } + + this.addSpline(44, 0, 0, 0, "Back straight", "modRingD64R128", this.textureArrays.fullColor[2]); + + for (let i = 0; i < 1024; i++) { + this.addSpline(1, Math.PI / 1024, 0, 0, "Bendyway", "modRingD64R128", this.textureArrays.fullColor[2]); + } + + //ramp up + for (let i = 0; i < 80; i++) { + this.addSpline(1, Math.PI * 0.025, 0, 0, "Ramp Down", "modRingD64R128", this.textureArrays.fullColor[2], true, { right: 0, up: 7, forward: 0 }); + } + + /* + for(let i = 0 ; i < 1024 ; i++){ + this.addSpline(1, Math.PI * 0.05, 0, 0, "Bendyway", "modRingD64R128", this.textureArrays.energySlide[0], true, {right: 0, up: 7, forward: 0}); + } + */ + + this.spline[this.spline.length - 1].stitch = false; + + obstSpots = []; + break; + case 1997: + this.addSpline(12, 0, 0, 0, "Start - Box 0", null, null, false); + this.spline[0].x = 256; + this.spline[0].y = 0; + this.spline[0].z = -200; + this.spline[this.spline.length - 1].stitch = false; + obstSpots = []; + break; + + case 9000://tutorial + //this.addSpline(80, 0, 0, 0, "Start / Finish Straight", "modRingD64R128", this.textureArrays.fullColor[2], true ); + + //s shape up + //this.addSpline(20, 0, Math.PI * -0.025, 0, "Right", "modRingD64R128", this.textureArrays.fullColor[2], true ); + //this.addSpline(20, 0, Math.PI * 0.025, 0, "Right", "modRingD64R128", this.textureArrays.fullColor[2], true ); + + //turn right 180 + this.addSpline(80, Math.PI * 0.0125, 0, 0, "Right", "modRingD64R128", this.textureArrays.fullColor[2], true); + + this.addSpline(80, 0, 0, 0, "Start / Finish Straight", "modRingD64R128", this.textureArrays.fullColor[2], true); + + //turn right 180 + this.addSpline(80, Math.PI * 0.0125, 0, 0, "Right", "modRingD64R128", this.textureArrays.fullColor[2], true); + + this.addSpline(80, 0, 0, 0, "Start / Finish Straight", "modRingD64R128", this.textureArrays.fullColor[2], true); + obstSpots = []; + break; + case 9001://tutorial 2 + //huge oval much fun + this.addSpline(44, 0, 0, 0, "Back straight", "modRingD64R128", this.textureArrays.fullColor[2]); + + for (let i = 0; i < 1024; i++) { + this.addSpline(1, Math.PI / 1024, 0, 0, "Bendyway", "modRingD64R128", this.textureArrays.fullColor[2]); + } + + this.addSpline(44, 0, 0, 0, "Back straight", "modRingD64R128", this.textureArrays.fullColor[2]); + + for (let i = 0; i < 1024; i++) { + this.addSpline(1, Math.PI / 1024, 0, 0, "Bendyway", "modRingD64R128", this.textureArrays.fullColor[2]); + } + + obstSpots = []; + break; + case 9002://tutorial 3 + //huge oval much fun + this.addSpline(40, 0, 0, 0, "Start straight", "modRingD64R128", this.textureArrays.fullColor[3]); + + + //this.addSpline(10, 0, 0, -Math.PI / 20, "Back straight", "modRingD64R128", this.textureArrays.fullColor[3]); + + //slow ramp to new pos + amt = 20; + ar = 0; + + //roll fully 2x + /* + for (let i = 0; i < amt * 1; i++) { + this.addSpline(1, 0, 0, (Math.PI * 2 / amt) * (i / amt), "Full Spiral In", "modRingD64R128", this.textureArrays.fullColor[3]); + } + for (let i = 0; i < amt * 1; i++) { + this.addSpline(1, 0, 0, (Math.PI * 2 / amt) * (1), "Full Spiral Mid", "modRingD64R128", this.textureArrays.fullColor[3]); + } + for (let i = 0; i < amt * 1; i++) { + this.addSpline(1, 0, 0, (Math.PI * 2 / amt) * (1 - (i / amt)), "Full Spiral Out", "modRingD64R128", this.textureArrays.fullColor[3]); + } + */ + /* + //180 roll + for (let i = 0; i < amt * 1; i++) { + ar = (Math.PI * 2 / amt) * (i * 0.5 / amt); + this.addSpline(1, 0, 0, ar, "Back straight", "modRingD64R128", this.textureArrays.fullColor[3]); + } + for (let i = 0; i < amt * 1; i++) { + ar = (Math.PI * 2 / amt) * (0.5 - (i * 0.5 / amt)); + this.addSpline(1, 0, 0, ar, "Back straight", "modRingD64R128", this.textureArrays.fullColor[3]); + } + */ + + this.addSpline(40, 0, -Math.PI / 80, 0, "Curve", "modRingD64R128", this.textureArrays.fullColor[4]); + + //90 deg roll left + for (let i = 0; i < amt * 1; i++) { + ar = (Math.PI * 2 / amt) * (i * 0.25 / amt); + this.addSpline(1, 0, 0, ar, "Roll", "modRingD64R128", this.textureArrays.fullColor[3]); + } + for (let i = 0; i < amt * 1; i++) { + ar = (Math.PI * 2 / amt) * (0.25 - (i * 0.25 / amt)); + this.addSpline(1, 0, 0, ar, "Roll", "modRingD64R128", this.textureArrays.fullColor[3]); + } + + this.addSpline(40, 0, -Math.PI / 80, 0, "Curve", "modRingD64R128", this.textureArrays.fullColor[4]); + + //180 roll r + for (let i = 0; i < amt * 1; i++) { + ar = (Math.PI * 2 / amt) * (i * 0.5 / amt); + this.addSpline(1, 0, 0, -ar, "Roll", "modRingD64R128", this.textureArrays.fullColor[3]); + } + for (let i = 0; i < amt * 1; i++) { + ar = (Math.PI * 2 / amt) * (0.5 - (i * 0.5 / amt)); + this.addSpline(1, 0, 0, -ar, "Roll", "modRingD64R128", this.textureArrays.fullColor[3]); + } + + this.addSpline(80, 0, -Math.PI / 80, 0, "Curve", "modRingD64R128", this.textureArrays.fullColor[4]); + + //side straight + this.addSpline(51, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.fullColor[3]); + + //90 deg roll right + for (let i = 0; i < amt * 1; i++) { + ar = (Math.PI * 2 / amt) * (i * 0.25 / amt); + this.addSpline(1, 0, 0, -ar, "Roll", "modRingD64R128", this.textureArrays.fullColor[3]); + } + for (let i = 0; i < amt * 1; i++) { + ar = (Math.PI * 2 / amt) * (0.25 - (i * 0.25 / amt)); + this.addSpline(1, 0, 0, -ar, "Roll", "modRingD64R128", this.textureArrays.fullColor[3]); + } + + this.addSpline(40, 0, -Math.PI / 80, 0, "Curve", "modRingD64R128", this.textureArrays.fullColor[4]); + + this.addSpline(40, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.fullColor[3]); + + this.addSpline(40, 0, -Math.PI / 80, 0, "Curve", "modRingD64R128", this.textureArrays.fullColor[4]); + + //90 deg roll right + for (let i = 0; i < amt * 1; i++) { + ar = (Math.PI * 2 / amt) * (i * 0.25 / amt); + this.addSpline(1, 0, 0, ar, "Roll", "modRingD64R128", this.textureArrays.fullColor[3]); + } + for (let i = 0; i < amt * 1; i++) { + ar = (Math.PI * 2 / amt) * (0.25 - (i * 0.25 / amt)); + this.addSpline(1, 0, 0, ar, "Roll", "modRingD64R128", this.textureArrays.fullColor[3]); + } + + this.addSpline(40, 0, -Math.PI / 80, 0, "Curve", "modRingD64R128", this.textureArrays.fullColor[4]); + + //down straight + this.addSpline(91, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.fullColor[3]); + + this.addSpline(40, 0, -Math.PI / 80, 0, "Curve", "modRingD64R128", this.textureArrays.fullColor[4]); + + //90 deg roll + for (let i = 0; i < amt * 1; i++) { + ar = (Math.PI * 2 / amt) * (i * 0.25 / amt); + this.addSpline(1, 0, 0, -ar, "Roll", "modRingD64R128", this.textureArrays.fullColor[3]); + } + for (let i = 0; i < amt * 1; i++) { + ar = (Math.PI * 2 / amt) * (0.25 - (i * 0.25 / amt)); + this.addSpline(1, 0, 0, -ar, "Roll", "modRingD64R128", this.textureArrays.fullColor[3]); + } + + this.addSpline(40, 0, -Math.PI / 80, 0, "Curve", "modRingD64R128", this.textureArrays.fullColor[4]); + + //back straight + //this.addSpline(171, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.fullColor[3]); + //this.addSpline(30, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.fullColor[3]); + // //90 deg roll left + for (let i = 0; i < amt * 1; i++) { + ar = (Math.PI * 2 / amt) * (i * 0.25 / amt); + this.addSpline(1, 0, 0, -ar, "Roll", "modRingD64R128", this.textureArrays.fullColor[3]); + } + for (let i = 0; i < amt * 1; i++) { + ar = (Math.PI * 2 / amt) * (0.25 - (i * 0.25 / amt)); + this.addSpline(1, 0, 0, -ar, "Roll", "modRingD64R128", this.textureArrays.fullColor[3]); + } + + this.addSpline(20, Math.PI / 80, 0, 0, "Straight", "modRingD64R128", this.textureArrays.fullColor[3]); + this.addSpline(20, -Math.PI / 80, 0, 0, "Straight", "modRingD64R128", this.textureArrays.fullColor[3]); + + this.addSpline(41, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.fullColor[3]); + + this.addSpline(20, -Math.PI / 80, 0, 0, "Straight", "modRingD64R128", this.textureArrays.fullColor[3]); + this.addSpline(20, Math.PI / 80, 0, 0, "Straight", "modRingD64R128", this.textureArrays.fullColor[3]); + + //this.addSpline(30, 0, 0, 0, "Straight", "modRingD64R128", this.textureArrays.fullColor[3]); + for (let i = 0; i < amt * 1; i++) { + ar = (Math.PI * 2 / amt) * (i * 0.25 / amt); + this.addSpline(1, 0, 0, ar, "Roll", "modRingD64R128", this.textureArrays.fullColor[3]); + } + for (let i = 0; i < amt * 1; i++) { + ar = (Math.PI * 2 / amt) * (0.25 - (i * 0.25 / amt)); + this.addSpline(1, 0, 0, ar, "Roll", "modRingD64R128", this.textureArrays.fullColor[3]); + } + + this.addSpline(40, 0, -Math.PI / 80, 0, "Curve", "modRingD64R128", this.textureArrays.fullColor[4]); + + this.addSpline(40, 0, -Math.PI / 80, 0, "Curve", "modRingD64R128", this.textureArrays.fullColor[4]); + + //90 deg roll left + for (let i = 0; i < amt * 1; i++) { + ar = (Math.PI * 2 / amt) * (i * 0.25 / amt); + this.addSpline(1, 0, 0, ar, "Roll", "modRingD64R128", this.textureArrays.fullColor[3]); + } + for (let i = 0; i < amt * 1; i++) { + ar = (Math.PI * 2 / amt) * (0.25 - (i * 0.25 / amt)); + this.addSpline(1, 0, 0, ar, "Roll", "modRingD64R128", this.textureArrays.fullColor[3]); + } + + this.addSpline(23, 0, 0, 0, "Curve", "modRingD64R128", this.textureArrays.fullColor[4]); + + + + obstSpots = []; + //this.spline[this.spline.length - 1].stitch = false; + break; + case 9999: + for (let i = 0; i < 32; i++) { + this.addSpline(7, (Math.PI * 2) / 320, 0, 0, "Bendyway", "modRingD64R128", this.textureArrays.atom[2], true); + this.addSpline(1, (Math.PI * 2) / 320, 0, 0, "Bendyway", "modRingD64R128", this.textureArrays.atomRing[2], true); + this.addSpline(1, (Math.PI * 2) / 320, 0, 0, "Bendyway", "modRingD64R128", this.textureArrays.atomRing[3], true); + this.addSpline(1, (Math.PI * 2) / 320, 0, 0, "Bendyway", "modRingD64R128", this.textureArrays.atomRing[2], true); + } + /* + for(let j = 0 ; j < 16 ; j++){ + for(let i = 0 ; i < 7 ; i++){ + this.addSpline(1, (Math.PI * 2) / 160, 0, 0, "Sewer Room 01", "modRingD64R128AtomRoom", this.textureArrays.atom[0], true ); + } + this.addSpline(1, (Math.PI * 2) / 160, 0, 0, "Sewer Room 01", "modRingD64R128AtomRoom01", this.textureArrays.atomRing[0], true ); + this.addSpline(1, (Math.PI * 2) / 160, 0, 0, "Sewer Room 01", "modRingD64R128AtomRoom", this.textureArrays.atomRing[1], true ); + this.addSpline(1, (Math.PI * 2) / 160, 0, 0, "Sewer Room 01", "modRingD64R128AtomRoom02", this.textureArrays.atomRing[0], true ); + } + */ + obstSpots = []; + break; + default: + ty = 0; + tp = 0; + tr = 0; + + this.createStartTunnel(); + + this.spline[this.spline.length - 1].stitch = false; + + obstSpots = []; + break; + } + + //move and rotate spline points via the ref that follows their directions + this.ref.jumpToPosition(this.spline[0]); + this.ref.data = { + trackedDir: { yaw: 0, pitch: 0, roll: 0 } + } + for (let [i, sp] of this.spline.entries()) { + //rotate ref to new direction and jump it forward + this.ref.jumpToPosition({ + x: this.ref.pos.x + (this.ref.transform.forward.x * this.ringDeepness) + (sp.transform.right.x * sp.offset.right) + (sp.transform.up.x * sp.offset.up) + (sp.transform.forward.x * sp.offset.forward), + y: this.ref.pos.y + (this.ref.transform.forward.y * this.ringDeepness) + (sp.transform.right.y * sp.offset.right) + (sp.transform.up.y * sp.offset.up) + (sp.transform.forward.y * sp.offset.forward), + z: this.ref.pos.z + (this.ref.transform.forward.z * this.ringDeepness) + (sp.transform.right.z * sp.offset.right) + (sp.transform.up.z * sp.offset.up) + (sp.transform.forward.z * sp.offset.forward), + }); + this.ref.rotateAroundAxis([this.ref.transform.up.x, this.ref.transform.up.y, this.ref.transform.up.z], sp.toYaw) + this.ref.rotateAroundAxis([this.ref.transform.right.x, this.ref.transform.right.y, this.ref.transform.right.z], sp.toPitch) + this.ref.rotateAroundAxis([this.ref.transform.forward.x, this.ref.transform.forward.y, this.ref.transform.forward.z], sp.toRoll) + + //this.ref.transform.forward = gl_vec3.normalize(this.ref.transform.forward, this.ref.transform.forward); + //this.ref.transform.right = gl_vec3.normalize(this.ref.transform.right, this.ref.transform.right); + //this.ref.transform.up = gl_vec3.normalize(this.ref.transform.up, this.ref.transform.up); + + this.ref.data.trackedDir.yaw += sp.toYaw; + if (this.ref.data.trackedDir.yaw > Math.PI) { this.ref.data.trackedDir.yaw -= Math.PI } + if (this.ref.data.trackedDir.yaw < Math.PI * -1) { this.ref.data.trackedDir.yaw += Math.PI } + this.ref.data.trackedDir.pitch += sp.toPitch; + if (this.ref.data.trackedDir.pitch > Math.PI) { this.ref.data.trackedDir.pitch -= Math.PI } + if (this.ref.data.trackedDir.pitch < Math.PI * -1) { this.ref.data.trackedDir.pitch += Math.PI } + this.ref.data.trackedDir.roll += sp.toRoll; + if (this.ref.data.trackedDir.roll > Math.PI) { this.ref.data.trackedDir.roll -= Math.PI } + if (this.ref.data.trackedDir.roll < Math.PI * -1) { this.ref.data.trackedDir.roll += Math.PI } + //console.log(this.ref.transform.rotationQuat) + //console.log(this.ref.data.trackedDir.yaw) + + sp.x = this.ref.pos.x; + sp.y = this.ref.pos.y; + sp.z = this.ref.pos.z; + sp.transform.rotationQuat = [this.ref.transform.rotationQuat[0], this.ref.transform.rotationQuat[1], this.ref.transform.rotationQuat[2], this.ref.transform.rotationQuat[3]] + sp.transform.up = { x: this.ref.transform.up.x, y: this.ref.transform.up.y, z: this.ref.transform.up.z } + sp.transform.right = { x: this.ref.transform.right.x, y: this.ref.transform.right.y, z: this.ref.transform.right.z } + sp.transform.forward = { x: this.ref.transform.forward.x, y: this.ref.transform.forward.y, z: this.ref.transform.forward.z } + sp.yaw = this.ref.data.trackedDir.yaw; + sp.pitch = this.ref.data.trackedDir.pitch; + sp.roll = this.ref.data.trackedDir.roll; + + //INFO immediately do it this is new INFO + if (sp.modelFile !== null && _dataOnly === false) { + sp.model = this.addRingFromModel(sp.modelFile, sp.textureArray, sp.stitch); + + let ring = this.rings[this.rings.length - 1]; + ring.jumpToPosition({ x: sp.x, y: sp.y, z: sp.z }); + ring.data.id = sp.id; + //todo: this might be insane for long tracks I feel - maybe the track builder can do smth in one also it needs to be able to go with larger station models in between + //for(let j = 0 ; j < i ; j++){ + /*ring.rotateAroundAxis([ring.transform.up.x, ring.transform.up.y, ring.transform.up.z], sp.yaw); + ring.rotateAroundAxis([ring.transform.right.x, ring.transform.right.y, ring.transform.right.z], sp.pitch); + ring.rotateAroundAxis([ring.transform.forward.x, ring.transform.forward.y, ring.transform.forward.z], sp.roll); */ + //} + + //quat rot in XYZ + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + ring.transform.toVectorArray(ring.transform.right), + ring.transform.toVectorArray(sp.transform.right) + ) + ring.rotateByQuaternion(targetRot); + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + ring.transform.toVectorArray(ring.transform.up), + ring.transform.toVectorArray(sp.transform.up) + ) + ring.rotateByQuaternion(targetRot); + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + ring.transform.toVectorArray(ring.transform.forward), + ring.transform.toVectorArray(sp.transform.forward) + ) + ring.rotateByQuaternion(targetRot); + //not a fix + //ring.rotateAroundAxis([ring.transform.forward.x, ring.transform.forward.y, ring.transform.forward.z], sp.roll); + + } + } + + //console.log(this.spline) + + /*//todo: this is the old one + this.rings = []; + for(let [i, sp] of this.spline.entries()){ + if(sp.modelFile !== null){ + sp.model = this.addRingFromModel(sp.modelFile, sp.textureArray, sp.stitch); + + let ring = this.rings[this.rings.length - 1]; + ring.jumpToPosition({x: sp.x, y: sp.y, z: sp.z}); + //todo: this might be insane for long tracks I feel - maybe the track builder can do smth in one also it needs to be able to go with larger station models in between + for(let j = 0 ; j < i ; j++){ + ring.rotateAroundAxis([ring.transform.up.x, ring.transform.up.y, ring.transform.up.z], this.spline[j].toYaw); + ring.rotateAroundAxis([ring.transform.right.x, ring.transform.right.y, ring.transform.right.z], this.spline[j].toPitch); + ring.rotateAroundAxis([ring.transform.forward.x, ring.transform.forward.y, ring.transform.forward.z], this.spline[j].toRoll); + } + /* + //new method //todo: sometimes fails when rotation is perfect mirror? + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + ring.transform.toVectorArray( ring.transform.forward), + ring.transform.toVectorArray( sp.transform.forward) + ) + ring.rotateByQuaternion(targetRot); + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + ring.transform.toVectorArray( ring.transform.right), + ring.transform.toVectorArray( sp.transform.right) + ) + ring.rotateByQuaternion(targetRot); + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + ring.transform.toVectorArray( ring.transform.up), + ring.transform.toVectorArray( sp.transform.up) + ) + ring.rotateByQuaternion(targetRot); + //not a fix + //ring.rotateAroundAxis([ring.transform.forward.x, ring.transform.forward.y, ring.transform.forward.z], sp.roll); + //prev end of multiline + } + } + */ + + //stitch rings together + for (let i = 0; i < this.spline.length - 1; i += 1) { + let myr = this.spline[i].model; + if (myr !== null) { + let nxr = this.spline[i + 1].model; + for (let j = 0; j < myr.quadData.length; j += 1) { + if (myr.data.stitch === true) { + if (nxr.quadData[j] !== undefined) { + myr.quadData[j].points[3].x = nxr.quadData[j].points[0].x + (nxr.quadData[j].pos.x) - (myr.pos.x); + myr.quadData[j].points[3].y = nxr.quadData[j].points[0].y + (nxr.quadData[j].pos.y) - (myr.pos.y); + myr.quadData[j].points[3].z = nxr.quadData[j].points[0].z + (nxr.quadData[j].pos.z) - (myr.pos.z); + + myr.quadData[j].points[2].x = nxr.quadData[j].points[1].x + (nxr.quadData[j].pos.x) - (myr.pos.x); + myr.quadData[j].points[2].y = nxr.quadData[j].points[1].y + (nxr.quadData[j].pos.y) - (myr.pos.y); + myr.quadData[j].points[2].z = nxr.quadData[j].points[1].z + (nxr.quadData[j].pos.z) - (myr.pos.z); + } + } + } + } + } + let myr = this.spline[this.spline.length - 1].model; + let nxr = this.spline[0].model; + if (myr !== null) { + if (myr.data.stitch === true) { + for (let j = 0; j < myr.quadData.length; j += 1) { + if (nxr.quadData[j] !== undefined) { + myr.quadData[j].points[3].x = nxr.quadData[j].points[0].x + (nxr.quadData[j].pos.x) - (myr.pos.x); + myr.quadData[j].points[3].y = nxr.quadData[j].points[0].y + (nxr.quadData[j].pos.y) - (myr.pos.y); + myr.quadData[j].points[3].z = nxr.quadData[j].points[0].z + (nxr.quadData[j].pos.z) - (myr.pos.z); + + myr.quadData[j].points[2].x = nxr.quadData[j].points[1].x + (nxr.quadData[j].pos.x) - (myr.pos.x); + myr.quadData[j].points[2].y = nxr.quadData[j].points[1].y + (nxr.quadData[j].pos.y) - (myr.pos.y); + myr.quadData[j].points[2].z = nxr.quadData[j].points[1].z + (nxr.quadData[j].pos.z) - (myr.pos.z); + } + } + } + } + + if(_dataOnly === false){ + this.createObstacles(_id, obstSpots); + } + + //console.log(this.spline) + } + + createObstacles(_id, _obstSpots) { + //add obstacles + for (let os of _obstSpots) { + this.obstacles.push(this.scene.geometryController.loadModel(os.name, os.model, { x: 0, y: 0, z: 0 })); + let o = this.obstacles[this.obstacles.length - 1]; + if (os.angle >= Math.PI * 1) { + os.angle -= Math.PI * 2; + } + if (os.angle < Math.PI * -1) { + os.angle += Math.PI * 2; + } + + o.data = { + id: os.sp.id, + roll: 0,//undefined, + angle: os.angle, + anim: 0, + collisionRadar: { + ignore: false, + offset: 0, + additionals: [] + }, + ignoreCollision: false, + ignoreRadar: false + } + o.flags.draw = true; + o.jumpToPosition({ x: os.sp.x, y: os.sp.y, z: os.sp.z }); + //quat rot in XYZ + let targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + o.transform.toVectorArray(o.transform.right), + o.transform.toVectorArray(os.sp.transform.right) + ) + o.rotateByQuaternion(targetRot); + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + o.transform.toVectorArray(o.transform.up), + o.transform.toVectorArray(os.sp.transform.up) + ) + o.rotateByQuaternion(targetRot); + targetRot = [0, 0, 0, 0]; + targetRot = gl_quat.rotationTo(targetRot, + o.transform.toVectorArray(o.transform.forward), + o.transform.toVectorArray(os.sp.transform.forward) + ) + o.rotateByQuaternion(targetRot); + o.rotateAroundAxis(o.transform.toVectorArray(o.transform.forward), os.angle); + o.jumpToPosition({ x: o.pos.x + o.transform.up.x * -os.radius, y: o.pos.y + o.transform.up.y * -os.radius, z: o.pos.z + o.transform.up.z * -os.radius }); + } + + //late update for obstacles per track id + switch (_id) { + case 0://METRO LOOP + //set up all blades to rotate + for (let i = 0; i < 6; i++) { + let o = this.obstacles[i]; + //console.log(i + ", " + (i % 6 >= 3 ? 1 : -1) ) + o.data.roll += ((Math.PI * 0.015) * (i % 6 >= 3 ? 1 : -1)) * this.scene.dt; + o.customUpdate = () => { + let turnSpeed = ((Math.PI * 0.015) * (i % 6 >= 3 ? 1 : -1)) * this.scene.dt; + o.rotateAroundAxis(o.transform.toVectorArray(o.transform.forward), turnSpeed); + o.data.roll += turnSpeed; + //use this for obstacle turn throughs + if (o.data.roll >= Math.PI) { + o.data.roll -= Math.PI * 2; + } + if (o.data.roll < Math.PI * -1) { + o.data.roll += Math.PI * 2; + } + } + } + //lightblade + this.obstacles[6].data.collisionRadar.offset += 4; + this.obstacles[6].data.collisionRadar.additionals = [8];//[-1, 7,8]; + //doors + this.obstacles[7].data.collisionRadar.additionals = [-3, -2, -1, 1, 2, 3, 4]; + this.obstacles[8].data.collisionRadar.additionals = [-2, -1, 1, 2, 3]; + this.obstacles[9].data.collisionRadar.additionals = [-2, -1, 1, 2, 3]; + this.obstacles[10].data.collisionRadar.additionals = [-3, -2, -1, 1, 2, 3, 4]; + this.obstacles[11].data.collisionRadar.additionals = [-3, -2, -1, 1, 2, 3, 4]; + //steam + for (let i = 0; i < 4; i++) { + this.obstacles[12 + i].data.roll = 0; + this.obstacles[12 + i].data.anim = 0; + this.obstacles[12 + i].trigger.isTrigger = true; + this.obstacles[12 + i].customUpdate = () => { + this.obstacles[12 + i].data.anim += 0.1 * this.scene.dt; + if (this.obstacles[12 + i].data.anim >= 1) { + this.obstacles[12 + i].data.anim = 0; + let rn = Math.floor(Math.random() * 6); + for (let q of this.obstacles[12 + i].quadData) { + q.setTexture(q.texture, q.frame.substr(0, 12) + String(rn), true); + q.clearQuads(); + q.createQuad(); + } + } + } + this.obstacles[12 + i].updateTrigger = () => { + //this.level.shipSpeed *= 0.95; + //this.level.playerShip.flightRadius -= (1 * (this.level.playerShip.speed * 0.25)) * this.scene.dt; + this.obstacles[12 + i].trigger.other.shipSpeed *= 0.95; + this.obstacles[12 + i].trigger.other.flightRadius -= (1 * (this.level.playerShip.speed * 0.25)) * this.scene.dt; + } + } + + //ventdoor + this.updateModelWithTextureArray(this.obstacles[11], this.textureArrays.ventDoor[1]); + break; + case 1://ATOMIC SEWERS + //rotate atom warning + this.obstacles[0].trigger.isTrigger = true; + this.obstacles[0].customUpdate = () => { + + this.obstacles[0].rotateAroundAxis(this.obstacles[0].transform.toVectorArray(this.obstacles[0].transform.forward), (Math.PI * 0.005)); + this.obstacles[0].data.roll += (Math.PI * 0.005) * this.scene.dt; + //use this for obstacle turn throughs + if (this.obstacles[0].data.roll >= Math.PI) { + this.obstacles[0].data.roll -= Math.PI * 2; + } + if (this.obstacles[0].data.roll < Math.PI * -1) { + this.obstacles[0].data.roll += Math.PI * 2; + } + + } + + //set blades to hold core pipe + for (let i = 1; i < 9; i += 1) { + if (i % 2 === 0) { + this.updateModelWithTextureArray(this.obstacles[i], this.textureArrays.metroBlade[1]); + this.obstacles[i].jumpToPosition({ + x: this.obstacles[i].pos.x + (this.obstacles[i].transform.right.x * 96), + y: this.obstacles[i].pos.y + (this.obstacles[i].transform.right.y * 96), + z: this.obstacles[i].pos.z + (this.obstacles[i].transform.right.z * 96) + }); + this.obstacles[i].data.collisionRadar.offset = -4; + } else { + this.obstacles[i].data.collisionRadar.additionals = [-1, 1, 2]; + } + } + this.obstacles[5].data.collisionRadar.additionals = [-1]; + this.obstacles[7].data.collisionRadar.additionals = [-1, 1]; + break; + case 2://CONSTRUCTION + break; + case 3://PIPELINE + this.obstacles[0].data.collisionRadar.additionals = [-1, 1, 2]; + this.obstacles[1].data.collisionRadar.additionals = [-1, 1, 2]; + this.obstacles[2].data.collisionRadar.additionals = [-1, 1, 2]; + this.obstacles[3].data.collisionRadar.additionals = [-1, 1, 2]; + this.obstacles[4].data.collisionRadar.additionals = [-1, 1, 2]; + //set blades to hold core pipe + for (let i = 5; i < 9; i += 1) { + this.updateModelWithTextureArray(this.obstacles[i], this.textureArrays.metroBlade[1]); + this.obstacles[i].jumpToPosition({ + x: this.obstacles[i].pos.x + (this.obstacles[i].transform.right.x * 96), + y: this.obstacles[i].pos.y + (this.obstacles[i].transform.right.y * 96), + z: this.obstacles[i].pos.z + (this.obstacles[i].transform.right.z * 96) + }); + this.obstacles[i].data.collisionRadar.offset = -4; + } + break; + case 4: + //set up all blades to rotate + for (let i = 0; i < 12; i++) { + let o = this.obstacles[i]; + //console.log(i + ", " + (i % 6 >= 3 ? 1 : -1) ) + o.data.roll += ((Math.PI * 0.015) * (i % 6 >= 3 ? 1 : -1)) * this.scene.dt; + o.customUpdate = () => { + let turnSpeed = ((Math.PI * 0.015) * (i % 6 >= 3 ? 1 : -1)) * this.scene.dt; + o.rotateAroundAxis(o.transform.toVectorArray(o.transform.forward), turnSpeed); + o.data.roll += turnSpeed; + //use this for obstacle turn throughs + if (o.data.roll >= Math.PI) { + o.data.roll -= Math.PI * 2; + } + if (o.data.roll < Math.PI * -1) { + o.data.roll += Math.PI * 2; + } + } + } + //first blade + this.obstacles[12].data.collisionRadar.offset += 5; + this.obstacles[12].data.collisionRadar.additionals = [8];//[-1, 7,8]; + + //this.obstacles[13].data.collisionRadar.additionals = [-3, -2, -1, 1, 2, 3, 4]; //half + this.obstacles[13].data.collisionRadar.additionals = [-1, 1, 2]; + this.obstacles[14].data.collisionRadar.additionals = [-2, -1, 1, 2, 3]; + this.obstacles[15].data.collisionRadar.additionals = [-2, -1, 1, 2, 3]; + this.obstacles[16].data.collisionRadar.additionals = [-1, 1, 2]; + this.obstacles[17].data.collisionRadar.additionals = [-1, 1, 2]; + this.obstacles[18].data.collisionRadar.additionals = [-2, -1, 1, 2, 3]; + + this.obstacles[19].data.collisionRadar.additionals = [-3, -2, -1, 1, 2, 3, 4]; + this.obstacles[20].data.collisionRadar.additionals = [-3, -2, -1, 1, 2, 3, 4]; + break; + default: + break; + } + + //console.log(this.obstacles) + } + + createStartTunnel() { + this.addSpline(1, 0, 0, (Math.PI * 0.25) * 0, "Start - Box 0", "modRingD256HangarLift", null, false); + this.addSpline(3, 0, 0, 0, "Start - Box 0", null, null, false); + this.addSpline(1, 0, 0, 0, "Start - Finish", "modRingD64R128", this.textureArrays.darkMetalRing[0], false); + this.addSpline(1, 0, 0, (Math.PI * 0.25) * 1, "Start - Box 1", "modRingD256HangarLift", null, false); + this.addSpline(3, 0, 0, 0, "Start - Box 1", null, null, false); + this.addSpline(1, 0, 0, 0, "Start - Finish", "modRingD64R128", this.textureArrays.darkMetalRing[0], false); + this.addSpline(1, 0, 0, (Math.PI * 0.25) * 1, "Start - Box 2", "modRingD256HangarLift", null, false); + this.addSpline(3, 0, 0, 0, "Start - Box 2", null, null, false); + this.addSpline(1, 0, 0, 0, "Start - Finish", "modRingD64R128", this.textureArrays.darkMetalRing[0], false); + this.addSpline(1, 0, 0, (Math.PI * 0.25) * 1, "Start - Box 3", "modRingD256HangarLift", null, false); + this.addSpline(3, 0, 0, 0, "Start - Box 3", null, null, false); + this.addSpline(1, 0, 0, 0, "Start - Finish", "modRingD64R128", this.textureArrays.darkMetalRing[0], false); + this.addSpline(1, 0, 0, (Math.PI * 0.25) * 1, "Start - Box 4", "modRingD256HangarLift", null, false); + this.addSpline(3, 0, 0, 0, "Start - Box 4", null, null, false); + this.addSpline(1, 0, 0, 0, "Start - Finish", "modRingD64R128", this.textureArrays.darkMetalRing[0], false); + this.addSpline(1, 0, 0, (Math.PI * 0.25) * 1, "Start - Box 5", "modRingD256HangarLift", null, false); + this.addSpline(3, 0, 0, 0, "Start - Box 5", null, null, false); + this.addSpline(1, 0, 0, 0, "Start - Finish", "modRingD64R128", this.textureArrays.darkMetalRing[0], false); + this.addSpline(1, 0, 0, (Math.PI * 0.25) * 1, "Start - Box 6", "modRingD256HangarLift", null, false); + this.addSpline(3, 0, 0, 0, "Start - Box 6", null, null, false); + this.addSpline(1, 0, 0, 0, "Start - Finish", "modRingD64R128", this.textureArrays.darkMetalRing[0], false); + this.addSpline(1, 0, 0, (Math.PI * 0.25) * 1, "Start - Box 7", "modRingD256HangarLift", null, false); + this.addSpline(3, 0, 0, 0, "Start - Box 7", null, null, false); + + this.addSpline(1, 0, 0, (Math.PI * 0.25) * -7, "Start - Finish", "modRingD64R128", this.textureArrays.darkMetalRing[0], true); + this.addSpline(1, 0, 0, 0, "Start - Finish", "modRingD64R128", this.textureArrays.startFinish[0], true); + this.addSpline(1, 0, 0, 0, "Start - Finish", "modRingD64R128", this.textureArrays.startFinish[1], true); + this.addSpline(1, 0, 0, 0, "Start - Finish", "modRingD64R128", this.textureArrays.startFinish[0], true); + this.addSpline(1, 0, 0, 0, "Start - Finish", "modRingD64R128", this.textureArrays.darkMetalRing[0], true); + //console.log(this.spline.length) length = 44 + } + + addSpline(_len, _ty, _tp, _tr, _name, _modelFile, _textureArray, _stitch = true, _offset = { right: 0, up: 0, forward: 0 }) { + for (let i = 0; i < _len; i++) { + this.spline.push({ + name: _name, + id: -1, + x: 0, y: 0, z: 0, + toYaw: _ty, toPitch: _tp, toRoll: _tr, + yaw: 0, pitch: 0, roll: 0, + transform: new Transform(), + modelFile: _modelFile, + textureArray: _textureArray, + stitch: i < _len - 1 ? true : _stitch, + offset: { + right: _offset.right, + up: _offset.up, + forward: _offset.forward + }, + obstacles: [], + model: null + }); + this.spline[this.spline.length - 1].id = this.spline.length - 1; + } + } + + + addRingFromModel(_modelFile, _textureArray, _stitch) { + let ring = this.scene.geometryController.loadModel("ring no " + String(this.rings.length), _modelFile, { x: 0, y: 0, z: 0 }); + //ring.flags.draw = true; + ring.data = { + id: -1, + stitch: _stitch + } + + if (_textureArray !== null) { + let texArr = JSON.parse(JSON.stringify(_textureArray)); + //randomize garden textures + if (_textureArray == this.textureArrays.garden[0]) { + for (let t of texArr) { + if (t.frame === "texBush01") { + let appendix = ""; + let r = Math.floor(Math.random() * 3) + if (r === 1) { appendix = "shrub" } + if (r === 2) { appendix = "fruit" } + r = Math.floor(Math.random() * 3) + 1; + let newFrame = "texBush0" + String(r) + appendix; + t.frame = newFrame; + } + } + } + + for (let [i, t] of texArr.entries()) { + ring.quadData[i].setTexture(t.texture, t.frame); + } + } else { + //special rings and models + //randomize adverts in metro stations + if (_modelFile === "modRingD512MetroStationStart" || _modelFile === "modRingD512MetroStationEnd" || _modelFile === "modRingD512MetroStation") { + //let possible = ["advFormula", "advNutricubes", "advSerpentiles"]; + let possible = ["advFoxxy", "advHog", "advWakeUp01", "advKronos", "advTrimond", "advSerpentiles", "advNutricubes", "advFormula", "advCyclotron"]; + let r = possible[Math.floor(Math.random() * possible.length)]; + for (let [i, q] of ring.quadData.entries()) { + if (q.frame.substr(0, 10) === "advFormula") { + let newframe = r + q.frame.substr(10, 2); + q.setTexture(q.texture, newframe); + } + } + } + } + this.rings.push(ring); + return ring; + } + + updateModelWithTextureArray(_model, _textureArray) { + for (let [i, t] of _textureArray.entries()) { + _model.quadData[i].setTexture(t.texture, t.frame); + } + } +} diff --git a/src/3d/transform.js b/src/3d/transform.js new file mode 100644 index 0000000..893880b --- /dev/null +++ b/src/3d/transform.js @@ -0,0 +1,126 @@ +export default class Transform { + constructor(){ + this.forward = { + x: 0, + y: 0, + z: 1 + } + this.right = { + x: 1, + y: 0, + z: 0 + } + this.up = { + x: 0, + y: -1, + z: 0 + } + this.prev = { + forward: { + x: 0, + y: 0, + z: 1 + }, + right: { + x: 1, + y: 0, + z: 0 + }, + up: { + x: 0, + y: -1, + z: 0 + } + } + + this.dir = { + yaw: 0, + pitch: 0, + roll: 0 + } + + + this.pos = { + x: 0, + y: 0, + z: 0 + }, + this.rotationQuat = gl_quat.create(); + this.axisQuat = gl_quat.create(); + } + + resetRotationQuat(){ + this.rotationQuat = gl_quat.create(); + } + + normalizeRotationQuat(){ + let newQuat = [0, 0, 0, 1]; + this.rotationQuat = gl_rvaa.AIOvec4normalize(newQuat, this.rotationQuat); + } + + calculateAxisQuat(){ + + } + + toVectorArray(_obj){ + let returnArr = []; + if(_obj.yaw === undefined){ + returnArr = [ _obj.x, _obj.y, _obj.z ] + }else{ + returnArr = [ _obj.pitch, _obj.yaw, _obj.roll ] + } + return returnArr; + } + + saveCurrentAxisToPrev(){ + this.prev.forward.x = this.forward.x; + this.prev.forward.y = this.forward.y; + this.prev.forward.z = this.forward.z; + + this.prev.right.x = this.right.x; + this.prev.right.y = this.right.y; + this.prev.right.z = this.right.z; + + this.prev.up.x = this.up.x; + this.prev.up.y = this.up.y; + this.prev.up.z = this.up.z; + } + + calculateHand(){ + + + + //this.calculateForward(); + //this.calculateRight(); + //this.calculateUp(); + } + + calculateForward(){ + this.forward.x = Math.cos(this.dir.pitch) * Math.sin(this.dir.yaw); + this.forward.y = -Math.sin(this.dir.pitch); + this.forward.z = Math.cos(this.dir.pitch) * Math.cos(this.dir.yaw); + } + + calculateRight(_ref = {x: 0, y: -1, z: 0}){ + /*let outXYZ = rti.cross([0, 0, 0], [this.forward.x, this.forward.y, this.forward.z], [_ref.x, _ref.y, _ref.z]); + this.right.x = outXYZ[0]; + this.right.y = outXYZ[1]; + this.right.z = outXYZ[2];*/ + + /*this.right.x = Math.cos(this.dir.yaw); + this.right.y = 0; + this.right.z = -Math.sin(this.dir.yaw);*/ + + this.right.x = Math.sin(this.dir.roll)*Math.sin(this.dir.pitch)*Math.sin(this.dir.yaw) + Math.cos(this.dir.roll)*Math.cos(this.dir.yaw) + this.right.y = Math.cos(this.dir.pitch)*Math.sin(this.dir.roll) + this.right.z = Math.sin(this.dir.roll)*Math.sin(this.dir.pitch)*Math.cos(this.dir.yaw) - Math.cos(this.dir.roll)*Math.sin(this.dir.yaw) + + } + + calculateUp(){ + let outXYZ = rti.cross([0, 0, 0], [this.right.x, this.right.y, this.right.z], [this.forward.x, this.forward.y, this.forward.z]); + this.up.x = outXYZ[0]; + this.up.y = outXYZ[1]; + this.up.z = outXYZ[2]; + } +} \ No newline at end of file diff --git a/src/additionalMath/euclidianDistance.js b/src/additionalMath/euclidianDistance.js new file mode 100755 index 0000000..00f7dfb --- /dev/null +++ b/src/additionalMath/euclidianDistance.js @@ -0,0 +1,18 @@ +export default class EuclidianDistance{ + constructor(){ + + } + + squared(a, b){ + var sum = 0 + var n + for (n = 0; n < a.length; n++) { + sum += Math.pow(a[n] - b[n], 2) + } + return sum; + } + + distance(a, b){ + return Math.sqrt(this.squared(a, b)); + } +} \ No newline at end of file diff --git a/src/additionalMath/gl_mat3.js b/src/additionalMath/gl_mat3.js new file mode 100644 index 0000000..3c363d9 --- /dev/null +++ b/src/additionalMath/gl_mat3.js @@ -0,0 +1,496 @@ +export default class GL_Mat3{ + constructor(){ + + } + + adjoint(out, a) { + /** + * Calculates the adjugate of a mat3 + * + * @alias mat3.adjoint + * @param {mat3} out the receiving matrix + * @param {mat3} a the source matrix + * @returns {mat3} out + */ + var a00 = a[0], a01 = a[1], a02 = a[2] + var a10 = a[3], a11 = a[4], a12 = a[5] + var a20 = a[6], a21 = a[7], a22 = a[8] + + out[0] = (a11 * a22 - a12 * a21) + out[1] = (a02 * a21 - a01 * a22) + out[2] = (a01 * a12 - a02 * a11) + out[3] = (a12 * a20 - a10 * a22) + out[4] = (a00 * a22 - a02 * a20) + out[5] = (a02 * a10 - a00 * a12) + out[6] = (a10 * a21 - a11 * a20) + out[7] = (a01 * a20 - a00 * a21) + out[8] = (a00 * a11 - a01 * a10) + + return out + } + + clone(a) { + /** + * Creates a new mat3 initialized with values from an existing matrix + * + * @alias mat3.clone + * @param {mat3} a matrix to clone + * @returns {mat3} a new 3x3 matrix + */ + var out = new Float32Array(9) + out[0] = a[0] + out[1] = a[1] + out[2] = a[2] + out[3] = a[3] + out[4] = a[4] + out[5] = a[5] + out[6] = a[6] + out[7] = a[7] + out[8] = a[8] + return out + } + + copy(out, a) { + /** + * Copy the values from one mat3 to another + * + * @alias mat3.copy + * @param {mat3} out the receiving matrix + * @param {mat3} a the source matrix + * @returns {mat3} out + */ + out[0] = a[0] + out[1] = a[1] + out[2] = a[2] + out[3] = a[3] + out[4] = a[4] + out[5] = a[5] + out[6] = a[6] + out[7] = a[7] + out[8] = a[8] + return out + } + + create() { + /** + * Creates a new identity mat3 + * + * @alias mat3.create + * @returns {mat3} a new 3x3 matrix + */ + var out = new Float32Array(9) + out[0] = 1 + out[1] = 0 + out[2] = 0 + out[3] = 0 + out[4] = 1 + out[5] = 0 + out[6] = 0 + out[7] = 0 + out[8] = 1 + return out + } + + determinant(a) { + /** + * Calculates the determinant of a mat3 + * + * @alias mat3.determinant + * @param {mat3} a the source matrix + * @returns {Number} determinant of a + */ + var a00 = a[0], a01 = a[1], a02 = a[2] + var a10 = a[3], a11 = a[4], a12 = a[5] + var a20 = a[6], a21 = a[7], a22 = a[8] + + return a00 * (a22 * a11 - a12 * a21) + a01 * (a12 * a20 - a22 * a10) + a02 * (a21 * a10 - a11 * a20) + } + + frob(a) { + /** + * Returns Frobenius norm of a mat3 + * + * @alias mat3.frob + * @param {mat3} a the matrix to calculate Frobenius norm of + * @returns {Number} Frobenius norm + */ + return Math.sqrt( + a[0]*a[0] + + a[1]*a[1] + + a[2]*a[2] + + a[3]*a[3] + + a[4]*a[4] + + a[5]*a[5] + + a[6]*a[6] + + a[7]*a[7] + + a[8]*a[8] + ) + } + + fromMat2d(out, a) { + /** + * Copies the values from a mat2d into a mat3 + * + * @alias mat3.fromMat2d + * @param {mat3} out the receiving matrix + * @param {mat2d} a the matrix to copy + * @returns {mat3} out + **/ + out[0] = a[0] + out[1] = a[1] + out[2] = 0 + + out[3] = a[2] + out[4] = a[3] + out[5] = 0 + + out[6] = a[4] + out[7] = a[5] + out[8] = 1 + + return out + } + + fromMat4(out, a) { + /** + * Copies the upper-left 3x3 values into the given mat3. + * + * @alias mat3.fromMat4 + * @param {mat3} out the receiving 3x3 matrix + * @param {mat4} a the source 4x4 matrix + * @returns {mat3} out + */ + out[0] = a[0] + out[1] = a[1] + out[2] = a[2] + out[3] = a[4] + out[4] = a[5] + out[5] = a[6] + out[6] = a[8] + out[7] = a[9] + out[8] = a[10] + return out + } + + fromQuat(out, q) { + /** + * Calculates a 3x3 matrix from the given quaternion + * + * @alias mat3.fromQuat + * @param {mat3} out mat3 receiving operation result + * @param {quat} q Quaternion to create matrix from + * + * @returns {mat3} out + */ + var x = q[0] + var y = q[1] + var z = q[2] + var w = q[3] + + var x2 = x + x + var y2 = y + y + var z2 = z + z + + var xx = x * x2 + var yx = y * x2 + var yy = y * y2 + var zx = z * x2 + var zy = z * y2 + var zz = z * z2 + var wx = w * x2 + var wy = w * y2 + var wz = w * z2 + + out[0] = 1 - yy - zz + out[3] = yx - wz + out[6] = zx + wy + + out[1] = yx + wz + out[4] = 1 - xx - zz + out[7] = zy - wx + + out[2] = zx - wy + out[5] = zy + wx + out[8] = 1 - xx - yy + + return out + } + + identity(out) { + /** + * Set a mat3 to the identity matrix + * + * @alias mat3.identity + * @param {mat3} out the receiving matrix + * @returns {mat3} out + */ + out[0] = 1 + out[1] = 0 + out[2] = 0 + out[3] = 0 + out[4] = 1 + out[5] = 0 + out[6] = 0 + out[7] = 0 + out[8] = 1 + return out + } + + invert(out, a) { + /** + * Inverts a mat3 + * + * @alias mat3.invert + * @param {mat3} out the receiving matrix + * @param {mat3} a the source matrix + * @returns {mat3} out + */ + var a00 = a[0], a01 = a[1], a02 = a[2] + var a10 = a[3], a11 = a[4], a12 = a[5] + var a20 = a[6], a21 = a[7], a22 = a[8] + + var b01 = a22 * a11 - a12 * a21 + var b11 = -a22 * a10 + a12 * a20 + var b21 = a21 * a10 - a11 * a20 + + // Calculate the determinant + var det = a00 * b01 + a01 * b11 + a02 * b21 + + if (!det) return null + det = 1.0 / det + + out[0] = b01 * det + out[1] = (-a22 * a01 + a02 * a21) * det + out[2] = (a12 * a01 - a02 * a11) * det + out[3] = b11 * det + out[4] = (a22 * a00 - a02 * a20) * det + out[5] = (-a12 * a00 + a02 * a10) * det + out[6] = b21 * det + out[7] = (-a21 * a00 + a01 * a20) * det + out[8] = (a11 * a00 - a01 * a10) * det + + return out + } + + multiply(out, a, b) { + /** + * Multiplies two mat3's + * + * @alias mat3.multiply + * @param {mat3} out the receiving matrix + * @param {mat3} a the first operand + * @param {mat3} b the second operand + * @returns {mat3} out + */ + var a00 = a[0], a01 = a[1], a02 = a[2] + var a10 = a[3], a11 = a[4], a12 = a[5] + var a20 = a[6], a21 = a[7], a22 = a[8] + + var b00 = b[0], b01 = b[1], b02 = b[2] + var b10 = b[3], b11 = b[4], b12 = b[5] + var b20 = b[6], b21 = b[7], b22 = b[8] + + out[0] = b00 * a00 + b01 * a10 + b02 * a20 + out[1] = b00 * a01 + b01 * a11 + b02 * a21 + out[2] = b00 * a02 + b01 * a12 + b02 * a22 + + out[3] = b10 * a00 + b11 * a10 + b12 * a20 + out[4] = b10 * a01 + b11 * a11 + b12 * a21 + out[5] = b10 * a02 + b11 * a12 + b12 * a22 + + out[6] = b20 * a00 + b21 * a10 + b22 * a20 + out[7] = b20 * a01 + b21 * a11 + b22 * a21 + out[8] = b20 * a02 + b21 * a12 + b22 * a22 + + return out + } + + normalFromMat4(out, a) { + /** + * Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix + * + * @alias mat3.normalFromMat4 + * @param {mat3} out mat3 receiving operation result + * @param {mat4} a Mat4 to derive the normal matrix from + * + * @returns {mat3} out + */ + var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3] + var a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7] + var a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11] + var a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15] + + var b00 = a00 * a11 - a01 * a10 + var b01 = a00 * a12 - a02 * a10 + var b02 = a00 * a13 - a03 * a10 + var b03 = a01 * a12 - a02 * a11 + var b04 = a01 * a13 - a03 * a11 + var b05 = a02 * a13 - a03 * a12 + var b06 = a20 * a31 - a21 * a30 + var b07 = a20 * a32 - a22 * a30 + var b08 = a20 * a33 - a23 * a30 + var b09 = a21 * a32 - a22 * a31 + var b10 = a21 * a33 - a23 * a31 + var b11 = a22 * a33 - a23 * a32 + + // Calculate the determinant + var det = b00 * b11 + - b01 * b10 + + b02 * b09 + + b03 * b08 + - b04 * b07 + + b05 * b06 + + if (!det) return null + det = 1.0 / det + + out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det + out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det + out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det + + out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det + out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det + out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det + + out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det + out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det + out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det + + return out + } + + rotate(out, a, rad) { + /** + * Rotates a mat3 by the given angle + * + * @alias mat3.rotate + * @param {mat3} out the receiving matrix + * @param {mat3} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat3} out + */ + var a00 = a[0], a01 = a[1], a02 = a[2] + var a10 = a[3], a11 = a[4], a12 = a[5] + var a20 = a[6], a21 = a[7], a22 = a[8] + + var s = Math.sin(rad) + var c = Math.cos(rad) + + out[0] = c * a00 + s * a10 + out[1] = c * a01 + s * a11 + out[2] = c * a02 + s * a12 + + out[3] = c * a10 - s * a00 + out[4] = c * a11 - s * a01 + out[5] = c * a12 - s * a02 + + out[6] = a20 + out[7] = a21 + out[8] = a22 + + return out + } + + scale(out, a, v) { + /** + * Scales the mat3 by the dimensions in the given vec2 + * + * @alias mat3.scale + * @param {mat3} out the receiving matrix + * @param {mat3} a the matrix to rotate + * @param {vec2} v the vec2 to scale the matrix by + * @returns {mat3} out + **/ + var x = v[0] + var y = v[1] + + out[0] = x * a[0] + out[1] = x * a[1] + out[2] = x * a[2] + + out[3] = y * a[3] + out[4] = y * a[4] + out[5] = y * a[5] + + out[6] = a[6] + out[7] = a[7] + out[8] = a[8] + + return out + } + + str(a) { + /** + * Returns a string representation of a mat3 + * + * @alias mat3.str + * @param {mat3} mat matrix to represent as a string + * @returns {String} string representation of the matrix + */ + return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' + a[8] + ')' + } + + translate(out, a, v) { + /** + * Translate a mat3 by the given vector + * + * @alias mat3.translate + * @param {mat3} out the receiving matrix + * @param {mat3} a the matrix to translate + * @param {vec2} v vector to translate by + * @returns {mat3} out + */ + var a00 = a[0], a01 = a[1], a02 = a[2] + var a10 = a[3], a11 = a[4], a12 = a[5] + var a20 = a[6], a21 = a[7], a22 = a[8] + var x = v[0], y = v[1] + + out[0] = a00 + out[1] = a01 + out[2] = a02 + + out[3] = a10 + out[4] = a11 + out[5] = a12 + + out[6] = x * a00 + y * a10 + a20 + out[7] = x * a01 + y * a11 + a21 + out[8] = x * a02 + y * a12 + a22 + + return out + } + + transpose(out, a) { + /** + * Transpose the values of a mat3 + * + * @alias mat3.transpose + * @param {mat3} out the receiving matrix + * @param {mat3} a the source matrix + * @returns {mat3} out + */ + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (out === a) { + var a01 = a[1], a02 = a[2], a12 = a[5] + out[1] = a[3] + out[2] = a[6] + out[3] = a01 + out[5] = a[7] + out[6] = a02 + out[7] = a12 + } else { + out[0] = a[0] + out[1] = a[3] + out[2] = a[6] + out[3] = a[1] + out[4] = a[4] + out[5] = a[7] + out[6] = a[2] + out[7] = a[5] + out[8] = a[8] + } + + return out + } + +} \ No newline at end of file diff --git a/src/additionalMath/gl_quat.js b/src/additionalMath/gl_quat.js new file mode 100644 index 0000000..318a676 --- /dev/null +++ b/src/additionalMath/gl_quat.js @@ -0,0 +1,445 @@ +export default class GL_Quat{ + constructor(){ + + } + + add(out, a, b){ + /** + * Adds two quat's + * + * @param {quat} out the receiving quaternion + * @param {quat} a the first operand + * @param {quat} b the second operand + * @returns {quat} out + * @function + */ + return gl_vec4.add(out, a, b); + } + + calculateW(out, a) { + /** + * Calculates the W component of a quat from the X, Y, and Z components. + * Assumes that quaternion is 1 unit in length. + * Any existing W component will be ignored. + * + * @param {quat} out the receiving quaternion + * @param {quat} a quat to calculate W component of + * @returns {quat} out + */ + var x = a[0], y = a[1], z = a[2] + + out[0] = x + out[1] = y + out[2] = z + out[3] = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z)) + return out + } + + clone(a){ + /** + * Creates a new quat initialized with values from an existing quaternion + * + * @param {quat} a quaternion to clone + * @returns {quat} a new quaternion + * @function + */ + return gl_vec4.clone(a); + } + + conjugate(out, a){ + /** + * Calculates the conjugate of a quat + * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result. + * + * @param {quat} out the receiving quaternion + * @param {quat} a quat to calculate conjugate of + * @returns {quat} out + */ + out[0] = -a[0]; + out[1] = -a[1]; + out[2] = -a[2]; + out[3] = a[3]; + return out; + } + + copy(out, a){ + /** + * Copy the values from one quat to another + * + * @param {quat} out the receiving quaternion + * @param {quat} a the source quaternion + * @returns {quat} out + * @function + */ + return gl_vec4.copy(out, a); + } + + create(){ + /** + * Creates a new identity quat + * + * @returns {quat} a new quaternion + */ + var out = new Float32Array(4); + out[0] = 0; + out[1] = 0; + out[2] = 0; + out[3] = 1; + return out; + } + + dot(a, b){ + return gl_vec4.dot(a, b) + } + + fromMat3 (out, m) { + /** + * Creates a quaternion from the given 3x3 rotation matrix. + * + * NOTE: The resultant quaternion is not normalized, so you should be sure + * to renormalize the quaternion yourself where necessary. + * + * @param {quat} out the receiving quaternion + * @param {mat3} m rotation matrix + * @returns {quat} out + * @function + */ + + // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes + // article "Quaternion Calculus and Fast Animation". + var fTrace = m[0] + m[4] + m[8] + var fRoot + + if (fTrace > 0.0) { + // |w| > 1/2, may as well choose w > 1/2 + fRoot = Math.sqrt(fTrace + 1.0) // 2w + out[3] = 0.5 * fRoot + fRoot = 0.5 / fRoot // 1/(4w) + out[0] = (m[5] - m[7]) * fRoot + out[1] = (m[6] - m[2]) * fRoot + out[2] = (m[1] - m[3]) * fRoot + } else { + // |w| <= 1/2 + var i = 0 + if (m[4] > m[0]) { + i = 1 + } + if (m[8] > m[i * 3 + i]) { + i = 2 + } + var j = (i + 1) % 3 + var k = (i + 2) % 3 + + fRoot = Math.sqrt(m[i * 3 + i] - m[j * 3 + j] - m[k * 3 + k] + 1.0) + out[i] = 0.5 * fRoot + fRoot = 0.5 / fRoot + out[3] = (m[j * 3 + k] - m[k * 3 + j]) * fRoot + out[j] = (m[j * 3 + i] + m[i * 3 + j]) * fRoot + out[k] = (m[k * 3 + i] + m[i * 3 + k]) * fRoot + } + + return out + } + + fromValues(x, y, z, w){ + return gl_vec4.fromValues(x, y, z, w); + } + + identity (out) { + /** + * Set a quat to the identity quaternion + * + * @param {quat} out the receiving quaternion + * @returns {quat} out + */ + out[0] = 0 + out[1] = 0 + out[2] = 0 + out[3] = 1 + return out + } + + invert (out, a) { + /** + * Calculates the inverse of a quat + * + * @param {quat} out the receiving quaternion + * @param {quat} a quat to calculate inverse of + * @returns {quat} out + */ + var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], + dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3, + invDot = dot ? 1.0 / dot : 0 + + // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0 + + out[0] = -a0 * invDot + out[1] = -a1 * invDot + out[2] = -a2 * invDot + out[3] = a3 * invDot + return out + } + + length(a){ + return gl_vec4.length(a); + } + + lerp (out, a, b, t) { + return gl_vec4.lerp(out, a, b, t); + } + + multiply(out, a, b){ + /** + * Multiplies two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ + out[0] = a[0] * b[0]; + out[1] = a[1] * b[1]; + out[2] = a[2] * b[2]; + out[3] = a[3] * b[3]; + return out; + } + + normalize (out, a) { + return gl_vec4.normalize(out, a); + } + + rotateX (out, a, rad) { + /** + * Rotates a quaternion by the given angle about the X axis + * + * @param {quat} out quat receiving operation result + * @param {quat} a quat to rotate + * @param {number} rad angle (in radians) to rotate + * @returns {quat} out + */ + rad *= 0.5 + + var ax = a[0], ay = a[1], az = a[2], aw = a[3], + bx = Math.sin(rad), bw = Math.cos(rad) + + out[0] = ax * bw + aw * bx + out[1] = ay * bw + az * bx + out[2] = az * bw - ay * bx + out[3] = aw * bw - ax * bx + return out + } + + rotateY (out, a, rad) { + /** + * Rotates a quaternion by the given angle about the Y axis + * + * @param {quat} out quat receiving operation result + * @param {quat} a quat to rotate + * @param {number} rad angle (in radians) to rotate + * @returns {quat} out + */ + rad *= 0.5 + + var ax = a[0], ay = a[1], az = a[2], aw = a[3], + by = Math.sin(rad), bw = Math.cos(rad) + + out[0] = ax * bw - az * by + out[1] = ay * bw + aw * by + out[2] = az * bw + ax * by + out[3] = aw * bw - ay * by + return out + } + + rotateZ (out, a, rad) { + /** + * Rotates a quaternion by the given angle about the Z axis + * + * @param {quat} out quat receiving operation result + * @param {quat} a quat to rotate + * @param {number} rad angle (in radians) to rotate + * @returns {quat} out + */ + rad *= 0.5 + + var ax = a[0], ay = a[1], az = a[2], aw = a[3], + bz = Math.sin(rad), bw = Math.cos(rad) + + out[0] = ax * bw + ay * bz + out[1] = ay * bw - ax * bz + out[2] = az * bw + aw * bz + out[3] = aw * bw - az * bz + return out + } + + rotationTo (out, a, b) { + /** + * Sets a quaternion to represent the shortest rotation from one + * vector to another. + * + * Both vectors are assumed to be unit length. + * + * @param {quat} out the receiving quaternion. + * @param {vec3} a the initial vector + * @param {vec3} b the destination vector + * @returns {quat} out + */ + var tmpvec3 = [0, 0, 0] + var xUnitVec3 = [1, 0, 0] + var yUnitVec3 = [0, 1, 0] + + var dot = gl_vec3.dot(a, b) + if (dot < -0.999999) { + gl_vec3.cross(tmpvec3, xUnitVec3, a) + if (gl_vec3.length(tmpvec3) < 0.000001) { + tmpvec3 = gl_vec3.cross(tmpvec3, yUnitVec3, a) + } + gl_vec3.normalize(tmpvec3, tmpvec3) + this.setAxisAngle(out, tmpvec3, Math.PI) + return out + } else if (dot > 0.999999) { + out[0] = 0 + out[1] = 0 + out[2] = 0 + out[3] = 1 + return out + } else { + tmpvec3 = gl_vec3.cross(tmpvec3, a, b) + out[0] = tmpvec3[0] + out[1] = tmpvec3[1] + out[2] = tmpvec3[2] + out[3] = 1 + dot + return this.normalize(out, out) + } + } + + scale(out, a, b){ + return gl_vec4.scale(out, a, b); + } + + set(out, x, y, z, w){ + return gl_vec4.set(out, x, y, z, w); + } + + setAxes (out, view, right, up) { + /** + * Sets the specified quaternion with values corresponding to the given + * axes. Each axis is a vec3 and is expected to be unit length and + * perpendicular to all other specified axes. + * + * @param {vec3} view the vector representing the viewing direction + * @param {vec3} right the vector representing the local "right" direction + * @param {vec3} up the vector representing the local "up" direction + * @returns {quat} out + */ + var matr = gl_mat3.create() + + matr[0] = right[0] + matr[3] = right[1] + matr[6] = right[2] + + matr[1] = up[0] + matr[4] = up[1] + matr[7] = up[2] + + matr[2] = -view[0] + matr[5] = -view[1] + matr[8] = -view[2] + + return this.normalize(out, this.fromMat3(out, matr)) + } + + setAxisAngle (out, axis, rad) { + /** + * Sets a quat from the given angle and rotation axis, + * then returns it. + * + * @param {quat} out the receiving quaternion + * @param {vec3} axis the axis around which to rotate + * @param {Number} rad the angle in radians + * @returns {quat} out + **/ + rad = rad * 0.5 + var s = Math.sin(rad) + out[0] = s * axis[0] + out[1] = s * axis[1] + out[2] = s * axis[2] + out[3] = Math.cos(rad) + return out + } + + slerp (out, a, b, t) { + /** + * Performs a spherical linear interpolation between two quat + * + * @param {quat} out the receiving quaternion + * @param {quat} a the first operand + * @param {quat} b the second operand + * @param {Number} t interpolation amount between the two inputs + * @returns {quat} out + */ + // benchmarks: + // http://jsperf.com/quaternion-slerp-implementations + + var ax = a[0], ay = a[1], az = a[2], aw = a[3], + bx = b[0], by = b[1], bz = b[2], bw = b[3] + + var omega, cosom, sinom, scale0, scale1 + + // calc cosine + cosom = ax * bx + ay * by + az * bz + aw * bw + // adjust signs (if necessary) + if (cosom < 0.0) { + cosom = -cosom + bx = -bx + by = -by + bz = -bz + bw = -bw + } + // calculate coefficients + if ((1.0 - cosom) > 0.000001) { + // standard case (slerp) + omega = Math.acos(cosom) + sinom = Math.sin(omega) + scale0 = Math.sin((1.0 - t) * omega) / sinom + scale1 = Math.sin(t * omega) / sinom + } else { + // "from" and "to" quaternions are very close + // ... so we can do a linear interpolation + scale0 = 1.0 - t + scale1 = t + } + // calculate final values + out[0] = scale0 * ax + scale1 * bx + out[1] = scale0 * ay + scale1 * by + out[2] = scale0 * az + scale1 * bz + out[3] = scale0 * aw + scale1 * bw + + return out + } + + sqlerp (out, a, b, c, d, t) { + /** + * Performs a spherical linear interpolation with two control points + * + * @param {quat} out the receiving quaternion + * @param {quat} a the first operand + * @param {quat} b the second operand + * @param {quat} c the third operand + * @param {quat} d the fourth operand + * @param {Number} t interpolation amount + * @returns {quat} out + */ + var temp1 = [0, 0, 0, 1] + var temp2 = [0, 0, 0, 1] + + temp1 = this.slerp(temp1, a, d, t) + temp2 = this.slerp(temp2, b, c, t) + out = this.slerp(out, temp1, temp2, 2 * t * (1 - t)) + + return out + } + + squaredLength(a){ + return gl_vec4.squaredLength(a) + } +} \ No newline at end of file diff --git a/src/additionalMath/gl_rvaa.js b/src/additionalMath/gl_rvaa.js new file mode 100644 index 0000000..a67d987 --- /dev/null +++ b/src/additionalMath/gl_rvaa.js @@ -0,0 +1,343 @@ +export default class GL_RVAA{ + constructor(){ + + } + + //INFO Vector3 functions + AIOvec3multiplyWithMatrix(out, vec, mat){ + /** + * Multiplies a vec3 with a mat3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a the vec3 + * @param {vec3} b the mat3 + * @returns {vec3} out + */ + + out[0] = mat[0] * vec[0] + mat[1] * vec[1] + mat[2] * vec[2] + out[1] = mat[3] * vec[0] + mat[4] * vec[1] + mat[5] * vec[2] + out[2] = mat[6] * vec[0] + mat[7] * vec[1] + mat[8] * vec[2] + + /* + out[0] = mat[0] * vec[0] + mat[3] * vec[1] + mat[6] * vec[2] + out[1] = mat[1] * vec[0] + mat[4] * vec[1] + mat[7] * vec[2] + out[2] = mat[2] * vec[0] + mat[5] * vec[1] + mat[8] * vec[2] + */ + return out + } + + AIOvec3normalize(out, a) { + /** + * Normalize a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to normalize + * @returns {vec3} out + */ + var x = a[0], + y = a[1], + z = a[2] + var len = x*x + y*y + z*z + if (len > 0) { + //TODO: evaluate use of glm_invsqrt here? + len = 1 / Math.sqrt(len) + out[0] = a[0] * len + out[1] = a[1] * len + out[2] = a[2] * len + } + return out + } + + AIOvec3add(out, a, b) { + /** + * Adds two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ + out[0] = a[0] + b[0] + out[1] = a[1] + b[1] + out[2] = a[2] + b[2] + return out + } + + AIOvec3subtract(out, a, b) { + /** + * Subtracts vector b from vector a + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ + out[0] = a[0] - b[0] + out[1] = a[1] - b[1] + out[2] = a[2] - b[2] + return out + } + + AIOvec3multiply(out, a, b) { + /** + * Multiplies two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ + out[0] = a[0] * b[0] + out[1] = a[1] * b[1] + out[2] = a[2] * b[2] + return out + } + + AIOvec3dot(a, b) { + /** + * Calculates the dot product of two vec3's + * + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {Number} dot product of a and b + */ + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + } + + AIOvec3cross(out, a, b) { + /** + * Computes the cross product of two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ + var ax = a[0], ay = a[1], az = a[2], + bx = b[0], by = b[1], bz = b[2] + + out[0] = ay * bz - az * by + out[1] = az * bx - ax * bz + out[2] = ax * by - ay * bx + return out + } + + AIOvec3fromValues(x, y, z) { + var out = new Float32Array(3) + out[0] = x + out[1] = y + out[2] = z + return out + } + + //INFO vector4 functions + AIOvec4copy (out, a) { + out[0] = a[0] + out[1] = a[1] + out[2] = a[2] + out[3] = a[3] + return out + } + + AIOvec4normalize (out, a) { + /** + * Normalize a vec4 + * + * @param {vec4} out the receiving vector + * @param {vec4} a vector to normalize + * @returns {vec4} out + */ + var x = a[0], + y = a[1], + z = a[2], + w = a[3] + var len = x * x + y * y + z * z + w * w + if (len > 0) { + len = 1 / Math.sqrt(len) + out[0] = x * len + out[1] = y * len + out[2] = z * len + out[3] = w * len + } + return out + } + + //INFO quat funcitons + AIOquatcreate () { + var out = new Float32Array(4) + out[0] = 0 + out[1] = 0 + out[2] = 0 + out[3] = 1 + return out + } + + AIOquatCreateFromAngleAxis(x, y, z, w){ + var a = w; + var s = Math.sin(a * 0.5); + var out = new Float32Array(4) + out[0] = x * s + out[1] = y * s + out[2] = z * s + out[3] = Math.cos(a * 0.5) + return out + } + + AIOquatfromValues (x, y, z, w) { + var out = new Float32Array(4) + out[0] = x + out[1] = y + out[2] = z + out[3] = w + return out + } + + AIOquatconjugate (out, a) { + out[0] = -a[0] + out[1] = -a[1] + out[2] = -a[2] + out[3] = a[3] + return out + } + + AIOquatmultiply (out, a, b) { + var ax = a[0], ay = a[1], az = a[2], aw = a[3], + bx = b[0], by = b[1], bz = b[2], bw = b[3] + + out[0] = ax * bw + aw * bx + ay * bz - az * by + out[1] = ay * bw + aw * by + az * bx - ax * bz + out[2] = az * bw + aw * bz + ax * by - ay * bx + out[3] = aw * bw - ax * bx - ay * by - az * bz + return out + } + + //INFO matrix functions + AIOmat3create() { + /** + * Creates a new identity mat3 + * + * @alias mat3.create + * @returns {mat3} a new 3x3 matrix + */ + var out = new Float32Array(9) + out[0] = 1 + out[1] = 0 + out[2] = 0 + out[3] = 0 + out[4] = 1 + out[5] = 0 + out[6] = 0 + out[7] = 0 + out[8] = 1 + return out + } + + AIOmat3fromQuat(out, q) { + /** + * Calculates a 3x3 matrix from the given quaternion + * + * @alias mat3.fromQuat + * @param {mat3} out mat3 receiving operation result + * @param {quat} q Quaternion to create matrix from + * + * @returns {mat3} out + */ + var x = q[0] + var y = q[1] + var z = q[2] + var w = q[3] + + var x2 = x + x + var y2 = y + y + var z2 = z + z + + var xx = x * x2 + var yx = y * x2 + var yy = y * y2 + var zx = z * x2 + var zy = z * y2 + var zz = z * z2 + var wx = w * x2 + var wy = w * y2 + var wz = w * z2 + + out[0] = 1 - yy - zz + out[3] = yx - wz + out[6] = zx + wy + + out[1] = yx + wz + out[4] = 1 - xx - zz + out[7] = zy - wx + + out[2] = zx - wy + out[5] = zy + wx + out[8] = 1 - xx - yy + + return out + } + + //var quat = require('gl-quat') + //var vec3 = require('gl-vec3') + + AIOrotateVectorAboutAxis(v, axis, angle) { + //INFO unused + var sinHalfAngle = Math.sin(angle / 2.0) + var cosHalfAngle = Math.cos(angle / 2.0) + + var rX = axis[0] * sinHalfAngle + var rY = axis[1] * sinHalfAngle + var rZ = axis[2] * sinHalfAngle + var rW = cosHalfAngle + + var q = this.AIOquatfromValues(rX, rY, rZ, rW) + + // find the conjugate of q. + var q_conj = this.AIOquatcreate() + this.AIOvec4copy(q_conj, q) + this.AIOquatconjugate(q_conj, q_conj) + + var p = this.AIOquatfromValues(v[0], v[1], v[2], 0) + + var result = this.AIOquatcreate() + + /* + Compute the product (q * p * q_conj) + For more details, please see page 75 in "Real-time rendering - Third edition" + */ + this.AIOquatmultiply(result, q, p) + this.AIOquatmultiply(result, result, q_conj) + + return this.AIOvec3fromValues(result[0], result[1], result[2]) + + } + + rotateVectorAboutAxis(v, axis, angle) { + var sinHalfAngle = Math.sin(angle / 2.0); + var cosHalfAngle = Math.cos(angle / 2.0); + + var rX = axis[0] * sinHalfAngle; + var rY = axis[1] * sinHalfAngle; + var rZ = axis[2] * sinHalfAngle; + var rW = cosHalfAngle; + + var q = gl_quat.fromValues(rX, rY, rZ, rW); + + // find the conjugate of q. + var q_conj = gl_quat.create(); + q_conj = gl_quat.copy(q_conj, q); + q_conj = gl_quat.conjugate(q_conj, q_conj); + + var p = gl_quat.fromValues(v[0], v[1], v[2], 0); + + var result = gl_quat.create(); + + /* + Compute the product (q * p * q_conj) + For more details, please see page 75 in "Real-time rendering - Third edition" + */ + result = gl_quat.multiply(result, q, p); + result = gl_quat.multiply(result, result, q_conj); + + return gl_vec3.fromValues(result[0], result[1], result[2]); + } +} \ No newline at end of file diff --git a/src/additionalMath/gl_vec3.js b/src/additionalMath/gl_vec3.js new file mode 100644 index 0000000..893b696 --- /dev/null +++ b/src/additionalMath/gl_vec3.js @@ -0,0 +1,702 @@ +export default class GL_Vec3{ + constructor(){ + this.epsilon = 0.000001; + } + + create() { + /** + * Creates a new, empty vec3 + * + * @returns {vec3} a new 3D vector + */ + var out = new Float32Array(3) + out[0] = 0 + out[1] = 0 + out[2] = 0 + return out + } + + clone(a) { + /** + * Creates a new vec3 initialized with values from an existing vector + * + * @param {vec3} a vector to clone + * @returns {vec3} a new 3D vector + */ + var out = new Float32Array(3) + out[0] = a[0] + out[1] = a[1] + out[2] = a[2] + return out + } + + angle(a, b) { + /** + * Get the angle between two 3D vectors + * @param {vec3} a The first operand + * @param {vec3} b The second operand + * @returns {Number} The angle in radians + */ + var tempA = this.fromValues(a[0], a[1], a[2]) + var tempB = this.fromValues(b[0], b[1], b[2]) + + this.normalize(tempA, tempA) + this.normalize(tempB, tempB) + + var cosine = this.dot(tempA, tempB) + + if(cosine > 1.0){ + return 0 + } else { + return Math.acos(cosine) + } + } + + fromValues(x, y, z) { + /** + * Creates a new vec3 initialized with the given values + * + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @returns {vec3} a new 3D vector + */ + var out = new Float32Array(3); + out[0] = x; + out[1] = y; + out[2] = z; + return out; + } + + copy(out, a) { + /** + * Copy the values from one vec3 to another + * + * @param {vec3} out the receiving vector + * @param {vec3} a the source vector + * @returns {vec3} out + */ + out[0] = a[0] + out[1] = a[1] + out[2] = a[2] + return out + } + + set(out, x, y, z) { + /** + * Set the components of a vec3 to the given values + * + * @param {vec3} out the receiving vector + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @returns {vec3} out + */ + out[0] = x + out[1] = y + out[2] = z + return out + } + + equals(a, b) { + /** + * Returns whether or not the vectors have approximately the same elements in the same position. + * + * @param {vec3} a The first vector. + * @param {vec3} b The second vector. + * @returns {Boolean} True if the vectors are equal, false otherwise. + */ + var a0 = a[0] + var a1 = a[1] + var a2 = a[2] + var b0 = b[0] + var b1 = b[1] + var b2 = b[2] + return (Math.abs(a0 - b0) <= this.epsilon * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && + Math.abs(a1 - b1) <= this.epsilon * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && + Math.abs(a2 - b2) <= this.epsilon * Math.max(1.0, Math.abs(a2), Math.abs(b2))) + } + + exactEquals(a, b) { + /** + * Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===) + * + * @param {vec3} a The first vector. + * @param {vec3} b The second vector. + * @returns {Boolean} True if the vectors are equal, false otherwise. + */ + return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] + } + + add(out, a, b) { + /** + * Adds two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ + out[0] = a[0] + b[0] + out[1] = a[1] + b[1] + out[2] = a[2] + b[2] + return out + } + + subtract(out, a, b) { + /** + * Subtracts vector b from vector a + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ + out[0] = a[0] - b[0] + out[1] = a[1] - b[1] + out[2] = a[2] - b[2] + return out + } + + sub(out, a, b){ + return this.subtract(out, a, b); + } + + multiply(out, a, b) { + /** + * Multiplies two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ + out[0] = a[0] * b[0] + out[1] = a[1] * b[1] + out[2] = a[2] * b[2] + return out + } + + mul(out, a, b){ + return this.multiply(out, a, b); + } + + multiplyWithMatrix(out, vec, mat){ + /** + * Multiplies a vec3 with a mat3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a the vec3 + * @param {vec3} b the mat3 + * @returns {vec3} out + */ + out[0] = mat[0] * vec[0] + mat[1] * vec[1] + mat[2] * vec[2] + out[1] = mat[3] * vec[3] + mat[4] * vec[4] + mat[5] * vec[5] + out[2] = mat[6] * vec[6] + mat[7] * vec[7] + mat[8] * vec[8] + return out + } + + divide(out, a, b) { + /** + * Divides two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ + out[0] = a[0] / b[0] + out[1] = a[1] / b[1] + out[2] = a[2] / b[2] + return out + } + + div(out, a, b){ + return this.divide(out, a, b); + } + + min(out, a, b) { + /** + * Returns the minimum of two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ + out[0] = Math.min(a[0], b[0]) + out[1] = Math.min(a[1], b[1]) + out[2] = Math.min(a[2], b[2]) + return out + } + + max(out, a, b) { + /** + * Returns the maximum of two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ + out[0] = Math.max(a[0], b[0]) + out[1] = Math.max(a[1], b[1]) + out[2] = Math.max(a[2], b[2]) + return out + } + + floor(out, a) { + /** + * Math.floor the components of a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to floor + * @returns {vec3} out + */ + out[0] = Math.floor(a[0]) + out[1] = Math.floor(a[1]) + out[2] = Math.floor(a[2]) + return out + } + + ceil(out, a) { + /** + * Math.ceil the components of a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to ceil + * @returns {vec3} out + */ + out[0] = Math.ceil(a[0]) + out[1] = Math.ceil(a[1]) + out[2] = Math.ceil(a[2]) + return out + } + + round(out, a) { + /** + * Math.round the components of a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to round + * @returns {vec3} out + */ + out[0] = Math.round(a[0]) + out[1] = Math.round(a[1]) + out[2] = Math.round(a[2]) + return out + } + + scale(out, a, b) { + /** + * Scales a vec3 by a scalar number + * + * @param {vec3} out the receiving vector + * @param {vec3} a the vector to scale + * @param {Number} b amount to scale the vector by + * @returns {vec3} out + */ + out[0] = a[0] * b + out[1] = a[1] * b + out[2] = a[2] * b + return out + } + + scaleAndAdd(out, a, b, scale) { + /** + * Adds two vec3's after scaling the second operand by a scalar value + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @param {Number} scale the amount to scale b by before adding + * @returns {vec3} out + */ + out[0] = a[0] + (b[0] * scale) + out[1] = a[1] + (b[1] * scale) + out[2] = a[2] + (b[2] * scale) + return out + } + + distance(a, b) { + /** + * Calculates the euclidian distance between two vec3's + * + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {Number} distance between a and b + */ + var x = b[0] - a[0], + y = b[1] - a[1], + z = b[2] - a[2] + return Math.sqrt(x*x + y*y + z*z) + } + + dist(a, b){ + return this.distance(a, b); + } + + squaredDistance(a, b) { + /** + * Calculates the squared euclidian distance between two vec3's + * + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {Number} squared distance between a and b + */ + var x = b[0] - a[0], + y = b[1] - a[1], + z = b[2] - a[2] + return x*x + y*y + z*z + } + + sqrDist(a, b){ + return this.squaredDistance(a, b); + } + + length(a) { + /** + * Calculates the length of a vec3 + * + * @param {vec3} a vector to calculate length of + * @returns {Number} length of a + */ + var x = a[0], + y = a[1], + z = a[2] + return Math.sqrt(x*x + y*y + z*z) + } + + len(a){ + return this.length(a); + } + + squaredLength(a) { + /** + * Calculates the squared length of a vec3 + * + * @param {vec3} a vector to calculate squared length of + * @returns {Number} squared length of a + */ + var x = a[0], + y = a[1], + z = a[2] + return x*x + y*y + z*z + } + + sqrLen(a){ + return this.squaredLength(a); + } + + negate(out, a) { + /** + * Negates the components of a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to negate + * @returns {vec3} out + */ + out[0] = -a[0] + out[1] = -a[1] + out[2] = -a[2] + return out + } + + inverse(out, a) { + /** + * Returns the inverse of the components of a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to invert + * @returns {vec3} out + */ + out[0] = 1.0 / a[0] + out[1] = 1.0 / a[1] + out[2] = 1.0 / a[2] + return out + } + + normalize(out, a) { + /** + * Normalize a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to normalize + * @returns {vec3} out + */ + var x = a[0], + y = a[1], + z = a[2] + var len = x*x + y*y + z*z + if (len > 0) { + //TODO: evaluate use of glm_invsqrt here? + len = 1 / Math.sqrt(len) + out[0] = a[0] * len + out[1] = a[1] * len + out[2] = a[2] * len + } + return out + } + + dot(a, b) { + /** + * Calculates the dot product of two vec3's + * + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {Number} dot product of a and b + */ + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + } + + cross(out, a, b) { + /** + * Computes the cross product of two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @returns {vec3} out + */ + var ax = a[0], ay = a[1], az = a[2], + bx = b[0], by = b[1], bz = b[2] + + out[0] = ay * bz - az * by + out[1] = az * bx - ax * bz + out[2] = ax * by - ay * bx + return out + } + + lerp(out, a, b, t) { + /** + * Performs a linear interpolation between two vec3's + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @param {Number} t interpolation amount between the two inputs + * @returns {vec3} out + */ + var ax = a[0], + ay = a[1], + az = a[2] + out[0] = ax + t * (b[0] - ax) + out[1] = ay + t * (b[1] - ay) + out[2] = az + t * (b[2] - az) + return out + } + + random(out, scale) { + /** + * Generates a random vector with the given scale + * + * @param {vec3} out the receiving vector + * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned + * @returns {vec3} out + */ + scale = scale || 1.0 + + var r = Math.random() * 2.0 * Math.PI + var z = (Math.random() * 2.0) - 1.0 + var zScale = Math.sqrt(1.0-z*z) * scale + + out[0] = Math.cos(r) * zScale + out[1] = Math.sin(r) * zScale + out[2] = z * scale + return out + } + + transformMat4(out, a, m) { + /** + * Transforms the vec3 with a mat4. + * 4th vector component is implicitly '1' + * + * @param {vec3} out the receiving vector + * @param {vec3} a the vector to transform + * @param {mat4} m matrix to transform with + * @returns {vec3} out + */ + var x = a[0], y = a[1], z = a[2], + w = m[3] * x + m[7] * y + m[11] * z + m[15] + w = w || 1.0 + out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w + out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w + out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w + return out + } + + transformMat3(out, a, m) { + /** + * Transforms the vec3 with a mat3. + * + * @param {vec3} out the receiving vector + * @param {vec3} a the vector to transform + * @param {mat4} m the 3x3 matrix to transform with + * @returns {vec3} out + */ + var x = a[0], y = a[1], z = a[2] + out[0] = x * m[0] + y * m[3] + z * m[6] + out[1] = x * m[1] + y * m[4] + z * m[7] + out[2] = x * m[2] + y * m[5] + z * m[8] + return out + } + + transformQuat(out, a, q) { + /** + * Transforms the vec3 with a quat + * + * Note: the quaternion must be a unit quaternion (|q| = 1) in + * order for this operation to be valid. + * + * @param {vec3} out the receiving vector + * @param {vec3} a the vector to transform + * @param {quat} q unit quaternion to transform with + * @returns {vec3} out + */ + + // Fast Vector Rotation using Quaternions by Robert Eisele + // https://raw.org/proof/vector-rotation-using-quaternions/ + + var x = a[0], y = a[1], z = a[2], + qx = q[0], qy = q[1], qz = q[2], qw = q[3] + + // t = q x v + var tx = qy * z - qz * y + var ty = qz * x - qx * z + var tz = qx * y - qy * x + + // t = 2t + tx *= 2 + ty *= 2 + tz *= 2 + + // v + w t + q x t + out[0] = x + qw * tx + qy * tz - qz * ty + out[1] = y + qw * ty + qz * tx - qx * tz + out[2] = z + qw * tz + qx * ty - qy * tx + + return out + } + + rotateX(out, a, b, c){ + /** + * Rotate a 3D vector around the x-axis + * @param {vec3} out The receiving vec3 + * @param {vec3} a The vec3 point to rotate + * @param {vec3} b The origin of the rotation + * @param {Number} c The angle of rotation + * @returns {vec3} out + */ + var by = b[1] + var bz = b[2] + + // Translate point to the origin + var py = a[1] - by + var pz = a[2] - bz + + var sc = Math.sin(c) + var cc = Math.cos(c) + + // perform rotation and translate to correct position + out[0] = a[0] + out[1] = by + py * cc - pz * sc + out[2] = bz + py * sc + pz * cc + + return out + } + + rotateY(out, a, b, c){ + /** + * Rotate a 3D vector around the y-axis + * @param {vec3} out The receiving vec3 + * @param {vec3} a The vec3 point to rotate + * @param {vec3} b The origin of the rotation + * @param {Number} c The angle of rotation + * @returns {vec3} out + */ + var bx = b[0] + var bz = b[2] + + // translate point to the origin + var px = a[0] - bx + var pz = a[2] - bz + + var sc = Math.sin(c) + var cc = Math.cos(c) + + // perform rotation and translate to correct position + out[0] = bx + pz * sc + px * cc + out[1] = a[1] + out[2] = bz + pz * cc - px * sc + + return out + } + + rotateZ(out, a, b, c){ + /** + * Rotate a 3D vector around the z-axis + * @param {vec3} out The receiving vec3 + * @param {vec3} a The vec3 point to rotate + * @param {vec3} b The origin of the rotation + * @param {Number} c The angle of rotation + * @returns {vec3} out + */ + var bx = b[0] + var by = b[1] + + //Translate point to the origin + var px = a[0] - bx + var py = a[1] - by + + var sc = Math.sin(c) + var cc = Math.cos(c) + + // perform rotation and translate to correct position + out[0] = bx + px * cc - py * sc + out[1] = by + px * sc + py * cc + out[2] = a[2] + + return out + } + + forEach(a, stride, offset, count, fn, arg) { + /** + * Perform some operation over an array of vec3s. + * + * @param {Array} a the array of vectors to iterate over + * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed + * @param {Number} offset Number of elements to skip at the beginning of the array + * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array + * @param {Function} fn Function to call for each vector in the array + * @param {Object} [arg] additional argument to pass to fn + * @returns {Array} a + * @function + */ + var i, l + if(!stride) { + stride = 3 + } + + if(!offset) { + offset = 0 + } + + if(count) { + l = Math.min((count * stride) + offset, a.length) + } else { + l = a.length + } + + for(i = offset; i < l; i += stride) { + vec[0] = a[i] + vec[1] = a[i+1] + vec[2] = a[i+2] + fn(vec, vec, arg) + a[i] = vec[0] + a[i+1] = vec[1] + a[i+2] = vec[2] + } + + return a + } +} \ No newline at end of file diff --git a/src/additionalMath/gl_vec4.js b/src/additionalMath/gl_vec4.js new file mode 100644 index 0000000..658cd73 --- /dev/null +++ b/src/additionalMath/gl_vec4.js @@ -0,0 +1,420 @@ +export default class GL_Vec4{ + constructor(){ + + } + + create () { + /** + * Creates a new, empty vec4 + * + * @returns {vec4} a new 4D vector + */ + var out = new Float32Array(4) + out[0] = 0 + out[1] = 0 + out[2] = 0 + out[3] = 0 + return out + } + + clone (a) { + /** + * Creates a new vec4 initialized with values from an existing vector + * + * @param {vec4} a vector to clone + * @returns {vec4} a new 4D vector + */ + var out = new Float32Array(4) + out[0] = a[0] + out[1] = a[1] + out[2] = a[2] + out[3] = a[3] + return out + } + + fromValues(x, y, z, w){ + /** + * Creates a new vec4 initialized with the given values + * + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @param {Number} w W component + * @returns {vec4} a new 4D vector + */ + var out = new Float32Array(4); + out[0] = x; + out[1] = y; + out[2] = z; + out[3] = w; + return out; + } + + copy(out, a){ + /** + * Copy the values from one vec4 to another + * + * @param {vec4} out the receiving vector + * @param {vec4} a the source vector + * @returns {vec4} out + */ + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + return out; + } + + set (out, x, y, z, w) { + /** + * Set the components of a vec4 to the given values + * + * @param {vec4} out the receiving vector + * @param {Number} x X component + * @param {Number} y Y component + * @param {Number} z Z component + * @param {Number} w W component + * @returns {vec4} out + */ + out[0] = x + out[1] = y + out[2] = z + out[3] = w + return out + } + + add (out, a, b) { + /** + * Adds two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ + out[0] = a[0] + b[0] + out[1] = a[1] + b[1] + out[2] = a[2] + b[2] + out[3] = a[3] + b[3] + return out + } + + subtract (out, a, b) { + /** + * Subtracts vector b from vector a + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ + out[0] = a[0] - b[0] + out[1] = a[1] - b[1] + out[2] = a[2] - b[2] + out[3] = a[3] - b[3] + return out + } + + multiply (out, a, b) { + /** + * Multiplies two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ + out[0] = a[0] * b[0] + out[1] = a[1] * b[1] + out[2] = a[2] * b[2] + out[3] = a[3] * b[3] + return out + } + + divide (out, a, b) { + /** + * Divides two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ + out[0] = a[0] / b[0] + out[1] = a[1] / b[1] + out[2] = a[2] / b[2] + out[3] = a[3] / b[3] + return out + } + + min (out, a, b) { + /** + * Returns the minimum of two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ + out[0] = Math.min(a[0], b[0]) + out[1] = Math.min(a[1], b[1]) + out[2] = Math.min(a[2], b[2]) + out[3] = Math.min(a[3], b[3]) + return out + } + + max (out, a, b) { + /** + * Returns the maximum of two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {vec4} out + */ + out[0] = Math.max(a[0], b[0]) + out[1] = Math.max(a[1], b[1]) + out[2] = Math.max(a[2], b[2]) + out[3] = Math.max(a[3], b[3]) + return out + } + + scale (out, a, b) { + /** + * Scales a vec4 by a scalar number + * + * @param {vec4} out the receiving vector + * @param {vec4} a the vector to scale + * @param {Number} b amount to scale the vector by + * @returns {vec4} out + */ + out[0] = a[0] * b + out[1] = a[1] * b + out[2] = a[2] * b + out[3] = a[3] * b + return out + } + + scaleAndAdd (out, a, b, scale) { + /** + * Adds two vec4's after scaling the second operand by a scalar value + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @param {Number} scale the amount to scale b by before adding + * @returns {vec4} out + */ + out[0] = a[0] + (b[0] * scale) + out[1] = a[1] + (b[1] * scale) + out[2] = a[2] + (b[2] * scale) + out[3] = a[3] + (b[3] * scale) + return out + } + + distance (a, b) { + /** + * Calculates the euclidian distance between two vec4's + * + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {Number} distance between a and b + */ + var x = b[0] - a[0], + y = b[1] - a[1], + z = b[2] - a[2], + w = b[3] - a[3] + return Math.sqrt(x * x + y * y + z * z + w * w) + } + + squaredDistance (a, b) { + /** + * Calculates the squared euclidian distance between two vec4's + * + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {Number} squared distance between a and b + */ + var x = b[0] - a[0], + y = b[1] - a[1], + z = b[2] - a[2], + w = b[3] - a[3] + return x * x + y * y + z * z + w * w + } + + length(a) { + /** + * Calculates the length of a vec4 + * + * @param {vec4} a vector to calculate length of + * @returns {Number} length of a + */ + var x = a[0], + y = a[1], + z = a[2], + w = a[3] + return Math.sqrt(x * x + y * y + z * z + w * w) + } + + squaredLength(a) { + /** + * Calculates the squared length of a vec4 + * + * @param {vec4} a vector to calculate squared length of + * @returns {Number} squared length of a + */ + var x = a[0], + y = a[1], + z = a[2], + w = a[3] + return x * x + y * y + z * z + w * w + } + + negate (out, a) { + /** + * Negates the components of a vec4 + * + * @param {vec4} out the receiving vector + * @param {vec4} a vector to negate + * @returns {vec4} out + */ + out[0] = -a[0] + out[1] = -a[1] + out[2] = -a[2] + out[3] = -a[3] + return out + } + + inverse (out, a) { + /** + * Returns the inverse of the components of a vec4 + * + * @param {vec4} out the receiving vector + * @param {vec4} a vector to invert + * @returns {vec4} out + */ + out[0] = 1.0 / a[0] + out[1] = 1.0 / a[1] + out[2] = 1.0 / a[2] + out[3] = 1.0 / a[3] + return out + } + + normalize (out, a) { + /** + * Normalize a vec4 + * + * @param {vec4} out the receiving vector + * @param {vec4} a vector to normalize + * @returns {vec4} out + */ + var x = a[0], + y = a[1], + z = a[2], + w = a[3] + var len = x * x + y * y + z * z + w * w + if (len > 0) { + len = 1 / Math.sqrt(len) + out[0] = x * len + out[1] = y * len + out[2] = z * len + out[3] = w * len + } + return out + } + + dot (a, b) { + /** + * Calculates the dot product of two vec4's + * + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @returns {Number} dot product of a and b + */ + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3] + } + + lerp (out, a, b, t) { + /** + * Performs a linear interpolation between two vec4's + * + * @param {vec4} out the receiving vector + * @param {vec4} a the first operand + * @param {vec4} b the second operand + * @param {Number} t interpolation amount between the two inputs + * @returns {vec4} out + */ + var ax = a[0], + ay = a[1], + az = a[2], + aw = a[3] + out[0] = ax + t * (b[0] - ax) + out[1] = ay + t * (b[1] - ay) + out[2] = az + t * (b[2] - az) + out[3] = aw + t * (b[3] - aw) + return out + } + + random (out, scale) { + /** + * Generates a random vector with the given scale + * + * @param {vec4} out the receiving vector + * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned + * @returns {vec4} out + */ + scale = scale || 1.0 + + // TODO: This is a pretty awful way of doing this. Find something better. + out[0] = Math.random() + out[1] = Math.random() + out[2] = Math.random() + out[3] = Math.random() + this.normalize(out, out) + this.scale(out, out, scale) + return out + } + + transformMat4 (out, a, m) { + /** + * Transforms the vec4 with a mat4. + * + * @param {vec4} out the receiving vector + * @param {vec4} a the vector to transform + * @param {mat4} m matrix to transform with + * @returns {vec4} out + */ + var x = a[0], y = a[1], z = a[2], w = a[3] + out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w + out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w + out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w + out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w + return out + } + + transformQuat (out, a, q) { + /** + * Transforms the vec4 with a quat + * + * @param {vec4} out the receiving vector + * @param {vec4} a the vector to transform + * @param {quat} q quaternion to transform with + * @returns {vec4} out + */ + var x = a[0], y = a[1], z = a[2], + qx = q[0], qy = q[1], qz = q[2], qw = q[3], + + // calculate quat * vec + ix = qw * x + qy * z - qz * y, + iy = qw * y + qz * x - qx * z, + iz = qw * z + qx * y - qy * x, + iw = -qx * x - qy * y - qz * z + + // calculate result * inverse quat + out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy + out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz + out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx + out[3] = a[3] + return out + } +} \ No newline at end of file diff --git a/src/additionalMath/pointInPolygon.js b/src/additionalMath/pointInPolygon.js new file mode 100755 index 0000000..157c65b --- /dev/null +++ b/src/additionalMath/pointInPolygon.js @@ -0,0 +1,22 @@ +export default class PIP { + constructor() { + + } + + pointInPolygon(_point, _poly){ + //point and poly must be arrays eg [0, 0] and [[0, 0], [0, 1], [1, 1]] + let x = _point[0], y = _point[1]; + + let inside = false; + for (let i = 0, j = _poly.length - 1; i < _poly.length; j = i++) { + let xi = _poly[i][0], yi = _poly[i][1]; + let xj = _poly[j][0], yj = _poly[j][1]; + + let intersect = ((yi > y) != (yj > y)) + && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); + if (intersect) inside = !inside; + } + + return inside; + } +} \ No newline at end of file diff --git a/src/additionalMath/rayTriangleIntersection.js b/src/additionalMath/rayTriangleIntersection.js new file mode 100755 index 0000000..ca26e20 --- /dev/null +++ b/src/additionalMath/rayTriangleIntersection.js @@ -0,0 +1,119 @@ +export default class RTI{ + constructor(){ + this.epsilon = 0.000001; + this.edge1 = [0, 0, 0]; + this.edge2 = [0, 0, 0]; + this.tvec = [0, 0, 0]; + this.pvec = [0, 0, 0]; + this.qvec = [0, 0, 0]; + } + + cross(_out, _a, _b) { + let ax = _a[0], ay = _a[1], az = _a[2], + bx = _b[0], by = _b[1], bz = _b[2] + + _out[0] = ay * bz - az * by + _out[1] = az * bx - ax * bz + _out[2] = ax * by - ay * bx + return _out + } + + dot(_a, _b) { + return _a[0] * _b[0] + _a[1] * _b[1] + _a[2] * _b[2] + } + + sub(_out, _a, _b) { + _out[0] = _a[0] - _b[0] + _out[1] = _a[1] - _b[1] + _out[2] = _a[2] - _b[2] + return _out + } + + intersect(_out, _pt, _dir, _tri) { + this.sub(this.edge1, _tri[1], _tri[0]); + this.sub(this.edge2, _tri[2], _tri[0]); + + this.cross(this.pvec, _dir, this.edge2); + let det = this.dot(this.edge1, this.pvec); + + if (det < this.epsilon) return null; + this.sub(this.tvec, _pt, _tri[0]); + let u = this.dot(this.tvec, this.pvec); + if (u < 0 || u > det) return null; + this.cross(this.qvec, this.tvec, this.edge1); + let v = this.dot(_dir, this.qvec); + if (v < 0 || u + v > det) return null; + + let t = this.dot(this.edge2, this.qvec) / det; + _out[0] = _pt[0] + t * _dir[0]; + _out[1] = _pt[1] + t * _dir[1]; + _out[2] = _pt[2] + t * _dir[2]; + return _out; + } + + //additional vector math + rotateX(out, a, b, c) { + /** + * Rotate a 3D vector around the x-axis + * @param {vec3} out The receiving vec3 + * @param {vec3} a The vec3 point to rotate + * @param {vec3} b The origin of the rotation + * @param {Number} c The angle of rotation + * @returns {vec3} out + */ + var by = b[1]; + var bz = b[2]; + + // Translate point to the origin + var py = a[1] - by; + var pz = a[2] - bz; + + var sc = Math.sin(c); + var cc = Math.cos(c); + + // perform rotation and translate to correct position + out[0] = a[0]; + out[1] = by + py * cc - pz * sc; + out[2] = bz + py * sc + pz * cc; + + return out; + } + + rotateY(out, a, b, c) { + var bx = b[0]; + var bz = b[2]; + + // translate point to the origin + var px = a[0] - bx; + var pz = a[2] - bz; + + var sc = Math.sin(c); + var cc = Math.cos(c); + + // perform rotation and translate to correct position + out[0] = bx + pz * sc + px * cc; + out[1] = a[1]; + out[2] = bz + pz * cc - px * sc; + + return out; + } + + rotateZ(out, a, b, c) { + var bx = b[0]; + var by = b[1]; + + //Translate point to the origin + var px = a[0] - bx; + var py = a[1] - by; + + var sc = Math.sin(c); + var cc = Math.cos(c); + + // perform rotation and translate to correct position + out[0] = bx + px * cc - py * sc; + out[1] = by + px * sc + py * cc; + out[2] = a[2]; + + return out; + } +} \ No newline at end of file diff --git a/src/character.js b/src/character.js new file mode 100644 index 0000000..d352d4d --- /dev/null +++ b/src/character.js @@ -0,0 +1,6 @@ +export default class Character{ + constructor(_name){ + this.name = _name; + + } +} \ No newline at end of file diff --git a/src/flagManager.js b/src/flagManager.js new file mode 100755 index 0000000..1ac822a --- /dev/null +++ b/src/flagManager.js @@ -0,0 +1,32 @@ +export default class Flagmanager { + constructor() { + this.flags = []; + } + + setFlag(_flagId, _value = true) { + let f = this.getFlagById(_flagId); + if (f === null) { + console.log("creating new flag: " + _flagId) + this.flags.push({ + id: _flagId, + value: _value + }); + } else { + f.value = _value; + } + //console.log(this.flags); + } + + getFlagById(_flagId) { + let r = this.flags.filter((e) => { return e.id === _flagId }); + if (r.length > 0) { + return r[0]; + } else { + return null; + } + } + + removeFlag(_flagId) { + this.flags = this.flags.filter((e) => { return e.id !== _flagId }); + } +} diff --git a/src/hand.js b/src/hand.js new file mode 100755 index 0000000..5c20974 --- /dev/null +++ b/src/hand.js @@ -0,0 +1,210 @@ +export default class Hand { + constructor(_scene) { + this.scene = _scene; + + this.justPressed = false; + this.pressed = false; + this.justReleased = false; + this.pressedTime = 0; + this.releasedTime = 0; + this.lastPressedTime = 0; + this.lastReleasedTime = 0; + + this.mouselock = false; + + this.wheel = 0; + + this.pos = { + x: 0, + y: 0 + } + + this.start = { + x: 0, + y: 0 + } + + this.vel = { + x: 0, + y: 0 + } + this.prev = { + x: 0, + y: 0 + } + + this.scene.input.on("wheel", (_pointer, _gameObjs, _deltaX, _deltaY, _deltaZ) => { + if (_deltaY > 0) { + this.wheel = -1; + } else if (_deltaY < 0) { + this.wheel = 1; + } + }, this); + + this.cursor = this.scene.add.sprite(0, 0, "atlasUi", "sprInteractCursor"); + this.cursor.depth = 10001; + this.cursor.setOrigin(0); + this.showCursor = true; + + this.useControllerMouse = false; + this.scene.input.activePointer.smoothFactor = 1; + } + + update(_delta) { + let gamepad = null; + gamepad = navigator.getGamepads()[Math.max(0, gamepadsConnected - 1)]; + if (gamepad === undefined) { + gamepad = null; + } + //check if using gamepad or mouse + if (gamepad !== null) { + let sra = Math.abs(INPUTS.stickRight.vertical); + let sla = Math.abs(INPUTS.stickLeft.vertical); + if (sra >= 0.2 || sla >= 0.2) { + this.useControllerMouse = true; + } + if (this.scene.data.systems.time.now - this.scene.input.activePointer.moveTime < 60) { + this.useControllerMouse = false; + } + } + + + //move with mouse + if (this.useControllerMouse === false) { + this.pos.x = this.scene.input.activePointer.worldX; + this.pos.y = this.scene.input.activePointer.worldY; + } else { + //give up mosue control + if (this.scene.input.activePointer.worldX !== this.prev.x || this.scene.input.activePointer.worldY !== this.prev.y) { + this.useControllerMouse = false; + console.log("not using controller anymore") + } + } + //or controller if moved the stick + if (gamepadsConnected > 0) { + if (Math.abs(INPUTS.stickRight.horizontal) > 0.1 || Math.abs(INPUTS.stickRight.vertical) > 0.1) { + this.useControllerMouse = true; + //console.log("use controller as mouse") + this.pos.x += Math.abs(INPUTS.stickRight.horizontal) > 0.1 ? INPUTS.stickRight.horizontal * OPTIONS.controls.mouse.sensitivity : 0; + this.pos.y += Math.abs(INPUTS.stickRight.vertical) > 0.1 ? INPUTS.stickRight.vertical * OPTIONS.controls.mouse.sensitivity : 0; + } + if (Math.abs(INPUTS.stickLeft.horizontal) > 0.1 || Math.abs(INPUTS.stickLeft.vertical) > 0.1) { + this.useControllerMouse = true; + //console.log("use controller as mouse") + this.pos.x += Math.abs(INPUTS.stickLeft.horizontal) > 0.1 ? INPUTS.stickLeft.horizontal * OPTIONS.controls.mouse.sensitivity : 0; + this.pos.y += Math.abs(INPUTS.stickLeft.vertical) > 0.1 ? INPUTS.stickLeft.vertical * OPTIONS.controls.mouse.sensitivity : 0; + } + } + + //vel moves the head when mouse cursor is locked + if (this.scene.input.mouse.locked === true) { + //if (this.mouselock === true){ + this.cursor.alpha = 0; + + if (this.scene.data.systems.time.now - this.scene.input.activePointer.moveTime < 60) { + this.vel.x = (this.scene.input.activePointer.movementX / 128) * _delta; + this.vel.y = (this.scene.input.activePointer.movementY / 128) * _delta; + + this.vel.x = Math.max(-1, Math.min(this.vel.x, 1)); + this.vel.y = Math.max(-1, Math.min(this.vel.y, 1)); + } else { + if (gamepadsConnected > 0) { + this.vel.x = Math.abs(INPUTS.stickRight.horizontal) > 0.1 ? INPUTS.stickRight.horizontal : 0; + this.vel.y = Math.abs(INPUTS.stickRight.vertical) > 0.1 ? INPUTS.stickRight.vertical : 0; + } + } + } else { + if (this.showCursor === true) { + this.cursor.alpha = 1; + } else { + this.cursor.alpha = 0; + } + if (gamepadsConnected > 0) { + //was always moving head evenn when not pointer locking + //this.vel.x = Math.abs(INPUTS.stickRight.horizontal) > 0.1 ? INPUTS.stickRight.horizontal : 0; + //this.vel.y = Math.abs(INPUTS.stickRight.vertical) > 0.1 ? INPUTS.stickRight.vertical : 0; + this.pos.x += Math.abs(INPUTS.stickRight.horizontal) > 0.1 ? INPUTS.stickRight.horizontal : 0; + this.pos.y += Math.abs(INPUTS.stickRight.vertical) > 0.1 ? INPUTS.stickRight.vertical : 0; + } + } + + + + this.vel.x *= OPTIONS.controls.mouse.sensitivity; + this.vel.y *= OPTIONS.controls.mouse.sensitivity; + + if (this.scene.input.activePointer.isDown || INPUTS.btnA.pressed) { + if (this.pressed === false) { + this.justPressed = true; + this.pressed = true; + this.justReleased = false; + + this.start.x = this.pos.x; + this.start.y = this.pos.y; + this.lastReleasedTime = this.releasedTime; + } else { + this.justPressed = false; + this.lastReleasedTime = 0; + } + this.pressedTime += 1; + this.releasedTime = 0; + } else { + if (this.pressed === true) { + this.pressed = false; + this.justReleased = true; + this.justPressed = false; + + this.start.x = this.pos.x; + this.start.y = this.pos.y; + this.lastPressedTime = this.pressedTime; + } else { + this.justReleased = false; + this.lastPressedTime = 0; + } + this.pressedTime = 0; + this.releasedTime += 1; + } + + this.pos.x = Math.max(-view.half.width, Math.min(this.pos.x, view.half.width)); + this.pos.y = Math.max(-view.half.height, Math.min(this.pos.y, view.half.height)); + + this.cursor.x = this.pos.x; + this.cursor.y = this.pos.y; + } + + lateUpdate() { + this.vel.x = 0; + this.vel.y = 0; + this.prev.x = this.scene.input.activePointer.worldX; + this.prev.y = this.scene.input.activePointer.worldY; + + this.wheel = 0; + } + + setMouseLock(_bool) { + document.body.style.cursor = 'none'; + /*if(INPUTS.btnA.justReleased){ + this.mouselock = true; + }*/ + + if (isMobile === false) { + this.mouselock = _bool; + if (this.mouselock === true) { + this.scene.input.mouse.requestPointerLock(); + } else { + if (this.scene.input.mouse.locked) { + this.scene.input.mouse.releasePointerLock(); + } + this.useControllerMouse = false; + } + } + } + + setCursorVisibility(_bool = true) { + if (_bool === true) { + this.cursor.alpha = 1; + } else { + this.cursor.alpha = 0; + } + } +} diff --git a/src/inputs.js b/src/inputs.js new file mode 100755 index 0000000..3a03d34 --- /dev/null +++ b/src/inputs.js @@ -0,0 +1,60 @@ +//basic keymapping to be filled and used by eg scn3d so that keyboard and gamepad inputs can be used interchangably +let INPUTS = { + stickLeft: { + name: "stickLeft", + horizontal: 0, + vertical: 0, + asKey: { + up: createMyKey("stickLeftUp"), + down: createMyKey("stickLeftDown"), + right: createMyKey("stickLeftRight"), + left: createMyKey("stickLeftLeft"), + } + }, stickRight: { + name: "stickRight", + horizontal: 0, + vertical: 0, + asKey: { + up: createMyKey("stickRightUp"), + down: createMyKey("stickRightDown"), + right: createMyKey("stickRightRight"), + left: createMyKey("stickRightLeft"), + } + }, triggerLeft: { + name: "triggerLeft", + amount: 0, + askey: createMyKey("virtualTriggerLeft") + }, + triggerRight: { + name: "triggerRight", + amount: 0, + askey: createMyKey("virtualTriggerRight") + }, + btnA: createMyKey("btnA"), + btnB: createMyKey("btnB"), + btnX: createMyKey("btnX"), + btnY: createMyKey("btnY"), + btnStart: createMyKey("btnStart"), + btnPause: createMyKey("btnPause"), + btnShoulderLeft: createMyKey("btnShoulderLeft"), + btnShoulderRight: createMyKey("btnShoulderRight"), + btnTriggerLeft: createMyKey("btnTriggerLeft"), + btnTriggerRight: createMyKey("btnTriggerRight"), + btnUp: createMyKey("btnUp"), + btnDown: createMyKey("btnDown"), + btnLeft: createMyKey("btnLeft"), + btnRight: createMyKey("btnRight"), + btnStickLeft: createMyKey("btnStickLeft"), + btnStickRight: createMyKey("btnStickRight"), +} + +function createMyKey(_name){ + return { + name: _name, + pressed: false, + justPressed: false, + justReleased: false, + pressedTime: 0, + value: 0 + } +} \ No newline at end of file diff --git a/src/librarySounds.js b/src/librarySounds.js new file mode 100755 index 0000000..848a521 --- /dev/null +++ b/src/librarySounds.js @@ -0,0 +1,65 @@ +let SOUNDS = { + mumble: new Howl({ + src: ['./assets/sounds/mumble00.mp3'], + autoplay: false, + loop: true, + volume: 1, + sprite: { + mumble00: [0, 81000], + mumble01: [0, 81000], + mumble02: [0, 81000] + } + }), + athmosEery: new Howl({ + src: ['./assets/sounds/aga_cc0_atmoseerie02.mp3', './assets/sounds/aga_cc0_atmoseerie02.ogg'], + autoplay: false, + loop: true, + volume: 1, + }), + athmosWind: new Howl({ + src: ['./assets/sounds/windFalling00.mp3', './assets/sounds/windFalling00.ogg'], + autoplay: false, + loop: true, + volume: 1, + }), + stepsHallway: new Howl({ + src: ['./assets/sounds/stepsHallwaySprite.mp3', './assets/sounds/stepsHallwaySprite.ogg'], + sprite: { + stepStart: [0, 500], + step0: [501, 1100], + step1: [1101, 1700], + step2: [1701, 2300], + step3: [2301, 2900], + step4: [2901, 3500], + step5: [3501, 4100], + step6: [4101, 4700], + step7: [4701, 5300] + } + }), + hurtFalling: new Howl({ + src: ['./assets/sounds/hurtFalling01Sprite.mp3', './assets/sounds/hurtFalling01Sprite.ogg'], + sprite: { + hurtStart: [0, 1150], + hurt0: [1300, 2450], + hurt1: [2980, 4300], + hurt2: [4410, 5370], + hurtEnd: [6210, 7538] + } + }), + pickPage: new Howl({ + src: ['./assets/sounds/pickPageSprite.mp3', './assets/sounds/pickPageSprite.ogg'], + sprite: { + pick00: [0, 999], + pick01: [1000, 1999], + pick02: [2000, 3999] + } + }), + dropPage: new Howl({ + src: ['./assets/sounds/dropPageSprite.mp3', './assets/sounds/dropPageSprite.ogg'], + sprite: { + drop00: [0, 999], + drop01: [1000, 1999], + drop02: [2000, 3999] + } + }), +} \ No newline at end of file diff --git a/src/preloader.js b/src/preloader.js new file mode 100755 index 0000000..9149fb1 --- /dev/null +++ b/src/preloader.js @@ -0,0 +1,36 @@ +export default function () { + + // Preloader scene + return new Phaser.Class({ + Extends: Phaser.Scene, + initialize: function Preloader() { + Phaser.Scene.call(this, { key: "Preloader" }) + }, + + preload: function () { + //this.load.bitmapFont("segoeUI_16", "./assets/fonts/segoeUI_16.png", "./assets/fonts/segoeUI_16.xml"); + this.load.bitmapFont("uiFont", "./assets/fonts/uiFont01.png", "./assets/fonts/uiFont01.xml"); + this.load.bitmapFont("uiFontOffwhite", "./assets/fonts/uiFont01offwhite.png", "./assets/fonts/uiFont01.xml"); + this.load.bitmapFont("bravenewEra", "./assets/fonts/bravenewEra_16.png", "./assets/fonts/bravenewEra_16.xml"); + this.load.bitmapFont("racer", "./assets/fonts/racer_16.png", "./assets/fonts/racer_16.xml"); + //this.load.bitmapFont("libraryModern", "./assets/fonts/libraryModernAll.png", "./assets/fonts/libraryModernAll.xml"); + //this.load.bitmapFont("libraryOlde", "./assets/fonts/libraryOlde2.png", "./assets/fonts/libraryOlde2.xml"); + //this.load.bitmapFont("medivalPixel", "./assets/fonts/medivalPixel.png", "./assets/fonts/medivalPixel.xml"); + + //this.load.bitmapFont("uiFont00", "./assets/fonts/pixelBlockRounded.png", "./assets/fonts/pixelBlockRounded.xml"); + + this.load.image("sprPixelMan", "./assets/sprites/splashscreen/sprPixelMan.png"); + this.load.spritesheet("sprPixelTurn", "./assets/sprites/splashscreen/sprPixelTurn.png", { frameWidth: 32, frameHeight: 32 }); + }, + + create: function () { + this.cameras.main.setBackgroundColor(0x000000); + this.load.off("progress", this.update_progress_display, this); + + //console.log(this.cache.bitmapFont.get("segoeUI_16")) + //this.cache.bitmapFont.get("segoeUI_16").data.lineHeight = 16; + this.scene.start("ScnLoad"); + } + }) + +} diff --git a/src/racingSounds.js b/src/racingSounds.js new file mode 100755 index 0000000..5cedd1e --- /dev/null +++ b/src/racingSounds.js @@ -0,0 +1,212 @@ +let SOUNDS = { + /*mumble: new Howl({ + src: ['./assets/sounds/mumble00.mp3'], + autoplay: false, + loop: true, + volume: 1, + sprite: { + mumble00: [0, 81000], + mumble01: [0, 81000], + mumble02: [0, 81000] + } + }), + athmosEery: new Howl({ + src: ['./assets/sounds/aga_cc0_atmoseerie02.mp3', './assets/sounds/aga_cc0_atmoseerie02.ogg'], + autoplay: false, + loop: true, + volume: 1, + }), + stepsHallway: new Howl({ + src: ['./assets/sounds/stepsHallwaySprite.mp3', './assets/sounds/stepsHallwaySprite.ogg'], + sprite: { + stepStart: [0, 500], + step0: [501, 1100], + step1: [1101, 1700], + step2: [1701, 2300], + step3: [2301, 2900], + step4: [2901, 3500], + step5: [3501, 4100], + step6: [4101, 4700], + step7: [4701, 5300] + } + }),*/ + shipEngine00: new Howl({ + src: ['./assets/sounds/race/jetengine.mp3', './assets/sounds/race/jetengine.ogg'], + autoplay: false, + loop: true, + volume: 1, + }), + shipEngine01: new Howl({ + src: ['./assets/sounds/race/rotorengine.mp3', './assets/sounds/race/rotorengine.ogg'], + autoplay: false, + loop: true, + volume: 1, + }), + shipScraping: new Howl({ + src: ['./assets/sounds/race/scrapelp.mp3', './assets/sounds/race/scrapelp.ogg'],//INFO is from wipeout do not use! + autoplay: false, + loop: true, + volume: 0.25, + }), + shipHeatWarning: new Howl({ + src: ['./assets/sounds/race/heatWarning.mp3', './assets/sounds/race/heatWarning.ogg'],//INFO is from wipeout do not use! + autoplay: false, + loop: true, + volume: 0.25, + }), + shipBump: new Howl({ + src: ['./assets/sounds/race/bumpSprite.mp3', './assets/sounds/race/bumpSprite.ogg'], + autoplay: false, + loop: false, + volume: 1, + sprite: { + bump0: [0, 999], + bump1: [1000, 1999], + bump2: [2000, 2999] + } + }), + shipSwoosh: new Howl({ + src: ['./assets/sounds/race/swooshSprite.mp3', './assets/sounds/race/swooshSprite.ogg'], + autoplay: false, + loop: false, + volume: 1, + sprite: { + swoosh0: [0, 999], + swoosh1: [1000, 1999], + //swoosh2: [2000, 2999] + } + }), + raceAnnouncer: new Howl({ + src: ['./assets/sounds/race/afSprite.mp3', './assets/sounds/race/afSprite.ogg'], + autoplay: false, + loop: false, + volume: 1, + sprite: { + newRecord: [0, 999], + three: [1000, 1999], + two: [3000, 3999], + one: [4000, 4999], + go: [5000, 5999], + finalLap: [6000, 6999] + } + }), + //fps player sounds + /* + athmosEery: new Howl({ + src: ['./assets/sounds/aga_cc0_atmoseerie02.mp3', './assets/sounds/aga_cc0_atmoseerie02.ogg'], + autoplay: false, + loop: true, + volume: 1, + }), + athmosWind: new Howl({ + src: ['./assets/sounds/windFalling00.mp3', './assets/sounds/windFalling00.ogg'], + autoplay: false, + loop: true, + volume: 1, + }),*/ + stepsHallway: new Howl({ + src: ['./assets/sounds/stepsHallwaySprite.mp3', './assets/sounds/stepsHallwaySprite.ogg'], + sprite: { + stepStart: [0, 500], + step0: [501, 1100], + step1: [1101, 1700], + step2: [1701, 2300], + step3: [2301, 2900], + step4: [2901, 3500], + step5: [3501, 4100], + step6: [4101, 4700], + step7: [4701, 5300] + } + }), + //menu sounds + menuSelect: new Howl({ + src: ['./assets/sounds/menu/select01.mp3', './assets/sounds/menu/select01.ogg'], + autoplay: false, + loop: false, + volume: 1, + }), + menuError: new Howl({ + src: ['./assets/sounds/menu/computerError.mp3', './assets/sounds/menu/computerError.ogg'], + autoplay: false, + loop: false, + volume: 1, + }), + computerStart: new Howl({ + src: ['./assets/sounds/menu/computerStart.mp3', './assets/sounds/menu/computerStart.ogg'], + autoplay: false, + loop: false, + volume: 1, + }), + + //music tracks + musicMenu00: new Howl({ + src: ['./assets/sounds/music/dejavu-Anima160kb.mp3', './assets/sounds/music/dejavu-Anima160kb.ogg'], + autoplay: false, + loop: true, + volume: 1, + }), + musicMenu01: new Howl({ + src: ['./assets/sounds/music/luce20000.mp3', './assets/sounds/music/luce20000.ogg'], + autoplay: false, + loop: true, + volume: 1, + }), + musicAcidLoop00: new Howl({ + src: ['./assets/sounds/music/flowing-acid-loop-354062.mp3', './assets/sounds/music/flowing-acid-loop-354062.ogg'], + autoplay: false, + loop: true, + volume: 1, + }), + musicAcidLoop01: new Howl({ + src: ['./assets/sounds/music/acid-loop-328882.mp3', './assets/sounds/music/acid-loop-328882.ogg'], + autoplay: false, + loop: true, + volume: 1, + }), + musicCalmLoop00: new Howl({ + src: ['./assets/sounds/music/calmLoop00.mp3', './assets/sounds/music/calmLoop00.ogg'], + autoplay: false, + loop: true, + volume: 1, + }), + //music sprite stream + /* + musicBoadicea00: new Howl({ + src: ['./assets/sounds/music/boadicea_sprite.mp3', './assets/sounds/music/boadicea_sprite.ogg'], + autoplay: false, + loop: true, + volume: 1, + sprite: { + bass: [0, 8000], + synth: [10000, 18000], + guitar: [20000, 28000], + piano: [30000, 38000], + shaker: [40000, 48000], + rythm: [50000, 58000], + } + }),*/ + musicBassLoop00: new Howl({ + src: ['./assets/sounds/music/boadicea_bass.mp3', './assets/sounds/music/boadicea_bass.ogg'], + autoplay: false, + loop: true, + volume: 1, + }), + musicSynthLoop00: new Howl({ + src: ['./assets/sounds/music/boadicea_synth.mp3', './assets/sounds/music/boadicea_synth.ogg'], + autoplay: false, + loop: true, + volume: 1, + }), + musicPianoLoop00: new Howl({ + src: ['./assets/sounds/music/boadicea_piano.mp3', './assets/sounds/music/boadicea_piano.ogg'], + autoplay: false, + loop: true, + volume: 1, + }), + musicRythmLoop00: new Howl({ + src: ['./assets/sounds/music/boadicea_rythm.mp3', './assets/sounds/music/boadicea_rythm.ogg'], + autoplay: false, + loop: true, + volume: 1, + }), +} diff --git a/src/scn3d.js b/src/scn3d.js new file mode 100755 index 0000000..2d7f6e7 --- /dev/null +++ b/src/scn3d.js @@ -0,0 +1,2042 @@ +import SoundManager from "./soundManager.js"; +import Hand from "./hand.js"; +import Cam from "./3d/cam.js"; +import GeometryController from "./3d/geometryController.js"; +import Editor from "./3d/editor.js"; +import { Player6dof } from "./3d/player6dof.js"; +//import { Player3d } from "./3d/player3d.js"; +//import { PlayerEuler } from "./3d/playerEuler.js"; + +import PanelWelcome from "./ui/panelWelcome.js"; +import PanelFlavourText from "./ui/panelFlavourText.js"; +import PanelEscapeMenu from "./ui/panelEscapeMenu.js"; + +import LevelMenu3d from "./3d/levels/lvlMenu3d.js"; +import LevelModelbuilder from "./3d/levels/lvlModelbuilder.js"; +import LevelEmpty00 from "./3d/levels/___lvlEmpty.js"; +import LevelQuadRingsTest from "./3d/levels/lvlQuadRingsTest.js"; +import LevelMarketsquareApartements00 from "./3d/levels/lvlMarketsquareApartements00.js"; +import LevelHangar00 from "./3d/levels/lvlHangar00.js"; +import LevelPlayerApartement00 from "./3d/levels/lvlPlayerApartement00.js"; +import LevelDream00 from "./3d/levels/lvlDream00.js"; +import LevelChurch00 from "./3d/levels/lvlChurch00.js"; +import LevelRaceDirectorOffice00 from "./3d/levels/lvlRaceDirectorOffice00.js"; +import Character from "./3d/character.js"; + +export default class Scn3d extends Phaser.Scene { + + constructor() { + super("Scn3d"); + } + + init(_data) { + this.initData = _data; + } + + create() { + //console.log(this); + this.cameras.main.setScroll(-this.game.config.width * 0.5, -this.game.config.height * 0.5); + this.cameras.main.setBackgroundColor(0x000000);//0x131313 + + //load a scenewide savegame to be used in all levels + this.saveGame = JSON.parse(localStorage.getItem(SAVEGAMENAME)); + + this.debugTxt = this.add.bitmapText(0, this.game.config.height * 0.4, "uiFont", "", 14, 1).setOrigin(0.5).setLetterSpacing(0); + //this.debugTxt.setText("Hello, my friend - I searched and longed so long for you!\nMultiline MULTILINE 16"); + + this.cameras.main.fadeFrom(500, 0, 0, 0, false, (_cam, _pct) => { + + }, this); + + this.left = this.game.config.width * -0.5; + this.right = this.game.config.width * 0.5; + this.top = this.game.config.height * -0.5; + this.bottom = this.game.config.height * 0.5; + + this.cursors = this.input.keyboard.createCursorKeys(); + this.keys = { + e: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.E), + q: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Q), + w: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W), + a: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A), + s: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S), + d: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D), + g: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.G), + n: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.N), + m: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.M), + t: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.T), + c: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.C), + v: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.V), + y: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Y), + x: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.X), + z: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Z), + u: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.U), + i: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.I), + o: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.O), + p: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.P), + j: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.J), + k: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.K), + l: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.L), + space: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE), + ctrl: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.CTRL), + shift: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SHIFT), + alt: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.ALT), + end: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.END), + insert: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.INSERT), + del: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.DELETE), + one: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.ONE), + two: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.TWO), + three: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.THREE), + four: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.FOUR), + five: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.FIVE), + six: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SIX), + seven: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SEVEN), + eight: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.EIGHT), + nine: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.NINE), + zero: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.ZERO), + tab: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.TAB), + enter: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.ENTER), + escape: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.ESC), + backspace: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.BACKSPACE), + comma: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.COMMA), + period: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.PERIOD), + } + this.numkeys = { + plus: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.NUMPAD_ADD), + minus: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.NUMPAD_SUBTRACT), + multiply: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.NUMPAD_MULTIPLY), + divide: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.NUMPAD_DIVIDE), + one: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.NUMPAD_ONE), + two: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.NUMPAD_TWO), + three: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.NUMPAD_THREE), + four: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.NUMPAD_FOUR), + five: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.NUMPAD_FIVE), + six: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.NUMPAD_SIX), + seven: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.NUMPAD_SEVEN), + eight: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.NUMPAD_EIGHT), + nine: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.NUMPAD_NINE), + zero: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.NUMPAD_ZERO) + } + + this.rando = new Phaser.Math.RandomDataGenerator("libraryofbabel"); + //this.rando.rnd(); + this.paused = false; + + this.hand = new Hand(this); + if (this.initData.level !== "modelBuilder") { + //make sure to only activate if level does start without panel + //this.hand.setMouseLock(true); + } + + this.soundManager = new SoundManager(this); + + this.playerGame = new Player6dof(this, "shipPlayer"); + this.playerWalk = new Player6dof(this, "fpsPlayer"); + this.playerWalk.useFpsBody = true; + this.playerWalk.dir.spd.pitch *= 0.5; + //this.playerWalk.setVisibility(true); + this.playerEditor = new Player6dof(this, "editorPlayer"); + this.player = this.playerGame; + this.player.pos.x = 0; + this.player.pos.y = 0; + this.player.pos.z = 0; + + this.teams = { + unknown: { + asset: "radioactive04", + atlas: "atlasAdverts", + shipModel: "modHoverCarTinnemann00", + color: "Yellow", + text: "" + }, arashi: { + asset: "sprLogoArashi", + atlas: "atlasAdverts", + shipModel: "modHoverCarWipeOutStyle", + color: "Red", + text: "The Arashi Corporation is a thin shadow of its former self. Once a leader in microchip technology and tunneling and mining, it was dismantled and bought up by more powerful corporations. Nowadays it only lives as a small racing team, with pride but without much financial resources.", + }, daito: { + asset: "sprLogoDaito", + atlas: "atlasAdverts", + shipModel: "modHoverCarF1", + color: "Yellow", + text: "Daito are unattainably elegant, fast and rich. They're actually just taking part in Formula Zero for fun to pass the time underground as they are coming from a control district. However, they enjoy humiliating the other drivers.", + }, tinnemann: { + asset: "sprLogoTinnemann", + atlas: "atlasAdverts", + shipModel: "modHoverCarTinnemann00", + color: "Blue", + text: "In principle, Tinnemann only drives in one direction: straight ahead. They are the bullies of the track. The Tinnemann Group is run in an extremely authoritarian manner and the residents of this district are used to being able to obtain small amenities only through sheer force. Anyone who doesn't move out of their path will be pushed out of their way.", + }, hampton: { + asset: "sprLogoHapton", + atlas: "atlasAdverts", + shipModel: "modHoverCarHapton00", + color: "Green", + text: "Hampton Systems manufactured tanks in the great war, then the scavenging vehicles and finally the tunneling machines. Now they are converting their powerful machines into equally powerful racing vehicles. War may change, but good machining does not...", + }, wienerblut: { + asset: "sprLogoHapton", + atlas: "atlasAdverts", + shipModel: "modHoverCarTinnemann00", + color: "Red", + text: "Wiener Blut, still working in the burial business and always making sure, there is someone to put underground.", + } + } + + this.characters = [ + new Character(this, "Roki", { + atlas: "charSheetExpressions", + angry: ["rokiExpressionAngry00", "rokiExpressionAngry01", "rokiExpressionAngry02", "rokiExpressionAngry03", "rokiExpressionNormal04", "rokiExpressionOuch02"], + normal: [], + thinking: ["rokiExpressionThinking00", "rokiExpressionThinking01"], + hit: ["rokiExpressionOuch00", "rokiExpressionOuch01", "rokiExpressionAngry02", "rokiExpressionOuch03"], + haha: ["rokiExpressionHaha00", "rokiExpressionHaha01", "rokiExpressionHaha02", "rokiExpressionHaha03", "rokiExpressionHaha04", "rokiExpressionHappy00", "rokiExpressionHappy01"], + taunt: ["rokiExpressionHappy02", "rokiExpressionHaha01"], + cheer: ["rokiExpressionHappy02", "rokiExpressionHappy01", "rokiExpressionHaha01", "rokiExpressionHaha00"] + }, "charSheetRoki", "rokiStandIdle000", this.teams.arashi), + new Character(this, "Bonez", { + atlas: "charSheetExpressions", + angry: ["bonezExpressionAngry00", "bonezExpressionAngry01"], + normal: [], + thinking: ["bonezExpressionHappy00"], + hit: ["bonezExpressionOuch00", "bonezExpressionOuch01", "bonezExpressionOuch02"], + haha: ["bonezExpressionHaha00", "bonezExpressionHaha01"], + taunt: ["bonezExpressionHaha00", "bonezExpressionAngry01"], + cheer: ["bonezExpressionHaha00", "bonezExpressionHaha01"] + }, "charSheetBonez", "bonezStandIdle0", this.teams.tinnemann), + new Character(this, "Foxxy", { + atlas: "charSheetExpressions", + angry: ["foxxyExpressionAngry00", "foxxyExpressionAngry01"], + normal: [], + thinking: ["foxxyExpressionOuch02"], + hit: ["foxxyExpressionOuch00", "foxxyExpressionOuch01", "foxxyExpressionOuch02"], + haha: ["foxxyExpressionHaha00", "foxxyExpressionHappy00"], + taunt: ["foxxyExpressionHaha00", "foxxyExpressionHappy02"], + cheer: ["foxxyExpressionHappy01", "foxxyExpressionHaha00"] + }, "charSheetFoxxy", "foxxyStandIdle000", this.teams.daito), + new Character(this, "Glaze", { + atlas: "charSheetExpressions", + angry: ["javiExpressionNormal00", "javiExpressionSad01"], + normal: [], + thinking: ["javiExpressionThink00"], + hit: ["javiExpressionSad00", "javiExpressionSad01", "javiExpressionThink00", "javiExpressionThink01"], + haha: ["javiExpressionHappy02", "javiExpressionHaha00", "javiExpressionHappy00"], + taunt: ["javiExpressionHappy02", "javiExpressionNormal01"], + cheer: ["javiExpressionHappy01", "javiExpressionHaha00"] + }, "charSheetGlaze", "glazeStandIdle000", this.teams.daito), + new Character(this, "Hog", { + atlas: "charSheetExpressions", + angry: ["hogExpressionAngry00", "hogExpressionAngry01"], + normal: [], + thinking: ["hogExpressionHappy00", "hogExpressionAngry00"], + hit: ["hogExpressionOuch00", "hogExpressionOuch01"], + haha: ["hogExpressionHappy00", "hogExpressionHappy01"], + taunt: ["hogExpressionAngry00", "hogExpressionAngry01", "hogExpressionHaha00"], + cheer: ["hogExpressionHappy00", "hogExpressionHappy01", "hogExpressionHaha00"] + }, "charSheetHog", "hogStandIdle000", this.teams.tinnemann), + new Character(this, "Roach", { + atlas: "charSheetExpressions", + angry: ["rahyExpressionAngry00", "rahyExpressionAngry01"], + normal: [], + thinking: ["rahyExpressionHappy01", "rahyExpressionAngry01", "rahyExpressionAngry00"], + hit: ["rahyExpressionOuch00", "rahyExpressionOuch01", "rahyExpressionOuch02"], + haha: ["rahyExpressionHaha00", "rahyExpressionHaha01", "rahyExpressionHaha02"], + taunt: ["rahyExpressionHaha00", "rahyExpressionAngry01", "rahyExpressionHaha01", "rahyExpressionHaha02"], + cheer: ["rahyExpressionHappy00", "rahyExpressionHappy01"] + }, "charSheetRahy", "rahyStandIdle0", this.teams.hampton), + new Character(this, "Scooter", { + atlas: "charSheetExpressions", + angry: ["scooterExpressionAngry00", "scooterExpressionOuch00"], + normal: [], + thinking: ["scooterExpressionOuch00"], + hit: ["scooterExpressionOuch00", "scooterExpressionAngry00"], + haha: ["scooterExpressionHaha02", "scooterExpressionHappy00", "scooterExpressionHaha00"], + taunt: ["scooterExpressionAngry00", "scooterExpressionHaha02", "scooterExpressionHaha01"], + cheer: ["scooterExpressionHappy00", "scooterExpressionHaha01"] + }, "charSheetScooter", "hannahStandIdle0", this.teams.hampton), + new Character(this, "Jay", { + atlas: "charSheetExpressions", + angry: ["jayExpressionAngry00", "jayExpressionAngry01", "jayExpressionAngry02"], + normal: [], + thinking: ["jayExpressionThinking00", "jayExpressionThinking01", "jayExpressionThinking02", "jayExpressionThinking03"], + hit: ["jayExpressionAngry02", "jayExpressionThinking00", "jayExpressionThinking01", "jayExpressionAngry00"], + haha: ["jayExpressionHappy01", "jayExpressionHaHa00", "jayExpressionHaha01", "jayExpressionHappy00"], + taunt: ["jayExpressionThinking03", "jayExpressionHaHa00", "jayExpressionHappy01"], + cheer: ["jayExpressionHaha01", "jayExpressionHappy00", "jayExpressionHappy01"] + }, "charSheetJay", "jayStandIdle000", this.teams.wienerblut), + new Character(this, "Jo", { + atlas: "charSheetExpressions", + angry: ["joExpressionOuch02", "joExpressionNormal01", "joExpressionNormal00"], + normal: [], + thinking: ["joExpressionNormal00", "joExpressionNormal01"], + hit: ["joExpressionNormal00", "joExpressionOuch00", "joExpressionOuch01", "joExpressionOuch02"], + haha: ["joExpressionHaha00", "joExpressionHaha01", "joExpressionHaha02"], + taunt: ["joExpressionHaha00", "joExpressionHaha01", "joExpressionHappy00"], + cheer: ["joExpressionHaha00", "joExpressionHaha02"] + }, "charSheetJo", "joStandIdle000", this.teams.wienerblut), + new Character(this, "Director", null, "charSheetRaceDirector", "paulStandIdle000", this.teams.unknown), + new Character(this, "Josef", null, "charSheetJosef", "josefStandIdle000", this.teams.unknown), + new Character(this, "Joe", null, "charSheetRahyMechanic", "rahyMechanicSitIdle010", this.teams.unknown), + new Character(this, "Booker", null, "charSheetBooker", "bookerStandIdle010", this.teams.unknown), + new Character(this, "Guard 1", null, "charSheetMaleguard", "maleguardStandIdle000", this.teams.unknown) + ]; + + this.characters[8].locked = true; + this.characters[9].locked = true; + + + this.editor = new Editor(this); + + this.camGame = new Cam(this); + this.camWalk = new Cam(this); + this.camEditor = new Cam(this); + this.cam = this.camGame; + this.geometryController = new GeometryController(this); + + + //test move cam zoom + /* + this.input.on("wheel", (_pointer, _gameObjs, _deltaX, _deltaY, _deltaZ) => { + if (_deltaY > 0) { + this.cam.zoom *= (0.95); + //this.cam.fov -= 0.5; + } else if (_deltaY < 0) { + this.cam.zoom *= (1 / 0.95); + //this.cam.fov += 0.5; + } + }, this); + */ + + //currently broken + /* + this.drawNo3d = false; + this.keys.o.on("up", (_key, _event) => { + this.drawNo3d = !this.drawNo3d; + for (let m of this.geometryController.models){ + if(this.drawNo3d === true){ + m.debug.mode = DRAWMODE.NOSCALE2D; + //m.debug.drawCollisions = true; + }else{ + m.debug.mode = 0; + //m.debug.drawCollisions = false; + } + } + }, this); + */ + + + + + this.modelName = ""; + //this.debugTxt = this.add.bitmapText((this.game.config.width * -0.5) + 16, (this.game.config.height * -0.5) + 16, "uiFont", "TEST Test test 00 gbqrSX5s", 16, 1).setOrigin(0).setLetterSpacing(1); + this.dt = 1; + this.offFrame = false; + this.quartFrame = 0; + this.quartFrameCum = 0; + this.quartJustChanged = true; + + //version text (currently demo) + this.versionTxt = this.add.bitmapText((this.game.config.width * 0.5) - 4, (this.game.config.height * 0.5) - 4, "uiFont", "demo v1.0", 14, 0).setOrigin(1, 1).setLetterSpacing(0); + this.versionTxt.depth = 99000; + + /* + unused old technique to find out how much delta needs to be modified to be independent from hz, but needs manual herz input by the player + this.deltaAdapter = { + interval: null, + last: 0, + current: 0, + pulse: 0, + pulseCorrection: 60, + hertzCorrection: 1 + } + this.deltaAdapter.interval = setInterval(() => { + //console.log(this.deltaAdapter.pulseCorrection); + this.deltaAdapter.pulseCorrection = this.deltaAdapter.pulse; + this.deltaAdapter.hertzCorrection = this.deltaAdapter.pulseCorrection / 60; + this.deltaAdapter.pulse = 0; + this.deltaAdapter.last = this.deltaAdapter.current; + this.deltaAdapter.current = Date.now(); + this.deltaAdapter.diff = this.deltaAdapter.current - this.deltaAdapter.last; + }, 1000); + */ + + //this.millis = 0; + //this.lastTime = 0; + + this.loadOptions(); + + //console.log(this.initData); + this.level = null; + this.loadLevel(this.initData.level, this.initData.params); + } + + update(_time, _delta) { + /* + // this is as accutate as _delta / 1000; so actually it should see if its 8 or 16 to get the hertz change + this.lastTime = this.millis; + this.millis = Date.now(); + console.log(((this.millis - this.lastTime) / 1000)); + console.log(_delta); + console.log("-------") + */ + + //console.log(_time, _delta) + //this.deltaAdapter.pulse += 1; + //TODO: hertzCorrection does not work and would still needs target herz to be input manually instead of calculating it somehow + //this.dt = (_delta * 0.1) / this.deltaAdapter.hertzCorrection; + + //TODO 60hz=16 120hz=8 + let adpt = _delta / 16; + /*if(this.paused === true){ + console.log(_delta.toFixed(4), adpt.toFixed(4)) + }*/ + this.dt = (_delta / adpt) * 0.1; + + this.dt = _delta * 0.1; + + this.offFrame = !this.offFrame; + //tick and use quartJustChanged for stuff that only needs to calculate or render every X frame + if (this.quartJustChanged === true) { + this.quartJustChanged = false; + } + this.quartFrameCum += this.dt; + if (this.quartFrameCum >= 16) { + this.quartFrameCum -= 16; + this.quartJustChanged = true; + } + //this.quartFrame = Math.floor(this.quartFrameCum); + + /* + ///calculating my own delta time + time = now(); + delta = time - previousTime; + previousTime = time; + fps = 1000/delta; + increment = 60/fps; + */ + + this.soundManager.update(_delta) + + if (this.player === this.playerGame) { + this.fillInputsForShipControlNoBox();//not xbox controller = NoBox + } else { + this.fillInputsNoBox(); + } + this.hand.update(_delta); + + if (this.editor.enabled === true) { + this.editorControls6dof(); + this.editor.update(); + } else { + + if (this.player === this.playerGame) { + //just listen to "player" while controlling ship + if (this.player.mode === PLAYERMODE.LOOK) { + this.player.gameControls6dof(); + } + } + if (this.player === this.playerWalk) { + if (this.player.mode === PLAYERMODE.LOOK) { + this.player.gameControlsFps(); + } else if (this.player.mode === PLAYERMODE.DIALOGUE) { + //player head can be moved by chacking and modifying player.dir + this.player.lookAt(this.player.lookTarget); + } + + //experimental IMPORTANT + if (this.keys.escape.isDown || INPUTS.btnStart.justPressed) { + if (this.player.panel === null) { + //todo: fix auto clicking on back when it was oopen once and the mosue is still on the back button position (locked) + /*if(this.scene.input.mouse.locked === true){ + this.scene.hand.setMouseLock(false); + }*/ + //todo it must not trigger in menu and other unwanted situations + + this.player.hideUI(); + this.player.setMode(PLAYERMODE.INTERACT); + this.player.panel = new PanelEscapeMenu(this, this.level, 0, true); + + this.paused = true; + } + } + + } + + } + + this.cam.update(); + if (this.player.mode !== PLAYERMODE.CUTSCENE) { + if (this.player === this.playerWalk) { + this.cam.setPositionAndRotation({ x: this.player.pos.x, y: this.player.pos.y - this.player.eyeHeight, z: this.player.pos.z }, this.player.dir); + } else { + let deltaPos = { + x: (this.cam.pos.x - this.player.pos.x) * this.dt, + y: (this.cam.pos.y - this.player.pos.y) * this.dt, + z: (this.cam.pos.z - this.player.pos.z) * this.dt, + } + this.cam.setPositionAndRotation({ x: this.player.pos.x + (deltaPos.x * 0.1), y: this.player.pos.y + (deltaPos.y * 0.1), z: this.player.pos.z + (deltaPos.z * 0.1) }, this.player.dir); + } + } + + this.player.update(_delta); + if (this.paused === false) { + this.level.update(_delta); + } + + //this.geometryController.draw(this.cam.pos, this.cam.dir); + + /* + let totrans = gl_rvaa.AIOquatCreateFromAngleAxis(this.cam.transform.up.x, this.cam.transform.up.y, this.cam.transform.up.z, 0.01) + gl_rvaa.AIOquatmultiply(this.cam.transform.rotationQuat, this.cam.transform.rotationQuat, totrans) + let rotMatrix = gl_rvaa.AIOmat3create() + gl_rvaa.AIOmat3fromQuat(rotMatrix, this.cam.transform.rotationQuat) + this.geometryController.drawFromMatrix(this.cam.pos, rotMatrix); + this.cam.transform.resetRotationQuat(); + */ + /* + //draw from matrix + let rotMatrix = gl_rvaa.AIOmat3create() + gl_rvaa.AIOmat3fromQuat(rotMatrix, curAxisQuat) + this.geometryController.drawFromMatrix(this.cam.pos, rotMatrix); + */ + + //let targetRot = [0, 0, 0, 0]; + //targetRot = gl_quat.rotationTo(targetRot, this.cam.transform.toVectorArray( this.cam.transform.up), this.cam.transform.toVectorArray( this.cam.transform.prev.up) ) + //let rot = [0, 0, 0, 0]; + //rot = gl_quat.slerp(rot, this.gondula.transform.rotationQuat, targetRot, 0.1); + //this.cam.rotateByQuaternion(targetRot); + + let curAxisQuat = gl_quat.create(); + curAxisQuat = gl_quat.setAxes( + curAxisQuat, + //this.cam.transform.toVectorArray(this.cam.transform.forward), + //this.cam.transform.toVectorArray(this.cam.transform.right), + //this.cam.transform.toVectorArray(this.cam.transform.up) + [this.cam.transform.forward.x * -1, this.cam.transform.forward.y * -1, this.cam.transform.forward.z * -1], + [this.cam.transform.right.x * 1, this.cam.transform.right.y * 1, this.cam.transform.right.z * 1], + [this.cam.transform.up.x * -1, this.cam.transform.up.y * -1, this.cam.transform.up.z * -1], + ); + //todo: maybe maybe slerp the camera rotation + /* + let preAxisQuat = gl_quat.create(); + preAxisQuat = gl_quat.setAxes( + preAxisQuat, + //this.cam.transform.toVectorArray(this.cam.transform.forward), + //this.cam.transform.toVectorArray(this.cam.transform.right), + //this.cam.transform.toVectorArray(this.cam.transform.up) + [this.cam.transform.prev.forward.x * -1, this.cam.transform.prev.forward.y * -1, this.cam.transform.prev.forward.z * -1], + [this.cam.transform.prev.right.x * 1, this.cam.transform.prev.right.y * 1, this.cam.transform.prev.right.z * 1], + [this.cam.transform.prev.up.x * -1, this.cam.transform.prev.up.y * -1, this.cam.transform.prev.up.z * -1], + ); + let rotQuat = [0, 0, 0, 0]; + rotQuat = gl_quat.slerp(rotQuat, preAxisQuat, curAxisQuat, 0.01); + */ + + //draw from quat + this.geometryController.drawFromQuat(this.cam.pos, curAxisQuat); + + this.cam.transform.saveCurrentAxisToPrev(); + + + + this.hand.lateUpdate(); + } + + save() { + localStorage.setItem(SAVEGAMENAME, JSON.stringify(this.saveGame)); + } + + saveOptions() { + this.saveGame.sound.master = OPTIONS.sound.master; + this.saveGame.sound.music = OPTIONS.sound.music; + this.saveGame.sound.sfx = OPTIONS.sound.sfx; + this.saveGame.sound.speech = OPTIONS.sound.speech; + this.saveGame.sound.mute = OPTIONS.sound.mute; + + this.saveGame.effects.screenshake = OPTIONS.effects.screenshake; + this.saveGame.effects.shaders = OPTIONS.effects.shaders; + + this.saveGame.controls.mouse.sensitivity = OPTIONS.controls.mouse.sensitivity; + + this.save(); + } + + loadOptions() { + OPTIONS.sound.master = this.saveGame.sound.master; + OPTIONS.sound.music = this.saveGame.sound.music; + OPTIONS.sound.sfx = this.saveGame.sound.sfx; + OPTIONS.sound.speech = this.saveGame.sound.speech; + OPTIONS.sound.mute = this.saveGame.sound.mute; + + for (let s of this.soundManager.soundRef) { + s.howlGroup.volume(OPTIONS.sound.sfx); + } + for (let s of this.soundManager.musicRef) { + s.howlGroup.volume(OPTIONS.sound.music); + } + Howler.volume(OPTIONS.sound.master); + + OPTIONS.effects.screenshake = this.saveGame.effects.screenshake; + OPTIONS.effects.shaders = this.saveGame.effects.shaders; + + OPTIONS.controls.mouse.sensitivity = this.saveGame.controls.mouse.sensitivity; + } + + editorControls6dof() { + if (this.hand.justReleased) { + let hits = []; + hits = this.geometryController.getQuadsFromScreenspaceAt(this.input.activePointer.worldX, this.input.activePointer.worldY, this.editor.editCollisions); + if (hits.length > 0) { + hits = hits.sort((a, b) => a.depth - b.depth); + this.editor.quad = hits[hits.length - 1]; + + this.editor.model = this.geometryController.getModelById(this.editor.quad.modelId); + //console.log(this.editor.model); + } + } + + //camera controls + let toDir = { + yaw: 0, + pitch: 0, + roll: 0 + } + if (this.cursors.up.isDown) { + toDir.pitch += this.player.dir.spd.pitch; + } + if (this.cursors.down.isDown) { + toDir.pitch -= this.player.dir.spd.pitch; + } + if (this.cursors.right.isDown) { + if (this.keys.q.isDown) { + toDir.roll -= this.player.dir.spd.roll; + } else { + toDir.yaw -= this.player.dir.spd.yaw; + } + } + if (this.cursors.left.isDown) { + if (this.keys.q.isDown) { + toDir.roll += this.player.dir.spd.roll; + } else { + toDir.yaw += this.player.dir.spd.yaw; + } + } + this.player.rotateAroundAxis(this.player.transform.toVectorArray(this.player.transform.up), toDir.yaw * -1); + + this.cam.rotateAroundAxis(this.cam.transform.toVectorArray(this.player.transform.up), toDir.yaw * -1); + this.cam.rotateAroundAxis(this.cam.transform.toVectorArray(this.player.transform.right), toDir.pitch); + this.cam.rotateAroundAxis(this.cam.transform.toVectorArray(this.cam.transform.forward), toDir.roll); + + this.player.transform.up.x = 0; + this.player.transform.up.y = -1; + this.player.transform.up.z = 0; + + + let spd = 3; + if (this.keys.a.isDown) { + this.player.pos.x += this.player.transform.right.x * -spd; + this.player.pos.y += this.player.transform.right.y * -spd; + this.player.pos.z += this.player.transform.right.z * -spd; + } + if (this.keys.d.isDown) { + this.player.pos.x += this.player.transform.right.x * spd; + this.player.pos.y += this.player.transform.right.y * spd; + this.player.pos.z += this.player.transform.right.z * spd; + } + if (this.keys.s.isDown) { + this.player.pos.x += this.player.transform.forward.x * -spd; + this.player.pos.y += this.player.transform.forward.y * -spd; + this.player.pos.z += this.player.transform.forward.z * -spd; + } + if (this.keys.w.isDown) { + this.player.pos.x += this.player.transform.forward.x * spd; + this.player.pos.y += this.player.transform.forward.y * spd; + this.player.pos.z += this.player.transform.forward.z * spd; + } + + if (this.keys.space.isDown) { + this.player.pos.x += this.player.transform.up.x * spd; + this.player.pos.y += this.player.transform.up.y * spd; + this.player.pos.z += this.player.transform.up.z * spd; + } + if (this.keys.c.isDown) { + this.player.pos.x += this.player.transform.up.x * -spd; + this.player.pos.y += this.player.transform.up.y * -spd; + this.player.pos.z += this.player.transform.up.z * -spd; + } + } + + editorControls() { + if (this.hand.justReleased) { + let hits = []; + hits = this.geometryController.getQuadsFromScreenspaceAt(this.input.activePointer.worldX, this.input.activePointer.worldY, this.editor.editCollisions); + if (hits.length > 0) { + hits = hits.sort((a, b) => a.depth - b.depth); + this.editor.quad = hits[hits.length - 1]; + + this.editor.model = this.geometryController.getModelById(this.editor.quad.modelId); + //console.log(this.editor.model); + } + } + + //camera controls + this.keyboardLook(); + + if (this.keys.a.isDown) { + this.player.pos.z -= Math.cos(this.player.dir.yaw - HALFPI) * 2;//all move was spd 1 + this.player.pos.x += Math.sin(this.player.dir.yaw - HALFPI) * 2; + } + if (this.keys.d.isDown) { + this.player.pos.z -= Math.cos(this.player.dir.yaw + HALFPI) * 2; + this.player.pos.x += Math.sin(this.player.dir.yaw + HALFPI) * 2; + } + if (this.keys.s.isDown) { + this.player.pos.z -= Math.cos(this.player.dir.yaw) * 3; + this.player.pos.x += Math.sin(this.player.dir.yaw) * 3; + } + if (this.keys.w.isDown) { + this.player.pos.z += Math.cos(this.player.dir.yaw) * 3; + this.player.pos.x -= Math.sin(this.player.dir.yaw) * 3; + } + + if (this.keys.space.isDown) { + this.player.pos.y -= 1; + } + if (this.keys.c.isDown) { + this.player.pos.y += 1; + } + } + + keyboardLook() { + if (this.cursors.up.isDown) { + this.player.dir.pitch += this.player.dir.spd.pitch; + } + if (this.cursors.down.isDown) { + this.player.dir.pitch -= this.player.dir.spd.pitch; + } + if (this.cursors.right.isDown) { + if (this.keys.q.isDown) { + this.player.dir.roll -= this.player.dir.spd.roll; + } else { + this.player.dir.yaw -= this.player.dir.spd.yaw; + } + } + if (this.cursors.left.isDown) { + if (this.keys.q.isDown) { + this.player.dir.roll += this.player.dir.spd.roll; + } else { + this.player.dir.yaw += this.player.dir.spd.yaw; + } + } + } + + loadLevel(_name, _params = null) { + this.unloadLevel(); + switch (_name) { + case "mainMenu": + this.level = new LevelMenu3d(this, _params); + break; + case "modelBuilder": + this.level = new LevelModelbuilder(this, _params); + break; + case "empty": + this.level = new LevelEmpty00(this, _params); + break; + case "dream00": + this.level = new LevelDream00(this, _params); + break; + case "quadRingsTest": + this.level = new LevelQuadRingsTest(this, _params); + break; + case "playerApartement00": + this.level = new LevelPlayerApartement00(this, _params); + break; + case "marketSquareApartements00": + this.level = new LevelMarketsquareApartements00(this, _params); + break; + case "hangar00": + this.level = new LevelHangar00(this, _params); + break; + case "hangar01": + this.level = new LevelHangar01(this, _params); + break; + case "church00": + this.level = new LevelChurch00(this, _params); + break; + case "office00": + this.level = new LevelRaceDirectorOffice00(this, _params); + break; + default: + break; + } + } + + unloadLevel() { + if (this.level !== null) { + this.geometryController.destroyModels(); + this.level.destroy(); + this.level = null; + } + } + + gotoMenu() { + this.scene.start("ScnMain"); + } + + //my wonky no xbox controller fill + fillInputsForShipControlNoBox() { + let gamepad = null; + gamepad = navigator.getGamepads()[Math.max(0, gamepadsConnected - 1)]; + if (gamepad === undefined) { + gamepad = null; + } + + //FORWARDS-BACKWARDDS (unused in ship) - except nose pitching + INPUTS.stickLeft.vertical = 0; + INPUTS.stickLeft.horizontal = 0; + INPUTS.triggerRight.amount = 0; + INPUTS.triggerLeft.amount = 0; + if (this.keys.w.isDown || this.cursors.up.isDown) { + INPUTS.triggerRight.amount = 1; + } else if (this.keys.s.isDown || this.cursors.down.isDown) { + INPUTS.triggerLeft.amount = 1; + } else { + if (gamepad !== null) { + //INPUTS.triggerRight.amount = (gamepad.buttons[7].value + 1) * 0.5; + //INPUTS.triggerLeft.amount = (gamepad.buttons[6].value + 1) * 0.5; + INPUTS.triggerRight.amount = gamepad.buttons[7].value + INPUTS.triggerLeft.amount = gamepad.buttons[6].value + } + } + if (gamepad !== null) { + INPUTS.stickLeft.vertical = gamepad.axes[1]; + } + //STRAFE / ROLL + if (this.keys.a.isDown || this.cursors.left.isDown) { + INPUTS.stickLeft.horizontal = -1; + } else if (this.keys.d.isDown || this.cursors.right.isDown) { + INPUTS.stickLeft.horizontal = 1; + } else { + if (gamepad !== null) { + INPUTS.stickLeft.horizontal = gamepad.axes[0]; + } + } + //LOOK UP-DOWN + INPUTS.stickRight.vertical = 0; + INPUTS.stickRight.horizontal = 0; + if (this.keys.i.isDown) { + INPUTS.stickRight.vertical = -1; + } else if (this.keys.k.isDown) { + INPUTS.stickRight.vertical = 1; + } else { + if (gamepad !== null) { + INPUTS.stickRight.vertical = gamepad.axes[3]; + } + } + //LOOK LEFT-RIGHT + if (this.keys.l.isDown) { + INPUTS.stickRight.horizontal = -1; + } else if (this.keys.j.isDown) { + INPUTS.stickRight.horizontal = 1; + } else { + if (gamepad !== null) { + INPUTS.stickRight.horizontal = gamepad.axes[2]; + } + } + //SCORE / info formerly tab + if (this.keys.tab.isDown || (gamepad !== null ? gamepad.buttons[4].pressed : false)) { + if (INPUTS.btnShoulderLeft.pressed === false) { + INPUTS.btnShoulderLeft.justPressed = true; + INPUTS.btnShoulderLeft.pressed = true; + INPUTS.btnShoulderLeft.justReleased = false; + } else { + INPUTS.btnShoulderLeft.justPressed = false; + } + } else { + if (INPUTS.btnShoulderLeft.pressed === true) { + INPUTS.btnShoulderLeft.pressed = false; + INPUTS.btnShoulderLeft.justReleased = true; + INPUTS.btnShoulderLeft.justPressed = false; + } else { + INPUTS.btnShoulderLeft.justReleased = false; + } + } + //JUMP wiss ma noch nicht + if (this.keys.space.isDown || (gamepad !== null ? gamepad.buttons[5].pressed : false)) { + if (INPUTS.btnShoulderRight.pressed === false) { + INPUTS.btnShoulderRight.justPressed = true; + INPUTS.btnShoulderRight.pressed = true; + INPUTS.btnShoulderRight.justReleased = false; + } else { + INPUTS.btnShoulderRight.justPressed = false; + } + } else { + if (INPUTS.btnShoulderRight.pressed === true) { + INPUTS.btnShoulderRight.pressed = false; + INPUTS.btnShoulderRight.justReleased = true; + INPUTS.btnShoulderRight.justPressed = false; + } else { + INPUTS.btnShoulderRight.justReleased = false; + } + } + //SPRINT wiss ma noch nicht + if (this.keys.s.isDown || (gamepad !== null ? (gamepad.buttons[6].value > 0.1) : false)) { + if (INPUTS.btnTriggerLeft.pressed === false) { + INPUTS.btnTriggerLeft.justPressed = true; + INPUTS.btnTriggerLeft.pressed = true; + INPUTS.btnTriggerLeft.justReleased = false; + } else { + INPUTS.btnTriggerLeft.justPressed = false; + } + } else { + if (INPUTS.btnTriggerLeft.pressed === true) { + INPUTS.btnTriggerLeft.pressed = false; + INPUTS.btnTriggerLeft.justReleased = true; + INPUTS.btnTriggerLeft.justPressed = false; + } else { + INPUTS.btnTriggerLeft.justReleased = false; + } + } + // + if (this.keys.w.isDown || (gamepad !== null ? (gamepad.buttons[7].value > 0.1) : false)) { + if (INPUTS.btnTriggerRight.pressed === false) { + INPUTS.btnTriggerRight.justPressed = true; + INPUTS.btnTriggerRight.pressed = true; + INPUTS.btnTriggerRight.justReleased = false; + } else { + INPUTS.btnTriggerRight.justPressed = false; + } + } else { + if (INPUTS.btnTriggerRight.pressed === true) { + INPUTS.btnTriggerRight.pressed = false; + INPUTS.btnTriggerRight.justReleased = true; + INPUTS.btnTriggerRight.justPressed = false; + } else { + INPUTS.btnTriggerRight.justReleased = false; + } + } + /* + //actual triggeraxis + INPUTS.triggerRight.amount = 0; + if (this.keys.w.isDown || this.cursors.up.isDown) { + INPUTS.triggerRight.amount = 1; + } else { + if (gamepad !== null) { + INPUTS.triggerRight.amount = gamepad.axes[5]; + } + } + */ + /* + //STRAFE / ROLL + INPUTS.triggerLeft.amount = 0; + if (this.keys.s.isDown || this.cursors.down.isDown) { + INPUTS.triggerLeft.amount = 1; + } else { + if (gamepad !== null) { + INPUTS.triggerLeft.amount = gamepad.axes[4]; + } + } + */ + + //A + if (this.keys.enter.isDown || (gamepad !== null ? gamepad.buttons[0].pressed : false)) { + if (INPUTS.btnA.pressed === false) { + INPUTS.btnA.justPressed = true; + INPUTS.btnA.pressed = true; + INPUTS.btnA.justReleased = false; + } else { + INPUTS.btnA.justPressed = false; + } + } else { + if (INPUTS.btnA.pressed === true) { + INPUTS.btnA.pressed = false; + INPUTS.btnA.justReleased = true; + INPUTS.btnA.justPressed = false; + } else { + INPUTS.btnA.justReleased = false; + } + } + //B //maybe backspace and escape as seperate start button? or just context sensitive esc + if (this.keys.escape.isDown || (gamepad !== null ? gamepad.buttons[1].pressed : false)) { + if (INPUTS.btnB.pressed === false) { + INPUTS.btnB.justPressed = true; + INPUTS.btnB.pressed = true; + INPUTS.btnB.justReleased = false; + } else { + INPUTS.btnB.justPressed = false; + } + } else { + if (INPUTS.btnB.pressed === true) { + INPUTS.btnB.pressed = false; + INPUTS.btnB.justReleased = true; + INPUTS.btnB.justPressed = false; + } else { + INPUTS.btnB.justReleased = false; + } + } + //Y + if (this.keys.c.isDown || (gamepad !== null ? gamepad.buttons[3].pressed : false)) { + if (INPUTS.btnY.pressed === false) { + INPUTS.btnY.justPressed = true; + INPUTS.btnY.pressed = true; + INPUTS.btnY.justReleased = false; + } else { + INPUTS.btnY.justPressed = false; + } + } else { + if (INPUTS.btnY.pressed === true) { + INPUTS.btnY.pressed = false; + INPUTS.btnY.justReleased = true; + INPUTS.btnY.justPressed = false; + } else { + INPUTS.btnY.justReleased = false; + } + } + //X //maybe backspace and escape as seperate start button? or just context sensitive esc + if (this.keys.x.isDown || (gamepad !== null ? gamepad.buttons[2].pressed : false)) { + if (INPUTS.btnX.pressed === false) { + INPUTS.btnX.justPressed = true; + INPUTS.btnX.pressed = true; + INPUTS.btnX.justReleased = false; + } else { + INPUTS.btnX.justPressed = false; + } + } else { + if (INPUTS.btnX.pressed === true) { + INPUTS.btnX.pressed = false; + INPUTS.btnX.justReleased = true; + INPUTS.btnX.justPressed = false; + } else { + INPUTS.btnX.justReleased = false; + } + } + + //STICK RIGHT DOWN change cam back to default rotation + if (this.keys.alt.isDown || (gamepad !== null ? gamepad.buttons[11].pressed : false)) { + if (INPUTS.btnStickRight.pressed === false) { + INPUTS.btnStickRight.justPressed = true; + INPUTS.btnStickRight.pressed = true; + INPUTS.btnStickRight.justReleased = false; + } else { + INPUTS.btnStickRight.justPressed = false; + } + } else { + if (INPUTS.btnStickRight.pressed === true) { + INPUTS.btnStickRight.pressed = false; + INPUTS.btnStickRight.justReleased = true; + INPUTS.btnStickRight.justPressed = false; + } else { + INPUTS.btnStickRight.justReleased = false; + } + } + //STICK LEFT DOWN + if (/*this.keys.ctrl.isDown ||*/ (gamepad !== null ? gamepad.buttons[10].pressed : false)) { + if (INPUTS.btnStickLeft.pressed === false) { + INPUTS.btnStickLeft.justPressed = true; + INPUTS.btnStickLeft.pressed = true; + INPUTS.btnStickLeft.justReleased = false; + } else { + INPUTS.btnStickLeft.justPressed = false; + } + } else { + if (INPUTS.btnStickLeft.pressed === true) { + INPUTS.btnStickLeft.pressed = false; + INPUTS.btnStickLeft.justReleased = true; + INPUTS.btnStickLeft.justPressed = false; + } else { + INPUTS.btnStickLeft.justReleased = false; + } + } + + //START MENU + if (this.keys.backspace.isDown || (gamepad !== null ? gamepad.buttons[9].pressed : false)) { + if (INPUTS.btnStart.pressed === false) { + INPUTS.btnStart.justPressed = true; + INPUTS.btnStart.pressed = true; + INPUTS.btnStart.justReleased = false; + } else { + INPUTS.btnStart.justPressed = false; + } + } else { + if (INPUTS.btnStart.pressed === true) { + INPUTS.btnStart.pressed = false; + INPUTS.btnStart.justReleased = true; + INPUTS.btnStart.justPressed = false; + } else { + INPUTS.btnStart.justReleased = false; + } + } + + //SELECT + if (this.keys.backspace.isDown || (gamepad !== null ? gamepad.buttons[8].pressed : false)) { + if (INPUTS.btnPause.pressed === false) { + INPUTS.btnPause.justPressed = true; + INPUTS.btnPause.pressed = true; + INPUTS.btnPause.justReleased = false; + } else { + INPUTS.btnPause.justPressed = false; + } + } else { + if (INPUTS.btnPause.pressed === true) { + INPUTS.btnPause.pressed = false; + INPUTS.btnPause.justReleased = true; + INPUTS.btnPause.justPressed = false; + } else { + INPUTS.btnPause.justReleased = false; + } + } + + /* + if(gamepad !== null){ + let str = ""; + for(let x of gamepad.axes){ + str += String(x.toFixed(4)) + ", "; + } + console.log(gamepad.axes[4].toFixed(4) + ", " + gamepad.axes[5].toFixed(4)); + } + */ + } + + fillInputsNoBox() { + let gamepad = null; + gamepad = navigator.getGamepads()[Math.max(0, gamepadsConnected - 1)]; + if (gamepad === undefined) { + gamepad = null; + } + + //FORWARDS-BACKWARDDS + INPUTS.stickLeft.vertical = 0; + INPUTS.stickLeft.horizontal = 0; + if (this.keys.w.isDown /*|| this.hand.pressed === true*/) { + INPUTS.stickLeft.vertical = -1; + } else if (this.keys.s.isDown) { + INPUTS.stickLeft.vertical = 1; + } else { + if (gamepad !== null) { + INPUTS.stickLeft.vertical = gamepad.axes[1]; + } + } + //STRAFE + if (this.keys.a.isDown) { + INPUTS.stickLeft.horizontal = -1; + } else if (this.keys.d.isDown) { + INPUTS.stickLeft.horizontal = 1; + } else { + if (gamepad !== null) { + INPUTS.stickLeft.horizontal = gamepad.axes[0]; + } + } + //LOOK UP-DOWN + INPUTS.stickRight.vertical = 0; + INPUTS.stickRight.horizontal = 0; + if (this.cursors.up.isDown) { + INPUTS.stickRight.vertical = -1; + } else if (this.cursors.down.isDown) { + INPUTS.stickRight.vertical = 1; + } else { + if (gamepad !== null) { + INPUTS.stickRight.vertical = gamepad.axes[3]; + } + } + //LOOK LEFT-RIGHT + if (this.cursors.left.isDown) { + INPUTS.stickRight.horizontal = -1; + } else if (this.cursors.right.isDown) { + INPUTS.stickRight.horizontal = 1; + } else { + if (gamepad !== null) { + INPUTS.stickRight.horizontal = gamepad.axes[2]; + } + } + //CROUCH + if (this.keys.tab.isDown || (gamepad !== null ? gamepad.buttons[4].pressed : false)) { + if (INPUTS.btnShoulderLeft.pressed === false) { + INPUTS.btnShoulderLeft.justPressed = true; + INPUTS.btnShoulderLeft.pressed = true; + INPUTS.btnShoulderLeft.justReleased = false; + } else { + INPUTS.btnShoulderLeft.justPressed = false; + } + } else { + if (INPUTS.btnShoulderLeft.pressed === true) { + INPUTS.btnShoulderLeft.pressed = false; + INPUTS.btnShoulderLeft.justReleased = true; + INPUTS.btnShoulderLeft.justPressed = false; + } else { + INPUTS.btnShoulderLeft.justReleased = false; + } + } + //JUMP + if (this.keys.space.isDown || (gamepad !== null ? gamepad.buttons[5].pressed : false)) { + if (INPUTS.btnShoulderRight.pressed === false) { + INPUTS.btnShoulderRight.justPressed = true; + INPUTS.btnShoulderRight.pressed = true; + INPUTS.btnShoulderRight.justReleased = false; + } else { + INPUTS.btnShoulderRight.justPressed = false; + } + } else { + if (INPUTS.btnShoulderRight.pressed === true) { + INPUTS.btnShoulderRight.pressed = false; + INPUTS.btnShoulderRight.justReleased = true; + INPUTS.btnShoulderRight.justPressed = false; + } else { + INPUTS.btnShoulderRight.justReleased = false; + } + } + //SPRINT + //if (this.keys.shift.isDown || (gamepad !== null ? (gamepad.axes[2] > -0.9) : false)) { + if (this.keys.shift.isDown || (gamepad !== null ? (gamepad.buttons[6] > -0.9) : false)) { + if (INPUTS.btnTriggerLeft.pressed === false) { + INPUTS.btnTriggerLeft.justPressed = true; + INPUTS.btnTriggerLeft.pressed = true; + INPUTS.btnTriggerLeft.justReleased = false; + } else { + INPUTS.btnTriggerLeft.justPressed = false; + } + } else { + if (INPUTS.btnTriggerLeft.pressed === true) { + INPUTS.btnTriggerLeft.pressed = false; + INPUTS.btnTriggerLeft.justReleased = true; + INPUTS.btnTriggerLeft.justPressed = false; + } else { + INPUTS.btnTriggerLeft.justReleased = false; + } + } + //if (/*this.keys.shift.isDown ||*/ (gamepad !== null ? (gamepad.axes[5] > -0.9) : false)) { + if (/*this.keys.shift.isDown ||*/ (gamepad !== null ? (gamepad.buttons[7] > -0.9) : false)) { + if (INPUTS.btnTriggerRight.pressed === false) { + INPUTS.btnTriggerRight.justPressed = true; + INPUTS.btnTriggerRight.pressed = true; + INPUTS.btnTriggerRight.justReleased = false; + } else { + INPUTS.btnTriggerRight.justPressed = false; + } + } else { + if (INPUTS.btnTriggerRight.pressed === true) { + INPUTS.btnTriggerRight.pressed = false; + INPUTS.btnTriggerRight.justReleased = true; + INPUTS.btnTriggerRight.justPressed = false; + } else { + INPUTS.btnTriggerRight.justReleased = false; + } + } + //A + if (this.keys.enter.isDown || (gamepad !== null ? gamepad.buttons[0].pressed : false)) { + if (INPUTS.btnA.pressed === false) { + INPUTS.btnA.justPressed = true; + INPUTS.btnA.pressed = true; + INPUTS.btnA.justReleased = false; + } else { + INPUTS.btnA.justPressed = false; + } + } else { + if (INPUTS.btnA.pressed === true) { + INPUTS.btnA.pressed = false; + INPUTS.btnA.justReleased = true; + INPUTS.btnA.justPressed = false; + } else { + INPUTS.btnA.justReleased = false; + } + } + //B //maybe backspace and escape as seperate start button? or just context sensitive esc + if (this.keys.escape.isDown || (gamepad !== null ? gamepad.buttons[1].pressed : false)) { + if (INPUTS.btnB.pressed === false) { + INPUTS.btnB.justPressed = true; + INPUTS.btnB.pressed = true; + INPUTS.btnB.justReleased = false; + } else { + INPUTS.btnB.justPressed = false; + } + } else { + if (INPUTS.btnB.pressed === true) { + INPUTS.btnB.pressed = false; + INPUTS.btnB.justReleased = true; + INPUTS.btnB.justPressed = false; + } else { + INPUTS.btnB.justReleased = false; + } + } + //Y + if (this.keys.c.isDown || (gamepad !== null ? gamepad.buttons[3].pressed : false)) { + if (INPUTS.btnY.pressed === false) { + INPUTS.btnY.justPressed = true; + INPUTS.btnY.pressed = true; + INPUTS.btnY.justReleased = false; + } else { + INPUTS.btnY.justPressed = false; + } + } else { + if (INPUTS.btnY.pressed === true) { + INPUTS.btnY.pressed = false; + INPUTS.btnY.justReleased = true; + INPUTS.btnY.justPressed = false; + } else { + INPUTS.btnY.justReleased = false; + } + } + //X //maybe backspace and escape as seperate start button? or just context sensitive esc + if (this.keys.x.isDown || (gamepad !== null ? gamepad.buttons[2].pressed : false)) { + if (INPUTS.btnX.pressed === false) { + INPUTS.btnX.justPressed = true; + INPUTS.btnX.pressed = true; + INPUTS.btnX.justReleased = false; + } else { + INPUTS.btnX.justPressed = false; + } + } else { + if (INPUTS.btnX.pressed === true) { + INPUTS.btnX.pressed = false; + INPUTS.btnX.justReleased = true; + INPUTS.btnX.justPressed = false; + } else { + INPUTS.btnX.justReleased = false; + } + } + + //START MENU + if (this.keys.backspace.isDown || (gamepad !== null ? gamepad.buttons[9].pressed : false)) { + if (INPUTS.btnStart.pressed === false) { + INPUTS.btnStart.justPressed = true; + INPUTS.btnStart.pressed = true; + INPUTS.btnStart.justReleased = false; + } else { + INPUTS.btnStart.justPressed = false; + } + } else { + if (INPUTS.btnStart.pressed === true) { + INPUTS.btnStart.pressed = false; + INPUTS.btnStart.justReleased = true; + INPUTS.btnStart.justPressed = false; + } else { + INPUTS.btnStart.justReleased = false; + } + } + } + + + //normal Xbox fill + fillInputsForShipControl() { + let gamepad = null; + gamepad = navigator.getGamepads()[Math.max(0, gamepadsConnected - 1)]; + if (gamepad === undefined) { + gamepad = null; + } + + //FORWARDS-BACKWARDDS (unused in ship) - except nose pitching + INPUTS.stickLeft.vertical = 0; + INPUTS.stickLeft.horizontal = 0; + INPUTS.triggerRight.amount = 0; + INPUTS.triggerLeft.amount = 0; + if (this.keys.w.isDown || this.cursors.up.isDown) { + //INPUTS.stickLeft.vertical = -1; + INPUTS.triggerRight.amount = 1; + } else if (this.keys.s.isDown || this.cursors.down.isDown) { + //INPUTS.stickLeft.vertical = 1; + INPUTS.triggerLeft.amount = 1; + } else { + if (gamepad !== null) { + //INPUTS.stickLeft.vertical = gamepad.axes[1]; + INPUTS.triggerRight.amount = gamepad.buttons[7].value; + INPUTS.triggerLeft.amount = gamepad.buttons[6].value; + } + } + if (gamepad !== null) { + INPUTS.stickLeft.vertical = gamepad.axes[1]; + } + //STRAFE / ROLL + if (this.keys.a.isDown || this.cursors.left.isDown) { + INPUTS.stickLeft.horizontal = -1; + } else if (this.keys.d.isDown || this.cursors.right.isDown) { + INPUTS.stickLeft.horizontal = 1; + } else { + if (gamepad !== null) { + INPUTS.stickLeft.horizontal = gamepad.axes[0]; + } + } + //LOOK UP-DOWN + INPUTS.stickRight.vertical = 0; + INPUTS.stickRight.horizontal = 0; + if (this.keys.i.isDown) { + INPUTS.stickRight.vertical = -1; + } else if (this.keys.k.isDown) { + INPUTS.stickRight.vertical = 1; + } else { + if (gamepad !== null) { + INPUTS.stickRight.vertical = gamepad.axes[3]; + } + } + //LOOK LEFT-RIGHT + if (this.keys.l.isDown) { + INPUTS.stickRight.horizontal = -1; + } else if (this.keys.j.isDown) { + INPUTS.stickRight.horizontal = 1; + } else { + if (gamepad !== null) { + INPUTS.stickRight.horizontal = gamepad.axes[2]; + } + } + //SCORE / info formerly tab + if (this.keys.tab.isDown || (gamepad !== null ? gamepad.buttons[4].pressed : false)) { + if (INPUTS.btnShoulderLeft.pressed === false) { + INPUTS.btnShoulderLeft.justPressed = true; + INPUTS.btnShoulderLeft.pressed = true; + INPUTS.btnShoulderLeft.justReleased = false; + } else { + INPUTS.btnShoulderLeft.justPressed = false; + } + } else { + if (INPUTS.btnShoulderLeft.pressed === true) { + INPUTS.btnShoulderLeft.pressed = false; + INPUTS.btnShoulderLeft.justReleased = true; + INPUTS.btnShoulderLeft.justPressed = false; + } else { + INPUTS.btnShoulderLeft.justReleased = false; + } + } + //JUMP wiss ma noch nicht + if (this.keys.space.isDown || (gamepad !== null ? gamepad.buttons[5].pressed : false)) { + if (INPUTS.btnShoulderRight.pressed === false) { + INPUTS.btnShoulderRight.justPressed = true; + INPUTS.btnShoulderRight.pressed = true; + INPUTS.btnShoulderRight.justReleased = false; + } else { + INPUTS.btnShoulderRight.justPressed = false; + } + } else { + if (INPUTS.btnShoulderRight.pressed === true) { + INPUTS.btnShoulderRight.pressed = false; + INPUTS.btnShoulderRight.justReleased = true; + INPUTS.btnShoulderRight.justPressed = false; + } else { + INPUTS.btnShoulderRight.justReleased = false; + } + } + //SPRINT wiss ma noch nicht + if (this.keys.shift.isDown || (gamepad !== null ? gamepad.buttons[6].pressed : false)) { + if (INPUTS.btnTriggerLeft.pressed === false) { + INPUTS.btnTriggerLeft.justPressed = true; + INPUTS.btnTriggerLeft.pressed = true; + INPUTS.btnTriggerLeft.justReleased = false; + } else { + INPUTS.btnTriggerLeft.justPressed = false; + } + } else { + if (INPUTS.btnTriggerLeft.pressed === true) { + INPUTS.btnTriggerLeft.pressed = false; + INPUTS.btnTriggerLeft.justReleased = true; + INPUTS.btnTriggerLeft.justPressed = false; + } else { + INPUTS.btnTriggerLeft.justReleased = false; + } + } + // + if (this.keys.w.isDown || (gamepad !== null ? gamepad.buttons[7].pressed : false)) { + if (INPUTS.btnTriggerRight.pressed === false) { + INPUTS.btnTriggerRight.justPressed = true; + INPUTS.btnTriggerRight.pressed = true; + INPUTS.btnTriggerRight.justReleased = false; + } else { + INPUTS.btnTriggerRight.justPressed = false; + } + } else { + if (INPUTS.btnTriggerRight.pressed === true) { + INPUTS.btnTriggerRight.pressed = false; + INPUTS.btnTriggerRight.justReleased = true; + INPUTS.btnTriggerRight.justPressed = false; + } else { + INPUTS.btnTriggerRight.justReleased = false; + } + } + /* + //actual triggeraxis + INPUTS.triggerRight.amount = 0; + if (this.keys.w.isDown || this.cursors.up.isDown) { + INPUTS.triggerRight.amount = 1; + } else { + if (gamepad !== null) { + INPUTS.triggerRight.amount = gamepad.axes[5]; + } + } + */ + /* + //STRAFE / ROLL + INPUTS.triggerLeft.amount = 0; + if (this.keys.s.isDown || this.cursors.down.isDown) { + INPUTS.triggerLeft.amount = 1; + } else { + if (gamepad !== null) { + INPUTS.triggerLeft.amount = gamepad.axes[4]; + } + } + */ + + //A + if (this.keys.enter.isDown || (gamepad !== null ? gamepad.buttons[0].pressed : false)) { + if (INPUTS.btnA.pressed === false) { + INPUTS.btnA.justPressed = true; + INPUTS.btnA.pressed = true; + INPUTS.btnA.justReleased = false; + } else { + INPUTS.btnA.justPressed = false; + } + } else { + if (INPUTS.btnA.pressed === true) { + INPUTS.btnA.pressed = false; + INPUTS.btnA.justReleased = true; + INPUTS.btnA.justPressed = false; + } else { + INPUTS.btnA.justReleased = false; + } + } + //B //maybe backspace and escape as seperate start button? or just context sensitive esc + if (this.keys.escape.isDown || (gamepad !== null ? gamepad.buttons[1].pressed : false)) { + if (INPUTS.btnB.pressed === false) { + INPUTS.btnB.justPressed = true; + INPUTS.btnB.pressed = true; + INPUTS.btnB.justReleased = false; + } else { + INPUTS.btnB.justPressed = false; + } + } else { + if (INPUTS.btnB.pressed === true) { + INPUTS.btnB.pressed = false; + INPUTS.btnB.justReleased = true; + INPUTS.btnB.justPressed = false; + } else { + INPUTS.btnB.justReleased = false; + } + } + //Y + if (this.keys.c.isDown || (gamepad !== null ? gamepad.buttons[2].pressed : false)) { + if (INPUTS.btnY.pressed === false) { + INPUTS.btnY.justPressed = true; + INPUTS.btnY.pressed = true; + INPUTS.btnY.justReleased = false; + } else { + INPUTS.btnY.justPressed = false; + } + } else { + if (INPUTS.btnY.pressed === true) { + INPUTS.btnY.pressed = false; + INPUTS.btnY.justReleased = true; + INPUTS.btnY.justPressed = false; + } else { + INPUTS.btnY.justReleased = false; + } + } + //X //maybe backspace and escape as seperate start button? or just context sensitive esc + if (this.keys.x.isDown || (gamepad !== null ? gamepad.buttons[3].pressed : false)) { + if (INPUTS.btnX.pressed === false) { + INPUTS.btnX.justPressed = true; + INPUTS.btnX.pressed = true; + INPUTS.btnX.justReleased = false; + } else { + INPUTS.btnX.justPressed = false; + } + } else { + if (INPUTS.btnX.pressed === true) { + INPUTS.btnX.pressed = false; + INPUTS.btnX.justReleased = true; + INPUTS.btnX.justPressed = false; + } else { + INPUTS.btnX.justReleased = false; + } + } + + //STICK RIGHT DOWN change cam back to default rotation + if (this.keys.alt.isDown || (gamepad !== null ? gamepad.buttons[11].pressed : false)) { + if (INPUTS.btnStickRight.pressed === false) { + INPUTS.btnStickRight.justPressed = true; + INPUTS.btnStickRight.pressed = true; + INPUTS.btnStickRight.justReleased = false; + } else { + INPUTS.btnStickRight.justPressed = false; + } + } else { + if (INPUTS.btnStickRight.pressed === true) { + INPUTS.btnStickRight.pressed = false; + INPUTS.btnStickRight.justReleased = true; + INPUTS.btnStickRight.justPressed = false; + } else { + INPUTS.btnStickRight.justReleased = false; + } + } + //STICK LEFT DOWN + if (/*this.keys.ctrl.isDown ||*/ (gamepad !== null ? gamepad.buttons[10].pressed : false)) { + if (INPUTS.btnStickLeft.pressed === false) { + INPUTS.btnStickLeft.justPressed = true; + INPUTS.btnStickLeft.pressed = true; + INPUTS.btnStickLeft.justReleased = false; + } else { + INPUTS.btnStickLeft.justPressed = false; + } + } else { + if (INPUTS.btnStickLeft.pressed === true) { + INPUTS.btnStickLeft.pressed = false; + INPUTS.btnStickLeft.justReleased = true; + INPUTS.btnStickLeft.justPressed = false; + } else { + INPUTS.btnStickLeft.justReleased = false; + } + } + + //START MENU + if (this.keys.backspace.isDown || (gamepad !== null ? gamepad.buttons[9].pressed : false)) { + if (INPUTS.btnStart.pressed === false) { + INPUTS.btnStart.justPressed = true; + INPUTS.btnStart.pressed = true; + INPUTS.btnStart.justReleased = false; + } else { + INPUTS.btnStart.justPressed = false; + } + } else { + if (INPUTS.btnStart.pressed === true) { + INPUTS.btnStart.pressed = false; + INPUTS.btnStart.justReleased = true; + INPUTS.btnStart.justPressed = false; + } else { + INPUTS.btnStart.justReleased = false; + } + } + + /* + if(gamepad !== null){ + let str = ""; + for(let x of gamepad.axes){ + str += String(x.toFixed(4)) + ", "; + } + console.log(gamepad.axes[4].toFixed(4) + ", " + gamepad.axes[5].toFixed(4)); + } + */ + } + + fillInputs() { + let gamepad = null; + gamepad = navigator.getGamepads()[Math.max(0, gamepadsConnected - 1)]; + if (gamepad === undefined) { + gamepad = null; + } + + //FORWARDS-BACKWARDDS + INPUTS.stickLeft.vertical = 0; + INPUTS.stickLeft.horizontal = 0; + if (this.keys.w.isDown /*|| this.hand.pressed === true*/) { + INPUTS.stickLeft.vertical = -1; + } else if (this.keys.s.isDown) { + INPUTS.stickLeft.vertical = 1; + } else { + if (gamepad !== null) { + INPUTS.stickLeft.vertical = gamepad.axes[1]; + } + } + //STRAFE + if (this.keys.a.isDown) { + INPUTS.stickLeft.horizontal = -1; + } else if (this.keys.d.isDown) { + INPUTS.stickLeft.horizontal = 1; + } else { + if (gamepad !== null) { + INPUTS.stickLeft.horizontal = gamepad.axes[0]; + } + } + //LOOK UP-DOWN + INPUTS.stickRight.vertical = 0; + INPUTS.stickRight.horizontal = 0; + if (this.cursors.up.isDown) { + INPUTS.stickRight.vertical = -1; + } else if (this.cursors.down.isDown) { + INPUTS.stickRight.vertical = 1; + } else { + if (gamepad !== null) { + INPUTS.stickRight.vertical = gamepad.axes[3]; + } + } + //LOOK LEFT-RIGHT + if (this.cursors.left.isDown) { + INPUTS.stickRight.horizontal = -1; + } else if (this.cursors.right.isDown) { + INPUTS.stickRight.horizontal = 1; + } else { + if (gamepad !== null) { + INPUTS.stickRight.horizontal = gamepad.axes[2]; + } + } + //CROUCH + if (this.keys.tab.isDown || (gamepad !== null ? gamepad.buttons[4].pressed : false)) { + if (INPUTS.btnShoulderLeft.pressed === false) { + INPUTS.btnShoulderLeft.justPressed = true; + INPUTS.btnShoulderLeft.pressed = true; + INPUTS.btnShoulderLeft.justReleased = false; + } else { + INPUTS.btnShoulderLeft.justPressed = false; + } + } else { + if (INPUTS.btnShoulderLeft.pressed === true) { + INPUTS.btnShoulderLeft.pressed = false; + INPUTS.btnShoulderLeft.justReleased = true; + INPUTS.btnShoulderLeft.justPressed = false; + } else { + INPUTS.btnShoulderLeft.justReleased = false; + } + } + //JUMP + if (this.keys.space.isDown || (gamepad !== null ? gamepad.buttons[5].pressed : false)) { + if (INPUTS.btnShoulderRight.pressed === false) { + INPUTS.btnShoulderRight.justPressed = true; + INPUTS.btnShoulderRight.pressed = true; + INPUTS.btnShoulderRight.justReleased = false; + } else { + INPUTS.btnShoulderRight.justPressed = false; + } + } else { + if (INPUTS.btnShoulderRight.pressed === true) { + INPUTS.btnShoulderRight.pressed = false; + INPUTS.btnShoulderRight.justReleased = true; + INPUTS.btnShoulderRight.justPressed = false; + } else { + INPUTS.btnShoulderRight.justReleased = false; + } + } + //SPRINT + if (this.keys.shift.isDown || (gamepad !== null ? gamepad.buttons[6].pressed : false)) { + if (INPUTS.btnTriggerLeft.pressed === false) { + INPUTS.btnTriggerLeft.justPressed = true; + INPUTS.btnTriggerLeft.pressed = true; + INPUTS.btnTriggerLeft.justReleased = false; + } else { + INPUTS.btnTriggerLeft.justPressed = false; + } + } else { + if (INPUTS.btnTriggerLeft.pressed === true) { + INPUTS.btnTriggerLeft.pressed = false; + INPUTS.btnTriggerLeft.justReleased = true; + INPUTS.btnTriggerLeft.justPressed = false; + } else { + INPUTS.btnTriggerLeft.justReleased = false; + } + } + if (/*this.keys.shift.isDown ||*/ (gamepad !== null ? gamepad.buttons[7].pressed : false)) { + if (INPUTS.btnTriggerRight.pressed === false) { + INPUTS.btnTriggerRight.justPressed = true; + INPUTS.btnTriggerRight.pressed = true; + INPUTS.btnTriggerRight.justReleased = false; + } else { + INPUTS.btnTriggerRight.justPressed = false; + } + } else { + if (INPUTS.btnTriggerRight.pressed === true) { + INPUTS.btnTriggerRight.pressed = false; + INPUTS.btnTriggerRight.justReleased = true; + INPUTS.btnTriggerRight.justPressed = false; + } else { + INPUTS.btnTriggerRight.justReleased = false; + } + } + //A + if (this.keys.enter.isDown || (gamepad !== null ? gamepad.buttons[0].pressed : false)) { + if (INPUTS.btnA.pressed === false) { + INPUTS.btnA.justPressed = true; + INPUTS.btnA.pressed = true; + INPUTS.btnA.justReleased = false; + } else { + INPUTS.btnA.justPressed = false; + } + } else { + if (INPUTS.btnA.pressed === true) { + INPUTS.btnA.pressed = false; + INPUTS.btnA.justReleased = true; + INPUTS.btnA.justPressed = false; + } else { + INPUTS.btnA.justReleased = false; + } + } + //B //maybe backspace and escape as seperate start button? or just context sensitive esc + if (this.keys.escape.isDown || (gamepad !== null ? gamepad.buttons[1].pressed : false)) { + if (INPUTS.btnB.pressed === false) { + INPUTS.btnB.justPressed = true; + INPUTS.btnB.pressed = true; + INPUTS.btnB.justReleased = false; + } else { + INPUTS.btnB.justPressed = false; + } + } else { + if (INPUTS.btnB.pressed === true) { + INPUTS.btnB.pressed = false; + INPUTS.btnB.justReleased = true; + INPUTS.btnB.justPressed = false; + } else { + INPUTS.btnB.justReleased = false; + } + } + //Y + if (this.keys.c.isDown || (gamepad !== null ? gamepad.buttons[2].pressed : false)) { + if (INPUTS.btnY.pressed === false) { + INPUTS.btnY.justPressed = true; + INPUTS.btnY.pressed = true; + INPUTS.btnY.justReleased = false; + } else { + INPUTS.btnY.justPressed = false; + } + } else { + if (INPUTS.btnY.pressed === true) { + INPUTS.btnY.pressed = false; + INPUTS.btnY.justReleased = true; + INPUTS.btnY.justPressed = false; + } else { + INPUTS.btnY.justReleased = false; + } + } + //X //maybe backspace and escape as seperate start button? or just context sensitive esc + if (this.keys.x.isDown || (gamepad !== null ? gamepad.buttons[3].pressed : false)) { + if (INPUTS.btnX.pressed === false) { + INPUTS.btnX.justPressed = true; + INPUTS.btnX.pressed = true; + INPUTS.btnX.justReleased = false; + } else { + INPUTS.btnX.justPressed = false; + } + } else { + if (INPUTS.btnX.pressed === true) { + INPUTS.btnX.pressed = false; + INPUTS.btnX.justReleased = true; + INPUTS.btnX.justPressed = false; + } else { + INPUTS.btnX.justReleased = false; + } + } + + //START MENU + if (this.keys.backspace.isDown || (gamepad !== null ? gamepad.buttons[9].pressed : false)) { + if (INPUTS.btnStart.pressed === false) { + INPUTS.btnStart.justPressed = true; + INPUTS.btnStart.pressed = true; + INPUTS.btnStart.justReleased = false; + } else { + INPUTS.btnStart.justPressed = false; + } + } else { + if (INPUTS.btnStart.pressed === true) { + INPUTS.btnStart.pressed = false; + INPUTS.btnStart.justReleased = true; + INPUTS.btnStart.justPressed = false; + } else { + INPUTS.btnStart.justReleased = false; + } + } + } + + fillInputsOLD() { + let gamepad = null; + gamepad = navigator.getGamepads()[Math.max(0, gamepadsConnected - 1)]; + if (gamepad === undefined) { + gamepad = null; + } + + //FORWARDS-BACKWARDDS + INPUTS.stickLeft.vertical = 0; + INPUTS.stickLeft.horizontal = 0; + if (this.keys.w.isDown /*|| this.hand.pressed === true*/) { + INPUTS.stickLeft.vertical = -1; + } else if (this.keys.s.isDown) { + INPUTS.stickLeft.vertical = 1; + } else { + if (gamepad !== null) { + INPUTS.stickLeft.vertical = gamepad.axes[1]; + } + } + //STRAFE + if (this.keys.a.isDown) { + INPUTS.stickLeft.horizontal = -1; + } else if (this.keys.d.isDown) { + INPUTS.stickLeft.horizontal = 1; + } else { + if (gamepad !== null) { + INPUTS.stickLeft.horizontal = gamepad.axes[0]; + } + } + //LOOK UP-DOWN + INPUTS.stickRight.vertical = 0; + INPUTS.stickRight.horizontal = 0; + if (this.cursors.up.isDown) { + INPUTS.stickRight.vertical = -1; + } else if (this.cursors.down.isDown) { + INPUTS.stickRight.vertical = 1; + } else { + if (gamepad !== null) { + INPUTS.stickRight.vertical = gamepad.axes[3]; + } + } + //LOOK LEFT-RIGHT + if (this.cursors.left.isDown) { + INPUTS.stickRight.horizontal = -1; + } else if (this.cursors.right.isDown) { + INPUTS.stickRight.horizontal = 1; + } else { + if (gamepad !== null) { + INPUTS.stickRight.horizontal = gamepad.axes[2]; + } + } + //CROUCH + if (this.keys.tab.isDown || (gamepad !== null ? gamepad.buttons[4].pressed : false)) { + if (INPUTS.btnShoulderLeft.pressed === false) { + INPUTS.btnShoulderLeft.justPressed = true; + INPUTS.btnShoulderLeft.pressed = true; + INPUTS.btnShoulderLeft.justReleased = false; + } else { + INPUTS.btnShoulderLeft.justPressed = false; + } + } else { + if (INPUTS.btnShoulderLeft.pressed === true) { + INPUTS.btnShoulderLeft.pressed = false; + INPUTS.btnShoulderLeft.justReleased = true; + INPUTS.btnShoulderLeft.justPressed = false; + } else { + INPUTS.btnShoulderLeft.justReleased = false; + } + } + //JUMP + if (this.keys.space.isDown || (gamepad !== null ? gamepad.buttons[5].pressed : false)) { + if (INPUTS.btnShoulderRight.pressed === false) { + INPUTS.btnShoulderRight.justPressed = true; + INPUTS.btnShoulderRight.pressed = true; + INPUTS.btnShoulderRight.justReleased = false; + } else { + INPUTS.btnShoulderRight.justPressed = false; + } + } else { + if (INPUTS.btnShoulderRight.pressed === true) { + INPUTS.btnShoulderRight.pressed = false; + INPUTS.btnShoulderRight.justReleased = true; + INPUTS.btnShoulderRight.justPressed = false; + } else { + INPUTS.btnShoulderRight.justReleased = false; + } + } + //SPRINT + if (this.keys.shift.isDown || (gamepad !== null ? gamepad.buttons[6].pressed : false)) { + if (INPUTS.btnTriggerLeft.pressed === false) { + INPUTS.btnTriggerLeft.justPressed = true; + INPUTS.btnTriggerLeft.pressed = true; + INPUTS.btnTriggerLeft.justReleased = false; + } else { + INPUTS.btnTriggerLeft.justPressed = false; + } + } else { + if (INPUTS.btnTriggerLeft.pressed === true) { + INPUTS.btnTriggerLeft.pressed = false; + INPUTS.btnTriggerLeft.justReleased = true; + INPUTS.btnTriggerLeft.justPressed = false; + } else { + INPUTS.btnTriggerLeft.justReleased = false; + } + } + if (/*this.keys.shift.isDown ||*/ (gamepad !== null ? gamepad.buttons[7].pressed : false)) { + if (INPUTS.btnTriggerRight.pressed === false) { + INPUTS.btnTriggerRight.justPressed = true; + INPUTS.btnTriggerRight.pressed = true; + INPUTS.btnTriggerRight.justReleased = false; + } else { + INPUTS.btnTriggerRight.justPressed = false; + } + } else { + if (INPUTS.btnTriggerRight.pressed === true) { + INPUTS.btnTriggerRight.pressed = false; + INPUTS.btnTriggerRight.justReleased = true; + INPUTS.btnTriggerRight.justPressed = false; + } else { + INPUTS.btnTriggerRight.justReleased = false; + } + } + //A + if (this.keys.enter.isDown || (gamepad !== null ? gamepad.buttons[0].pressed : false)) { + if (INPUTS.btnA.pressed === false) { + INPUTS.btnA.justPressed = true; + INPUTS.btnA.pressed = true; + INPUTS.btnA.justReleased = false; + } else { + INPUTS.btnA.justPressed = false; + } + } else { + if (INPUTS.btnA.pressed === true) { + INPUTS.btnA.pressed = false; + INPUTS.btnA.justReleased = true; + INPUTS.btnA.justPressed = false; + } else { + INPUTS.btnA.justReleased = false; + } + } + //B //maybe backspace and escape as seperate start button? or just context sensitive esc + if (this.keys.escape.isDown || (gamepad !== null ? gamepad.buttons[1].pressed : false)) { + if (INPUTS.btnB.pressed === false) { + INPUTS.btnB.justPressed = true; + INPUTS.btnB.pressed = true; + INPUTS.btnB.justReleased = false; + } else { + INPUTS.btnB.justPressed = false; + } + } else { + if (INPUTS.btnB.pressed === true) { + INPUTS.btnB.pressed = false; + INPUTS.btnB.justReleased = true; + INPUTS.btnB.justPressed = false; + } else { + INPUTS.btnB.justReleased = false; + } + } + //Y + if (this.keys.c.isDown || (gamepad !== null ? gamepad.buttons[2].pressed : false)) { + if (INPUTS.btnY.pressed === false) { + INPUTS.btnY.justPressed = true; + INPUTS.btnY.pressed = true; + INPUTS.btnY.justReleased = false; + } else { + INPUTS.btnY.justPressed = false; + } + } else { + if (INPUTS.btnY.pressed === true) { + INPUTS.btnY.pressed = false; + INPUTS.btnY.justReleased = true; + INPUTS.btnY.justPressed = false; + } else { + INPUTS.btnY.justReleased = false; + } + } + //X //maybe backspace and escape as seperate start button? or just context sensitive esc + if (this.keys.x.isDown || (gamepad !== null ? gamepad.buttons[3].pressed : false)) { + if (INPUTS.btnX.pressed === false) { + INPUTS.btnX.justPressed = true; + INPUTS.btnX.pressed = true; + INPUTS.btnX.justReleased = false; + } else { + INPUTS.btnX.justPressed = false; + } + } else { + if (INPUTS.btnX.pressed === true) { + INPUTS.btnX.pressed = false; + INPUTS.btnX.justReleased = true; + INPUTS.btnX.justPressed = false; + } else { + INPUTS.btnX.justReleased = false; + } + } + + //START MENU + if (this.keys.backspace.isDown || (gamepad !== null ? gamepad.buttons[9].pressed : false)) { + if (INPUTS.btnStart.pressed === false) { + INPUTS.btnStart.justPressed = true; + INPUTS.btnStart.pressed = true; + INPUTS.btnStart.justReleased = false; + } else { + INPUTS.btnStart.justPressed = false; + } + } else { + if (INPUTS.btnStart.pressed === true) { + INPUTS.btnStart.pressed = false; + INPUTS.btnStart.justReleased = true; + INPUTS.btnStart.justPressed = false; + } else { + INPUTS.btnStart.justReleased = false; + } + } + } + +} diff --git a/src/scnLoad.js b/src/scnLoad.js new file mode 100755 index 0000000..bbb4071 --- /dev/null +++ b/src/scnLoad.js @@ -0,0 +1,311 @@ +export default class ScnLoad extends Phaser.Scene { + constructor() { + super("ScnLoad"); + this.loadTxt = null; + } + + preload() { + this.cameras.main.setBackgroundColor(0x000000); + this.cameras.main.setScroll(-this.game.config.width * 0.5, -this.game.config.height * 0.5); + + view.full.width = this.game.config.width; + view.full.height = this.game.config.height; + view.half.width = this.game.config.width * 0.5; + view.half.height = this.game.config.height * 0.5; + + this.load.setBaseURL("./assets/"); + //this.load.image('image0', '0.png'); + //this.load.json("story1", "storyjson/story1.json"); + //this.load.text("locDE", "languageData/deutsch.txt"); + //this.load.audio('decisionLeft', 'audio/decision.wav'); + //this.load.atlas("tilesGrass", "sprites/tiles/grassDirt.png", "sprites/tiles/tilesGround_atlas.json"); + + //conversations + this.load.json("diaDemoRoki00", "json/dialogues/diaDemoRoki00.json"); + this.load.json("diaDemoHangarMechanic00", "json/dialogues/diaDemoHangarMechanic00.json"); + this.load.json("diaDemoHangarMechanic01", "json/dialogues/diaDemoHangarMechanic01.json"); + this.load.json("diaDemoRaceTutorial", "json/dialogues/diaDemoRaceTutorial.json"); + this.load.json("diaDemoTableround00", "json/dialogues/diaDemoTableround00.json"); + + this.load.json("diaDream00RaceDirector00", "json/dialogues/diaDream00RaceDirector00.json"); + this.load.json("diaDream00Barbara00", "json/dialogues/diaDream00Barbara00.json"); + this.load.json("diaDream00Barbara01", "json/dialogues/diaDream00Barbara01.json"); + this.load.json("diaDream00Beggar01", "json/dialogues/diaDream00Beggar01.json"); + this.load.json("diaDream00Nosef00", "json/dialogues/diaDream00Nosef00.json"); + + this.load.json("diaOffice00Guard00", "json/dialogues/diaOffice00Guard00.json"); + + this.load.json("diaMarketsquare00Vip00", "json/dialogues/diaMarketsquare00Vip00.json"); + this.load.json("diaMarketsquare00Jay00", "json/dialogues/diaMarketsquare00Jay00.json"); + this.load.json("diaMarketsquare00Booker00", "json/dialogues/diaMarketsquare00Booker00.json"); + this.load.json("diaMarketsquare00Roki00", "json/dialogues/diaMarketsquare00Roki00.json"); + this.load.json("diaMarketsquare00Glaze00", "json/dialogues/diaMarketsquare00Glaze00.json"); + this.load.json("diaMarketsquare00Roomba00", "json/dialogues/diaMarketsquare00Roomba00.json"); + + this.load.json("diaApartement00Moritz00", "json/dialogues/diaApartement00Moritz00.json"); + + this.load.json("diaTestJosef", "json/dialogues/testJosef01.json"); + this.load.json("diaHangarMechanic00", "json/dialogues/diaHangarMechanic00.json"); + this.load.json("diaMisterTutorial00", "json/dialogues/diaMisterTutorial00.json"); + this.load.json("diaInfogrunts00", "json/dialogues/diaInfogrunts00.json"); + this.load.json("diaTestLibrarian", "json/dialogues/testLibrarian.json"); + this.load.json("diaHangar00Roomba00", "json/dialogues/diaHangar00Roomba00.json"); + + //hover cars + this.load.json("modLegalityBox", "json/models/legalityBox.json"); + this.load.json("modHoverCarWipeOutStyle", "json/models/hoverCarWipeOutStyle.json"); + this.load.json("modHoverCarF1", "json/models/hoverCarF1.json"); + this.load.json("modHoverCarTinnemann00", "json/models/hoverCarTinnemann00SC.json"); //hoverCarTinnemann00 + this.load.json("modHoverCarHapton00", "json/models/hoverCarHapton00SC.json"); //hoverCarHapton00re + this.load.json("modLensflare", "json/models/lensflare.json"); + + //models architecture + this.load.json("modRingD64R128", "json/models/ringD64R128.json"); + this.load.json("modRingD64R128Core", "json/models/ringD64R128Core.json"); + this.load.json("modRingD64R128CoreStart", "json/models/ringD64R128CoreStart.json"); + this.load.json("modRingD64R128CoreEnd", "json/models/ringD64R128CoreEnd.json"); + //this.load.json("modRingD64R128Flat", "json/models/ringD64R128Flat.json"); + this.load.json("modRingD64R128Lab", "json/models/ringD64R128Lab.json"); + this.load.json("modRingD64R128Garden", "json/models/ringD64R128Garden.json"); + this.load.json("modRingD64R128GardenStart", "json/models/ringD64R128GardenStart.json"); + this.load.json("modRingD64R128GardenEnd", "json/models/ringD64R128GardenEnd.json"); + this.load.json("modRingD64R128AtomRoom", "json/models/ringD64R128AtomRoom.json"); + this.load.json("modRingD64R128AtomRoom01", "json/models/ringD64R128AtomRoom01.json"); + this.load.json("modRingD64R128AtomRoom02", "json/models/ringD64R128AtomRoom02.json"); + this.load.json("modRingD64R128Watertunnel", "json/models/ringD64R128Watertunnel.json"); + this.load.json("modRingD64R128Octagon", "json/models/ringD64R128Octagon.json"); + this.load.json("modRingD64R128Quadrat", "json/models/ringD64R128Quadrat.json"); + this.load.json("modRingD64R128Skull", "json/models/ringD64R128Skull.json"); + this.load.json("modRingD64R128RoundCanyonBoth", "json/models/ringD64R128RoundCanyonBoth.json"); + this.load.json("modRingD64R128RoundCanyon", "json/models/ringD64R128RoundCanyon.json"); + + this.load.json("modRingD256HangarLift", "json/models/ringD256HangarLift.json"); + + this.load.json("modRingD512MetroStation", "json/models/ringD512MetroStation.json"); + this.load.json("modRingD512MetroStationStart", "json/models/ringD512MetroStationStart.json"); + this.load.json("modRingD512MetroStationEnd", "json/models/ringD512MetroStationEnd.json"); + + this.load.json("modObstVentBlade", "json/models/obstVentBlade.json"); + this.load.json("modObstVentBladeDestroyed", "json/models/obstVentBladeDestroyed.json"); + this.load.json("modObstMetroBlade", "json/models/obstMetroBlade.json"); + this.load.json("modObstMetalDoorMirrored", "json/models/obstMetalDoorMirrored.json"); + this.load.json("modObstVentDoor", "json/models/obstVentDoor.json"); + this.load.json("modObst3x3Door", "json/models/obst3x3Door.json"); + this.load.json("modObst1x2Blade", "json/models/obst1x2Blade.json"); + this.load.json("modObstSteam", "json/models/obstSteam.json"); + this.load.json("modObstWatertunnelCollar", "json/models/obstWatertunnelCollar.json"); + + //models level architecture + //elevator + this.load.json("modElevatorBase", "json/models/elevator/elevatorBase.json"); + this.load.json("modElevatorButton", "json/models/elevator/elevatorButton.json"); + this.load.json("modElevatorDoor", "json/models/elevator/elevatorDoor.json"); + //hangar + this.load.json("modHangarMain", "json/models/hangar/hangarMain.json"); + this.load.json("modHangarHallway", "json/models/hangar/hangarHallway.json"); + this.load.json("modHangarDoor", "json/models/hangar/hangarDoor.json"); + this.load.json("modShipInteractable", "json/models/hangar/shipInteractable.json"); + this.load.json("modHallwayPainting", "json/models/hangar/hallwayPainting.json"); + //marketsquare + this.load.json("modElevatorRoom", "json/models/marketsquare/elevatorRoom.json"); + this.load.json("modLounge", "json/models/marketsquare/driversLounge.json"); + this.load.json("modMarketsquareApartements", "json/models/marketsquare/marketsquareApartements.json"); + this.load.json("modMarketsquareStaircase", "json/models/marketsquare/marketStaircase.json"); + this.load.json("modCafeTableRound", "json/models/marketsquare/cafeTableRound.json"); + //player apartement + this.load.json("modPlayerApartement", "json/models/playerApartement/playerApartement.json"); + this.load.json("modComputer", "json/models/playerApartement/computer.json"); + this.load.json("modSeatBasic", "json/models/seatBasic.json"); + //race director office + this.load.json("modRaceDirectorOfficeRoom", "json/models/raceDirectorOffice/raceDirectorOfficeRoom.json"); + //church + this.load.json("modMetroStationArcade", "json/models/church/metroStationArcade.json"); + this.load.json("modMetroStationArcadeCorner", "json/models/church/metroStationArcadeCorner.json"); + this.load.json("modMetroStationArcadeCornerEntry", "json/models/church/metroStationArcadeCornerEntry.json"); + this.load.json("modMetroStationArcadeRoom00", "json/models/church/metroStationArcadeRoom00.json"); + //metro + this.load.json("modMetroStationDream", "json/models/metro/metroStationDream.json"); + this.load.json("modMetroStationDreamRight", "json/models/metro/metroStationDreamRight.json"); + this.load.json("modMetroStationCorridorT", "json/models/metro/metroStationCorridorT.json"); + this.load.json("modMetroCarExterior", "json/models/metro/metroCarExterior.json"); + this.load.json("modMetroCarExteriorBack", "json/models/metro/metroCarExteriorBack.json"); + this.load.json("modMetroCarInterior", "json/models/metro/metroCarInterior.json"); + this.load.json("modMetroCarInteriorFront", "json/models/metro/metroCarInteriorFront.json"); + this.load.json("modMetroCarInteriorBack", "json/models/metro/metroCarInteriorBack.json"); //todo: remove bc unused? + this.load.json("modMetroCarToStation", "json/models/metro/metroCarToStation.json"); + this.load.json("modMetroRailTunnelSegment", "json/models/metro/metroRailTunnelSegment.json"); + + //models characters + this.load.json("modCharacterDefaultHuman", "json/models/characters/characterTurnaroundDefaultHuman.json"); + //this.load.json("modCharacterMechanicSitting", "json/models/characters/characterTurnaroundMechanicSitting.json"); + //this.load.json("modCharacterLibrarian", "json/models/characterTurnaroundLibrarian.json"); + //this.load.json("modCharacterLibrarianSit", "json/models/characterTurnaroundLibrarianSit.json"); + + //models various + this.load.json("modDebugTile", "json/models/debugTile.json"); + this.load.json("modCenterWall32x32", "json/models/centerWall32x32.json"); + this.load.json("modRacingPickup", "json/models/racingPickup.json"); + this.load.json("modDebugArrow", "json/models/debugArrow.json"); + this.load.json("modJumpspot", "json/models/jumpspot.json"); + this.load.json("modTriggerWall1x1", "json/models/triggerWall1x1.json"); + this.load.json("modTrigger64x64", "json/models/trigger64x64.json"); + this.load.json("modArcadeAutomat", "json/models/arcadeAutomat.json"); + this.load.json("modArcadeAutomatScreen", "json/models/arcadeAutomatScreen.json"); + + //character sprites + //this.load.image("testJosef00", "sprites/characters/testJosef.png"); + this.load.image("hlBarabara", "sprites/characters/hlBarabara.png"); + this.load.image("beggar", "sprites/characters/beggar.png"); + this.load.image("roomba", "sprites/characters/roomba.png"); + //this.load.spritesheet("turnaroundMoritzsheet00", "sprites/characters/turnaroundMoritzsheet00.png", { frameWidth: 46, frameHeight: 128 }); + for (let i = 0; i < 5; i++) { + this.load.spritesheet("turnaroundHumansheet0" + String(i), "sprites/characters/turnaroundHumansheet0" + String(i) + ".png", { + frameWidth: 46, + frameHeight: 128, + }); + } + //this.load.spritesheet("turnaroundJosef00", "sprites/characters/turnaroundJosef00.png", { frameWidth: 24, frameHeight: 64 }); + this.load.spritesheet("turnaroundJosef00", "sprites/characters/turnaroundPatrik00.png", { frameWidth: 56, frameHeight: 128 }); + this.load.spritesheet("turnaroundMoritz00", "sprites/characters/turnaroundMoritz00.png", { frameWidth: 46, frameHeight: 128 }); + this.load.spritesheet("turnaroundPaulsheet00", "sprites/characters/turnaroundPaulsheet00.png", { frameWidth: 101, frameHeight: 128 }); + this.load.spritesheet("turnaroundLarasheet00", "sprites/characters/turnaroundLarasheet00.png", { frameWidth: 57, frameHeight: 120 }); + //this.load.spritesheet("turnaroundFoxxyIdle00", "sprites/characters/turnaroundFoxxyIdle00.png", { frameWidth: 83, frameHeight: 128 }); + //this.load.spritesheet("turnaroundScooterIdle00", "sprites/characters/turnaroundScooterIdle00.png", { frameWidth: 53, frameHeight: 128 }); + //this.load.spritesheet("turnaroundMechanicSitting00", "sprites/characters/turnaroundMechanicSitting01.png", { frameWidth: 77, frameHeight: 128 }); + //this.load.spritesheet("turnaroundLibrarian00", "sprites/characters/turnaroundLibrarian00.png", { frameWidth: 33, frameHeight: 128 });//standing + //this.load.spritesheet("turnaroundLibrarian01", "sprites/characters/turnaroundLibrarian01.png", { frameWidth: 59, frameHeight: 64 });//sitting on floor + + //character atlas + this.load.atlas("charSheetRoki", "sprites/characters/charSheetRoki.png", "sprites/characters/charSheetRoki.json"); + this.load.atlas("charSheetScooter", "sprites/characters/charSheetHannah.png", "sprites/characters/charSheetHannah.json"); + this.load.atlas("charSheetBonez", "sprites/characters/charSheetBonez.png", "sprites/characters/charSheetBonez.json"); + this.load.atlas("charSheetBooker", "sprites/characters/charSheetBooker.png", "sprites/characters/charSheetBooker.json"); + this.load.atlas("charSheetJosef", "sprites/characters/charSheetJosef.png", "sprites/characters/charSheetJosef.json"); + this.load.atlas("charSheetGlaze", "sprites/characters/charSheetGlaze.png", "sprites/characters/charSheetGlaze.json"); + this.load.atlas("charSheetMaleguard", "sprites/characters/charSheetMaleguard.png", "sprites/characters/charSheetMaleguard.json"); + this.load.atlas("charSheetJasonguard", "sprites/characters/charSheetJasonguard.png", "sprites/characters/charSheetJasonguard.json"); + this.load.atlas("charSheetHog", "sprites/characters/charSheetHog.png", "sprites/characters/charSheetHog.json"); + this.load.atlas("charSheetRaceDirector", "sprites/characters/charSheetRaceDirector.png", "sprites/characters/charSheetRaceDirector.json"); + this.load.atlas("charSheetFoxxy", "sprites/characters/charSheetFoxxy.png", "sprites/characters/charSheetFoxxy.json"); + this.load.atlas("charSheetRahy", "sprites/characters/charSheetRahy.png", "sprites/characters/charSheetRahy.json"); + this.load.atlas("charSheetRahyMechanic", "sprites/characters/charSheetRahyMechanic.png", "sprites/characters/charSheetRahyMechanic.json"); + this.load.atlas("charSheetVip", "sprites/characters/charSheetVip.png", "sprites/characters/charSheetVip.json"); + this.load.atlas("charSheetJay", "sprites/characters/charSheetJay.png", "sprites/characters/charSheetJay.json"); + this.load.atlas("charSheetJo", "sprites/characters/charSheetJo.png", "sprites/characters/charSheetJo.json"); + this.load.atlas("charSheetExpressions", "sprites/characters/charSheetExpressions.png", "sprites/characters/charSheetExpressions.json"); + + this.load.image("texInvisible", "sprites/texInvisible.png"); + + //this.load.image("itenDreamKey", "sprites/inventory/itemDreamKey00.png"); + //atlas + this.load.atlas("atlasAll", "sprites/atlas/texAll.png", "sprites/atlas/texAll.json"); + this.load.atlas("atlasAdverts", "sprites/atlas/texAdverts.png", "sprites/atlas/texAdverts.json"); + this.load.atlas("atlasObstacles", "sprites/atlas/texObstacles.png", "sprites/atlas/texObstacles.json"); + this.load.atlas("atlasFire", "sprites/atlas/texFire.png", "sprites/atlas/texFire.json"); + this.load.atlas("atlasPlating", "sprites/atlas/texPlating.png", "sprites/atlas/texPlating.json"); + this.load.atlas("atlasUi", "sprites/atlas/texUi.png", "sprites/atlas/texUi.json"); + this.load.atlas("atlasDesktopBackgrounds", "sprites/atlas/texDesktopBackgrounds.png", "sprites/atlas/texDesktopBackgrounds.json"); + this.load.atlas("atlasFps", "sprites/atlas/texFps.png", "sprites/atlas/texFps.json"); + this.load.atlas("atlasObjects", "sprites/atlas/texObjects.png", "sprites/atlas/texObjects.json"); + /* + //FPS tex + this.load.image("sprFPSstand", "sprites/fps_tex/fps_tex_128_stand.png"); + this.load.image("sprFPSwalk_0", "sprites/fps_tex/fps_tex_128_walk_0.png"); + this.load.image("sprFPSwalk_1", "sprites/fps_tex/fps_tex_128_walk_1.png"); + this.load.image("sprFPSwalk_2", "sprites/fps_tex/fps_tex_128_walk_2.png"); + this.load.image("sprFPSwalk_3", "sprites/fps_tex/fps_tex_128_walk_3.png"); + this.load.image("sprFPSuse", "sprites/fps_tex/fps_tex_128_use.png"); + this.load.image("sprFPSpoint", "sprites/fps_tex/fps_tex_128_use_point.png"); + this.load.image("sprFPSinventory", "sprites/fps_tex/fps_tex_128_inventory.png"); + */ + + //story intro + this.load.image("sprStoryPolitics00", "sprites/story/storyPolitics01.png"); + this.load.image("sprStoryLoop00", "sprites/story/storyLoop01.png"); + this.load.image("sprStoryRacing00", "sprites/story/storyRacing01.png"); + + this.load.image("infoRake00", "sprites/infoRake00.png"); + this.load.image("infoRake01", "sprites/infoRake01.png"); + this.load.image("infoRake02", "sprites/infoRake02.png"); + + this.load.image("sprCockpitMockup", "sprites/sprCockpitMockup.png"); + + //defaults + this.load.image("sprDebugTexture", "sprites/sprDebugTexture.png"); + this.load.image("sprDebugTarget00", "sprites/sprDebugTarget00.png"); + this.load.image("sprObsDebugTrigger_0", "sprites/sprDebugTrigger00.png"); + this.load.image("sprDebugArrow00", "sprites/sprDebugArrow00.png"); + this.load.image("sprDebugQuadPoint0", "sprites/sprDebugQuadPoint0.png"); + this.load.image("sprDebugQuadPoint1", "sprites/sprDebugQuadPoint1.png"); + this.load.image("sprDebugQuadPoint2", "sprites/sprDebugQuadPoint2.png"); + this.load.image("sprDebugQuadPoint3", "sprites/sprDebugQuadPoint3.png"); + this.load.image("sprDebugQuadPoint4", "sprites/sprDebugQuadPoint4.png"); + this.load.image("sprDebugQuadPointCenter", "sprites/sprDebugQuadPointCenter.png"); + this.load.image("sprUiMenuBg", "sprites/sprUiMenuBg.png"); + + //AUDIO + /*this.load.audio("sndCaveSynth", "sounds/synth.mp3"); + this.load.audio("sndCaveDonner", "sounds/doennerOnly.mp3"); + this.load.audio("sndCavePiano", "sounds/klavierAmericanPower.mp3"); + this.load.audio("sndCaveGuitarIntro", "sounds/gitarreIntro.mp3");*/ + + this.loadTxt = this.add + .bitmapText(0, this.game.config.height * 0.5 - 32, "uiFont", "LOADING: 0%", 14, 1) + .setOrigin(0.5) + .setLetterSpacing(0); + this.ancient = this.add.sprite(0, 0, "sprPixelMan").setScale(2); + this.pixel = this.add.sprite(0, -48, "sprPixelTurn").setScale(2); + + let turnAnim = this.anims.create({ + key: "turning", + frames: this.anims.generateFrameNumbers("sprPixelTurn"), + frameRate: 32, + repeat: -1, + }); + this.pixel.play("turning"); + this.logoDidRepeat = 0; + this.pixel.on( + "animationrepeat", + function () { + this.logoDidRepeat += 1; + }, + this, + ); + + this.load.on("progress", this.updateProgressDisplay, this); + + if (this.game.config.width < this.game.config.height) { + isMobile = true; + } + //console.log(isMobile) + // + console.log("init some flags"); + + flagManager.setFlag("track00record", "-1"); + flagManager.setFlag("track01record", "-1"); + flagManager.setFlag("track02record", "-1"); + flagManager.setFlag("track03record", "-1"); + + //this.input.setDefaultCursor("url(./assets/cursors/cursor.cur), default"); + } + + create() { + this.load.off("progress", this.updateProgressDisplay, this); + //this.cache.bitmapFont.get("segoeUI_16").data.lineHeight = 16; + } + + update() { + if (this.logoDidRepeat >= 2) { + this.scene.start("ScnSavegameCheck"); + //this.scene.start("Scn3d", { level: "lobby00" }); + } + } + + updateProgressDisplay(_pct) { + let txt = "LOADING: " + String(Math.floor(_pct * 100)) + "%\n"; + if (_pct === 1) { + txt += "decoding audio"; + } + this.loadTxt.setText(txt); + } +} diff --git a/src/scnMain.js b/src/scnMain.js new file mode 100755 index 0000000..077683b --- /dev/null +++ b/src/scnMain.js @@ -0,0 +1,73 @@ +//import Class from "./subfolder/class.js"; + +export default class ScnMain extends Phaser.Scene { + + constructor() { + super("ScnMain"); + } + + init(_data) { + + } + + create() { + //console.log(this); + this.cameras.main.setScroll(-this.game.config.width * 0.5, -this.game.config.height * 0.5); + this.cameras.main.setBackgroundColor(0x000000); + + this.left = this.game.config.width * -0.5; + this.right = this.game.config.width * 0.5; + this.top = this.game.config.height * -0.5; + this.bottom = this.game.config.height * 0.5; + + this.cursors = this.input.keyboard.createCursorKeys(); + this.keys = { + e: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.E), + q: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Q), + w: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W), + a: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A), + s: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S), + d: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D), + space: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE), + end: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.END), + one: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.ONE), + two: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.TWO), + three: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.THREE), + four: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.FOUR), + five: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.FIVE), + six: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SIX), + seven: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SEVEN), + eight: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.EIGHT), + nine: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.NINE), + zero: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.ZERO), + tab: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.TAB), + plus: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.NUMPAD_ADD), + minus: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.NUMPAD_SUBSTRACT), + } + + /*this.keys.q.on("down", (_key, _event) => { + _event.stopPropagation(); + console.log(navigator.getGamepads()[Math.max(0, gamepadsConnected - 1)]); + }, this);*/ + + this.noise = this.plugins.get("rexperlinplugin").add(0); + //random noise value + let x,y,z = 0; + let rn = this.noise.simplex3(x, y ,z); + + this.loadTxt = this.add.bitmapText(0, 0, "whiteRabbit_16", "Deeper\nand\nDEEPER", 16, 1).setOrigin(0.5); + + this.tests = []; + for(let i = 0 ; i < 100 ; i++){ + rn = this.noise.simplex3(i, 0, 0); + this.tests.push(this.add.sprite(i*32, rn * 32, "sprDesert00")); + } + } + + update(_time, _delta){ + /*this.delta.current += _delta; + while (this.delta.current >= this.delta.treshold){ + this.delta.current -= this.delta.treshold; + }*/ + } +} \ No newline at end of file diff --git a/src/scnMainMenu.js b/src/scnMainMenu.js new file mode 100755 index 0000000..4c94404 --- /dev/null +++ b/src/scnMainMenu.js @@ -0,0 +1,100 @@ +import Hand from "./hand.js"; +import Button from "./ui/button.js"; +import { SliderHorizontal, SliderVertical } from "./ui/slider.js"; + +export default class ScnMainMenu extends Phaser.Scene { + + constructor() { + super("ScnMainMenu"); + } + + init(_data) { + + } + + create() { + this.cameras.main.setScroll(-this.game.config.width * 0.5, -this.game.config.height * 0.5); + this.cameras.main.setBackgroundColor(0x131313); + + //$("#optionbox").show(); + + this.saveGame = this.getFreshSaveGame(); + if (localStorage.getItem(SAVEGAMENAME) === null || localStorage.getItem(SAVEGAMENAME) === "null") { + console.log("creating savegame"); + localStorage.setItem(SAVEGAMENAME, JSON.stringify(this.saveGame)); + } else { + this.saveGame = JSON.parse(localStorage.getItem(SAVEGAMENAME)); + /*if (this.checkSaveGameInegrity() === false) { + console.warn("found corrupt savegame, generating a new one") + this.saveGame = this.getFreshSaveGame(); + localStorage.setItem(SAVEGAMENAME, JSON.stringify(this.saveGame)); + }*/ + } + + //this.sprTitle = this.add.sprite(0, 0, "sprTitle00"); + + //this.ancient = this.add.sprite(0, -64, "sprPixelMan").setScale(1); + this.pixel = this.add.sprite(0, -48, "sprPixelTurn").setScale(3); + let turnAnim = this.anims.create({ + key: "turningMenu", + frames: this.anims.generateFrameNumbers("sprPixelTurn"), + frameRate: 32, + repeat: -1 + }); + this.pixel.play("turningMenu"); + + this.hand = new Hand(this); + + /*this.tweenPlay = this.add.tween({ + targets: this.btnToGame.sprite, + y: -64, + duration: 2000, + ease: "power2", + onComplete: () => { + console.log("complete") + } + });*/ + + /* + this.sliMouse = new SliderHorizontal(this, { x: 0, y: -96 }, 1, 128); + this.sliMouse.move(0, -96); + this.sliMouse.releaseFunc = () => { + console.log(this.sliMouse.value); + } + */ + + this.btnToGame = new Button(this, {x: 0, y: 32}, "sprBtn00", "Play", false, () => { + this.scene.start("Scn3d", { level: "lobby00" }); + }); + + this.btnToEditor = new Button(this, { x: 0, y: 96 }, "sprBtn00", "Editor", false, () => { + $("#optionbox").hide(); + this.scene.start("Scn3d", { level: "modelBuilder" }); + }); + } + + update(_time, _delta){ + //console.log(_delta) + this.hand.update(); + + this.btnToGame.update(); + this.btnToEditor.update(); + + //this.sliMouse.update(); + } + + getFreshSaveGame() { + return { + savedModels: [], + sound: { + music: OPTIONS.sound.music, + sfx: OPTIONS.sound.sfx, + speech: OPTIONS.sound.speech + }, + effects: { + screenshake: OPTIONS.effects.screenshake, + shader: OPTIONS.effects.shader + } + } + } +} \ No newline at end of file diff --git a/src/scnSavegameCheck.js b/src/scnSavegameCheck.js new file mode 100755 index 0000000..10ed084 --- /dev/null +++ b/src/scnSavegameCheck.js @@ -0,0 +1,87 @@ +export default class ScnSavegameCheck extends Phaser.Scene { + + constructor() { + super("ScnSavegameCheck"); + } + + init(_data) { + + } + + create() { + this.cameras.main.setScroll(-this.game.config.width * 0.5, -this.game.config.height * 0.5); + this.cameras.main.setBackgroundColor(0x131313); + + //$("#optionbox").show(); + + this.saveGame = this.getFreshSaveGame(); + if (localStorage.getItem(SAVEGAMENAME) === null || localStorage.getItem(SAVEGAMENAME) === "null") { + console.log("creating savegame"); + localStorage.setItem(SAVEGAMENAME, JSON.stringify(this.saveGame)); + } else { + this.saveGame = JSON.parse(localStorage.getItem(SAVEGAMENAME)); + if (this.checkSaveGameInegrity() === false) { + console.warn("found corrupt savegame, generating a new one") + this.saveGame = this.getFreshSaveGame(); + localStorage.setItem(SAVEGAMENAME, JSON.stringify(this.saveGame)); + }else{ + console.log("loaded savegame") + console.log(this.saveGame) + } + } + + //this.scene.start("Scn3d", { level: "marketSquareApartements00", params: {lounge: false} }); + this.scene.start("Scn3d", { level: "mainMenu", params: null }); + } + + update(_time, _delta){ + + } + + getFreshSaveGame() { + return { + sound: { + master: OPTIONS.sound.master, + music: OPTIONS.sound.music, + sfx: OPTIONS.sound.sfx, + speech: OPTIONS.sound.speech, + mute: OPTIONS.sound.mute + }, + effects: { + screenshake: OPTIONS.effects.screenshake, + shader: OPTIONS.effects.shader, + viewDistWalk: OPTIONS.effects.viewDistWalk, + viewDistShip: OPTIONS.effects.viewDistShip + }, + controls: { + mouse: { + sensitivity: 3 + }, + mobile: false + }, + config: { + preferredCam: 0, + collisionRadar: 1, + idealLine: 1, + hideUI: false + }, + version: 0.2, + forceFresh: false //uncomment for fresh savegame force + } + } + + checkSaveGameInegrity(){ + let correct = true; + + let save = JSON.parse(localStorage.getItem(SAVEGAMENAME)); + let saveKeys = Object.keys(save); + let freshData = this.getFreshSaveGame() + let freshKeys = Object.keys(freshData); + + correct = saveKeys.length === freshKeys.length; + if(freshData.forceFresh === true){ + return false; + } + return correct; + } +} \ No newline at end of file diff --git a/src/soundManager.js b/src/soundManager.js new file mode 100644 index 0000000..c9cb712 --- /dev/null +++ b/src/soundManager.js @@ -0,0 +1,449 @@ +export default class SoundManager{ + constructor(_scene){ + this.scene = _scene; + + //menu select + this.menuSelectSound = { + stopAfterPlayback: false, + array: [ + SOUNDS.menuSelect.play() + ], + howlGroup: SOUNDS.menuSelect, + counter: { + current: 0, + reset: 999 + } + } + for(let s of this.menuSelectSound.array){ + this.menuSelectSound.howlGroup.stop(s); + } + //menu error + this.menuErrorSound = { + stopAfterPlayback: false, + array: [ + SOUNDS.menuError.play() + ], + howlGroup: SOUNDS.menuError, + counter: { + current: 0, + reset: 999 + } + } + for(let s of this.menuErrorSound.array){ + this.menuErrorSound.howlGroup.stop(s); + } + + //computer startup + this.computerStartSound = { + stopAfterPlayback: false, + array: [ + SOUNDS.computerStart.play() + ], + howlGroup: SOUNDS.computerStart, + counter: { + current: 0, + reset: 999 + } + } + for(let s of this.computerStartSound.array){ + this.computerStartSound.howlGroup.stop(s); + } + + //foot steps + this.stepSound = { + stopAfterPlayback: true, + array: [ + SOUNDS.stepsHallway.play("step0"), + SOUNDS.stepsHallway.play("step1"), + SOUNDS.stepsHallway.play("step2"), + SOUNDS.stepsHallway.play("step3"), + SOUNDS.stepsHallway.play("step4"), + SOUNDS.stepsHallway.play("step5"), + SOUNDS.stepsHallway.play("step6"), + SOUNDS.stepsHallway.play("step7") + ], + howlGroup: SOUNDS.stepsHallway, + counter: { + current: 0, + reset: 599 + } + } + for(let s of this.stepSound.array){ + this.stepSound.howlGroup.stop(s); + } + + //raceAnnouncer + this.raceAnnouncer = { + stopAfterPlayback: true, + array: [ + SOUNDS.raceAnnouncer.play("newRecord"), + SOUNDS.raceAnnouncer.play("three"), + SOUNDS.raceAnnouncer.play("two"), + SOUNDS.raceAnnouncer.play("one"), + SOUNDS.raceAnnouncer.play("go"), + SOUNDS.raceAnnouncer.play("finalLap"), + ], + howlGroup: SOUNDS.raceAnnouncer, + counter: { + current: 0, + reset: 999 + } + } + for(let s of this.raceAnnouncer.array){ + this.raceAnnouncer.howlGroup.stop(s); + } + + //swooshes + this.swooshSound = { + stopAfterPlayback: true, + array: [ + SOUNDS.shipSwoosh.play("swoosh0"), + SOUNDS.shipSwoosh.play("swoosh1") + ], + howlGroup: SOUNDS.shipSwoosh, + counter: { + current: 0, + reset: 999 + } + } + for(let s of this.swooshSound.array){ + this.swooshSound.howlGroup.stop(s); + } + + //heatWarning + this.heatWarningSound = { + stopAfterPlayback: false, + array: [ + SOUNDS.shipHeatWarning.play() + ], + howlGroup: SOUNDS.shipHeatWarning, + counter: { + current: 0, + reset: 999 + } + } + for(let s of this.heatWarningSound.array){ + this.heatWarningSound.howlGroup.stop(s); + } + //scrape + this.scrapeSound = { + stopAfterPlayback: false, + array: [ + SOUNDS.shipScraping.play() + ], + howlGroup: SOUNDS.shipScraping, + counter: { + current: 0, + reset: 999 + } + } + for(let s of this.scrapeSound.array){ + this.scrapeSound.howlGroup.stop(s); + } + //bumps + this.bumpSound = { + stopAfterPlayback: true, + array: [ + SOUNDS.shipBump.play("bump0"), + SOUNDS.shipBump.play("bump1"), + SOUNDS.shipBump.play("bump2") + ], + howlGroup: SOUNDS.shipBump, + counter: { + current: 0, + reset: 999 + } + } + for(let s of this.bumpSound.array){ + this.bumpSound.howlGroup.stop(s); + } + + //engine + this.engineSound = { + stopAfterPlayback: false, + array: [ + SOUNDS.shipEngine00.play() + ], + howlGroup: SOUNDS.shipEngine00, + counter: { + current: 0, + reset: 999 + } + } + for(let s of this.engineSound.array){ + this.engineSound.howlGroup.stop(s); + } + this.engineRotorSound = { + stopAfterPlayback: false, + array: [ + SOUNDS.shipEngine01.play() + ], + howlGroup: SOUNDS.shipEngine01, + counter: { + current: 0, + reset: 999 + } + } + for(let s of this.engineRotorSound.array){ + this.engineRotorSound.howlGroup.stop(s); + } + + //music tracks + this.musicMenu00 = { + stopAfterPlayback: false, + array: [ + SOUNDS.musicMenu00.play() + ], + howlGroup: SOUNDS.musicMenu00, + counter: { + current: 0, + reset: 999 + } + } + for(let s of this.musicMenu00.array){ + this.musicMenu00.howlGroup.stop(s); + } + + this.musicMenu01 = { + stopAfterPlayback: false, + array: [ + SOUNDS.musicMenu01.play() + ], + howlGroup: SOUNDS.musicMenu01, + counter: { + current: 0, + reset: 999 + } + } + for(let s of this.musicMenu01.array){ + this.musicMenu01.howlGroup.stop(s); + } + + this.musicAcidLoop00 = { + stopAfterPlayback: false, + array: [ + SOUNDS.musicAcidLoop00.play() + ], + howlGroup: SOUNDS.musicAcidLoop00, + counter: { + current: 0, + reset: 999 + } + } + for(let s of this.musicAcidLoop00.array){ + this.musicAcidLoop00.howlGroup.stop(s); + } + + this.musicAcidLoop01 = { + stopAfterPlayback: false, + array: [ + SOUNDS.musicAcidLoop01.play() + ], + howlGroup: SOUNDS.musicAcidLoop01, + counter: { + current: 0, + reset: 999 + } + } + for(let s of this.musicAcidLoop01.array){ + this.musicAcidLoop01.howlGroup.stop(s); + } + + this.musicCalmLoop00 = { + stopAfterPlayback: false, + array: [ + SOUNDS.musicCalmLoop00.play() + ], + howlGroup: SOUNDS.musicCalmLoop00, + counter: { + current: 0, + reset: 999 + } + } + for(let s of this.musicCalmLoop00.array){ + this.musicCalmLoop00.howlGroup.stop(s); + } + + //music sprite + this.musicBassLoop00 = { + stopAfterPlayback: false, + array: [ + SOUNDS.musicBassLoop00.play(), + ], + howlGroup: SOUNDS.musicBassLoop00, + counter: { + current: 0, + reset: 8000 + } + } + for(let s of this.musicBassLoop00.array){ + this.musicBassLoop00.howlGroup.stop(s); + } + this.musicSynthLoop00 = { + stopAfterPlayback: false, + array: [ + SOUNDS.musicSynthLoop00.play(), + ], + howlGroup: SOUNDS.musicSynthLoop00, + counter: { + current: 0, + reset: 8000 + } + } + for(let s of this.musicSynthLoop00.array){ + this.musicSynthLoop00.howlGroup.stop(s); + } + this.musicPianoLoop00 = { + stopAfterPlayback: false, + array: [ + SOUNDS.musicPianoLoop00.play(), + ], + howlGroup: SOUNDS.musicPianoLoop00, + counter: { + current: 0, + reset: 8000 + } + } + for(let s of this.musicPianoLoop00.array){ + this.musicPianoLoop00.howlGroup.stop(s); + } + this.musicRythmLoop00 = { + stopAfterPlayback: false, + array: [ + SOUNDS.musicRythmLoop00.play(), + ], + howlGroup: SOUNDS.musicRythmLoop00, + counter: { + current: 0, + reset: 8000 + } + } + for(let s of this.musicRythmLoop00.array){ + this.musicRythmLoop00.howlGroup.stop(s); + } + + + this.allRef = [ + this.menuSelectSound, + this.menuErrorSound, + this.computerStartSound, + this.raceAnnouncer, + this.swooshSound, + this.stepSound, + this.bumpSound, + this.engineSound, + this.engineRotorSound, + this.scrapeSound, + this.heatWarningSound, + this.musicMenu00, + this.musicMenu01, + this.musicAcidLoop00, + this.musicAcidLoop01, + this.musicCalmLoop00, + this.musicBassLoop00, + this.musicSynthLoop00, + this.musicPianoLoop00, + this.musicRythmLoop00, + ]; + + this.soundRef = [ + this.menuSelectSound, + this.menuErrorSound, + this.computerStartSound, + this.raceAnnouncer, + this.swooshSound, + this.stepSound, + this.bumpSound, + this.engineSound, + this.engineRotorSound, + this.scrapeSound, + this.heatWarningSound + ] + + this.musicRef = [ + this.musicMenu00, + this.musicMenu01, + this.musicAcidLoop00, + this.musicAcidLoop01, + this.musicCalmLoop00, + this.musicBassLoop00, + this.musicSynthLoop00, + this.musicPianoLoop00, + this.musicRythmLoop00, + ] + + //base volume + Howler.volume(0.75); + } + + update(_delta){ + for(let ar of this.allRef){ + if(ar.stopAfterPlayback === true && ar.howlGroup.playing() === true){ + ar.counter.current += 1 * _delta; + if(ar.counter.current >= ar.counter.reset){ + ar.counter.current = 0; + for(let s of ar.array){ + ar.howlGroup.stop(s); + } + ar.howlGroup.stop(); + } + } + } + } + + playSound(_sound){ + for(let s of _sound.array){ + _sound.howlGroup.stop(s); + } + _sound.howlGroup.stop(); + + _sound.howlGroup.play(); + _sound.counter.current = 0; + } + + stopSound(_sound){ + //_sound.howlGroup.stop(_sound.array[0]); + _sound.howlGroup.stop(); + _sound.counter.current = 0; + } + + playRandomSound(_sound){ + //play random sound from soundsprite + for(let s of _sound.array){ + _sound.howlGroup.stop(s); + } + _sound.howlGroup.stop(); + + let r = _sound.array[Math.floor(Math.random() * _sound.array.length)]; + _sound.howlGroup.play(r); + _sound.counter.current = 0; + } + + playSpecificSound(_sound, _no){ + //play specific sound from soundsprite difined by _no + for(let s of _sound.array){ + _sound.howlGroup.stop(s); + } + _sound.howlGroup.stop(); + + let r = _sound.array[_no]; + _sound.howlGroup.play(r); + _sound.counter.current = 0; + } + + playLayeredMusic(_musicArray){ + for(let s of _musicArray){ + this.playSound(s); + } + } + + stopLayeredMusic(_musicArray){ + for(let s of _musicArray){ + this.stopSound(s); + } + } + + fadeMusicLayer(_musicArray, _layerNo, _volFrom, _volTo, _dur = 1000){ + _musicArray[_layerNo].howlGroup.fade(_volFrom, _volTo, _dur); + } +} diff --git a/src/ui/button.js b/src/ui/button.js new file mode 100755 index 0000000..71be489 --- /dev/null +++ b/src/ui/button.js @@ -0,0 +1,219 @@ +export default class Button { + constructor(_scene, _pos, _atlas, _frame, _text, _togglebutton, _func) { + this.scene = _scene; + this.pos = _pos; + this.text = _text; + this.func = _func; + this.toggleOffFunc = () => { }; + this.hoverInFunc = () => { }; + this.hoverOutFunc = () => { }; + this.hovering = false; + this.tintFill = true; + this.tintText = true; + this.data = {} + + this.colors = { + out: 0xfff1e8, + over: 0x29adff, + on: 0x00e436, + off: 0xad2900 + } + this.changeColor = true; + this.useOtherTextColor = false; + this.textColors = { + out: 0xfff1e8, + over: 0x29adff, + on: 0x00e436, + off: 0xad2900 + } + + this.states = { + out: 0, + over: 1, + on: 2, + off: 3 + } + this.state = this.states.out; + this.togglebutton = _togglebutton; + this.active = false; + + this.sprite = this.scene.add.sprite(_pos.x, _pos.y, _atlas, _frame); + this.sprite.depth = 10000; + this.txt = this.scene.add.bitmapText(_pos.x, _pos.y, "uiFont", _text, 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.txt.depth = 10000; + + this.colorInState(this.state); + } + + update() { + //if(this.sprite.getBounds().contains(this.scene.input.activePointer.worldX, this.scene.input.activePointer.worldY)){ + if (this.sprite.getBounds().contains(this.scene.hand.pos.x, this.scene.hand.pos.y)) { + if (this.scene.hand.pressed === false) { + if (this.active === false) { + this.switchState(this.states.over); + if (this.hovering === false) { + this.hoverInFunc(); + this.hovering = true; + this.scene.soundManager.playSound(this.scene.soundManager.menuSelectSound); + } + } else { + this.switchState(this.states.over); + } + } + if (this.scene.hand.justPressed === true) { + if (this.active === true) { + this.switchState(this.states.over); + } else { + this.switchState(this.states.on); + } + } + if (this.scene.hand.justReleased === true) { + if (this.togglebutton === true) { + if (this.active === false) { + this.active = true; + this.func(); + } else { + this.active = false; + this.toggleOffFunc(); + } + } else { + this.func(); + } + } + } else { + if (this.active === false) { + this.switchState(this.states.out); + } else { + this.switchState(this.states.on); + } + + if (this.hovering === true) { + this.hoverOutFunc(); + this.hovering = false; + } + } + } + + simulateClick(_triggerFunction = true) { + if (this.togglebutton === true) { + if (this.active === false) { + this.active = true; + if(_triggerFunction === true){ + this.func(); + } + } else { + this.active = false; + if (_triggerFunction === true) { + this.toggleOffFunc(); + } + } + } else { + if (_triggerFunction === true) { + this.func(); + } + } + } + + switchState(_state) { + if (this.state !== _state) { + this.state = _state; + if (this.changeColor === true) { + this.colorInState(this.state); + } + } + } + + colorInState(_state) { + if (this.tintFill === true) { + switch (this.state) { + case this.states.out: + this.sprite.setTintFill(this.colors.out); + if (this.tintText === true) { this.txt.setTintFill(this.colors.out); } + if (this.useOtherTextColor === true) { this.txt.setTintFill(this.textColors.out); } + break; + case this.states.over: + this.sprite.setTintFill(this.colors.over); + if (this.tintText === true) { this.txt.setTintFill(this.colors.over); } + if (this.useOtherTextColor === true) { this.txt.setTintFill(this.textColors.over); } + break; + case this.states.on: + this.sprite.setTintFill(this.colors.on); + if (this.tintText === true) { this.txt.setTintFill(this.colors.out); } + if (this.useOtherTextColor === true) { this.txt.setTintFill(this.textColors.on); } + break; + case this.states.off: + this.sprite.setTintFill(this.colors.off); + if (this.tintText === true) { this.txt.setTintFill(this.colors.out); } + if (this.useOtherTextColor === true) { this.txt.setTintFill(this.textColors.off); } + break; + default: + break; + } + } else { + switch (this.state) { + case this.states.out: + this.sprite.setTint(this.colors.out); + if (this.tintText === true) { this.txt.setTint(this.colors.out); } + if (this.useOtherTextColor === true) { this.txt.setTintFill(this.textColors.out); } + break; + case this.states.over: + this.sprite.setTint(this.colors.over); + if (this.tintText === true) { this.txt.setTint(this.colors.over); } + if (this.useOtherTextColor === true) { this.txt.setTintFill(this.textColors.over); } + break; + case this.states.on: + this.sprite.setTint(this.colors.on); + if (this.tintText === true) { this.txt.setTint(this.colors.out); } + if (this.useOtherTextColor === true) { this.txt.setTintFill(this.textColors.on); } + break; + case this.states.off: + this.sprite.setTint(this.colors.off); + if (this.tintText === true) { this.txt.setTint(this.colors.out); } + if (this.useOtherTextColor === true) { this.txt.setTintFill(this.textColors.off); } + break; + default: + break; + } + } + } + + setDepth(_depth) { + this.sprite.depth = _depth; + this.txt.depth = _depth; + } + + setSpriteVisibility(_bool) { + if (_bool === true) { + this.sprite.alpha = 1; + } else { + this.sprite.alpha = 0; + } + } + + setHighlighting(_bool) { + if (_bool === true) { + this.changeColor = true; + this.colorInState(); + } else { + this.changeColor = false; + this.sprite.clearTint(); + } + } + + move(_x, _y) { + this.sprite.x = _x; + this.sprite.y = _y; + this.txt.x = _x; + this.txt.y = _y; + } + + addToContainer(_container) { + _container.add(this.sprite); + _container.add(this.txt); + } + + destroy() { + this.sprite.destroy(); + this.txt.destroy(); + } +} diff --git a/src/ui/computer/programs/programCalendarAero.js b/src/ui/computer/programs/programCalendarAero.js new file mode 100644 index 0000000..c0ebae1 --- /dev/null +++ b/src/ui/computer/programs/programCalendarAero.js @@ -0,0 +1,115 @@ +import Button from "../../button.js"; + +export default class ProgramCalendar { + constructor(_scene, _computer, _window) { + this.scene = _scene; + this.computer = _computer; + this.window = _window; + + this.tiles = []; + let i = 0; + for (let yy = 0; yy < 4; yy++) { + for (let xx = 0; xx < 7; xx++) { + /*tile.colors = { + out: 0x83769c, + over: 0x29adff, + on: 0x00e436, + off: 0xad2900 + }*/ + if (i === 10) { + this.tiles.push(new Button(this.scene, { x: this.window.pos.x + 16 + (xx * 37), y: this.window.pos.y + 32 + (yy * 37) }, "atlasUi", "sprDesktopCalendarTileMarked", String(i + 1), false, () => { + this.txtNoData.alpha = 0; + this.textContainer.alpha = 1; + })); + } else if (i === 22) { + this.tiles.push(new Button(this.scene, { x: this.window.pos.x + 16 + (xx * 37), y: this.window.pos.y + 32 + (yy * 37) }, "atlasUi", "sprDesktopCalendarTile", String(i + 1), false, () => { + this.txtNoData.setText("I see you."); + this.txtNoData.alpha = 1; + this.textContainer.alpha = 0; + })); + } else { + this.tiles.push(new Button(this.scene, { x: this.window.pos.x + 16 + (xx * 37), y: this.window.pos.y + 32 + (yy * 37) }, "atlasUi", "sprDesktopCalendarTile", String(i + 1), false, () => { + this.txtNoData.setText("503: Service Unavailable"); + this.txtNoData.alpha = 1; + this.textContainer.alpha = 0; + })); + } + + + let tile = this.tiles[this.tiles.length - 1]; + + tile.tintFill = false; + tile.tintText = false; + tile.colorInState(tile.states.out); + tile.setDepth(this.window.depth + 1); + this.window.container.add(tile.sprite); + this.window.container.add(tile.txt); + + i += 1; + } + } + + this.textContainer = this.scene.add.container(0, 0); + this.window.container.add(this.textContainer); + + this.txtTrackTitle = this.scene.add.bitmapText((this.window.pos.x + this.window.width * 0.5) - 64, this.window.pos.y + (this.window.height * 0.5) + 64, "uiFont", "upcoming race:", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.txtTrackTitle.depth = this.depth + 1; + this.txtTrackTitle.setTintFill(0x83769c); + this.textContainer.add(this.txtTrackTitle); + + this.txtTrackname = this.scene.add.bitmapText((this.window.pos.x + this.window.width * 0.5) - 64, this.window.pos.y + (this.window.height * 0.5) + 104 - 14, "uiFont", "Metro Loop", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.txtTrackname.depth = this.depth + 1; + this.txtTrackname.setTintFill(0x83769c); + this.textContainer.add(this.txtTrackname); + + this.txtSessionTitle = this.scene.add.bitmapText((this.window.pos.x + this.window.width * 0.5) + 64, this.window.pos.y + (this.window.height * 0.5) + 64, "uiFont", "upcoming sessions:", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.txtSessionTitle.depth = this.depth + 1; + this.txtSessionTitle.setTintFill(0x83769c); + this.textContainer.add(this.txtSessionTitle); + + this.txtSessions = this.scene.add.bitmapText(this.window.pos.x + (this.window.width * 0.5) + 32, this.window.pos.y + (this.window.height * 0.5) + 104, "uiFont", "09:00\n11:00\n14:00", 14, 0).setOrigin(1, 0.5).setLetterSpacing(0); + this.txtSessions.depth = this.depth + 1; + this.txtSessions.setTintFill(0x83769c); + this.textContainer.add(this.txtSessions); + + this.txtSessionNames = this.scene.add.bitmapText(this.window.pos.x + (this.window.width * 0.5) + 32, this.window.pos.y + (this.window.height * 0.5) + 104, "uiFont", " Free Practice\n Qualifying\n Race", 14, 0).setOrigin(0, 0.5).setLetterSpacing(0); + this.txtSessionNames.depth = this.depth + 1; + this.txtSessionNames.setTintFill(0x83769c); + this.textContainer.add(this.txtSessionNames); + //this.window.container.add(this.txtSessionNames); + + this.txtNoData = this.scene.add.bitmapText(this.window.pos.x + (this.window.width * 0.5) + 0, this.window.pos.y + (this.window.height * 0.5) + 104 - 14, "uiFont", "503: Service Unavailable", 14, 0).setOrigin(0.5, 0.5).setLetterSpacing(0); + this.txtNoData.depth = this.depth + 1; + this.txtNoData.setTintFill(0xff004d); + this.window.container.add(this.txtNoData); + + this.txtNoData.alpha = 0; + this.textContainer.alpha = 0; + } + + update() { + //console.log("update claendar") + for (let t of this.tiles) { + t.update(); + + if (t.hovering === true) { + this.computer.cursor.setTexture("atlasUi", "sprDesktopCursorTouch"); + } + } + } + + destroy() { + this.txtTrackTitle.destroy(); + this.txtTrackname.destroy(); + this.txtSessionTitle.destroy(); + this.txtSessions.destroy(); + this.txtSessionNames.destroy(); + this.textContainer.destroy(); + + this.txtNoData.destroy(); + + for (let t of this.tiles) { + t.destroy(); + } + } +} diff --git a/src/ui/computer/programs/programMessengerAero.js b/src/ui/computer/programs/programMessengerAero.js new file mode 100644 index 0000000..28333c6 --- /dev/null +++ b/src/ui/computer/programs/programMessengerAero.js @@ -0,0 +1,22 @@ +import Button from "../../button.js"; + +export default class ProgramMessenger { + constructor(_scene, _computer, _window) { + this.scene = _scene; + this.computer = _computer; + this.window = _window; + + this.txtDenied = this.scene.add.bitmapText(this.window.pos.x + (this.window.width * 0.5) + 0, this.window.pos.y + (this.window.height * 0.5), "uiFont", "403: Access Denied", 14, 0).setOrigin(0.5, 0.5).setLetterSpacing(0); + this.txtDenied.depth = this.depth + 1; + this.txtDenied.setTintFill(0xff004d); + this.window.container.add(this.txtDenied); + } + + update() { + //console.log("update messages"); + } + + destroy() { + this.txtDenied.destroy(); + } +} diff --git a/src/ui/computer/programs/programRegulationsAero.js b/src/ui/computer/programs/programRegulationsAero.js new file mode 100644 index 0000000..37a924d --- /dev/null +++ b/src/ui/computer/programs/programRegulationsAero.js @@ -0,0 +1,152 @@ +import Button from "../../button.js"; + +export default class ProgramRegulations{ + constructor(_scene, _computer, _window){ + this.scene = _scene; + this.computer = _computer; + this.window = _window; + + this.pageNo = 0; + this.pages = [{ + atlas: "", + asset: "", + name: "", + texts: [ + "Resistance Racing", + "technical Manual version 0.1", + "written by Joe Barber" + ] + },{ + atlas: "infoRake00", + asset: "", + name: "neutral pitch", + texts: [] + }, { + atlas: "infoRake01", + asset: "", + name: "good pitch", + texts: [] + }, { + atlas: "infoRake02", + asset: "", + name: "aggressive pitch", + texts: [] + }]; + this.pageMax = this.pages.length; + this.pageImage = this.scene.add.sprite(this.window.pos.x + this.window.width * 0.5, this.window.pos.y + this.window.height * 0.5, this.pages[this.pageNo].atlas, this.pages[this.pageNo].asset); + this.pageImage.depth = this.window.depth + 1; + this.window.container.add(this.pageImage); + + this.txtPreview = this.scene.add.bitmapText(this.window.pos.x + this.window.width * 0.5, this.window.pos.y + (this.window.height * 0.5) + 64 + 8, "uiFont", this.pages[this.pageNo].name, 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.txtPreview.depth = this.depth + 1; + this.txtPreview.setTintFill(0x83769c); + this.window.container.add(this.txtPreview); + + this.txtPageNo = this.scene.add.bitmapText(this.window.pos.x + this.window.width * 0.5, this.window.pos.y + this.window.height - 8, "uiFont", "1/10", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.txtPageNo.depth = this.depth + 1; + this.txtPageNo.setTintFill(0x83769c); + this.window.container.add(this.txtPageNo); + + this.texts = []; + + this.btnNext = new Button(this.scene, { x: this.window.pos.x + (this.window.width * 0.5) + 32, y: this.window.pos.y + (this.window.height * 1) - 8 }, "atlasUi", "sprBtn12", "", false, () => { + this.pageNo += 1; + if(this.pageNo >= this.pageMax){ + this.pageNo -= this.pageMax; + } + this.changePage(this.pageNo) + }); + this.btnNext.setDepth(this.window.depth + 1); + this.btnNext.colors = { + out: 0x83769c, + over: 0x29adff, + on: 0x00e436, + off: 0xad2900 + } + this.btnNext.tintFill = false; + this.btnNext.colorInState(this.btnNext.states.out); + this.window.container.add(this.btnNext.sprite); + this.window.container.add(this.btnNext.txt); + + this.btnPrev = new Button(this.scene, { x: this.window.pos.x + (this.window.width * 0.5) - 32, y: this.window.pos.y + (this.window.height * 1) - 8 }, "atlasUi", "sprBtn11", "", false, () => { + this.pageNo -= 1; + if(this.pageNo < 0){ + this.pageNo += this.pageMax; + } + this.changePage(this.pageNo) + }); + this.btnPrev.setDepth(this.window.depth + 1); + this.btnPrev.colors = { + out: 0x83769c, + over: 0x29adff, + on: 0x00e436, + off: 0xad2900 + } + this.btnPrev.tintFill = false; + this.btnPrev.colorInState(this.btnPrev.states.out); + this.window.container.add(this.btnPrev.sprite); + this.window.container.add(this.btnPrev.txt); + + this.changePage(0); + } + + changePage(_no) { + this.txtPageNo.setText(String(_no + 1) + '/' + String(this.pageMax)); + + let data = this.pages[this.pageNo]; + console.log(data) + if (data.texts.length > 0) { + this.pageImage.alpha = 0; + this.txtPreview.alpha = 0; + + for (let txt of this.texts) { + this.window.container.remove(txt); + txt.destroy(); + } + this.texts = []; + + let part = (this.window.height - 16) / data.texts.length; + for (let [i, d] of data.texts.entries()) { + //this.texts.push(this.scene.add.bitmapText(this.window.pos.x + this.window.width * 0.5, this.window.pos.y + (this.window.height * 0.5) + (part * i), "uiFont", d, 14, 0)) + this.texts.push(this.scene.add.bitmapText(this.window.pos.x + this.window.width * 0.5, this.window.pos.y + (part * i) + 16, "uiFont", d, 14, 0)); + let t = this.texts[this.texts.length - 1]; + t.setOrigin(0.5); + t.setLetterSpacing(0); + t.depth = this.depth + 1; + t.setTintFill(0x83769c); + this.window.container.add(t); + } + } else { + this.pageImage.alpha = 1; + this.pageImage.setTexture(this.pages[this.pageNo].atlas, this.pages[_no].asset); + this.txtPreview.alpha = 1; + this.txtPreview.setText(this.pages[_no].name); + + for (let txt of this.texts) { + this.window.container.remove(txt); + txt.destroy(); + } + this.texts = []; + } + } + + update(){ + this.btnNext.update(); + this.btnPrev.update(); + + if(this.btnNext.hovering === true || this.btnPrev.hovering === true){ + this.computer.cursor.setTexture("atlasUi", "sprDesktopCursorTouch"); + } + } + + destroy(){ + this.btnNext.destroy(); + this.btnPrev.destroy(); + this.txtPageNo.destroy(); + this.pageImage.destroy(); + + for (let txt of this.texts) { + txt.destroy(); + } + } +} diff --git a/src/ui/computer/programs/programSystemAero.js b/src/ui/computer/programs/programSystemAero.js new file mode 100644 index 0000000..b20114b --- /dev/null +++ b/src/ui/computer/programs/programSystemAero.js @@ -0,0 +1,236 @@ +import Button from "../../button.js"; +import PanelEscapeMenu from "../../panelEscapeMenu.js"; + +export default class ProgramSystem { + constructor(_scene, _computer, _window) { + this.scene = _scene; + this.computer = _computer; + this.window = _window; + + this.contSYS = this.scene.add.container(0, 0); + this.window.container.add(this.contSYS); + this.contAUX = this.scene.add.container(0, 0); + this.window.container.add(this.contAUX); + this.contAUX.alpha = 0; + /*this.contGFX = this.scene.add.container(0, 0); + this.contGFX.alpha = 0; + this.contCTL = this.scene.add.container(0, 0); + this.contCTL.alpha = 0; + this.activeContainer = this.contAUX;*/ + + this.options = { + sys: 0, + aux: 1, + gfx: 2, + ctl: 3 + } + this.currentOption = this.options.sys; + + //system options background + this.btnOptions = new Button(this.scene, { x: this.window.pos.x + this.window.width * 0.5, y: this.window.pos.y + 20 }, "atlasUi", "sprBtn13long", "options", false, () => { + console.log("aaa") + if (this.currentOption === this.currentOption.sys) { + this.currentOption = this.options.aux; + this.contSYS.alpha = 0; + this.contAUX.alpha = 1; + } + }); + this.btnOptions.setDepth(this.window.depth + 1); + this.btnOptions.colors = { + out: 0x83769c, + over: 0x29adff, + on: 0x00e436, + off: 0xad2900 + } + this.btnOptions.tintFill = false; + this.btnOptions.tintText = false; + this.btnOptions.colorInState(this.btnOptions.states.off); + this.contSYS.add(this.btnOptions.sprite); + this.contSYS.add(this.btnOptions.txt); + + this.backgroundNo = 0; + this.backgrounds = [{ + atlas: "atlasDesktopBackgrounds", + asset: "sprDesktopBackground00", + locked: false, + name: "Formula Aero" + }, { + atlas: "atlasDesktopBackgrounds", + asset: "sprDesktopBackground01", + locked: false, + name: "Long Nails" + }, { + atlas: "atlasDesktopBackgrounds", + asset: "sprDesktopBackground02", + locked: false, + name: "Dreams of the Overworld" + }, { + atlas: "atlasDesktopBackgrounds", + asset: "sprDesktopBackground03", + locked: false, + name: "SerpenTiles" + }, { + atlas: "atlasDesktopBackgrounds", + asset: "sprDesktopBackground03", + locked: true, + name: "SerpenTiles" + }, { + atlas: "atlasDesktopBackgrounds", + asset: "sprDesktopBackground04", + locked: false, + name: "Abstract Mirror 1 by Thisispow on Reddit" + }, { + atlas: "atlasDesktopBackgrounds", + asset: "sprDesktopBackground05", + locked: false, + name: "Abstract Mirror 2 by Thisispow on Reddit" + }, { + atlas: "atlasDesktopBackgrounds", + asset: "sprDesktopBackground06", + locked: false, + name: "Abstract Mirror 3 by Thisispow on Reddit" + }, { + atlas: "atlasDesktopBackgrounds", + asset: "sprDesktopBackground07", + locked: false, + name: "Red Ship Fast" + }, { + atlas: "atlasDesktopBackgrounds", + asset: "sprDesktopBackground08", + locked: false, + name: "Corporate Race" + }, { + atlas: "atlasDesktopBackgrounds", + asset: "sprDesktopBackground09", + locked: false, + name: "Metalheart" + }, { + atlas: "atlasDesktopBackgrounds", + asset: "sprDesktopBackground10", + locked: false, + name: "Tunnel" + }, { + atlas: "atlasDesktopBackgrounds", + asset: "sprDesktopBackground11", + locked: false, + name: "Gen X Soft Club - Tokyo Metro" + }]; + this.backgroundMax = this.backgrounds.length; + this.bgPreview = this.scene.add.sprite(this.window.pos.x + this.window.width * 0.5, this.window.pos.y + this.window.height * 0.5, this.backgrounds[this.backgroundNo].atlas, this.backgrounds[this.backgroundNo].asset); + this.bgPreview.depth = this.window.depth + 1; + this.bgPreview.setScale(0.25); + this.contSYS.add(this.bgPreview); + + this.txtPreview = this.scene.add.bitmapText(this.window.pos.x + this.window.width * 0.5, this.window.pos.y + (this.window.height * 0.5) + 64 + 8, "uiFont", this.backgrounds[this.backgroundNo].name, 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.txtPreview.depth = this.depth + 1; + this.txtPreview.setTintFill(0x83769c); + this.contSYS.add(this.txtPreview); + + this.btnNext = new Button(this.scene, { x: this.window.pos.x + this.window.width - 16, y: this.window.pos.y + this.window.height * 0.5 }, "atlasUi", "sprBtn12", "", false, () => { + this.backgroundNo += 1; + if (this.backgroundNo >= this.backgroundMax) { + this.backgroundNo -= this.backgroundMax; + } + this.changeBackgroundPreview(this.backgroundNo) + }); + this.btnNext.setDepth(this.window.depth + 1); + this.btnNext.colors = { + out: 0x83769c, + over: 0x29adff, + on: 0x00e436, + off: 0xad2900 + } + this.btnNext.tintFill = false; + this.btnNext.colorInState(this.btnNext.states.out); + this.contSYS.add(this.btnNext.sprite); + this.contSYS.add(this.btnNext.txt); + + this.btnPrev = new Button(this.scene, { x: this.window.pos.x + 16, y: this.window.pos.y + this.window.height * 0.5 }, "atlasUi", "sprBtn11", "", false, () => { + this.backgroundNo -= 1; + if (this.backgroundNo < 0) { + this.backgroundNo += this.backgroundMax; + } + this.changeBackgroundPreview(this.backgroundNo) + }); + this.btnPrev.setDepth(this.window.depth + 1); + this.btnPrev.colors = { + out: 0x83769c, + over: 0x29adff, + on: 0x00e436, + off: 0xad2900 + } + this.btnPrev.tintFill = false; + this.btnPrev.colorInState(this.btnPrev.states.out); + this.contSYS.add(this.btnPrev.sprite); + this.contSYS.add(this.btnPrev.txt); + + + //audio options + this.btnSystem = new Button(this.scene, { x: this.window.pos.x + this.window.width * 0.5, y: this.window.pos.y + 20 }, "atlasUi", "sprBtn13long", "system", false, () => { + console.log("closing audio") + if (this.currentOption === this.currentOption.aux) { + this.currentOption = this.options.sys; + this.contAUX.alpha = 0; + this.contSYS.alpha = 1; + } + }); + this.btnSystem.setDepth(this.window.depth + 1); + this.btnSystem.colors = { + out: 0x83769c, + over: 0x29adff, + on: 0x00e436, + off: 0xad2900 + } + this.btnSystem.tintFill = false; + this.btnSystem.tintText = false; + this.btnSystem.colorInState(this.btnSystem.states.out); + this.contAUX.add(this.btnSystem.sprite); + this.contAUX.add(this.btnSystem.txt); + } + + changeBackgroundPreview(_no) { + if (this.backgrounds[_no].locked === false) { + this.bgPreview.alpha = 1; + this.bgPreview.setTexture(this.backgrounds[this.backgroundNo].atlas, this.backgrounds[_no].asset); + this.txtPreview.setText(this.backgrounds[_no].name); + this.computer.background.setTexture(this.backgrounds[this.backgroundNo].atlas, this.backgrounds[_no].asset); + flagManager.setFlag("desktopBackground", String(this.backgroundNo)); + } else { + this.bgPreview.alpha = 0.1; + //this.txtPreview.setText(this.backgrounds[_no].text); + this.txtPreview.setText("locked"); + } + } + + update() { + switch (this.currentOption) { + case this.options.sys: + this.btnNext.update(); + this.btnPrev.update(); + //this.btnOptions.update(); + + if (this.btnNext.hovering === true || this.btnPrev.hovering === true || this.btnOptions.hovering === true) { + this.computer.cursor.setTexture("atlasUi", "sprDesktopCursorTouch"); + } + break; + case this.options.aux: + this.btnSystem.update(); + break; + default: + break; + } + + } + + destroy() { + this.btnOptions.destroy(); + this.btnNext.destroy(); + this.btnPrev.destroy(); + this.bgPreview.destroy(); + + this.btnSystem.destroy(); + + this.contSYS.destroy(); + this.contAUX.destroy(); + } +} diff --git a/src/ui/computer/windowAero.js b/src/ui/computer/windowAero.js new file mode 100644 index 0000000..00c3f96 --- /dev/null +++ b/src/ui/computer/windowAero.js @@ -0,0 +1,135 @@ +import Button from "../button.js"; + +export default class ComputerWindowAero{ + constructor(_scene, _computer, _name, _x, _y, _width, _height){ + this.scene = _scene; + this.computer = _computer; + this.name = _name; + this.width = _width; + this.height = _height; + this.pos = { + x: _x, + y: _y + } + this.depth = 15000; + this.isOpen = false; + + this.container = this.scene.add.container(0, 0); + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0xfff1e8, 1); + this.bgGraphics.fillRect(this.pos.x - 16, this.pos.y, this.width + 32, this.height); + this.bgGraphics.fillRect(this.pos.x, this.pos.y - 16, this.width, this.height + 32); + this.bgGraphics.depth = this.depth; + this.container.add(this.bgGraphics); + + this.txtWindowname = this.scene.add.bitmapText(this.pos.x + (this.width * 0.5), this.pos.y, "uiFont", this.name, 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.txtWindowname.depth = this.depth + 1; + this.txtWindowname.setTintFill(0x1d2b53); + this.container.add(this.txtWindowname); + + this.cornerTL = this.scene.add.sprite(this.pos.x - 8, this.pos.y - 8, "atlasUi", "sprDesktopWindowCorner"); + this.cornerTL.depth = this.depth; + this.container.add(this.cornerTL); + + this.cornerTR = this.scene.add.sprite(this.pos.x + this.width + 8, this.pos.y - 8, "atlasUi", "sprDesktopWindowCorner"); + this.cornerTR.angle = 90; + this.cornerTR.depth = this.depth; + this.container.add(this.cornerTR); + + this.cornerBL = this.scene.add.sprite(this.pos.x - 8, this.pos.y + this.height + 7, "atlasUi", "sprDesktopWindowCorner"); + this.cornerBL.angle = 270; + this.cornerBL.depth = this.depth; + this.container.add(this.cornerBL); + + this.cornerBR = this.scene.add.sprite(this.pos.x + this.width + 8, this.pos.y + this.height + 7, "atlasUi", "sprDesktopWindowCorner"); + this.cornerBR.angle = 180; + this.cornerBR.depth = this.depth; + this.container.add(this.cornerBR); + + this.btnBack = new Button(this.scene, { x: this.pos.x, y: this.pos.y }, "atlasUi", "sprBtn09b", "", false, () => { + this.close(); + }); + this.btnBack.setDepth(this.depth + 1); + this.btnBack.colors = { + out: 0xff004d, + over: 0x29adff, + on: 0x00e436, + off: 0xad2900 + } + this.btnBack.tintFill = false; + this.btnBack.colorInState(this.btnBack.states.out); + this.container.add(this.btnBack.sprite); + + this.program = null; + + this.container.alpha = 0; + } + + update(){ + if(this.btnBack.hovering === true){ + this.computer.cursor.setTexture("atlasUi", "sprDesktopCursorTouch"); + }else{ + //this.computer.cursor.setTexture("atlasUi", "sprDesktopCursorNormal"); + } + + if(this.isOpen === true){ + if(this.container.alpha < 1){ + this.container.alpha *= 1.1; + if(this.container.alpha > 0.9){ + this.container.alpha = 1; + } + } + }else{ + if(this.container.alpha > 0){ + this.container.alpha *= 0.9; + } + if(this.container.alpha <= 0.1){ + this.closeForReal(); + } + } + + if(this.program !== null){ + this.program.update(); + } + + this.btnBack.update(); + } + + open(){ + this.computer.windowOpen = this; + this.container.alpha = 0.1; + this.isOpen = true; + } + + close(){ + if(this.computer.windowToClose === null){ + this.isOpen = false; + this.computer.windowToClose = this; + } + } + + closeForReal(){ + this.container.alpha = 0; + this.computer.windowToClose = null; + if(this.computer.windowOpen === this){ + this.computer.windowOpen = null; + } + } + + destroy(){ + if(this.program !== null){ + this.program.destroy(); + } + + this.bgGraphics.destroy(); + this.txtWindowname.destroy(); + this.cornerTL.destroy(); + this.cornerTR.destroy(); + this.cornerBL.destroy(); + this.cornerBR.destroy(); + this.btnBack.destroy(); + + this.container.destroy(); + } +} \ No newline at end of file diff --git a/src/ui/conversationManager.js b/src/ui/conversationManager.js new file mode 100755 index 0000000..1765aa4 --- /dev/null +++ b/src/ui/conversationManager.js @@ -0,0 +1,539 @@ +import ConversationOption from "./conversationOption.js"; + +export default class ConversationManager { + constructor(_scene) { + this.scene = _scene; + this.btnOptions = []; + this.npc = null; + this.npcSprite = null; + this.npcTextGhost = this.scene.add.bitmapText(0, -32, "uiFont", "", 14, 1).setOrigin(0.5, 1).setLetterSpacing(0); + this.npcTextGhost.maxWidth = 460; + this.npcTextGhost.depth = 10000; + this.npcTextGhost.alpha = 0; + this.npcTextGhost.setLeftAlign(); + this.npcText = this.scene.add.bitmapText(0, -32, "uiFont", "", 14, 1).setOrigin(0, 0).setLetterSpacing(0); + this.npcText.maxWidth = 460; + this.npcText.depth = 10000; + this.npcText.setLeftAlign(); + + + this.conversation = { + file: null, + treePosition: 0, + speakingTo: { + name: "", + }, + }; + + this.highlightedAnswer = 0; + this.usedKeyboard = false; + this.cooldown = { + current: 0, + max: 10, + }; + this.animText = { + text: "", + textFull: "", + current: 0, + end: 0, + } + + this.bg = this.scene.add.graphics(); + + this.glyphs = '0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz[]/&"!§$%&/()=?[].:,;+-#~*|<>'; + this.rend = ''; + this.dead = false; + } + + update() { + if (this.animText.current < this.animText.end && this.dead === false) { + this.animText.current += 1 * this.scene.dt; + this.animText.text = this.animText.textFull.substring(0, Math.floor(this.animText.current)); + //this.npcText.setText(this.animText.text + (Math.floor(this.animText.current) % 4 < 2 ? " []" : " ")); + + let rend = ' '; + lp: for (let i = Math.floor(this.animText.current); i < this.animText.end; i++) { + rend += this.glyphs[Math.floor(Math.random() * this.glyphs.length)]; + if (rend.length > 10) { + break lp; + } + } + this.npcText.setText(this.animText.text + rend); + + let tb = this.npcTextGhost.getTextBounds(); + this.bg.clear(); + this.bg.fillStyle(0x000000, 1); + this.bg.fillRect(tb.local.x - tb.local.width * 0.5 - 3, tb.local.y + this.npcTextGhost.y - (tb.local.height * 1) - 3, tb.local.width + 6, tb.local.height + 6); + this.bg.depth = this.npcText.depth - 1; + + this.npcText.setPosition(tb.local.x - tb.local.width * 0.5, tb.local.y + this.npcTextGhost.y - tb.local.height) + } + + if (this.cooldown.current <= 0) { + let lit = null; + for (let b of this.btnOptions) { + b.btn.update(); + if (b.btn.state === b.btn.states.over) { + lit = b; + } + } + + if (this.btnOptions.length > 0) { + if (INPUTS.btnUp.justPressed === true || INPUTS.stickLeft.asKey.up.justPressed === true) { + this.usedKeyboard = true; + if (lit !== null) { + lit.btn.state = lit.btn.states.out; + } + this.btnOptions[this.highlightedAnswer].btn.switchState(this.btnOptions[this.highlightedAnswer].btn.states.out); + this.highlightedAnswer -= 1; + } + if (INPUTS.btnDown.justPressed === true || INPUTS.stickLeft.asKey.down.justPressed === true) { + this.usedKeyboard = true; + if (lit !== null) { + lit.btn.state = lit.btn.states.out; + } + this.btnOptions[this.highlightedAnswer].btn.switchState(this.btnOptions[this.highlightedAnswer].btn.states.out); + this.highlightedAnswer += 1; + } + + if (this.scene.hand.mouseMoved === true) { + if (lit !== this.btnOptions[this.highlightedAnswer] && lit !== null) { + this.btnOptions[this.highlightedAnswer].btn.switchState(this.btnOptions[this.highlightedAnswer].btn.states.out); + } + this.usedKeyboard = false; + } + + if (this.usedKeyboard === true) { + if (lit !== null) { + lit.btn.switchState(lit.btn.states.out); + } + this.highlightedAnswer = Math.max(0, Math.min(this.highlightedAnswer, this.btnOptions.length - 1)); + this.btnOptions[this.highlightedAnswer].btn.switchState(this.btnOptions[this.highlightedAnswer].btn.states.over); + } + + if (INPUTS.btnA.justReleased === true) { + //this.btnOptions[this.highlightedAnswer].btn.simulateClick(); + } + } + } else { + this.cooldown.current -= 1; + } + } + + createOptions(_elem) { + for (let b of this.btnOptions) { + b.btn.destroy(); + } + this.btnOptions = []; + + let rec = 0; + for (let [i, a] of _elem.answers.entries()) { + let valid = true; + //check if option is valid + if (a.checkFlag !== undefined) { + valid = false; + //todo check if flag is set + if (flagManager.getFlagById(a.checkFlag) !== null) { + valid = true; + } + } + if (a.checkFlagTrue !== undefined) { + valid = false; + //todo check if flag is set + if (flagManager.getFlagById(a.checkFlagTrue).value === "true") { + valid = true; + } + } + if (a.checkFlagFalse !== undefined) { + valid = false; + //todo check if flag is set + if (flagManager.getFlagById(a.checkFlagFalse).value === "false") { + valid = true; + } + } + /*if (a.checkPlayerInventory !== undefined) { + valid = false; + for (let i of this.scene.playerData.inventory) { + if (i.type === a.checkPlayerInventory.type && i.data.id === a.checkPlayerInventory.dataId) { + valid = true; + } + } + }*/ + + //push conversation option + if (valid === true) { + //check if another styling applies than default + let atext = String(i) + ". >> " + a.text + " <<"; + if (a.style !== undefined) { + if (a.style === "command") { + atext = "*" + a.text + "*"; + } + } + + this.btnOptions.push({ + data: a, + btn: new ConversationOption(this.scene, { x: 0, y: i * 22 }, atext, () => { + this.interpret(a.actions.split(" ")); + }), + }); + //update the rec for move left aligned below + let w = this.btnOptions[this.btnOptions.length - 1].btn.txt.getTextBounds().local.width; + if (w > rec) { + rec = w; + } + } else { + this.btnOptions.push({ + data: a, + btn: new ConversationOption(this.scene, { x: 0, y: i * 22 }, String(i) + ". *locked*", () => { }), + }); + //update the rec for move left aligned below + let w = this.btnOptions[this.btnOptions.length - 1].btn.txt.getTextBounds().local.width; + if (w > rec) { + rec = w; + } + } + } + //move all buttons left by half of widest button (left aligned list but centered on screen) + for (let b of this.btnOptions) { + b.btn.move(b.btn.txt.x - rec * 0.5, b.btn.txt.y); + } + + this.highlightedAnswer = Math.max(0, Math.min(this.highlightedAnswer, this.btnOptions.length - 1)); + this.cooldown.current = this.cooldown.max; + } + + interpret(_actions) { + let arr = _actions; + let modelId = ""; + switch (arr[0]) { + case "GOTO": + this.goto(Number(arr[1])); + arr.splice(0, 2); + break; + case "GOTONOACTION": + this.goto(Number(arr[1]), false); + arr.splice(0, 2); + break; + case "SETFILE": // [diag id / filename] [tree position / start id] + //todo maybe set file like old style for a specific character or create SETFILEFORID action + //currently this only sets file for the currernt NPC conversation + this.setConversation(arr[1], Number(arr[2])); + arr.splice(0, 3); + break; + case "EXIT": + arr.splice(0, 1); + //save latest position in conversation for reentry + if (this.npc != null) { + this.npc.data.conversation.treePosition = this.conversation.treePosition; + } + this.clearConversation(); + this.scene.player.setMode(PLAYERMODE.LOOK); + break; + case "SETFLAG": // [flag id] [value] + flagManager.setFlag(arr[1], arr[2]); + arr.splice(0, 3); + break; + case "REMOVEFLAG": // [flag id] + flagManager.removeFlag(arr[1]); + arr.splice(0, 2); + break; + case "CHECKFLAGBOOL": //[flag id][GOTO A][GOTO B] + if (flagManager.getFlagById(arr[1]).value === "true") { + this.goto(Number(arr[2])); + } else { + this.goto(Number(arr[3])); + } + arr.splice(0, 4); + break; + case "REMOVEMODEL": // [model id] + this.scene.geometryController.destroyModelById(arr[1]); + arr.splice(0, 2); + break; + case "SCALE": // [model id] [x] [y] [z] + this.scene.geometryController.getModelById(arr[1]).scale({ x: arr[2], y: arr[3], z: arr[4] }); + arr.splice(0, 5); + break; + case "LOOKATRAD": // [model id] [rad] + this.scene.geometryController.getModelById(arr[1]).lookDir.yaw = Number(arr[2]); + arr.splice(0, 3); + break; + case "LOOKATMODEL": // [model id] [other model id] + arr.splice(0, 2); + break; + case "PLAYERLOOKAT": // [other model id] + //todo make player look at model - maybe at position but needs another action? + //modelId = this.scene.geometryController.models.filter((el) => { return el.id === arr[1] })[0]; + //let a = Phaser.Math.Angle.Between(this.scene.cam.pos.x * -1, this.scene.cam.pos.z * -1, modelId.pos.x, modelId.pos.z) + (Math.PI * 0.5); + //this.scene.cam.dir.x = a * -1; + + let toDir = { + yaw: Math.PI * 0.25, + }; + this.scene.player.dir.yaw += toDir.yaw; + this.scene.player.rotateAroundAxis(this.scene.player.transform.toVectorArray(this.scene.player.transform.up), toDir.yaw * -1); + + arr.splice(0, 2); + break; + case "TRIGGERDIALOGUE": + //todo simulate click action on other model with its dialogue + //modelId = this.scene.geometryController.models.filter((el) => { return el.id === arr[1] })[0]; + //this.triggerDialogue(modelId); + arr.splice(0, 2); + break; + case "JUMPPLAYERPOSITION": + this.scene.player.jumpToPosition( + { + x: arr[1], + y: arr[2], + z: arr[3], + }, + true, + ); + arr.splice(0, 4); + break; + case "JUMPPLAYERPOSITIONRELATIVE": + this.scene.player.jumpToPosition( + { + x: this.scene.player.pos.x + arr[1], + y: this.scene.player.pos.y + arr[2], + z: this.scene.player.pos.z + arr[3], + }, + true, + ); + arr.splice(0, 4); + break; + case "JUMPTOPOSITION": + modelId = this.scene.geometryController.models.filter((el) => { + return el.id === arr[1]; + })[0]; + modelId.jumpToPosition({ x: Number(arr[2]), y: Number(arr[3]), z: Number(arr[4]) }); + arr.splice(0, 5); + break; + case "JUMPTOPOSITIONRELATIVE": + modelId = this.scene.geometryController.models.filter((el) => { + return el.id === arr[1]; + })[0]; + modelId.jumpToPosition({ x: modelId.pos.x + Number(arr[2]), y: modelId.pos.y + Number(arr[3]), z: modelId.pos.z + Number(arr[4]) }); + arr.splice(0, 5); + break; + case "ADDWAYPOINT": // [model id] [x] [y] [z] [spd] [jump] + modelId = this.scene.geometryController.models.filter((el) => { + return el.id === arr[1]; + })[0]; + //console.log(modelId) + /* + if(modelId.data.waypoints === undefined || modelId.data.waypoints === null){ + modelId.data.waypoints = []; + } + modelId.waypoints.push({ x: Number(arr[2]), y: Number(arr[3]), z: Number(arr[4]) }, Number(arr[5]), Boolean(Number(arr[6]))); + */ + modelId.mover.targets.push({ + pos: { + x: Number(arr[2]), + y: Number(arr[3]), + z: Number(arr[4]), + spd: Number(arr[5]), + }, + dir: { + yaw: modelId.dir.yaw, + pitch: modelId.dir.pitch, + roll: modelId.dir.roll, + spd: 0.01, + }, + jump: Boolean(Number(arr[6])), + }); + modelId.mover.target = modelId.mover.targets[0]; + //modelId.mover.isMoving = true; + arr.splice(0, 7); + break; + case "STARTWAYPOINT": + modelId = this.scene.geometryController.models.filter((el) => { + return el.id === arr[1]; + })[0]; + modelId.mover.target = modelId.mover.targets[0]; + modelId.mover.isMoving = true; + arr.splice(2, 0); + break; + case "SETTEXTURE": // [model id] [quadData nr = 0] [texture] [frame = 0] + modelId = this.scene.geometryController.models.filter((el) => { + return el.id === arr[1]; + })[0]; + modelId.quadData[arr[2]].setTexture(arr[3], arr[4], false); + arr.splice(0, 5); + break; + case "SETATLAS8WAY": // [model id] [quadData nr = 0] [texture] [frame = 0] + modelId = this.scene.geometryController.models.filter((el) => { + return el.id === arr[1]; + })[0]; + modelId.atlas = arr[3]; + modelId.atlas8wayFrame = arr[4]; + modelId.quadData[arr[2]].setTexture(arr[3], arr[4], false); + arr.splice(0, 5); + break; + case "IS8WAY": + modelId = this.scene.geometryController.models.filter((el) => { + return el.id === arr[1]; + })[0]; + modelId.flags.is8way = arr[2] === "true" ? true : false; + arr.splice(0, 3); + break; + case "USESATLAS": + modelId = this.scene.geometryController.models.filter((el) => { + return el.id === arr[1]; + })[0]; + modelId.flags.usesAtlas = arr[2] === "true" ? true : false; + arr.splice(0, 3); + break; + case "ENDDIALOGUE": + this.endDialogue(); + arr.splice(0, 1); + break; + /* + //old one + case "SETFILE": + modelId = this.scene.geometryController.models.filter((el) => { return el.id === arr[1] })[0]; + if (arr[2] !== "null") { + modelId.file = arr[2]; + } else { + modelId.file = null; + } + arr.splice(0, 3); + break; + */ + case "PLAYSOUND": + //todo sound controller or model has a (spatial) sound? + modelId = this.scene.geometryController.models.filter((el) => { + return el.id === arr[1]; + })[0]; + modelId.setSfx(arr[2], { loop: Boolean(Number(arr[3])) }); + arr.splice(0, 4); + break; + case "STOPSOUND": + //todo sound controller or model has a (spatial) sound? + modelId = this.scene.geometryController.models.filter((el) => { + return el.id === arr[1]; + })[0]; + modelId.stopSfx(); + arr.splice(0, 2); + break; + case "LOADLEVEL": + this.scene.loadLevel(arr[1]); + arr.splice(0, 2); + break; + case "RESTART": + //this.scene.restart(); + //this.scene.scene.start("Preloader"); + arr.splice(0, 1); + break; + case "TRIGGERACTION": + modelId = this.scene.geometryController.models.filter((el) => { + return el.id === arr[1]; + })[0]; + modelId.action(); + arr.splice(0, 2); + break; + case "TRIGGERACTIONID": + modelId = this.scene.geometryController.models.filter((el) => { + return el.id === arr[1]; + })[0]; + modelId.customActions[Number(arr[2])](); + arr.splice(0, 3); + break; + default: + console.log(arr[0]); + arr.splice(0, 1); + break; + } + if (arr.length > 0) { + this.interpret(arr); + } + } + + goto(_id, _interpretActions = true) { + this.conversation.treePosition = _id; + let elem = this.conversation.file.cards.filter((e) => e.id === _id)[0]; + if (elem === undefined) { + elem = this.conversation.file.cards[0]; + } + //this.npcText.setText(this.replaceCheck(elem.text)) + this.npcTextGhost.setText(this.replaceCheck(elem.text)); + this.animText.text = ""; + this.animText.textFull = this.npcTextGhost.text; + this.animText.current = 0; + this.animText.end = this.animText.textFull.length; + + + let tb = this.npcTextGhost.getTextBounds(); + this.bg.clear(); + this.bg.fillStyle(0x000000, 1); + this.bg.fillRect(tb.local.x - tb.local.width * 0.5 - 3, tb.local.y + this.npcText.y - tb.local.height * 1 - 3, tb.local.width + 6, tb.local.height + 6); + this.bg.depth = this.npcText.depth - 1; + + if (this.npcSprite !== null) { + this.npcSprite.destroy(); + } + if (elem.sprite !== undefined) { + //TODO eventually adding a sprite for people who speak to you + //this.npcSprite = this.scene.add.sprite(-142, -85, elem.sprite); + } + + if (elem.actions !== undefined && _interpretActions === true) { + this.interpret(elem.actions.split(" ")); + } + + this.createOptions(elem); + } + + replaceCheck(_str) { + /*if (this.npc !== null) { + _str = _str.replace("PLAYERNAME", this.npc.conversation.speakingTo.name !== null ? this.npc.conversation.speakingTo.name : this.scene.playerData.name); + } else { + _str = _str.replace("PLAYERNAME", this.scene.playerData.name); + }*/ + return _str; + } + + setNPC(_npc) { + this.npc = _npc; + } + + setConversation(_fileName, _startId) { + this.dead = false; + this.conversation.file = this.scene.cache.json.get(_fileName); + //save current fileName in NPC if possible for reentry purpose + if (this.npc != null) { + this.npc.data.conversation.fileName = _fileName; + } + this.conversation.treePosition = _startId; + this.goto(_startId); + } + + clearConversation() { + this.npcText.setText(""); + for (let b of this.btnOptions) { + b.btn.destroy(); + } + this.btnOptions = []; + if (this.npcSprite !== null) { + this.npcSprite.destroy(); + } + this.bg.clear(); + this.dead = true; + } + + destroy() { + this.npcText.destroy(); + this.npcTextGhost.destroy(); + for (let b of this.btnOptions) { + b.btn.destroy(); + } + this.btnOptions = []; + if (this.npcSprite !== null) { + this.npcSprite.destroy(); + } + this.bg.clear(); + this.bg.destroy(); + + this.dead = true; + } +} diff --git a/src/ui/conversationOption.js b/src/ui/conversationOption.js new file mode 100755 index 0000000..16901c5 --- /dev/null +++ b/src/ui/conversationOption.js @@ -0,0 +1,116 @@ +export default class ConversationOption{ + constructor(_scene, _pos, _text, _func){ + this.scene = _scene; + this.pos = _pos; + this.func = _func; + this.toggleOffFunc = () => {}; + + this.colors = { + out: 0xfff1e8, + over: 0x29adff, + on: 0x00e436 + } + + this.states = { + out: 0, + over: 1, + on: 2 + } + this.state = this.states.out; + this.active = false; + + this.txt = this.scene.add.bitmapText(_pos.x, _pos.y, "uiFont", _text, 14, 0).setOrigin(0, 0.5).setLetterSpacing(0); + this.txt.depth = 10000; + this.txt.maxWidth = 460; + + this.colorInState(this.state); + + let tb = this.txt.getTextBounds(); + this.rect = new Phaser.GameObjects.Rectangle(this.scene, tb.local.x, tb.local.y + this.txt.y, tb.local.width, tb.local.height).setOrigin(0, 0.5); + + this.bg = this.scene.add.graphics(); + this.bg.fillStyle(0x000000, 0.5); + this.bg.fillRect(0, 0, tb.local.width + 6, tb.local.height + 6); + this.bg.x = this.txt.x - 3; + this.bg.y = this.txt.y - (tb.local.height * 0.5) - 3; + this.bg.depth = this.txt.depth-1; + } + + update(){ + + if(this.rect.getBounds().contains(this.scene.hand.pos.x, this.scene.hand.pos.y)){ + if(this.scene.hand.pressed === false){ + if(this.active === false){ + this.switchState(this.states.over); + }else{ + this.switchState(this.states.out); + } + } + if(this.scene.hand.justPressed === true){ + if(this.active === true){ + this.switchState(this.states.over); + }else{ + this.switchState(this.states.on); + } + } + if(this.scene.hand.justReleased === true){ + this.func(); + } + }else{ + if(this.active === false){ + this.switchState(this.states.out); + }else{ + this.switchState(this.states.on); + } + } + } + + simulateClick(){ + this.func(); + } + + switchState(_state){ + if (this.state !== _state) { + this.state = _state; + this.colorInState(this.state); + } + } + + colorInState(_state){ + switch(this.state){ + case this.states.out: + this.txt.setTintFill(this.colors.out); + break; + case this.states.over: + this.txt.setTintFill(this.colors.over); + break; + case this.states.on: + this.txt.setTintFill(this.colors.out); + break; + default: + break; + } + } + + move(_x, _y){ + this.txt.x = _x; + this.txt.y = _y; + + let tb = this.txt.getTextBounds(); + this.bg.x = this.txt.x - 3; + this.bg.y = this.txt.y - (tb.local.height * 0.5) - 3; + + this.rect.x = _x; + this.rect.y = _y; + } + + destroy(){ + this.txt.destroy(); + this.rect.destroy(); + this.bg.destroy(); + } + + setDepth(_depth){ + this.txt.depth = _depth; + } +} \ No newline at end of file diff --git a/src/ui/movingGrid.js b/src/ui/movingGrid.js new file mode 100755 index 0000000..990926d --- /dev/null +++ b/src/ui/movingGrid.js @@ -0,0 +1,87 @@ +export default class MovingGrid{ + constructor(_scene, _sizeX, _sizeY, _cellSize){ + this.scene = _scene; + this.size = { + x: _sizeX, + y: _sizeY + } + this.cellSize = _cellSize; + + this.points = []; + for (let yy = 0; yy < this.size.y; yy += this.cellSize){ + for (let xx = 0; xx < this.size.x; xx += this.cellSize) { + this.points.push({ + id: this.points.length, + x: 16 + xx - (this.scene.game.config.width * 0.5), + y: 16 + yy - (this.scene.game.config.height * 0.5), + sprite: this.scene.add.sprite(xx, yy, "atlasUi", "sprUiMenuBg") + }); + this.points[this.points.length - 1].sprite.depth = 9991; + } + } + + this.pointers = []; + + //this.highlight = this.scene.add.graphics(); + } + + update(){ + for(let m of this.pointers){ + for(let p of this.points){ + let a = Phaser.Math.Angle.Between(p.x, p.y, m.x, m.y); + let d = Phaser.Math.Distance.Between(m.x, m.y, p.x, p.y); + if (d < m.influence) { + p.sprite.x = p.x + Math.cos(a) * Math.min(d * 0.25, ((m.influence * 2) / d)); + p.sprite.y = p.y + Math.sin(a) * Math.min(d * 0.25, ((m.influence * 2) / d)); + } else { + p.sprite.x = p.x; + p.sprite.y = p.y; + } + p.sprite.setScale(1); + } + } + + //this.highlight.clear(); + //this.highlight.lineStyle(1, 0x00ff00); + let lx = Math.floor(this.size.x / this.cellSize); + let mx = this.scene.hand.pos.x + (this.scene.game.config.width * 0.5) - 16; + let my = this.scene.hand.pos.y + (this.scene.game.config.height * 0.5) - 16; + let xx = Math.floor(mx / this.cellSize); + let yy = Math.floor(my / this.cellSize); + let id = Math.max(0, Math.min((yy * lx) + xx, this.points.length-1)); + this.points[id].sprite.setScale(4); + } + + addPointer(_id, _x, _y, _influence){ + this.pointers.push({ + id: _id, + influence: _influence, + pos: { + x: _x, + y: _y + } + }); + } + + updatePointer(_id, _x, _y, _influence){ + let m = this.pointers.filter(el => el.id === _id)[0]; + m.x = _x; + m.y = _y; + m.influence = _influence; + } + + removePointerById(_id){ + for(let i = this.pointers.length-1 ; i >= 0 ; i--){ + if(this.pointers[i].id === _id){ + this.pointers.splice(i, 1); + } + } + } + + destroy(){ + for(let p of this.points){ + p.sprite.destroy(); + } + //this.highlight.destroy(); + } +} \ No newline at end of file diff --git a/src/ui/panelElevator.js b/src/ui/panelElevator.js new file mode 100755 index 0000000..634d65f --- /dev/null +++ b/src/ui/panelElevator.js @@ -0,0 +1,225 @@ +import Button from "./button.js"; +import { SliderHorizontal } from "./slider.js"; +import MovingGrid from "./movingGrid.js"; + +export default class PanelElevator { + constructor(_scene) { + this.scene = _scene; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x000000, 0.9); + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + + this.bgGrid = new MovingGrid(this.scene, this.scene.game.config.width, this.scene.game.config.height, 32); + this.bgGrid.addPointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + + //left side + this.btnBack = new Button(this.scene, { x: -160, y: -68 }, "atlasUi", "sprBtn00", "BACK", false, () => { + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + + /* + this.btnToTrack = new Button(this.scene, { x: -160, y: -34 }, "atlasUi", "sprBtn00", "DIRECT TRACK", false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.loadLevel("quadRingsTest", {track: 2, startFromHangar: false, playerShipModel: "modHoverCarWipeOutStyle"}); + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + + this.btnToShipSelection = new Button(this.scene, { x: -160, y: 34 }, "atlasUi", "sprBtn00", "MAIN MENU", false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.scene.player.setVisibility(false); + + this.scene.loadLevel("mainMenu", {}); + this.destroy(); + }); + */ + + /* + this.btnToEditor = new Button(this.scene, { x: -160, y: 102 }, "atlasUi", "sprBtn00", "editor", false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + + this.scene.loadLevel("modelBuilder"); + }); + */ + + //right side + this.btnOffice = new Button(this.scene, { x: 160, y: -68 }, "atlasUi", "sprBtn00", "OFFICE", false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + + this.scene.loadLevel("office00"); + }); + + this.btnQuarters = new Button(this.scene, { x: 160, y: -34 }, "atlasUi", "sprBtn00", "QUARTERS", false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + //only bc immideat new panel in level + this.scene.loadLevel("playerApartement00", { fromElevator: false }); + }); + + this.btnLounge = new Button(this.scene, { x: 160, y: 0 }, "atlasUi", "sprBtn00", "LOUNGE", false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + + this.scene.loadLevel("marketSquareApartements00", { lounge: true }); + }); + + this.btnSocial = new Button(this.scene, { x: 160, y: 34 }, "atlasUi", "sprBtn00", "MARKET", false, () => { + this.scene.player.jumpToPosition({ x: 256, y: 16, z: -96 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + + this.scene.loadLevel("marketSquareApartements00", { lounge: false }); + }); + + this.btnHangar = new Button(this.scene, { x: 160, y: 68 }, "atlasUi", "sprBtn00", "HANGAR", false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + + if (flagManager.getFlagById("demoProgress").value === "0") { + this.scene.loadLevel("hangar00", { startFromElevator: true, showIntro: true }); + } else { + this.scene.loadLevel("hangar00", { startFromElevator: true }); + } + }); + + this.btnPower = new Button(this.scene, { x: 160, y: 102 }, "atlasUi", "sprBtn00", "CHVRCH CLUB" /*"POWER"*/, false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + + this.scene.loadLevel("church00"); + }); + + /* + //this.btnOffice.switchState(this.btnOffice.states.off); + this.btnQuarters.switchState(this.btnQuarters.states.off); + this.btnLounge.switchState(this.btnLounge.states.off); + //this.btnPower.switchState(this.btnPower.states.off); + + if (flagManager.getFlagById("playingDemo").value === "1") { + this.btnHangar.switchState(this.btnHangar.states.off); + this.btnLounge.switchState(this.btnLounge.states.off); + this.btnQuarters.switchState(this.btnQuarters.states.off); + this.btnSocial.switchState(this.btnSocial.states.off); + } + */ + /*this.btnDream = new Button(this.scene, { x: 160, y: -66 }, "atlasUi", "sprBtn00", "DREAM", false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + + this.scene.loadLevel("dream00"); + });*/ + + if (flagManager.getFlagById("officeLevel").value === "-1") { + this.btnOffice.switchState(this.btnOffice.states.off); + } + if (flagManager.getFlagById("quartersLevel").value === "-1") { + this.btnQuarters.switchState(this.btnQuarters.states.off); + } + if (flagManager.getFlagById("loungeLevel").value === "-1") { + this.btnLounge.switchState(this.btnLounge.states.off); + } + if (flagManager.getFlagById("marketLevel").value === "-1") { + this.btnSocial.switchState(this.btnSocial.states.off); + } + if (flagManager.getFlagById("hangarLevel").value === "-1") { + this.btnHangar.switchState(this.btnHangar.states.off); + } + if (flagManager.getFlagById("churchLevel").value === "-1") { + this.btnPower.switchState(this.btnPower.states.off); + } + + this.lockButtons = true; + } + + update() { + this.bgGrid.updatePointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + this.bgGrid.update(); + + if (this.lockButtons === false) { + this.btnBack.update(); + //this.btnToTrack.update(); + //this.btnToShipSelection.update(); + //this.btnToEditor.update(); + //this.btnDream.update(); + /*if (flagManager.getFlagById("playingDemo").value === "0") { + this.btnOffice.update(); + this.btnQuarters.update(); + this.btnLounge.update(); + this.btnSocial.update(); + this.btnHangar.update(); + this.btnPower.update(); + }*/ + + if (flagManager.getFlagById("officeLevel").value !== "-1") { + this.btnOffice.update(); + } + if (flagManager.getFlagById("quartersLevel").value !== "-1") { + this.btnQuarters.update(); + } + if (flagManager.getFlagById("loungeLevel").value !== "-1") { + this.btnLounge.update(); + } + if (flagManager.getFlagById("marketLevel").value !== "-1") { + this.btnSocial.update(); + } + if (flagManager.getFlagById("hangarLevel").value !== "-1") { + this.btnHangar.update(); + } + if (flagManager.getFlagById("churchLevel").value !== "-1") { + this.btnPower.update(); + } + } else { + this.lockButtons = false; + } + } + + destroy() { + this.bgGraphics.destroy(); + this.bgGrid.destroy(); + + this.btnBack.destroy(); + //this.btnToTrack.destroy(); + //this.btnToShipSelection.destroy(); + //this.btnToEditor.destroy(); + //this.btnDream.destroy(); + this.btnOffice.destroy(); + this.btnQuarters.destroy(); + this.btnLounge.destroy(); + this.btnSocial.destroy(); + this.btnHangar.destroy(); + this.btnPower.destroy(); + } +} diff --git a/src/ui/panelElevatorMaster.js b/src/ui/panelElevatorMaster.js new file mode 100755 index 0000000..7d08735 --- /dev/null +++ b/src/ui/panelElevatorMaster.js @@ -0,0 +1,185 @@ +import Button from "./button.js"; +import { SliderHorizontal } from "./slider.js"; +import MovingGrid from "./movingGrid.js"; + +export default class PanelElevator { + constructor(_scene) { + this.scene = _scene; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x000000, 0.9); + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + + this.bgGrid = new MovingGrid(this.scene, this.scene.game.config.width, this.scene.game.config.height, 32); + this.bgGrid.addPointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + + //left side + this.btnBack = new Button(this.scene, { x: -160, y: -68 }, "atlasUi", "sprBtn00", "BACK", false, () => { + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + + /* + this.btnToTrack = new Button(this.scene, { x: -160, y: -34 }, "atlasUi", "sprBtn00", "DIRECT TRACK", false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.loadLevel("quadRingsTest", {track: 2, startFromHangar: false, playerShipModel: "modHoverCarWipeOutStyle"}); + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + + this.btnToShipSelection = new Button(this.scene, { x: -160, y: 34 }, "atlasUi", "sprBtn00", "MAIN MENU", false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.scene.player.setVisibility(false); + + this.scene.loadLevel("mainMenu", {}); + this.destroy(); + }); + */ + + /* + this.btnToEditor = new Button(this.scene, { x: -160, y: 102 }, "atlasUi", "sprBtn00", "editor", false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + + this.scene.loadLevel("modelBuilder"); + }); + */ + + //right side + this.btnOffice = new Button(this.scene, { x: 160, y: -68 }, "atlasUi", "sprBtn00", "OFFICE", false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + + this.scene.loadLevel("office00"); + }); + + this.btnQuarters = new Button(this.scene, { x: 160, y: -34 }, "atlasUi", "sprBtn00", "QUARTERS", false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + //only bc immideat new panel in level + this.scene.loadLevel("playerApartement00"); + }); + + this.btnLounge = new Button(this.scene, { x: 160, y: 0 }, "atlasUi", "sprBtn00", "LOUNGE", false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + + this.scene.loadLevel("marketSquareApartements00", { lounge: true }); + }); + + this.btnSocial = new Button(this.scene, { x: 160, y: 34 }, "atlasUi", "sprBtn00", "MARKET", false, () => { + this.scene.player.jumpToPosition({ x: 256, y: 16, z: -96 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + + this.scene.loadLevel("marketSquareApartements00", { lounge: false }); + }); + + this.btnHangar = new Button(this.scene, { x: 160, y: 68 }, "atlasUi", "sprBtn00", "HANGAR", false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + + if (flagManager.getFlagById("demoProgress").value === "0") { + this.scene.loadLevel("hangar00", { startFromElevator: true, showIntro: true }); + } else { + this.scene.loadLevel("hangar00", { startFromElevator: true }); + } + }); + + this.btnPower = new Button(this.scene, { x: 160, y: 102 }, "atlasUi", "sprBtn00", "CHVRCH CLUB"/*"POWER"*/, false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + + this.scene.loadLevel("church00"); + }); + + //this.btnOffice.switchState(this.btnOffice.states.off); + this.btnQuarters.switchState(this.btnQuarters.states.off); + this.btnLounge.switchState(this.btnLounge.states.off); + //this.btnPower.switchState(this.btnPower.states.off); + + if (flagManager.getFlagById("playingDemo").value === "1") { + this.btnHangar.switchState(this.btnHangar.states.off); + this.btnLounge.switchState(this.btnLounge.states.off); + this.btnQuarters.switchState(this.btnQuarters.states.off); + this.btnSocial.switchState(this.btnSocial.states.off); + } + + /*this.btnDream = new Button(this.scene, { x: 160, y: -66 }, "atlasUi", "sprBtn00", "DREAM", false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + + this.scene.loadLevel("dream00"); + });*/ + this.lockButtons = true; + } + + update() { + this.bgGrid.updatePointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + this.bgGrid.update(); + + if (this.lockButtons === false) { + this.btnBack.update(); + //this.btnToTrack.update(); + //this.btnToShipSelection.update(); + //this.btnToEditor.update(); + //this.btnDream.update(); + if (flagManager.getFlagById("playingDemo").value === "0") { + this.btnOffice.update(); + this.btnQuarters.update(); + this.btnLounge.update(); + this.btnSocial.update(); + this.btnHangar.update(); + this.btnPower.update(); + } + } else { + this.lockButtons = false; + } + } + + destroy() { + this.bgGraphics.destroy(); + this.bgGrid.destroy(); + + this.btnBack.destroy(); + //this.btnToTrack.destroy(); + //this.btnToShipSelection.destroy(); + //this.btnToEditor.destroy(); + //this.btnDream.destroy(); + this.btnOffice.destroy(); + this.btnQuarters.destroy(); + this.btnLounge.destroy(); + this.btnSocial.destroy(); + this.btnHangar.destroy(); + this.btnPower.destroy(); + } +} diff --git a/src/ui/panelEndOfCanyon.js b/src/ui/panelEndOfCanyon.js new file mode 100755 index 0000000..8d5a760 --- /dev/null +++ b/src/ui/panelEndOfCanyon.js @@ -0,0 +1,169 @@ +import Button from "./button.js"; +import { SliderHorizontal } from "./slider.js"; +import MovingGrid from "./movingGrid.js"; + +export default class PanelEndOfRace { + constructor(_scene, _level, _previousState = 0) { + this.scene = _scene; + this.level = _level; + this.previousState = _previousState; + + this.scene.hand.setMouseLock(false); + this.scene.hand.showCursor = true; + this.scene.hand.cursor.alpha = 1; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x000000, 0.9); + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + this.bgGraphics.depth = 9990; + + this.bgGrid = new MovingGrid(this.scene, this.scene.game.config.width, this.scene.game.config.height, 32); + this.bgGrid.addPointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + + this.qrcode = this.scene.add.sprite(-160, 68, "atlasUi", "qrcode"); + this.qrcode.depth = 9999; + + this.scene.soundManager.stopSound(this.level.musicTrack); + + let playingStory = flagManager.getFlagById("playingStory").value; + + //left side + this.btnContinue = new Button(this.scene, { x: -160, y: -68 }, "atlasUi", "sprBtn00", "CONTINUE", false, () => { + + if (this.level.finishedRace === true) { + this.scene.paused = false; + this.scene.soundManager.stopSound(this.scene.soundManager.engineSound); + this.scene.soundManager.stopSound(this.scene.soundManager.engineRotorSound); + this.scene.soundManager.stopSound(this.scene.soundManager.scrapeSound); + this.scene.soundManager.stopSound(this.scene.soundManager.heatWarningSound); + this.scene.soundManager.stopSound(this.level.musicTrack); + if (playingStory === "1") { + this.scene.player.panel = null; + this.level.destroy(); + + this.destroy(); + //this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + this.scene.loadLevel("hangar00", null);//dream00 + //INFO demo starts with a panel so dont override after the fact + //this.scene.player.setMode(PLAYERMODE.LOOK); + //this.scene.player.panel = null; + } else { + /* + this.level.destroy(); + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.destroy(); + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.scene.player.setVisibility(false); + this.scene.loadLevel("mainMenu", {}); + */ + + this.scene.paused = false; + //if(this.fromWalk === false){ + this.scene.soundManager.stopSound(this.scene.soundManager.engineSound); + this.scene.soundManager.stopSound(this.scene.soundManager.engineRotorSound); + this.scene.soundManager.stopSound(this.scene.soundManager.scrapeSound); + this.scene.soundManager.stopSound(this.scene.soundManager.heatWarningSound); + this.scene.soundManager.stopSound(this.level.musicTrack); + //} + this.scene.player.panel = null; + this.level.destroy(); + + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.scene.player.setVisibility(false); + this.scene.loadLevel("mainMenu", {}); + this.destroy(); + } + } else { + //go for second round + this.level.startFromHangar = false; + this.level.params.startFromHangar = false; + this.level.loadTrack(this.level.params.track); + + //restart all ships + for (let ai of this.level.aiShips) { + ai.fastestLap = 0; + ai.last.fastestLap = 0; + } + this.level.playerShip.fastestLap = 0; + this.level.playerShip.last.fastestLap = 0; + this.level.playerShip.autopilot = false; + //this.level.ui.show(); + + this.scene.paused = false; + this.level.state = this.previousState; + this.level.ui.show(); + this.scene.player.panel = null; + this.destroy(); + } + + + + }); + + //show all laptimes in a container - another container could be the position of everyone and their best lap or smth + this.lapContainer = this.scene.add.container(0, 0); + this.lapContainer.depth = 9999; + this.txtLapNo = []; + this.txtLapPos = []; + this.txtLapTime = []; + + let xx = 64; + let yy = 0; + let names = ["YOU", this.level.aiShips[0].name]; + for (let lap = -1; lap < this.level.maxLaps; lap++) { + xx = -64; + yy = Math.floor((this.level.maxLaps * 0.5) * -34) + ((lap + 1) * 34);//(this.scene.game.config.height * -0.4) + ((lap + 1) * 34); + this.txtLapNo.push(new Button(this.scene, { x: xx + 40, y: yy }, "atlasUi", "sprBtn00", lap === -1 ? "PILOT" : names[lap], false, () => { })); + this.txtLapTime.push(new Button(this.scene, { x: xx + 120, y: yy }, "atlasUi", "sprBtn00", lap === -1 ? "POINTS" : this.level.raceModeData.points.rounds[lap], false, () => { })); + //this.txtLapPos.push(new Button(this.scene, { x: xx + 160, y: yy }, "atlasUi", "sprBtn08", lap === -1 ? "POS" : "X", false, () => { })); + } + let winStr = "RACE OVER!"; + //if (this.level.playerShip.position > -1) { + if (this.level.raceModeData.points.overall > 0) { + winStr = "YOU WON!" + } else { + winStr = "YOU LOST BY: " + String(this.level.raceModeData.points.overall) + " PTS!"; + } + if (this.level.finishedRace === false) { + winStr = "YOU ARE HUNTED NOW"; + } + this.txtLapPos.push(this.scene.add.bitmapText(0, yy + 34, "uiFont", winStr, 14, 0).setOrigin(0.5).setLetterSpacing(0)) + this.txtLapPos[this.txtLapPos.length - 1].depth = 9999; + + this.lockButtons = true; + } + + update() { + this.bgGrid.updatePointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + this.bgGrid.update(); + + if (this.lockButtons === false) { + this.btnContinue.update(); + + if (INPUTS.btnA.justReleased) { + this.btnContinue.func(); + } + } else { + this.lockButtons = false; + } + } + + destroy() { + this.bgGraphics.destroy(); + this.bgGrid.destroy(); + + this.qrcode.destroy(); + + for (let txt of this.txtLapNo) { txt.destroy(); } + for (let txt of this.txtLapTime) { txt.destroy(); } + for (let txt of this.txtLapPos) { txt.destroy(); } + this.lapContainer.destroy(); + + this.btnContinue.destroy(); + } +} diff --git a/src/ui/panelEndOfRace.js b/src/ui/panelEndOfRace.js new file mode 100755 index 0000000..86d423a --- /dev/null +++ b/src/ui/panelEndOfRace.js @@ -0,0 +1,144 @@ +import Button from "./button.js"; +import { SliderHorizontal } from "./slider.js"; +import MovingGrid from "./movingGrid.js"; + +export default class PanelEndOfRace { + constructor(_scene, _level, _previousState = 0, _fromWalk = false) { + this.scene = _scene; + this.level = _level; + this.previousState = _previousState; + this.fromWalk = _fromWalk; + + this.scene.hand.setMouseLock(false); + this.scene.hand.showCursor = true; + this.scene.hand.cursor.alpha = 1; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x000000, 0.9); + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + this.bgGraphics.depth = 9990; + + this.bgGrid = new MovingGrid(this.scene, this.scene.game.config.width, this.scene.game.config.height, 32); + this.bgGrid.addPointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + + this.qrcode = this.scene.add.sprite(-160, 68, "atlasUi", "qrcode"); + this.qrcode.depth = 9999; + + this.scene.soundManager.stopSound(this.level.musicTrack); + + let playingStory = flagManager.getFlagById("playingStory").value; + + //left side + this.btnContinue = new Button(this.scene, { x: -160, y: -68 }, "atlasUi", "sprBtn00", "CONTINUE", false, () => { + this.scene.paused = false; + this.scene.soundManager.stopSound(this.scene.soundManager.engineSound); + this.scene.soundManager.stopSound(this.scene.soundManager.engineRotorSound); + this.scene.soundManager.stopSound(this.scene.soundManager.scrapeSound); + this.scene.soundManager.stopSound(this.scene.soundManager.heatWarningSound); + this.scene.soundManager.stopSound(this.level.musicTrack); + if (playingStory === "1") { + this.scene.player.panel = null; + this.level.destroy(); + + this.destroy(); + //this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + this.scene.loadLevel("hangar00", null);//dream00 + //INFO demo starts with a panel so dont override after the fact + //this.scene.player.setMode(PLAYERMODE.LOOK); + //this.scene.player.panel = null; + } else { + /* //old back to menu + this.level.destroy(); + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.destroy(); + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.scene.player.setVisibility(false); + this.scene.loadLevel("mainMenu", {}); + */ + + this.scene.paused = false; + //if(this.fromWalk === false){ + this.scene.soundManager.stopSound(this.scene.soundManager.engineSound); + this.scene.soundManager.stopSound(this.scene.soundManager.engineRotorSound); + this.scene.soundManager.stopSound(this.scene.soundManager.scrapeSound); + this.scene.soundManager.stopSound(this.scene.soundManager.heatWarningSound); + this.scene.soundManager.stopSound(this.level.musicTrack); + //} + this.scene.player.panel = null; + this.level.destroy(); + + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.scene.player.setVisibility(false); + this.destroy(); + this.scene.loadLevel("mainMenu", {}); + } + }); + + //show all laptimes in a container - another container could be the position of everyone and their best lap or smth + this.lapContainer = this.scene.add.container(0, 0); + this.lapContainer.depth = 9999; + this.txtLapNo = []; + this.txtLapPos = []; + this.txtLapTime = []; + + let xx = 64; + let yy = 0; + for (let lap = -1; lap < this.level.maxLaps; lap++) { + xx = -64; + yy = Math.floor((this.level.maxLaps * 0.5) * -34) + ((lap + 1) * 34);//(this.scene.game.config.height * -0.4) + ((lap + 1) * 34); + this.txtLapNo.push(new Button(this.scene, { x: xx + 0, y: yy }, "atlasUi", "sprBtn08", lap === -1 ? "LAP" : String(lap + 1), false, () => { })); + this.txtLapTime.push(new Button(this.scene, { x: xx + 80, y: yy }, "atlasUi", "sprBtn00", lap === -1 ? "TIME" : timeToLapTime(this.level.playerShip.lapTimes[lap].time), false, () => { })); + this.txtLapPos.push(new Button(this.scene, { x: xx + 160, y: yy }, "atlasUi", "sprBtn08", lap === -1 ? "POS" : String(this.level.playerShip.lapTimes[lap].position + 1) + ".", false, () => { })); + } + let winStr = "RACE OVER!"; + if (this.level.playerShip.position > -1) { + let affix = "th"; + if (this.level.playerShip.position === 0) { + affix = "ST" + winStr = "YOU WON!" + } else { + if (this.level.playerShip.position === 1) { affix = "ND" } + if (this.level.playerShip.position === 2) { affix = "RD" } + winStr = "YOU FINISHED " + String(Number(this.level.playerShip.position + 1)) + affix; + } + } + this.txtLapPos.push(this.scene.add.bitmapText(0, yy + 34, "uiFont", winStr, 14, 0).setOrigin(0.5).setLetterSpacing(0)) + this.txtLapPos[this.txtLapPos.length - 1].depth = 9999; + + this.lockButtons = true; + } + + update() { + this.bgGrid.updatePointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + this.bgGrid.update(); + + if (this.lockButtons === false) { + this.btnContinue.update(); + + if (INPUTS.btnA.justReleased) { + this.btnContinue.func(); + } + } else { + this.lockButtons = false; + } + } + + destroy() { + this.bgGraphics.destroy(); + this.bgGrid.destroy(); + + this.qrcode.destroy(); + + for (let txt of this.txtLapNo) { txt.destroy(); } + for (let txt of this.txtLapTime) { txt.destroy(); } + for (let txt of this.txtLapPos) { txt.destroy(); } + this.lapContainer.destroy(); + + this.btnContinue.destroy(); + } +} diff --git a/src/ui/panelEnterShip.js b/src/ui/panelEnterShip.js new file mode 100755 index 0000000..f5dd720 --- /dev/null +++ b/src/ui/panelEnterShip.js @@ -0,0 +1,108 @@ +import Button from "./button.js"; +import { SliderHorizontal } from "./slider.js"; +import MovingGrid from "./movingGrid.js"; + +export default class PanelEnterShip{ + constructor(_scene, _level, _returnPos) { + this.scene = _scene; + this.level = _level; + this.returnPos = _returnPos; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x000000, 0.9); + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + + this.bgGrid = new MovingGrid(this.scene, this.scene.game.config.width, this.scene.game.config.height, 32); + this.bgGrid.addPointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + + this.btnBack = new Button(this.scene, { x: -160, y: -68 }, "atlasUi", "sprBtn00", "EXIT SHIP", false, () => { + //console.log(this.scene.hand.justPressed + " , " + this.scene.hand.justReleased) + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + + this.level.shipInteractable.interactable = true; + this.scene.player.jumpToPosition(_returnPos, true); + this.scene.player.eyeHeight = 24; + this.scene.player.setMoveMode(PLAYERMOVE.STAND); + + this.destroy(); + }); + + this.btnTrack00 = new Button(this.scene, { x: 160, y: -68 }, "atlasUi", "sprBtn00", "TEST TRACK", false, () => { + this.level.leavingHangar = true;//todo: create a function with leave to track? After moving enough upward? + this.level.toTrack = 0; + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + + this.btnTrack01 = new Button(this.scene, { x: 160, y: -34 }, "atlasUi", "sprBtn00", "SEWERS", false, () => { + this.level.leavingHangar = true; + this.level.toTrack = 1; + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + + this.btnTrack02 = new Button(this.scene, { x: 160, y: 0 }, "atlasUi", "sprBtn00", "CONSTRUCTION", false, () => { + this.level.leavingHangar = true; + this.level.toTrack = 2; + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + + this.btnTrack03 = new Button(this.scene, { x: 160, y: 34 }, "atlasUi", "sprBtn00", "OVAL", false, () => { + this.level.leavingHangar = true; + this.level.toTrack = 3; + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + + this.btnTrack04 = new Button(this.scene, { x: 160, y: 68 }, "atlasUi", "sprBtn00", "TEST", false, () => { + this.level.leavingHangar = true; + this.level.toTrack = 0; + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + + this.btnTrack01.switchState(this.btnTrack01.states.off); + + this.lockButtons = true; + } + + update(){ + this.bgGrid.updatePointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + this.bgGrid.update(); + + if(this.lockButtons <= false){ + + this.btnBack.update(); + this.btnTrack00.update(); + this.btnTrack01.update(); + this.btnTrack02.update(); + this.btnTrack03.update(); + //this.btnTrack04.update(); + }else{ + this.lockButtons = false; + } + } + + destroy(){ + this.bgGraphics.destroy(); + this.bgGrid.destroy(); + this.btnBack.destroy(); + this.btnTrack00.destroy(); + this.btnTrack01.destroy(); + this.btnTrack02.destroy(); + this.btnTrack03.destroy(); + this.btnTrack04.destroy(); + } +} \ No newline at end of file diff --git a/src/ui/panelEnterShipDemo00.js b/src/ui/panelEnterShipDemo00.js new file mode 100755 index 0000000..da87324 --- /dev/null +++ b/src/ui/panelEnterShipDemo00.js @@ -0,0 +1,190 @@ +import Button from "./button.js"; +import { SliderHorizontal } from "./slider.js"; +import MovingGrid from "./movingGrid.js"; + +export default class PanelEnterShipDemo00 { + constructor(_scene, _level, _returnPos) { + this.scene = _scene; + this.level = _level; + this.returnPos = _returnPos; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x000000, 0.9); + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + + this.bgGrid = new MovingGrid(this.scene, this.scene.game.config.width, this.scene.game.config.height, 32); + this.bgGrid.addPointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + + this.btnBack = new Button(this.scene, { x: -160, y: -68 }, "atlasUi", "sprBtn00", "EXIT SHIP", false, () => { + //console.log(this.scene.hand.justPressed + " , " + this.scene.hand.justReleased) + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + + this.level.shipInteractable.interactable = true; + this.scene.player.jumpToPosition(_returnPos, true); + this.scene.player.eyeHeight = 24; + this.scene.player.setMoveMode(PLAYERMOVE.STAND); + + this.destroy(); + }); + + this.btnTrack00 = new Button(this.scene, { x: 16, y: -68 }, "atlasUi", "sprBtn00square", "LOAD SIMULATION\nTUTORIAL", false, () => { + this.level.leavingHangar = false; + this.level.toTrack = 9000; + this.level.maxLaps = 99; + this.level.raceMode = 99; + + if (Number(flagManager.getFlagById("demoProgress").value) >= 1) { + this.level.toTrack = 9002; + this.level.maxLaps = 5; + this.level.raceMode = 0; + } + + //flagManager.setFlag("demoProgress", "1"); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + + this.level.startSimulation(); + }); + if (Number(flagManager.getFlagById("demoProgress").value) >= 1) { + this.btnTrack00.txt.setText("RACING LINE\nHOT LAPS"); + } + + this.btnTrack01 = new Button(this.scene, { x: 160, y: -68 }, "atlasUi", "sprBtn00square", "METRO LOOP\nQUALIFICATION", false, () => { + this.level.leavingHangar = true; + this.level.toTrack = 0; + //todo check if practice is needed or quali skipped after herring talk + + if (Number(flagManager.getFlagById("demoProgress").value) >= 4) { + this.level.toTrack = 0; + this.level.maxLaps = 5; + this.level.raceMode = 5; + } else { + this.level.maxLaps = 3; + this.level.raceMode = 3; + flagManager.setFlag("demoProgress", "4"); + } + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + if (Number(flagManager.getFlagById("demoProgress").value) >= 4) { + this.btnTrack01.txt.setText("METRO LOOP\nFULL RACE"); + } + + this.btnTrack02 = new Button(this.scene, { x: 16, y: 76 }, "atlasUi", "sprBtn00square", "PIPELINE\nRACE ROKI", false, () => { + this.level.leavingHangar = true; + this.level.toTrack = 3; + this.level.maxLaps = 2; + this.level.raceMode = 6; //5gp 6canyon + + if (Number(flagManager.getFlagById("demoProgress").value) >= 4) { + this.level.toTrack = 3; + this.level.maxLaps = 3; + this.level.raceMode = 5; + } + + //flagManager.setFlag("demoProgress", "2"); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + if (Number(flagManager.getFlagById("demoProgress").value) >= 4) { + this.btnTrack02.txt.setText("PIPELINE\nFULL RACE"); + } + + this.btnTrack03 = new Button(this.scene, { x: 160, y: 76 }, "atlasUi", "sprBtn00square", "ATOMIC SEWERS\nHOT LAPS", false, () => { + this.level.leavingHangar = true; + this.level.toTrack = 1; + this.level.maxLaps = 7; + this.level.raceMode = 0; + + //flagManager.setFlag("demoProgress", "2"); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + + /* + this.btnTrack04 = new Button(this.scene, { x: 160, y: 68 }, "atlasUi", "sprBtn00", "TEST", false, () => { + this.level.leavingHangar = true; + this.level.toTrack = 0; + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + this.btnTrack01.switchState(this.btnTrack01.states.off);*/ + + //todo: reset this + //if (Number(flagManager.getFlagById("demoProgress").value) > 0) { this.btnTrack00.switchState(this.btnTrack01.states.off); } + if (Number(flagManager.getFlagById("demoProgress").value) <= 3) { + this.btnTrack01.switchState(this.btnTrack01.states.off); + } + if (Number(flagManager.getFlagById("demoProgress").value) <= 2) { + this.btnTrack02.switchState(this.btnTrack02.states.off); + } + if (Number(flagManager.getFlagById("demoProgress").value) <= 1) { + this.btnTrack03.switchState(this.btnTrack03.states.off); + } + + if (Number(flagManager.getFlagById("demoProgress").value) === 5) { + this.btnTrack00.switchState(this.btnTrack01.states.off); + this.btnTrack01.switchState(this.btnTrack01.states.off); + this.btnTrack02.switchState(this.btnTrack01.states.off); + this.btnTrack03.switchState(this.btnTrack01.states.off); + } + + this.lockButtons = true; + } + + update() { + this.bgGrid.updatePointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + this.bgGrid.update(); + + if (this.lockButtons <= false) { + this.btnBack.update(); + + //todo: reset this + let progress = Number(flagManager.getFlagById("demoProgress").value); + + if ((progress >= 0 && progress < 5) || progress > 5) { + this.btnTrack00.update(); + } + if ((progress >= 2 && progress < 5) || progress > 5) { + this.btnTrack02.update(); + } + if ((progress >= 4 && progress < 5) || progress > 5) { + this.btnTrack01.update(); + } + if ((progress >= 1 && progress < 5) || progress > 5) { + this.btnTrack03.update(); + } + + //this.btnTrack00.update() + //this.btnTrack01.update() + //this.btnTrack02.update() + //this.btnTrack03.update() + + //this.btnTrack04.update(); + } else { + this.lockButtons = false; + } + } + + destroy() { + this.bgGraphics.destroy(); + this.bgGrid.destroy(); + this.btnBack.destroy(); + this.btnTrack00.destroy(); + this.btnTrack01.destroy(); + this.btnTrack02.destroy(); + this.btnTrack03.destroy(); + //this.btnTrack04.destroy(); + } +} diff --git a/src/ui/panelEscapeMenu.js b/src/ui/panelEscapeMenu.js new file mode 100755 index 0000000..1609e0e --- /dev/null +++ b/src/ui/panelEscapeMenu.js @@ -0,0 +1,400 @@ +import Button from "./button.js"; +import { SliderHorizontal } from "./slider.js"; +import MovingGrid from "./movingGrid.js"; + +export default class PanelEscapeMenu{ + constructor(_scene, _level, _previousState = 0, _fromWalk = false) { + this.scene = _scene; + this.level = _level; + this.previousState = _previousState; + this.fromWalk = _fromWalk; + + this.scene.hand.setMouseLock(false); + this.scene.hand.showCursor = true; + this.scene.hand.cursor.alpha = 1; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x1d2b53, 0.9); //0x000000, 0.9 + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + + this.bgGrid = new MovingGrid(this.scene, this.scene.game.config.width, this.scene.game.config.height, 32); + this.bgGrid.addPointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + + this.qrcode = this.scene.add.sprite(160, 68, "atlasUi", "qrcode"); + this.qrcode.depth = 9999; + + //left side + this.btnBack = new Button(this.scene, { x: -176, y: -112}, "atlasUi", "sprBtn00", "CONTINUE", false, () => { + this.scene.saveOptions(); + //this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.paused = false; + if(this.fromWalk === false){ + //racing + this.level.state = this.previousState; + this.level.ui.show(); + }else{ + //fps level + this.scene.player.showUI(); + this.scene.player.setMode(PLAYERMODE.LOOK); + } + + this.scene.player.panel = null; + this.destroy(); + }); + + /* + this.btnToTrack = new Button(this.scene, { x: -160, y: -34 }, "atlasUi", "sprBtn00", "DIRECT TRACK", false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + + this.scene.loadLevel("quadRingsTest", {track: 2, startFromHangar: false, playerShipModel: "modHoverCarWipeOutStyle"}); + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + */ + + let playingStory = flagManager.getFlagById("playingStory").value; + this.btnToMainMenu = new Button(this.scene, { x: -176, y: 112 }, "atlasUi", "sprBtn00", "MAIN MENU", false, () => { + //todo: you need be able to jump back into the main menu as well - idk maybe it needs a third button to either go to hangar or main menu + /*if(playingStory === "1"){ + this.scene.player.panel = null; + this.level.destroy(); + + this.destroy(); + //this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + this.scene.loadLevel("hangar00", {startFromElevator: true, showIntro: true});//dream00 + //INFO demo starts with a panel so dont override after the fact + //this.scene.player.setMode(PLAYERMODE.LOOK); + //this.scene.player.panel = null; + }else{*/ + this.scene.paused = false; + if(this.fromWalk === false){ + this.scene.soundManager.stopSound(this.scene.soundManager.engineSound); + this.scene.soundManager.stopSound(this.scene.soundManager.engineRotorSound); + this.scene.soundManager.stopSound(this.scene.soundManager.scrapeSound); + this.scene.soundManager.stopSound(this.scene.soundManager.heatWarningSound); + this.scene.soundManager.stopSound(this.level.musicTrack); + } + this.scene.player.panel = null; + this.level.destroy(); + + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.scene.player.setVisibility(false); + this.scene.loadLevel("mainMenu", {}); + this.destroy(); + //} + }); + this.btnToHangar = null; + if(playingStory === "1" && this.scene.player.id === "shipPlayer"){ + this.btnToHangar = new Button(this.scene, { x: -176, y: -112 + 34 }, "atlasUi", "sprBtn00", "END RACE", false, () => { + this.scene.soundManager.stopSound(this.scene.soundManager.engineSound); + this.scene.soundManager.stopSound(this.scene.soundManager.engineRotorSound); + this.scene.soundManager.stopSound(this.scene.soundManager.scrapeSound); + this.scene.soundManager.stopSound(this.scene.soundManager.heatWarningSound); + this.scene.soundManager.stopSound(this.level.musicTrack); + + this.scene.paused = false; + + this.scene.player.panel = null; + this.level.destroy(); + + this.destroy(); + //this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + this.scene.loadLevel("hangar00", {startFromElevator: false, showIntro: false});//dream00 + //INFO demo starts with a panel so dont override after the fact + //this.scene.player.setMode(PLAYERMODE.LOOK); + //this.scene.player.panel = null; + }); + } + + /* + this.btnToEditor = new Button(this.scene, { x: -160, y: 102 }, "atlasUi", "sprBtn00", "editor", false, () => { + this.level.destroy(); + + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + + this.scene.loadLevel("modelBuilder"); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + */ + + this.btnAUX = new Button(this.scene, { x: 176 + 32 - 132, y: -112 }, "atlasUi", "sprBtn00mid", "AUX", false, () => { + this.contAUX.alpha = 1; + this.contGFX.alpha = 0; + this.contCTL.alpha = 0; + this.activeContainer = this.contAUX; + }); + this.btnGFX = new Button(this.scene, { x: 176 + 32 - 66, y: -112 }, "atlasUi", "sprBtn00mid", "GFX", false, () => { + this.contAUX.alpha = 0; + this.contGFX.alpha = 1; + this.contCTL.alpha = 0; + this.activeContainer = this.contGFX; + }); + this.btnCTL = new Button(this.scene, { x: 176 + 32, y: -112 }, "atlasUi", "sprBtn00mid", "CTRL", false, () => { + this.contAUX.alpha = 0; + this.contGFX.alpha = 0; + this.contCTL.alpha = 1; + this.activeContainer = this.contCTL; + }); + + this.contAUX = this.scene.add.container(0, 0); + this.contGFX = this.scene.add.container(0, 0); + this.contGFX.alpha = 0; + this.contCTL = this.scene.add.container(0, 0); + this.contCTL.alpha = 0; + this.activeContainer = this.contAUX; + + //sound options + this.sliMaster = new SliderHorizontal(this.scene, {x: 0, y: -34}, OPTIONS.sound.master, 128); + this.sliMaster.move(0, -34); + this.sliMaster.releaseFunc = () => { + Howler.volume(this.sliMaster.value); + this.scene.soundManager.playSpecificSound(this.scene.soundManager.raceAnnouncer, 0); + OPTIONS.sound.master = this.sliMaster.value; + } + this.btnMaster = new Button(this.scene, { x: -128, y: -34 }, "atlasUi", "sprBtn08", "master:", false, () => { + if(this.sliMaster.value > 0){ + this.sliMaster.setTo(0); + }else{ + this.sliMaster.setTo(1); + } + }); + this.sliMaster.addToContainer(this.contAUX); + this.btnMaster.addToContainer(this.contAUX); + + this.sliSound = new SliderHorizontal(this.scene, {x: 0, y: 0}, OPTIONS.sound.sfx, 128); + this.sliSound.move(0, 0); + this.sliSound.releaseFunc = () => { + for(let s of this.scene.soundManager.soundRef){ + s.howlGroup.volume(this.sliSound.value); + } + this.scene.soundManager.playSpecificSound(this.scene.soundManager.raceAnnouncer, 0); + OPTIONS.sound.sfx = this.sliSound.value; + } + this.btnSound = new Button(this.scene, { x: -128, y: 0 }, "atlasUi", "sprBtn08", "sound:", false, () => { + if(this.sliSound.value > 0){ + this.sliSound.setTo(0); + }else{ + this.sliSound.setTo(1); + } + }); + this.sliSound.addToContainer(this.contAUX); + this.btnSound.addToContainer(this.contAUX); + + this.sliMusic = new SliderHorizontal(this.scene, {x: 0, y: 34}, OPTIONS.sound.music, 128); + this.sliMusic.move(0, 34); + this.sliMusic.releaseFunc = () => { + //Howler.volume(this.sliMusic.value); + for(let s of this.scene.soundManager.musicRef){ + s.howlGroup.volume(this.sliMusic.value); + } + OPTIONS.sound.music = this.sliMusic.value; + } + this.btnMusic = new Button(this.scene, { x: -128, y: 34 }, "atlasUi", "sprBtn08", "music:", false, () => { + if(this.sliMusic.value > 0){ + this.sliMusic.setTo(0); + }else{ + this.sliMusic.setTo(1); + } + }); + this.sliMusic.addToContainer(this.contAUX); + this.btnMusic.addToContainer(this.contAUX); + + //graphical options + this.sliScreenshake = new SliderHorizontal(this.scene, {x: 0, y: -34}, OPTIONS.effects.screenshake, 128); + this.sliScreenshake.move(0, -34); + this.sliScreenshake.releaseFunc = () => { + OPTIONS.effects.screenshake = this.sliScreenshake.value; + } + this.btnScreenshake = new Button(this.scene, { x: -128, y: -34 }, "atlasUi", "sprBtn00mid", "screenshake:", false, () => { + if(this.sliScreenshake.value > 0){ + this.sliScreenshake.setTo(0); + }else{ + this.sliScreenshake.setTo(1); + } + }); + this.sliScreenshake.addToContainer(this.contGFX); + this.btnScreenshake.addToContainer(this.contGFX); + + this.btnFullscreen = new Button(this.scene, { x: -128, y: 0 }, "atlasUi", "sprBtn00mid", "fullscreen", false, () => { + if(document.fullscreen === false){ + if(document.documentElement.requestFullscreen) { + document.documentElement.requestFullscreen(); + } else if(document.documentElement.msRequestFullscreen) { // for IE11 (remove June 15, 2022) + document.documentElement.msRequestFullscreen(); + } else if(document.documentElement.webkitRequestFullscreen) { // iOS Safari + document.documentElement.webkitRequestFullscreen(); + } + }else{ + if (document.exitFullscreen) { + document.exitFullscreen(); + } else if (document.msExitFullscreen) { + document.msExitFullscreen(); + } else if (document.webkitExitFullscreen) { + document.webkitExitFullscreen(); + } + } + }); + this.btnFullscreen.addToContainer(this.contGFX); + + this.btnHUD = new Button(this.scene, { x: -128, y: 34 }, "atlasUi", "sprBtn00mid", "HUD", true, () => { + if(OPTIONS.config.hideUI === false){ + OPTIONS.config.hideUI = true; + this.btnHUDTxt.setText("hidden"); + }else{ + OPTIONS.config.hideUI = false; + this.btnHUDTxt.setText("active"); + } + }); + this.btnHUD.toggleOffFunc = this.btnHUD.func; + this.btnHUD.addToContainer(this.contGFX); + this.btnHUDTxt = this.scene.add.bitmapText(this.btnHUD.pos.x + 128, this.btnHUD.pos.y, "uiFont", "active", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.btnHUDTxt.depth = 10000; + this.contGFX.add(this.btnHUDTxt); + if(OPTIONS.config.hideUI === false){ + this.btnHUD.active = true; + this.btnHUDTxt.setText("active"); + }else{ + this.btnHUD.active = false; + this.btnHUDTxt.setText("hidden"); + } + + //control options + this.sliCursorspeed = new SliderHorizontal(this.scene, {x: 0, y: 0}, OPTIONS.controls.mouse.sensitivity / 6, 128); + this.sliCursorspeed.move(0, 0); + this.sliCursorspeed.releaseFunc = () => { + OPTIONS.controls.mouse.sensitivity = Math.max(0.1, this.sliCursorspeed.value * 6); + } + this.btnCursorspeed = new Button(this.scene, { x: -128, y: 0 }, "atlasUi", "sprBtn00mid", "mouse sensitivity:", false, () => { + if(this.sliCursorspeed.value > 0){ + this.sliCursorspeed.setTo(0); + }else{ + this.sliCursorspeed.setTo(1); + } + }); + this.sliCursorspeed.addToContainer(this.contCTL); + this.btnCursorspeed.addToContainer(this.contCTL); + + this.btnRadar = new Button(this.scene, { x: -128, y: 34 }, "atlasUi", "sprBtn00mid", "radar", true, () => { + if(OPTIONS.config.collisionRadar === 0){ + OPTIONS.config.collisionRadar = 1; + this.btnRadarTxt.setText("active"); + }else{ + OPTIONS.config.collisionRadar = 0; + this.btnRadarTxt.setText("off"); + } + }); + this.btnRadar.toggleOffFunc = this.btnRadar.func; + this.btnRadar.addToContainer(this.contCTL); + this.btnRadarTxt = this.scene.add.bitmapText(this.btnRadar.pos.x + 128, this.btnRadar.pos.y, "uiFont", "active", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.btnRadarTxt.depth = 10000; + this.contCTL.add(this.btnRadarTxt); + if(OPTIONS.config.collisionRadar === 0){ + this.btnRadar.active = false; + this.btnRadarTxt.setText("off"); + }else{ + this.btnRadar.active = true; + this.btnRadarTxt.setText("active"); + } + + this.lockButtons = true; + } + + update(){ + this.bgGrid.updatePointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + this.bgGrid.update(); + + if(this.lockButtons === false){ + this.btnBack.update(); + //this.btnToTrack.update(); + this.btnToMainMenu.update(); + if(this.btnToHangar !== null){ + this.btnToHangar.update(); + } + //this.btnToEditor.update(); + + //todo: does not work although lockButtons should prevent it + if(INPUTS.btnStart.justpressed){ + this.btnBack.func(); + } + + this.btnAUX.update(); + this.btnGFX.update(); + this.btnCTL.update(); + + switch(this.activeContainer){ + case this.contAUX: + this.btnMaster.update(); + this.sliMaster.update(); + this.btnSound.update(); + this.sliSound.update(); + this.btnMusic.update(); + this.sliMusic.update(); + break; + case this.contGFX: + this.btnScreenshake.update(); + this.sliScreenshake.update(); + this.btnFullscreen.update(); + this.btnHUD.update(); + break; + case this.contCTL: + this.btnCursorspeed.update(); + this.sliCursorspeed.update(); + this.btnRadar.update(); + break; + default: + break; + } + }else{ + this.lockButtons = false; + } + } + + destroy(){ + this.bgGraphics.destroy(); + this.bgGrid.destroy(); + + this.qrcode.destroy(); + + this.btnBack.destroy(); + //this.btnToTrack.destroy(); + this.btnToMainMenu.destroy(); + if(this.btnToHangar !== null){ + this.btnToHangar.destroy(); + } + //this.btnToEditor.destroy(); + + this.btnAUX.destroy(); + this.btnGFX.destroy(); + this.btnCTL.destroy(); + + this.btnMaster.destroy(); + this.sliMaster.destroy(); + this.btnSound.destroy(); + this.sliSound.destroy(); + this.btnMusic.destroy(); + this.sliMusic.destroy(); + + this.btnScreenshake.destroy(); + this.sliScreenshake.destroy(); + this.btnFullscreen.destroy(); + this.btnHUD.destroy(); + this.btnHUDTxt.destroy(); + + this.btnCursorspeed.destroy(); + this.sliCursorspeed.destroy(); + this.btnRadar.destroy(); + this.btnRadarTxt.destroy(); + + this.contAUX.destroy(); + this.contGFX.destroy(); + this.contCTL.destroy(); + } +} \ No newline at end of file diff --git a/src/ui/panelFlavourText.js b/src/ui/panelFlavourText.js new file mode 100755 index 0000000..7fea8b6 --- /dev/null +++ b/src/ui/panelFlavourText.js @@ -0,0 +1,59 @@ +export default class PanelFlavourText{ + constructor(_scene, _txt) { + this.scene = _scene; + + //stop use click clicking immediatly again and eg hit the back btn + this.scene.hand.justPressed = false; + this.scene.hand.pressed = false; + this.scene.hand.justReleased = false; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x000000, 0.75); + this.bgGraphics.fillRect(this.scene.left, -64, this.scene.game.config.width, 64); + + /* + this.bgGraphics.beginPath(); + this.bgGraphics.lineStyle(1, 0xffffff); + this.bgGraphics.moveTo(-128, -16); + this.bgGraphics.lineTo(128, -16); + this.bgGraphics.strokePath(); + */ + + this.header = this.scene.add.bitmapText(0, -32, "segoeUI_16", _txt, 16, 0).setOrigin(0.5); + this.header.depth = 10000; + + this.tweenBg = this.scene.add.tween({ + targets: this.bgGraphics, + alpha: 0, + delay: 1500, + duration: 2500, + ease: Phaser.Math.Easing.Cubic.Out, + onComplete: () => { + this.destroy(); + this.scene.player.panel = null; + } + }) + + this.tweenHeader = this.scene.add.tween({ + targets: this.header, + alpha: 0, + delay: 1500, + duration: 2500, + ease: Phaser.Math.Easing.Quintic.Out, + onComplete: () => { + + } + }) + } + + update(){ + + } + + destroy(){ + //this.tweenBg.destroy(); + //this.tweenHeader.destroy(); + this.bgGraphics.destroy(); + this.header.destroy(); + } +} \ No newline at end of file diff --git a/src/ui/panelIntro.js b/src/ui/panelIntro.js new file mode 100755 index 0000000..f87bc84 --- /dev/null +++ b/src/ui/panelIntro.js @@ -0,0 +1,240 @@ +import Button from "./button.js"; +import { SliderHorizontal } from "./slider.js"; +import MovingGrid from "./movingGrid.js"; + +export default class PanelIntroDemo{ + constructor(_scene) { + this.scene = _scene; + + this.scene.hand.justPressed = false; + this.scene.hand.pressed = false; + this.scene.hand.justReleased = false; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x000000, 0.95); + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + + this.bgGrid = new MovingGrid(this.scene, this.scene.game.config.width, this.scene.game.config.height, 32); + this.bgGrid.addPointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + + this.pos = { + x: 0, + y: this.scene.game.config.height, + start: { + x: 0, + y: this.scene.game.config.height, + }, + end: { + x: 0, + y: this.scene.game.config.height * -1, + }, + in: { + x: 0, + y: this.scene.game.config.height, + }, + out: { + x: 0, + y: 0, + } + } + this.target = { + in: { + x: 0, + y: 0 + }, + out: { + x: 0, + y: this.scene.game.config.height * -1, + } + } + + this.tweenIn = this.scene.tweens.add({ + targets: this.pos.in, + x: { value: () => this.target.in.x }, + y: { value: () => this.target.in.y }, + ease: "Sine.easeInOut", + duration: 500, + callbackScope: this + }); + this.tweenOut = this.scene.tweens.add({ + targets: this.pos.out, + x: { value: () => this.target.out.x}, + y: { value: () => this.target.out.y}, + ease: "Sine.easeInOut", + duration: 750, + callbackScope: this + }); + + //STORYBITS //this.scene.add.bitmapText(0, (this.scene.game.config.height * -0.4), "uiFont", "Test", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.story = { + currentBit: 0, + previousBit: -1, + bits: [ + { + txt: this.scene.add.bitmapText(this.pos.start.x, this.pos.start.y, "uiFont", "The world is dying.", 14, 0).setOrigin(0.5).setLetterSpacing(0), + }, { + txt: this.scene.add.bitmapText(this.pos.start.x, this.pos.start.y, "uiFont", "We are dying.", 14, 0).setOrigin(0.5).setLetterSpacing(0), + }, { + txt: this.scene.add.bitmapText(this.pos.start.x, this.pos.start.y, "uiFont", "A global rise in CO2 levels forced civilisation underground.", 14, 0).setOrigin(0.5).setLetterSpacing(0), + }, { + txt: this.scene.add.bitmapText(this.pos.start.x, this.pos.start.y, "uiFont", "Our cities were connected through pipelines and hyperloops, built to help us reach prosperity.", 14, 0).setOrigin(0.5).setLetterSpacing(0), + }, { + txt: this.scene.add.bitmapText(this.pos.start.x, this.pos.start.y, "uiFont", "Or so we thought.", 14, 0).setOrigin(0.5).setLetterSpacing(0), + }, { + txt: this.scene.add.bitmapText(this.pos.start.x, this.pos.start.y, "uiFont", "The rich got richer, the poor grew more poor.", 14, 0).setOrigin(0.5).setLetterSpacing(0), + }, { + txt: this.scene.add.bitmapText(this.pos.start.x, this.pos.start.y, "uiFont", "Nobody wanted to do anything against the climate crisis. No government wanted to risk their economy.", 14, 0).setOrigin(0.5).setLetterSpacing(0), + sprite: this.scene.add.sprite(this.pos.start.x, this.pos.start.y * 2, "sprStoryPolitics00") + }, { + txt: this.scene.add.bitmapText(this.pos.start.x, this.pos.start.y, "uiFont", "Instead we got to build for a new future with climate change in mind.", 14, 0).setOrigin(0.5).setLetterSpacing(0), + sprite: this.scene.add.sprite(this.pos.start.x, this.pos.start.y * 2, "sprStoryLoop00") + }, { + txt: this.scene.add.bitmapText(this.pos.start.x, this.pos.start.y, "uiFont", "Underground.", 14, 0).setOrigin(0.5).setLetterSpacing(0), + }, { + txt: this.scene.add.bitmapText(this.pos.start.x, this.pos.start.y, "uiFont", "We built huge air filtering stations, underground gardens, anti-flood pumps. The economy boomed. Everyone had a job and worked for a new future. A new hope.", 14, 0).setOrigin(0.5).setLetterSpacing(0), + }, { + txt: this.scene.add.bitmapText(this.pos.start.x, this.pos.start.y, "uiFont", "Little did we know, that the superrich already planned further ahead.", 14, 0).setOrigin(0.5).setLetterSpacing(0), + }, { + txt: this.scene.add.bitmapText(this.pos.start.x, this.pos.start.y, "uiFont", "Earths climate is on a runaway course and we are trapped underground.", 14, 0).setOrigin(0.5).setLetterSpacing(0), + }, { + txt: this.scene.add.bitmapText(this.pos.start.x, this.pos.start.y, "uiFont", "The rich elite secured their future. Some bought themselves a stasis chamber to outwait the catastrophe. Others left earth to colonise mars and start anew.", 14, 0).setOrigin(0.5).setLetterSpacing(0), + }, { + txt: this.scene.add.bitmapText(this.pos.start.x, this.pos.start.y, "uiFont", "People are unemployed and dying. They dance a danse-macabre until all will come to an end.", 14, 0).setOrigin(0.5).setLetterSpacing(0), + }, { + txt: this.scene.add.bitmapText(this.pos.start.x, this.pos.start.y, "uiFont", "There is only one chance left for some us. We race in the tunnels to win one of the last tickets in a rocket off earth.", 14, 0).setOrigin(0.5).setLetterSpacing(0), + sprite: this.scene.add.sprite(this.pos.start.x, this.pos.start.y * 2, "sprStoryRacing00") + }, { + txt: this.scene.add.bitmapText(this.pos.start.x, this.pos.start.y, "uiFont", "Our grandparents were the people who built this all!", 14, 0).setOrigin(0.5).setLetterSpacing(0), + }, { + txt: this.scene.add.bitmapText(this.pos.start.x, this.pos.start.y, "uiFont", "And we are the people who race to escape it!", 14, 0).setOrigin(0.5).setLetterSpacing(0), + } + ] + } + for(let b of this.story.bits){ + if(b.txt !== undefined){ + b.txt.setMaxWidth(292); + b.txt.depth = 9999; + } + if (b.sprite !== undefined) { + //b.sprite.depth = -100; + b.txt.depth = 9899; + } + } + + //left side + this.btnBack = new Button(this.scene, { x: -160, y: -68 }, "atlasUi", "sprBtn00", "SKIP", false, () => { + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + + //left side + this.btnContinue = new Button(this.scene, { x: -160, y: -34 }, "atlasUi", "sprBtn00", "CONTINUE", false, () => { + + }); + + this.narrator = this.scene.add.sprite(-160, 68, "atlasUi", "portraitRob00sw"); + this.narrator.depth = 9999; + + this.lockButtons = true; + } + + update(){ + this.bgGrid.updatePointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + this.bgGrid.update(); + + if(this.lockButtons === false){ + + this.btnBack.update(); + this.btnContinue.update(); + + if (this.story.currentBit < this.story.bits.length) { + this.story.bits[this.story.currentBit].txt.x = this.pos.in.x + 64; + this.story.bits[this.story.currentBit].txt.y = this.pos.in.y; + if (this.story.bits[this.story.currentBit].sprite !== undefined){ + this.story.bits[this.story.currentBit].sprite.x = this.pos.in.x; + this.story.bits[this.story.currentBit].sprite.y = this.pos.in.y * 2; + //todo: think if you want it this way or if it just stays + this.narrator.alpha = 0; + }else{ + this.narrator.alpha = 1; + } + } + if(this.story.previousBit >= 0){ + this.story.bits[this.story.previousBit].txt.x = this.pos.out.x + 64; + this.story.bits[this.story.previousBit].txt.y = this.pos.out.y; + if (this.story.bits[this.story.previousBit].sprite !== undefined) { + this.story.bits[this.story.previousBit].sprite.x = this.pos.out.x; + this.story.bits[this.story.previousBit].sprite.y = this.pos.out.y * 2; + } + } + + if ((this.scene.hand.justReleased === true || INPUTS.btnA.justReleased === true) && this.tweenOut.isPlaying() === false && this.tweenIn.isPlaying() === false){ + if(this.story.currentBit < this.story.bits.length){ + this.story.currentBit += 1; + this.story.previousBit += 1; + + this.pos.in.x = this.pos.start.x; + this.pos.in.y = this.pos.start.y; + this.tweenIn.updateTo("x", this.target.in.x, false); + this.tweenIn.updateTo("y", this.target.in.y, false); + this.tweenIn.restart(); + + this.pos.out.x = 0; + this.pos.out.y = 0; + this.tweenOut.updateTo("x", this.target.out.x, false); + this.tweenOut.updateTo("y", this.target.out.y, false); + this.tweenOut.restart(); + + if(this.story.currentBit === this.story.bits.length){ + this.gotoGame(); + } + }else{ + this.gotoGame(); + } + } + + if(INPUTS.btnB.justReleased === true){ + this.gotoMenu(); + } + + }else{ + this.lockButtons = false; + } + + + } + + gotoGame(){ + /*//from wakeup + this.scene.player.panel = null; + this.scene.player.showUI(); + this.destroy();*/ + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + } + + gotoMenu(){ + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + } + + destroy(){ + this.bgGraphics.destroy(); + this.bgGrid.destroy(); + + this.btnBack.destroy(); + this.btnContinue.destroy(); + + this.narrator.destroy(); + + for(let b of this.story.bits){ + b.txt.destroy(); + if(b.sprite !== undefined){ + b.sprite.destroy(); + } + } + } +} \ No newline at end of file diff --git a/src/ui/panelInventory.js b/src/ui/panelInventory.js new file mode 100755 index 0000000..1793152 --- /dev/null +++ b/src/ui/panelInventory.js @@ -0,0 +1,160 @@ +import Button from "./button.js"; + +export default class PanelInventory{ + constructor(_scene) { + this.scene = _scene; + + //stop use click clicking immediatly again and eg hit the back btn + this.scene.hand.justPressed = false; + this.scene.hand.pressed = false; + this.scene.hand.justReleased = false; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x000000, 0.9); + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + + this.btnBack = new Button(this.scene, { x: -180, y: -116 }, "atlasUi", "sprBtn00", "back", false, () => { + this.destroy(); + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + }); + + /*this.btnDream = new Button(this.scene, { x: 160, y: -66 }, "sprBtn00", "DREAM", false, () => { + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + this.scene.loadLevel("dream00"); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + });*/ + + //this.saveGame = JSON.parse(localStorage.getItem(SAVEGAMENAME)); + + this.drag = { + item: null, + offset: { + x: 0, + y: 0 + } + } + + this.bg = this.scene.add.sprite(0, 0, "atlasFps", "fps_tex_128_inventory"); + this.bg.setScale(4); + this.bg.alpha = 0.5; + + let xx = -2000; + let yy = 0; + + if (flagManager.getFlagById("dreamcoin") !== null) { + xx = Number(flagManager.getFlagById("dreamcoin").value) > 0 ? -128 : -2000; + } + this.dreamcoin = this.scene.add.sprite(xx, 0, "atlasObstacles", "obstTokenSmiley"); + + if (flagManager.getFlagById("dream00hasKey") !== null) { + xx = flagManager.getFlagById("dream00hasKey").value === "true" ? -128 : -2000; + } + this.dreamkey = this.scene.add.sprite(xx, 0, "atlasObjects", "itemDreamKey00"); + /* + if (flagManager.getFlagById("00hasRevolver") !== null) { + xx = flagManager.getFlagById("00hasRevolver").value === "true" ? -128 : -2000; + } + this.revolver = this.scene.add.sprite(xx, 0, "itemRevolver"); + + xx = -2000; + if (flagManager.getFlagById("00hasBullet") !== null) { + xx = flagManager.getFlagById("00hasBullet").value === "true" ? 32 : -2000; + } + this.bullet = this.scene.add.sprite(xx, 0, "atlasItems", "itemRevolverRoundFull"); + this.bullet.rotation = Math.PI * 0.5; + + xx = -2000; + if (flagManager.getFlagById("00hasCigarettes") !== null) { + xx = flagManager.getFlagById("00hasCigarettes").value === "true" ? 0 : -2000; + } + this.cigarettes = this.scene.add.sprite(xx, 64, "atlasItems", "itemCigarettes00"); + + xx = -2000; + if (flagManager.getFlagById("00hasKeycard") !== null) { + xx = flagManager.getFlagById("00hasKeycard").value === "true" ? -128 : -2000; + } + this.keycard = this.scene.add.sprite(xx, 96, "atlasItems", "itemKeycard"); + + xx = -2000; + if (flagManager.getFlagById("00hasShipcard") !== null) { + xx = flagManager.getFlagById("00hasShipcard").value === "true" ? 128 : -2000; + } + this.shipcard = this.scene.add.sprite(xx, 0, "atlasItems", "itemCardBoat"); + + xx = -2000; + if (flagManager.getFlagById("00hasPlant") !== null) { + xx = flagManager.getFlagById("00hasPlant").value === "true" ? -128 : -2000; + } + this.plant = this.scene.add.sprite(xx, 0, "atlasItems", "itemPlant00"); + + this.photo = this.scene.add.sprite(-96, -64, "atlasItems", "itemPhotoWho"); + + this.items = [ + this.revolver, + this.bullet, + this.cigarettes, + this.keycard, + this.shipcard, + this.plant, + this.photo + ]*/ + + this.items = [ + this.dreamcoin + ] + + for (let it of this.items) { + it.setInteractive(); + it.on("pointerdown", (_a, _b, _c) => { + this.drag.item = it; + this.bringToFront(this.drag.item); + this.drag.offset.x = this.scene.hand.pos.x - it.x; + this.drag.offset.y = this.scene.hand.pos.y - it.y; + }) + } + } + + update(){ + this.btnBack.update(); + + if (this.drag.item !== null) { + this.drag.item.x = this.scene.hand.pos.x - this.drag.offset.x; + this.drag.item.y = this.scene.hand.pos.y - this.drag.offset.y; + if (this.scene.hand.pressed === false) { + this.drag.item = null; + } + } + } + + bringToFront(_item){ + for(let it of this.items){ + if(it === _item){ + it.depth = 10; + }else{ + it.depth = 5; + } + } + } + + destroy(){ + this.bgGraphics.destroy(); + this.btnBack.destroy(); + this.bg.destroy(); + + this.dreamcoin.destroy(); + this.dreamkey.destroy(); + /* + this.revolver.destroy(); + this.bullet.destroy(); + this.cigarettes.destroy(); + this.keycard.destroy(); + this.shipcard.destroy(); + this.plant.destroy(); + this.photo.destroy(); + */ + } +} diff --git a/src/ui/panelJoeComputer.js b/src/ui/panelJoeComputer.js new file mode 100755 index 0000000..c1d1b01 --- /dev/null +++ b/src/ui/panelJoeComputer.js @@ -0,0 +1,207 @@ +import Button from "./button.js"; +import { SliderHorizontal } from "./slider.js"; +import MovingGrid from "./movingGrid.js"; +import ComputerWindowAero from "./computer/windowAero.js"; +import ProgramSystem from "./computer/programs/programSystemAero.js"; +import ProgramCalendar from "./computer/programs/programCalendarAero.js"; +import ProgramMessenger from "./computer/programs/programMessengerAero.js"; +import ProgramRegulations from "./computer/programs/programRegulationsAero.js"; + +export default class PanelJoeComputer { + constructor(_scene) { + this.scene = _scene; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x000000, 0.9); + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + + this.screenTop = this.scene.game.config.height * -0.5; + this.screenBottom = this.scene.game.config.height * 0.5; + this.screenLeft = this.scene.game.config.width * -0.5; + this.screenRight = this.scene.game.config.width * 0.5; + + //this.bgGrid = new MovingGrid(this.scene, this.scene.game.config.width, this.scene.game.config.height, 32); + //this.bgGrid.addPointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + + let deskBgFlag = flagManager.getFlagById("desktopBackgroundJoe").value; + this.background = this.scene.add.sprite(0, 0, "atlasDesktopBackgrounds", "sprDesktopBackground0" + deskBgFlag); + this.background.alpha = 1;//0.75; + + this.scene.hand.showCursor = false; + this.cursor = this.scene.add.sprite(0, 0, "atlasUi", "sprDesktopCursorNormal"); + this.cursor.depth = 10001; + this.cursor.setOrigin(0, 0); + + this.windowOpen = null; + this.windowToOpen = null; + this.windowToClose = null; + this.windowSystem = new ComputerWindowAero(this.scene, this, "System", -128, -128, 256, 200); + this.windowMessenger = new ComputerWindowAero(this.scene, this, "Messenger", -128, -128, 256, 256); + this.windowTech = new ComputerWindowAero(this.scene, this, "Technical Regulations", -128, -128, 256, 256); + this.windowCalendar = new ComputerWindowAero(this.scene, this, "Race Calendar", -128, -128, 256, 256); + //programs + this.programSystem = new ProgramSystem(this.scene, this, this.windowSystem); + this.programSystem.changeBackgroundPreview(String(deskBgFlag));//todo: save this number + this.windowSystem.program = this.programSystem; + this.programCalendar = new ProgramCalendar(this.scene, this, this.windowCalendar); + this.windowCalendar.program = this.programCalendar; + this.programRegulations = new ProgramRegulations(this.scene, this, this.windowTech); + this.windowTech.program = this.programRegulations; + this.programMessenger = new ProgramMessenger(this.scene, this, this.windowMessenger); + this.windowMessenger.program = this.programMessenger; + + + //left side + this.btnBack = new Button(this.scene, { x: this.screenLeft + 32, y: this.screenTop + 32 }, "atlasUi", "sprDesktopIconLogout", "", false, () => { + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + this.btnBack.colors = { + out: 0xff004d, + over: 0x29adff, + on: 0x00e436, + off: 0xad2900 + } + this.btnBack.colorInState(this.btnBack.states.out); + + this.txtTime = this.scene.add.bitmapText(this.screenLeft + 16, this.screenBottom - 16, "uiFont", "00:00 DD/MM/2k97", 14, 0).setOrigin(0, 0.5).setLetterSpacing(0); + this.txtTime.depth = 9999; + this.txtTime.setTintFill(0xfff1e8); + + //desktop icons + this.btnSystem = new Button(this.scene, { x: this.screenRight - 32, y: this.screenTop + 32 }, "atlasUi", "sprDesktopIconSystem", "", false, () => { + //if(this.windowOpen === null){ + // this.windowOpen = this.windowSystem; + // this.windowOpen.open(); + //}else + if (this.windowOpen !== this.windowSystem && this.windowToClose === null) { + if (this.windowOpen !== null) { + this.windowOpen.close(); + } + this.windowOpen = this.windowSystem; + if (this.windowSystem.isOpen === false) { + this.windowOpen.open(); + } + } + }); + this.btnSystem.setHighlighting(false); + + this.btnMessenger = new Button(this.scene, { x: this.screenRight - 32, y: this.screenTop + 80 }, "atlasUi", "sprDesktopIconMessenger", "", false, () => { + if (this.windowOpen !== this.windowMessenger && this.windowToClose === null) { + if (this.windowOpen !== null) { + this.windowOpen.close(); + } + this.windowOpen = this.windowMessenger; + if (this.windowMessenger.isOpen === false) { + this.windowOpen.open(); + } + } + }); + this.btnMessenger.setHighlighting(false); + + this.btnTech = new Button(this.scene, { x: this.screenRight - 80, y: this.screenTop + 32 }, "atlasUi", "sprDesktopIconTechCol", "", false, () => { + if (this.windowOpen !== this.windowTech && this.windowToClose === null) { + if (this.windowOpen !== null) { + this.windowOpen.close(); + } + this.windowOpen = this.windowTech; + if (this.windowTech.isOpen === false) { + this.windowOpen.open(); + } + } + }); + this.btnTech.setHighlighting(false); + + this.btnCalendar = new Button(this.scene, { x: this.screenRight - 80, y: this.screenTop + 80 }, "atlasUi", "sprDesktopIconCalendar", "", false, () => { + if (this.windowOpen !== this.windowCalendar && this.windowToClose === null) { + if (this.windowOpen !== null) { + this.windowOpen.close(); + } + this.windowOpen = this.windowCalendar; + if (this.windowCalendar.isOpen === false) { + this.windowOpen.open(); + } + } + }); + this.btnCalendar.setHighlighting(false); + + /*this.btnLcarsSystem = new Button(this.scene, { x: this.screenRight - 80, y: this.screenBottom - 32 }, "sprDesktopIconSystemLcars", "", false, () => { + + }); + this.btnLcarsSystem.setHighlighting(false); + this.btnLcarsBrowser = new Button(this.scene, { x: this.screenRight - 32, y: this.screenBottom - 32 }, "sprDesktopIconBrowserLcars", "", false, () => { + + }); + this.btnLcarsBrowser.setHighlighting(false);*/ + + this.lockButtons = true; + this.date = new Date(); + + this.scene.soundManager.playSound(this.scene.soundManager.computerStartSound); + } + + update() { + //this.bgGrid.updatePointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + //this.bgGrid.update(); + + this.updateCursor(); + + if (this.lockButtons === false) { + this.btnBack.update(); + this.btnSystem.update(); + this.btnMessenger.update(); + this.btnTech.update(); + this.btnCalendar.update(); + //this.btnLcarsSystem.update(); + //this.btnLcarsBrowser.update(); + } else { + this.lockButtons = false; + } + + if (this.windowOpen !== null) { + this.windowOpen.update(); + } + if (this.windowToClose !== null) { + this.windowToClose.update(); + } + + let d = this.date; + this.txtTime.setText(zeroPad(d.getHours(), 2) + ":" + zeroPad(d.getMinutes(), 2) + " " + zeroPad(d.getDate(), 2) + "." + zeroPad(d.getMonth(), 2) + ".2k97"); + } + + updateCursor() { + this.cursor.x = this.scene.hand.pos.x; + this.cursor.y = this.scene.hand.pos.y; + + if (this.btnSystem.hovering === true || this.btnMessenger.hovering === true || this.btnTech.hovering === true || this.btnBack.hovering === true || this.btnCalendar.hovering === true /*|| this.btnLcarsBrowser.hovering === true || this.btnLcarsSystem.hovering === true*/) { + this.cursor.setTexture("atlasUi", "sprDesktopCursorTouch"); + } else { + this.cursor.setTexture("atlasUi", "sprDesktopCursorNormal"); + } + } + + destroy() { + this.bgGraphics.destroy(); + //this.bgGrid.destroy(); + this.background.destroy(); + this.cursor.destroy(); + + this.windowOpen = null; + this.windowMessenger.destroy(); + this.windowSystem.destroy(); + this.windowTech.destroy(); + this.windowCalendar.destroy(); + + this.btnBack.destroy(); + this.btnSystem.destroy(); + this.btnMessenger.destroy(); + this.btnTech.destroy(); + this.btnCalendar.destroy(); + + this.txtTime.destroy(); + //this.btnLcarsSystem.destroy(); + //this.btnLcarsBrowser.destroy(); + this.scene.hand.showCursor = true; + } +} diff --git a/src/ui/panelLevelname.js b/src/ui/panelLevelname.js new file mode 100755 index 0000000..8a2c9b3 --- /dev/null +++ b/src/ui/panelLevelname.js @@ -0,0 +1,57 @@ +export default class PanelLevelname{ + constructor(_scene, _txt) { + this.scene = _scene; + + //stop use click clicking immediatly again and eg hit the back btn + this.scene.hand.justPressed = false; + this.scene.hand.pressed = false; + this.scene.hand.justReleased = false; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x000000, 0.75); + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + + this.bgGraphics.beginPath(); + this.bgGraphics.lineStyle(1, 0xffffff); + this.bgGraphics.moveTo(-128, -16); + this.bgGraphics.lineTo(128, -16); + this.bgGraphics.strokePath(); + + this.header = this.scene.add.bitmapText(0, -32, "segoeUI_16", _txt, 16, 0).setOrigin(0.5); + this.header.depth = 10000; + + this.tweenBg = this.scene.add.tween({ + targets: this.bgGraphics, + alpha: 0, + delay: 1500, + duration: 2500, + ease: Phaser.Math.Easing.Cubic.Out, + onComplete: () => { + this.destroy(); + this.scene.player.panel = null; + } + }) + + this.tweenHeader = this.scene.add.tween({ + targets: this.header, + alpha: 0, + delay: 1500, + duration: 2500, + ease: Phaser.Math.Easing.Quintic.Out, + onComplete: () => { + + } + }) + } + + update(){ + + } + + destroy(){ + //this.tweenBg.destroy(); + //this.tweenHeader.destroy(); + this.bgGraphics.destroy(); + this.header.destroy(); + } +} \ No newline at end of file diff --git a/src/ui/panelLoungeRoundtable00.js b/src/ui/panelLoungeRoundtable00.js new file mode 100755 index 0000000..c3874dd --- /dev/null +++ b/src/ui/panelLoungeRoundtable00.js @@ -0,0 +1,72 @@ +import Button from "./button.js"; +import MovingGrid from "./movingGrid.js"; + +export default class PanelLoungeRoundtable00{ + constructor(_scene, _level, _treePosition = 0) { + this.scene = _scene; + this.level = _level; + this.treePosition = _treePosition; + + this.scene.hand.setMouseLock(false); + this.scene.hand.showCursor = true; + this.scene.hand.cursor.alpha = 1; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x000000, 0.25); + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + this.bgGraphics.depth = 9990; + + this.bgGrid = new MovingGrid(this.scene, this.scene.game.config.width, this.scene.game.config.height, 32); + this.bgGrid.addPointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + + this.narrator = this.scene.add.sprite(-160, -68-34, "charSheetExpressions", "scooterExpressionOuch00"); + this.narrator.depth = 9999; + this.faces = [ + "scooterExpressionOuch00", + "hogExpressionHaha00", + "rahyExpressionAngry01", + "scooterExpressionOuch00", + "rahyExpressionOuch01", + "hogExpressionHaha00", + "scooterExpressionHaha01", + "rahyExpressionHaha02", + "scooterExpressionHaHa00", + "rahyExpressionAngry00",//9 + "hogExpressionHappy01", + "scooterExpressionAngry00", + "hogExpressionHaha00", + "rahyExpressionAngry01", + "rahyExpressionAngry00" + ] + + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.level.loungeTables[1]); + this.scene.player.conversationManager.setConversation(this.level.loungeTables[1].data.conversation.fileName, this.level.loungeTables[1].data.conversation.treePosition); + + + this.lockButtons = true; + } + + update(){ + this.bgGrid.updatePointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + this.bgGrid.update(); + + if(this.lockButtons === false){ + this.narrator.setTexture("charSheetExpressions", this.faces[this.scene.player.conversationManager.conversation.treePosition]); + if(this.level.loungeTables[1].data.conversation.treePosition === 14){ + this.scene.paused = false; + this.scene.player.panel = null; + this.destroy(); + } + }else{ + this.lockButtons = false; + } + } + + destroy(){ + this.bgGraphics.destroy(); + this.bgGrid.destroy(); + + this.narrator.destroy(); + } +} \ No newline at end of file diff --git a/src/ui/panelPainting.js b/src/ui/panelPainting.js new file mode 100755 index 0000000..8f20c3e --- /dev/null +++ b/src/ui/panelPainting.js @@ -0,0 +1,48 @@ +import Button from "./button.js"; +import { SliderHorizontal } from "./slider.js"; +import MovingGrid from "./movingGrid.js"; + +export default class PanelPainting{ + constructor(_scene) { + this.scene = _scene; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x000000, 0.9); + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + + this.bgGrid = new MovingGrid(this.scene, this.scene.game.config.width, this.scene.game.config.height, 32); + this.bgGrid.addPointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + + //left side + this.btnBack = new Button(this.scene, { x: -160, y: -68 }, "atlasUi", "sprBtn00", "BACK", false, () => { + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + + this.description = this.scene.add.bitmapText(0, 34 , "uiFont", "The Arashi Corporation is a thin shadow of its former self. Once a leader in microchip technology and tunneling and mining, it was dismantled and bought up by more powerful corporations. Nowadays it only lives as a small racing team, with pride but without much financial resources.", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.description.depth = 9999; + this.description.maxWidth = 240; + + this.lockButtons = true; + } + + update(){ + this.bgGrid.updatePointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + this.bgGrid.update(); + + if(this.lockButtons === false){ + this.btnBack.update(); + }else{ + this.lockButtons = false; + } + } + + destroy(){ + this.bgGraphics.destroy(); + this.bgGrid.destroy(); + + this.btnBack.destroy(); + this.description.destroy(); + } +} \ No newline at end of file diff --git a/src/ui/panelPlayerComputer.js b/src/ui/panelPlayerComputer.js new file mode 100755 index 0000000..0cdb230 --- /dev/null +++ b/src/ui/panelPlayerComputer.js @@ -0,0 +1,250 @@ +import Button from "./button.js"; +import { SliderHorizontal } from "./slider.js"; +import MovingGrid from "./movingGrid.js"; +import ComputerWindowAero from "./computer/windowAero.js"; +import ProgramSystem from "./computer/programs/programSystemAero.js"; +import ProgramCalendar from "./computer/programs/programCalendarAero.js"; +import ProgramMessenger from "./computer/programs/programMessengerAero.js"; +import ProgramRegulations from "./computer/programs/programRegulationsAero.js"; + +export default class PanelPlayerComputer { + constructor(_scene) { + this.scene = _scene; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x000000, 0.9); + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + + this.screenTop = this.scene.game.config.height * -0.5; + this.screenBottom = this.scene.game.config.height * 0.5; + this.screenLeft = this.scene.game.config.width * -0.5; + this.screenRight = this.scene.game.config.width * 0.5; + + //this.bgGrid = new MovingGrid(this.scene, this.scene.game.config.width, this.scene.game.config.height, 32); + //this.bgGrid.addPointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + + let deskBgFlag = flagManager.getFlagById("desktopBackground").value; + this.background = this.scene.add.sprite(0, 0, "atlasDesktopBackgrounds", "sprDesktopBackground0" + deskBgFlag); + this.background.alpha = 1; //0.75; + + this.scene.hand.showCursor = false; + this.cursor = this.scene.add.sprite(0, 0, "atlasUi", "sprDesktopCursorNormal"); + this.cursor.depth = 10001; + this.cursor.setOrigin(0, 0); + + this.windowOpen = null; + this.windowToOpen = null; + this.windowToClose = null; + this.windowSystem = new ComputerWindowAero(this.scene, this, "System", -128, -128, 256, 200); + this.windowMessenger = new ComputerWindowAero(this.scene, this, "Messenger", -128, -128, 256, 256); + this.windowTech = new ComputerWindowAero(this.scene, this, "Technical Regulations", -128, -128, 256, 256); + this.windowCalendar = new ComputerWindowAero(this.scene, this, "Race Calendar", -128, -128, 256, 256); + //programs + this.programSystem = new ProgramSystem(this.scene, this, this.windowSystem); + this.programSystem.changeBackgroundPreview(String(deskBgFlag)); //todo: save this number + this.windowSystem.program = this.programSystem; + this.programCalendar = new ProgramCalendar(this.scene, this, this.windowCalendar); + this.windowCalendar.program = this.programCalendar; + this.programRegulations = new ProgramRegulations(this.scene, this, this.windowTech); + this.windowTech.program = this.programRegulations; + this.programMessenger = new ProgramMessenger(this.scene, this, this.windowMessenger); + this.windowMessenger.program = this.programMessenger; + + //left side + this.btnBack = new Button(this.scene, { x: this.screenLeft + 32, y: this.screenTop + 32 }, "atlasUi", "sprDesktopIconLogout", "", false, () => { + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + this.btnBack.colors = { + out: 0xff004d, + over: 0x29adff, + on: 0x00e436, + off: 0xad2900, + }; + this.btnBack.colorInState(this.btnBack.states.out); + + this.txtTime = this.scene.add + .bitmapText(this.screenLeft + 16, this.screenBottom - 16, "uiFont", "00:00 DD/MM/2k97", 14, 0) + .setOrigin(0, 0.5) + .setLetterSpacing(0); + this.txtTime.depth = 9999; + this.txtTime.setTintFill(0xfff1e8); + + //desktop icons + this.btnSystem = new Button(this.scene, { x: this.screenRight - 32, y: this.screenTop + 32 }, "atlasUi", "sprDesktopIconSystem", "", false, () => { + //if(this.windowOpen === null){ + // this.windowOpen = this.windowSystem; + // this.windowOpen.open(); + //}else + if (this.windowOpen !== this.windowSystem && this.windowToClose === null) { + if (this.windowOpen !== null) { + this.windowOpen.close(); + } + this.windowOpen = this.windowSystem; + if (this.windowSystem.isOpen === false) { + this.windowOpen.open(); + } + } + }); + this.btnSystem.setHighlighting(false); + + this.btnMessenger = new Button(this.scene, { x: this.screenRight - 32, y: this.screenTop + 80 }, "atlasUi", "sprDesktopIconMessenger", "", false, () => { + if (this.windowOpen !== this.windowMessenger && this.windowToClose === null) { + if (this.windowOpen !== null) { + this.windowOpen.close(); + } + this.windowOpen = this.windowMessenger; + if (this.windowMessenger.isOpen === false) { + this.windowOpen.open(); + } + } + }); + this.btnMessenger.setHighlighting(false); + + this.btnTech = new Button(this.scene, { x: this.screenRight - 80, y: this.screenTop + 32 }, "atlasUi", "sprDesktopIconTechCol", "", false, () => { + if (this.windowOpen !== this.windowTech && this.windowToClose === null) { + if (this.windowOpen !== null) { + this.windowOpen.close(); + } + this.windowOpen = this.windowTech; + if (this.windowTech.isOpen === false) { + this.windowOpen.open(); + } + } + }); + this.btnTech.setHighlighting(false); + + this.btnCalendar = new Button(this.scene, { x: this.screenRight - 80, y: this.screenTop + 80 }, "atlasUi", "sprDesktopIconCalendar", "", false, () => { + if (this.windowOpen !== this.windowCalendar && this.windowToClose === null) { + if (this.windowOpen !== null) { + this.windowOpen.close(); + } + this.windowOpen = this.windowCalendar; + if (this.windowCalendar.isOpen === false) { + this.windowOpen.open(); + } + } + }); + this.btnCalendar.setHighlighting(false); + + this.sticky = null; + if (flagManager.getFlagById("apartement00sticky").value === "1") { + this.sticky = this.scene.add.sprite(0, 0, "atlasUi", "sprStickyNote"); + this.sticky.setInteractive.interactable = true; + this.sticky.depth = 19000; + this.txtSticky = this.scene.add + .bitmapText(0, 0, "uiFont", "the pc is not setup\nyet\ncome see me\nin the hangar\n\nbring nutricubes", 14, 0) + .setOrigin(0.5) + .setLetterSpacing(0); + this.txtSticky.depth = 19001; + this.txtSticky.setTintFill(0x1d2b53); + + flagManager.setFlag("quartersLevel", "00"); + flagManager.setFlag("hangarLevel", "00"); + } + + /*this.btnLcarsSystem = new Button(this.scene, { x: this.screenRight - 80, y: this.screenBottom - 32 }, "sprDesktopIconSystemLcars", "", false, () => { + + }); + this.btnLcarsSystem.setHighlighting(false); + this.btnLcarsBrowser = new Button(this.scene, { x: this.screenRight - 32, y: this.screenBottom - 32 }, "sprDesktopIconBrowserLcars", "", false, () => { + + }); + this.btnLcarsBrowser.setHighlighting(false);*/ + + this.lockButtons = true; + this.date = new Date(); + + this.scene.soundManager.playSound(this.scene.soundManager.computerStartSound); + } + + update() { + //this.bgGrid.updatePointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + //this.bgGrid.update(); + + this.updateCursor(); + + if (this.lockButtons === false) { + if (this.sticky !== null) { + if (this.sticky.getBounds().contains(this.scene.hand.pos.x, this.scene.hand.pos.y)) { + this.sticky.tint = 0xbbbbbb; + if (this.scene.hand.justReleased === true) { + flagManager.setFlag("apartement00sticky", "0"); + this.sticky.destroy(); + this.txtSticky.destroy(); + } + } else { + this.sticky.tint = 0xffffff; + } + } + + this.btnBack.update(); + this.btnSystem.update(); + this.btnMessenger.update(); + this.btnTech.update(); + this.btnCalendar.update(); + //this.btnLcarsSystem.update(); + //this.btnLcarsBrowser.update(); + } else { + this.lockButtons = false; + } + + if (this.windowOpen !== null) { + this.windowOpen.update(); + } + if (this.windowToClose !== null) { + this.windowToClose.update(); + } + + let d = this.date; + this.txtTime.setText(zeroPad(d.getHours(), 2) + ":" + zeroPad(d.getMinutes(), 2) + " " + zeroPad(d.getDate(), 2) + "." + zeroPad(d.getMonth(), 2) + ".2k97"); + } + + updateCursor() { + this.cursor.x = this.scene.hand.pos.x; + this.cursor.y = this.scene.hand.pos.y; + + if ( + this.btnSystem.hovering === true || + this.btnMessenger.hovering === true || + this.btnTech.hovering === true || + this.btnBack.hovering === true || + this.btnCalendar.hovering === true /*|| this.btnLcarsBrowser.hovering === true || this.btnLcarsSystem.hovering === true*/ + ) { + this.cursor.setTexture("atlasUi", "sprDesktopCursorTouch"); + } else { + this.cursor.setTexture("atlasUi", "sprDesktopCursorNormal"); + } + } + + destroy() { + this.bgGraphics.destroy(); + //this.bgGrid.destroy(); + this.background.destroy(); + this.cursor.destroy(); + + this.windowOpen = null; + this.windowMessenger.destroy(); + this.windowSystem.destroy(); + this.windowTech.destroy(); + this.windowCalendar.destroy(); + + this.btnBack.destroy(); + this.btnSystem.destroy(); + this.btnMessenger.destroy(); + this.btnTech.destroy(); + this.btnCalendar.destroy(); + + this.txtTime.destroy(); + + if (this.sticky !== null) { + this.sticky.destroy(); + this.txtSticky.destroy(); + } + + //this.btnLcarsSystem.destroy(); + //this.btnLcarsBrowser.destroy(); + this.scene.hand.showCursor = true; + } +} diff --git a/src/ui/panelRaceTutorial.js b/src/ui/panelRaceTutorial.js new file mode 100755 index 0000000..7aec109 --- /dev/null +++ b/src/ui/panelRaceTutorial.js @@ -0,0 +1,174 @@ +import Button from "./button.js"; +import { SliderHorizontal } from "./slider.js"; +import MovingGrid from "./movingGrid.js"; + +export default class PanelRaceTutorial { + constructor(_scene, _level, _previousState = 0, _tutorial = 0) { + this.scene = _scene; + this.level = _level; + this.previousState = _previousState; + this.tutorial = _tutorial; + + this.scene.hand.setMouseLock(false); + this.scene.hand.showCursor = true; + this.scene.hand.cursor.alpha = 1; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x000000, 0.25); + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + this.bgGraphics.depth = 9990; + + this.bgGrid = new MovingGrid(this.scene, this.scene.game.config.width, this.scene.game.config.height, 32); + this.bgGrid.addPointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + + //left side + /* + this.btnContinue = new Button(this.scene, { x: -160, y: -68 }, "atlasUi", "sprBtn00", "CONTINUE", false, () => { + this.scene.paused = false; + //racing + this.level.state = this.previousState; + this.level.ui.show(); + this.scene.player.panel = null; + this.destroy(); + }); + */ + + //this.narrator = this.scene.add.sprite(-160, -68 - 34, "atlasUi", "portraitLara00sw"); + this.narrator = this.scene.add.sprite(-160, -68 - 34, "charSheetExpressions", "rokiExpressionAngry00"); + this.narrator.depth = 9999; + + /* + let txts = [ + "Hate to stop you right away, but I am here to help you learn the ropes!", + "" + ] + + this.txt = this.scene.add.bitmapText(0, 34, "uiFont", txts[this.tutorial], 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.txt.depth = 9999; + this.txt.maxWidth = 240;*/ + + this.scene.player.setMode(PLAYERMODE.DIALOGUE); + this.scene.player.conversationManager.setNPC(this.level.aiShips[0].ship); + this.scene.player.conversationManager.setConversation(this.level.aiShips[0].ship.data.conversation.fileName, this.level.aiShips[0].ship.data.conversation.treePosition); + + + this.lockButtons = true; + } + + update() { + this.bgGrid.updatePointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + this.bgGrid.update(); + + if (this.lockButtons === false) { + //this.btnContinue.update(); + + //if(INPUTS.btnA.justReleased){ + //this.btnContinue.func(); + //} + + //listen to end of conversation and quit + //if(this.scene.player.conversation === null){ + // + + switch (this.scene.player.conversationManager.conversation.treePosition) { + case 0: + this.narrator.setTexture("charSheetExpressions", "rokiExpressionHappy02"); + break; + case 3: + this.narrator.setTexture("charSheetExpressions", "rokiExpressionNormal02"); + break; + case 4: + this.narrator.setTexture("charSheetExpressions", "rokiExpressionNormal01"); + break; + case 7: + this.narrator.setTexture("charSheetExpressions", "rokiExpressionHaha00"); + break; + case 8: + this.narrator.setTexture("charSheetExpressions", "joeExpressionNormal00"); + break; + case 9: + this.narrator.setTexture("charSheetExpressions", "rokiExpressionHaha04"); + break; + case 10: + this.narrator.setTexture("charSheetExpressions", "joeExpressionNormal00"); + break; + case 11: + this.narrator.setTexture("charSheetExpressions", "rokiExpressionThinking01"); + break; + case 13: + this.narrator.setTexture("charSheetExpressions", "rokiExpressionHappy02"); + break; + case 15: + this.narrator.setTexture("charSheetExpressions", "rokiExpressionOuch02"); + break; + case 16: + this.narrator.setTexture("charSheetExpressions", "rokiExpressionHaha00"); + break; + case 17: + this.narrator.setTexture("charSheetExpressions", "rokiExpressionHappy00"); + break; + case 21: + this.narrator.setTexture("charSheetExpressions", "rokiExpressionHappy01"); + break; + case 39: + this.narrator.setTexture("charSheetExpressions", "rokiExpressionHappy02"); + break; + case 40: + this.narrator.setTexture("charSheetExpressions", "rokiExpressionAngry03"); + break; + case 42: + this.narrator.setTexture("charSheetExpressions", "rokiExpressionHaha04"); + break; + case 43: + this.narrator.setTexture("charSheetExpressions", "rokiExpressionNormal01"); + break; + default: + this.narrator.setTexture("charSheetExpressions", "rokiExpressionAngry02"); + break; + } + + if (this.scene.player.mode !== PLAYERMODE.DIALOGUE) { + if (this.level.aiShips[0].ship.data.conversation.treePosition !== 9999) { + console.log("cycle from end of diag") + this.level.cycleTutorial(); + + this.scene.paused = false; + //racing + this.level.state = this.previousState; + this.level.ui.show(); + this.scene.player.panel = null; + this.destroy(); + } else { + flagManager.setFlag("demoProgress", "1"); + + this.scene.soundManager.stopSound(this.scene.soundManager.engineSound); + this.scene.soundManager.stopSound(this.scene.soundManager.engineRotorSound); + this.scene.soundManager.stopSound(this.scene.soundManager.scrapeSound); + this.scene.soundManager.stopSound(this.scene.soundManager.heatWarningSound); + this.scene.soundManager.stopSound(this.level.musicTrack); + + this.scene.paused = false; + + this.scene.player.panel = null; + this.level.destroy(); + + this.destroy(); + //this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + this.scene.loadLevel("hangar00", { startFromElevator: false, showIntro: false });//dream00 + } + } + } else { + this.lockButtons = false; + } + } + + destroy() { + this.bgGraphics.destroy(); + this.bgGrid.destroy(); + + //this.txt.destroy(); + this.narrator.destroy(); + + //this.btnContinue.destroy(); + } +} diff --git a/src/ui/panelStopTrain.js b/src/ui/panelStopTrain.js new file mode 100755 index 0000000..9fc8ed4 --- /dev/null +++ b/src/ui/panelStopTrain.js @@ -0,0 +1,134 @@ +import Button from "./button.js"; +import { SliderHorizontal } from "./slider.js"; +import MovingGrid from "./movingGrid.js"; + +export default class PanelStopTrain { + constructor(_scene, _level) { + this.scene = _scene; + this.level = _level; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x000000, 0.9); + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + + this.bgGrid = new MovingGrid(this.scene, this.scene.game.config.width, this.scene.game.config.height, 32); + this.bgGrid.addPointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + + this.btnBack = new Button(this.scene, { x: -160, y: -68 }, "atlasUi", "sprBtn00", "BACK", false, () => { + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.level.metroComputer.interactable = true; + + this.destroy(); + }); + + this.ridges = []; + this.ridges.push(this.scene.add.sprite(-64, 0, "atlasAll", "texWallGrind07")) + this.ridges.push(this.scene.add.sprite(64, 0, "atlasAll", "texWallGrind07")) + for (let r of this.ridges) { + r.setScale(4 / 32, 3); + r.setOrigin(0.5, 1); + } + + this.lever = this.scene.add.sprite(0, -96, "atlasUi", "sprBtn14"); + this.lever.interactable = true; + this.leverFollow = false; + this.leverLock = false; + this.keyStarted = false; + + this.lockSymbol = this.scene.add.sprite(128, -16, "atlasUi", "sprBtnLock00"); + + this.keyhole = this.scene.add.sprite(128, 64, "atlasUi", flagManager.getFlagById("dream00hasKey").value === "true" ? "sprBtn15key" : "sprBtn15"); + this.keyhole.interactable = true; + + flagManager.setFlag("dream00searchKey", "true"); + + this.lockButtons = true; + } + + update() { + this.bgGrid.updatePointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + this.bgGrid.update(); + + if (this.lockButtons <= false) { + this.btnBack.update(); + + if (this.lever.getBounds().contains(this.scene.hand.pos.x, this.scene.hand.pos.y)) { + this.lever.tint = 0xbbbbbb; + if (this.scene.hand.pressed === true && this.keyStarted === true) { + this.leverFollow = true; + } + if (this.scene.hand.justPressed === true && this.keyStarted === false) { + this.scene.soundManager.playSound(this.scene.soundManager.menuErrorSound); + } + } else { + this.lever.tint = 0xffffff; + } + if (this.keyhole.getBounds().contains(this.scene.hand.pos.x, this.scene.hand.pos.y)) { + this.keyhole.tint = 0xbbbbbb; + if (this.scene.hand.pressed === true && flagManager.getFlagById("dream00hasKey").value === "true") { + this.keyhole.rotation = Math.PI * 0.5; + this.keyStarted = true; + this.keyhole.interactable = false; + this.lockSymbol.setTexture("atlasUi", "sprBtnLock01") + } + if (this.scene.hand.justPressed === true && flagManager.getFlagById("dream00hasKey").value === "false") { + this.scene.soundManager.playSound(this.scene.soundManager.menuErrorSound); + } + } else { + this.keyhole.tint = 0xffffff; + } + if (this.scene.hand.pressed === false) { + this.leverFollow = false; + if (this.lever.y > 64) { + this.leverLock = true; + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.level.metroComputer.interactable = false; + + this.destroy(); + this.level.stopTrainTop(); + } + } + + if (this.leverFollow === true) { + this.lever.y = this.scene.hand.pos.y; + } else { + let leverDelta = 0; + if (this.leverLock === false) { + leverDelta = 96 - this.lever.y; + this.lever.y -= Math.max(1, leverDelta * 0.1); + } else { + leverDelta = -96 + this.lever.y; + this.lever.y -= Math.min(-1, leverDelta * 1); + } + } + this.lever.y = Math.max(-96, Math.min(96, this.lever.y)); + + let ridgeScale = (this.lever.y * -1) / 32; + if (ridgeScale > 0) { + ridgeScale = Math.max(0.25, ridgeScale); + } else { + ridgeScale = Math.min(-0.25, ridgeScale); + } + for (let r of this.ridges) { + r.setScale(4 / 32, ridgeScale); + } + } else { + this.lockButtons = false; + } + } + + destroy() { + this.bgGraphics.destroy(); + this.bgGrid.destroy(); + this.btnBack.destroy(); + this.lever.destroy(); + this.keyhole.destroy(); + this.lockSymbol.destroy(); + for (let r of this.ridges) { + r.destroy(); + } + } +} diff --git a/src/ui/panelTunnelMainMenu.js b/src/ui/panelTunnelMainMenu.js new file mode 100755 index 0000000..fe7797f --- /dev/null +++ b/src/ui/panelTunnelMainMenu.js @@ -0,0 +1,369 @@ +import Button from "./button.js"; +import { SliderHorizontal } from "./slider.js"; +import MovingGrid from "./movingGrid.js"; +import PanelTunnelSelector from "./panelTunnelSelector.js"; +import PanelTunnelOptions from "./panelTunnelOptions.js"; + +export default class PanelTunnelMainMenu { + constructor(_scene, _level, _returnPos) { + this.scene = _scene; + this.level = _level; + this.returnPos = _returnPos; + + //this.bgGraphics = this.scene.add.graphics(); + //this.bgGraphics.fillStyle(0x000000, 0.1); + //this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + + //this.bgGrid = new MovingGrid(this.scene, this.scene.game.config.width, this.scene.game.config.height, 32); + //this.bgGrid.addPointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + + /* + //draw faint scanlines + this.scanlinesAnim = 0; + let th = 6; + this.scanlines = this.scene.add.graphics(0, 0); + this.scanlines.lineStyle(3, 0xffffff, 0.025);// green: 0x00e436 orig: 3, 0xffffff, 0.25 + this.scanlines.beginPath(); + for (let y = 0; y < this.scene.game.config.height + 6; y++) { + if ((Math.floor(this.scene.game.config.height + y)) % th === Math.floor(this.scanlinesAnim)) { + this.scanlines.moveTo(this.scene.game.config.width * -0.5, -6 + y + (this.scene.game.config.height * -0.5)); + this.scanlines.lineTo(this.scene.game.config.width * 0.5, -6 + y + (this.scene.game.config.height * -0.5)); + } + } + this.scanlines.strokePath(); + this.scanlines.depth = 10000; + this.scanlines.setVisible(false); + this.scanMask = this.scanlines.createGeometryMask(); + */ + + this.logos = []; + this.logos.push(this.scene.add.sprite(0, 0, "atlasUi", "mainMenuLogoFZ")); + this.logos.push(this.scene.add.sprite(0, 0, "atlasUi", "mainMenuLogoRR")); + //this.logos.push(this.scene.add.sprite(0, 0, "atlasUi", "logoRRsmall")); + for (let [i, l] of this.logos.entries()) { + l.depth = 9998; + //if(i > 0){l.alpha = 0}else{ + l.alpha = 0; + //l.angle = Math.PI; + if (i === 1) { + } else { + l.angle = Math.PI * -0.5; + } + //} + } + this.logoAnimator = 0; + + this.colors = { + out: 0xfff1e8, //white 0xfff1e8 + over: 0x29adff, //light blue: 0x29adff //dark blue 1d2b53 //yellow 0xffec27 + on: 0x00e436, + off: 0xad2900, + }; + + let a = 0; + //new game + a = Math.PI * 1.09; + this.btnBackgroundNewGame = this.scene.add.sprite(Math.cos(a) * 100, Math.sin(a) * 100, "atlasUi", "mainMenuBtnBlur"); + this.btnBackgroundNewGame.setOrigin(0, 0.1); + this.btnBackgroundNewGame.setTint(this.colors.over); + this.btnBackgroundNewGame.rotation = a; + this.btnBackgroundNewGame.depth = 9999; + //this.btnBackgroundNewGame.setMask(this.scanMask); + this.btnNewGame = new Button(this.scene, { x: Math.cos(a + 0.2) * 190, y: Math.sin(a + 0.2) * 190 }, "atlasUi", "sprBtn00", "NEW GAME", false, () => { + /* + //old direct to hangar demo + this.scene.soundManager.stopSound(this.level.mainMusic); + this.scene.player.panel = null; + + this.setupNewGame(); + + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + this.scene.loadLevel("hangar00", { startFromElevator: true, showIntro: true });//dream00 + //INFO demo starts with a panel so dont override after the fact + //this.scene.player.setMode(PLAYERMODE.LOOK); + //this.scene.player.panel = null; + this.destroy(); + */ + this.scene.soundManager.stopSound(this.level.mainMusic); + this.scene.player.panel = null; + + this.setupNewGame(); + + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + this.scene.loadLevel("dream00", null); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + this.btnNewGame.hoverInFunc = () => { + this.btnBackgroundNewGame.setTint(this.colors.out); + this.btnBackgroundNewGame.depth = 10000; + }; + this.btnNewGame.hoverOutFunc = () => { + this.btnBackgroundNewGame.setTint(this.colors.over); + this.btnBackgroundNewGame.depth = 9999; + }; + this.btnNewGame.txt.destroy(); + this.btnNewGame.txt = this.scene.add.bitmapText(this.btnNewGame.pos.x, this.btnNewGame.pos.y, "racer", this.btnNewGame.text, 16, 0).setOrigin(0.5).setLetterSpacing(0); + this.btnNewGame.txt.depth = 10000; + this.btnNewGame.txt.rotation = a + Math.PI * 1.05; + this.btnNewGame.sprite.alpha = 0; + + //load game + a = Math.PI * 1; //0.975; + this.btnBackgroundLoadGame = this.scene.add.sprite(Math.cos(a) * 100, Math.sin(a) * 100, "atlasUi", "mainMenuBtnBlur"); + this.btnBackgroundLoadGame.setOrigin(0, 0.1); + this.btnBackgroundLoadGame.setTint(this.colors.over); + this.btnBackgroundLoadGame.rotation = a; + this.btnBackgroundLoadGame.depth = 9999; + //this.btnBackgroundLoadGame.setMask(this.scanMask); + this.btnLoadGame = new Button(this.scene, { x: Math.cos(a + 0.2) * 190, y: Math.sin(a + 0.2) * 190 }, "atlasUi", "sprBtn00", "LOAD GAME", false, () => { + this.scene.soundManager.stopSound(this.level.mainMusic); + this.scene.player.panel = null; + + this.setupNewGame(); + + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + this.scene.loadLevel("dream00", null); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + this.btnLoadGame.hoverInFunc = () => { + this.btnBackgroundLoadGame.setTint(this.colors.out); + this.btnBackgroundLoadGame.depth = 10000; + }; + this.btnLoadGame.hoverOutFunc = () => { + this.btnBackgroundLoadGame.setTint(this.colors.over); + this.btnBackgroundLoadGame.depth = 9999; + }; + this.btnLoadGame.txt.destroy(); + this.btnLoadGame.txt = this.scene.add.bitmapText(this.btnLoadGame.pos.x, this.btnLoadGame.pos.y, "racer", this.btnLoadGame.text, 16, 0).setOrigin(0.5).setLetterSpacing(0); + this.btnLoadGame.txt.depth = 10000; + this.btnLoadGame.txt.rotation = a + Math.PI * 1.05; + this.btnLoadGame.sprite.alpha = 0; + + //custom race + a = Math.PI * 0.8; + this.btnBackgroundCustomGame = this.scene.add.sprite(Math.cos(a) * 100, Math.sin(a) * 100, "atlasUi", "mainMenuBtnBlur"); + this.btnBackgroundCustomGame.setOrigin(0, 0.1); + this.btnBackgroundCustomGame.setTint(this.colors.over); + this.btnBackgroundCustomGame.rotation = a; + this.btnBackgroundCustomGame.depth = 9999; + //this.btnBackgroundCustomGame.setMask(this.scanMask); + this.btnCustomGame = new Button(this.scene, { x: Math.cos(a + 0.2) * 200, y: Math.sin(a + 0.2) * 200 }, "atlasUi", "sprBtn00", "CUSTOM RACE", false, () => { + flagManager.setFlag("playingStory", "0"); + + this.level.state = this.level.states.shipSelection; + this.level.lerper = 100; + this.level.calculateLerpStep(); + this.level.playerShip.speed = this.level.speed.switching; + this.scene.player.panel = null; + this.level.actions.push(() => { + this.scene.player.panel = new PanelTunnelSelector(this.scene, this.level); + }); + this.destroy(); + }); + this.btnCustomGame.hoverInFunc = () => { + this.btnBackgroundCustomGame.setTint(this.colors.out); + }; + this.btnCustomGame.hoverOutFunc = () => { + this.btnBackgroundCustomGame.setTint(this.colors.over); + }; + this.btnCustomGame.txt.destroy(); + this.btnCustomGame.txt = this.scene.add + .bitmapText(this.btnCustomGame.pos.x, this.btnCustomGame.pos.y, "racer", this.btnCustomGame.text, 16, 0) + .setOrigin(0.5) + .setLetterSpacing(0); + this.btnCustomGame.txt.depth = 10000; + this.btnCustomGame.txt.rotation = a + Math.PI * 1.05; + this.btnCustomGame.sprite.alpha = 0; + + //options + a = Math.PI * 1.75; + this.btnBackgroundOptions = this.scene.add.sprite(Math.cos(a) * 100, Math.sin(a) * 100, "atlasUi", "mainMenuBtnBlur"); + this.btnBackgroundOptions.setOrigin(0, 0.1); + this.btnBackgroundOptions.setTint(this.colors.over); + this.btnBackgroundOptions.rotation = a; + this.btnBackgroundOptions.depth = 9999; + //this.btnBackgroundOptions.setMask(this.scanMask); + this.btnOptions = new Button(this.scene, { x: Math.cos(a + 0.2) * 200, y: Math.sin(a + 0.2) * 200 }, "atlasUi", "sprBtn00", "OPTIONS", false, () => { + this.level.state = this.level.states.options; + this.level.lerper = 100; + this.level.calculateLerpStep(); + this.scene.player.panel = null; + this.level.actions.push(() => { + this.scene.player.panel = new PanelTunnelOptions(this.scene, this.level); + }); + this.destroy(); + }); + this.btnOptions.hoverInFunc = () => { + this.btnBackgroundOptions.setTint(this.colors.out); + }; + this.btnOptions.hoverOutFunc = () => { + this.btnBackgroundOptions.setTint(this.colors.over); + }; + this.btnOptions.txt.destroy(); + this.btnOptions.txt = this.scene.add.bitmapText(this.btnOptions.pos.x, this.btnOptions.pos.y, "racer", this.btnOptions.text, 16, 0).setOrigin(0.5).setLetterSpacing(0); + this.btnOptions.txt.depth = 10000; + this.btnOptions.txt.rotation = a + Math.PI + Math.PI * 1.05; + this.btnOptions.sprite.alpha = 0; + + //credits + a = Math.PI * 0; + this.btnBackgroundCredits = this.scene.add.sprite(Math.cos(a) * 100, Math.sin(a) * 100, "atlasUi", "mainMenuBtnBlur"); + this.btnBackgroundCredits.setOrigin(0, 0.1); + this.btnBackgroundCredits.setTint(this.colors.over); + this.btnBackgroundCredits.rotation = a; + this.btnBackgroundCredits.depth = 9999; + //this.btnBackgroundCredits.setMask(this.scanMask); + this.btnCredits = new Button(this.scene, { x: Math.cos(a + 0.2) * 200, y: Math.sin(a + 0.2) * 200 }, "atlasUi", "sprBtn00", "EDITOR", false, () => { + this.scene.soundManager.stopSound(this.level.mainMusic); + this.scene.player.panel = null; + + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + this.scene.loadLevel("modelBuilder"); + + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.destroy(); + }); + this.btnCredits.hoverInFunc = () => { + this.btnBackgroundCredits.setTint(this.colors.out); + }; + this.btnCredits.hoverOutFunc = () => { + this.btnBackgroundCredits.setTint(this.colors.over); + }; + this.btnCredits.txt.destroy(); + this.btnCredits.txt = this.scene.add.bitmapText(this.btnCredits.pos.x, this.btnCredits.pos.y, "racer", this.btnCredits.text, 16, 0).setOrigin(0.5).setLetterSpacing(0); + this.btnCredits.txt.depth = 10000; + this.btnCredits.txt.rotation = a + Math.PI + Math.PI * 1.05; + this.btnCredits.sprite.alpha = 0; + + //quit + a = Math.PI * 0.1; + this.btnBackgroundQuit = this.scene.add.sprite(Math.cos(a) * 100, Math.sin(a) * 100, "atlasUi", "mainMenuBtnBlur"); + this.btnBackgroundQuit.setOrigin(0, 0.1); + this.btnBackgroundQuit.setTint(this.colors.over); + this.btnBackgroundQuit.rotation = a; + this.btnBackgroundQuit.depth = 9999; + //this.btnBackgroundQuit.setMask(this.scanMask); + this.btnQuit = new Button(this.scene, { x: Math.cos(a + 0.2) * 200, y: Math.sin(a + 0.2) * 200 }, "atlasUi", "sprBtn00", "TRAILER", false, () => { + //window.close();//IMPORTANT this does not work - how will it work in built version? + //$(".videoHolder").show(); + //$("#trailer")[0].play(); + //let elem = document.getElementsByClassName("videoHolder"); + //console.log(elem); + //elem[0].style.display = "block"; + //for (let s of this.scene.soundManager.musicRef) { + //s.howlGroup.volume(0); + //} + }); + this.btnQuit.hoverInFunc = () => { + this.btnBackgroundQuit.setTint(this.colors.out); + }; + this.btnQuit.hoverOutFunc = () => { + this.btnBackgroundQuit.setTint(this.colors.over); + }; + this.btnQuit.txt.destroy(); + this.btnQuit.txt = this.scene.add.bitmapText(this.btnQuit.pos.x, this.btnQuit.pos.y, "racer", this.btnQuit.text, 16, 0).setOrigin(0.5).setLetterSpacing(0); + this.btnQuit.txt.depth = 10000; + this.btnQuit.txt.rotation = a + Math.PI + Math.PI * 1.09; + this.btnQuit.sprite.alpha = 0; + + this.lockButtons = true; + } + + update() { + //this.bgGrid.updatePointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + //this.bgGrid.update(); + /* + this.scanlinesAnim += 0.1 * this.scene.dt; + if(this.scanlinesAnim >= 6){ + this.scanlinesAnim -= 6; + } + this.scanlines.y = this.scanlinesAnim; + //this.scanlines.rotation += 0.01; + */ + this.logoAnimator += 0.0025 * this.scene.dt; //0.002 * this.scene.dt; + + this.logos[0].alpha = Math.sin(this.logoAnimator); + this.logos[0].alpha = Math.max(0, this.logos[0].alpha) * 10; + if (this.logos[0].alpha < 0.5 && this.logoAnimator > 1) { + let amt = Math.cos(this.logoAnimator) * 0.2; + if (amt < 0) { + amt *= -1; + } + this.logos[0].rotation -= amt; + } else { + this.logos[0].rotation = 0; + } + this.logos[1].alpha = Math.sin(this.logoAnimator + Math.PI); + this.logos[1].alpha = Math.max(0, this.logos[1].alpha) * 10; + if (this.logos[1].alpha < 0.5) { + let amt = Math.cos(this.logoAnimator + Math.PI) * 0.2; + if (amt < 0) { + amt *= -1; + } + this.logos[1].rotation -= amt; + } else { + this.logos[1].rotation = 0; + } + + if (this.lockButtons <= false) { + this.btnNewGame.update(); + this.btnLoadGame.update(); + this.btnCustomGame.update(); + this.btnOptions.update(); + this.btnCredits.update(); + this.btnQuit.update(); + //this.btnToTrack.update(); + } else { + this.lockButtons = false; + } + } + + setupNewGame() { + flagManager.setFlag("playingStory", "1"); + + flagManager.setFlag("officeLevel", "-1"); + flagManager.setFlag("quartersLevel", "-1"); + flagManager.setFlag("loungeLevel", "-1"); + flagManager.setFlag("marketLevel", "-1"); + flagManager.setFlag("hangarLevel", "-1"); + flagManager.setFlag("churchLevel", "-1"); + + //flagManager.setFlag("playingDemo", "1"); + flagManager.setFlag("apartement00sticky", "1"); + + flagManager.setFlag("wonDemoRace", "false"); + flagManager.setFlag("demoProgress", "0"); + flagManager.setFlag("demoTutorialStep", "0"); + flagManager.setFlag("desktopBackground", "0"); + flagManager.setFlag("desktopBackgroundJoe", "0"); + } + + destroy() { + //this.bgGraphics.destroy(); + //this.bgGrid.destroy(); + for (let l of this.logos) { + l.destroy(); + } + this.btnNewGame.destroy(); + this.btnLoadGame.destroy(); + this.btnCustomGame.destroy(); + this.btnOptions.destroy(); + this.btnCredits.destroy(); + this.btnQuit.destroy(); + + this.btnBackgroundNewGame.destroy(); + this.btnBackgroundLoadGame.destroy(); + this.btnBackgroundCustomGame.destroy(); + this.btnBackgroundOptions.destroy(); + this.btnBackgroundCredits.destroy(); + this.btnBackgroundQuit.destroy(); + //this.btnToTrack.destroy(); + } +} diff --git a/src/ui/panelTunnelOptions.js b/src/ui/panelTunnelOptions.js new file mode 100755 index 0000000..d0af284 --- /dev/null +++ b/src/ui/panelTunnelOptions.js @@ -0,0 +1,298 @@ +import Button from "./button.js"; +import { SliderHorizontal } from "./slider.js"; +import MovingGrid from "./movingGrid.js"; +import PanelTunnelMainMenu from "./panelTunnelMainMenu.js"; + +export default class PanelTunnelOptions { + constructor(_scene, _level, _returnPos) { + this.scene = _scene; + this.level = _level; + this.returnPos = _returnPos; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x1d2b53, 0.9); //0x000000 black - 0xa7d254 green - 0x1d2b53 blue - 0x29adff lightblue + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + + this.bgGrid = new MovingGrid(this.scene, this.scene.game.config.width, this.scene.game.config.height, 32); + this.bgGrid.addPointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + + + this.btnBack = new Button(this.scene, { x: -176, y: -112 + 34 }, "atlasUi", "sprBtn00", "CANCEL", false, () => { + this.level.state = this.level.states.main; + this.level.lerper = 100; + this.level.calculateLerpStep(); + this.level.actions.push(() => { + this.scene.player.panel = new PanelTunnelMainMenu(this.scene, this.level); + }); + this.destroy(); + }); + + this.btnApply = new Button(this.scene, { x: -176, y: -112 }, "atlasUi", "sprBtn00", "APPLY", false, () => { + this.scene.saveOptions(); + this.level.state = this.level.states.main; + this.level.lerper = 100; + this.level.calculateLerpStep(); + this.level.actions.push(() => { + this.scene.player.panel = new PanelTunnelMainMenu(this.scene, this.level); + }); + this.destroy(); + }); + + this.btnAUX = new Button(this.scene, { x: 176 + 32 - 132, y: -112 }, "atlasUi", "sprBtn00mid", "AUX", false, () => { + this.contAUX.alpha = 1; + this.contGFX.alpha = 0; + this.contCTL.alpha = 0; + this.activeContainer = this.contAUX; + }); + this.btnGFX = new Button(this.scene, { x: 176 + 32 - 66, y: -112 }, "atlasUi", "sprBtn00mid", "GFX", false, () => { + this.contAUX.alpha = 0; + this.contGFX.alpha = 1; + this.contCTL.alpha = 0; + this.activeContainer = this.contGFX; + }); + this.btnCTL = new Button(this.scene, { x: 176 + 32, y: -112 }, "atlasUi", "sprBtn00mid", "CTRL", false, () => { + this.contAUX.alpha = 0; + this.contGFX.alpha = 0; + this.contCTL.alpha = 1; + this.activeContainer = this.contCTL; + }); + + this.contAUX = this.scene.add.container(0, 0); + this.contGFX = this.scene.add.container(0, 0); + this.contGFX.alpha = 0; + this.contCTL = this.scene.add.container(0, 0); + this.contCTL.alpha = 0; + this.activeContainer = this.contAUX; + + //sound options + this.sliMaster = new SliderHorizontal(this.scene, { x: 0, y: -34 }, OPTIONS.sound.master, 128); + this.sliMaster.move(0, -34); + this.sliMaster.releaseFunc = () => { + Howler.volume(this.sliMaster.value); + this.scene.soundManager.playSpecificSound(this.scene.soundManager.raceAnnouncer, 0); + OPTIONS.sound.master = this.sliMaster.value; + } + this.btnMaster = new Button(this.scene, { x: -128, y: -34 }, "atlasUi", "sprBtn08", "master:", false, () => { + if (this.sliMaster.value > 0) { + this.sliMaster.setTo(0); + } else { + this.sliMaster.setTo(1); + } + }); + this.sliMaster.addToContainer(this.contAUX); + this.btnMaster.addToContainer(this.contAUX); + + this.sliSound = new SliderHorizontal(this.scene, { x: 0, y: 0 }, OPTIONS.sound.sfx, 128); + this.sliSound.move(0, 0); + this.sliSound.releaseFunc = () => { + for (let s of this.scene.soundManager.soundRef) { + s.howlGroup.volume(this.sliSound.value); + } + this.scene.soundManager.playSpecificSound(this.scene.soundManager.raceAnnouncer, 0); + OPTIONS.sound.sfx = this.sliSound.value; + } + this.btnSound = new Button(this.scene, { x: -128, y: 0 }, "atlasUi", "sprBtn08", "sound:", false, () => { + if (this.sliSound.value > 0) { + this.sliSound.setTo(0); + } else { + this.sliSound.setTo(1); + } + }); + this.sliSound.addToContainer(this.contAUX); + this.btnSound.addToContainer(this.contAUX); + + this.sliMusic = new SliderHorizontal(this.scene, { x: 0, y: 34 }, OPTIONS.sound.music, 128); + this.sliMusic.move(0, 34); + this.sliMusic.releaseFunc = () => { + //Howler.volume(this.sliMusic.value); + for (let s of this.scene.soundManager.musicRef) { + s.howlGroup.volume(this.sliMusic.value); + } + OPTIONS.sound.music = this.sliMusic.value; + } + this.btnMusic = new Button(this.scene, { x: -128, y: 34 }, "atlasUi", "sprBtn08", "music:", false, () => { + if (this.sliMusic.value > 0) { + this.sliMusic.setTo(0); + } else { + this.sliMusic.setTo(1); + } + }); + this.sliMusic.addToContainer(this.contAUX); + this.btnMusic.addToContainer(this.contAUX); + + //graphical options + this.sliScreenshake = new SliderHorizontal(this.scene, { x: 0, y: -34 }, OPTIONS.effects.screenshake, 128); + this.sliScreenshake.move(0, -34); + this.sliScreenshake.releaseFunc = () => { + OPTIONS.effects.screenshake = this.sliScreenshake.value; + } + this.btnScreenshake = new Button(this.scene, { x: -128, y: -34 }, "atlasUi", "sprBtn00mid", "screenshake:", false, () => { + if (this.sliScreenshake.value > 0) { + this.sliScreenshake.setTo(0); + } else { + this.sliScreenshake.setTo(1); + } + }); + this.sliScreenshake.addToContainer(this.contGFX); + this.btnScreenshake.addToContainer(this.contGFX); + + this.btnFullscreen = new Button(this.scene, { x: -128, y: 0 }, "atlasUi", "sprBtn00mid", "fullscreen", false, () => { + if (document.fullscreen === false) { + if (document.documentElement.requestFullscreen) { + document.documentElement.requestFullscreen(); + } else if (document.documentElement.msRequestFullscreen) { // for IE11 (remove June 15, 2022) + document.documentElement.msRequestFullscreen(); + } else if (document.documentElement.webkitRequestFullscreen) { // iOS Safari + document.documentElement.webkitRequestFullscreen(); + } + } else { + if (document.exitFullscreen) { + document.exitFullscreen(); + } else if (document.msExitFullscreen) { + document.msExitFullscreen(); + } else if (document.webkitExitFullscreen) { + document.webkitExitFullscreen(); + } + } + }); + this.btnFullscreen.addToContainer(this.contGFX); + + this.btnHUD = new Button(this.scene, { x: -128, y: 34 }, "atlasUi", "sprBtn00mid", "HUD", true, () => { + if (OPTIONS.config.hideUI === false) { + OPTIONS.config.hideUI = true; + this.btnHUDTxt.setText("hidden"); + } else { + OPTIONS.config.hideUI = false; + this.btnHUDTxt.setText("active"); + } + }); + this.btnHUD.toggleOffFunc = this.btnHUD.func; + this.btnHUD.addToContainer(this.contGFX); + this.btnHUDTxt = this.scene.add.bitmapText(this.btnHUD.pos.x + 128, this.btnHUD.pos.y, "uiFont", "active", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.btnHUDTxt.depth = 10000; + this.contGFX.add(this.btnHUDTxt); + if (OPTIONS.config.hideUI === false) { + this.btnHUD.active = true; + this.btnHUDTxt.setText("active"); + } else { + this.btnHUD.active = false; + this.btnHUDTxt.setText("hidden"); + } + + //control options + this.sliCursorspeed = new SliderHorizontal(this.scene, { x: 0, y: 0 }, OPTIONS.controls.mouse.sensitivity / 6, 128); + this.sliCursorspeed.move(0, 0); + this.sliCursorspeed.releaseFunc = () => { + OPTIONS.controls.mouse.sensitivity = Math.max(0.1, this.sliCursorspeed.value * 6); + } + this.btnCursorspeed = new Button(this.scene, { x: -128, y: 0 }, "atlasUi", "sprBtn00mid", "mouse sensitivity:", false, () => { + if (this.sliCursorspeed.value > 0) { + this.sliCursorspeed.setTo(0); + } else { + this.sliCursorspeed.setTo(1); + } + }); + this.sliCursorspeed.addToContainer(this.contCTL); + this.btnCursorspeed.addToContainer(this.contCTL); + + this.btnRadar = new Button(this.scene, { x: -128, y: 34 }, "atlasUi", "sprBtn00mid", "radar", true, () => { + if (OPTIONS.config.collisionRadar === 0) { + OPTIONS.config.collisionRadar = 1; + this.btnRadarTxt.setText("active"); + } else { + OPTIONS.config.collisionRadar = 0; + this.btnRadarTxt.setText("off"); + } + }); + this.btnRadar.toggleOffFunc = this.btnRadar.func; + this.btnRadar.addToContainer(this.contCTL); + this.btnRadarTxt = this.scene.add.bitmapText(this.btnRadar.pos.x + 128, this.btnRadar.pos.y, "uiFont", "active", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.btnRadarTxt.depth = 10000; + this.contCTL.add(this.btnRadarTxt); + if (OPTIONS.config.collisionRadar === 0) { + this.btnRadar.active = false; + this.btnRadarTxt.setText("off"); + } else { + this.btnRadar.active = true; + this.btnRadarTxt.setText("active"); + } + + this.lockButtons = true; + } + + update() { + this.bgGrid.updatePointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + this.bgGrid.update(); + + if (this.lockButtons <= false) { + this.btnBack.update(); + this.btnApply.update(); + this.btnAUX.update(); + this.btnGFX.update(); + this.btnCTL.update(); + + switch (this.activeContainer) { + case this.contAUX: + this.btnMaster.update(); + this.sliMaster.update(); + this.btnSound.update(); + this.sliSound.update(); + this.btnMusic.update(); + this.sliMusic.update(); + break; + case this.contGFX: + this.btnScreenshake.update(); + this.sliScreenshake.update(); + this.btnFullscreen.update(); + this.btnHUD.update(); + break; + case this.contCTL: + this.btnCursorspeed.update(); + this.sliCursorspeed.update(); + this.btnRadar.update(); + break; + default: + break; + } + + + + } else { + this.lockButtons = false; + } + } + + destroy() { + this.bgGraphics.destroy(); + this.bgGrid.destroy(); + + this.btnBack.destroy(); + this.btnApply.destroy(); + + this.btnAUX.destroy(); + this.btnGFX.destroy(); + this.btnCTL.destroy(); + + this.btnMaster.destroy(); + this.sliMaster.destroy(); + this.btnSound.destroy(); + this.sliSound.destroy(); + this.btnMusic.destroy(); + this.sliMusic.destroy(); + + this.btnScreenshake.destroy(); + this.sliScreenshake.destroy(); + this.btnFullscreen.destroy(); + this.btnHUD.destroy(); + this.btnHUDTxt.destroy(); + + this.btnCursorspeed.destroy(); + this.sliCursorspeed.destroy(); + this.btnRadar.destroy(); + this.btnRadarTxt.destroy(); + + this.contAUX.destroy(); + this.contGFX.destroy(); + this.contCTL.destroy(); + } +} diff --git a/src/ui/panelTunnelSelector.js b/src/ui/panelTunnelSelector.js new file mode 100755 index 0000000..8b56220 --- /dev/null +++ b/src/ui/panelTunnelSelector.js @@ -0,0 +1,310 @@ +import Button from "./button.js"; +import { SliderHorizontal } from "./slider.js"; +import MovingGrid from "./movingGrid.js"; +import PanelTunnelMainMenu from "./panelTunnelMainMenu.js"; +import PanelTunnelTrackSelection from "./panelTunnelTrackSelection.js"; + +export default class PanelTunnelSelector { + constructor(_scene, _level, _returnPos) { + this.scene = _scene; + this.level = _level; + this.returnPos = _returnPos; + + //this.bgGraphics = this.scene.add.graphics(); + //this.bgGraphics.fillStyle(0x000000, 0.1); + //this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + + //this.bgGrid = new MovingGrid(this.scene, this.scene.game.config.width, this.scene.game.config.height, 32); + //this.bgGrid.addPointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + + //INFO IMPORTANT keep this up to date with level aiShips or pull data from level + this.infos = [ + { + logo: this.scene.add.sprite(198, -38, "atlasAdverts", "sprLogoArashi"), + text: "The Arashi Corporation is a thin shadow of its former self. Once a leader in microchip technology and tunneling and mining, it was dismantled and bought up by more powerful corporations. Nowadays it only lives as a small racing team, with pride but without much financial resources.", + txt: this.scene.add.bitmapText(-240 + 8, -112 + 34, "uiFont", "", 14, 0), + }, + { + logo: this.scene.add.sprite(198, -38, "atlasAdverts", "sprLogoDaito"), + text: "Daito are unattainably elegant, fast and rich. They're actually just taking part in Formula Zero for fun to pass the time underground as they are coming from a control district. However, they enjoy humiliating the other drivers.", + txt: this.scene.add.bitmapText(-240 + 8, -112 + 34, "uiFont", "", 14, 0), + }, + { + logo: this.scene.add.sprite(198, -38, "atlasAdverts", "sprLogoTinnemann"), + text: "In principle, Tinnemann only drives in one direction: straight ahead. They are the bullies of the track. The Tinnemann Group is run in an extremely authoritarian manner and the residents of this district are used to being able to obtain small amenities only through sheer force. Anyone who doesn't move out of their path will be pushed out of their way.", + txt: this.scene.add.bitmapText(-240 + 8, -112 + 34, "uiFont", "", 14, 0), + }, + { + logo: this.scene.add.sprite(198, -38, "atlasAdverts", "sprLogoHapton"), + text: "Hampton Systems manufactured tanks in the great war, then the scavenging vehicles and finally the tunneling machines. Now they are converting their powerful machines into equally powerful racing vehicles. War may change, but good machining does not...", + txt: this.scene.add.bitmapText(-240 + 8, -112 + 34, "uiFont", "", 14, 0), + }, + { + logo: this.scene.add.sprite(198, -38, "atlasAdverts", "radioactive04"), + text: "unknown information", + txt: this.scene.add.bitmapText(-240 + 8, -112 + 34, "uiFont", "", 14, 0), + }, + ]; + for (let i of this.infos) { + i.logo.alpha = 0; + i.txt.alpha = 0; + i.txt.maxWidth = 180; + i.txt.setText(i.text); + //i.txt.setTintFill(0x1d2b53) + i.txt.setOrigin(0); + i.txt.setLetterSpacing(0); + } + + this.character = { + ghostReverse: this.scene.add.sprite(512, 0, "charSheetRoki", "rokiStandIdle0000"), + ghost: this.scene.add.sprite(198, 0, "charSheetRoki", "rokiStandIdle0000"), + sprite: this.scene.add.sprite(198, 0, "charSheetRoki", "rokiStandIdle0000"), + name: this.scene.add.bitmapText(198, 80, "racer", "Roki", 16, 0).setOrigin(0.5).setLetterSpacing(0), + dir: 0, + atlas: "charSheetRoki", + asset: "rokiStandIdle000", + pos: {x: 198, y: 0} + }; + this.character.ghostReverse.y = 512; + this.character.ghostReverse.setScale(10); + this.character.ghostReverse.alpha = 0.25; + + this.characterTweenIn = this.scene.tweens.add({ + targets: this.character.sprite, + x: { from: -256, to: 198 }, + ease: "Cubic", + repeat: 0, + duration: 1000, + persist: true, + onRestart: () => { }, + onUpdate: () => {}, + onComplete: (_ev) => {/*this.characterTweenGhost.restart();*/} + }).pause(); + this.characterTweenGhostReverse = this.scene.tweens.add({ + targets: this.character.ghostReverse, + x: { from: 512, to: -256 }, + alpha: { from: 1, to: 0 }, + ease: "Linear", + repeat: 0, + duration: 2000, + persist: true, + }).pause(); + this.characterTweenGhost = this.scene.tweens.add({ + targets: this.character.ghost, + alpha: {from: 1, to: 0}, + scale: 4, + ease: "Linear", + repeat: 0, + duration: 500, + persist: true, + }).pause(); + + /* + this.zoomTween = this.scene.tweens.add({ + targets: this, + zoom: 0.0001, + // x: '+=1', + // x: '-=1', + // x: '*=1', + // x: '/=1', + // x: 'random(0.25, 0.75)', + // x: 'int(10, 100)', + // x: [100, 300, 200, 600], + // x: { from: 0, to: 1 }, + // x: { start: 0, to: 1 }, + // x: { start: value0, from: value1, to: value2 }, + // x: { + // getActive: function (target, key, value, targetIndex, totalTargets, tween) { return newValue; }, + // getStart: function (target, key, value, targetIndex, totalTargets, tween) { return newValue; }, + // getEnd: function (target, key, value, targetIndex, totalTargets, tween) { return newValue; } + // }, + ease: 'Linear', // 'Cubic', 'Elastic', 'Bounce', 'Back' + duration: 1000, + repeat: 0, // -1: infinity + yoyo: true, + //persist: true, + // interpolation: null, + onYoyo: () => { + console.log(this) + } + }).pause(); + */ + + + this.btnBack = new Button(this.scene, { x: -176, y: -112 }, "atlasUi", "sprBtnNFS01", "BACK", false, () => { + this.level.state = this.level.states.main; + this.level.lerper = 100; + this.level.calculateLerpStep(); + //this.level.playerShip.speed = 10; + this.level.actions.push(() => { + this.scene.player.panel = new PanelTunnelMainMenu(this.scene, this.level); + }); + this.destroy(); + }); + this.level.makeBtnNFS(this.btnBack); + + this.btnTrackSelection = new Button(this.scene, { x: -176 + 128, y: -112 }, "atlasUi", "sprBtnNFS02", "TRACK SELECT", false, () => { + this.level.state = this.level.states.trackSelection; + this.level.lerper = 100; + this.level.calculateLerpStep(); + //this.level.playerShip.speed = 10; + this.level.actions.push(() => { + this.scene.player.panel = new PanelTunnelTrackSelection(this.scene, this.level); + }); + this.destroy(); + }); + this.level.makeBtnNFS(this.btnTrackSelection); + + //this.btnToTrack = new Button(this.scene, { x: 0, y: 128-16 }, "atlasUi", "sprBtn00", "DIRECT TRACK", false, () => { + this.btnToTrack = new Button(this.scene, { x: -176 + 256, y: -112 }, "atlasUi", "sprBtnNFS00", "START RACE", false, () => { + this.scene.soundManager.stopSound(this.level.mainMusic); + this.scene.player.panel = null; + + this.scene.player.jumpToPosition({ x: 0, y: 0, z: 0 }); + this.scene.loadLevel("quadRingsTest", { track: this.level.trackSelected, raceMode: 5, maxLaps: 5, startFromHangar: false, playerShipModel: this.level.playerShip.modelFile }); + //this.scene.loadLevel("quadRingsTest", { track: 1, raceMode: 0, maxLaps: 99, startFromHangar: false, playerShipModel: this.level.playerShip.modelFile }); + //this.scene.loadLevel("quadRingsTest", { track: 4, raceMode: 5, maxLaps: 99, startFromHangar: false, playerShipModel: this.level.playerShip.modelFile }); + + //this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.playerWalk.setVisibility(false); + this.scene.player.panel = null; + this.destroy(); + }); + this.level.makeBtnNFS(this.btnToTrack); + + this.btnDeco00 = new Button(this.scene, { x: 208-48, y: -112 }, "atlasUi", "sprBtnSlider00", "", false, () => {}); + this.level.makeBtnNFS(this.btnDeco00); + this.btnDeco00.sprite.setScale(2); + + this.btnDeco01 = new Button(this.scene, { x: 208 - 11, y: -112 }, "atlasUi", "sprBtnNFS07", "//", false, () => {}); + this.level.makeBtnNFS(this.btnDeco01); + this.btnDeco01.sprite.setScale(0.5, 1); + + this.btnDeco02 = new Button(this.scene, { x: 208 + 22, y: -112 }, "atlasUi", "sprBtnSlider00", "", false, () => {}); + this.level.makeBtnNFS(this.btnDeco02); + this.btnDeco02.sprite.setScale(2); + + this.btnShipNext = new Button(this.scene, { x: 208, y: 128 - 16 }, "atlasUi", "sprBtnNFS04", ">>>", false, () => { + this.level.playerShip.speed = this.level.speed.switching; + this.level.shipSelected += 1; + if (this.level.shipSelected >= this.level.aiShips.length) { + this.level.shipSelected -= this.level.aiShips.length; + } + this.level.playerShip = this.level.aiShips[this.level.shipSelected]; + this.level.playerShip.speed = this.level.speed.switching; + this.showInfo(this.level.shipSelected); + }); + this.level.makeBtnNFS(this.btnShipNext); + + this.btnShipPrev = new Button(this.scene, { x: -208, y: 128 - 16 }, "atlasUi", "sprBtnNFS05", "<<<", false, () => { + this.level.playerShip.speed = this.level.speed.switching; + this.level.shipSelected -= 1; + if (this.level.shipSelected < 0) { + this.level.shipSelected += this.level.aiShips.length; + } + this.level.playerShip = this.level.aiShips[this.level.shipSelected]; + this.level.playerShip.speed = this.level.speed.switching; + this.showInfo(this.level.shipSelected); + }); + this.level.makeBtnNFS(this.btnShipPrev); + + this.btnShipInfo = new Button(this.scene, { x: -208 + 64, y: 128 - 16 }, "atlasUi", "sprBtnNFS06", "NFO", false, () => { + //alert("show racer info") + }); + this.level.makeBtnNFS(this.btnShipInfo); + + this.lockButtons = true; + this.showInfo(this.level.shipSelected); + } + + showInfo(_no) { + for (let i of this.infos) { + i.logo.alpha = 0; + i.txt.alpha = 0; + } + this.infos[_no % 5].logo.alpha = 1; + this.infos[_no % 5].txt.alpha = 1; + + this.character.atlas = this.level.aiShips[this.level.shipSelected].character.promoAtlas; + this.character.asset = this.level.aiShips[this.level.shipSelected].character.promoAsset; + this.character.ghost.setTexture(this.character.atlas, this.character.asset + "0"); + this.character.ghost.setScale(1); + this.character.ghost.alpha = 0; + this.character.ghost.setTintFill(0xffffff); + this.character.ghostReverse.setTexture(this.character.atlas, this.character.asset + "0"); + + if (this.level.aiShips[this.level.shipSelected].character.locked === true) { + this.character.sprite.setTintFill(0x000000); + this.character.ghostReverse.setTintFill(0x000000); + this.character.name.setText("locked"); + this.btnToTrack.switchState(this.btnToTrack.states.off); + this.btnShipInfo.switchState(this.btnShipInfo.states.off); + } else { + this.character.sprite.clearTint(); + this.character.ghostReverse.clearTint(); + this.character.name.setText(this.level.aiShips[this.level.shipSelected].character.name); + } + + this.characterTweenIn.restart(); + this.characterTweenGhost.restart(); + this.characterTweenGhostReverse.restart(); + + //console.log(this.btnToTrack.state) + } + + update() { + //this.bgGrid.updatePointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + //this.bgGrid.update(); + + + if (this.lockButtons <= false) { + if(this.character !== null){ + this.character.dir += 0.06 * this.scene.dt; + if (this.character.dir > 8) { + this.character.dir -= 8; + } + this.character.sprite.setTexture(this.character.atlas, this.character.asset + String(Math.floor(this.character.dir % 8))); + } + + this.btnBack.update(); + this.btnTrackSelection.update(); + if (this.level.aiShips[this.level.shipSelected].character.locked === false) { + this.btnToTrack.update(); + this.btnShipInfo.update(); + } + this.btnShipNext.update(); + this.btnShipPrev.update(); + } else { + this.lockButtons = false; + } + } + + destroy() { + //this.bgGraphics.destroy(); + //this.bgGrid.destroy(); + for (let i of this.infos) { + i.logo.destroy(); + i.txt.destroy(); + } + this.character.sprite.destroy(); + this.character.ghost.destroy(); + this.character.ghostReverse.destroy(); + this.character.name.destroy(); + this.character = null; + + this.scene.tweens.remove(this.characterTweenGhost); + this.scene.tweens.remove(this.characterTweenGhostReverse); + this.scene.tweens.remove(this.characterTweenIn); + + this.btnBack.destroy(); + this.btnTrackSelection.destroy(); + this.btnToTrack.destroy(); + this.btnShipNext.destroy(); + this.btnShipInfo.destroy(); + this.btnShipPrev.destroy(); + + this.btnDeco00.destroy(); + this.btnDeco01.destroy(); + this.btnDeco02.destroy(); + } +} diff --git a/src/ui/panelTunnelTrackSelection.js b/src/ui/panelTunnelTrackSelection.js new file mode 100755 index 0000000..f026e9b --- /dev/null +++ b/src/ui/panelTunnelTrackSelection.js @@ -0,0 +1,408 @@ +import Button from "./button.js"; +import { SliderHorizontal } from "./slider.js"; +import MovingGrid from "./movingGrid.js"; +import PanelTunnelSelector from "./panelTunnelSelector.js"; + +export default class PanelTunnelTrackSelection { + constructor(_scene, _level, _returnPos) { + this.scene = _scene; + this.level = _level; + this.returnPos = _returnPos; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x1d2b53, 0.9); //0x000000 black - 0xa7d254 green - 0x1d2b53 blue - 0x29adff lightblue + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + + this.bgGrid = new MovingGrid(this.scene, this.scene.game.config.width, this.scene.game.config.height, 32); + this.bgGrid.addPointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + + this.trackBtnSelected = 0; + this.trackBtnSelectedOffset = 0; + + this.trackGraphics = this.scene.add.graphics(); + this.trackGraphics.depth = 10000; + this.trackMap = { + spline: [], + dir: { yaw: 0, pitch: 0, roll: 0 }, + spd: 0.01, + origin: { x: 0, y: 0 }, + zoom: 64, + bounds: { p0: { x: 0, y: 0 }, p1: { x: 0, y: 0 } }, + racer: 0, + oblique: true + } + + this.btnBack = new Button(this.scene, { x: -176-32, y: -112 }, "atlasUi", "sprBtn00mid", "BACK", false, () => { + this.level.state = this.level.states.shipSelection; + this.level.lerper = 100; + this.level.calculateLerpStep(); + this.level.actions.push(() => { + this.scene.player.panel = new PanelTunnelSelector(this.scene, this.level); + }); + this.destroy(); + }); + + this.sliZoom = new SliderHorizontal(this.scene, { x: 0, y: 112 }, 0.75, 128); + this.sliZoom.move(0, -112); + this.sliZoom.changeFunc = () => { + this.trackMap.zoom = Math.max(1, (256 - this.sliZoom.value * 256)); + } + + this.btnTrackOblique = new Button(this.scene, { x: 176-64, y: -112 }, "atlasUi", "sprBtn00mid", "OBL", false, () => { + this.trackMap.oblique = !this.trackMap.oblique; + if (this.trackMap.oblique === true) { this.btnTrackOblique.txt.setText("OBL"); } + else { this.btnTrackOblique.txt.setText("D3D"); } + }); + + + this.btnsTrack = []; + + this.btnTrackScrollUp = new Button(this.scene, { x: 176+32, y: -112 }, "atlasUi", "sprBtn08", "<<<", false, () => { + if (this.trackBtnSelected > 1) { + this.trackBtnSelected -= 1; + this.toggleOffTrackButtons(); + this.btnsTrack[this.trackBtnSelected].simulateClick(); + } else { + this.cycleTrackButtons(-1); + } + this.loadTrackMap(this.btnsTrack[this.trackBtnSelected].data.trackId); + }); + this.btnTrackScrollUp.txt.angle = 90; + + this.btnTrack00 = new Button(this.scene, { x: 176, y: -68 }, "atlasUi", "sprBtn01", "METRO LOOP", true, () => { + this.toggleOffTrackButtons(); + this.btnTrack00.active = true; + this.trackBtnSelected = 0; + this.loadTrackMap(this.btnTrack00.data.trackId); + }); + this.btnTrack00.useOtherTextColor = true; + this.btnTrack00.data = {trackId: 0} + this.btnsTrack.push(this.btnTrack00); + + this.btnTrack01 = new Button(this.scene, { x: 176, y: -34 }, "atlasUi", "sprBtn01", "ATOMIC SEWERS", true, () => { + this.toggleOffTrackButtons(); + this.btnTrack01.active = true; + this.trackBtnSelected = 1; + this.loadTrackMap(this.btnTrack01.data.trackId); + }); + this.btnTrack01.useOtherTextColor = true; + this.btnTrack01.data = {trackId: 1} + this.btnsTrack.push(this.btnTrack01); + + this.btnTrack02 = new Button(this.scene, { x: 176, y: 0 }, "atlasUi", "sprBtn01", "CONSTRUCTION", true, () => { + this.toggleOffTrackButtons(); + this.btnTrack02.active = true; + this.trackBtnSelected = 2; + this.loadTrackMap(this.btnTrack02.data.trackId); + }); + this.btnTrack02.useOtherTextColor = true; + this.btnTrack02.data = {trackId: 2} + this.btnsTrack.push(this.btnTrack02); + + this.btnTrack03 = new Button(this.scene, { x: 176, y: 34 }, "atlasUi", "sprBtn01", "PIPELINE", true, () => { + this.toggleOffTrackButtons(); + this.btnTrack03.active = true; + this.trackBtnSelected = 3; + this.loadTrackMap(this.btnTrack03.data.trackId); + }); + this.btnTrack03.useOtherTextColor = true; + this.btnTrack03.data = {trackId: 3} + this.btnsTrack.push(this.btnTrack03); + + this.btnTrack04 = new Button(this.scene, { x: 176, y: 68 }, "atlasUi", "sprBtn01", "VELOCIDROME", true, () => { + this.toggleOffTrackButtons(); + this.btnTrack04.active = true; + this.trackBtnSelected = 4; + this.loadTrackMap(this.btnTrack04.data.trackId); + }); + this.btnTrack04.useOtherTextColor = true; + this.btnTrack04.data = {trackId: 4} + this.btnsTrack.push(this.btnTrack04); + + this.btnTrackScrollDown = new Button(this.scene, { x: 176+32, y: 112 }, "atlasUi", "sprBtn08", ">>>", false, () => { + if (this.trackBtnSelected < this.btnsTrack.length - 2) { + this.trackBtnSelected += 1; + this.toggleOffTrackButtons(); + this.btnsTrack[this.trackBtnSelected].simulateClick(); + } else { + this.cycleTrackButtons(1); + } + this.loadTrackMap(this.btnsTrack[this.trackBtnSelected].data.trackId); + }); + this.btnTrackScrollDown.txt.angle = 90; + + + + this.btnsTrack[this.trackBtnSelected].simulateClick(); + + this.lockButtons = true; + } + + update() { + this.bgGrid.updatePointer("hand", this.scene.hand.pos.x, this.scene.hand.pos.y, 128); + this.bgGrid.update(); + + this.renderTrackMap(this.trackMap.oblique); + + if (this.lockButtons <= false) { + this.btnBack.update(); + this.sliZoom.update(); + this.btnTrackOblique.update(); + this.btnTrackScrollUp.update(); + this.btnTrackScrollDown.update(); + this.btnTrack00.update(); + this.btnTrack01.update(); + this.btnTrack02.update(); + this.btnTrack03.update(); + this.btnTrack04.update(); + } else { + this.lockButtons = false; + } + + this.level.trackSelected = this.btnsTrack[this.trackBtnSelected].data.trackId; + } + + loadTrackMap(_trackId) { + this.level.trackPreview.loadTrack(_trackId, true); + + this.trackMap.spline = []; + this.trackMap.origin = { x: 0, y: 0 } + this.trackMap.center = { x: 0, y: 0 } + + let dim = { x0: 0, x1: 0, y0: 0, y1: 0 } + for (let i = 0; i < this.level.trackPreview.spline.length; i += 1) { + let s = this.level.trackPreview.spline[i]; + dim.x0 = Math.min(s.x, dim.x0); + dim.y0 = Math.min(s.z, dim.y0); + dim.x1 = Math.max(s.x, dim.x1); + dim.y1 = Math.max(s.z, dim.y1); + + this.trackMap.center.x += s.x; + this.trackMap.center.y += s.z; + + this.trackMap.spline.push({ + x: s.x * -1, + y: s.y, + z: s.z, + id: i, + type: 0 + }); + } + + this.trackMap.bounds = {p0: {x: dim.x0, y: dim.y0}, p1: {x: dim.x1, y: dim.y1}} + + this.trackMap.origin.x = ((dim.x0 + dim.x1) * -0.5); + this.trackMap.origin.y = ((dim.y0 + dim.y1) * -0.5); + + for (let s of this.trackMap.spline) { + s.x -= this.trackMap.origin.x; + s.z += this.trackMap.origin.y; + } + + //console.log(this.trackMap) + } + + renderTrackMap(_oblique = true) { + this.trackGraphics.clear(); + this.trackGraphics.lineStyle(3, 0xffffff, 1); + this.trackGraphics.fillStyle(0xffffff, 1); + //this.trackGraphics.beginPath(); + this.trackGraphics.fillCircle(0, 0, 2);//origin + + this.trackMap.racer += 1; + if (this.trackMap.racer >= this.trackMap.spline.length) { + this.trackMap.racer -= this.trackMap.spline.length; + } + + this.trackMap.dir.yaw += 0.01; + let cos = Math.cos(this.trackMap.dir.yaw); + let sin = Math.sin(this.trackMap.dir.yaw); + + if (_oblique === true) { + let firs = {x: 0, y: 0} + let prev = {x: 0, y: 0} + for (let i = 0; i < this.trackMap.spline.length; i += 1) { + let s = this.trackMap.spline[i]; + + let nx = (cos * s.x) + (sin * s.z); + let ny = s.y; + let nz = (cos * s.z) - (sin * s.x); + + //3dize + nz = (nz * 0.5) + ny; + + nx /= this.trackMap.zoom; + ny /= this.trackMap.zoom; + nz /= this.trackMap.zoom; + + if (i === 0) { + firs.x = nx; + firs.y = nz; + } + + if (i > 0) { + //this.trackGraphics.lineStyle(3, 0xffffff, 1 - Math.min(0.5, Math.max(0, Math.abs(ny) / 64))); + //this.trackGraphics.lineStyle(2, 0xffffff, Math.max(0.5, ((i + this.trackMap.racer) % 20) / 20)); + //this.trackGraphics.lineStyle(2, 0xffffff, Math.max(0.5, (i % 20) / 20)); + //if (i < this.trackMap.racer && i > this.trackMap.racer - 20) { + if (i - Math.floor(this.trackMap.racer) < 10 && i - Math.floor(this.trackMap.racer) > 0) { + this.trackGraphics.lineStyle(2, 0xe60840, 1);//0xf79e00 + } else { + this.trackGraphics.lineStyle(2, 0xf8f2e6, 1); + } + this.trackGraphics.beginPath(); + this.trackGraphics.moveTo(prev.x, prev.y); + this.trackGraphics.lineTo(nx, nz); + this.trackGraphics.strokePath(); + } + + let radius = 1; + if (i < 44) { + if(i % 2 === 0){ + this.trackGraphics.fillStyle(0x7d7195, 1); + radius = 3; + this.trackGraphics.fillCircle(nx, nz, radius); + } else { + this.trackGraphics.fillStyle(0xf8f2e6, 1); + } + }else { + this.trackGraphics.fillStyle(0xf8f2e6, 1);// ((i + this.trackMap.racer) % 10 / 10)); + } + if (i - Math.floor(this.trackMap.racer) < 10 && i - Math.floor(this.trackMap.racer) > 0) { + this.trackGraphics.fillStyle(0xe60840, 1 -(Math.floor(this.trackMap.racer) - i) * 0.1); + radius = (11 + (Math.floor(this.trackMap.racer) - i)) * 0.5; + this.trackGraphics.fillCircle(nx, nz, radius); + } + prev.x = nx; + prev.y = nz; + } + + this.trackGraphics.beginPath(); + this.trackGraphics.moveTo(prev.x / this.trackMap.zoom, prev.y / this.trackMap.zoom); + this.trackGraphics.lineTo(firs.x / this.trackMap.zoom, firs.y / this.trackMap.zoom); + this.trackGraphics.strokePath(); + } else { + let firs = {x: 0, y: 0} + let prev = {x: 0, y: 0} + for (let i = 0; i < this.trackMap.spline.length; i += 1) { + let s = this.trackMap.spline[i]; + + let nx = (cos * s.x) + (sin * s.z); + let ny = s.y + 2000; + let nz = (cos * s.z) - (sin * s.x); + nz *= -1; + //3dize + //nz = (nz * 0.5) + ny; + let nzMod = nz + 10000; + if(nzMod > 0){ + nx = (nx / nzMod) * 5000; + ny = (ny / nzMod) * 5000; + } + + nx /= this.trackMap.zoom; + ny /= this.trackMap.zoom; + nz /= this.trackMap.zoom; + + if (i === 0) { + firs.x = nx; + firs.y = ny; + } + + if (i > 0) { + //this.trackGraphics.lineStyle(3, 0xffffff, 1 - Math.min(0.5, Math.max(0, Math.abs(ny) / 64))); + //this.trackGraphics.lineStyle(2, 0xffffff, Math.max(0.5, ((i + this.trackMap.racer) % 20) / 20)); + //this.trackGraphics.lineStyle(2, 0xffffff, Math.max(0.5, (i % 20) / 20)); + //if (i < this.trackMap.racer && i > this.trackMap.racer - 20) { + if (i - Math.floor(this.trackMap.racer) < 10 && i - Math.floor(this.trackMap.racer) > 0) { + this.trackGraphics.lineStyle(2, 0xe60840, 1);//0xf79e00 + } else { + this.trackGraphics.lineStyle(2, 0xf8f2e6, 1); + } + this.trackGraphics.beginPath(); + this.trackGraphics.moveTo(prev.x, prev.y); + this.trackGraphics.lineTo(nx, ny); + this.trackGraphics.strokePath(); + } + + let radius = 1; + if (i < 44) { + if(i % 2 === 0){ + this.trackGraphics.fillStyle(0x7d7195, 1); + radius = 3; + this.trackGraphics.fillCircle(nx, ny, radius); + } else { + this.trackGraphics.fillStyle(0xf8f2e6, 1); + } + }else { + this.trackGraphics.fillStyle(0xf8f2e6, 1);// ((i + this.trackMap.racer) % 10 / 10)); + } + if (i - Math.floor(this.trackMap.racer) < 10 && i - Math.floor(this.trackMap.racer) > 0) { + this.trackGraphics.fillStyle(0xe60840, 1 -(Math.floor(this.trackMap.racer) - i) * 0.1); + radius = (11 + (Math.floor(this.trackMap.racer) - i)) * 0.5; + this.trackGraphics.fillCircle(nx, ny, radius); + } + + prev.x = nx; + prev.y = ny; + } + + this.trackGraphics.beginPath(); + this.trackGraphics.moveTo(prev.x / this.trackMap.zoom, prev.y / this.trackMap.zoom); + this.trackGraphics.lineTo(firs.x / this.trackMap.zoom, firs.y / this.trackMap.zoom); + this.trackGraphics.strokePath(); + } + } + + cycleTrackButtons(_amt) { + let arr = [this.btnTrack00, this.btnTrack01, this.btnTrack02, this.btnTrack03, this.btnTrack04]; + if (_amt > 0) { + let help = arr[0].text; + let helpData = JSON.parse(JSON.stringify(arr[0].data)); + for (let i = 0; i < arr.length - 1; i++){ + arr[i].txt.setText(arr[i + 1].text); + arr[i].text = arr[i + 1].text; + arr[i].data = arr[i + 1].data; + } + arr[4].txt.setText(help); + arr[4].text = help; + arr[4].data = helpData; + } else if (_amt < 0) { + let help = arr[4].text; + let helpData = JSON.parse(JSON.stringify(arr[4].data)); + for (let i = arr.length - 1; i > 0; i--){ + arr[i].txt.setText(arr[i - 1].text); + arr[i].text = arr[i - 1].text; + arr[i].data = arr[i - 1].data; + } + arr[0].txt.setText(help); + arr[0].text = help; + arr[0].data = helpData; + } + } + + toggleOffTrackButtons() { + for (let b of this.btnsTrack) { + if (b.active === true) { + b.simulateClick(false); + } + } + } + + destroy() { + this.bgGraphics.destroy(); + this.bgGrid.destroy(); + + this.trackGraphics.destroy(); + + this.btnBack.destroy(); + this.sliZoom.destroy(); + this.btnTrackOblique.destroy(); + this.btnTrackScrollUp.destroy(); + this.btnTrackScrollDown.destroy(); + this.btnTrack00.destroy(); + this.btnTrack01.destroy(); + this.btnTrack02.destroy(); + this.btnTrack03.destroy(); + this.btnTrack04.destroy(); + } +} diff --git a/src/ui/panelWakeUp.js b/src/ui/panelWakeUp.js new file mode 100755 index 0000000..a19c67d --- /dev/null +++ b/src/ui/panelWakeUp.js @@ -0,0 +1,74 @@ +export default class PanelWakeUp{ + constructor(_scene, _text = "") { + this.scene = _scene; + + //stop use click clicking immediatly again and eg hit the back btn + this.scene.hand.justPressed = false; + this.scene.hand.pressed = false; + this.scene.hand.justReleased = false; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x000000, 0.75); + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + + this.bgGraphics.beginPath(); + this.bgGraphics.lineStyle(1, 0xffffff); + this.bgGraphics.moveTo(-128, -16); + this.bgGraphics.lineTo(128, -16); + this.bgGraphics.strokePath(); + + this.eyelidLow = this.scene.add.sprite(0, 0, "atlasAll", "texStone01b"); + this.eyelidLow.setScale(this.scene.game.config.width / 32, this.scene.game.config.height / 32); + this.eyelidLow.alpha = 0.25; + this.eyelidUp = this.scene.add.sprite(0, 0, "atlasAll", "texStone01b"); + this.eyelidUp.rotation = Math.PI; + this.eyelidUp.setScale(this.scene.game.config.width / 32, this.scene.game.config.height / 32); + this.eyelidUp.alpha = 0.25; + + this.text = _text; + if(_text === ""){ + this.text = "Wakey, Wakey, mon ami!"; + } + + this.header = this.scene.add.bitmapText(0, -32, "uiFont", this.text, 16, 0).setOrigin(0.5); + this.header.depth = 10000; + + this.tweenBg = this.scene.add.tween({ + targets: this.bgGraphics, + alpha: 0, + delay: 1500, + duration: 2500, + ease: Phaser.Math.Easing.Cubic.Out, + onComplete: () => { + this.destroy(); + this.scene.player.panel = null; + this.scene.player.showUI(); + } + }) + + this.tweenHeader = this.scene.add.tween({ + targets: this.header, + alpha: 0, + delay: 1500, + duration: 2500, + ease: Phaser.Math.Easing.Quintic.Out, + onComplete: () => { + + } + }) + } + + update(){ + this.eyelidLow.y = (1 - this.header.alpha) * this.scene.game.config.height; + this.eyelidUp.y = (1 - this.header.alpha) * -this.scene.game.config.height; + } + + destroy(){ + //this.tweenBg.destroy(); + //this.tweenHeader.destroy(); + this.bgGraphics.destroy(); + this.header.destroy(); + this.eyelidLow.destroy(); + this.eyelidUp.destroy(); + } +} \ No newline at end of file diff --git a/src/ui/panelWelcome.js b/src/ui/panelWelcome.js new file mode 100755 index 0000000..15c933a --- /dev/null +++ b/src/ui/panelWelcome.js @@ -0,0 +1,55 @@ +import Button from "./button.js"; +import {SliderHorizontal, SliderVertical} from "./slider.js"; + +export default class PanelWelcome{ + constructor(_scene) { + this.scene = _scene; + + //stop use click clicking immediatly again and eg hit the back btn + this.scene.hand.justPressed = false; + this.scene.hand.pressed = false; + this.scene.hand.justReleased = false; + + this.bgGraphics = this.scene.add.graphics(); + this.bgGraphics.fillStyle(0x000000, 0.9); + this.bgGraphics.fillRect(this.scene.left, this.scene.top, this.scene.game.config.width, this.scene.game.config.height); + /* + this.bgSprite = this.scene.add.sprite(0, this.scene.bottom - (25 * 4), "klimtUI01"); + this.bgSprite.setScale(4); + this.bgSpriteOver = this.scene.add.sprite(0, this.scene.bottom - (40 * 4), "klimtUI02"); + this.bgSpriteOver.setScale(4); + */ + + let btnPos = { x: 0, y: this.scene.bottom - (25 * 4) }; + if(isMobile === true){ + btnPos.y = 155; + } + this.btnPlay = new Button(this.scene, { x: btnPos.x, y: btnPos.y }, "atlasUi", "sprBtn00Invisible", "START GAME", false, () => { + this.destroy(); + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + }); + + + this.btnToEditor = new Button(this.scene, { x: this.scene.left + 64, y: this.scene.bottom - 24 }, "atlasUi", "sprBtn01", "Editor", false, () => { + //$("#optionbox").hide(); + //this.scene.scene.start("Scn3d", { level: "modelBuilder" }); + this.destroy(); + this.scene.player.setMode(PLAYERMODE.LOOK); + this.scene.player.panel = null; + this.scene.loadLevel("modelBuilder"); + }); + + } + + update(){ + this.btnPlay.update(); + this.btnToEditor.update(); + } + + destroy(){ + this.bgGraphics.destroy(); + this.btnPlay.destroy(); + this.btnToEditor.destroy(); + } +} \ No newline at end of file diff --git a/src/ui/racing/times.js b/src/ui/racing/times.js new file mode 100644 index 0000000..9a829c1 --- /dev/null +++ b/src/ui/racing/times.js @@ -0,0 +1,5 @@ +export default class RaceTimes{ + constructor(){ + + } +} \ No newline at end of file diff --git a/src/ui/racing/ui.js b/src/ui/racing/ui.js new file mode 100644 index 0000000..9a5a3e6 --- /dev/null +++ b/src/ui/racing/ui.js @@ -0,0 +1,527 @@ +export default class UI { + constructor(_scene, _level) { + this.scene = _scene; + this.level = _level; + this.hidden = false; + this.rumbling = false; + this.rumble = { + intensity: { + x: 1, + y: 2 + }, + time: 0 + } + this.scrape = { + isScraping: false, + amount: 0 + } + this.heat = { + amount: 0 + } + + this.container = this.scene.add.container(0, 0); + + //cockpit + this.cockpit = this.scene.add.sprite(0, 200, "sprCockpitMockup"); + this.cockpit.depth = 9997; + this.cockpit.alpha = 0; + this.container.add(this.cockpit); + + //vignette borders + this.vignetteScrape = this.scene.add.sprite(0, 0, "atlasUi", "sprUiTunnelBorderScrape"); + this.vignetteScrape.depth = 9998; + this.vignetteScrape.setScale(this.scene.game.config.width / 16, this.scene.game.config.height / 64); + this.vignetteScrape.setTint(0xffa300); + this.container.add(this.vignetteScrape); + + this.vignetteHeat = this.scene.add.sprite(0, 0, "atlasUi", "sprUiTunnelBorderHeat00"); + this.vignetteHeat.depth = 9998; + this.vignetteHeat.setScale(this.scene.game.config.width / 16, this.scene.game.config.height / 64); + this.vignetteHeat.setTint(0xffa300); + this.container.add(this.vignetteHeat); + + //texts + this.txtHelper = this.scene.add.bitmapText(0, (this.scene.game.config.height * -0.4), "uiFont", "Test", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.txtHelper.depth = 9999; + this.container.add(this.txtHelper); + this.txtLower = this.scene.add.bitmapText(0, (this.scene.game.config.height * 0.4), "uiFont", "Test", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.txtLower.depth = 9999; + this.container.add(this.txtLower); + + this.txtDelta = this.scene.add.bitmapText((this.scene.game.config.width * -0.5) + 8, (this.scene.game.config.height * -0.5) + 8, "uiFont", "Test", 14, 0).setOrigin(0, 0.5).setLetterSpacing(0); + this.txtDelta.depth = 9999; + this.txtDelta.alpha = 0; + this.container.add(this.txtDelta); + + this.txtBestLapTime = this.scene.add.bitmapText((this.scene.game.config.width * -0.5) + 16, (this.scene.game.config.height * -0.4) + 0, "uiFont", "NO BEST LAP YET", 14, 0).setOrigin(0, 0.5).setLetterSpacing(0); + this.txtBestLapTime.depth = 9999; + this.container.add(this.txtBestLapTime); + this.txtLastLapTime = this.scene.add.bitmapText((this.scene.game.config.width * -0.5) + 16, (this.scene.game.config.height * -0.4) + 16, "uiFont", "NO LAST LAP YET", 14, 0).setOrigin(0, 0.5).setLetterSpacing(0); + this.txtLastLapTime.depth = 9999; + this.container.add(this.txtLastLapTime); + this.txtLapTime = this.scene.add.bitmapText((this.scene.game.config.width * -0.5) + 16, (this.scene.game.config.height * -0.4) + 32, "uiFont", "CURRENT LAP", 14, 0).setOrigin(0, 0.5).setLetterSpacing(0); + this.txtLapTime.depth = 9999; + this.container.add(this.txtLapTime); + + this.txtLapPos = this.scene.add.bitmapText((this.scene.game.config.width * -0.5) + 16, (this.scene.game.config.height * -0.4) + 48, "uiFont", "CURRENT POS", 14, 0).setOrigin(0, 0.5).setLetterSpacing(0); + this.txtLapPos.depth = 9999; + this.container.add(this.txtLapPos); + + this.txtWarning = this.scene.add.bitmapText(0, (this.scene.game.config.height * -0.4) + 48, "uiFont", "!!!WARNING!!!", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.txtWarning.depth = 9999; + this.container.add(this.txtWarning); + + this.txtCountdown = this.scene.add.bitmapText(0, 0, "uiFont", "", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.txtCountdown.depth = 9999; + this.txtCountdown.alpha = 1; + this.container.add(this.txtCountdown); + + this.lineMap = this.scene.add.graphics(0, 0); + this.lineMap.depth = 9999; + this.container.add(this.lineMap); + this.lineMap.lineStyle(1, 0xffffff, 1);//0x00e436 + this.lineMap.beginPath(); + this.lineMap.moveTo((this.scene.game.config.width * 0.5) - 16.5, (this.scene.game.config.height * -0.5) + 16); + this.lineMap.lineTo((this.scene.game.config.width * 0.5) - 16.5, (this.scene.game.config.height * 0.5) - 16); + this.lineMap.strokePath(); + + this.reactionPosition = { x: (this.scene.game.config.width * 0.5) - 96, y: (this.scene.game.config.height * -0.5) + 64 } + this.racerReaction = this.scene.add.sprite(this.reactionPosition.x, this.reactionPosition.y, "charSheetExpressions", "bonezExpressionHaha01"); + this.racerReaction.depth = 9999; + this.racerReaction.alpha = 0; + this.racerReactionUpcount = 0.01; + this.container.add(this.racerReaction); + this.racerReactionName = this.scene.add.bitmapText(this.reactionPosition.x, this.reactionPosition.y + 32 + 8, "uiFontOffwhite", "RACER", 14, 0).setOrigin(0.5).setLetterSpacing(0); + //this.racerReactionName.setTintFill(0xfff1e8) + this.racerReactionName.depth = 9999; + this.racerReactionName.alpha = 0; + this.container.add(this.racerReactionName); + + //danger circle + this.dangerCircleContainer = this.scene.add.container(); + this.dangerCircleContainer.depth = 9998; + this.container.add(this.dangerCircleContainer); + this.dangerCirclets = []; + for (let q = 0; q < 4; q++) { + for (let i = 0; i < 4; i++) { + this.dangerCirclets.push([]); + let arr = this.dangerCirclets[this.dangerCirclets.length - 1]; + for (let j = 0; j < 6; j++) { + arr.push(this.scene.add.sprite(0, 32, "atlasUi", "sprUiCollisionWarningCircle" + String(i) + String(j))); + let s = arr[arr.length - 1]; + s.setOrigin(0, 1); + s.rotation = (Math.PI * 0.5) * q; + s.alpha = 0; + this.dangerCircleContainer.add(s); + } + } + } + + //slipstream visual + this.slipstream = this.scene.add.graphics(0, 0); + this.slipstream.depth = 9999; + this.container.add(this.slipstream); + this.slipstream.lineStyle(1, 0xffffff, 1); + this.slipstreamAngle = 0; + + //(tutorial) progress + this.progress = this.scene.add.graphics(0, 0); + this.progress.depth = 9999; + this.container.add(this.progress); + this.progress.lineStyle(1, 0xffffff, 1); + this.txtProgress = this.scene.add.bitmapText(0, (this.scene.game.config.height * -0.4) + 38, "uiFont", "", 14, 0).setOrigin(0.5).setLetterSpacing(0); + this.container.add(this.txtProgress); + + //tacho + this.tachoContainer = this.scene.add.container(); + this.tachoContainer.depth = 9998; + this.container.add(this.tachoContainer); + + this.txtTachoSpd = this.scene.add.bitmapText((this.scene.game.config.width * -0.5) + 16 + 90, (this.scene.game.config.height * 0.4) + 12, "uiFont", "0000 SPD", 14, 0).setOrigin(1, 0.5).setLetterSpacing(0); + this.txtTachoSpd.depth = 9999; + this.tachoContainer.add(this.txtTachoSpd); + + //INFO without border looks somehow better, but also it does read less good against some tunnnel textures + //this.tachoBorder = this.scene.add.sprite((this.scene.game.config.width * -0.5) + 16, (this.scene.game.config.height * 0.4), "atlasUi", "sprUiTunnelTachoBorder"); + //this.tachoBorder.setOrigin(0, 0.5); + //this.tachoBorder.depth = 9999; + //this.tachoContainer.add(this.tachoBorder); + this.tachoNeedleContainer = this.scene.add.container(); + this.tachoContainer.add(this.tachoNeedleContainer); + this.tachoOverspeed = this.scene.add.sprite((this.scene.game.config.width * -0.5) + 16, (this.scene.game.config.height * 0.4), "atlasUi", "sprUiTunnelTachoOverspeed"); + this.tachoOverspeed.setOrigin(0, 0.5); + this.tachoOverspeed.depth = 9998; + this.tachoOverspeed.setTint(0xff004d); + this.tachoNeedleContainer.add(this.tachoOverspeed); + this.tachoHighlight = this.scene.add.sprite((this.scene.game.config.width * -0.5) + 16, (this.scene.game.config.height * 0.4), "atlasUi", "sprUiTunnelTacho"); + this.tachoHighlight.setOrigin(0, 0.5); + this.tachoHighlight.depth = 9999; + this.tachoNeedleContainer.add(this.tachoHighlight); + this.tachoMaskImage = this.scene.add.image((this.scene.game.config.width * -0.5) + 16, (this.scene.game.config.height * 0.4), "atlasUi", "sprUiTunnelTachoMask"); + this.tachoMaskImage.setOrigin(0, 0.5); + this.tachoMaskImage.setVisible(false); + this.tachoMaskImage.depth = 9999; + this.tachoContainer.add(this.tachoMaskImage); + this.tachoMask = this.tachoMaskImage.createBitmapMask(); + this.tachoNeedleContainer.setMask(this.tachoMask); + + + //middle pitch thingy + this.pitchContainer = this.scene.add.container(); + this.pitchContainer.depth = 9999; + this.pitchPosY = 32; + //this.container.add(this.pitchContainer); //todo: this somehow just hides the pitch container? if I add it, the mouse hand cursor is visible + + this.pitchYL = this.scene.add.sprite(-16, this.pitchPosY, "atlasUi", "sprUiTunnelTarget03Hor"); + this.pitchYL.depth = 9999; + this.pitchYR = this.scene.add.sprite(16, this.pitchPosY, "atlasUi", "sprUiTunnelTarget03Hor"); + this.pitchYR.setScale(-1, 1); + this.pitchYR.depth = 9999; + this.pitchContainer.add(this.pitchYL); + this.pitchContainer.add(this.pitchYR); + + this.pitchXL = this.scene.add.sprite(-32, this.pitchPosY, "atlasUi", "sprUiTunnelTarget00"); + this.pitchXL.setOrigin(1, 0.5); + this.pitchXL.depth = 9999; + this.pitchXR = this.scene.add.sprite(32, this.pitchPosY, "atlasUi", "sprUiTunnelTarget00"); + this.pitchXR.setOrigin(1, 0.5); + this.pitchXR.setScale(-1, 1); + this.pitchXR.depth = 9999; + this.pitchContainer.add(this.pitchXL); + this.pitchContainer.add(this.pitchXR); + + this.pitchLimit = this.scene.add.sprite(0, this.pitchPosY + 64, "atlasUi", "sprUiTunnelDanger04"); + this.pitchLimit.depth = 9999; + this.pitchContainer.add(this.pitchLimit); + this.pitchLimitMaskImage = this.scene.add.image(0, this.pitchPosY, "atlasUi", "sprUiTunnelDangerMask"); + this.pitchLimitMaskImage.setVisible(false); + this.pitchLimitMaskImage.depth = 9999; + this.pitchContainer.add(this.pitchLimitMaskImage); + this.pitchLimitMask = this.pitchLimitMaskImage.createBitmapMask(); + this.pitchLimit.setMask(this.pitchLimitMask); + + this.ships = []; + } + + update(_delta) { + if (this.hidden === false) { + + //show cockpit + if (this.level.playerShip.camera === 1) { + this.cockpit.alpha = 1; + } else { + this.cockpit.alpha = 0; + } + + //rumble + if (this.rumble.time > 0) { + this.rumble.time -= this.scene.dt; + this.container.x = -this.rumble.intensity.x + (Math.random() * (this.rumble.intensity.x * 2)); + this.container.y = -this.rumble.intensity.y + (Math.random() * (this.rumble.intensity.y * 2)); + } + + //if(this.scrape.isScraping === true){ + if (this.level.playerShip.scraping === true) { + //this.vignetteScrape.alpha = Math.random() * Math.min(1, (3000 / this.level.playerShip.scrapingTime)); + this.vignetteScrape.alpha = 0.5 + this.vignetteScrape.y = Math.random() * (1 * this.level.playerShip.speed); + this.rumble.time = 1; + this.rumble.intensity.x = this.level.playerShip.speed / this.level.playerShip.speedMax; + this.rumble.intensity.y = (this.level.playerShip.speed / this.level.playerShip.speedMax) * 2; + } else { + this.vignetteScrape.alpha = 0; + } + + if (this.racerReactionUpcount > 0) { + this.racerReactionUpcount -= this.scene.dt; + if (this.racerReactionUpcount < 0) { + this.racerReactionUpcount = 0; + } + } + // TODO why does alpha blip to 1 in tutorial? + this.racerReaction.alpha = Math.min(1, this.racerReactionUpcount); + this.racerReactionName.alpha = Math.min(1, this.racerReactionUpcount); + + this.vignetteHeat.alpha = Math.log(1.1 - (this.level.playerShip.temp / 999)) * -0.5; + + this.txtWarning.setText(""); + //slipstream draw + if (this.level.playerShip.slipstreamTarget === null) { + //todo: idk, alpha does not work somehow, it just blinks out of existance later + /*this.slipstream.alpha -= 0.01 * this.scene.dt; + if(this.slipstream.alpha <= 0){ + this.slipstream.clear(); + }*/ + this.slipstream.clear(); + this.txtWarning.setText(""); + } + if (this.level.playerShip.slipstreaming === true) { + if (this.level.playerShip.slipstreamTarget !== null) { + this.slipstreamAngle += 0.025 * this.scene.dt; + //this.slipstream.alpha = 0.1; + let d2dTarget = this.level.playerShip.slipstreamTarget.getScreenBounds(); + let d2dMid = { + x: d2dTarget.p0.x + ((d2dTarget.p1.x - d2dTarget.p0.x) * 0.5), + y: d2dTarget.p0.y + ((d2dTarget.p1.y - d2dTarget.p0.y) * 0.5) + } + let d2dLen = (d2dTarget.p1.x - d2dTarget.p0.x) * 1; + let d2dPoints = []; + for (let i = 0; i < Math.PI * 2; i += Math.PI * 0.5) { + d2dPoints.push({ + x: d2dMid.x + (Math.cos(i + this.slipstreamAngle) * d2dLen), + y: d2dMid.y + (Math.sin(i + this.slipstreamAngle) * d2dLen) + }) + } + + this.slipstream.clear(); + this.slipstream.beginPath(); + this.slipstream.moveTo(d2dPoints[0].x, d2dPoints[0].y); + this.slipstream.lineTo(d2dPoints[1].x, d2dPoints[1].y); + this.slipstream.moveTo(d2dPoints[1].x, d2dPoints[1].y); + this.slipstream.lineTo(d2dPoints[2].x, d2dPoints[2].y); + this.slipstream.moveTo(d2dPoints[2].x, d2dPoints[2].y); + this.slipstream.lineTo(d2dPoints[3].x, d2dPoints[3].y); + this.slipstream.moveTo(d2dPoints[3].x, d2dPoints[3].y); + this.slipstream.lineTo(d2dPoints[0].x, d2dPoints[0].y); + this.slipstream.strokePath(); + + this.txtWarning.setText("\\\\\\ SLIPSTREAMING ///"); + } + } + //TODO: this is a bit meh also the warning stays on only for a short time, the exact data, and not like slipstreamin with a fade + if (this.level.situation.actions.slipstreamed.who !== "") { + this.txtWarning.setText("!!! BEING SLIPSTREAMED !!!"); + } + + if (this.level.playerShip.temp >= 900) { + this.txtWarning.setText("!!! OVERHEATING !!!"); + } + + //radar + if (OPTIONS.config.collisionRadar === 0 && this.dangerCircleContainer.alpha === 1) { + this.dangerCircleContainer.alpha = 0; + } else if (OPTIONS.config.collisionRadar === 1 && this.dangerCircleContainer.alpha === 0) { + this.dangerCircleContainer.alpha = 1; + } + + //progress (especially tutorial) + if (this.level.raceMode === this.level.raceModes.tutorial) { + if (this.level.tutorialStep === 1 || this.level.tutorialStep === 3 || this.level.tutorialStep === 5) { + this.progress.clear(); + this.progress.lineStyle(1, 0xffffff, 1); + this.progress.beginPath(); + this.progress.moveTo(-100, (this.scene.game.config.height * -0.4) + 24); + this.progress.lineTo(100, (this.scene.game.config.height * -0.4) + 24); + this.progress.strokePath(); + this.progress.lineStyle(3, 0xffffff, 1); + this.progress.beginPath(); + this.progress.moveTo(-86, (this.scene.game.config.height * -0.4) + 24); + this.progress.lineTo(-86 + (172 * (this.level.tutorialHoldVar / this.level.tutorialHoldVarMax)), (this.scene.game.config.height * -0.4) + 24); + this.progress.strokePath(); + } else { + this.progress.clear(); + } + } + + //normal draw + let linePart = this.level.trackBuilder.spline.length > 0 ? (this.scene.game.config.height - 32) / this.level.trackBuilder.spline.length : 1; + for (let s of this.ships) { + // + //console.log(s.shipManager.splineId * linePart) + s.sprTarget.x = Math.floor(this.scene.game.config.width * 0.5) - 16.5; + s.sprTarget.y = Math.floor(this.scene.game.config.height * 0.5) - 16 - Math.floor(s.shipManager.splineId * linePart); + s.txtName.x = Math.floor(this.scene.game.config.width * 0.5) - 16.5 - 16; + s.txtName.y = s.sprTarget.y; + if (s.txtName.alpha < 1) { + s.txtName.alpha += 0.1 + }; + for (let o of this.ships) { + if (s.txtName.y <= (o.txtName.y + 7) && s.txtName.y >= (o.txtName.y - 7)) { + if (s.shipManager.splineId < o.shipManager.splineId) { + s.txtName.alpha -= 0.1; + } else { + o.txtName.alpha -= 0.1; + s.txtName.alpha += 0.1; + } + if (s.shipManager.isPlayer === true) { + o.txtName.alpha -= 0.1; + } + } + } + if (s.shipManager.isPlayer === true) { + s.txtName.alpha = 1; + + //update reticle + //this.pitchX.x = this.scene.hand.pos.x; + //this.pitchY.y = this.scene.hand.pos.y; + this.pitchYL.y = this.pitchPosY + (s.shipManager.pitch.current * 32); + this.pitchYR.y = this.pitchPosY + (s.shipManager.pitch.current * 32); + } + s.txtName.alpha = Math.max(0, Math.min(s.txtName.alpha, 1)); + } + + } + } + + addReaction(_atlas, _texture, _character) { + if (this.racerReactionUpcount <= 0 && this.hidden === false) { + this.racerReaction.setTexture(_atlas, _texture); + this.racerReaction.alpha = 1; + this.racerReactionUpcount = 300; + + this.racerReactionName.setText(_character.name); + this.racerReactionName.alpha = 1; + } + } + + registerShip(_shipManager) { + this.ships.push({ + shipManager: _shipManager, + //line: this.scene.add.graphics(0, 0), + txtName: this.scene.add.bitmapText(0, 0, "uiFont", _shipManager.name, 14, 0), + txtPlace: this.scene.add.bitmapText(0, 0, "uiFont", "0", 14, 0), + sprFace: null, + sprTarget: null//this.scene.add.sprite(0, 0, "atlasUi", "sprUiTrackLineBike") + }); + + let s = this.ships[this.ships.length - 1]; + s.txtName.setOrigin(1, 0.5); + s.txtName.setLetterSpacing(0); + s.txtName.alpha = 1; + this.container.add(s.txtName); + s.txtPlace.setOrigin(0, 0.5); + s.txtPlace.setLetterSpacing(0); + s.txtPlace.alpha = 0; + //this.container.add(s.txtPlace); + /* + s.line.lineStyle(1, 0xffffff, 1);//0x00e436 + s.line.beginPath(); + s.line.moveTo(-8, 0); + s.line.lineTo(8, 0); + s.line.strokePath(); + */ + if (s.shipManager.isAI === true) { + s.sprTarget = this.scene.add.sprite(0, 0, "atlasUi", "sprUiTrackLineBike"); + } else { + s.sprTarget = this.scene.add.sprite(0, 0, "atlasUi", "sprUiTrackLinePlayer"); + } + s.sprTarget.setOrigin(1, 0.5); + this.container.add(s.sprTarget); + } + + toggleVisibility() { + if (this.hidden === true) { + OPTIONS.config.hideUI = false; + this.show(); + } else { + this.hide(); + OPTIONS.config.hideUI = true; + } + } + + show() { + if (this.hidden === true && OPTIONS.config.hideUI === false) { + /* + this.txtHelper.alpha = 1; + this.txtLower.alpha = 1; + this.txtDelta.alpha = 1; + this.txtBestLapTime.alpha = 1; + this.txtLastLapTime.alpha = 1; + this.txtLapTime.alpha = 1; + + this.pitchXL.alpha = 1; + this.pitchXR.alpha = 1; + this.pitchYL.alpha = 1; + this.pitchYR.alpha = 1; + this.pitchLimit.alpha = 1; + + this.lineMap.alpha = 1; + for(let s of this.ships){ + s.txtName.alpha = 1; + //s.txtPlace.alpha = 1; + if(s.sprFace !== null){ + s.sprFace.alpha = 1; + } + s.sprTarget.alpha = 1; + } + */ + this.container.each((_el) => { + _el.alpha = 1; + }); + this.pitchContainer.each((_el) => { + _el.alpha = 1; + }); + + this.txtCountdown.alpha = 0; + if (this.level.countdown.step <= 4) { + this.txtCountdown.alpha = 1; + } + this.hidden = false; + } + } + + hide() { + if (this.hidden === false && OPTIONS.config.hideUI === false) { + this.container.each((_el) => { + _el.alpha = 0; + }); + this.pitchContainer.each((_el) => { + _el.alpha = 0; + }); + /* + this.txtHelper.alpha = 0; + this.txtLower.alpha = 0; + this.txtDelta.alpha = 0; + this.txtBestLapTime.alpha = 0; + this.txtLastLapTime.alpha = 0; + this.txtLapTime.alpha = 0; + + this.pitchXL.alpha = 0; + this.pitchXR.alpha = 0; + this.pitchYL.alpha = 0; + this.pitchYR.alpha = 0; + this.pitchLimit.alpha = 0; + + this.lineMap.alpha = 0; + for(let s of this.ships){ + s.txtName.alpha = 0; + s.txtPlace.alpha = 0; + if(s.sprFace !== null){ + s.sprFace.alpha = 0; + } + s.sprTarget.alpha = 0; + } + this.txtCountdown.alpha = 0; + */ + + this.hidden = true; + } + } + + destroy() { + this.container.each((_el) => { + _el.destroy(); + }); + this.pitchContainer.each((_el) => { + _el.destroy(); + }); + this.pitchContainer.destroy(); + this.container.destroy(); + + /* + this.txtHelper.destroy(); + this.txtDelta.destroy(); + this.txtBestLapTime.destroy(); + this.txtLapTime.destroy(); + this.pitchXL.destroy(); + this.pitchXR.destroy(); + this.pitchYL.destroy(); + this.pitchYR.destroy(); + this.pitchLimit.destroy(); + this.pitchLimitMask.destroy(); + this.pitchLimitMaskImage.destroy(); + this.lineMap.destroy(); + this.txtCountdown.destroy(); + */ + } +} diff --git a/src/ui/slider.js b/src/ui/slider.js new file mode 100755 index 0000000..a8e7bad --- /dev/null +++ b/src/ui/slider.js @@ -0,0 +1,412 @@ +export class SliderHorizontal{ + constructor(_scene, _pos, _start, _width) { + this.scene = _scene; + this.pos = _pos; + this.start = _start; + this.width = _width; + this.autoReturn = false; + this.margin = 15; + + this.colors = { + out: 0xfff1e8, + over: 0x29adff, + on: 0x00e436, + off: 0xad2900 + } + + this.states = { + out: 0, + over: 1, + on: 2 + } + this.state = this.states.out; + this.active = false; + this.hovering = false; + this.value = 0; + + this.releaseFunc = () => { }; + this.changeFunc = () => { }; + this.minFunc = () => { }; + this.maxFunc = () => { }; + + this.sliderEndRight = this.scene.add.sprite(this.pos.x + (this.width * 0.5) - 8, this.pos.y, "atlasUi", "sprSliderRight00"); + this.sliderEndRight.setTintFill(0xfff1e8); + this.sliderEndLeft = this.scene.add.sprite(this.pos.x - (this.width * 0.5) + 8, this.pos.y, "atlasUi", "sprSliderLeft00"); + this.sliderEndLeft.setTintFill(0xfff1e8); + + this.range = Phaser.Math.Distance.Between(this.sliderEndLeft.x + this.margin, 0, this.sliderEndRight.x - this.margin, 0); + this.sliderPos = { + x: this.sliderEndLeft.x + (this.range * this.start), + y: this.pos.y + } + this.sliderTarget = { + follow: false, + x: 0, + y: 0 + } + + this.sliderLights = []; + for (let i = 0; i <= this.range; i += 12) { + this.sliderLights.push(this.scene.add.sprite(this.pos.x, this.pos.y, "atlasUi", "sprSliderHighlight00")); + } + + this.slider = this.scene.add.sprite(this.sliderPos.x, this.sliderPos.y, "atlasUi", "sprBtnSlider00"); + this.slider.setTintFill(0x00e436); + + this.colorInState(this.state); + } + + update() { + //if (this.slider.getBounds().contains(this.scene.input.activePointer.worldX, this.scene.input.activePointer.worldY)) { + if (this.slider.getBounds().contains(this.scene.hand.pos.x, this.scene.hand.pos.y)) { + if (this.scene.hand.pressed === false) { + this.switchState(this.states.over); + this.active = false; + if(this.hovering === false){ + this.hovering = true; + this.scene.soundManager.playSound(this.scene.soundManager.menuSelectSound); + } + } + if (this.scene.hand.justPressed === true) { + this.switchState(this.states.on); + this.sliderTarget.follow = true; + this.active = true; + } + if (this.scene.hand.justReleased === true) { + this.sliderTarget.follow = false; + this.releaseFunc(); + this.active = false; + } else { + this.changeFunc(); + } + } else { + if (this.active === false) { + this.switchState(this.states.out); + this.hovering = false; + } else { + this.changeFunc(); + if (this.scene.hand.justReleased === true) { + this.hovering = false; + this.sliderTarget.follow = false; + this.active = false; + if (this.slider.x >= this.sliderEndRight.x - this.margin) { + //releasing on top + this.releaseFunc(); + this.maxFunc(); + } else if (this.slider.x <= this.sliderEndLeft.x + this.margin) { + //releasing on bottom + this.releaseFunc(); + this.minFunc(); + } else { + //releasing anywhere + this.releaseFunc(); + } + } + } + } + + for (let l of this.sliderLights) { + if (l.x < this.slider.x) { + l.setTintFill(0x00e436); + } else { + l.setTintFill(0x000000); + } + } + + if (this.sliderTarget.follow === true) { + //this.sliderPos.x = Math.min(this.sliderEndRight.x - this.margin, Math.max(this.scene.input.activePointer.worldX, this.sliderEndLeft.x + this.margin)); + this.sliderPos.x = Math.min(this.sliderEndRight.x - this.margin, Math.max(this.scene.hand.pos.x, this.sliderEndLeft.x + this.margin)); + this.slider.x = this.sliderPos.x; + } else { + if (this.autoReturn === true) { + if (this.slider.x > this.sliderEndLeft.x + this.margin) { + this.sliderPos.x -= this.range * 0.01; + } else { + this.sliderPos.x = this.sliderEndLeft.x + this.margin; + } + this.slider.x = this.sliderPos.x; + } + } + + this.value = Phaser.Math.Distance.Between(this.sliderEndLeft.x + this.margin, 0, this.sliderPos.x, 0) / this.range; + } + + setTo(_amt = 0){ + this.sliderPos.x = this.sliderEndLeft.x + this.margin + (this.range * _amt); + this.slider.x = this.sliderPos.x; + this.value = Phaser.Math.Distance.Between(this.sliderEndLeft.x + this.margin, 0, this.sliderPos.x, 0) / this.range; + this.releaseFunc(); + } + + switchState(_state) { + if (this.state !== _state) { + this.state = _state; + this.colorInState(this.state); + } + } + + colorInState(_state) { + switch (this.state) { + case this.states.out: + this.slider.setTintFill(this.colors.out); + break; + case this.states.over: + this.slider.setTintFill(this.colors.over); + break; + case this.states.on: + this.slider.setTintFill(this.colors.on); + break; + default: + break; + } + } + + move(_x, _y) { + this.pos.x = _x; + this.pos.y = _y; + + this.sliderEndLeft.x = this.pos.x - (this.width * 0.5) + 8; + this.sliderEndLeft.y = this.pos.y; + this.sliderEndRight.x = this.pos.x + (this.width * 0.5) - 8; + this.sliderEndRight.y = this.pos.y; + + for (let [i, l] of this.sliderLights.entries()) { + l.x = this.sliderEndLeft.x + this.margin + (i * 12); + l.y = this.sliderEndLeft.y; + } + + this.range = Phaser.Math.Distance.Between(this.sliderEndLeft.x + this.margin, 0, this.sliderEndRight.x - this.margin, 0); + this.sliderPos = { + x: this.sliderEndLeft.x + this.margin + (this.range * this.start), + y: this.pos.y + } + + this.sliderPos.y = this.pos.y; + this.slider.x = this.sliderPos.x; + this.slider.y = this.sliderPos.y; + } + + addToContainer(_container){ + for (let [i, l] of this.sliderLights.entries()) { + _container.add(l); + } + _container.add(this.sliderEndLeft); + _container.add(this.sliderEndRight); + _container.add(this.slider); + } + + destroy() { + this.sliderEndLeft.destroy(); + this.sliderEndRight.destroy(); + this.slider.destroy(); + + for (let l of this.sliderLights) { + l.destroy(); + } + } +} + +export class SliderVertical { + constructor(_scene, _pos, _start, _height) { + this.scene = _scene; + this.pos = _pos; + this.start = _start; + this.height = _height; + this.autoReturn = false; + this.margin = 15; + + this.colors = { + out: 0xfff1e8, + over: 0x29adff, + on: 0x00e436, + off: 0xad2900 + } + + this.states = { + out: 0, + over: 1, + on: 2 + } + this.state = this.states.out; + this.active = false; + this.hovering = false; + this.value = 0; + + this.releaseFunc = () => {}; + this.changeFunc = () => {}; + this.minFunc = () => {}; + this.maxFunc = () => {}; + + this.sliderEndTop = this.scene.add.sprite(this.pos.x, this.pos.y - (this.height * 0.5) + 8, "atlasUi", "sprSliderLeft00"); + this.sliderEndTop.angle = 90; + this.sliderEndTop.setTintFill(0xfff1e8); + this.sliderEndBottom = this.scene.add.sprite(this.pos.x, this.pos.y + (this.height * 0.5) - 8, "atlasUi", "sprSliderRight00"); + this.sliderEndBottom.angle = 90; + this.sliderEndBottom.setTintFill(0xfff1e8); + + this.range = Phaser.Math.Distance.Between(0, this.sliderEndTop.y + this.margin, 0, this.sliderEndBottom.y - this.margin); + this.sliderPos = { + x: this.pos.x, + y: this.sliderEndBottom.y - (this.range * this.start) + } + this.sliderTarget = { + follow: false, + x: 0, + y: 0 + } + + this.sliderLights = []; + for(let i = 0 ; i <= this.range ; i += 12){ + this.sliderLights.push(this.scene.add.sprite(0, 0, "atlasUi", "sprSliderHighlight00")); + this.sliderLights[this.sliderLights.length - 1].angle = 90; + } + + this.slider = this.scene.add.sprite(this.sliderPos.x, this.sliderPos.y, "atlasUi", "sprBtnSlider00"); + this.slider.angle = 90; + this.slider.setTintFill(0x00e436); + + this.colorInState(this.state); + } + + update(){ + //if (this.slider.getBounds().contains(this.scene.input.activePointer.worldX, this.scene.input.activePointer.worldY)) { + if (this.slider.getBounds().contains(this.scene.hand.pos.x, this.scene.hand.pos.y)) { + if (this.scene.hand.pressed === false) { + this.switchState(this.states.over); + this.active = false; + if(this.hovering === false){ + this.hovering = true; + this.scene.soundManager.playSound(this.scene.soundManager.menuSelectSound); + } + } + if (this.scene.hand.justPressed === true) { + this.switchState(this.states.on); + this.sliderTarget.follow = true; + this.active = true; + } + if (this.scene.hand.justReleased === true) { + this.sliderTarget.follow = false; + this.releaseFunc(); + this.active = false; + } else { + this.changeFunc(); + } + } else { + if(this.active === false){ + this.switchState(this.states.out); + this.hovering = false; + } else { + this.changeFunc(); + if (this.scene.hand.justReleased === true) { + this.hovering = false; + this.sliderTarget.follow = false; + this.active = false; + if(this.slider.y <= this.sliderEndTop.y + this.margin){ + //releasing on top + this.releaseFunc(); + this.maxFunc(); + }else if(this.slider.y >= this.sliderEndBottom.y - this.margin){ + //releasing on bottom + this.releaseFunc(); + this.minFunc(); + }else{ + //releasing anywhere + this.releaseFunc(); + } + } + } + } + + for(let l of this.sliderLights){ + if (l.y > this.slider.y) { + l.setTintFill(0x00e436); + } else { + l.setTintFill(0x000000); + } + } + + if(this.sliderTarget.follow === true){ + //this.sliderPos.y = Math.min(this.sliderEndBottom.y - this.margin, Math.max(this.scene.input.activePointer.worldY, this.sliderEndTop.y + this.margin)); + this.sliderPos.y = Math.min(this.sliderEndBottom.y - this.margin, Math.max(this.scene.hand.pos.y, this.sliderEndTop.y + this.margin)); + this.slider.y = this.sliderPos.y; + }else{ + if(this.autoReturn === true){ + if (this.slider.y < this.sliderEndBottom.y - this.margin){ + this.sliderPos.y += this.range * 0.01; + }else{ + this.sliderPos.y = this.sliderEndBottom.y - this.margin; + } + this.slider.y = this.sliderPos.y; + } + } + + this.value = Phaser.Math.Distance.Between(0, this.sliderPos.y, 0, this.sliderEndBottom.y - this.margin)/this.range; + } + + switchState(_state) { + if (this.state !== _state) { + this.state = _state; + this.colorInState(this.state); + } + } + + colorInState(_state) { + switch (this.state) { + case this.states.out: + this.slider.setTintFill(this.colors.out); + break; + case this.states.over: + this.slider.setTintFill(this.colors.over); + break; + case this.states.on: + this.slider.setTintFill(this.colors.on); + break; + default: + break; + } + } + + move(_x, _y){ + this.pos.x = _x; + this.pos.y = _y; + + this.sliderEndTop.x = this.pos.x; + this.sliderEndTop.y = this.pos.y - (this.height * 0.5) + 8; + this.sliderEndBottom.x = this.pos.x; + this.sliderEndBottom.y = this.pos.y + (this.height * 0.5) - 8; + + for(let [i, l] of this.sliderLights.entries()){ + l.x = this.sliderEndBottom.x; + l.y = this.sliderEndBottom.y - this.margin - (i * 12); + } + + this.range = Phaser.Math.Distance.Between(0, this.sliderEndTop.y+this.margin, 0, this.sliderEndBottom.y-this.margin); + this.sliderPos = { + x: this.pos.x, + y: this.sliderEndBottom.y - this.margin - (this.range * this.start) + } + + this.sliderPos.x = this.pos.x; + this.slider.x = this.sliderPos.x; + this.slider.y = this.sliderPos.y; + } + + addToContainer(_container){ + for (let [i, l] of this.sliderLights.entries()) { + _container.add(l); + } + _container.add(this.sliderEndLeft); + _container.add(this.sliderEndRight); + _container.add(this.slider); + } + + destroy(){ + this.sliderEndTop.destroy(); + this.sliderEndBottom.destroy(); + this.slider.destroy(); + + for(let l of this.sliderLights){ + l.destroy(); + } + } +}