From e5b75945207642f4b9d78aacffee534d377ec0f8 Mon Sep 17 00:00:00 2001 From: POW_Boy1 Date: Thu, 7 May 2026 17:59:32 -0400 Subject: [PATCH 1/5] Add GitHub Actions workflow for GitHub Pages deployment This workflow automates the deployment of static content to GitHub Pages on pushes to the main branch or manually via the Actions tab. --- .github/workflows/static.yml | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/workflows/static.yml diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml new file mode 100644 index 0000000..460f782 --- /dev/null +++ b/.github/workflows/static.yml @@ -0,0 +1,43 @@ +# Simple workflow for deploying static content to GitHub Pages +name: Deploy static content to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: ["main"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + # Single deploy job since we're just deploying + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Pages + uses: actions/configure-pages@v5 + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + # Upload entire repository + path: '.' + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v5 From a7cc85844472a6cd210f65a5cf8658904ccf98ce Mon Sep 17 00:00:00 2001 From: POWBoy1 Date: Thu, 7 May 2026 18:30:45 -0400 Subject: [PATCH 2/5] LDM --- README.md | 1 + assets/scripts/core/game-scene.js | 244 ++++++++++++++++-------------- assets/scripts/core/level.js | 96 ++++++------ assets/scripts/core/main.js | 4 +- assets/scripts/core/player.js | 14 +- assets/scripts/core/triggers.js | 70 ++++----- assets/scripts/utils/config.js | 14 +- 7 files changed, 238 insertions(+), 205 deletions(-) diff --git a/README.md b/README.md index 44a7a05..8b5f5ed 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ - **Different Gamemodes** - Multiple working gamemodes such as the Ball, Wave, Cube, UFO, Mini portals and Speed portals! - **Practice Mode** - Practice mode is still very buggy at the time. Currently, you can press Z to add a checkpoint, or X to delete a checkpoint, and P to enable and disable Practice mode! - **Extra Settingss** - You can enable and disable Noclip or Show Hitboxes from the pause menu in a level, along with other settings, like the level percentage! +- **Low Detail Mode (LDM)** - Automatically enables on low-performance devices to improve frame rate by disabling particle effects and optimizing rendering. Can be manually controlled via URL parameter (?ldm) or localStorage. ## What we hope to see added in the future: - **All Gamemodes** - This will allow every official main level to be playable, along with others that require currently un-implemented gamemodes. diff --git a/assets/scripts/core/game-scene.js b/assets/scripts/core/game-scene.js index c9180b7..633bab9 100644 --- a/assets/scripts/core/game-scene.js +++ b/assets/scripts/core/game-scene.js @@ -169,31 +169,33 @@ class GameScene extends Phaser.Scene { this._level.createEndPortal(this); this._glitterCenterX = 0; this._glitterCenterY = T; - this._glitterEmitter = this.add.particles(0, 0, "GJ_WebSheet", { - frame: "square.png", - speed: 0, - scale: { - start: 0.375, - end: 0 - }, - alpha: { - start: 1, - end: 0 - }, - lifespan: { - min: 200, - max: 1800 - }, - frequency: 60, - blendMode: S, - tint: window.mainColor, - emitting: false, - emitCallback: _0x3c2a3e => { - _0x3c2a3e.x = this._glitterCenterX + (Math.random() * 2 - 1) * (screenWidth / 1.8); - _0x3c2a3e.y = this._glitterCenterY + (Math.random() * 2 - 1) * 320; - } - }); - this._level.additiveContainer.add(this._glitterEmitter); + if (!window.lowDetailMode) { + this._glitterEmitter = this.add.particles(0, 0, "GJ_WebSheet", { + frame: "square.png", + speed: 0, + scale: { + start: 0.375, + end: 0 + }, + alpha: { + start: 1, + end: 0 + }, + lifespan: { + min: 200, + max: 1800 + }, + frequency: 60, + blendMode: S, + tint: window.mainColor, + emitting: false, + emitCallback: _0x3c2a3e => { + _0x3c2a3e.x = this._glitterCenterX + (Math.random() * 2 - 1) * (screenWidth / 1.8); + _0x3c2a3e.y = this._glitterCenterY + (Math.random() * 2 - 1) * 320; + } + }); + this._level.additiveContainer.add(this._glitterEmitter); + } this._bg.setTint(this._colorManager.getHex(fs)); this._level.setGroundColor(this._colorManager.getHex(gs)); this._level.additiveContainer.setVisible(false); @@ -278,33 +280,35 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" this._makeBouncyButton(this._menuNewgroundsBtn, 0.8, () => { this._buildNewgroundsPopup(); }, () => this._menuActive && !this._newgroundsPopup); - this._menuGlitter = this.add.particles(0, 0, "GJ_WebSheet", { - frame: "square.png", - speed: 0, - scale: { - start: 0.5, - end: 0 - }, - alpha: { - start: 0.6, - end: 0.2 - }, - lifespan: { - min: 1000, - max: 2000 - }, - frequency: 35, - blendMode: S, - tint: 20670, - x: { - min: -130, - max: 130 - }, - y: { - min: -100, - max: 100 - } - }).setScrollFactor(0).setDepth(29); + if (!window.lowDetailMode) { + this._menuGlitter = this.add.particles(0, 0, "GJ_WebSheet", { + frame: "square.png", + speed: 0, + scale: { + start: 0.5, + end: 0 + }, + alpha: { + start: 0.6, + end: 0.2 + }, + lifespan: { + min: 1000, + max: 2000 + }, + frequency: 35, + blendMode: S, + tint: 20670, + x: { + min: -130, + max: 130 + }, + y: { + min: -100, + max: 100 + } + }).setScrollFactor(0).setDepth(29); + } this._playBtn = this.add.image(0, 0, "GJ_WebSheet", "GJ_playBtn_001.png").setScrollFactor(0).setDepth(30).setInteractive(); this._playBtnPressed = false; this._makeBouncyButton(this._playBtn, 1, () => { @@ -2262,10 +2266,12 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" this._restartLevel(); } toggleGlitter(_0x34c21a) { - if (_0x34c21a) { - this._glitterEmitter.start(); - } else { - this._glitterEmitter.stop(); + if (this._glitterEmitter) { + if (_0x34c21a) { + this._glitterEmitter.start(); + } else { + this._glitterEmitter.stop(); + } } } _setParticleTimeScale(timeScale) { @@ -3453,7 +3459,9 @@ _buildSettingsPopup() { this._player2.setShipVisible(false); this._player2.setBallVisible(false); this._player2.setWaveVisible(false); - this._glitterEmitter.stop(); + if (this._glitterEmitter) { + this._glitterEmitter.stop(); + } let speedKey = parseInt(window.settingsMap["kA4"] || "0"); if (speedKey == 0) { playerSpeed = SpeedPortal.ONE_TIMES; @@ -4445,38 +4453,40 @@ _applyMirrorEffect() { } }); const _0x2884ff = [window.mainColor, 16777215]; - for (let _0x5f16c8 = 0; _0x5f16c8 < 2; _0x5f16c8++) { - this.add.particles(_0x56628c, 250, "GJ_WebSheet", { - frame: "square.png", - speed: { - min: 300, - max: 700 - }, - angle: { - min: 0, - max: 360 - }, - scale: { - start: 0.4, - end: 0.13 - }, - lifespan: { - min: 0, - max: 1000 - }, - quantity: 50, - stopAfter: 200, - blendMode: S, - tint: _0x2884ff[_0x5f16c8], - x: { - min: -800, - max: 800 - }, - y: { - min: -80, - max: 80 - } - }).setScrollFactor(0).setDepth(59); + if (!window.lowDetailMode) { + for (let _0x5f16c8 = 0; _0x5f16c8 < 2; _0x5f16c8++) { + this.add.particles(_0x56628c, 250, "GJ_WebSheet", { + frame: "square.png", + speed: { + min: 300, + max: 700 + }, + angle: { + min: 0, + max: 360 + }, + scale: { + start: 0.4, + end: 0.13 + }, + lifespan: { + min: 0, + max: 1000 + }, + quantity: 50, + stopAfter: 200, + blendMode: S, + tint: _0x2884ff[_0x5f16c8], + x: { + min: -800, + max: 800 + }, + y: { + min: -80, + max: 80 + } + }).setScrollFactor(0).setDepth(59); + } } const _0x2eadf2 = this._level.endXPos - this._cameraX; const _0x380b24 = b(this._endPortalGameY) + this._cameraY; @@ -4990,33 +5000,35 @@ _applyMirrorEffect() { this._audio.playEffect("highscoreGet02"); const _0x1204d3 = _0x4edc03; const _0x96e3b2 = _0x5a0e9 + this._endLayerInternal.y; - this.add.particles(_0x1204d3, _0x96e3b2, "GJ_WebSheet", { - frame: "square.png", - speed: { - min: 200, - max: 600 - }, - angle: { - min: 0, - max: 360 - }, - scale: { - start: 0.5, - end: 0 - }, - alpha: { - start: 1, - end: 0 - }, - lifespan: { - min: 200, - max: 600 - }, - quantity: 30, - stopAfter: 30, - blendMode: S, - tint: 16776960 - }).setScrollFactor(0).setDepth(202); + if (!window.lowDetailMode) { + this.add.particles(_0x1204d3, _0x96e3b2, "GJ_WebSheet", { + frame: "square.png", + speed: { + min: 200, + max: 600 + }, + angle: { + min: 0, + max: 360 + }, + scale: { + start: 0.5, + end: 0 + }, + alpha: { + start: 1, + end: 0 + }, + lifespan: { + min: 200, + max: 600 + }, + quantity: 30, + stopAfter: 30, + blendMode: S, + tint: 16776960 + }).setScrollFactor(0).setDepth(202); + } const _0x43203f = this.add.graphics().setScrollFactor(0).setDepth(202).setBlendMode(S); const _0x403316 = { t: 0 diff --git a/assets/scripts/core/level.js b/assets/scripts/core/level.js index 25c64ac..63bc37d 100644 --- a/assets/scripts/core/level.js +++ b/assets/scripts/core/level.js @@ -1348,51 +1348,53 @@ window.LevelObject = class LevelObject { this._endPortalShine.setTint(window.mainColor); this._endPortalShine.setScale(1, 960 / _0x3e25a9); this.additiveContainer.add(this._endPortalShine); - const _0x58cedb = _0x3b56d4 - 30; - const _0x4f52b7 = { - getRandomPoint: _0x4f04dd => { - const _0x53ec71 = (85 + Math.random() * 190) * Math.PI / 180; - const _0x42e60c = 320 + (Math.random() * 2 - 1) * 80; - _0x4f04dd.x = Math.cos(_0x53ec71) * _0x42e60c; - _0x4f04dd.y = Math.sin(_0x53ec71) * _0x42e60c; - return _0x4f04dd; - } - }; - this._endPortalEmitter = _0x41fbdb.add.particles(_0x58cedb, _0x1c3aea, "GJ_WebSheet", { - frame: "square.png", - lifespan: { - min: 200, - max: 1000 - }, - speed: 0, - scale: { - start: 0.75, - end: 0.125 - }, - alpha: { - start: 1, - end: 0 - }, - tint: window.mainColor, - blendMode: Phaser.BlendModes.ADD, - frequency: 10, - maxParticles: 100, - emitting: true, - emitZone: { - type: "random", - source: _0x4f52b7 - }, - emitCallback: _0x2daff4 => { - const _0x5e30d8 = -_0x2daff4.x; - const _0x17ba71 = -_0x2daff4.y; - const _0x3c5c52 = Math.sqrt(_0x5e30d8 * _0x5e30d8 + _0x17ba71 * _0x17ba71) || 1; - const _0x279521 = (_0x3c5c52 - 20) / (_0x2daff4.life / 1000 || 0.3); - _0x2daff4.velocityX = _0x5e30d8 / _0x3c5c52 * _0x279521; - _0x2daff4.velocityY = _0x17ba71 / _0x3c5c52 * _0x279521; - } - }); - this._endPortalEmitter.setDepth(14); - this.topContainer.add(this._endPortalEmitter); + if (!window.lowDetailMode) { + const _0x58cedb = _0x3b56d4 - 30; + const _0x4f52b7 = { + getRandomPoint: _0x4f04dd => { + const _0x53ec71 = (85 + Math.random() * 190) * Math.PI / 180; + const _0x42e60c = 320 + (Math.random() * 2 - 1) * 80; + _0x4f04dd.x = Math.cos(_0x53ec71) * _0x42e60c; + _0x4f04dd.y = Math.sin(_0x53ec71) * _0x42e60c; + return _0x4f04dd; + } + }; + this._endPortalEmitter = _0x41fbdb.add.particles(_0x58cedb, _0x1c3aea, "GJ_WebSheet", { + frame: "square.png", + lifespan: { + min: 200, + max: 1000 + }, + speed: 0, + scale: { + start: 0.75, + end: 0.125 + }, + alpha: { + start: 1, + end: 0 + }, + tint: window.mainColor, + blendMode: Phaser.BlendModes.ADD, + frequency: 10, + maxParticles: 100, + emitting: true, + emitZone: { + type: "random", + source: _0x4f52b7 + }, + emitCallback: _0x2daff4 => { + const _0x5e30d8 = -_0x2daff4.x; + const _0x17ba71 = -_0x2daff4.y; + const _0x3c5c52 = Math.sqrt(_0x5e30d8 * _0x5e30d8 + _0x17ba71 * _0x17ba71) || 1; + const _0x279521 = (_0x3c5c52 - 20) / (_0x2daff4.life / 1000 || 0.3); + _0x2daff4.velocityX = _0x5e30d8 / _0x3c5c52 * _0x279521; + _0x2daff4.velocityY = _0x17ba71 / _0x3c5c52 * _0x279521; + } + }); + this._endPortalEmitter.setDepth(14); + this.topContainer.add(this._endPortalEmitter); + } this._endPortalGameY = 240; } updateEndPortalY(_0x26f0ab, _0x43c4d1) { @@ -1405,7 +1407,9 @@ window.LevelObject = class LevelObject { const _0x32e645 = b(_0x1be4c3); this._endPortalContainer.y = _0x32e645; this._endPortalShine.y = _0x32e645; - this._endPortalEmitter.y = _0x32e645; + if (this._endPortalEmitter) { + this._endPortalEmitter.y = _0x32e645; + } this._endPortalGameY = _0x1be4c3; } checkColorTriggers(_0x2b00ce) { diff --git a/assets/scripts/core/main.js b/assets/scripts/core/main.js index 4106d94..3682bf4 100644 --- a/assets/scripts/core/main.js +++ b/assets/scripts/core/main.js @@ -44,7 +44,7 @@ const phaserConfig = { height: screenHeight, resolution: 1, fps: { - smoothStep: true + smoothStep: !window.lowDetailMode }, backgroundColor: "#000000", parent: document.body, @@ -52,7 +52,7 @@ const phaserConfig = { windowEvents: false }, render: { - powerPreference: "default" + powerPreference: window.lowDetailMode ? "low-power" : "default" }, scale: { mode: Phaser.Scale.FIT, diff --git a/assets/scripts/core/player.js b/assets/scripts/core/player.js index f824aa2..85b4c5b 100644 --- a/assets/scripts/core/player.js +++ b/assets/scripts/core/player.js @@ -456,6 +456,7 @@ class PlayerObject { } } _initParticles(scene) { + const freq = window.lowDetailMode ? 0 : 1000 / 30; this._particleEmitter = scene.add.particles(0, 0, "GJ_WebSheet", { frame: "square.png", speed: { @@ -475,8 +476,8 @@ class PlayerObject { end: 0 }, gravityY: 600, - frequency: 1000 / 30, - blendMode: "ADD", + frequency: freq, + blendMode: window.lowDetailMode ? "NORMAL" : "ADD", alpha: { start: 1, end: 0 @@ -505,8 +506,8 @@ class PlayerObject { end: 0 }, gravityY: 600, - frequency: 1000 / 30, - blendMode: "ADD", + frequency: freq, + blendMode: window.lowDetailMode ? "NORMAL" : "ADD", tint: { start: 16737280, end: 16711680 @@ -538,8 +539,8 @@ class PlayerObject { end: 0 }, gravityY: 600, - frequency: 1000 / 30, - blendMode: "ADD", + frequency: freq, + blendMode: window.lowDetailMode ? "NORMAL" : "ADD", tint: { start: 16760320, end: 16711680 @@ -633,6 +634,7 @@ class PlayerObject { this._waveTrail.addToContainer(this._gameLayer.container, 9); } _updateParticles(_0xc43238, _0x52b718, _0x5af874) { + if (!this._particleEmitter) return; if (this.p.isDead) { return; } diff --git a/assets/scripts/core/triggers.js b/assets/scripts/core/triggers.js index 7c00285..32e0af9 100644 --- a/assets/scripts/core/triggers.js +++ b/assets/scripts/core/triggers.js @@ -188,38 +188,40 @@ function particleEffect(gameScene, color1 = 16777215, color2 = 16777215) { const xPos = basePos + (screenWidth - 400) * Math.random(); const yPos = basePos + Math.random() * 240; circleEffect(gameScene, xPos, yPos, 40, 140 + Math.random() * 60, 500, true, true, color2); - gameScene.add.particles(xPos, yPos, "GJ_WebSheet", { - frame: "square.png", - speed: { - min: 520, - max: 920 - }, - angle: { - min: 0, - max: 360 - }, - scale: { - start: 0.4, - end: 0.13 - }, - alpha: { - start: 1, - end: 0 - }, - lifespan: { - min: 0, - max: 500 - }, - stopAfter: 25, - blendMode: S, - tint: color1, - x: { - min: -20, - max: 20 - }, - y: { - min: -20, - max: 20 - } - }).setScrollFactor(0).setDepth(57); + if (!window.lowDetailMode) { + gameScene.add.particles(xPos, yPos, "GJ_WebSheet", { + frame: "square.png", + speed: { + min: 520, + max: 920 + }, + angle: { + min: 0, + max: 360 + }, + scale: { + start: 0.4, + end: 0.13 + }, + alpha: { + start: 1, + end: 0 + }, + lifespan: { + min: 0, + max: 500 + }, + stopAfter: 25, + blendMode: S, + tint: color1, + x: { + min: -20, + max: 20 + }, + y: { + min: -20, + max: 20 + } + }).setScrollFactor(0).setDepth(57); + } } diff --git a/assets/scripts/utils/config.js b/assets/scripts/utils/config.js index 9bb07d7..d0e3b95 100644 --- a/assets/scripts/utils/config.js +++ b/assets/scripts/utils/config.js @@ -27,6 +27,18 @@ if (urlParams.has('id')) { window.levelID = urlParams.get('id'); } +// Low Detail Mode for older devices +window.lowDetailMode = localStorage.getItem("lowDetailMode") === "true" || urlParams.has('ldm'); + +// Auto-detect low performance devices +if (!window.lowDetailMode) { + const cores = navigator.hardwareConcurrency || 2; + const memory = navigator.deviceMemory || 4; + const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); + // Enable LDM if less than 4 cores, less than 4GB memory, or mobile device + window.lowDetailMode = cores < 4 || memory < 4 || isMobile; +} + // ------------------------------- function hexToHexadecimal(str) { @@ -65,7 +77,7 @@ const T = 460; function b(y) { return T - y; } -let S = Phaser.BlendModes.ADD; +let S = window.lowDetailMode ? Phaser.BlendModes.NORMAL : Phaser.BlendModes.ADD; let E = Phaser.BlendModes.NORMAL; const fs = 1000; From 79883eb91e621fe9cbb59ebab8f38b63669cdef7 Mon Sep 17 00:00:00 2001 From: POWBoy1 Date: Thu, 7 May 2026 20:57:00 -0400 Subject: [PATCH 3/5] added some stuff Added Slope hitboxes WIP Added Manual Select LDM Added Disable Vsync (Not working) --- assets/scripts/core/game-scene.js | 41 ++++++++++++++++++++++++++++--- assets/scripts/core/level.js | 15 +++++++++++ assets/scripts/core/main.js | 4 +-- assets/scripts/utils/config.js | 5 +++- 4 files changed, 59 insertions(+), 6 deletions(-) diff --git a/assets/scripts/core/game-scene.js b/assets/scripts/core/game-scene.js index 633bab9..15095d1 100644 --- a/assets/scripts/core/game-scene.js +++ b/assets/scripts/core/game-scene.js @@ -2575,6 +2575,29 @@ _buildSettingsPopup() { () => window.solidWave, (v) => window.solidWave = v ); + createToggle(container, column1X, startY + (spacingY * 4), "Low Detail Mode", + () => window.lowDetailMode, + (v) => { + window.lowDetailMode = v; + localStorage.setItem("lowDetailMode", v); + let S = v ? Phaser.BlendModes.NORMAL : Phaser.BlendModes.ADD; + if (this.game && this.game.renderer) { + this.game.renderer.pipelines && this.game.renderer.gl && ( + this.game.renderer.gl.disable(this.game.renderer.gl.BLEND) + ); + } + } + ); + createToggle(container, column1X, startY + (spacingY * 5), "Disable VSync WIP", + () => window.vsyncDisabled, + (v) => { + window.vsyncDisabled = v; + localStorage.setItem("vsyncDisabled", v); + if (this.game && this.game.loop) { + this.game.loop.smoothStep = !v; + } + } + ); }; const buildPage = (idx) => { @@ -2605,7 +2628,9 @@ _buildSettingsPopup() { hitboxTrail: window.showHitboxTrail, showFPS: this._fpsText.visible, solidWaveTrail: window.solidWave, - noclipAccuracy: window.noClipAccuracy + noclipAccuracy: window.noClipAccuracy, + vsyncDisabled: window.vsyncDisabled, + lowDetailMode: window.lowDetailMode }; localStorage.setItem("gd_settings", JSON.stringify(settings)); } @@ -2620,7 +2645,9 @@ _buildSettingsPopup() { hitboxTrail: false, showFPS: false, solidWaveTrail: false, - noclipAccuracy: false + noclipAccuracy: false, + vsyncDisabled: false, + lowDetailMode: window.lowDetailMode }; const data = saved ? JSON.parse(saved) : defaults; @@ -2634,6 +2661,14 @@ _buildSettingsPopup() { this._fpsText.visible = data.showFPS; window.solidWave = data.solidWaveTrail; window.noClipAccuracy = data.noclipAccuracy; + window.vsyncDisabled = data.vsyncDisabled ?? false; + // lowDetailMode already set by config.js; only override if explicitly saved + if (data.lowDetailMode !== undefined && saved) { + window.lowDetailMode = data.lowDetailMode; + } + if (window.vsyncDisabled && this.game && this.game.loop) { + this.game.loop.smoothStep = false; + } } _buildInfoPopup() { @@ -5579,4 +5614,4 @@ _applyMirrorEffect() { duration: 500 }); } -} +} \ No newline at end of file diff --git a/assets/scripts/core/level.js b/assets/scripts/core/level.js index 63bc37d..728802c 100644 --- a/assets/scripts/core/level.js +++ b/assets/scripts/core/level.js @@ -1209,6 +1209,21 @@ window.LevelObject = class LevelObject { this.objects.push(_0x3c84ad); this._addCollisionToSection(_0x3c84ad); } + } else if (_SLOPE_DATA[levelObj.id]) { + const _slopeData = _SLOPE_DATA[levelObj.id]; + const _slopeW = _slopeData.gw * a; + const _slopeH = _slopeData.gh * a; + const _slopeCollider = new Collider(slopeType, worldX, worldY, _slopeW, _slopeH, levelObj.rot || 0); + _slopeCollider.slopeAngleDeg = _slopeData.angle; + // determine visual/physics orientation from object flips + _slopeCollider.slopeDir = levelObj.flipX ? -1 : 1; + _slopeCollider.slopeFlipY = !!levelObj.flipY; + // assume 'pit' frames are empty (not filled) + _slopeCollider.slopeIsFilled = !(objectDef && objectDef.frame && String(objectDef.frame).toLowerCase().includes("pit")); + _slopeCollider.objid = levelObj.id; + _registerCollider(_slopeCollider); + this.objects.push(_slopeCollider); + this._addCollisionToSection(_slopeCollider); } else if (objectDef.type === portalType) { let _0xad0974 = objectDef.gridW * a; diff --git a/assets/scripts/core/main.js b/assets/scripts/core/main.js index 3682bf4..cd889f2 100644 --- a/assets/scripts/core/main.js +++ b/assets/scripts/core/main.js @@ -44,7 +44,7 @@ const phaserConfig = { height: screenHeight, resolution: 1, fps: { - smoothStep: !window.lowDetailMode + smoothStep: !window.vsyncDisabled && !window.lowDetailMode }, backgroundColor: "#000000", parent: document.body, @@ -77,4 +77,4 @@ window.getCacheInfo = () => { return window.gameCache.getCacheStats(); } return null; -}; +}; \ No newline at end of file diff --git a/assets/scripts/utils/config.js b/assets/scripts/utils/config.js index d0e3b95..1c578c0 100644 --- a/assets/scripts/utils/config.js +++ b/assets/scripts/utils/config.js @@ -30,6 +30,9 @@ if (urlParams.has('id')) { // Low Detail Mode for older devices window.lowDetailMode = localStorage.getItem("lowDetailMode") === "true" || urlParams.has('ldm'); +// VSync disabled flag (loaded from settings, default false) +window.vsyncDisabled = localStorage.getItem("vsyncDisabled") === "true"; + // Auto-detect low performance devices if (!window.lowDetailMode) { const cores = navigator.hardwareConcurrency || 2; @@ -119,4 +122,4 @@ function addImageToScene(scene, x, y, textureName) { } else { return null; } -} +} \ No newline at end of file From 391a38a34ef7e2a42ccf359baf19d81475afdae8 Mon Sep 17 00:00:00 2001 From: POWBoy1 Date: Sun, 10 May 2026 23:02:29 -0400 Subject: [PATCH 4/5] LDM LDM is now fully done, Particles are minimal/Decreased. Anti-aliasing is disabled when LDM is on. VSync option was removed since it doesnt work. --- assets/scripts/core/game-scene.js | 39 +++++++------------ assets/scripts/core/level.js | 17 +------- assets/scripts/core/main.js | 6 ++- assets/scripts/core/player.js | 6 ++- assets/scripts/utils/config.js | 6 +-- assets/scripts/utils/performance-optimizer.js | 1 - 6 files changed, 24 insertions(+), 51 deletions(-) delete mode 100644 assets/scripts/utils/performance-optimizer.js diff --git a/assets/scripts/core/game-scene.js b/assets/scripts/core/game-scene.js index 15095d1..7d13a3c 100644 --- a/assets/scripts/core/game-scene.js +++ b/assets/scripts/core/game-scene.js @@ -2575,7 +2575,7 @@ _buildSettingsPopup() { () => window.solidWave, (v) => window.solidWave = v ); - createToggle(container, column1X, startY + (spacingY * 4), "Low Detail Mode", + createToggle(container, column1X, startY + (spacingY * 4), "Low Detail Mode (Refresh Required)", () => window.lowDetailMode, (v) => { window.lowDetailMode = v; @@ -2586,15 +2586,9 @@ _buildSettingsPopup() { this.game.renderer.gl.disable(this.game.renderer.gl.BLEND) ); } - } - ); - createToggle(container, column1X, startY + (spacingY * 5), "Disable VSync WIP", - () => window.vsyncDisabled, - (v) => { - window.vsyncDisabled = v; - localStorage.setItem("vsyncDisabled", v); - if (this.game && this.game.loop) { - this.game.loop.smoothStep = !v; + if (this.game && this.game.canvas) { + const ctx = this.game.canvas.getContext('2d'); + if (ctx) ctx.imageSmoothingEnabled = !v; } } ); @@ -2629,7 +2623,6 @@ _buildSettingsPopup() { showFPS: this._fpsText.visible, solidWaveTrail: window.solidWave, noclipAccuracy: window.noClipAccuracy, - vsyncDisabled: window.vsyncDisabled, lowDetailMode: window.lowDetailMode }; localStorage.setItem("gd_settings", JSON.stringify(settings)); @@ -2646,7 +2639,6 @@ _buildSettingsPopup() { showFPS: false, solidWaveTrail: false, noclipAccuracy: false, - vsyncDisabled: false, lowDetailMode: window.lowDetailMode }; @@ -2661,13 +2653,13 @@ _buildSettingsPopup() { this._fpsText.visible = data.showFPS; window.solidWave = data.solidWaveTrail; window.noClipAccuracy = data.noclipAccuracy; - window.vsyncDisabled = data.vsyncDisabled ?? false; // lowDetailMode already set by config.js; only override if explicitly saved if (data.lowDetailMode !== undefined && saved) { window.lowDetailMode = data.lowDetailMode; } - if (window.vsyncDisabled && this.game && this.game.loop) { - this.game.loop.smoothStep = false; + if (window.lowDetailMode && this.game && this.game.canvas) { + const ctx = this.game.canvas.getContext('2d'); + if (ctx) ctx.imageSmoothingEnabled = false; } } @@ -2705,7 +2697,7 @@ _buildSettingsPopup() { const _0x3cdf70c = this.add.bitmapText(xPos, yPos, "goldFont", "bog, AntiMatter, arbstro, aloaf", 40).setOrigin(0.5, 0.5).setScale(0.6); this._infoPopup.add(_0x3cdf70c); yPos += 35; - const _0x3cdf70d = this.add.bitmapText(xPos, yPos, "goldFont", "t0nchi7 and Lasokar.", 40).setOrigin(0.5, 0.5).setScale(0.6); + const _0x3cdf70d = this.add.bitmapText(xPos, yPos, "goldFont", "t0nchi7, Lasokar & POW_Boy1.", 40).setOrigin(0.5, 0.5).setScale(0.6); this._infoPopup.add(_0x3cdf70d); yPos += 35; const _0x97b2a9 = this.add.text(xPos, 463, "© 2026 RobTop Games. All rights reserved.", { @@ -2756,22 +2748,19 @@ _buildSettingsPopup() { bounceContainer.add(contentContainer); /* colors for reference 0xff6666 - 0xff9944 + 0xff9944 - important notes 0xaaddff - fun messages from me :) 0xff00ff - pink dev entries + 0xd98282 - POW_Boy1 entries */ const updateEntries = [ { text: "Update Log", scale: 0.85, font: "goldFont" }, - { text: "Accurate Featured tab demo.", scale: 0.65 }, - { text: "Info popups.", scale: 0.65 }, - { text: "Main menu buttons.", scale: 0.65 }, - { text: "Settings, Stats and Newgrounds.", scale: 0.65 }, - { text: "Fixed being able to go to the level selector while in menus.", scale: 0.35 }, - { text: "GD accurate loading screen.", scale: 0.65 }, - { text: "UI tweaks.", scale: 0.65 }, - { text: "Bug fixes.", scale: 0.65 }, + { text: "Added LDM (Low Detail Mode).", scale: 0.65 }, + { text: "LDM is automatically enabled on trash devices.", scale: 0.45, color: 0xff9944 }, { text: "is this update finally out?", scale: 0.65, color: 0xaaddff }, { text: "- rohanis0000", scale: 0.65, color: 0xaaddff }, + { text: "I love working on LDM", scale: 0.65, color: 0xd98282 }, + { text: "- POW_Boy1", scale: 0.65, color: 0xd98282 }, ]; let yPos = 0; const lineItems = []; diff --git a/assets/scripts/core/level.js b/assets/scripts/core/level.js index 728802c..512ff38 100644 --- a/assets/scripts/core/level.js +++ b/assets/scripts/core/level.js @@ -1104,7 +1104,7 @@ window.LevelObject = class LevelObject { if (levelObj.id === 1331) { } } - if (objectDef && objectDef.portalParticle && frameName) { + if (objectDef && objectDef.portalParticle && frameName && !window.lowDetailMode) { let _0x3a9438 = worldX; let _0x2e9079 = b(worldY); const _0x143187 = 2; @@ -1209,21 +1209,6 @@ window.LevelObject = class LevelObject { this.objects.push(_0x3c84ad); this._addCollisionToSection(_0x3c84ad); } - } else if (_SLOPE_DATA[levelObj.id]) { - const _slopeData = _SLOPE_DATA[levelObj.id]; - const _slopeW = _slopeData.gw * a; - const _slopeH = _slopeData.gh * a; - const _slopeCollider = new Collider(slopeType, worldX, worldY, _slopeW, _slopeH, levelObj.rot || 0); - _slopeCollider.slopeAngleDeg = _slopeData.angle; - // determine visual/physics orientation from object flips - _slopeCollider.slopeDir = levelObj.flipX ? -1 : 1; - _slopeCollider.slopeFlipY = !!levelObj.flipY; - // assume 'pit' frames are empty (not filled) - _slopeCollider.slopeIsFilled = !(objectDef && objectDef.frame && String(objectDef.frame).toLowerCase().includes("pit")); - _slopeCollider.objid = levelObj.id; - _registerCollider(_slopeCollider); - this.objects.push(_slopeCollider); - this._addCollisionToSection(_slopeCollider); } else if (objectDef.type === portalType) { let _0xad0974 = objectDef.gridW * a; diff --git a/assets/scripts/core/main.js b/assets/scripts/core/main.js index cd889f2..ee76ccf 100644 --- a/assets/scripts/core/main.js +++ b/assets/scripts/core/main.js @@ -44,7 +44,7 @@ const phaserConfig = { height: screenHeight, resolution: 1, fps: { - smoothStep: !window.vsyncDisabled && !window.lowDetailMode + smoothStep: !window.lowDetailMode }, backgroundColor: "#000000", parent: document.body, @@ -52,7 +52,9 @@ const phaserConfig = { windowEvents: false }, render: { - powerPreference: window.lowDetailMode ? "low-power" : "default" + powerPreference: window.lowDetailMode ? "low-power" : "default", + antialias: !window.lowDetailMode, + desynchronized: window.vsyncDisabled }, scale: { mode: Phaser.Scale.FIT, diff --git a/assets/scripts/core/player.js b/assets/scripts/core/player.js index 85b4c5b..8748546 100644 --- a/assets/scripts/core/player.js +++ b/assets/scripts/core/player.js @@ -1200,7 +1200,8 @@ if (this.p.isFlying || this.p.isUfo) { const _0x3f0446 = _0x3f4b84._getMirrorXOffset(_0x3f4b84._playerWorldX - _0x3f4b84._cameraX); const _0x53ac5b = b(this.p.y) + this._lastCameraY; const _0x281e43 = 0.9; - _0x3f4b84.add.particles(_0x3f0446, _0x53ac5b, "GJ_WebSheet", { + if (!window.lowDetailMode) { + _0x3f4b84.add.particles(_0x3f0446, _0x53ac5b, "GJ_WebSheet", { frame: "square.png", speed: { min: 200, @@ -1235,6 +1236,7 @@ if (this.p.isFlying || this.p.isUfo) { max: 20 } }).setScrollFactor(0).setDepth(15); + } const _0x438d80 = _0x3f4b84.add.graphics().setScrollFactor(0).setDepth(15).setBlendMode(S); const _0x4683eb = { t: 0 @@ -1340,7 +1342,7 @@ if (this.p.isFlying || this.p.isUfo) { _0xba83f5.y = -(_0x20396e + _0x20847a / 2 - sliderBar / 2); this._explosionContainer.add(_0xba83f5); let _0x298d34 = null; - if (_0x156c8b % 2 == 0) { + if (_0x156c8b % 2 == 0 && !window.lowDetailMode) { const _0x367bdb = 200 + Math.random() * 200; const _0x5e5fa8 = _0xba83f5; _0x298d34 = _0x44acaf.add.particles(0, 0, "GJ_WebSheet", { diff --git a/assets/scripts/utils/config.js b/assets/scripts/utils/config.js index 1c578c0..9d4d1c9 100644 --- a/assets/scripts/utils/config.js +++ b/assets/scripts/utils/config.js @@ -27,18 +27,14 @@ if (urlParams.has('id')) { window.levelID = urlParams.get('id'); } -// Low Detail Mode for older devices window.lowDetailMode = localStorage.getItem("lowDetailMode") === "true" || urlParams.has('ldm'); -// VSync disabled flag (loaded from settings, default false) window.vsyncDisabled = localStorage.getItem("vsyncDisabled") === "true"; -// Auto-detect low performance devices if (!window.lowDetailMode) { const cores = navigator.hardwareConcurrency || 2; const memory = navigator.deviceMemory || 4; - const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); - // Enable LDM if less than 4 cores, less than 4GB memory, or mobile device + const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|ChromeOS|IEMobile|Opera Mini/i.test(navigator.userAgent); window.lowDetailMode = cores < 4 || memory < 4 || isMobile; } diff --git a/assets/scripts/utils/performance-optimizer.js b/assets/scripts/utils/performance-optimizer.js deleted file mode 100644 index 7d459b9..0000000 --- a/assets/scripts/utils/performance-optimizer.js +++ /dev/null @@ -1 +0,0 @@ -// working on this in a test branch. From 524a62ec6f1f32f071948194e7884b1e443000ee Mon Sep 17 00:00:00 2001 From: POWBoy1 Date: Mon, 11 May 2026 20:02:25 -0400 Subject: [PATCH 5/5] Tweaks with stuff Fixed orbs still having particles when LDM is on. and more. --- assets/scripts/core/game-scene.js | 120 +++++----- assets/scripts/core/level.js | 190 +++++++-------- assets/scripts/core/player.js | 384 +++++++++++++++--------------- 3 files changed, 355 insertions(+), 339 deletions(-) diff --git a/assets/scripts/core/game-scene.js b/assets/scripts/core/game-scene.js index 7d13a3c..61335b6 100644 --- a/assets/scripts/core/game-scene.js +++ b/assets/scripts/core/game-scene.js @@ -2757,9 +2757,7 @@ _buildSettingsPopup() { { text: "Update Log", scale: 0.85, font: "goldFont" }, { text: "Added LDM (Low Detail Mode).", scale: 0.65 }, { text: "LDM is automatically enabled on trash devices.", scale: 0.45, color: 0xff9944 }, - { text: "is this update finally out?", scale: 0.65, color: 0xaaddff }, - { text: "- rohanis0000", scale: 0.65, color: 0xaaddff }, - { text: "I love working on LDM", scale: 0.65, color: 0xd98282 }, + { text: "WSP People!", scale: 0.65, color: 0xd98282 }, { text: "- POW_Boy1", scale: 0.65, color: 0xd98282 }, ]; let yPos = 0; @@ -4072,50 +4070,52 @@ _buildSettingsPopup() { } } this._level.updateAudioScale(this._audio.getMeteringValue()); - if (!this._orbGfx) { - this._orbGfx = this.add.graphics().setDepth(54).setBlendMode(S); - } - this._orbParticleAngle = ((this._orbParticleAngle || 0) + deltaTime * 0.004) % (Math.PI * 2); - this._orbGfxTimer = (this._orbGfxTimer || 0) + deltaTime; - if (this._orbGfxTimer > 33) { - this._orbGfxTimer = 0; - this._orbGfx.clear(); - if (this._level && this._level._orbSprites && this._level.container) { - try { - let _drawn = 0; - const _orbTypeColorMap = { - 36: 0xfffb57, - 84: 0x58ffff, - 141: 0xff52f0, - 444: 0xff00d2, - 1022: 0x63ff5f, - 1330: 0xffffff, - 1333: 0xff6326, - 1594: 0x6cff6b, - 1704: 0x04ff04, - 1751: 0xff00d2 - }; - for (let _oSpr of this._level._orbSprites) { - if (_drawn >= 4) break; - if (!_oSpr || !_oSpr.visible || !_oSpr.active || !_oSpr.scene) continue; - const _sx = _oSpr.x + this._level.container.x; - const _sy = _oSpr.y + this._level.container.y; - if (_sx < -40 || _sx > screenWidth + 40 || _sy < -40 || _sy > screenHeight + 40) continue; - _drawn++; - const _orbTypeTint = _orbTypeColorMap[_oSpr._orbId]; - for (let _pi = 0; _pi < 5; _pi++) { - const _orbitSpeed = 0.7 + (_pi % 3) * 0.35; - const _orbitR = 34 + (_pi * 5 % 17); - const _ang = this._orbParticleAngle * _orbitSpeed + (_pi * Math.PI * 2 / 5); - const _px = _sx + Math.cos(_ang) * _orbitR; - const _py = _sy + Math.sin(_ang) * (_orbitR * 0.85); - const _size = (window.orbParticleSize || 3.5) + (_pi % 3) * 1.0; - const _alpha = 0.5 + (_pi % 4) * 0.12; - this._orbGfx.fillStyle(_orbTypeTint, _alpha); - this._orbGfx.fillRect(_px - _size, _py - _size, _size * 2, _size * 2); + if (!window.lowDetailMode) { + if (!this._orbGfx) { + this._orbGfx = this.add.graphics().setDepth(54).setBlendMode(S); + } + this._orbParticleAngle = ((this._orbParticleAngle || 0) + deltaTime * 0.004) % (Math.PI * 2); + this._orbGfxTimer = (this._orbGfxTimer || 0) + deltaTime; + if (this._orbGfxTimer > 33) { + this._orbGfxTimer = 0; + this._orbGfx.clear(); + if (this._level && this._level._orbSprites && this._level.container) { + try { + let _drawn = 0; + const _orbTypeColorMap = { + 36: 0xfffb57, + 84: 0x58ffff, + 141: 0xff52f0, + 444: 0xff00d2, + 1022: 0x63ff5f, + 1330: 0xffffff, + 1333: 0xff6326, + 1594: 0x6cff6b, + 1704: 0x04ff04, + 1751: 0xff00d2 + }; + for (let _oSpr of this._level._orbSprites) { + if (_drawn >= 4) break; + if (!_oSpr || !_oSpr.visible || !_oSpr.active || !_oSpr.scene) continue; + const _sx = _oSpr.x + this._level.container.x; + const _sy = _oSpr.y + this._level.container.y; + if (_sx < -40 || _sx > screenWidth + 40 || _sy < -40 || _sy > screenHeight + 40) continue; + _drawn++; + const _orbTypeTint = _orbTypeColorMap[_oSpr._orbId]; + for (let _pi = 0; _pi < 5; _pi++) { + const _orbitSpeed = 0.7 + (_pi % 3) * 0.35; + const _orbitR = 34 + (_pi * 5 % 17); + const _ang = this._orbParticleAngle * _orbitSpeed + (_pi * Math.PI * 2 / 5); + const _px = _sx + Math.cos(_ang) * _orbitR; + const _py = _sy + Math.sin(_ang) * (_orbitR * 0.85); + const _size = (window.orbParticleSize || 3.5) + (_pi % 3) * 1.0; + const _alpha = 0.5 + (_pi % 4) * 0.12; + this._orbGfx.fillStyle(_orbTypeTint, _alpha); + this._orbGfx.fillRect(_px - _size, _py - _size, _size * 2, _size * 2); + } } + } catch(e) {} } - } catch(e) {} } } let quantizedDelta = this._quantizeDelta(deltaTime); @@ -4361,10 +4361,12 @@ _applyMirrorEffect() { const _0x356782 = this._level.endXPos - this._cameraX; const _0x2d967b = b(this._endPortalGameY) + this._cameraY; - for (let _0x481f7c = 0; _0x481f7c < 5; _0x481f7c++) { - this.time.delayedCall(_0x481f7c * 50, () => circleEffect(this, _0x356782, _0x2d967b, 10, screenWidth, 500, false, true, window.mainColor)); + if (!window.lowDetailMode) { + for (let _0x481f7c = 0; _0x481f7c < 5; _0x481f7c++) { + this.time.delayedCall(_0x481f7c * 50, () => circleEffect(this, _0x356782, _0x2d967b, 10, screenWidth, 500, false, true, window.mainColor)); + } + circleEffect(this, _0x356782, _0x2d967b, 10, 1000, 500, true, false, window.mainColor); } - circleEffect(this, _0x356782, _0x2d967b, 10, 1000, 500, true, false, window.mainColor); this._showCompleteEffect(); } _showCompleteEffect() { @@ -4450,7 +4452,9 @@ _applyMirrorEffect() { } }); })(this, this._level.endXPos - this._cameraX + 60, b(this._endPortalGameY) + this._cameraY, window.mainColor); - this.cameras.main.shake(1950, 0.004); + if (!window.lowDetailMode) { + this.cameras.main.shake(1950, 0.004); + } this.time.delayedCall(1950, () => this._showCompleteText()); } _showCompleteText() { @@ -4514,14 +4518,16 @@ _applyMirrorEffect() { } const _0x2eadf2 = this._level.endXPos - this._cameraX; const _0x380b24 = b(this._endPortalGameY) + this._cameraY; - circleEffect(this, _0x2eadf2, _0x380b24, 10, screenWidth, 800, true, false, window.mainColor); - circleEffect(this, _0x56628c, 250, 10, 1000, 800, true, false, window.mainColor); - for (let _0x579e05 = 0; _0x579e05 < 5; _0x579e05++) { - this.time.delayedCall(_0x579e05 * 50, () => circleEffect(this, _0x2eadf2, _0x380b24, 10, screenWidth, 500, false, true, window.mainColor)); - } - for (let _0x429722 = 0; _0x429722 < 10; _0x429722++) { - const _0xbf7dd0 = _0x429722 * 150 + (Math.random() * 160 - 80); - this.time.delayedCall(Math.max(0, _0xbf7dd0), () => particleEffect(this, window.mainColor, window.secondaryColor)); + if (!window.lowDetailMode) { + circleEffect(this, _0x2eadf2, _0x380b24, 10, screenWidth, 800, true, false, window.mainColor); + circleEffect(this, _0x56628c, 250, 10, 1000, 800, true, false, window.mainColor); + for (let _0x579e05 = 0; _0x579e05 < 5; _0x579e05++) { + this.time.delayedCall(_0x579e05 * 50, () => circleEffect(this, _0x2eadf2, _0x380b24, 10, screenWidth, 500, false, true, window.mainColor)); + } + for (let _0x429722 = 0; _0x429722 < 10; _0x429722++) { + const _0xbf7dd0 = _0x429722 * 150 + (Math.random() * 160 - 80); + this.time.delayedCall(Math.max(0, _0xbf7dd0), () => particleEffect(this, window.mainColor, window.secondaryColor)); + } } this.time.delayedCall(1500, () => this._showEndLayer()); } diff --git a/assets/scripts/core/level.js b/assets/scripts/core/level.js index 512ff38..661693d 100644 --- a/assets/scripts/core/level.js +++ b/assets/scripts/core/level.js @@ -787,109 +787,113 @@ window.LevelObject = class LevelObject { for (let levelObj of _0x35f1ae) { let objectDef = getObjectFromId(levelObj.id); if (objectDef && objectDef.type === triggerType) { - if (levelObj.id === 29 || levelObj.id === 30) { - this._colorTriggers.push({ - x: levelObj.x * 2, - index: levelObj.id === 29 ? 1000 : 1001, - color: { - r: parseInt(levelObj._raw[7] ?? 255, 10), - g: parseInt(levelObj._raw[8] ?? 255, 10), - b: parseInt(levelObj._raw[9] ?? 255, 10) - }, - duration: parseFloat(levelObj._raw[10] ?? 0), - tintGround: levelObj._raw[14] === "1" - }); - } - if (objectDef.enterEffect) { - this._enterEffectTriggers.push({ - x: levelObj.x * 2, - effect: objectDef.enterEffect - }); - } - if (levelObj.id === 901) { - const _raw = levelObj._raw; - this._moveTriggers.push({ - x: levelObj.x * 2, - duration: parseFloat(_raw[10] ?? 0), - easingType: parseInt(_raw[30] ?? 0, 10), - easingRate: parseFloat(_raw[85] ?? 2), - targetGroup: parseInt(_raw[51] ?? 0, 10), - offsetX: parseFloat(_raw[28] ?? 0) * 2, - offsetY: parseFloat(_raw[29] ?? 0) * 2, - lockX: _raw[58] === '1', - lockY: _raw[59] === '1', - }); - } - if (levelObj.id === 1007) { - const _raw = levelObj._raw; - this._alphaTriggers.push({ - x: levelObj.x * 2, - duration: parseFloat(_raw[10] ?? 0), - targetGroup: parseInt(_raw[51] ?? 0, 10), - targetOpacity: Math.max(0, Math.min(1, parseFloat(_raw[35] ?? 1))), + // Always load start positions even in LDM + if (levelObj.id === 31) { + this._startPositions.push({ + x: 2 * levelObj.x, + y: 2 * levelObj.y, + gameMode: levelObj.gameMode, + miniMode: levelObj.miniMode, + speed: levelObj.speed, + mirrored: levelObj.mirrored, + gravityFlipped: levelObj.flipGravity }); } - if (levelObj.id === 899) { - const _raw = levelObj._raw; - const targetChannel = parseInt(_raw[23] ?? 0, 10); - if (targetChannel > 0) { + // Skip other triggers in LDM mode + if (!window.lowDetailMode) { + if (levelObj.id === 29 || levelObj.id === 30) { this._colorTriggers.push({ x: levelObj.x * 2, - index: targetChannel, + index: levelObj.id === 29 ? 1000 : 1001, + color: { + r: parseInt(levelObj._raw[7] ?? 255, 10), + g: parseInt(levelObj._raw[8] ?? 255, 10), + b: parseInt(levelObj._raw[9] ?? 255, 10) + }, + duration: parseFloat(levelObj._raw[10] ?? 0), + tintGround: levelObj._raw[14] === "1" + }); + } + if (objectDef.enterEffect) { + this._enterEffectTriggers.push({ + x: levelObj.x * 2, + effect: objectDef.enterEffect + }); + } + if (levelObj.id === 901) { + const _raw = levelObj._raw; + this._moveTriggers.push({ + x: levelObj.x * 2, + duration: parseFloat(_raw[10] ?? 0), + easingType: parseInt(_raw[30] ?? 0, 10), + easingRate: parseFloat(_raw[85] ?? 2), + targetGroup: parseInt(_raw[51] ?? 0, 10), + offsetX: parseFloat(_raw[28] ?? 0) * 2, + offsetY: parseFloat(_raw[29] ?? 0) * 2, + lockX: _raw[58] === '1', + lockY: _raw[59] === '1', + }); + } + if (levelObj.id === 1007) { + const _raw = levelObj._raw; + this._alphaTriggers.push({ + x: levelObj.x * 2, + duration: parseFloat(_raw[10] ?? 0), + targetGroup: parseInt(_raw[51] ?? 0, 10), + targetOpacity: Math.max(0, Math.min(1, parseFloat(_raw[35] ?? 1))), + }); + } + if (levelObj.id === 899) { + const _raw = levelObj._raw; + const targetChannel = parseInt(_raw[23] ?? 0, 10); + if (targetChannel > 0) { + this._colorTriggers.push({ + x: levelObj.x * 2, + index: targetChannel, + color: { + r: parseInt(_raw[7] ?? 255, 10), + g: parseInt(_raw[8] ?? 255, 10), + b: parseInt(_raw[9] ?? 255, 10) + }, + duration: parseFloat(_raw[10] ?? 0), + tintGround: _raw[14] === "1", + opacity: parseFloat(_raw[35] ?? 1) + }); + } + } + if (levelObj.id === 1346) { + const _raw = levelObj._raw; + this._rotateTriggers.push({ + x: levelObj.x * 2, + targetGroup: parseInt(_raw[51] ?? 0, 10), + degrees: parseFloat(_raw[68] ?? 0), + duration: parseFloat(_raw[10] ?? 0), + easingType: parseInt(_raw[30] ?? 0, 10), + easingRate: parseFloat(_raw[85] ?? 2), + lockRotation: _raw[70] === '1', + times360: parseInt(_raw[69] ?? 0, 10), + centerGroup: parseInt(_raw[71] ?? 0, 10), + }); + } + if (levelObj.id === 1006) { + const _raw = levelObj._raw; + const targetType = parseInt(_raw[52] ?? 0, 10); + this._pulseTriggers.push({ + x: levelObj.x * 2, + targetGroup: targetType === 1 ? parseInt(_raw[51] ?? 0, 10) : 0, + targetChannel: targetType === 0 ? parseInt(_raw[51] ?? 0, 10) : 0, + targetType: targetType, color: { r: parseInt(_raw[7] ?? 255, 10), g: parseInt(_raw[8] ?? 255, 10), b: parseInt(_raw[9] ?? 255, 10) }, - duration: parseFloat(_raw[10] ?? 0), - tintGround: _raw[14] === "1", - opacity: parseFloat(_raw[35] ?? 1) + fadeIn: parseFloat(_raw[45] ?? 0), + hold: parseFloat(_raw[46] ?? 0), + fadeOut: parseFloat(_raw[47] ?? 0), }); } } - if (levelObj.id === 1346) { - const _raw = levelObj._raw; - this._rotateTriggers.push({ - x: levelObj.x * 2, - targetGroup: parseInt(_raw[51] ?? 0, 10), - degrees: parseFloat(_raw[68] ?? 0), - duration: parseFloat(_raw[10] ?? 0), - easingType: parseInt(_raw[30] ?? 0, 10), - easingRate: parseFloat(_raw[85] ?? 2), - lockRotation: _raw[70] === '1', - times360: parseInt(_raw[69] ?? 0, 10), - centerGroup: parseInt(_raw[71] ?? 0, 10), - }); - } - if (levelObj.id === 1006) { - const _raw = levelObj._raw; - const targetType = parseInt(_raw[52] ?? 0, 10); - this._pulseTriggers.push({ - x: levelObj.x * 2, - targetGroup: targetType === 1 ? parseInt(_raw[51] ?? 0, 10) : 0, - targetChannel: targetType === 0 ? parseInt(_raw[51] ?? 0, 10) : 0, - targetType: targetType, - color: { - r: parseInt(_raw[7] ?? 255, 10), - g: parseInt(_raw[8] ?? 255, 10), - b: parseInt(_raw[9] ?? 255, 10) - }, - fadeIn: parseFloat(_raw[45] ?? 0), - hold: parseFloat(_raw[46] ?? 0), - fadeOut: parseFloat(_raw[47] ?? 0), - }); - } - if (levelObj.id === 31) { - this._startPositions.push({ - x: 2 * levelObj.x, - y: 2 * levelObj.y, - gameMode: levelObj.gameMode, - miniMode: levelObj.miniMode, - speed: levelObj.speed, - mirrored: levelObj.mirrored, - gravityFlipped: levelObj.flipGravity - }); - } continue; } let worldX = levelObj.x * 2; @@ -950,7 +954,7 @@ window.LevelObject = class LevelObject { } } let _0xOrbGlow = null; - if (objectDef.glow) { + if (!window.lowDetailMode && objectDef.glow) { _0xOrbGlow = this._addGlowSprite(scene, spriteWorldX, baseY, frameName, levelObj, worldX); if (_0xOrbGlow) { _0xOrbGlow._eeZDepth = _objZDepth - 0.003; @@ -1267,7 +1271,7 @@ window.LevelObject = class LevelObject { _registerCollider(padObj); this.objects.push(padObj); this._addCollisionToSection(padObj); - } else if (objectDef.type === ringType) { + } else if (!window.lowDetailMode && objectDef.type === ringType) { let orbW = objectDef.gridW * a; let orbH = objectDef.gridH * a; let orbObj = new Collider(jumpRingType, worldX, worldY, orbW, orbH, levelObj.rot || 0); diff --git a/assets/scripts/core/player.js b/assets/scripts/core/player.js index 8748546..82ed24a 100644 --- a/assets/scripts/core/player.js +++ b/assets/scripts/core/player.js @@ -456,177 +456,179 @@ class PlayerObject { } } _initParticles(scene) { - const freq = window.lowDetailMode ? 0 : 1000 / 30; - this._particleEmitter = scene.add.particles(0, 0, "GJ_WebSheet", { - frame: "square.png", - speed: { - min: 110, - max: 190 - }, - angle: { - min: 225, - max: 315 - }, - lifespan: { - min: 150, - max: 450 - }, - scale: { - start: 0.5, - end: 0 - }, - gravityY: 600, - frequency: freq, - blendMode: window.lowDetailMode ? "NORMAL" : "ADD", - alpha: { - start: 1, - end: 0 - }, - tint: window.mainColor - }); - this._particleEmitter.stop(); - this._particleEmitter.setDepth(9); - this._gameLayer.container.add(this._particleEmitter); - this._flyParticleEmitter = scene.add.particles(0, 0, "GJ_WebSheet", { - frame: "square.png", - speed: { - min: 22, - max: 38 - }, - angle: { - min: 225, - max: 315 - }, - lifespan: { - min: 150, - max: 450 - }, - scale: { - start: 0.5, - end: 0 - }, - gravityY: 600, - frequency: freq, - blendMode: window.lowDetailMode ? "NORMAL" : "ADD", - tint: { - start: 16737280, - end: 16711680 - }, - alpha: { - start: 1, - end: 0 - } - }); - this._flyParticleEmitter.stop(); - this._flyParticleEmitter.setDepth(9); - this._gameLayer.container.add(this._flyParticleEmitter); - this._flyParticle2Emitter = scene.add.particles(0, 0, "GJ_WebSheet", { - frame: "square.png", - speed: { - min: 220, - max: 380 - }, - angle: { - min: 180, - max: 360 - }, - lifespan: { - min: 150, - max: 450 - }, - scale: { - start: 0.75, - end: 0 - }, - gravityY: 600, - frequency: freq, - blendMode: window.lowDetailMode ? "NORMAL" : "ADD", - tint: { - start: 16760320, - end: 16711680 - }, - alpha: { - start: 1, - end: 0 - } - }); - this._flyParticle2Emitter.stop(); - this._flyParticle2Emitter.setDepth(9); - this._gameLayer.container.add(this._flyParticle2Emitter); - this._shipDragEmitter = scene.add.particles(0, 0, "GJ_WebSheet", { - frame: "square.png", - x: { - min: -18, - max: 18 - }, - speed: { - min: 223.79999999999998, - max: 343.79999999999995 - }, - angle: { - min: 205, - max: 295 - }, - lifespan: { - min: 80, - max: 220 - }, - scale: { - start: 0.375, - end: 0 - }, - gravityX: -700, - gravityY: 600, - frequency: 25, - blendMode: "ADD", - alpha: { - start: 1, - end: 0 - } - }); - this._shipDragEmitter.stop(); - this._shipDragEmitter.setDepth(22); + if (!window.lowDetailMode) { + const freq = 1000 / 30; + this._particleEmitter = scene.add.particles(0, 0, "GJ_WebSheet", { + frame: "square.png", + speed: { + min: 110, + max: 190 + }, + angle: { + min: 225, + max: 315 + }, + lifespan: { + min: 150, + max: 450 + }, + scale: { + start: 0.5, + end: 0 + }, + gravityY: 600, + frequency: freq, + blendMode: "ADD", + alpha: { + start: 1, + end: 0 + }, + tint: window.mainColor + }); + this._particleEmitter.stop(); + this._particleEmitter.setDepth(9); + this._gameLayer.container.add(this._particleEmitter); + this._flyParticleEmitter = scene.add.particles(0, 0, "GJ_WebSheet", { + frame: "square.png", + speed: { + min: 22, + max: 38 + }, + angle: { + min: 225, + max: 315 + }, + lifespan: { + min: 150, + max: 450 + }, + scale: { + start: 0.5, + end: 0 + }, + gravityY: 600, + frequency: freq, + blendMode: "ADD", + tint: { + start: 16737280, + end: 16711680 + }, + alpha: { + start: 1, + end: 0 + } + }); + this._flyParticleEmitter.stop(); + this._flyParticleEmitter.setDepth(9); + this._gameLayer.container.add(this._flyParticleEmitter); + this._flyParticle2Emitter = scene.add.particles(0, 0, "GJ_WebSheet", { + frame: "square.png", + speed: { + min: 220, + max: 380 + }, + angle: { + min: 180, + max: 360 + }, + lifespan: { + min: 150, + max: 450 + }, + scale: { + start: 0.75, + end: 0 + }, + gravityY: 600, + frequency: freq, + blendMode: "ADD", + tint: { + start: 16760320, + end: 16711680 + }, + alpha: { + start: 1, + end: 0 + } + }); + this._flyParticle2Emitter.stop(); + this._flyParticle2Emitter.setDepth(9); + this._gameLayer.container.add(this._flyParticle2Emitter); + this._shipDragEmitter = scene.add.particles(0, 0, "GJ_WebSheet", { + frame: "square.png", + x: { + min: -18, + max: 18 + }, + speed: { + min: 223.79999999999998, + max: 343.79999999999995 + }, + angle: { + min: 205, + max: 295 + }, + lifespan: { + min: 80, + max: 220 + }, + scale: { + start: 0.375, + end: 0 + }, + gravityX: -700, + gravityY: 600, + frequency: 25, + blendMode: "ADD", + alpha: { + start: 1, + end: 0 + } + }); + this._shipDragEmitter.stop(); + this._shipDragEmitter.setDepth(22); + const _0x57911a = { + frame: "square.png", + speed: { + min: 250, + max: 350 + }, + angle: { + min: 210, + max: 330 + }, + lifespan: { + min: 50, + max: 600 + }, + scale: { + start: 0.625, + end: 0 + }, + gravityY: 1000, + blendMode: "ADD", + alpha: { + start: 1, + end: 0 + }, + tint: window.mainColor, + emitting: false + }; + this._landEmitter1 = scene.add.particles(0, 0, "GJ_WebSheet", { + ..._0x57911a + }); + this._landEmitter2 = scene.add.particles(0, 0, "GJ_WebSheet", { + ..._0x57911a + }); + this._gameLayer.topContainer.add(this._landEmitter1); + this._gameLayer.topContainer.add(this._landEmitter2); + } this._shipDragActive = false; this._particleActive = false; this._flyParticle2Active = false; this._flyParticleActive = false; - const _0x57911a = { - frame: "square.png", - speed: { - min: 250, - max: 350 - }, - angle: { - min: 210, - max: 330 - }, - lifespan: { - min: 50, - max: 600 - }, - scale: { - start: 0.625, - end: 0 - }, - gravityY: 1000, - blendMode: "ADD", - alpha: { - start: 1, - end: 0 - }, - tint: window.mainColor, - emitting: false - }; - this._landEmitter1 = scene.add.particles(0, 0, "GJ_WebSheet", { - ..._0x57911a - }); - this._landEmitter2 = scene.add.particles(0, 0, "GJ_WebSheet", { - ..._0x57911a - }); this._aboveContainer = scene.add.container(0, 0); this._aboveContainer.setDepth(13); - this._gameLayer.topContainer.add(this._landEmitter1); - this._gameLayer.topContainer.add(this._landEmitter2); this._landIdx = false; this._streak = new StreakManager(this._scene, "streak_01", 0.231, 10, 8, 100, window.secondaryColor, 0.7); this._streak.addToContainer(this._gameLayer.container, 8); @@ -923,7 +925,7 @@ if (this.p.isFlying || this.p.isUfo) { this.p.isJumping = false; this.stopRotation(); this._rotation = 0; - this._particleEmitter.stop(); + if (this._particleEmitter) this._particleEmitter.stop(); this._flyParticle2Active = false; this._streak.reset(); this._streak.start(); @@ -950,11 +952,11 @@ if (this.p.isFlying || this.p.isUfo) { this.p.isJumping = false; this.stopRotation(); this._rotation = 0; - this._flyParticleEmitter.stop(); + if (this._flyParticleEmitter) this._flyParticleEmitter.stop(); this._flyParticleActive = false; - this._flyParticle2Emitter.stop(); + if (this._flyParticle2Emitter) this._flyParticle2Emitter.stop(); this._flyParticle2Active = false; - this._shipDragEmitter.stop(); + if (this._shipDragEmitter) this._shipDragEmitter.stop(); this._shipDragActive = false; this._particleActive = false; this._streak.stop(); @@ -1106,7 +1108,7 @@ if (this.p.isFlying || this.p.isUfo) { this.p.isJumping = false; this.stopRotation(); this._rotation = 0; - this._particleEmitter.stop(); + if (this._particleEmitter) this._particleEmitter.stop(); this._streak.reset(); this._streak.start(); this.setBallVisible(false); @@ -1136,7 +1138,7 @@ if (this.p.isFlying || this.p.isUfo) { this.p.isJumping = false; this.stopRotation(); this._rotation = 0; - this._flyParticleEmitter.stop(); + if (this._flyParticleEmitter) this._flyParticleEmitter.stop(); this.setCubeVisible(!this.p.isBall && !this.p.isFlying); this.setBallVisible(this.p.isBall); this.setShipVisible(this.p.isFlying); @@ -1175,9 +1177,11 @@ if (this.p.isFlying || this.p.isUfo) { if (_0x4a38a5 && !this.p.isFlying && !this.p.isWave && !this.p.isSpider) { this._landIdx = !this._landIdx; const _0x31584b = this._landIdx ? this._landEmitter1 : this._landEmitter2; - const _0x2248d5 = this._scene._playerWorldX; - const _0x17e0bb = this.p.gravityFlipped ? b(this.p.y) - 30 : b(this.p.y) + 30; - _0x31584b.explode(10, _0x2248d5, _0x17e0bb); + if (_0x31584b) { + const _0x2248d5 = this._scene._playerWorldX; + const _0x17e0bb = this.p.gravityFlipped ? b(this.p.y) - 30 : b(this.p.y) + 30; + _0x31584b.explode(10, _0x2248d5, _0x17e0bb); + } } } killPlayer() { @@ -1186,13 +1190,13 @@ if (this.p.isFlying || this.p.isUfo) { } this.p.isDead = true; this._scene.toggleGlitter(false); - this._particleEmitter.stop(); + if (this._particleEmitter) this._particleEmitter.stop(); this._particleActive = false; - this._flyParticleEmitter.stop(); + if (this._flyParticleEmitter) this._flyParticleEmitter.stop(); this._flyParticleActive = false; - this._flyParticle2Emitter.stop(); + if (this._flyParticle2Emitter) this._flyParticle2Emitter.stop(); this._flyParticle2Active = false; - this._shipDragEmitter.stop(); + if (this._shipDragEmitter) this._shipDragEmitter.stop(); this._shipDragActive = false; this._streak.stop(); this._streak.reset(); @@ -1799,9 +1803,11 @@ _updateBallJump(_0x2fe319) { this.p.onGround = false; this.p.canJump = false; this.p.isJumping = true; - try { - this._flyParticle2Emitter.explode(6, this._scene._playerWorldX, b(this.p.y) + (this.p.gravityFlipped ? -18 : 18)); - } catch(e) {} + if (this._flyParticle2Emitter) { + try { + this._flyParticle2Emitter.explode(6, this._scene._playerWorldX, b(this.p.y) + (this.p.gravityFlipped ? -18 : 18)); + } catch(e) {} + } } if (!this.p.wasBoosted) { const _ufoMaxUp = this.p.isMini ? 18.824 : 16; @@ -2678,10 +2684,10 @@ _updateBallJump(_0x2fe319) { const _0x8bc9f4 = _0x568b25 + 300; const _0x11b580 = [this._playerSpriteLayer, this._playerGlowLayer, this._playerOverlayLayer, this._playerExtraLayer, this._ballSpriteLayer, this._ballGlowLayer, this._ballOverlayLayer, this._waveSpriteLayer, this._waveOverlayLayer, this._waveExtraLayer, this._waveGlowLayer, this._shipSpriteLayer, this._shipGlowLayer, this._shipOverlayLayer, this._shipExtraLayer].filter(_0x3e9c62 => _0x3e9c62 && _0x3e9c62.sprite.visible).map(_0x5cedeb => _0x5cedeb.sprite); this._startPercent = (this._scene._playerWorldX / this._scene._level.endXPos) * 100; - this._particleEmitter.stop(); - this._flyParticleEmitter.stop(); - this._flyParticle2Emitter.stop(); - this._shipDragEmitter.stop(); + if (this._particleEmitter) this._particleEmitter.stop(); + if (this._flyParticleEmitter) this._flyParticleEmitter.stop(); + if (this._flyParticle2Emitter) this._flyParticle2Emitter.stop(); + if (this._shipDragEmitter) this._shipDragEmitter.stop(); const _0x154798 = this.p.isFlying; const _0x3793a4 = [this._shipSpriteLayer, this._shipGlowLayer, this._shipOverlayLayer, this._shipExtraLayer]; const _0xbd676f = [this._playerSpriteLayer, this._playerGlowLayer, this._playerOverlayLayer, this._playerExtraLayer]; @@ -2778,13 +2784,13 @@ _updateBallJump(_0x2fe319) { _0x1e656c.sprite.setScale(1); } } - this._particleEmitter.stop(); + if (this._particleEmitter) this._particleEmitter.stop(); this._particleActive = false; - this._flyParticleEmitter.stop(); + if (this._flyParticleEmitter) this._flyParticleEmitter.stop(); this._flyParticleActive = false; - this._flyParticle2Emitter.stop(); + if (this._flyParticle2Emitter) this._flyParticle2Emitter.stop(); this._flyParticle2Active = false; - this._shipDragEmitter.stop(); + if (this._shipDragEmitter) this._shipDragEmitter.stop(); this._shipDragActive = false; this._streak.stop(); this._streak.reset();