User prompt
Add a eminem inspired song
User prompt
Now could you add Channel Z for the music by the b52s
User prompt
Get rid of the owner only button
User prompt
Move the owner button to the right a tiny bit
User prompt
Add the owner button in between the score and the level texts
User prompt
There should be a button that says owner only and only the owner can click it ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Remove the owner only button
User prompt
Please fix the bug: 'Uncaught ReferenceError: auth is not defined' in or related to this line: 'if (auth.isOwner()) {' Line Number: 633
User prompt
Please fix the bug: 'Uncaught ReferenceError: auth is not defined' in or related to this line: 'if (auth.isOwner()) {' Line Number: 633
User prompt
Please fix the bug: 'Uncaught ReferenceError: auth is not defined' in or related to this line: 'if (auth.isOwner()) {' Line Number: 632
User prompt
Please fix the bug: 'Uncaught ReferenceError: auth is not defined' in or related to this line: 'if (auth.isOwner()) {' Line Number: 632
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Import auth plugin for isOwner() function
//Storage functionality removed as requested
var Coin = Container.expand(function () {
var self = Container.call(this);
// Coin sprite
var sprite = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
// Animate coin
self.update = function () {
sprite.rotation += 0.05;
};
self.collect = function () {
LK.getSound('coin').play();
self.destroy();
};
return self;
});
var ControlButton = Container.expand(function (type) {
var self = Container.call(this);
// Control button properties
self.type = type; // 'jump', 'left', or 'right'
self.isPressed = false;
// Button sprite
var sprite = self.attachAsset(type + 'Button', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
// Button icon (text inside the button)
var icon;
if (type === 'jump') {
icon = new Text2('↑', {
size: 100,
fill: 0xFFFFFF
});
} else if (type === 'left') {
icon = new Text2('←', {
size: 100,
fill: 0xFFFFFF
});
} else if (type === 'right') {
icon = new Text2('→', {
size: 100,
fill: 0xFFFFFF
});
}
if (icon) {
icon.anchor.set(0.5, 0.5);
self.addChild(icon);
}
self.down = function (x, y, obj) {
self.isPressed = true;
// Use tween for alpha change with proper easing function
tween(sprite, {
alpha: 0.8
}, {
duration: 100,
easing: tween.easeOutQuad
});
};
self.up = function (x, y, obj) {
self.isPressed = false;
sprite.alpha = 0.5;
};
return self;
});
var Enemy = Container.expand(function (patrolDistance) {
var self = Container.call(this);
// Default parameter
patrolDistance = patrolDistance || 200;
// Enemy properties
self.speed = 3;
self.direction = 1;
self.patrolDistance = patrolDistance;
self.startX = 0;
// Enemy sprite
var sprite = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
self.x += self.speed * self.direction;
// Check if we need to change direction
if (Math.abs(self.x - self.startX) > self.patrolDistance) {
self.direction *= -1;
sprite.scaleX = -sprite.scaleX; // Flip the enemy when changing direction
}
};
self.setStartPosition = function (x, y) {
self.x = x;
self.y = y;
self.startX = x;
};
return self;
});
var Goal = Container.expand(function () {
var self = Container.call(this);
// Goal sprite
var sprite = self.attachAsset('goal', {
anchorX: 0.5,
anchorY: 0.5
});
self.reach = function () {
LK.getSound('win').play();
LK.effects.flashObject(self, 0x00ff00, 1000);
// Teleport to next level immediately
// Increment level and create new level
level += 1;
levelTxt.setText('Level: ' + level);
createLevel(level);
};
return self;
});
var Platform = Container.expand(function (width, height, isMoving) {
var self = Container.call(this);
// Default parameters
width = width || 200;
height = height || 30;
isMoving = isMoving || false;
// Platform properties
self.isMoving = isMoving;
self.moveSpeed = 2;
self.direction = 1;
self.moveDistance = 300;
self.startX = 0;
self.lastX = 0; // Initialize lastX for tracking platform movement
// Platform sprite
var sprite = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
width: width,
height: height
});
self.update = function () {
if (self.isMoving) {
// Store previous x position to calculate movement delta
self.lastX = self.x;
self.x += self.moveSpeed * self.direction;
// Check if we need to change direction
if (Math.abs(self.x - self.startX) > self.moveDistance) {
self.direction *= -1;
}
}
};
self.setStartPosition = function (x, y) {
self.x = x;
self.y = y;
self.startX = x;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
// Player properties
self.vx = 0;
self.vy = 0;
self.speed = 8;
self.jumpForce = -25; // Increased jump force from -20 to -25
self.gravity = 0.8; // Reduced gravity from 1 to 0.8
self.isJumping = false;
self.isDead = false;
self.facingRight = true;
self.canJump = false;
// Create a simple block character with eyes and smiley face
// Main block (body)
var block = self.addChild(LK.getAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
width: 80,
height: 80,
tint: 0x4287f5 // Blue block color
}));
// Eyes (small white rectangles)
var leftEye = self.addChild(LK.getAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
width: 10,
height: 10,
x: -20,
y: -15,
tint: 0xFFFFFF // White eyes
}));
var rightEye = self.addChild(LK.getAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
width: 10,
height: 10,
x: 20,
y: -15,
tint: 0xFFFFFF // White eyes
}));
// Smile (simple arc using three rectangles)
var leftSmile = self.addChild(LK.getAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
width: 15,
height: 5,
x: -15,
y: 15,
tint: 0x000000 // Black smile
}));
var rightSmile = self.addChild(LK.getAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
width: 15,
height: 5,
x: 15,
y: 15,
tint: 0x000000 // Black smile
}));
var bottomSmile = self.addChild(LK.getAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
width: 30,
height: 5,
x: 0,
y: 20,
tint: 0x000000 // Black smile
}));
// Store reference to all parts for animation
self.parts = {
block: block,
leftEye: leftEye,
rightEye: rightEye,
leftSmile: leftSmile,
rightSmile: rightSmile,
bottomSmile: bottomSmile
};
// Create a hitbox for collision detection (invisible)
var sprite = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0 // Make invisible, just for collision
});
self.update = function () {
if (self.isDead) {
return;
}
// Store previous position to track changes
self.lastX = self.x;
self.lastY = self.y;
// Apply gravity with terminal velocity to prevent falling too fast
self.vy = Math.min(self.vy + self.gravity, 25);
// Apply air resistance when jumping
if (self.isJumping) {
self.vx *= 0.98; // Less friction in air
} else {
self.vx *= 0.85; // More friction on ground
}
// Add coyote time for more forgiving jumps
if (self.canJump) {
self.lastOnGroundTime = LK.ticks;
}
// Allow jump within 7 frames of leaving a platform (coyote time)
if (self.lastOnGroundTime && LK.ticks - self.lastOnGroundTime < 7) {
self.canJump = true;
}
// Update position based on velocity with subpixel movement for smoother motion
self.x += self.vx;
self.y += self.vy;
// Reset jump state if on ground
if (self.canJump) {
self.isJumping = false;
} else {
self.isJumping = true;
}
// Only update animations every other frame to reduce CPU load
if (LK.ticks % 2 === 0) {
// Keep player oriented based on direction
if (self.vx > 0.5 && !self.facingRight) {
self.facingRight = true;
sprite.scaleX = 1;
// Flip all parts to face right
Object.values(self.parts).forEach(function (part) {
part.scaleX = Math.abs(part.scaleX);
});
self.parts.leftEye.x = -20;
self.parts.rightEye.x = 20;
self.parts.leftSmile.x = -15;
self.parts.rightSmile.x = 15;
self.parts.bottomSmile.x = 0;
} else if (self.vx < -0.5 && self.facingRight) {
self.facingRight = false;
sprite.scaleX = -1;
// Flip all parts to face left
Object.values(self.parts).forEach(function (part) {
part.scaleX = -Math.abs(part.scaleX);
});
self.parts.leftEye.x = 20;
self.parts.rightEye.x = -20;
self.parts.leftSmile.x = 15;
self.parts.rightSmile.x = -15;
self.parts.bottomSmile.x = 0;
}
// Dynamic block rotation based on velocity
if (Math.abs(self.vx) > 0.5) {
// Proportional tilt based on speed
var tiltAmount = Math.min(Math.abs(self.vx) * 0.01, 0.15);
self.parts.block.rotation = self.vx > 0 ? tiltAmount : -tiltAmount;
} else {
// Reset when standing still
if (self.parts.block.rotation !== 0) {
tween(self.parts.block, {
rotation: 0
}, {
duration: 150,
easing: tween.easeOutQuad
});
}
}
// Enhanced jumping animation
if (self.isJumping) {
// Dynamic squish based on vertical velocity
var jumpSquish = Math.min(Math.abs(self.vy) * 0.02, 0.3);
// Rising vs falling animation
if (self.vy < 0) {
// Rising - stretch vertically
self.parts.block.scaleY = 1 + jumpSquish;
self.parts.block.scaleX = self.facingRight ? 1 - jumpSquish * 0.5 : -(1 - jumpSquish * 0.5);
} else {
// Falling - compress horizontally
self.parts.block.scaleY = 1 - jumpSquish * 0.7;
self.parts.block.scaleX = self.facingRight ? 1 + jumpSquish : -(1 + jumpSquish);
}
} else {
// Subtle bounce when on ground and moving
if (Math.abs(self.vx) > 1) {
var bounceAmount = Math.sin(LK.ticks * 0.2) * 0.05;
self.parts.block.scaleY = 1 + bounceAmount;
self.parts.block.scaleX = self.facingRight ? 1 - bounceAmount * 0.5 : -(1 - bounceAmount * 0.5);
} else {
// Reset scale when not jumping or moving
self.parts.block.scaleY = 1;
self.parts.block.scaleX = self.facingRight ? 1 : -1;
}
}
// Enhanced blinking system
if (!self.nextBlinkTime) {
self.nextBlinkTime = LK.ticks + Math.floor(Math.random() * 180) + 180; // 3-6 seconds at 60fps
}
if (LK.ticks >= self.nextBlinkTime) {
// Hide eyes for blinking with smooth animation
tween(self.parts.leftEye, {
scaleY: 0.1
}, {
duration: 100
});
tween(self.parts.rightEye, {
scaleY: 0.1
}, {
duration: 100
});
// Show eyes after blink with smooth animation
if (LK.ticks >= self.nextBlinkTime + 5) {
tween(self.parts.leftEye, {
scaleY: 1
}, {
duration: 100
});
tween(self.parts.rightEye, {
scaleY: 1
}, {
duration: 100
});
// Set next blink time
self.nextBlinkTime = LK.ticks + Math.floor(Math.random() * 180) + 180;
}
}
}
};
self.jump = function () {
if (self.canJump && !self.isDead) {
self.vy = self.jumpForce;
self.isJumping = true;
LK.getSound('jump').play();
// Add jump animation with tween
tween(self.parts.block, {
scaleY: 0.7,
scaleX: self.facingRight ? 1.3 : -1.3
}, {
duration: 200,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Return to normal after the jump animation
tween(self.parts.block, {
scaleY: 1,
scaleX: self.facingRight ? 1 : -1
}, {
duration: 300,
easing: tween.easeOutQuad
});
}
});
// Make the face look excited during jump
tween(self.parts.leftEye, {
y: -20
}, {
duration: 300,
easing: tween.easeOutQuad
});
tween(self.parts.rightEye, {
y: -20
}, {
duration: 300,
easing: tween.easeOutQuad
});
tween(self.parts.bottomSmile, {
y: 15
}, {
duration: 300,
easing: tween.easeOutQuad
});
// Reset face after jump animation
LK.setTimeout(function () {
if (!self.isDead) {
tween(self.parts.leftEye, {
y: -15
}, {
duration: 300,
easing: tween.easeInOutQuad
});
tween(self.parts.rightEye, {
y: -15
}, {
duration: 300,
easing: tween.easeInOutQuad
});
tween(self.parts.bottomSmile, {
y: 20
}, {
duration: 300,
easing: tween.easeInOutQuad
});
}
}, 350);
self.canJump = false;
}
};
self.moveLeft = function () {
if (!self.isDead) {
// Smooth acceleration to the left
self.vx = Math.max(self.vx - 1.5, -self.speed);
// Add slight lean effect when moving left
if (self.facingRight) {
self.facingRight = false;
tween(self.parts.block, {
rotation: -0.1
}, {
duration: 200,
easing: tween.easeOutQuad
});
}
}
};
self.moveRight = function () {
if (!self.isDead) {
// Smooth acceleration to the right
self.vx = Math.min(self.vx + 1.5, self.speed);
// Add slight lean effect when moving right
if (!self.facingRight) {
self.facingRight = true;
tween(self.parts.block, {
rotation: 0.1
}, {
duration: 200,
easing: tween.easeOutQuad
});
}
}
};
self.stop = function () {
if (!self.isDead) {
// Smooth deceleration to stop
if (Math.abs(self.vx) < 0.5) {
self.vx = 0;
} else {
self.vx *= 0.8; // Gradually slow down
}
// Return to upright position when stopping
tween(self.parts.block, {
rotation: 0
}, {
duration: 200,
easing: tween.easeOutQuad
});
}
};
self.die = function () {
if (!self.isDead) {
self.isDead = true;
LK.getSound('hit').play();
LK.effects.flashObject(self, 0xff0000, 500);
// Block death animation - scatter the block parts
Object.values(self.parts).forEach(function (part) {
// Use tween to create a scatter effect
tween(part, {
y: part.y + (Math.random() * 300 - 150),
x: part.x + (Math.random() * 300 - 150),
rotation: Math.floor(Math.random() * 4) * (Math.PI / 2),
alpha: 0
}, {
duration: 800,
easing: tween.easeInQuad
});
});
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
};
return self;
});
// SettingsButton class removed as requested
var Spike = Container.expand(function () {
var self = Container.call(this);
// Spike sprite
var sprite = self.attachAsset('spike', {
anchorX: 0.5,
anchorY: 0.5
});
// Make spike pointy with rotation
sprite.rotation = Math.PI;
// Animation for spike
self.update = function () {
// Subtle pulsing animation
if (!self.pulseDirection) {
self.pulseDirection = 1;
self.pulseValue = 0;
}
self.pulseValue += 0.02 * self.pulseDirection;
if (self.pulseValue > 1 || self.pulseValue < 0) {
self.pulseDirection *= -1;
}
var scale = 0.95 + self.pulseValue * 0.1;
// Directly set x and y scale properties instead of using scale.set
sprite.scale.x = 1;
sprite.scale.y = scale;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue
});
/****
* Game Code
****/
// Game variables
var player;
var platforms = [];
var coins = [];
var enemies = [];
var goal;
var jumpButton;
var leftButton;
var rightButton;
var cameraPosX = 0;
var cameraPosY = 0;
var worldContainer;
var uiContainer;
var levelWidth = 5000; // The total width of the level
var groundY = 2732 - 100; // Y position of the ground
var score = 0;
var level = 1;
// Initialize UI
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -250; // Offset from topRight anchor
var levelTxt = new Text2('Level: ' + level, {
size: 60,
fill: 0xFFFFFF
});
levelTxt.anchor.set(0, 0);
LK.gui.top.addChild(levelTxt);
// Add Owner Only button
var ownerOnlyBtn = new Container();
var ownerOnlyBg = ownerOnlyBtn.addChild(LK.getAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
width: 200,
height: 60,
tint: 0x3498db // Blue color
}));
var ownerOnlyText = new Text2('Owner Only', {
size: 30,
fill: 0xFFFFFF
});
ownerOnlyText.anchor.set(0.5, 0.5);
ownerOnlyBtn.addChild(ownerOnlyText);
ownerOnlyBtn.x = 160; // Position next to level text
ownerOnlyBtn.y = 0;
LK.gui.top.addChild(ownerOnlyBtn);
// Add click detection for the owner only button
ownerOnlyBtn.down = function (x, y, obj) {
// Check if the current user is the owner
if (auth.isOwner()) {
// Only owner can trigger this
LK.effects.flashObject(ownerOnlyBtn, 0x00ff00, 500); // Green flash to indicate success
ownerOnlyText.setText('Access Granted');
// Reset text after 2 seconds
LK.setTimeout(function () {
ownerOnlyText.setText('Owner Only');
}, 2000);
} else {
// Not the owner
LK.effects.flashObject(ownerOnlyBtn, 0xff0000, 500); // Red flash to indicate failure
ownerOnlyText.setText('Access Denied');
// Reset text after 2 seconds
LK.setTimeout(function () {
ownerOnlyText.setText('Owner Only');
}, 2000);
}
};
// Initialize world container to allow camera movement
worldContainer = new Container();
game.addChild(worldContainer);
// Create player
player = new Player();
player.x = 200;
player.y = groundY - 200;
worldContainer.addChild(player);
// Create control buttons
jumpButton = new ControlButton('jump');
jumpButton.x = 2048 - 250;
jumpButton.y = 2732 - 250;
jumpButton.scale.set(1.5, 1.5); // Make jump button 50% larger
game.addChild(jumpButton);
leftButton = new ControlButton('left');
leftButton.x = 200;
leftButton.y = 2732 - 250;
leftButton.scale.set(1.5, 1.5); // Make left button 50% larger
game.addChild(leftButton);
rightButton = new ControlButton('right');
rightButton.x = 500;
rightButton.y = 2732 - 250;
rightButton.scale.set(1.5, 1.5); // Make right button 50% larger
game.addChild(rightButton);
// Create level function
function createLevel(level) {
// Clear previous level objects
for (var i = platforms.length - 1; i >= 0; i--) {
worldContainer.removeChild(platforms[i]);
platforms.splice(i, 1);
}
for (var i = coins.length - 1; i >= 0; i--) {
worldContainer.removeChild(coins[i]);
coins.splice(i, 1);
}
for (var i = enemies.length - 1; i >= 0; i--) {
worldContainer.removeChild(enemies[i]);
enemies.splice(i, 1);
}
if (goal) {
worldContainer.removeChild(goal);
goal = null;
}
// Create ground - ensure complete coverage
for (var i = 0; i < levelWidth; i += 400) {
var ground = new Platform(400, 50, false);
ground.setStartPosition(i + 200, groundY);
// Apply brown color to ground platforms
var groundSprite = ground.children[0];
tween(groundSprite, {
tint: 0x8b4513
}, {
duration: 0
}); // Make ground brown
worldContainer.addChild(ground);
platforms.push(ground);
}
// Add additional terrain features
// Add dirt layer below ground
for (var i = 0; i < levelWidth; i += 400) {
var dirt = new Platform(400, 100, false);
dirt.setStartPosition(i + 200, groundY + 75);
var dirtSprite = dirt.children[0];
tween(dirtSprite, {
tint: 0x5d3a1a // Darker brown for dirt
}, {
duration: 0
});
worldContainer.addChild(dirt);
platforms.push(dirt);
}
// Add rocky foundation at the bottom
for (var i = 0; i < levelWidth; i += 400) {
var rock = new Platform(400, 200, false);
rock.setStartPosition(i + 200, groundY + 225);
var rockSprite = rock.children[0];
tween(rockSprite, {
tint: 0x444444 // Dark gray for rocks
}, {
duration: 0
});
worldContainer.addChild(rock);
platforms.push(rock);
}
// Update level width based on level
if (level === 2) {
levelWidth = 6000; // Extend level width for level 2
} else if (level === 5) {
levelWidth = 6000; // Extend level width for level 5
} else if (level === 6) {
levelWidth = 7000; // Extend level width for level 6
} else if (level === 7) {
levelWidth = 8000; // Extend level width for level 7
} else if (level === 8) {
levelWidth = 8500; // Extend level width for level 8
} else if (level === 9) {
levelWidth = 9000; // Extend level width for level 9
} else if (level === 10) {
levelWidth = 10000; // Extend level width for level 10
} else {
levelWidth = 5000; // Default level width
}
// Level-specific configurations
switch (level) {
case 1:
// Level 1: Basic platforms and coins
createPlatform(600, groundY - 200, 200, 30, false);
createPlatform(900, groundY - 350, 200, 30, false);
createPlatform(1300, groundY - 500, 200, 30, false);
createPlatform(1700, groundY - 350, 200, 30, false);
createPlatform(2100, groundY - 200, 200, 30, false);
createCoin(600, groundY - 300);
createCoin(900, groundY - 450);
createCoin(1300, groundY - 600);
createCoin(1700, groundY - 450);
createCoin(2100, groundY - 300);
// Place goal at the end of level 1
createGoal(2400, groundY - 100);
break;
case 2:
// Level 2: Moving platforms, enemies and spikes
// Starting platforms
createPlatform(500, groundY - 200, 200, 30, false);
createPlatform(800, groundY - 300, 200, 30, true);
// First section - moving platform challenge
createPlatform(1200, groundY - 400, 150, 30, true);
createPlatform(1600, groundY - 350, 150, 30, true);
createPlatform(2000, groundY - 400, 150, 30, true);
// Middle section - spike hazards
createPlatform(2400, groundY - 300, 300, 30, false);
createSpike(2350, groundY - 350);
createSpike(2450, groundY - 350);
createSpike(2550, groundY - 350);
// Enemy section with platforms
createPlatform(2800, groundY - 200, 200, 30, false);
createPlatform(3200, groundY - 350, 200, 30, false);
createPlatform(3600, groundY - 500, 200, 30, true);
createPlatform(4000, groundY - 350, 200, 30, false);
// Final challenge section
createPlatform(4400, groundY - 300, 150, 30, true);
createPlatform(4700, groundY - 400, 150, 30, true);
createPlatform(5000, groundY - 300, 200, 30, false);
// Coins strategically placed
createCoin(500, groundY - 300);
createCoin(800, groundY - 400);
createCoin(1200, groundY - 500);
createCoin(1600, groundY - 450);
createCoin(2000, groundY - 500);
createCoin(2400, groundY - 400);
createCoin(3200, groundY - 450);
createCoin(3600, groundY - 600);
createCoin(4000, groundY - 450);
createCoin(4700, groundY - 500);
createCoin(5000, groundY - 400);
// Enemies patrolling
createEnemy(1000, groundY - 50, 300);
createEnemy(2000, groundY - 50, 400);
createEnemy(3000, groundY - 50, 500);
createEnemy(4000, groundY - 50, 600);
// Additional spikes on the ground
createSpike(1500, groundY - 50);
createSpike(2500, groundY - 50);
createSpike(3500, groundY - 50);
createSpike(4500, groundY - 50);
// Place goal at the end of level 2
createGoal(5200, groundY - 100);
break;
case 3:
// Level 3: Complex platforming with more enemies
createPlatform(500, groundY - 200, 200, 30, false);
createPlatform(800, groundY - 350, 200, 30, true);
createPlatform(1200, groundY - 500, 200, 30, false);
createPlatform(1600, groundY - 650, 200, 30, true);
createPlatform(2000, groundY - 500, 200, 30, false);
createPlatform(2400, groundY - 350, 200, 30, true);
createPlatform(2800, groundY - 200, 200, 30, false);
createPlatform(3200, groundY - 350, 200, 30, true);
createCoin(500, groundY - 300);
createCoin(800, groundY - 450);
createCoin(1200, groundY - 600);
createCoin(1600, groundY - 750);
createCoin(2000, groundY - 600);
createCoin(2400, groundY - 450);
createCoin(2800, groundY - 300);
createCoin(3200, groundY - 450);
createEnemy(700, groundY - 50, 200);
createEnemy(1400, groundY - 50, 300);
createEnemy(2100, groundY - 50, 400);
createEnemy(2800, groundY - 50, 500);
// Place goal at the end of level 3
createGoal(3600, groundY - 100);
break;
case 4:
// Level 4: Multi-path challenges with spike maze
// Starting area
createPlatform(400, groundY - 200, 200, 30, false);
createPlatform(700, groundY - 350, 200, 30, false);
// Upper path - difficult but rewarding
createPlatform(1000, groundY - 500, 200, 30, true);
createPlatform(1400, groundY - 650, 200, 30, true);
createPlatform(1800, groundY - 700, 200, 30, false);
createCoin(1000, groundY - 600);
createCoin(1400, groundY - 750);
createCoin(1800, groundY - 800);
// Lower path - safer but fewer rewards
createPlatform(1200, groundY - 250, 200, 30, false);
createPlatform(1600, groundY - 300, 200, 30, false);
createSpike(1400, groundY - 350);
createSpike(1800, groundY - 350);
createCoin(1200, groundY - 350);
// Paths converge
createPlatform(2200, groundY - 450, 300, 30, false);
// Spike maze section
createPlatform(2600, groundY - 300, 500, 30, false);
for (var i = 0; i < 8; i++) {
createSpike(2400 + i * 60, groundY - 350);
}
// Advanced enemy gauntlet
createPlatform(3200, groundY - 400, 200, 30, true);
createPlatform(3600, groundY - 500, 200, 30, true);
createPlatform(4000, groundY - 400, 200, 30, true);
createEnemy(3200, groundY - 500, 150);
createEnemy(3600, groundY - 600, 150);
createEnemy(4000, groundY - 500, 150);
createCoin(3200, groundY - 500);
createCoin(3600, groundY - 600);
createCoin(4000, groundY - 500);
// Final stretch with vertical challenge
createPlatform(4400, groundY - 300, 200, 30, false);
createPlatform(4700, groundY - 450, 200, 30, false);
createPlatform(5000, groundY - 600, 200, 30, false);
createCoin(4400, groundY - 400);
createCoin(4700, groundY - 550);
createCoin(5000, groundY - 700);
// Place goal at the end
createGoal(5300, groundY - 600);
break;
case 5:
// Level 5: Vertical climbing challenge
// Set longer level
levelWidth = 6000;
// Starting area
createPlatform(400, groundY - 200, 200, 30, false);
// Initial vertical section
for (var i = 0; i < 6; i++) {
var y = groundY - 300 - i * 150;
createPlatform(700, y, 150, 30, i % 2 === 0);
createCoin(700, y - 100);
}
// Dangerous moving platform section
createPlatform(1000, groundY - 1000, 150, 30, true);
createPlatform(1300, groundY - 1100, 150, 30, true);
createPlatform(1600, groundY - 1000, 150, 30, true);
createSpike(1000, groundY - 1050);
createSpike(1300, groundY - 1150);
createSpike(1600, groundY - 1050);
createCoin(1000, groundY - 1100);
createCoin(1300, groundY - 1200);
createCoin(1600, groundY - 1100);
// Horizontal traversal at height
for (var i = 0; i < 5; i++) {
createPlatform(2000 + i * 300, groundY - 900, 200, 30, i % 2 === 1);
createCoin(2000 + i * 300, groundY - 1000);
if (i % 2 === 0) {
createEnemy(2000 + i * 300, groundY - 950, 150);
}
}
// Descending section with enemies
for (var i = 0; i < 5; i++) {
var y = groundY - 800 + i * 150;
createPlatform(3600, y, 200, 30, false);
if (i % 2 === 0) {
createEnemy(3600, y - 50, 150);
}
createCoin(3600, y - 100);
}
// Final challenge section
createPlatform(4200, groundY - 300, 150, 30, true);
createPlatform(4500, groundY - 400, 150, 30, true);
createPlatform(4800, groundY - 500, 150, 30, true);
createPlatform(5100, groundY - 400, 150, 30, true);
createPlatform(5400, groundY - 300, 150, 30, true);
// Add spikes and coins to final section
for (var i = 0; i < 5; i++) {
createSpike(4200 + i * 300, groundY - 50);
createCoin(4200 + i * 300, groundY - 550);
}
// Place goal at the end
createGoal(5700, groundY - 300);
break;
case 6:
// Level 6: Precision timing challenge
levelWidth = 7000;
// Starting area
createPlatform(400, groundY - 200, 200, 30, false);
// Synchronized moving platform sequence
for (var i = 0; i < 8; i++) {
createPlatform(800 + i * 400, groundY - 300 - i % 2 * 200, 150, 30, true);
createCoin(800 + i * 400, groundY - 400 - i % 2 * 200);
}
// Enemy corridor
createPlatform(4000, groundY - 200, 800, 30, false);
for (var i = 0; i < 6; i++) {
createEnemy(4100 + i * 120, groundY - 250, 80);
if (i % 2 === 0) {
createCoin(4100 + i * 120, groundY - 350);
}
}
// Advanced jumping challenge
var jumpHeights = [350, 500, 400, 600, 450, 700, 500];
for (var i = 0; i < jumpHeights.length; i++) {
createPlatform(5000 + i * 250, groundY - jumpHeights[i], 150, 30, false);
createCoin(5000 + i * 250, groundY - jumpHeights[i] - 100);
}
// Enemy and spike combination
createPlatform(6800, groundY - 400, 400, 30, false);
for (var i = 0; i < 6; i++) {
if (i % 2 === 0) {
createEnemy(6700 + i * 70, groundY - 450, 60);
} else {
createSpike(6700 + i * 70, groundY - 450);
}
}
createCoin(6800, groundY - 500);
createCoin(7000, groundY - 500);
// Place goal at the end
createGoal(7200, groundY - 400);
break;
case 7:
// Level 7: Speed run with timed sections
levelWidth = 8000;
// Quick start
createPlatform(400, groundY - 200, 600, 30, false);
createCoin(400, groundY - 300);
createCoin(600, groundY - 300);
createCoin(800, groundY - 300);
// Fast moving platform sequence
for (var i = 0; i < 5; i++) {
var platform = createPlatform(1200 + i * 400, groundY - 300, 200, 30, true);
platform.moveSpeed = 4; // Faster movement
createCoin(1200 + i * 400, groundY - 400);
}
// Enemy sprint section
createPlatform(3200, groundY - 250, 1000, 30, false);
for (var i = 0; i < 10; i++) {
createEnemy(3300 + i * 100, groundY - 300, 80);
if (i % 3 === 0) {
createCoin(3300 + i * 100, groundY - 400);
}
}
// Spike jump sequence
for (var i = 0; i < 8; i++) {
createPlatform(4300 + i * 200, groundY - 250, 120, 30, false);
createSpike(4300 + i * 200 - 50, groundY - 300);
createSpike(4300 + i * 200 + 50, groundY - 300);
createCoin(4300 + i * 200, groundY - 350);
}
// Final sprint with alternating hazards
createPlatform(6000, groundY - 300, 1500, 30, false);
for (var i = 0; i < 12; i++) {
if (i % 3 === 0) {
createEnemy(6100 + i * 120, groundY - 350, 80);
} else if (i % 3 === 1) {
createSpike(6100 + i * 120, groundY - 350);
} else {
createCoin(6100 + i * 120, groundY - 450);
}
}
// Place goal at the end
createGoal(7600, groundY - 300);
break;
case 8:
// Level 8: Puzzle platforming
levelWidth = 8500;
// Starting section
createPlatform(400, groundY - 200, 200, 30, false);
// Vertical puzzle structure
var puzzleHeights = [300, 500, 700, 900, 700, 500, 300];
for (var i = 0; i < puzzleHeights.length; i++) {
for (var j = 0; j < puzzleHeights.length; j++) {
if ((i + j) % 2 === 0) {
createPlatform(800 + i * 200, groundY - puzzleHeights[j], 150, 30, false);
if (i === 3 && j === 3) {
// Special reward at the center of the maze
for (var k = 0; k < 5; k++) {
createCoin(800 + i * 200 - 40 + k * 20, groundY - puzzleHeights[j] - 100);
}
}
}
}
}
// Moving platform challenge
for (var i = 0; i < 5; i++) {
var yPos = groundY - 300 - Math.sin(i * 0.7) * 300;
createPlatform(2300 + i * 250, yPos, 150, 30, true);
createCoin(2300 + i * 250, yPos - 100);
}
// Enemy gauntlet with safe spots
createPlatform(3800, groundY - 300, 1200, 30, false);
for (var i = 0; i < 10; i++) {
if (i % 3 !== 1) {
// Every third space is safe
createEnemy(3900 + i * 120, groundY - 350, 80);
} else {
createCoin(3900 + i * 120, groundY - 400);
}
}
// Spike maze section
var mazeWidth = 2000;
var mazePlatform = createPlatform(5400, groundY - 400, mazeWidth, 30, false);
for (var i = 0; i < 30; i++) {
// Create a pattern of spikes with safe passages
if (i % 4 !== 0) {
createSpike(4400 + i * 70, groundY - 450);
} else {
createCoin(4400 + i * 70, groundY - 550);
}
}
// Final ascent
for (var i = 0; i < 6; i++) {
createPlatform(6800 + i * 200, groundY - 400 - i * 100, 150, 30, i % 2 === 0);
createCoin(6800 + i * 200, groundY - 450 - i * 100);
}
// Place goal at the end
createGoal(8000, groundY - 1000);
break;
case 9:
// Level 9: Speed and skill test
levelWidth = 9000;
// Quick start platforms
createPlatform(400, groundY - 200, 200, 30, false);
// Fast-paced moving platform sequence
for (var i = 0; i < 12; i++) {
var platform = createPlatform(800 + i * 300, groundY - 250 - Math.sin(i * 0.5) * 200, 150, 30, true);
platform.moveSpeed = 3 + i % 3; // Varying speeds
createCoin(800 + i * 300, groundY - 350 - Math.sin(i * 0.5) * 200);
}
// Spike jump challenge
for (var i = 0; i < 10; i++) {
createPlatform(4500 + i * 200, groundY - 300, 100, 30, false);
// Create spike patterns between platforms
for (var j = 0; j < 3; j++) {
createSpike(4500 + i * 200 - 80 + j * 40, groundY - 50);
}
createCoin(4500 + i * 200, groundY - 400);
}
// Enemy wave section
createPlatform(6500, groundY - 350, 1000, 30, false);
for (var i = 0; i < 8; i++) {
var enemy = createEnemy(6600 + i * 120, groundY - 400, 100);
if (i % 2 === 0) {
createCoin(6600 + i * 120, groundY - 500);
}
}
// Combined hazard section
for (var i = 0; i < 5; i++) {
createPlatform(7600 + i * 250, groundY - 400, 200, 30, true);
createEnemy(7600 + i * 250 - 80, groundY - 450, 50);
createSpike(7600 + i * 250 + 80, groundY - 450);
createCoin(7600 + i * 250, groundY - 550);
}
// Place goal at the end
createGoal(8900, groundY - 400);
break;
case 10:
// Level 10: Grand finale with all challenges combined
levelWidth = 10000;
// Starting area
createPlatform(400, groundY - 200, 300, 30, false);
createCoin(400, groundY - 300);
createCoin(500, groundY - 300);
createCoin(600, groundY - 300);
// Section 1: Precision platforming
for (var i = 0; i < 8; i++) {
createPlatform(900 + i * 200, groundY - 200 - Math.sin(i * 0.8) * 300, 150, 30, i % 2 === 0);
createCoin(900 + i * 200, groundY - 300 - Math.sin(i * 0.8) * 300);
}
// Section 2: Enemy gauntlet
createPlatform(2600, groundY - 300, 800, 30, false);
for (var i = 0; i < 10; i++) {
createEnemy(2700 + i * 80, groundY - 350, 50);
if (i % 2 === 0) {
createCoin(2700 + i * 80, groundY - 450);
}
}
// Section 3: Spike maze
createPlatform(3600, groundY - 400, 1000, 30, false);
for (var i = 0; i < 20; i++) {
if (i % 3 !== 1) {
// Every third position is safe
createSpike(3650 + i * 50, groundY - 450);
} else {
createCoin(3650 + i * 50, groundY - 550);
}
}
// Section 4: Vertical climbing challenge
for (var i = 0; i < 8; i++) {
createPlatform(4800, groundY - 300 - i * 150, 200, 30, i % 2 === 1);
createCoin(4800, groundY - 400 - i * 150);
}
// Section 5: Moving platform timing challenge
for (var i = 0; i < 6; i++) {
var platform = createPlatform(5300 + i * 300, groundY - 1200, 150, 30, true);
platform.moveDistance = 400 + i * 50; // Increasing move distances
createCoin(5300 + i * 300, groundY - 1300);
}
// Section 6: Combined hazards
for (var i = 0; i < 10; i++) {
createPlatform(7000 + i * 200, groundY - 600, 150, 30, i % 3 === 0);
if (i % 3 === 0) {
createEnemy(7000 + i * 200, groundY - 650, 70);
} else if (i % 3 === 1) {
createSpike(7000 + i * 200, groundY - 650);
} else {
createCoin(7000 + i * 200, groundY - 700);
}
}
// Final challenge - all hazards combined with moving platforms
for (var i = 0; i < 5; i++) {
var platform = createPlatform(9000 + i * 150, groundY - 500 + Math.sin(i * 0.6) * 150, 120, 30, true);
platform.moveSpeed = 4; // Fast movement
createEnemy(9000 + i * 150 - 50, groundY - 550 + Math.sin(i * 0.6) * 150, 40);
createSpike(9000 + i * 150 + 50, groundY - 550 + Math.sin(i * 0.6) * 150);
createCoin(9000 + i * 150, groundY - 650 + Math.sin(i * 0.6) * 150);
}
// Place goal at the end - grand finish
createGoal(9800, groundY - 500);
// Add a victory coin path to goal
for (var i = 0; i < 10; i++) {
createCoin(9700 + i * 10, groundY - 600 - i * 10);
}
break;
default:
// Levels beyond 10 - procedurally generated with increasing difficulty
var platformCount = level * 5;
var enemyCount = level * 2;
var coinCount = level * 5;
// Create platforms with varying heights and spacing
for (var i = 0; i < platformCount; i++) {
var x = 500 + i * 500;
var y = groundY - (Math.random() * 500 + 100);
var isMoving = Math.random() > 0.5;
createPlatform(x, y, 200, 30, isMoving);
// Add a coin above each platform
createCoin(x, y - 100);
}
// Add enemies
for (var i = 0; i < enemyCount; i++) {
var x = 800 + i * 800;
var patrolDistance = 200 + Math.random() * 300;
createEnemy(x, groundY - 50, patrolDistance);
}
// Place goal at the end
createGoal(500 + platformCount * 500 + 200, groundY - 100);
break;
}
// Reset player position
player.x = 200;
player.y = groundY - 200;
player.vx = 0;
player.vy = 0;
player.isDead = false;
// Reset camera
cameraPosX = 0;
worldContainer.x = 0;
}
// Helper functions for creating level elements
function createPlatform(x, y, width, height, isMoving) {
var platform = new Platform(width, height, isMoving);
platform.setStartPosition(x, y);
worldContainer.addChild(platform);
platforms.push(platform);
return platform;
}
// Helper function to create spikes
function createSpike(x, y) {
var spike = new Spike();
spike.x = x;
spike.y = y;
worldContainer.addChild(spike);
enemies.push(spike); // Add to enemies array for collision detection
return spike;
}
function createCoin(x, y) {
var coin = new Coin();
coin.x = x;
coin.y = y;
worldContainer.addChild(coin);
coins.push(coin);
return coin;
}
function createEnemy(x, y, patrolDistance) {
var enemy = new Enemy(patrolDistance);
enemy.setStartPosition(x, y);
worldContainer.addChild(enemy);
enemies.push(enemy);
return enemy;
}
function createGoal(x, y) {
goal = new Goal();
goal.x = x;
goal.y = y;
worldContainer.addChild(goal);
return goal;
}
// Check collisions between player and platforms
function checkPlatformCollisions() {
player.canJump = false;
// Pre-calculate player dimensions once
var playerWidth = player.children[0].width;
var playerHeight = player.children[0].height;
var playerLeft = player.x - playerWidth / 2;
var playerRight = player.x + playerWidth / 2;
var playerTop = player.y - playerHeight / 2;
var playerBottom = player.y + playerHeight / 2;
// Only check platforms that are visible in the camera view (+ some margin)
var cameraLeftX = cameraPosX - 200;
var cameraRightX = cameraPosX + 2048 + 200;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
// Quick check if platform is in camera view
if (platform.x + 200 < cameraLeftX || platform.x - 200 > cameraRightX) {
continue; // Skip platforms outside camera view
}
// Get platform dimensions (adjust based on asset size)
var platformWidth = platform.children[0].width;
var platformHeight = platform.children[0].height;
var platformLeft = platform.x - platformWidth / 2;
var platformRight = platform.x + platformWidth / 2;
var platformTop = platform.y - platformHeight / 2;
var platformBottom = platform.y + platformHeight / 2;
// Check for collision
if (playerRight > platformLeft && playerLeft < platformRight && playerBottom > platformTop && playerTop < platformBottom) {
// Calculate overlap on each side
var overlapLeft = playerRight - platformLeft;
var overlapRight = platformRight - playerLeft;
var overlapTop = playerBottom - platformTop;
var overlapBottom = platformBottom - playerTop;
// Find the smallest overlap
var minOverlap = Math.min(overlapLeft, overlapRight, overlapTop, overlapBottom);
// Resolve collision based on the smallest overlap
if (minOverlap === overlapTop && player.vy >= 0) {
// Landing on top of platform
// Use a much larger fixed offset for legs to prevent glitching through platform
var legOffset = 50; // Significantly increased offset value to ensure proper positioning
player.y = platformTop - playerHeight / 2 - legOffset;
player.vy = 0;
player.canJump = true;
// Apply slight downward force to keep player grounded
player.lastGroundedY = player.y;
// If platform is moving, adjust player x position based on actual platform movement
if (platform.isMoving && platform.lastX !== undefined) {
// Move player by the same amount the platform moved
var platformDeltaX = platform.x - platform.lastX;
// Always move player with platform when standing on it, even if not pressing movement keys
player.x += platformDeltaX;
}
} else if (minOverlap === overlapBottom && player.vy <= 0) {
// Hitting bottom of platform
player.y = platformBottom + playerHeight / 2;
player.vy = 0;
} else if (minOverlap === overlapLeft && player.vx > 0) {
// Hitting left side of platform
player.x = platformLeft - playerWidth / 2;
player.vx = 0;
} else if (minOverlap === overlapRight && player.vx < 0) {
// Hitting right side of platform
player.x = platformRight + playerWidth / 2;
player.vx = 0;
}
}
}
}
// Check collisions with coins
function checkCoinCollisions() {
// Only check coins that are visible in the camera view (+ some margin)
var cameraLeftX = cameraPosX - 100;
var cameraRightX = cameraPosX + 2048 + 100;
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
// Skip coins outside camera view
if (coin.x < cameraLeftX || coin.x > cameraRightX) {
continue;
}
if (player.intersects(coin)) {
// Collect coin
score += 10;
// No storage saving
scoreTxt.setText('Score: ' + score);
// No tracking coins in storage
coin.collect();
coins.splice(i, 1);
}
}
}
// Check collisions with enemies
function checkEnemyCollisions() {
// Only check enemies that are visible in the camera view (+ some margin)
var cameraLeftX = cameraPosX - 100;
var cameraRightX = cameraPosX + 2048 + 100;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip enemies outside camera view
if (enemy.x < cameraLeftX || enemy.x > cameraRightX) {
continue;
}
if (player.intersects(enemy) && !player.isDead) {
// Check if player is landing on enemy (from above)
var playerBottom = player.y + player.children[0].height / 2;
var enemyTop = enemy.y - enemy.children[0].height / 2;
if (player.vy > 0 && playerBottom - enemyTop < 20) {
// Bounce off enemy
player.vy = player.jumpForce * 0.7;
// Remove enemy
enemy.destroy();
enemies.splice(i, 1);
// Add points
score += 50;
// No storage saving
scoreTxt.setText('Score: ' + score);
} else {
// Player dies
player.die();
}
break;
}
}
}
// Check if player reached the goal
function checkGoalCollision() {
if (goal && player.intersects(goal)) {
goal.reach();
}
}
// Update camera to follow player
function updateCamera() {
// Only follow horizontally
var targetX = Math.max(0, Math.min(levelWidth - 2048, player.x - 2048 / 2));
cameraPosX += (targetX - cameraPosX) * 0.1; // Smooth camera movement
worldContainer.x = -cameraPosX;
}
// Check if player fell off the level
function checkFallOffLevel() {
if (player.y > 2732 + 200 && !player.isDead) {
player.die();
}
}
// Set current level without storage
level = 1; // Default to level 1 without storage
levelTxt.setText('Level: ' + level);
// Reset score without storage
score = 0;
scoreTxt.setText('Score: ' + score);
// Settings button removed as requested
// Initialize the level
createLevel(level);
// Play background music
LK.playMusic('gameMusic');
// Main game loop
game.update = function () {
// Process player controls - only move when buttons are explicitly pressed
if (jumpButton.isPressed) {
player.jump();
}
if (leftButton.isPressed) {
player.moveLeft();
} else if (rightButton.isPressed) {
player.moveRight();
} else {
player.stop();
}
// Update player
player.update();
// Update camera first to determine what's visible
updateCamera();
// Only update objects that are visible in the camera view (+ some margin)
var cameraLeftX = cameraPosX - 200;
var cameraRightX = cameraPosX + 2048 + 200;
// Update platforms
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
// Only update platforms near the camera view
if (platform.x + 200 >= cameraLeftX && platform.x - 200 <= cameraRightX) {
platform.update();
}
}
// Update coins
for (var i = 0; i < coins.length; i++) {
var coin = coins[i];
// Only update coins near the camera view
if (coin.x >= cameraLeftX && coin.x <= cameraRightX) {
coin.update();
}
}
// Update enemies
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Only update enemies near the camera view
if (enemy.x + 200 >= cameraLeftX && enemy.x - 200 <= cameraRightX) {
enemy.update();
}
}
// Check collisions
checkPlatformCollisions();
checkCoinCollisions();
checkEnemyCollisions();
checkGoalCollision();
checkFallOffLevel();
};
// Game-wide touch events
game.down = function (x, y, obj) {
// Only process direct button presses
// No automatic button activation when touching the game area
// Store the touch ID only if touching a control button
if (obj.target && (obj.target === jumpButton || obj.target === leftButton || obj.target === rightButton)) {
game.activeTouchId = obj.event ? obj.event.pointerId : null;
}
};
game.move = function (x, y, obj) {
// No additional move handling needed at game level
};
// Settings functionality removed as requested
game.up = function (x, y, obj) {
// Only process the button that was actually released
// Don't reset all buttons on any touch release
if (obj.target === leftButton) {
leftButton.up(x, y, obj);
} else if (obj.target === rightButton) {
rightButton.up(x, y, obj);
} else if (obj.target === jumpButton) {
jumpButton.up(x, y, obj);
}
// Reset the touch ID only if this is the touch we're tracking
if (game.activeTouchId === (obj.event ? obj.event.pointerId : null)) {
game.activeTouchId = null;
}
}; ===================================================================
--- original.js
+++ change.js
@@ -5,8 +5,9 @@
/****
* Classes
****/
+// Import auth plugin for isOwner() function
//Storage functionality removed as requested
var Coin = Container.expand(function () {
var self = Container.call(this);
// Coin sprite