/****
* Plugins
****/
var storage = LK.import("@upit/storage.v1", {
coins: 0,
selectedSkin: 0,
unlockedSkins: [0],
highScore: 0,
soundVolume: 1,
musicVolume: 1,
soundMuted: false,
musicMuted: false
});
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.moveSpeed = 2;
self.direction = 1;
self.startX = 0;
self.range = 200;
self.update = function () {
self.x += self.moveSpeed * self.direction;
if (self.x > self.startX + self.range || self.x < self.startX - self.range) {
self.direction *= -1;
}
// Rotation for visual effect
obstacleGraphics.rotation += 0.1;
};
return self;
});
var Platform = Container.expand(function (width, height) {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: width / 200,
scaleY: height / 20
});
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.onGround = false;
self.moveSpeed = 8;
self.jumpPower = 22.5;
self.gravity = 0.8;
self.maxVelocityY = 20;
self.update = function () {
// Apply physics based on current dimension
self.applyPhysics();
// Update position
self.x += self.velocityX;
self.y += self.velocityY;
// Keep player on screen horizontally
if (self.x < 20) {
self.x = 20;
}
if (self.x > 2028) {
self.x = 2028;
}
// Check platform collisions
self.checkPlatformCollisions();
// Check if player falls off screen or goes above screen
if (self.y > 2800 || self.y < -50) {
self.resetPosition();
}
};
self.applyPhysics = function () {
if (currentDimension === 0) {
// Normal gravity
self.velocityY += self.gravity;
} else if (currentDimension === 1) {
// Reverse gravity
self.velocityY -= self.gravity;
} else if (currentDimension === 2) {
// Underwater - slower movement
self.velocityY += self.gravity * 0.3;
self.velocityX *= 0.9;
} else if (currentDimension === 3) {
// Low gravity
self.velocityY += self.gravity * 0.4;
} else if (currentDimension === 4) {
// Ice - slippery
self.velocityY += self.gravity;
self.velocityX *= 0.98;
}
// Limit velocity
if (self.velocityY > self.maxVelocityY) {
self.velocityY = self.maxVelocityY;
}
if (self.velocityY < -self.maxVelocityY) {
self.velocityY = -self.maxVelocityY;
}
};
self.checkPlatformCollisions = function () {
self.onGround = false;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
if (self.intersects(platform)) {
if (currentDimension === 1) {
// Reverse gravity - land on top of platforms
if (self.velocityY < 0) {
self.y = platform.y + platform.height / 2 + self.height / 2;
self.velocityY = 0;
self.onGround = true;
}
} else {
// Normal - land on bottom of platforms
if (self.velocityY > 0) {
self.y = platform.y - platform.height / 2 - self.height / 2;
self.velocityY = 0;
self.onGround = true;
}
}
}
}
};
self.jump = function () {
if (self.onGround) {
if (currentDimension === 1) {
// Reverse gravity jump
self.velocityY = self.jumpPower;
} else {
self.velocityY = -self.jumpPower;
}
playSound('jump');
}
};
self.moveLeft = function () {
if (currentDimension === 4) {
// Ice - reduced control
self.velocityX -= self.moveSpeed * 0.3;
} else {
self.velocityX = -self.moveSpeed;
}
};
self.moveRight = function () {
if (currentDimension === 4) {
// Ice - reduced control
self.velocityX += self.moveSpeed * 0.3;
} else {
self.velocityX = self.moveSpeed;
}
};
self.resetPosition = function () {
playSound('fall');
self.x = 200;
self.y = 1000;
self.velocityX = 0;
self.velocityY = 0;
};
return self;
});
var Portal = Container.expand(function () {
var self = Container.call(this);
var portalGraphics = self.attachAsset('portal', {
anchorX: 0.5,
anchorY: 0.5
});
self.pulseScale = 1;
self.pulseDirection = 1;
self.update = function () {
// Pulse animation
self.pulseScale += self.pulseDirection * 0.02;
if (self.pulseScale > 1.2) {
self.pulseScale = 1.2;
self.pulseDirection = -1;
} else if (self.pulseScale < 0.8) {
self.pulseScale = 0.8;
self.pulseDirection = 1;
}
portalGraphics.scaleX = self.pulseScale;
portalGraphics.scaleY = self.pulseScale;
// Rotate
portalGraphics.rotation += 0.05;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Game variables
var player;
var platforms = [];
var obstacles = [];
var portal;
var currentDimension = 0;
var dimensionTimer = 0;
var maxDimensionTime = 1800; // 30 seconds at 60fps
var backgrounds = [];
var dimensionNames = ["Normal Lab", "Reverse Gravity", "Underwater", "Low Gravity", "Ice World"];
var isGameStarted = false;
var leftPressed = false;
var rightPressed = false;
var gameState = 'menu'; // 'menu', 'playing', 'settings', 'shop'
var menuUI = {};
var settingsUI = {};
var shopUI = {};
var playerSkins = [{
name: 'Default',
cost: 0,
unlocked: true
}, {
name: 'Red Robot',
cost: 50,
unlocked: false
}, {
name: 'Blue Knight',
cost: 100,
unlocked: false
}, {
name: 'Green Alien',
cost: 150,
unlocked: false
}];
// Create backgrounds
for (var i = 0; i < 5; i++) {
var bg = LK.getAsset('background' + (i + 1), {
anchorX: 0,
anchorY: 0,
alpha: 0
});
backgrounds.push(bg);
game.addChild(bg);
}
// Show custom game over screen
function showGameOverScreen() {
// Create collapse effect - darken screen
tween(game, {
alpha: 0.3
}, {
duration: 1000
});
// Portal closing animation
tween(portal, {
scaleX: 0,
scaleY: 0,
rotation: portal.rotation + Math.PI * 2
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Show game over after collapse effect
displayGameOverInfo();
}
});
}
// Display game over information
function displayGameOverInfo() {
// Calculate survival time in seconds
var survivalTime = Math.floor(dimensionTimer / 60);
// Create game over container
var gameOverContainer = new Container();
game.addChild(gameOverContainer);
// Dark background overlay
var overlay = LK.getAsset('background5', {
anchorX: 0,
anchorY: 0,
alpha: 0.8
});
gameOverContainer.addChild(overlay);
// Game Over title
var gameOverTitle = new Text2('GAME OVER', {
size: 120,
fill: 0xFF0000
});
gameOverTitle.anchor.set(0.5, 0.5);
gameOverTitle.x = 1024;
gameOverTitle.y = 800;
gameOverContainer.addChild(gameOverTitle);
// Final score
var finalScoreText = new Text2('Final Score: ' + LK.getScore(), {
size: 80,
fill: 0xFFFFFF
});
finalScoreText.anchor.set(0.5, 0.5);
finalScoreText.x = 1024;
finalScoreText.y = 1000;
gameOverContainer.addChild(finalScoreText);
// Time survived
var timeText = new Text2('Time Survived: ' + survivalTime + 's', {
size: 80,
fill: 0xFFFFFF
});
timeText.anchor.set(0.5, 0.5);
timeText.x = 1024;
timeText.y = 1150;
gameOverContainer.addChild(timeText);
// Dimensions completed
var dimensionsText = new Text2('Dimensions Reached: ' + (currentDimension + 1), {
size: 80,
fill: 0xFFFFFF
});
dimensionsText.anchor.set(0.5, 0.5);
dimensionsText.x = 1024;
dimensionsText.y = 1300;
gameOverContainer.addChild(dimensionsText);
// Fade in the game over screen
gameOverContainer.alpha = 0;
tween(gameOverContainer, {
alpha: 1
}, {
duration: 1000,
onFinish: function onFinish() {
// After showing info, trigger LK game over
LK.setTimeout(function () {
LK.showGameOver();
}, 3000);
}
});
}
;
// Set initial background
backgrounds[0].alpha = 1;
// Create player
player = game.addChild(new Player());
player.resetPosition();
// Create initial platforms
function createPlatforms() {
// Clear existing platforms
for (var i = 0; i < platforms.length; i++) {
platforms[i].destroy();
}
platforms = [];
// Create platforms based on dimension
if (currentDimension === 0) {
// Normal platforms
platforms.push(game.addChild(new Platform(300, 20)));
platforms[0].x = 300;
platforms[0].y = 1200;
platforms.push(game.addChild(new Platform(250, 20)));
platforms[1].x = 700;
platforms[1].y = 1000;
platforms.push(game.addChild(new Platform(200, 20)));
platforms[2].x = 1200;
platforms[2].y = 800;
platforms.push(game.addChild(new Platform(300, 20)));
platforms[3].x = 1600;
platforms[3].y = 600;
} else if (currentDimension === 1) {
// Reverse gravity - platforms on top
platforms.push(game.addChild(new Platform(300, 20)));
platforms[0].x = 300;
platforms[0].y = 500;
platforms.push(game.addChild(new Platform(250, 20)));
platforms[1].x = 700;
platforms[1].y = 700;
platforms.push(game.addChild(new Platform(200, 20)));
platforms[2].x = 1200;
platforms[2].y = 900;
platforms.push(game.addChild(new Platform(300, 20)));
platforms[3].x = 1600;
platforms[3].y = 1100;
} else {
// Other dimensions - mixed platforms
platforms.push(game.addChild(new Platform(250, 20)));
platforms[0].x = 400;
platforms[0].y = 1100;
platforms.push(game.addChild(new Platform(200, 20)));
platforms[1].x = 800;
platforms[1].y = 900;
platforms.push(game.addChild(new Platform(300, 20)));
platforms[2].x = 1300;
platforms[2].y = 700;
platforms.push(game.addChild(new Platform(250, 20)));
platforms[3].x = 1700;
platforms[3].y = 500;
}
}
// Create obstacles
function createObstacles() {
// Clear existing obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
obstacles = [];
// Create 2-3 obstacles per dimension
for (var i = 0; i < 3; i++) {
var obstacle = game.addChild(new Obstacle());
obstacle.x = 500 + i * 400;
obstacle.y = 1300 - i * 200;
obstacle.startX = obstacle.x;
obstacles.push(obstacle);
}
}
// Create portal
portal = game.addChild(new Portal());
portal.x = 1800;
portal.y = 400;
// Create UI overlay
var scoreText = new Text2('Score: 0', {
size: 50,
fill: 0xFFFF00
});
scoreText.anchor.set(0, 0);
scoreText.x = 120;
scoreText.y = 20;
LK.gui.topLeft.addChild(scoreText);
var timerText = new Text2('Time: 30s', {
size: 50,
fill: 0xFFFFFF
});
timerText.anchor.set(0.5, 0);
timerText.y = 20;
LK.gui.top.addChild(timerText);
var dimensionText = new Text2('Dimension: Normal Lab', {
size: 45,
fill: 0x00FFFF
});
dimensionText.anchor.set(1, 0);
dimensionText.x = -20;
dimensionText.y = 20;
LK.gui.topRight.addChild(dimensionText);
// Initialize storage values
storage.coins = storage.coins || 0;
storage.selectedSkin = storage.selectedSkin || 0;
storage.unlockedSkins = storage.unlockedSkins || [0];
storage.highScore = storage.highScore || 0;
// Create main menu UI
function createMainMenu() {
menuUI.container = new Container();
game.addChild(menuUI.container);
// Challenge subtitle
menuUI.title = new Text2('30-Second Portal Challenge', {
size: 80,
fill: 0x000000
});
menuUI.title.anchor.set(0.5, 0.5);
menuUI.title.x = 1024;
menuUI.title.y = 400;
menuUI.container.addChild(menuUI.title);
// Play button with custom background
menuUI.playButtonBg = menuUI.container.attachAsset('menuButtonPlay', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 800
});
// Settings button with custom background
menuUI.settingsButtonBg = menuUI.container.attachAsset('menuButtonSettings', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 950
});
// Shop button with custom background
menuUI.shopButtonBg = menuUI.container.attachAsset('menuButtonShop', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1100
});
// Quit button with custom background
menuUI.quitButtonBg = menuUI.container.attachAsset('menuButtonQuit', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1250
});
// High score display
menuUI.highScoreText = new Text2('High Score: ' + storage.highScore, {
size: 65,
fill: 0x000000,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
menuUI.highScoreText.anchor.set(0.5, 0.5);
menuUI.highScoreText.x = 1024;
menuUI.highScoreText.y = 1400;
menuUI.container.addChild(menuUI.highScoreText);
// Coins display
menuUI.coinsText = new Text2('Coins: ' + storage.coins, {
size: 65,
fill: 0xFFFF00,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
menuUI.coinsText.anchor.set(0.5, 0.5);
menuUI.coinsText.x = 1024;
menuUI.coinsText.y = 1500;
menuUI.container.addChild(menuUI.coinsText);
}
// Create settings menu UI
function createSettingsMenu() {
settingsUI.container = new Container();
game.addChild(settingsUI.container);
settingsUI.container.visible = false;
// Title
settingsUI.title = new Text2('SETTINGS', {
size: 100,
fill: 0xFFFFFF
});
settingsUI.title.anchor.set(0.5, 0.5);
settingsUI.title.x = 1024;
settingsUI.title.y = 400;
settingsUI.container.addChild(settingsUI.title);
// Back button with custom background
settingsUI.backButtonBg = settingsUI.container.attachAsset('menuButtonBack', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1200
});
settingsUI.backButton = new Text2('BACK', {
size: 60,
fill: 0xFFFFFF
});
settingsUI.backButton.anchor.set(0.5, 0.5);
settingsUI.backButton.x = 1024;
settingsUI.backButton.y = 1200;
settingsUI.container.addChild(settingsUI.backButton);
// Sound Volume Label
settingsUI.soundVolumeLabel = new Text2('Sound Volume:', {
size: 60,
fill: 0xFFFFFF
});
settingsUI.soundVolumeLabel.anchor.set(0.5, 0.5);
settingsUI.soundVolumeLabel.x = 1024;
settingsUI.soundVolumeLabel.y = 600;
settingsUI.container.addChild(settingsUI.soundVolumeLabel);
// Sound Volume Buttons
settingsUI.soundLowButton = new Text2('LOW', {
size: 50,
fill: storage.soundVolume === 0.3 ? 0x00FF00 : 0xFFFFFF
});
settingsUI.soundLowButton.anchor.set(0.5, 0.5);
settingsUI.soundLowButton.x = 700;
settingsUI.soundLowButton.y = 700;
settingsUI.container.addChild(settingsUI.soundLowButton);
settingsUI.soundMedButton = new Text2('MED', {
size: 50,
fill: storage.soundVolume === 0.7 ? 0x00FF00 : 0xFFFFFF
});
settingsUI.soundMedButton.anchor.set(0.5, 0.5);
settingsUI.soundMedButton.x = 1024;
settingsUI.soundMedButton.y = 700;
settingsUI.container.addChild(settingsUI.soundMedButton);
settingsUI.soundHighButton = new Text2('HIGH', {
size: 50,
fill: storage.soundVolume === 1.0 ? 0x00FF00 : 0xFFFFFF
});
settingsUI.soundHighButton.anchor.set(0.5, 0.5);
settingsUI.soundHighButton.x = 1348;
settingsUI.soundHighButton.y = 700;
settingsUI.container.addChild(settingsUI.soundHighButton);
// Sound Mute Button
settingsUI.soundMuteButton = new Text2(storage.soundMuted ? 'UNMUTE SOUND' : 'MUTE SOUND', {
size: 50,
fill: storage.soundMuted ? 0xFF0000 : 0xFFFF00
});
settingsUI.soundMuteButton.anchor.set(0.5, 0.5);
settingsUI.soundMuteButton.x = 1024;
settingsUI.soundMuteButton.y = 800;
settingsUI.container.addChild(settingsUI.soundMuteButton);
// Music Volume Label
settingsUI.musicVolumeLabel = new Text2('Music Volume:', {
size: 60,
fill: 0xFFFFFF
});
settingsUI.musicVolumeLabel.anchor.set(0.5, 0.5);
settingsUI.musicVolumeLabel.x = 1024;
settingsUI.musicVolumeLabel.y = 900;
settingsUI.container.addChild(settingsUI.musicVolumeLabel);
// Music Volume Buttons
settingsUI.musicLowButton = new Text2('LOW', {
size: 50,
fill: storage.musicVolume === 0.3 ? 0x00FF00 : 0xFFFFFF
});
settingsUI.musicLowButton.anchor.set(0.5, 0.5);
settingsUI.musicLowButton.x = 700;
settingsUI.musicLowButton.y = 1000;
settingsUI.container.addChild(settingsUI.musicLowButton);
settingsUI.musicMedButton = new Text2('MED', {
size: 50,
fill: storage.musicVolume === 0.7 ? 0x00FF00 : 0xFFFFFF
});
settingsUI.musicMedButton.anchor.set(0.5, 0.5);
settingsUI.musicMedButton.x = 1024;
settingsUI.musicMedButton.y = 1000;
settingsUI.container.addChild(settingsUI.musicMedButton);
settingsUI.musicHighButton = new Text2('HIGH', {
size: 50,
fill: storage.musicVolume === 1.0 ? 0x00FF00 : 0xFFFFFF
});
settingsUI.musicHighButton.anchor.set(0.5, 0.5);
settingsUI.musicHighButton.x = 1348;
settingsUI.musicHighButton.y = 1000;
settingsUI.container.addChild(settingsUI.musicHighButton);
// Music Mute Button
settingsUI.musicMuteButton = new Text2(storage.musicMuted ? 'UNMUTE MUSIC' : 'MUTE MUSIC', {
size: 50,
fill: storage.musicMuted ? 0xFF0000 : 0xFFFF00
});
settingsUI.musicMuteButton.anchor.set(0.5, 0.5);
settingsUI.musicMuteButton.x = 1024;
settingsUI.musicMuteButton.y = 1100;
settingsUI.container.addChild(settingsUI.musicMuteButton);
}
// Create shop menu UI
function createShopMenu() {
shopUI.container = new Container();
game.addChild(shopUI.container);
shopUI.container.visible = false;
// Title
shopUI.title = new Text2('SHOP', {
size: 100,
fill: 0xFFFFFF
});
shopUI.title.anchor.set(0.5, 0.5);
shopUI.title.x = 1024;
shopUI.title.y = 300;
shopUI.container.addChild(shopUI.title);
// Coins display
shopUI.coinsText = new Text2('Coins: ' + storage.coins, {
size: 50,
fill: 0xFFD700
});
shopUI.coinsText.anchor.set(0.5, 0.5);
shopUI.coinsText.x = 1024;
shopUI.coinsText.y = 400;
shopUI.container.addChild(shopUI.coinsText);
// Skin selection area
shopUI.skinButtons = [];
for (var i = 0; i < playerSkins.length; i++) {
var skin = playerSkins[i];
var yPos = 550 + i * 120;
// Skin name
var skinText = new Text2(skin.name, {
size: 50,
fill: storage.selectedSkin === i ? 0x00FF00 : 0xFFFFFF
});
skinText.anchor.set(0.5, 0.5);
skinText.x = 700;
skinText.y = yPos;
shopUI.container.addChild(skinText);
// Cost/Status
var statusText;
if (storage.unlockedSkins.indexOf(i) !== -1) {
if (storage.selectedSkin === i) {
statusText = new Text2('EQUIPPED', {
size: 40,
fill: 0x00FF00
});
} else {
statusText = new Text2('SELECT', {
size: 40,
fill: 0xFFFF00
});
}
} else {
statusText = new Text2('Cost: ' + skin.cost, {
size: 40,
fill: 0xFF0000
});
}
statusText.anchor.set(0.5, 0.5);
statusText.x = 1300;
statusText.y = yPos;
shopUI.container.addChild(statusText);
shopUI.skinButtons.push({
skinText: skinText,
statusText: statusText,
skinIndex: i,
yPos: yPos
});
}
// Back button with custom background
shopUI.backButtonBg = shopUI.container.attachAsset('menuButtonBack', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1200
});
shopUI.backButton = new Text2('BACK', {
size: 60,
fill: 0xFFFFFF
});
shopUI.backButton.anchor.set(0.5, 0.5);
shopUI.backButton.x = 1024;
shopUI.backButton.y = 1200;
shopUI.container.addChild(shopUI.backButton);
}
// Update settings UI
function updateSettingsUI() {
settingsUI.soundLowButton.tint = storage.soundVolume === 0.3 ? 0x00FF00 : 0xFFFFFF;
settingsUI.soundMedButton.tint = storage.soundVolume === 0.7 ? 0x00FF00 : 0xFFFFFF;
settingsUI.soundHighButton.tint = storage.soundVolume === 1.0 ? 0x00FF00 : 0xFFFFFF;
settingsUI.soundMuteButton.setText(storage.soundMuted ? 'UNMUTE SOUND' : 'MUTE SOUND');
settingsUI.soundMuteButton.tint = storage.soundMuted ? 0xFF0000 : 0xFFFF00;
settingsUI.musicLowButton.tint = storage.musicVolume === 0.3 ? 0x00FF00 : 0xFFFFFF;
settingsUI.musicMedButton.tint = storage.musicVolume === 0.7 ? 0x00FF00 : 0xFFFFFF;
settingsUI.musicHighButton.tint = storage.musicVolume === 1.0 ? 0x00FF00 : 0xFFFFFF;
settingsUI.musicMuteButton.setText(storage.musicMuted ? 'UNMUTE MUSIC' : 'MUTE MUSIC');
settingsUI.musicMuteButton.tint = storage.musicMuted ? 0xFF0000 : 0xFFFF00;
}
// Update shop UI
function updateShopUI() {
shopUI.coinsText.setText('Coins: ' + storage.coins);
for (var i = 0; i < shopUI.skinButtons.length; i++) {
var button = shopUI.skinButtons[i];
var skin = playerSkins[button.skinIndex];
// Update skin name color
button.skinText.tint = storage.selectedSkin === button.skinIndex ? 0x00FF00 : 0xFFFFFF;
// Update status text
if (storage.unlockedSkins.indexOf(button.skinIndex) !== -1) {
if (storage.selectedSkin === button.skinIndex) {
button.statusText.setText('EQUIPPED');
button.statusText.tint = 0x00FF00;
} else {
button.statusText.setText('SELECT');
button.statusText.tint = 0xFFFF00;
}
} else {
button.statusText.setText('Cost: ' + skin.cost);
button.statusText.tint = storage.coins >= skin.cost ? 0xFFFF00 : 0xFF0000;
}
}
}
// Show specific menu
function showMenu(menuType) {
gameState = menuType;
menuUI.container.visible = menuType === 'menu';
settingsUI.container.visible = menuType === 'settings';
shopUI.container.visible = menuType === 'shop';
if (menuType === 'shop') {
updateShopUI();
}
if (menuType === 'settings') {
updateSettingsUI();
}
if (menuType === 'menu') {
menuUI.highScoreText.setText('High Score: ' + storage.highScore);
menuUI.coinsText.setText('Coins: ' + storage.coins);
}
}
// Apply music volume settings
function applyMusicVolume() {
if (storage.musicMuted) {
LK.stopMusic();
} else {
LK.playMusic('BackSound', {
fade: {
start: 0,
end: storage.musicVolume,
duration: 500
}
});
}
}
// Apply sound volume to a sound effect
function playSound(soundId) {
if (!storage.soundMuted) {
var sound = LK.getSound(soundId);
sound.volume = storage.soundVolume;
sound.play();
}
}
// Start the actual game
function startGame() {
gameState = 'playing';
isGameStarted = true;
// Hide all menus
menuUI.container.visible = false;
settingsUI.container.visible = false;
shopUI.container.visible = false;
// Initialize level
createPlatforms();
createObstacles();
// Start background music with volume settings
applyMusicVolume();
}
// Initialize menus
createMainMenu();
createSettingsMenu();
createShopMenu();
showMenu('menu');
// Input handling
game.down = function (x, y, obj) {
if (gameState === 'menu') {
// Check menu button clicks
if (y >= 750 && y <= 850) {
// Play button
startGame();
} else if (y >= 900 && y <= 1000) {
// Settings button
showMenu('settings');
} else if (y >= 1050 && y <= 1150) {
// Shop button
showMenu('shop');
} else if (y >= 1200 && y <= 1300) {
// Quit button (for web games, this might just show a message)
console.log('Quit button pressed');
}
return;
}
if (gameState === 'settings') {
// Check sound volume buttons
if (y >= 650 && y <= 750) {
if (x >= 650 && x <= 750) {
// Sound Low
storage.soundVolume = 0.3;
updateSettingsUI();
} else if (x >= 974 && x <= 1074) {
// Sound Med
storage.soundVolume = 0.7;
updateSettingsUI();
} else if (x >= 1298 && x <= 1398) {
// Sound High
storage.soundVolume = 1.0;
updateSettingsUI();
}
return;
}
// Check sound mute button
if (y >= 750 && y <= 850) {
storage.soundMuted = !storage.soundMuted;
updateSettingsUI();
return;
}
// Check music volume buttons
if (y >= 950 && y <= 1050) {
if (x >= 650 && x <= 750) {
// Music Low
storage.musicVolume = 0.3;
updateSettingsUI();
applyMusicVolume();
} else if (x >= 974 && x <= 1074) {
// Music Med
storage.musicVolume = 0.7;
updateSettingsUI();
applyMusicVolume();
} else if (x >= 1298 && x <= 1398) {
// Music High
storage.musicVolume = 1.0;
updateSettingsUI();
applyMusicVolume();
}
return;
}
// Check music mute button
if (y >= 1050 && y <= 1150) {
storage.musicMuted = !storage.musicMuted;
updateSettingsUI();
applyMusicVolume();
return;
}
// Check back button
if (y >= 1150 && y <= 1250) {
showMenu('menu');
}
return;
}
if (gameState === 'shop') {
// Check skin buttons
for (var i = 0; i < shopUI.skinButtons.length; i++) {
var button = shopUI.skinButtons[i];
if (y >= button.yPos - 50 && y <= button.yPos + 50) {
var skin = playerSkins[button.skinIndex];
if (storage.unlockedSkins.indexOf(button.skinIndex) !== -1) {
// Skin is unlocked, select it
storage.selectedSkin = button.skinIndex;
updateShopUI();
} else if (storage.coins >= skin.cost) {
// Purchase skin
storage.coins -= skin.cost;
storage.unlockedSkins.push(button.skinIndex);
storage.selectedSkin = button.skinIndex;
updateShopUI();
}
return;
}
}
// Check back button
if (y >= 1150 && y <= 1250) {
showMenu('menu');
}
return;
}
if (gameState === 'playing') {
if (x < 1024) {
leftPressed = true;
} else if (x > 1024) {
rightPressed = true;
}
// Jump on tap
player.jump();
}
};
game.up = function (x, y, obj) {
leftPressed = false;
rightPressed = false;
};
// Game update loop
game.update = function () {
if (gameState !== 'playing') {
return;
}
// Handle input
if (leftPressed) {
player.moveLeft();
} else if (rightPressed) {
player.moveRight();
} else if (currentDimension !== 4) {
// Stop horizontal movement (except on ice)
player.velocityX = 0;
}
// Update dimension timer
dimensionTimer++;
var timeLeft = Math.ceil((maxDimensionTime - dimensionTimer) / 60);
timerText.setText('Time: ' + timeLeft + 's');
// Flash timer when low
if (timeLeft <= 5) {
timerText.alpha = Math.sin(LK.ticks * 0.3) * 0.5 + 0.5;
} else {
timerText.alpha = 1;
}
// Check for dimension change
if (dimensionTimer >= maxDimensionTime) {
// Game over - player failed to reach portal in time
showGameOverScreen();
}
// Check portal collision
if (player.intersects(portal)) {
changeDimension();
}
// Check obstacle collisions
for (var i = 0; i < obstacles.length; i++) {
if (player.intersects(obstacles[i])) {
playSound('hit');
LK.effects.flashScreen(0xff0000, 500);
player.resetPosition();
break;
}
}
// Update score
scoreText.setText('Score: ' + LK.getScore().toString());
};
function changeDimension() {
playSound('portal');
LK.setScore(LK.getScore() + 10);
// Award coins
storage.coins += 5;
// Update high score
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
}
// Flash effect
LK.effects.flashScreen(0xffffff, 300);
// Reset timer
dimensionTimer = 0;
// Change dimension
currentDimension = (currentDimension + 1) % 5;
// Change background
for (var i = 0; i < backgrounds.length; i++) {
tween(backgrounds[i], {
alpha: i === currentDimension ? 1 : 0
}, {
duration: 500
});
}
// Update UI
dimensionText.setText('Dimension: ' + dimensionNames[currentDimension]);
// Reset player position and velocity
player.x = 200;
if (currentDimension === 1) {
player.y = 2200; // Start at bottom for reverse gravity
} else {
player.y = 1000;
}
player.velocityX = 0;
player.velocityY = 0;
// Recreate platforms and obstacles
createPlatforms();
createObstacles();
// Move portal to new position
portal.x = 1600 + Math.random() * 200;
portal.y = 300 + Math.random() * 200;
// Check win condition
if (LK.getScore() >= 100) {
LK.showYouWin();
}
} /****
* Plugins
****/
var storage = LK.import("@upit/storage.v1", {
coins: 0,
selectedSkin: 0,
unlockedSkins: [0],
highScore: 0,
soundVolume: 1,
musicVolume: 1,
soundMuted: false,
musicMuted: false
});
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.moveSpeed = 2;
self.direction = 1;
self.startX = 0;
self.range = 200;
self.update = function () {
self.x += self.moveSpeed * self.direction;
if (self.x > self.startX + self.range || self.x < self.startX - self.range) {
self.direction *= -1;
}
// Rotation for visual effect
obstacleGraphics.rotation += 0.1;
};
return self;
});
var Platform = Container.expand(function (width, height) {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: width / 200,
scaleY: height / 20
});
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.onGround = false;
self.moveSpeed = 8;
self.jumpPower = 22.5;
self.gravity = 0.8;
self.maxVelocityY = 20;
self.update = function () {
// Apply physics based on current dimension
self.applyPhysics();
// Update position
self.x += self.velocityX;
self.y += self.velocityY;
// Keep player on screen horizontally
if (self.x < 20) {
self.x = 20;
}
if (self.x > 2028) {
self.x = 2028;
}
// Check platform collisions
self.checkPlatformCollisions();
// Check if player falls off screen or goes above screen
if (self.y > 2800 || self.y < -50) {
self.resetPosition();
}
};
self.applyPhysics = function () {
if (currentDimension === 0) {
// Normal gravity
self.velocityY += self.gravity;
} else if (currentDimension === 1) {
// Reverse gravity
self.velocityY -= self.gravity;
} else if (currentDimension === 2) {
// Underwater - slower movement
self.velocityY += self.gravity * 0.3;
self.velocityX *= 0.9;
} else if (currentDimension === 3) {
// Low gravity
self.velocityY += self.gravity * 0.4;
} else if (currentDimension === 4) {
// Ice - slippery
self.velocityY += self.gravity;
self.velocityX *= 0.98;
}
// Limit velocity
if (self.velocityY > self.maxVelocityY) {
self.velocityY = self.maxVelocityY;
}
if (self.velocityY < -self.maxVelocityY) {
self.velocityY = -self.maxVelocityY;
}
};
self.checkPlatformCollisions = function () {
self.onGround = false;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
if (self.intersects(platform)) {
if (currentDimension === 1) {
// Reverse gravity - land on top of platforms
if (self.velocityY < 0) {
self.y = platform.y + platform.height / 2 + self.height / 2;
self.velocityY = 0;
self.onGround = true;
}
} else {
// Normal - land on bottom of platforms
if (self.velocityY > 0) {
self.y = platform.y - platform.height / 2 - self.height / 2;
self.velocityY = 0;
self.onGround = true;
}
}
}
}
};
self.jump = function () {
if (self.onGround) {
if (currentDimension === 1) {
// Reverse gravity jump
self.velocityY = self.jumpPower;
} else {
self.velocityY = -self.jumpPower;
}
playSound('jump');
}
};
self.moveLeft = function () {
if (currentDimension === 4) {
// Ice - reduced control
self.velocityX -= self.moveSpeed * 0.3;
} else {
self.velocityX = -self.moveSpeed;
}
};
self.moveRight = function () {
if (currentDimension === 4) {
// Ice - reduced control
self.velocityX += self.moveSpeed * 0.3;
} else {
self.velocityX = self.moveSpeed;
}
};
self.resetPosition = function () {
playSound('fall');
self.x = 200;
self.y = 1000;
self.velocityX = 0;
self.velocityY = 0;
};
return self;
});
var Portal = Container.expand(function () {
var self = Container.call(this);
var portalGraphics = self.attachAsset('portal', {
anchorX: 0.5,
anchorY: 0.5
});
self.pulseScale = 1;
self.pulseDirection = 1;
self.update = function () {
// Pulse animation
self.pulseScale += self.pulseDirection * 0.02;
if (self.pulseScale > 1.2) {
self.pulseScale = 1.2;
self.pulseDirection = -1;
} else if (self.pulseScale < 0.8) {
self.pulseScale = 0.8;
self.pulseDirection = 1;
}
portalGraphics.scaleX = self.pulseScale;
portalGraphics.scaleY = self.pulseScale;
// Rotate
portalGraphics.rotation += 0.05;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Game variables
var player;
var platforms = [];
var obstacles = [];
var portal;
var currentDimension = 0;
var dimensionTimer = 0;
var maxDimensionTime = 1800; // 30 seconds at 60fps
var backgrounds = [];
var dimensionNames = ["Normal Lab", "Reverse Gravity", "Underwater", "Low Gravity", "Ice World"];
var isGameStarted = false;
var leftPressed = false;
var rightPressed = false;
var gameState = 'menu'; // 'menu', 'playing', 'settings', 'shop'
var menuUI = {};
var settingsUI = {};
var shopUI = {};
var playerSkins = [{
name: 'Default',
cost: 0,
unlocked: true
}, {
name: 'Red Robot',
cost: 50,
unlocked: false
}, {
name: 'Blue Knight',
cost: 100,
unlocked: false
}, {
name: 'Green Alien',
cost: 150,
unlocked: false
}];
// Create backgrounds
for (var i = 0; i < 5; i++) {
var bg = LK.getAsset('background' + (i + 1), {
anchorX: 0,
anchorY: 0,
alpha: 0
});
backgrounds.push(bg);
game.addChild(bg);
}
// Show custom game over screen
function showGameOverScreen() {
// Create collapse effect - darken screen
tween(game, {
alpha: 0.3
}, {
duration: 1000
});
// Portal closing animation
tween(portal, {
scaleX: 0,
scaleY: 0,
rotation: portal.rotation + Math.PI * 2
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Show game over after collapse effect
displayGameOverInfo();
}
});
}
// Display game over information
function displayGameOverInfo() {
// Calculate survival time in seconds
var survivalTime = Math.floor(dimensionTimer / 60);
// Create game over container
var gameOverContainer = new Container();
game.addChild(gameOverContainer);
// Dark background overlay
var overlay = LK.getAsset('background5', {
anchorX: 0,
anchorY: 0,
alpha: 0.8
});
gameOverContainer.addChild(overlay);
// Game Over title
var gameOverTitle = new Text2('GAME OVER', {
size: 120,
fill: 0xFF0000
});
gameOverTitle.anchor.set(0.5, 0.5);
gameOverTitle.x = 1024;
gameOverTitle.y = 800;
gameOverContainer.addChild(gameOverTitle);
// Final score
var finalScoreText = new Text2('Final Score: ' + LK.getScore(), {
size: 80,
fill: 0xFFFFFF
});
finalScoreText.anchor.set(0.5, 0.5);
finalScoreText.x = 1024;
finalScoreText.y = 1000;
gameOverContainer.addChild(finalScoreText);
// Time survived
var timeText = new Text2('Time Survived: ' + survivalTime + 's', {
size: 80,
fill: 0xFFFFFF
});
timeText.anchor.set(0.5, 0.5);
timeText.x = 1024;
timeText.y = 1150;
gameOverContainer.addChild(timeText);
// Dimensions completed
var dimensionsText = new Text2('Dimensions Reached: ' + (currentDimension + 1), {
size: 80,
fill: 0xFFFFFF
});
dimensionsText.anchor.set(0.5, 0.5);
dimensionsText.x = 1024;
dimensionsText.y = 1300;
gameOverContainer.addChild(dimensionsText);
// Fade in the game over screen
gameOverContainer.alpha = 0;
tween(gameOverContainer, {
alpha: 1
}, {
duration: 1000,
onFinish: function onFinish() {
// After showing info, trigger LK game over
LK.setTimeout(function () {
LK.showGameOver();
}, 3000);
}
});
}
;
// Set initial background
backgrounds[0].alpha = 1;
// Create player
player = game.addChild(new Player());
player.resetPosition();
// Create initial platforms
function createPlatforms() {
// Clear existing platforms
for (var i = 0; i < platforms.length; i++) {
platforms[i].destroy();
}
platforms = [];
// Create platforms based on dimension
if (currentDimension === 0) {
// Normal platforms
platforms.push(game.addChild(new Platform(300, 20)));
platforms[0].x = 300;
platforms[0].y = 1200;
platforms.push(game.addChild(new Platform(250, 20)));
platforms[1].x = 700;
platforms[1].y = 1000;
platforms.push(game.addChild(new Platform(200, 20)));
platforms[2].x = 1200;
platforms[2].y = 800;
platforms.push(game.addChild(new Platform(300, 20)));
platforms[3].x = 1600;
platforms[3].y = 600;
} else if (currentDimension === 1) {
// Reverse gravity - platforms on top
platforms.push(game.addChild(new Platform(300, 20)));
platforms[0].x = 300;
platforms[0].y = 500;
platforms.push(game.addChild(new Platform(250, 20)));
platforms[1].x = 700;
platforms[1].y = 700;
platforms.push(game.addChild(new Platform(200, 20)));
platforms[2].x = 1200;
platforms[2].y = 900;
platforms.push(game.addChild(new Platform(300, 20)));
platforms[3].x = 1600;
platforms[3].y = 1100;
} else {
// Other dimensions - mixed platforms
platforms.push(game.addChild(new Platform(250, 20)));
platforms[0].x = 400;
platforms[0].y = 1100;
platforms.push(game.addChild(new Platform(200, 20)));
platforms[1].x = 800;
platforms[1].y = 900;
platforms.push(game.addChild(new Platform(300, 20)));
platforms[2].x = 1300;
platforms[2].y = 700;
platforms.push(game.addChild(new Platform(250, 20)));
platforms[3].x = 1700;
platforms[3].y = 500;
}
}
// Create obstacles
function createObstacles() {
// Clear existing obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
obstacles = [];
// Create 2-3 obstacles per dimension
for (var i = 0; i < 3; i++) {
var obstacle = game.addChild(new Obstacle());
obstacle.x = 500 + i * 400;
obstacle.y = 1300 - i * 200;
obstacle.startX = obstacle.x;
obstacles.push(obstacle);
}
}
// Create portal
portal = game.addChild(new Portal());
portal.x = 1800;
portal.y = 400;
// Create UI overlay
var scoreText = new Text2('Score: 0', {
size: 50,
fill: 0xFFFF00
});
scoreText.anchor.set(0, 0);
scoreText.x = 120;
scoreText.y = 20;
LK.gui.topLeft.addChild(scoreText);
var timerText = new Text2('Time: 30s', {
size: 50,
fill: 0xFFFFFF
});
timerText.anchor.set(0.5, 0);
timerText.y = 20;
LK.gui.top.addChild(timerText);
var dimensionText = new Text2('Dimension: Normal Lab', {
size: 45,
fill: 0x00FFFF
});
dimensionText.anchor.set(1, 0);
dimensionText.x = -20;
dimensionText.y = 20;
LK.gui.topRight.addChild(dimensionText);
// Initialize storage values
storage.coins = storage.coins || 0;
storage.selectedSkin = storage.selectedSkin || 0;
storage.unlockedSkins = storage.unlockedSkins || [0];
storage.highScore = storage.highScore || 0;
// Create main menu UI
function createMainMenu() {
menuUI.container = new Container();
game.addChild(menuUI.container);
// Challenge subtitle
menuUI.title = new Text2('30-Second Portal Challenge', {
size: 80,
fill: 0x000000
});
menuUI.title.anchor.set(0.5, 0.5);
menuUI.title.x = 1024;
menuUI.title.y = 400;
menuUI.container.addChild(menuUI.title);
// Play button with custom background
menuUI.playButtonBg = menuUI.container.attachAsset('menuButtonPlay', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 800
});
// Settings button with custom background
menuUI.settingsButtonBg = menuUI.container.attachAsset('menuButtonSettings', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 950
});
// Shop button with custom background
menuUI.shopButtonBg = menuUI.container.attachAsset('menuButtonShop', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1100
});
// Quit button with custom background
menuUI.quitButtonBg = menuUI.container.attachAsset('menuButtonQuit', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1250
});
// High score display
menuUI.highScoreText = new Text2('High Score: ' + storage.highScore, {
size: 65,
fill: 0x000000,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
menuUI.highScoreText.anchor.set(0.5, 0.5);
menuUI.highScoreText.x = 1024;
menuUI.highScoreText.y = 1400;
menuUI.container.addChild(menuUI.highScoreText);
// Coins display
menuUI.coinsText = new Text2('Coins: ' + storage.coins, {
size: 65,
fill: 0xFFFF00,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
menuUI.coinsText.anchor.set(0.5, 0.5);
menuUI.coinsText.x = 1024;
menuUI.coinsText.y = 1500;
menuUI.container.addChild(menuUI.coinsText);
}
// Create settings menu UI
function createSettingsMenu() {
settingsUI.container = new Container();
game.addChild(settingsUI.container);
settingsUI.container.visible = false;
// Title
settingsUI.title = new Text2('SETTINGS', {
size: 100,
fill: 0xFFFFFF
});
settingsUI.title.anchor.set(0.5, 0.5);
settingsUI.title.x = 1024;
settingsUI.title.y = 400;
settingsUI.container.addChild(settingsUI.title);
// Back button with custom background
settingsUI.backButtonBg = settingsUI.container.attachAsset('menuButtonBack', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1200
});
settingsUI.backButton = new Text2('BACK', {
size: 60,
fill: 0xFFFFFF
});
settingsUI.backButton.anchor.set(0.5, 0.5);
settingsUI.backButton.x = 1024;
settingsUI.backButton.y = 1200;
settingsUI.container.addChild(settingsUI.backButton);
// Sound Volume Label
settingsUI.soundVolumeLabel = new Text2('Sound Volume:', {
size: 60,
fill: 0xFFFFFF
});
settingsUI.soundVolumeLabel.anchor.set(0.5, 0.5);
settingsUI.soundVolumeLabel.x = 1024;
settingsUI.soundVolumeLabel.y = 600;
settingsUI.container.addChild(settingsUI.soundVolumeLabel);
// Sound Volume Buttons
settingsUI.soundLowButton = new Text2('LOW', {
size: 50,
fill: storage.soundVolume === 0.3 ? 0x00FF00 : 0xFFFFFF
});
settingsUI.soundLowButton.anchor.set(0.5, 0.5);
settingsUI.soundLowButton.x = 700;
settingsUI.soundLowButton.y = 700;
settingsUI.container.addChild(settingsUI.soundLowButton);
settingsUI.soundMedButton = new Text2('MED', {
size: 50,
fill: storage.soundVolume === 0.7 ? 0x00FF00 : 0xFFFFFF
});
settingsUI.soundMedButton.anchor.set(0.5, 0.5);
settingsUI.soundMedButton.x = 1024;
settingsUI.soundMedButton.y = 700;
settingsUI.container.addChild(settingsUI.soundMedButton);
settingsUI.soundHighButton = new Text2('HIGH', {
size: 50,
fill: storage.soundVolume === 1.0 ? 0x00FF00 : 0xFFFFFF
});
settingsUI.soundHighButton.anchor.set(0.5, 0.5);
settingsUI.soundHighButton.x = 1348;
settingsUI.soundHighButton.y = 700;
settingsUI.container.addChild(settingsUI.soundHighButton);
// Sound Mute Button
settingsUI.soundMuteButton = new Text2(storage.soundMuted ? 'UNMUTE SOUND' : 'MUTE SOUND', {
size: 50,
fill: storage.soundMuted ? 0xFF0000 : 0xFFFF00
});
settingsUI.soundMuteButton.anchor.set(0.5, 0.5);
settingsUI.soundMuteButton.x = 1024;
settingsUI.soundMuteButton.y = 800;
settingsUI.container.addChild(settingsUI.soundMuteButton);
// Music Volume Label
settingsUI.musicVolumeLabel = new Text2('Music Volume:', {
size: 60,
fill: 0xFFFFFF
});
settingsUI.musicVolumeLabel.anchor.set(0.5, 0.5);
settingsUI.musicVolumeLabel.x = 1024;
settingsUI.musicVolumeLabel.y = 900;
settingsUI.container.addChild(settingsUI.musicVolumeLabel);
// Music Volume Buttons
settingsUI.musicLowButton = new Text2('LOW', {
size: 50,
fill: storage.musicVolume === 0.3 ? 0x00FF00 : 0xFFFFFF
});
settingsUI.musicLowButton.anchor.set(0.5, 0.5);
settingsUI.musicLowButton.x = 700;
settingsUI.musicLowButton.y = 1000;
settingsUI.container.addChild(settingsUI.musicLowButton);
settingsUI.musicMedButton = new Text2('MED', {
size: 50,
fill: storage.musicVolume === 0.7 ? 0x00FF00 : 0xFFFFFF
});
settingsUI.musicMedButton.anchor.set(0.5, 0.5);
settingsUI.musicMedButton.x = 1024;
settingsUI.musicMedButton.y = 1000;
settingsUI.container.addChild(settingsUI.musicMedButton);
settingsUI.musicHighButton = new Text2('HIGH', {
size: 50,
fill: storage.musicVolume === 1.0 ? 0x00FF00 : 0xFFFFFF
});
settingsUI.musicHighButton.anchor.set(0.5, 0.5);
settingsUI.musicHighButton.x = 1348;
settingsUI.musicHighButton.y = 1000;
settingsUI.container.addChild(settingsUI.musicHighButton);
// Music Mute Button
settingsUI.musicMuteButton = new Text2(storage.musicMuted ? 'UNMUTE MUSIC' : 'MUTE MUSIC', {
size: 50,
fill: storage.musicMuted ? 0xFF0000 : 0xFFFF00
});
settingsUI.musicMuteButton.anchor.set(0.5, 0.5);
settingsUI.musicMuteButton.x = 1024;
settingsUI.musicMuteButton.y = 1100;
settingsUI.container.addChild(settingsUI.musicMuteButton);
}
// Create shop menu UI
function createShopMenu() {
shopUI.container = new Container();
game.addChild(shopUI.container);
shopUI.container.visible = false;
// Title
shopUI.title = new Text2('SHOP', {
size: 100,
fill: 0xFFFFFF
});
shopUI.title.anchor.set(0.5, 0.5);
shopUI.title.x = 1024;
shopUI.title.y = 300;
shopUI.container.addChild(shopUI.title);
// Coins display
shopUI.coinsText = new Text2('Coins: ' + storage.coins, {
size: 50,
fill: 0xFFD700
});
shopUI.coinsText.anchor.set(0.5, 0.5);
shopUI.coinsText.x = 1024;
shopUI.coinsText.y = 400;
shopUI.container.addChild(shopUI.coinsText);
// Skin selection area
shopUI.skinButtons = [];
for (var i = 0; i < playerSkins.length; i++) {
var skin = playerSkins[i];
var yPos = 550 + i * 120;
// Skin name
var skinText = new Text2(skin.name, {
size: 50,
fill: storage.selectedSkin === i ? 0x00FF00 : 0xFFFFFF
});
skinText.anchor.set(0.5, 0.5);
skinText.x = 700;
skinText.y = yPos;
shopUI.container.addChild(skinText);
// Cost/Status
var statusText;
if (storage.unlockedSkins.indexOf(i) !== -1) {
if (storage.selectedSkin === i) {
statusText = new Text2('EQUIPPED', {
size: 40,
fill: 0x00FF00
});
} else {
statusText = new Text2('SELECT', {
size: 40,
fill: 0xFFFF00
});
}
} else {
statusText = new Text2('Cost: ' + skin.cost, {
size: 40,
fill: 0xFF0000
});
}
statusText.anchor.set(0.5, 0.5);
statusText.x = 1300;
statusText.y = yPos;
shopUI.container.addChild(statusText);
shopUI.skinButtons.push({
skinText: skinText,
statusText: statusText,
skinIndex: i,
yPos: yPos
});
}
// Back button with custom background
shopUI.backButtonBg = shopUI.container.attachAsset('menuButtonBack', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1200
});
shopUI.backButton = new Text2('BACK', {
size: 60,
fill: 0xFFFFFF
});
shopUI.backButton.anchor.set(0.5, 0.5);
shopUI.backButton.x = 1024;
shopUI.backButton.y = 1200;
shopUI.container.addChild(shopUI.backButton);
}
// Update settings UI
function updateSettingsUI() {
settingsUI.soundLowButton.tint = storage.soundVolume === 0.3 ? 0x00FF00 : 0xFFFFFF;
settingsUI.soundMedButton.tint = storage.soundVolume === 0.7 ? 0x00FF00 : 0xFFFFFF;
settingsUI.soundHighButton.tint = storage.soundVolume === 1.0 ? 0x00FF00 : 0xFFFFFF;
settingsUI.soundMuteButton.setText(storage.soundMuted ? 'UNMUTE SOUND' : 'MUTE SOUND');
settingsUI.soundMuteButton.tint = storage.soundMuted ? 0xFF0000 : 0xFFFF00;
settingsUI.musicLowButton.tint = storage.musicVolume === 0.3 ? 0x00FF00 : 0xFFFFFF;
settingsUI.musicMedButton.tint = storage.musicVolume === 0.7 ? 0x00FF00 : 0xFFFFFF;
settingsUI.musicHighButton.tint = storage.musicVolume === 1.0 ? 0x00FF00 : 0xFFFFFF;
settingsUI.musicMuteButton.setText(storage.musicMuted ? 'UNMUTE MUSIC' : 'MUTE MUSIC');
settingsUI.musicMuteButton.tint = storage.musicMuted ? 0xFF0000 : 0xFFFF00;
}
// Update shop UI
function updateShopUI() {
shopUI.coinsText.setText('Coins: ' + storage.coins);
for (var i = 0; i < shopUI.skinButtons.length; i++) {
var button = shopUI.skinButtons[i];
var skin = playerSkins[button.skinIndex];
// Update skin name color
button.skinText.tint = storage.selectedSkin === button.skinIndex ? 0x00FF00 : 0xFFFFFF;
// Update status text
if (storage.unlockedSkins.indexOf(button.skinIndex) !== -1) {
if (storage.selectedSkin === button.skinIndex) {
button.statusText.setText('EQUIPPED');
button.statusText.tint = 0x00FF00;
} else {
button.statusText.setText('SELECT');
button.statusText.tint = 0xFFFF00;
}
} else {
button.statusText.setText('Cost: ' + skin.cost);
button.statusText.tint = storage.coins >= skin.cost ? 0xFFFF00 : 0xFF0000;
}
}
}
// Show specific menu
function showMenu(menuType) {
gameState = menuType;
menuUI.container.visible = menuType === 'menu';
settingsUI.container.visible = menuType === 'settings';
shopUI.container.visible = menuType === 'shop';
if (menuType === 'shop') {
updateShopUI();
}
if (menuType === 'settings') {
updateSettingsUI();
}
if (menuType === 'menu') {
menuUI.highScoreText.setText('High Score: ' + storage.highScore);
menuUI.coinsText.setText('Coins: ' + storage.coins);
}
}
// Apply music volume settings
function applyMusicVolume() {
if (storage.musicMuted) {
LK.stopMusic();
} else {
LK.playMusic('BackSound', {
fade: {
start: 0,
end: storage.musicVolume,
duration: 500
}
});
}
}
// Apply sound volume to a sound effect
function playSound(soundId) {
if (!storage.soundMuted) {
var sound = LK.getSound(soundId);
sound.volume = storage.soundVolume;
sound.play();
}
}
// Start the actual game
function startGame() {
gameState = 'playing';
isGameStarted = true;
// Hide all menus
menuUI.container.visible = false;
settingsUI.container.visible = false;
shopUI.container.visible = false;
// Initialize level
createPlatforms();
createObstacles();
// Start background music with volume settings
applyMusicVolume();
}
// Initialize menus
createMainMenu();
createSettingsMenu();
createShopMenu();
showMenu('menu');
// Input handling
game.down = function (x, y, obj) {
if (gameState === 'menu') {
// Check menu button clicks
if (y >= 750 && y <= 850) {
// Play button
startGame();
} else if (y >= 900 && y <= 1000) {
// Settings button
showMenu('settings');
} else if (y >= 1050 && y <= 1150) {
// Shop button
showMenu('shop');
} else if (y >= 1200 && y <= 1300) {
// Quit button (for web games, this might just show a message)
console.log('Quit button pressed');
}
return;
}
if (gameState === 'settings') {
// Check sound volume buttons
if (y >= 650 && y <= 750) {
if (x >= 650 && x <= 750) {
// Sound Low
storage.soundVolume = 0.3;
updateSettingsUI();
} else if (x >= 974 && x <= 1074) {
// Sound Med
storage.soundVolume = 0.7;
updateSettingsUI();
} else if (x >= 1298 && x <= 1398) {
// Sound High
storage.soundVolume = 1.0;
updateSettingsUI();
}
return;
}
// Check sound mute button
if (y >= 750 && y <= 850) {
storage.soundMuted = !storage.soundMuted;
updateSettingsUI();
return;
}
// Check music volume buttons
if (y >= 950 && y <= 1050) {
if (x >= 650 && x <= 750) {
// Music Low
storage.musicVolume = 0.3;
updateSettingsUI();
applyMusicVolume();
} else if (x >= 974 && x <= 1074) {
// Music Med
storage.musicVolume = 0.7;
updateSettingsUI();
applyMusicVolume();
} else if (x >= 1298 && x <= 1398) {
// Music High
storage.musicVolume = 1.0;
updateSettingsUI();
applyMusicVolume();
}
return;
}
// Check music mute button
if (y >= 1050 && y <= 1150) {
storage.musicMuted = !storage.musicMuted;
updateSettingsUI();
applyMusicVolume();
return;
}
// Check back button
if (y >= 1150 && y <= 1250) {
showMenu('menu');
}
return;
}
if (gameState === 'shop') {
// Check skin buttons
for (var i = 0; i < shopUI.skinButtons.length; i++) {
var button = shopUI.skinButtons[i];
if (y >= button.yPos - 50 && y <= button.yPos + 50) {
var skin = playerSkins[button.skinIndex];
if (storage.unlockedSkins.indexOf(button.skinIndex) !== -1) {
// Skin is unlocked, select it
storage.selectedSkin = button.skinIndex;
updateShopUI();
} else if (storage.coins >= skin.cost) {
// Purchase skin
storage.coins -= skin.cost;
storage.unlockedSkins.push(button.skinIndex);
storage.selectedSkin = button.skinIndex;
updateShopUI();
}
return;
}
}
// Check back button
if (y >= 1150 && y <= 1250) {
showMenu('menu');
}
return;
}
if (gameState === 'playing') {
if (x < 1024) {
leftPressed = true;
} else if (x > 1024) {
rightPressed = true;
}
// Jump on tap
player.jump();
}
};
game.up = function (x, y, obj) {
leftPressed = false;
rightPressed = false;
};
// Game update loop
game.update = function () {
if (gameState !== 'playing') {
return;
}
// Handle input
if (leftPressed) {
player.moveLeft();
} else if (rightPressed) {
player.moveRight();
} else if (currentDimension !== 4) {
// Stop horizontal movement (except on ice)
player.velocityX = 0;
}
// Update dimension timer
dimensionTimer++;
var timeLeft = Math.ceil((maxDimensionTime - dimensionTimer) / 60);
timerText.setText('Time: ' + timeLeft + 's');
// Flash timer when low
if (timeLeft <= 5) {
timerText.alpha = Math.sin(LK.ticks * 0.3) * 0.5 + 0.5;
} else {
timerText.alpha = 1;
}
// Check for dimension change
if (dimensionTimer >= maxDimensionTime) {
// Game over - player failed to reach portal in time
showGameOverScreen();
}
// Check portal collision
if (player.intersects(portal)) {
changeDimension();
}
// Check obstacle collisions
for (var i = 0; i < obstacles.length; i++) {
if (player.intersects(obstacles[i])) {
playSound('hit');
LK.effects.flashScreen(0xff0000, 500);
player.resetPosition();
break;
}
}
// Update score
scoreText.setText('Score: ' + LK.getScore().toString());
};
function changeDimension() {
playSound('portal');
LK.setScore(LK.getScore() + 10);
// Award coins
storage.coins += 5;
// Update high score
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
}
// Flash effect
LK.effects.flashScreen(0xffffff, 300);
// Reset timer
dimensionTimer = 0;
// Change dimension
currentDimension = (currentDimension + 1) % 5;
// Change background
for (var i = 0; i < backgrounds.length; i++) {
tween(backgrounds[i], {
alpha: i === currentDimension ? 1 : 0
}, {
duration: 500
});
}
// Update UI
dimensionText.setText('Dimension: ' + dimensionNames[currentDimension]);
// Reset player position and velocity
player.x = 200;
if (currentDimension === 1) {
player.y = 2200; // Start at bottom for reverse gravity
} else {
player.y = 1000;
}
player.velocityX = 0;
player.velocityY = 0;
// Recreate platforms and obstacles
createPlatforms();
createObstacles();
// Move portal to new position
portal.x = 1600 + Math.random() * 200;
portal.y = 300 + Math.random() * 200;
// Check win condition
if (LK.getScore() >= 100) {
LK.showYouWin();
}
}
dead logo obstacle red color. In-Game asset. 2d. High contrast. No shadows
size 200x20 PLATFORM Shape Box. In-Game asset. 2d. High contrast. No shadows
The education 2d player video game 2d player. In-Game asset. 2d. High contrast. No shadows
Video game 2D Portal image. In-Game asset. 2d. High contrast. No shadows
2D Video game Background with not platform just SKY. In-Game asset. 2d. High contrast. No shadows
Just For 2D Video Game Reverse Sky With Out Platforme`s BUt its reverse
Ice theme background 2d game video. In-Game asset. 2d. High contrast. No shadows
Under Water Background for 2d games. In-Game asset. 2d. High contrast. No shadows
Play button for portal video game. In-Game asset. 2d. High contrast. No shadows
play button for video game. In-Game asset. 2d. High contrast. No shadows
Quit button for video game. In-Game asset. 2d. High contrast. No shadows
settings button for video game have a text. In-Game asset. 2d. High contrast. No shadows
shop button for 2d video game. In-Game asset. 2d. High contrast. No shadows
low gravity background background fro 2d game. In-Game asset. 2d. High contrast. No shadows