User prompt
Make it so you can glide ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make you sell the trophies on the last platform
User prompt
Make it so the platforms are closer
User prompt
Make it so it’s a little easier
User prompt
Make it so you fall slower
User prompt
Make it easier
Code edit (1 edits merged)
Please save this source code
User prompt
Shadow Swap: Dimension Shifter
Initial prompt
Genre: Puzzle Platformer Concept: You play as a shadow who can “swap places” with light! The world is filled with puzzles where light and shadow behave like solid platforms or traps. You must swap between shadow and light form to navigate tricky levels, avoid enemies, and activate switches. Key Features: • Light = visible, passable platforms. • Shadow = invisible paths and walls only shadows can use. • Swapping at the right time is the key to survival. • Boss levels where you race against moving light sources.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { currentLevel: 1, unlockedLevels: 1 }); /**** * Classes ****/ var DimensionSwitch = Container.expand(function () { var self = Container.call(this); // Create switch graphic self.graphic = self.attachAsset('dimensionSwitch', { anchorX: 0.5, anchorY: 0.5 }); // Create pulsing animation self.pulseAnimation = function () { tween(self.graphic, { scaleX: 1.2, scaleY: 1.2 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(self.graphic, { scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.easeInOut, onFinish: self.pulseAnimation }); } }); }; // Start pulsing self.pulseAnimation(); return self; }); var Goal = Container.expand(function () { var self = Container.call(this); // Create goal graphic self.graphic = self.attachAsset('goal', { anchorX: 0.5, anchorY: 0.5 }); // Animate the goal self.animateGoal = function () { tween(self, { rotation: Math.PI * 2 }, { duration: 3000, onFinish: function onFinish() { self.rotation = 0; self.animateGoal(); } }); }; // Start animation self.animateGoal(); return self; }); var Hazard = Container.expand(function () { var self = Container.call(this); // Create hazard graphic self.graphic = self.attachAsset('hazard', { anchorX: 0.5, anchorY: 0.5 }); return self; }); var LevelButton = Container.expand(function (levelNum) { var self = Container.call(this); self.levelNum = levelNum; // Create button background self.background = self.attachAsset('levelSelectButton', { anchorX: 0.5, anchorY: 0.5 }); // Create level text self.text = new Text2(levelNum.toString(), { size: 50, fill: 0xFFFFFF }); self.text.anchor.set(0.5, 0.5); self.addChild(self.text); // Interactive events self.down = function (x, y, obj) { if (storage.unlockedLevels >= self.levelNum) { tween(self, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100 }); } }; self.up = function (x, y, obj) { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 100, onFinish: function onFinish() { if (storage.unlockedLevels >= self.levelNum) { storage.currentLevel = self.levelNum; startGame(); } } }); }; // Update appearance based on level unlock status self.updateAppearance = function () { if (storage.unlockedLevels >= self.levelNum) { self.background.alpha = 1; self.text.alpha = 1; } else { self.background.alpha = 0.5; self.text.setText("🔒"); } }; self.updateAppearance(); return self; }); var Platform = Container.expand(function (type) { var self = Container.call(this); // Platform properties self.type = type || 'light'; // 'light' or 'shadow' // Create platform graphic self.graphic = self.attachAsset(self.type === 'light' ? 'lightPlatform' : 'shadowPlatform', { anchorX: 0.5, anchorY: 0.5 }); // Check if platform is solid in current dimension self.isSolid = function (isDimensionLight) { return self.type === 'light' && isDimensionLight || self.type === 'shadow' && !isDimensionLight; }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); // Player properties self.velocityX = 0; self.velocityY = 0; self.speed = 8; self.jumpForce = -20; self.gravity = 1; self.isGrounded = false; self.isDimensionLight = true; self.isDead = false; // Create light and shadow versions of player self.lightForm = self.attachAsset('playerLight', { anchorX: 0.5, anchorY: 0.5 }); self.shadowForm = self.attachAsset('playerShadow', { anchorX: 0.5, anchorY: 0.5, visible: false }); // Swap dimensions self.swapDimension = function () { if (self.isDead) { return; } self.isDimensionLight = !self.isDimensionLight; self.lightForm.visible = self.isDimensionLight; self.shadowForm.visible = !self.isDimensionLight; LK.getSound('swap').play(); // Visual effect for dimension swap LK.effects.flashObject(self, self.isDimensionLight ? 0xFFFFFF : 0x000000, 300); }; // Jump action self.jump = function () { if (self.isGrounded && !self.isDead) { self.velocityY = self.jumpForce; self.isGrounded = false; LK.getSound('jump').play(); } }; // Move left self.moveLeft = function () { if (!self.isDead) { self.velocityX = -self.speed; } }; // Move right self.moveRight = function () { if (!self.isDead) { self.velocityX = self.speed; } }; // Stop horizontal movement self.stopMoving = function () { self.velocityX = 0; }; // Kill player self.die = function () { if (!self.isDead) { self.isDead = true; LK.getSound('death').play(); tween(self, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { // Let the game handle the reset restartLevel(); } }); } }; // Physics update self.update = function () { if (self.isDead) { return; } // Apply gravity self.velocityY += self.gravity; // Apply velocities self.x += self.velocityX; self.y += self.velocityY; // Simple friction if (Math.abs(self.velocityX) > 0.1) { self.velocityX *= 0.9; } else { self.velocityX = 0; } // Screen bounds if (self.x < 30) { self.x = 30; } else if (self.x > 2048 - 30) { self.x = 2048 - 30; } if (self.y > 2732) { self.die(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // Game states var STATE_MENU = 'menu'; var STATE_GAME = 'game'; var gameState = STATE_MENU; // Game elements var player; var platforms = []; var hazards = []; var dimensionSwitches = []; var goal; var levelButtons = []; var touchControls = {}; var background; // Game logic variables var totalLevels = 5; var currentLevel = storage.currentLevel || 1; var isSwapEnabled = true; var swapCooldown = 0; var levelComplete = false; // Level designs var levels = [ // Level 1: Simple introduction { playerStart: { x: 300, y: 300 }, platforms: [{ x: 300, y: 400, type: 'light', width: 1 }, { x: 600, y: 600, type: 'shadow', width: 1 }, { x: 900, y: 800, type: 'light', width: 1 }, { x: 1200, y: 1000, type: 'shadow', width: 1 }, { x: 1500, y: 1200, type: 'light', width: 1 }], dimensionSwitches: [{ x: 600, y: 520 }, { x: 1200, y: 920 }], hazards: [], goal: { x: 1500, y: 1120 } }, // Level 2: Platforms and hazards { playerStart: { x: 200, y: 300 }, platforms: [{ x: 200, y: 400, type: 'light', width: 1 }, { x: 500, y: 500, type: 'shadow', width: 1 }, { x: 800, y: 600, type: 'light', width: 1 }, { x: 1100, y: 700, type: 'shadow', width: 1 }, { x: 1400, y: 800, type: 'light', width: 1 }, { x: 1700, y: 900, type: 'shadow', width: 1 }], dimensionSwitches: [{ x: 500, y: 420 }, { x: 1100, y: 620 }], hazards: [{ x: 800, y: 500 }, { x: 1400, y: 700 }], goal: { x: 1700, y: 820 } }, // Level 3: More complex puzzle { playerStart: { x: 150, y: 300 }, platforms: [{ x: 150, y: 400, type: 'light', width: 1 }, { x: 450, y: 400, type: 'shadow', width: 1 }, { x: 750, y: 500, type: 'light', width: 1 }, { x: 1050, y: 500, type: 'shadow', width: 1 }, { x: 1350, y: 600, type: 'light', width: 1 }, { x: 1650, y: 600, type: 'shadow', width: 1 }, { x: 1650, y: 800, type: 'light', width: 1 }, { x: 1350, y: 800, type: 'shadow', width: 1 }, { x: 1050, y: 1000, type: 'light', width: 1 }, { x: 750, y: 1000, type: 'shadow', width: 1 }], dimensionSwitches: [{ x: 450, y: 320 }, { x: 1050, y: 420 }, { x: 1650, y: 520 }, { x: 1050, y: 920 }], hazards: [{ x: 750, y: 400 }, { x: 1350, y: 500 }, { x: 1350, y: 900 }], goal: { x: 750, y: 920 } }, // Level 4: Advanced obstacles { playerStart: { x: 200, y: 200 }, platforms: [{ x: 200, y: 300, type: 'light', width: 1 }, { x: 500, y: 300, type: 'shadow', width: 1 }, { x: 800, y: 400, type: 'light', width: 1 }, { x: 1100, y: 400, type: 'shadow', width: 1 }, { x: 1400, y: 500, type: 'light', width: 1 }, { x: 1700, y: 500, type: 'shadow', width: 1 }, { x: 1400, y: 700, type: 'shadow', width: 1 }, { x: 1100, y: 700, type: 'light', width: 1 }, { x: 800, y: 900, type: 'shadow', width: 1 }, { x: 500, y: 900, type: 'light', width: 1 }, { x: 200, y: 1100, type: 'shadow', width: 1 }, { x: 500, y: 1100, type: 'light', width: 1 }], dimensionSwitches: [{ x: 500, y: 220 }, { x: 1100, y: 320 }, { x: 1400, y: 620 }, { x: 800, y: 820 }, { x: 200, y: 1020 }], hazards: [{ x: 800, y: 300 }, { x: 1400, y: 400 }, { x: 1100, y: 600 }, { x: 500, y: 800 }], goal: { x: 500, y: 1020 } }, // Level 5: Final challenge { playerStart: { x: 150, y: 200 }, platforms: [{ x: 150, y: 300, type: 'light', width: 1 }, { x: 450, y: 400, type: 'shadow', width: 1 }, { x: 750, y: 500, type: 'light', width: 1 }, { x: 1050, y: 600, type: 'shadow', width: 1 }, { x: 1350, y: 700, type: 'light', width: 1 }, { x: 1650, y: 800, type: 'shadow', width: 1 }, { x: 1350, y: 1000, type: 'shadow', width: 1 }, { x: 1050, y: 1200, type: 'light', width: 1 }, { x: 750, y: 1400, type: 'shadow', width: 1 }, { x: 450, y: 1600, type: 'light', width: 1 }, { x: 750, y: 1800, type: 'shadow', width: 1 }, { x: 1050, y: 2000, type: 'light', width: 1 }, { x: 1350, y: 2200, type: 'shadow', width: 1 }, { x: 1650, y: 2400, type: 'light', width: 1 }], dimensionSwitches: [{ x: 450, y: 320 }, { x: 1050, y: 520 }, { x: 1650, y: 720 }, { x: 1050, y: 1120 }, { x: 450, y: 1520 }, { x: 1050, y: 1920 }, { x: 1650, y: 2320 }], hazards: [{ x: 750, y: 400 }, { x: 1350, y: 600 }, { x: 1350, y: 900 }, { x: 750, y: 1300 }, { x: 750, y: 1700 }, { x: 1350, y: 2100 }], goal: { x: 1650, y: 2320 } }]; // Initialize menu function setupMenu() { gameState = STATE_MENU; clearLevel(); // Create title text var titleText = new Text2("SHADOW SWAP", { size: 100, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 2048 / 2; titleText.y = 400; game.addChild(titleText); // Create level selection text var levelSelectText = new Text2("SELECT LEVEL", { size: 60, fill: 0xFFFFFF }); levelSelectText.anchor.set(0.5, 0.5); levelSelectText.x = 2048 / 2; levelSelectText.y = 550; game.addChild(levelSelectText); // Create level selection buttons for (var i = 0; i < totalLevels; i++) { var button = new LevelButton(i + 1); button.x = 2048 / 2 + (i - 2) * 250; button.y = 700; levelButtons.push(button); game.addChild(button); } // Create instruction text var instructionText = new Text2("CONTROLS:\n" + "- TAP LEFT/RIGHT SIDES TO MOVE\n" + "- TAP CENTER TO JUMP\n" + "- SWIPE UP TO SWAP DIMENSIONS\n\n" + "GOAL:\n" + "- NAVIGATE THROUGH PLATFORMS\n" + "- LIGHT PLATFORMS ARE SOLID IN LIGHT DIMENSION\n" + "- SHADOW PLATFORMS ARE SOLID IN SHADOW DIMENSION\n" + "- REACH THE GREEN GOAL TO COMPLETE LEVEL", { size: 40, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 0); instructionText.x = 2048 / 2; instructionText.y = 900; game.addChild(instructionText); } // Start game with the selected level function startGame() { gameState = STATE_GAME; clearLevel(); setupLevel(storage.currentLevel); LK.playMusic('gameBgm'); } // Clear all game elements function clearLevel() { // Remove all game objects if (player) { game.removeChild(player); player = null; } platforms.forEach(function (platform) { game.removeChild(platform); }); platforms = []; hazards.forEach(function (hazard) { game.removeChild(hazard); }); hazards = []; dimensionSwitches.forEach(function (dimensionSwitch) { game.removeChild(dimensionSwitch); }); dimensionSwitches = []; if (goal) { game.removeChild(goal); goal = null; } levelButtons.forEach(function (button) { game.removeChild(button); }); levelButtons = []; // Remove any other UI elements for (var key in touchControls) { if (touchControls[key]) { game.removeChild(touchControls[key]); } } touchControls = {}; // Reset game state levelComplete = false; isSwapEnabled = true; swapCooldown = 0; // Clear any existing children while (game.children.length > 0) { game.removeChild(game.children[0]); } } // Set up a level function setupLevel(levelNum) { currentLevel = levelNum; var levelData = levels[levelNum - 1] || levels[0]; // Create background background = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5, alpha: 0.3 }); background.x = 2048 / 2; background.y = 2732 / 2; game.addChild(background); // Create level text var levelText = new Text2("LEVEL " + currentLevel, { size: 60, fill: 0xFFFFFF }); levelText.anchor.set(0.5, 0); levelText.x = 2048 / 2; levelText.y = 50; game.addChild(levelText); // Create dimension indicator var dimensionText = new Text2("DIMENSION: LIGHT", { size: 40, fill: 0xFFFFFF }); dimensionText.anchor.set(0.5, 0); dimensionText.x = 2048 / 2; dimensionText.y = 120; game.addChild(dimensionText); touchControls.dimensionText = dimensionText; // Create player player = new Player(); player.x = levelData.playerStart.x; player.y = levelData.playerStart.y; game.addChild(player); // Create platforms levelData.platforms.forEach(function (platformData) { var platform = new Platform(platformData.type); platform.x = platformData.x; platform.y = platformData.y; // Apply custom width if specified if (platformData.width && platformData.width > 1) { platform.graphic.scaleX = platformData.width; } platforms.push(platform); game.addChild(platform); }); // Create dimension switches levelData.dimensionSwitches.forEach(function (switchData) { var dimensionSwitch = new DimensionSwitch(); dimensionSwitch.x = switchData.x; dimensionSwitch.y = switchData.y; dimensionSwitches.push(dimensionSwitch); game.addChild(dimensionSwitch); }); // Create hazards levelData.hazards.forEach(function (hazardData) { var hazard = new Hazard(); hazard.x = hazardData.x; hazard.y = hazardData.y; hazards.push(hazard); game.addChild(hazard); }); // Create goal goal = new Goal(); goal.x = levelData.goal.x; goal.y = levelData.goal.y; game.addChild(goal); // Touch controls areas (invisible) var leftControl = LK.getAsset('lightPlatform', { anchorX: 0, anchorY: 0, alpha: 0 }); leftControl.width = 2048 / 3; leftControl.height = 2732; leftControl.x = 0; leftControl.y = 0; game.addChild(leftControl); touchControls.left = leftControl; var rightControl = LK.getAsset('lightPlatform', { anchorX: 0, anchorY: 0, alpha: 0 }); rightControl.width = 2048 / 3; rightControl.height = 2732; rightControl.x = 2048 * 2 / 3; rightControl.y = 0; game.addChild(rightControl); touchControls.right = rightControl; var centerControl = LK.getAsset('lightPlatform', { anchorX: 0, anchorY: 0, alpha: 0 }); centerControl.width = 2048 / 3; centerControl.height = 2732; centerControl.x = 2048 / 3; centerControl.y = 0; game.addChild(centerControl); touchControls.center = centerControl; } // Restart current level function restartLevel() { clearLevel(); setupLevel(currentLevel); } // Complete level and move to next function completeLevel() { if (!levelComplete) { levelComplete = true; LK.getSound('win').play(); // Update unlocked levels if (currentLevel >= storage.unlockedLevels) { storage.unlockedLevels = currentLevel + 1; if (storage.unlockedLevels > totalLevels) { storage.unlockedLevels = totalLevels; } } // Show win animation tween(player, { scaleX: 1.5, scaleY: 1.5 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { LK.showYouWin(); // Move to next level if (currentLevel < totalLevels) { storage.currentLevel = currentLevel + 1; } else { // If all levels completed, go back to menu setupMenu(); } } }); } } // Check collisions between player and platforms function checkPlatformCollisions() { var wasGrounded = player.isGrounded; player.isGrounded = false; platforms.forEach(function (platform) { if (platform.isSolid(player.isDimensionLight) && player.intersects(platform)) { // Calculate collision sides var playerBottom = player.y + player.lightForm.height / 2; var playerTop = player.y - player.lightForm.height / 2; var playerLeft = player.x - player.lightForm.width / 2; var playerRight = player.x + player.lightForm.width / 2; var platformBottom = platform.y + platform.graphic.height / 2; var platformTop = platform.y - platform.graphic.height / 2; var platformLeft = platform.x - platform.graphic.width / 2; var platformRight = platform.x + platform.graphic.width / 2; // Calculate penetration depths var fromTop = playerBottom - platformTop; var fromBottom = platformBottom - playerTop; var fromLeft = playerRight - platformLeft; var fromRight = platformRight - playerLeft; // Find minimum penetration var minPenetration = Math.min(fromTop, fromBottom, fromLeft, fromRight); // Resolve collision based on minimum penetration if (minPenetration === fromTop && player.velocityY > 0) { player.y = platformTop - player.lightForm.height / 2; player.velocityY = 0; player.isGrounded = true; } else if (minPenetration === fromBottom && player.velocityY < 0) { player.y = platformBottom + player.lightForm.height / 2; player.velocityY = 0; } else if (minPenetration === fromLeft && player.velocityX > 0) { player.x = platformLeft - player.lightForm.width / 2; player.velocityX = 0; } else if (minPenetration === fromRight && player.velocityX < 0) { player.x = platformRight + player.lightForm.width / 2; player.velocityX = 0; } } }); // Landing effect if (!wasGrounded && player.isGrounded) { tween(player, { scaleX: 1.2, scaleY: 0.8 }, { duration: 100, onFinish: function onFinish() { tween(player, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); } } // Check other game object interactions function checkInteractions() { // Check dimension switches dimensionSwitches.forEach(function (dimensionSwitch) { if (player.intersects(dimensionSwitch) && isSwapEnabled) { player.swapDimension(); isSwapEnabled = false; swapCooldown = 30; // Half-second cooldown at 60 FPS // Update dimension text if (touchControls.dimensionText) { touchControls.dimensionText.setText("DIMENSION: " + (player.isDimensionLight ? "LIGHT" : "SHADOW")); } // Animate the switch tween(dimensionSwitch, { scaleX: 1.5, scaleY: 1.5 }, { duration: 200, onFinish: function onFinish() { tween(dimensionSwitch, { scaleX: 1, scaleY: 1 }, { duration: 200 }); } }); } }); // Check hazards hazards.forEach(function (hazard) { if (player.intersects(hazard)) { player.die(); } }); // Check goal if (player.intersects(goal)) { completeLevel(); } // Swap cooldown if (!isSwapEnabled) { swapCooldown--; if (swapCooldown <= 0) { isSwapEnabled = true; } } } // Touch controls var touchStart = { x: 0, y: 0 }; var isTouching = false; var movingLeft = false; var movingRight = false; game.down = function (x, y, obj) { if (gameState === STATE_GAME) { touchStart.x = x; touchStart.y = y; isTouching = true; // Check which control area was touched if (x < 2048 / 3) { // Left side - move left movingLeft = true; player.moveLeft(); } else if (x > 2048 * 2 / 3) { // Right side - move right movingRight = true; player.moveRight(); } else { // Center - jump player.jump(); } } }; game.move = function (x, y, obj) { if (gameState === STATE_GAME && isTouching) { // Check for swipe up (dimension swap) if (y < touchStart.y - 100) { if (isSwapEnabled) { player.swapDimension(); isSwapEnabled = false; swapCooldown = 30; // Update dimension text if (touchControls.dimensionText) { touchControls.dimensionText.setText("DIMENSION: " + (player.isDimensionLight ? "LIGHT" : "SHADOW")); } } // Reset touch to prevent multiple swipes isTouching = false; } } }; game.up = function (x, y, obj) { if (gameState === STATE_GAME) { isTouching = false; // Stop horizontal movement if this was a movement control if (movingLeft || movingRight) { player.stopMoving(); movingLeft = false; movingRight = false; } } }; // Main game update loop game.update = function () { if (gameState === STATE_GAME && !levelComplete && player && !player.isDead) { // Update player physics player.update(); // Check collisions and interactions checkPlatformCollisions(); checkInteractions(); } }; // Initialize the game with the menu setupMenu();
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,1091 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ currentLevel: 1,
+ unlockedLevels: 1
+});
+
+/****
+* Classes
+****/
+var DimensionSwitch = Container.expand(function () {
+ var self = Container.call(this);
+ // Create switch graphic
+ self.graphic = self.attachAsset('dimensionSwitch', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Create pulsing animation
+ self.pulseAnimation = function () {
+ tween(self.graphic, {
+ scaleX: 1.2,
+ scaleY: 1.2
+ }, {
+ duration: 500,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ tween(self.graphic, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 500,
+ easing: tween.easeInOut,
+ onFinish: self.pulseAnimation
+ });
+ }
+ });
+ };
+ // Start pulsing
+ self.pulseAnimation();
+ return self;
+});
+var Goal = Container.expand(function () {
+ var self = Container.call(this);
+ // Create goal graphic
+ self.graphic = self.attachAsset('goal', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Animate the goal
+ self.animateGoal = function () {
+ tween(self, {
+ rotation: Math.PI * 2
+ }, {
+ duration: 3000,
+ onFinish: function onFinish() {
+ self.rotation = 0;
+ self.animateGoal();
+ }
+ });
+ };
+ // Start animation
+ self.animateGoal();
+ return self;
+});
+var Hazard = Container.expand(function () {
+ var self = Container.call(this);
+ // Create hazard graphic
+ self.graphic = self.attachAsset('hazard', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ return self;
+});
+var LevelButton = Container.expand(function (levelNum) {
+ var self = Container.call(this);
+ self.levelNum = levelNum;
+ // Create button background
+ self.background = self.attachAsset('levelSelectButton', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Create level text
+ self.text = new Text2(levelNum.toString(), {
+ size: 50,
+ fill: 0xFFFFFF
+ });
+ self.text.anchor.set(0.5, 0.5);
+ self.addChild(self.text);
+ // Interactive events
+ self.down = function (x, y, obj) {
+ if (storage.unlockedLevels >= self.levelNum) {
+ tween(self, {
+ scaleX: 0.9,
+ scaleY: 0.9
+ }, {
+ duration: 100
+ });
+ }
+ };
+ self.up = function (x, y, obj) {
+ tween(self, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 100,
+ onFinish: function onFinish() {
+ if (storage.unlockedLevels >= self.levelNum) {
+ storage.currentLevel = self.levelNum;
+ startGame();
+ }
+ }
+ });
+ };
+ // Update appearance based on level unlock status
+ self.updateAppearance = function () {
+ if (storage.unlockedLevels >= self.levelNum) {
+ self.background.alpha = 1;
+ self.text.alpha = 1;
+ } else {
+ self.background.alpha = 0.5;
+ self.text.setText("🔒");
+ }
+ };
+ self.updateAppearance();
+ return self;
+});
+var Platform = Container.expand(function (type) {
+ var self = Container.call(this);
+ // Platform properties
+ self.type = type || 'light'; // 'light' or 'shadow'
+ // Create platform graphic
+ self.graphic = self.attachAsset(self.type === 'light' ? 'lightPlatform' : 'shadowPlatform', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Check if platform is solid in current dimension
+ self.isSolid = function (isDimensionLight) {
+ return self.type === 'light' && isDimensionLight || self.type === 'shadow' && !isDimensionLight;
+ };
+ return self;
+});
+var Player = Container.expand(function () {
+ var self = Container.call(this);
+ // Player properties
+ self.velocityX = 0;
+ self.velocityY = 0;
+ self.speed = 8;
+ self.jumpForce = -20;
+ self.gravity = 1;
+ self.isGrounded = false;
+ self.isDimensionLight = true;
+ self.isDead = false;
+ // Create light and shadow versions of player
+ self.lightForm = self.attachAsset('playerLight', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.shadowForm = self.attachAsset('playerShadow', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ visible: false
+ });
+ // Swap dimensions
+ self.swapDimension = function () {
+ if (self.isDead) {
+ return;
+ }
+ self.isDimensionLight = !self.isDimensionLight;
+ self.lightForm.visible = self.isDimensionLight;
+ self.shadowForm.visible = !self.isDimensionLight;
+ LK.getSound('swap').play();
+ // Visual effect for dimension swap
+ LK.effects.flashObject(self, self.isDimensionLight ? 0xFFFFFF : 0x000000, 300);
+ };
+ // Jump action
+ self.jump = function () {
+ if (self.isGrounded && !self.isDead) {
+ self.velocityY = self.jumpForce;
+ self.isGrounded = false;
+ LK.getSound('jump').play();
+ }
+ };
+ // Move left
+ self.moveLeft = function () {
+ if (!self.isDead) {
+ self.velocityX = -self.speed;
+ }
+ };
+ // Move right
+ self.moveRight = function () {
+ if (!self.isDead) {
+ self.velocityX = self.speed;
+ }
+ };
+ // Stop horizontal movement
+ self.stopMoving = function () {
+ self.velocityX = 0;
+ };
+ // Kill player
+ self.die = function () {
+ if (!self.isDead) {
+ self.isDead = true;
+ LK.getSound('death').play();
+ tween(self, {
+ alpha: 0
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ // Let the game handle the reset
+ restartLevel();
+ }
+ });
+ }
+ };
+ // Physics update
+ self.update = function () {
+ if (self.isDead) {
+ return;
+ }
+ // Apply gravity
+ self.velocityY += self.gravity;
+ // Apply velocities
+ self.x += self.velocityX;
+ self.y += self.velocityY;
+ // Simple friction
+ if (Math.abs(self.velocityX) > 0.1) {
+ self.velocityX *= 0.9;
+ } else {
+ self.velocityX = 0;
+ }
+ // Screen bounds
+ if (self.x < 30) {
+ self.x = 30;
+ } else if (self.x > 2048 - 30) {
+ self.x = 2048 - 30;
+ }
+ if (self.y > 2732) {
+ self.die();
+ }
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x222222
+});
+
+/****
+* Game Code
+****/
+// Game states
+var STATE_MENU = 'menu';
+var STATE_GAME = 'game';
+var gameState = STATE_MENU;
+// Game elements
+var player;
+var platforms = [];
+var hazards = [];
+var dimensionSwitches = [];
+var goal;
+var levelButtons = [];
+var touchControls = {};
+var background;
+// Game logic variables
+var totalLevels = 5;
+var currentLevel = storage.currentLevel || 1;
+var isSwapEnabled = true;
+var swapCooldown = 0;
+var levelComplete = false;
+// Level designs
+var levels = [
+// Level 1: Simple introduction
+{
+ playerStart: {
+ x: 300,
+ y: 300
+ },
+ platforms: [{
+ x: 300,
+ y: 400,
+ type: 'light',
+ width: 1
+ }, {
+ x: 600,
+ y: 600,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 900,
+ y: 800,
+ type: 'light',
+ width: 1
+ }, {
+ x: 1200,
+ y: 1000,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 1500,
+ y: 1200,
+ type: 'light',
+ width: 1
+ }],
+ dimensionSwitches: [{
+ x: 600,
+ y: 520
+ }, {
+ x: 1200,
+ y: 920
+ }],
+ hazards: [],
+ goal: {
+ x: 1500,
+ y: 1120
+ }
+},
+// Level 2: Platforms and hazards
+{
+ playerStart: {
+ x: 200,
+ y: 300
+ },
+ platforms: [{
+ x: 200,
+ y: 400,
+ type: 'light',
+ width: 1
+ }, {
+ x: 500,
+ y: 500,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 800,
+ y: 600,
+ type: 'light',
+ width: 1
+ }, {
+ x: 1100,
+ y: 700,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 1400,
+ y: 800,
+ type: 'light',
+ width: 1
+ }, {
+ x: 1700,
+ y: 900,
+ type: 'shadow',
+ width: 1
+ }],
+ dimensionSwitches: [{
+ x: 500,
+ y: 420
+ }, {
+ x: 1100,
+ y: 620
+ }],
+ hazards: [{
+ x: 800,
+ y: 500
+ }, {
+ x: 1400,
+ y: 700
+ }],
+ goal: {
+ x: 1700,
+ y: 820
+ }
+},
+// Level 3: More complex puzzle
+{
+ playerStart: {
+ x: 150,
+ y: 300
+ },
+ platforms: [{
+ x: 150,
+ y: 400,
+ type: 'light',
+ width: 1
+ }, {
+ x: 450,
+ y: 400,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 750,
+ y: 500,
+ type: 'light',
+ width: 1
+ }, {
+ x: 1050,
+ y: 500,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 1350,
+ y: 600,
+ type: 'light',
+ width: 1
+ }, {
+ x: 1650,
+ y: 600,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 1650,
+ y: 800,
+ type: 'light',
+ width: 1
+ }, {
+ x: 1350,
+ y: 800,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 1050,
+ y: 1000,
+ type: 'light',
+ width: 1
+ }, {
+ x: 750,
+ y: 1000,
+ type: 'shadow',
+ width: 1
+ }],
+ dimensionSwitches: [{
+ x: 450,
+ y: 320
+ }, {
+ x: 1050,
+ y: 420
+ }, {
+ x: 1650,
+ y: 520
+ }, {
+ x: 1050,
+ y: 920
+ }],
+ hazards: [{
+ x: 750,
+ y: 400
+ }, {
+ x: 1350,
+ y: 500
+ }, {
+ x: 1350,
+ y: 900
+ }],
+ goal: {
+ x: 750,
+ y: 920
+ }
+},
+// Level 4: Advanced obstacles
+{
+ playerStart: {
+ x: 200,
+ y: 200
+ },
+ platforms: [{
+ x: 200,
+ y: 300,
+ type: 'light',
+ width: 1
+ }, {
+ x: 500,
+ y: 300,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 800,
+ y: 400,
+ type: 'light',
+ width: 1
+ }, {
+ x: 1100,
+ y: 400,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 1400,
+ y: 500,
+ type: 'light',
+ width: 1
+ }, {
+ x: 1700,
+ y: 500,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 1400,
+ y: 700,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 1100,
+ y: 700,
+ type: 'light',
+ width: 1
+ }, {
+ x: 800,
+ y: 900,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 500,
+ y: 900,
+ type: 'light',
+ width: 1
+ }, {
+ x: 200,
+ y: 1100,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 500,
+ y: 1100,
+ type: 'light',
+ width: 1
+ }],
+ dimensionSwitches: [{
+ x: 500,
+ y: 220
+ }, {
+ x: 1100,
+ y: 320
+ }, {
+ x: 1400,
+ y: 620
+ }, {
+ x: 800,
+ y: 820
+ }, {
+ x: 200,
+ y: 1020
+ }],
+ hazards: [{
+ x: 800,
+ y: 300
+ }, {
+ x: 1400,
+ y: 400
+ }, {
+ x: 1100,
+ y: 600
+ }, {
+ x: 500,
+ y: 800
+ }],
+ goal: {
+ x: 500,
+ y: 1020
+ }
+},
+// Level 5: Final challenge
+{
+ playerStart: {
+ x: 150,
+ y: 200
+ },
+ platforms: [{
+ x: 150,
+ y: 300,
+ type: 'light',
+ width: 1
+ }, {
+ x: 450,
+ y: 400,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 750,
+ y: 500,
+ type: 'light',
+ width: 1
+ }, {
+ x: 1050,
+ y: 600,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 1350,
+ y: 700,
+ type: 'light',
+ width: 1
+ }, {
+ x: 1650,
+ y: 800,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 1350,
+ y: 1000,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 1050,
+ y: 1200,
+ type: 'light',
+ width: 1
+ }, {
+ x: 750,
+ y: 1400,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 450,
+ y: 1600,
+ type: 'light',
+ width: 1
+ }, {
+ x: 750,
+ y: 1800,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 1050,
+ y: 2000,
+ type: 'light',
+ width: 1
+ }, {
+ x: 1350,
+ y: 2200,
+ type: 'shadow',
+ width: 1
+ }, {
+ x: 1650,
+ y: 2400,
+ type: 'light',
+ width: 1
+ }],
+ dimensionSwitches: [{
+ x: 450,
+ y: 320
+ }, {
+ x: 1050,
+ y: 520
+ }, {
+ x: 1650,
+ y: 720
+ }, {
+ x: 1050,
+ y: 1120
+ }, {
+ x: 450,
+ y: 1520
+ }, {
+ x: 1050,
+ y: 1920
+ }, {
+ x: 1650,
+ y: 2320
+ }],
+ hazards: [{
+ x: 750,
+ y: 400
+ }, {
+ x: 1350,
+ y: 600
+ }, {
+ x: 1350,
+ y: 900
+ }, {
+ x: 750,
+ y: 1300
+ }, {
+ x: 750,
+ y: 1700
+ }, {
+ x: 1350,
+ y: 2100
+ }],
+ goal: {
+ x: 1650,
+ y: 2320
+ }
+}];
+// Initialize menu
+function setupMenu() {
+ gameState = STATE_MENU;
+ clearLevel();
+ // Create title text
+ var titleText = new Text2("SHADOW SWAP", {
+ size: 100,
+ fill: 0xFFFFFF
+ });
+ titleText.anchor.set(0.5, 0.5);
+ titleText.x = 2048 / 2;
+ titleText.y = 400;
+ game.addChild(titleText);
+ // Create level selection text
+ var levelSelectText = new Text2("SELECT LEVEL", {
+ size: 60,
+ fill: 0xFFFFFF
+ });
+ levelSelectText.anchor.set(0.5, 0.5);
+ levelSelectText.x = 2048 / 2;
+ levelSelectText.y = 550;
+ game.addChild(levelSelectText);
+ // Create level selection buttons
+ for (var i = 0; i < totalLevels; i++) {
+ var button = new LevelButton(i + 1);
+ button.x = 2048 / 2 + (i - 2) * 250;
+ button.y = 700;
+ levelButtons.push(button);
+ game.addChild(button);
+ }
+ // Create instruction text
+ var instructionText = new Text2("CONTROLS:\n" + "- TAP LEFT/RIGHT SIDES TO MOVE\n" + "- TAP CENTER TO JUMP\n" + "- SWIPE UP TO SWAP DIMENSIONS\n\n" + "GOAL:\n" + "- NAVIGATE THROUGH PLATFORMS\n" + "- LIGHT PLATFORMS ARE SOLID IN LIGHT DIMENSION\n" + "- SHADOW PLATFORMS ARE SOLID IN SHADOW DIMENSION\n" + "- REACH THE GREEN GOAL TO COMPLETE LEVEL", {
+ size: 40,
+ fill: 0xFFFFFF
+ });
+ instructionText.anchor.set(0.5, 0);
+ instructionText.x = 2048 / 2;
+ instructionText.y = 900;
+ game.addChild(instructionText);
+}
+// Start game with the selected level
+function startGame() {
+ gameState = STATE_GAME;
+ clearLevel();
+ setupLevel(storage.currentLevel);
+ LK.playMusic('gameBgm');
+}
+// Clear all game elements
+function clearLevel() {
+ // Remove all game objects
+ if (player) {
+ game.removeChild(player);
+ player = null;
+ }
+ platforms.forEach(function (platform) {
+ game.removeChild(platform);
+ });
+ platforms = [];
+ hazards.forEach(function (hazard) {
+ game.removeChild(hazard);
+ });
+ hazards = [];
+ dimensionSwitches.forEach(function (dimensionSwitch) {
+ game.removeChild(dimensionSwitch);
+ });
+ dimensionSwitches = [];
+ if (goal) {
+ game.removeChild(goal);
+ goal = null;
+ }
+ levelButtons.forEach(function (button) {
+ game.removeChild(button);
+ });
+ levelButtons = [];
+ // Remove any other UI elements
+ for (var key in touchControls) {
+ if (touchControls[key]) {
+ game.removeChild(touchControls[key]);
+ }
+ }
+ touchControls = {};
+ // Reset game state
+ levelComplete = false;
+ isSwapEnabled = true;
+ swapCooldown = 0;
+ // Clear any existing children
+ while (game.children.length > 0) {
+ game.removeChild(game.children[0]);
+ }
+}
+// Set up a level
+function setupLevel(levelNum) {
+ currentLevel = levelNum;
+ var levelData = levels[levelNum - 1] || levels[0];
+ // Create background
+ background = LK.getAsset('background', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.3
+ });
+ background.x = 2048 / 2;
+ background.y = 2732 / 2;
+ game.addChild(background);
+ // Create level text
+ var levelText = new Text2("LEVEL " + currentLevel, {
+ size: 60,
+ fill: 0xFFFFFF
+ });
+ levelText.anchor.set(0.5, 0);
+ levelText.x = 2048 / 2;
+ levelText.y = 50;
+ game.addChild(levelText);
+ // Create dimension indicator
+ var dimensionText = new Text2("DIMENSION: LIGHT", {
+ size: 40,
+ fill: 0xFFFFFF
+ });
+ dimensionText.anchor.set(0.5, 0);
+ dimensionText.x = 2048 / 2;
+ dimensionText.y = 120;
+ game.addChild(dimensionText);
+ touchControls.dimensionText = dimensionText;
+ // Create player
+ player = new Player();
+ player.x = levelData.playerStart.x;
+ player.y = levelData.playerStart.y;
+ game.addChild(player);
+ // Create platforms
+ levelData.platforms.forEach(function (platformData) {
+ var platform = new Platform(platformData.type);
+ platform.x = platformData.x;
+ platform.y = platformData.y;
+ // Apply custom width if specified
+ if (platformData.width && platformData.width > 1) {
+ platform.graphic.scaleX = platformData.width;
+ }
+ platforms.push(platform);
+ game.addChild(platform);
+ });
+ // Create dimension switches
+ levelData.dimensionSwitches.forEach(function (switchData) {
+ var dimensionSwitch = new DimensionSwitch();
+ dimensionSwitch.x = switchData.x;
+ dimensionSwitch.y = switchData.y;
+ dimensionSwitches.push(dimensionSwitch);
+ game.addChild(dimensionSwitch);
+ });
+ // Create hazards
+ levelData.hazards.forEach(function (hazardData) {
+ var hazard = new Hazard();
+ hazard.x = hazardData.x;
+ hazard.y = hazardData.y;
+ hazards.push(hazard);
+ game.addChild(hazard);
+ });
+ // Create goal
+ goal = new Goal();
+ goal.x = levelData.goal.x;
+ goal.y = levelData.goal.y;
+ game.addChild(goal);
+ // Touch controls areas (invisible)
+ var leftControl = LK.getAsset('lightPlatform', {
+ anchorX: 0,
+ anchorY: 0,
+ alpha: 0
+ });
+ leftControl.width = 2048 / 3;
+ leftControl.height = 2732;
+ leftControl.x = 0;
+ leftControl.y = 0;
+ game.addChild(leftControl);
+ touchControls.left = leftControl;
+ var rightControl = LK.getAsset('lightPlatform', {
+ anchorX: 0,
+ anchorY: 0,
+ alpha: 0
+ });
+ rightControl.width = 2048 / 3;
+ rightControl.height = 2732;
+ rightControl.x = 2048 * 2 / 3;
+ rightControl.y = 0;
+ game.addChild(rightControl);
+ touchControls.right = rightControl;
+ var centerControl = LK.getAsset('lightPlatform', {
+ anchorX: 0,
+ anchorY: 0,
+ alpha: 0
+ });
+ centerControl.width = 2048 / 3;
+ centerControl.height = 2732;
+ centerControl.x = 2048 / 3;
+ centerControl.y = 0;
+ game.addChild(centerControl);
+ touchControls.center = centerControl;
+}
+// Restart current level
+function restartLevel() {
+ clearLevel();
+ setupLevel(currentLevel);
+}
+// Complete level and move to next
+function completeLevel() {
+ if (!levelComplete) {
+ levelComplete = true;
+ LK.getSound('win').play();
+ // Update unlocked levels
+ if (currentLevel >= storage.unlockedLevels) {
+ storage.unlockedLevels = currentLevel + 1;
+ if (storage.unlockedLevels > totalLevels) {
+ storage.unlockedLevels = totalLevels;
+ }
+ }
+ // Show win animation
+ tween(player, {
+ scaleX: 1.5,
+ scaleY: 1.5
+ }, {
+ duration: 500,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ LK.showYouWin();
+ // Move to next level
+ if (currentLevel < totalLevels) {
+ storage.currentLevel = currentLevel + 1;
+ } else {
+ // If all levels completed, go back to menu
+ setupMenu();
+ }
+ }
+ });
+ }
+}
+// Check collisions between player and platforms
+function checkPlatformCollisions() {
+ var wasGrounded = player.isGrounded;
+ player.isGrounded = false;
+ platforms.forEach(function (platform) {
+ if (platform.isSolid(player.isDimensionLight) && player.intersects(platform)) {
+ // Calculate collision sides
+ var playerBottom = player.y + player.lightForm.height / 2;
+ var playerTop = player.y - player.lightForm.height / 2;
+ var playerLeft = player.x - player.lightForm.width / 2;
+ var playerRight = player.x + player.lightForm.width / 2;
+ var platformBottom = platform.y + platform.graphic.height / 2;
+ var platformTop = platform.y - platform.graphic.height / 2;
+ var platformLeft = platform.x - platform.graphic.width / 2;
+ var platformRight = platform.x + platform.graphic.width / 2;
+ // Calculate penetration depths
+ var fromTop = playerBottom - platformTop;
+ var fromBottom = platformBottom - playerTop;
+ var fromLeft = playerRight - platformLeft;
+ var fromRight = platformRight - playerLeft;
+ // Find minimum penetration
+ var minPenetration = Math.min(fromTop, fromBottom, fromLeft, fromRight);
+ // Resolve collision based on minimum penetration
+ if (minPenetration === fromTop && player.velocityY > 0) {
+ player.y = platformTop - player.lightForm.height / 2;
+ player.velocityY = 0;
+ player.isGrounded = true;
+ } else if (minPenetration === fromBottom && player.velocityY < 0) {
+ player.y = platformBottom + player.lightForm.height / 2;
+ player.velocityY = 0;
+ } else if (minPenetration === fromLeft && player.velocityX > 0) {
+ player.x = platformLeft - player.lightForm.width / 2;
+ player.velocityX = 0;
+ } else if (minPenetration === fromRight && player.velocityX < 0) {
+ player.x = platformRight + player.lightForm.width / 2;
+ player.velocityX = 0;
+ }
+ }
+ });
+ // Landing effect
+ if (!wasGrounded && player.isGrounded) {
+ tween(player, {
+ scaleX: 1.2,
+ scaleY: 0.8
+ }, {
+ duration: 100,
+ onFinish: function onFinish() {
+ tween(player, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 100
+ });
+ }
+ });
+ }
+}
+// Check other game object interactions
+function checkInteractions() {
+ // Check dimension switches
+ dimensionSwitches.forEach(function (dimensionSwitch) {
+ if (player.intersects(dimensionSwitch) && isSwapEnabled) {
+ player.swapDimension();
+ isSwapEnabled = false;
+ swapCooldown = 30; // Half-second cooldown at 60 FPS
+ // Update dimension text
+ if (touchControls.dimensionText) {
+ touchControls.dimensionText.setText("DIMENSION: " + (player.isDimensionLight ? "LIGHT" : "SHADOW"));
+ }
+ // Animate the switch
+ tween(dimensionSwitch, {
+ scaleX: 1.5,
+ scaleY: 1.5
+ }, {
+ duration: 200,
+ onFinish: function onFinish() {
+ tween(dimensionSwitch, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 200
+ });
+ }
+ });
+ }
+ });
+ // Check hazards
+ hazards.forEach(function (hazard) {
+ if (player.intersects(hazard)) {
+ player.die();
+ }
+ });
+ // Check goal
+ if (player.intersects(goal)) {
+ completeLevel();
+ }
+ // Swap cooldown
+ if (!isSwapEnabled) {
+ swapCooldown--;
+ if (swapCooldown <= 0) {
+ isSwapEnabled = true;
+ }
+ }
+}
+// Touch controls
+var touchStart = {
+ x: 0,
+ y: 0
+};
+var isTouching = false;
+var movingLeft = false;
+var movingRight = false;
+game.down = function (x, y, obj) {
+ if (gameState === STATE_GAME) {
+ touchStart.x = x;
+ touchStart.y = y;
+ isTouching = true;
+ // Check which control area was touched
+ if (x < 2048 / 3) {
+ // Left side - move left
+ movingLeft = true;
+ player.moveLeft();
+ } else if (x > 2048 * 2 / 3) {
+ // Right side - move right
+ movingRight = true;
+ player.moveRight();
+ } else {
+ // Center - jump
+ player.jump();
+ }
+ }
+};
+game.move = function (x, y, obj) {
+ if (gameState === STATE_GAME && isTouching) {
+ // Check for swipe up (dimension swap)
+ if (y < touchStart.y - 100) {
+ if (isSwapEnabled) {
+ player.swapDimension();
+ isSwapEnabled = false;
+ swapCooldown = 30;
+ // Update dimension text
+ if (touchControls.dimensionText) {
+ touchControls.dimensionText.setText("DIMENSION: " + (player.isDimensionLight ? "LIGHT" : "SHADOW"));
+ }
+ }
+ // Reset touch to prevent multiple swipes
+ isTouching = false;
+ }
+ }
+};
+game.up = function (x, y, obj) {
+ if (gameState === STATE_GAME) {
+ isTouching = false;
+ // Stop horizontal movement if this was a movement control
+ if (movingLeft || movingRight) {
+ player.stopMoving();
+ movingLeft = false;
+ movingRight = false;
+ }
+ }
+};
+// Main game update loop
+game.update = function () {
+ if (gameState === STATE_GAME && !levelComplete && player && !player.isDead) {
+ // Update player physics
+ player.update();
+ // Check collisions and interactions
+ checkPlatformCollisions();
+ checkInteractions();
+ }
+};
+// Initialize the game with the menu
+setupMenu();
\ No newline at end of file
Switch. In-Game asset. 2d. High contrast. No shadows
Trophy. In-Game asset. 2d. High contrast. No shadows
Hazard. In-Game asset. 2d. High contrast. No shadows
A shadow ninja. In-Game asset. 2d. High contrast. No shadows
A shadow ninja. In-Game asset. 2d. High contrast. shadow
Shadow platform. In-Game asset. 2d. High contrast. No shadows