/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var ArrowButton = Container.expand(function (type, x, y) {
var self = Container.call(this);
var buttonGraphics;
if (type === 'left') {
buttonGraphics = self.attachAsset('leftArrow', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'right') {
buttonGraphics = self.attachAsset('rightArrow', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'jump') {
buttonGraphics = self.attachAsset('jumpButton', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.x = x || 0;
self.y = y || 0;
self.buttonType = type;
self.isPressed = false;
self.alpha = 0.7;
self.down = function (x, y, obj) {
if (gameState !== 'playing' || !player) return;
self.isPressed = true;
self.alpha = 1.0;
buttonGraphics.scaleX = 0.9;
buttonGraphics.scaleY = 0.9;
if (self.buttonType === 'left') {
player.moveLeft();
if (!player.isOnGround) {
player.velocityX -= player.speed * 0.3;
}
} else if (self.buttonType === 'right') {
player.moveRight();
if (!player.isOnGround) {
player.velocityX += player.speed * 0.3;
}
} else if (self.buttonType === 'jump') {
player.jump();
}
};
self.up = function (x, y, obj) {
self.isPressed = false;
self.alpha = 0.7;
buttonGraphics.scaleX = 1.0;
buttonGraphics.scaleY = 1.0;
};
return self;
});
var Goal = Container.expand(function (x, y) {
var self = Container.call(this);
var goalGraphics = self.attachAsset('goal', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x || 0;
self.y = y || 0;
// Pulsing animation for goal
self.update = function () {
var scale = 1 + Math.sin(LK.ticks * 0.1) * 0.1;
goalGraphics.scaleX = scale;
goalGraphics.scaleY = scale;
};
return self;
});
var Obstacle = Container.expand(function (x, y) {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x || 0;
self.y = y || 0;
return self;
});
var Platform = Container.expand(function (width, height, x, y) {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
width: width || 200,
height: height || 40
});
self.x = x || 0;
self.y = y || 0;
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.isJumping = false;
self.isOnGround = false;
self.speed = 8;
self.jumpPower = 20;
self.gravity = 0.8;
self.update = function () {
// Apply gravity
if (!self.isOnGround) {
self.velocityY += self.gravity;
}
// Update position
self.x += self.velocityX;
self.y += self.velocityY;
// Apply friction
self.velocityX *= 0.9;
// Check ground collision - eliminate player when touching ground
if (ground && self.intersects(ground)) {
resetPlayerPosition();
return;
}
// Player is never on ground now - always in air
self.isOnGround = false;
// Check wall collision
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
if (self.intersects(wall)) {
// Simple wall collision - push player back
if (self.x < wall.x) {
self.x = wall.x - wall.width / 2 - self.width / 2;
} else {
self.x = wall.x + wall.width / 2 + self.width / 2;
}
self.velocityX = 0;
}
}
// No obstacle collision needed
// Check goal collision
if (self.intersects(goal)) {
completeLevel();
}
// Check if player fell off screen
if (self.y > 2732 + 200) {
resetPlayerPosition();
}
};
self.jump = function () {
// Allow jumping anytime (air control)
self.velocityY = -self.jumpPower;
self.isJumping = true;
self.isOnGround = false;
LK.getSound('jump').play();
};
self.moveLeft = function () {
self.velocityX -= self.speed;
};
self.moveRight = function () {
self.velocityX += self.speed;
};
return self;
});
var Wall = Container.expand(function (width, height, x, y) {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
width: width || 40,
height: height || 200
});
self.x = x || 0;
self.y = y || 0;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game state variables
var gameState = 'menu'; // 'menu', 'playing', 'completed'
var startTime = 0;
var currentTime = 0;
var bestTime = storage.bestTime || null;
var playerName = storage.playerName || '';
// Game objects
var platforms = [];
var walls = [];
var obstacles = [];
var player = null;
var goal = null;
var ground = null;
// UI elements
var timeText = new Text2('Time: 0.00s', {
size: 60,
fill: 0xFFFFFF
});
timeText.anchor.set(0.5, 0);
LK.gui.top.addChild(timeText);
timeText.y = 50;
var bestTimeText = new Text2('Best: --', {
size: 40,
fill: 0xFFD700
});
bestTimeText.anchor.set(0.5, 0);
LK.gui.top.addChild(bestTimeText);
bestTimeText.y = 120;
var instructionText = new Text2('USE ON-SCREEN BUTTONS OR TAP AREAS TO MOVE AND JUMP', {
size: 45,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(instructionText);
instructionText.y = -50;
var titleText = new Text2('PARKOUR RUSH 3D', {
size: 80,
fill: 0xFF6600
});
titleText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(titleText);
titleText.y = -200;
var startText = new Text2('TAP TO START', {
size: 55,
fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(startText);
// On-screen control buttons
var leftArrowButton = null;
var rightArrowButton = null;
var jumpButton = null;
// Initialize level
function initializeLevel() {
// Clear existing objects
platforms = [];
walls = [];
obstacles = [];
// Create ground floor that eliminates player on contact
ground = game.addChild(new Platform(2048, 100, 1024, 2632));
// No other platforms - only ground floor
// Remove obstacles - no obstacles needed
// Create goal
goal = game.addChild(new Goal(600, 700));
// Create player
player = game.addChild(new Player());
resetPlayerPosition();
// Create on-screen control buttons
leftArrowButton = game.addChild(new ArrowButton('left', 200, 2500));
rightArrowButton = game.addChild(new ArrowButton('right', 400, 2500));
jumpButton = game.addChild(new ArrowButton('jump', 1600, 2500));
// Add text labels to buttons
var leftLabel = new Text2('◄', {
size: 60,
fill: 0xFFFFFF
});
leftLabel.anchor.set(0.5, 0.5);
leftLabel.x = 200;
leftLabel.y = 2500;
game.addChild(leftLabel);
var rightLabel = new Text2('►', {
size: 60,
fill: 0xFFFFFF
});
rightLabel.anchor.set(0.5, 0.5);
rightLabel.x = 400;
rightLabel.y = 2500;
game.addChild(rightLabel);
var jumpLabel = new Text2('↑', {
size: 70,
fill: 0xFFFFFF
});
jumpLabel.anchor.set(0.5, 0.5);
jumpLabel.x = 1600;
jumpLabel.y = 2500;
game.addChild(jumpLabel);
}
function resetPlayerPosition() {
if (player) {
player.x = 400;
player.y = 2300;
player.velocityX = 0;
player.velocityY = 0;
player.isJumping = false;
player.isOnGround = false;
LK.getSound('fall').play();
}
}
function startGame() {
gameState = 'playing';
startTime = Date.now();
titleText.visible = false;
startText.visible = false;
if (bestTime) {
bestTimeText.setText('Best: ' + (bestTime / 1000).toFixed(2) + 's');
}
}
function completeLevel() {
if (gameState !== 'playing') return;
gameState = 'completed';
var completionTime = Date.now() - startTime;
LK.getSound('complete').play();
// Update best time
if (!bestTime || completionTime < bestTime) {
bestTime = completionTime;
storage.bestTime = bestTime;
bestTimeText.setText('NEW BEST: ' + (bestTime / 1000).toFixed(2) + 's');
bestTimeText.tint = 0x00FF00;
// Flash effect for new record
tween(bestTimeText, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(bestTimeText, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeIn
});
}
});
} else {
bestTimeText.setText('Best: ' + (bestTime / 1000).toFixed(2) + 's');
}
// Show completion message
var completionText = new Text2('LEVEL COMPLETE!\nTime: ' + (completionTime / 1000).toFixed(2) + 's\nTAP TO RESTART', {
size: 60,
fill: 0x00FF00
});
completionText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(completionText);
// Set score for leaderboard
LK.setScore(Math.max(0, 10000 - completionTime));
// Auto restart after 3 seconds
LK.setTimeout(function () {
completionText.destroy();
gameState = 'menu';
titleText.visible = true;
startText.visible = true;
bestTimeText.tint = 0xFFD700;
resetPlayerPosition();
}, 3000);
}
// Initialize the level
initializeLevel();
// Touch controls
var touchStartX = 0;
var touchStartY = 0;
game.down = function (x, y, obj) {
touchStartX = x;
touchStartY = y;
if (gameState === 'menu') {
startGame();
} else if (gameState === 'completed') {
// Reset handled by auto restart
}
};
game.up = function (x, y, obj) {
if (gameState !== 'playing' || !player) return;
var deltaX = x - touchStartX;
var deltaY = y - touchStartY;
// Determine control type based on touch position and movement
if (Math.abs(deltaX) > Math.abs(deltaY) + 30) {
// Horizontal swipe - movement
if (deltaX < -50) {
player.moveLeft();
// Allow aerial movement with reduced control
if (!player.isOnGround) {
player.velocityX -= player.speed * 0.3;
}
} else if (deltaX > 50) {
player.moveRight();
// Allow aerial movement with reduced control
if (!player.isOnGround) {
player.velocityX += player.speed * 0.3;
}
}
} else if (x > 512 && x < 1536) {
// Center tap - jump (OK button functionality)
player.jump();
} else if (x <= 512) {
// Left side tap - move left
player.moveLeft();
// Allow aerial movement with reduced control
if (!player.isOnGround) {
player.velocityX -= player.speed * 0.3;
}
} else if (x >= 1536) {
// Right side tap - move right
player.moveRight();
// Allow aerial movement with reduced control
if (!player.isOnGround) {
player.velocityX += player.speed * 0.3;
}
}
};
// Keyboard state tracking - using touch-based simulation
var keys = {
space: false,
enter: false,
left: false,
right: false,
a: false,
d: false
};
// Game update loop
game.update = function () {
// Update current time display
if (gameState === 'playing') {
currentTime = Date.now() - startTime;
timeText.setText('Time: ' + (currentTime / 1000).toFixed(2) + 's');
}
// Camera follow player (simple version for 2D representation of 3D perspective)
if (player && gameState === 'playing') {
// Adjust camera position based on player position
var cameraY = Math.max(0, Math.min(1000, player.y - 1366));
game.y = -cameraY;
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var ArrowButton = Container.expand(function (type, x, y) {
var self = Container.call(this);
var buttonGraphics;
if (type === 'left') {
buttonGraphics = self.attachAsset('leftArrow', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'right') {
buttonGraphics = self.attachAsset('rightArrow', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'jump') {
buttonGraphics = self.attachAsset('jumpButton', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.x = x || 0;
self.y = y || 0;
self.buttonType = type;
self.isPressed = false;
self.alpha = 0.7;
self.down = function (x, y, obj) {
if (gameState !== 'playing' || !player) return;
self.isPressed = true;
self.alpha = 1.0;
buttonGraphics.scaleX = 0.9;
buttonGraphics.scaleY = 0.9;
if (self.buttonType === 'left') {
player.moveLeft();
if (!player.isOnGround) {
player.velocityX -= player.speed * 0.3;
}
} else if (self.buttonType === 'right') {
player.moveRight();
if (!player.isOnGround) {
player.velocityX += player.speed * 0.3;
}
} else if (self.buttonType === 'jump') {
player.jump();
}
};
self.up = function (x, y, obj) {
self.isPressed = false;
self.alpha = 0.7;
buttonGraphics.scaleX = 1.0;
buttonGraphics.scaleY = 1.0;
};
return self;
});
var Goal = Container.expand(function (x, y) {
var self = Container.call(this);
var goalGraphics = self.attachAsset('goal', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x || 0;
self.y = y || 0;
// Pulsing animation for goal
self.update = function () {
var scale = 1 + Math.sin(LK.ticks * 0.1) * 0.1;
goalGraphics.scaleX = scale;
goalGraphics.scaleY = scale;
};
return self;
});
var Obstacle = Container.expand(function (x, y) {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x || 0;
self.y = y || 0;
return self;
});
var Platform = Container.expand(function (width, height, x, y) {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
width: width || 200,
height: height || 40
});
self.x = x || 0;
self.y = y || 0;
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.isJumping = false;
self.isOnGround = false;
self.speed = 8;
self.jumpPower = 20;
self.gravity = 0.8;
self.update = function () {
// Apply gravity
if (!self.isOnGround) {
self.velocityY += self.gravity;
}
// Update position
self.x += self.velocityX;
self.y += self.velocityY;
// Apply friction
self.velocityX *= 0.9;
// Check ground collision - eliminate player when touching ground
if (ground && self.intersects(ground)) {
resetPlayerPosition();
return;
}
// Player is never on ground now - always in air
self.isOnGround = false;
// Check wall collision
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
if (self.intersects(wall)) {
// Simple wall collision - push player back
if (self.x < wall.x) {
self.x = wall.x - wall.width / 2 - self.width / 2;
} else {
self.x = wall.x + wall.width / 2 + self.width / 2;
}
self.velocityX = 0;
}
}
// No obstacle collision needed
// Check goal collision
if (self.intersects(goal)) {
completeLevel();
}
// Check if player fell off screen
if (self.y > 2732 + 200) {
resetPlayerPosition();
}
};
self.jump = function () {
// Allow jumping anytime (air control)
self.velocityY = -self.jumpPower;
self.isJumping = true;
self.isOnGround = false;
LK.getSound('jump').play();
};
self.moveLeft = function () {
self.velocityX -= self.speed;
};
self.moveRight = function () {
self.velocityX += self.speed;
};
return self;
});
var Wall = Container.expand(function (width, height, x, y) {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
width: width || 40,
height: height || 200
});
self.x = x || 0;
self.y = y || 0;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game state variables
var gameState = 'menu'; // 'menu', 'playing', 'completed'
var startTime = 0;
var currentTime = 0;
var bestTime = storage.bestTime || null;
var playerName = storage.playerName || '';
// Game objects
var platforms = [];
var walls = [];
var obstacles = [];
var player = null;
var goal = null;
var ground = null;
// UI elements
var timeText = new Text2('Time: 0.00s', {
size: 60,
fill: 0xFFFFFF
});
timeText.anchor.set(0.5, 0);
LK.gui.top.addChild(timeText);
timeText.y = 50;
var bestTimeText = new Text2('Best: --', {
size: 40,
fill: 0xFFD700
});
bestTimeText.anchor.set(0.5, 0);
LK.gui.top.addChild(bestTimeText);
bestTimeText.y = 120;
var instructionText = new Text2('USE ON-SCREEN BUTTONS OR TAP AREAS TO MOVE AND JUMP', {
size: 45,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(instructionText);
instructionText.y = -50;
var titleText = new Text2('PARKOUR RUSH 3D', {
size: 80,
fill: 0xFF6600
});
titleText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(titleText);
titleText.y = -200;
var startText = new Text2('TAP TO START', {
size: 55,
fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(startText);
// On-screen control buttons
var leftArrowButton = null;
var rightArrowButton = null;
var jumpButton = null;
// Initialize level
function initializeLevel() {
// Clear existing objects
platforms = [];
walls = [];
obstacles = [];
// Create ground floor that eliminates player on contact
ground = game.addChild(new Platform(2048, 100, 1024, 2632));
// No other platforms - only ground floor
// Remove obstacles - no obstacles needed
// Create goal
goal = game.addChild(new Goal(600, 700));
// Create player
player = game.addChild(new Player());
resetPlayerPosition();
// Create on-screen control buttons
leftArrowButton = game.addChild(new ArrowButton('left', 200, 2500));
rightArrowButton = game.addChild(new ArrowButton('right', 400, 2500));
jumpButton = game.addChild(new ArrowButton('jump', 1600, 2500));
// Add text labels to buttons
var leftLabel = new Text2('◄', {
size: 60,
fill: 0xFFFFFF
});
leftLabel.anchor.set(0.5, 0.5);
leftLabel.x = 200;
leftLabel.y = 2500;
game.addChild(leftLabel);
var rightLabel = new Text2('►', {
size: 60,
fill: 0xFFFFFF
});
rightLabel.anchor.set(0.5, 0.5);
rightLabel.x = 400;
rightLabel.y = 2500;
game.addChild(rightLabel);
var jumpLabel = new Text2('↑', {
size: 70,
fill: 0xFFFFFF
});
jumpLabel.anchor.set(0.5, 0.5);
jumpLabel.x = 1600;
jumpLabel.y = 2500;
game.addChild(jumpLabel);
}
function resetPlayerPosition() {
if (player) {
player.x = 400;
player.y = 2300;
player.velocityX = 0;
player.velocityY = 0;
player.isJumping = false;
player.isOnGround = false;
LK.getSound('fall').play();
}
}
function startGame() {
gameState = 'playing';
startTime = Date.now();
titleText.visible = false;
startText.visible = false;
if (bestTime) {
bestTimeText.setText('Best: ' + (bestTime / 1000).toFixed(2) + 's');
}
}
function completeLevel() {
if (gameState !== 'playing') return;
gameState = 'completed';
var completionTime = Date.now() - startTime;
LK.getSound('complete').play();
// Update best time
if (!bestTime || completionTime < bestTime) {
bestTime = completionTime;
storage.bestTime = bestTime;
bestTimeText.setText('NEW BEST: ' + (bestTime / 1000).toFixed(2) + 's');
bestTimeText.tint = 0x00FF00;
// Flash effect for new record
tween(bestTimeText, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(bestTimeText, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeIn
});
}
});
} else {
bestTimeText.setText('Best: ' + (bestTime / 1000).toFixed(2) + 's');
}
// Show completion message
var completionText = new Text2('LEVEL COMPLETE!\nTime: ' + (completionTime / 1000).toFixed(2) + 's\nTAP TO RESTART', {
size: 60,
fill: 0x00FF00
});
completionText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(completionText);
// Set score for leaderboard
LK.setScore(Math.max(0, 10000 - completionTime));
// Auto restart after 3 seconds
LK.setTimeout(function () {
completionText.destroy();
gameState = 'menu';
titleText.visible = true;
startText.visible = true;
bestTimeText.tint = 0xFFD700;
resetPlayerPosition();
}, 3000);
}
// Initialize the level
initializeLevel();
// Touch controls
var touchStartX = 0;
var touchStartY = 0;
game.down = function (x, y, obj) {
touchStartX = x;
touchStartY = y;
if (gameState === 'menu') {
startGame();
} else if (gameState === 'completed') {
// Reset handled by auto restart
}
};
game.up = function (x, y, obj) {
if (gameState !== 'playing' || !player) return;
var deltaX = x - touchStartX;
var deltaY = y - touchStartY;
// Determine control type based on touch position and movement
if (Math.abs(deltaX) > Math.abs(deltaY) + 30) {
// Horizontal swipe - movement
if (deltaX < -50) {
player.moveLeft();
// Allow aerial movement with reduced control
if (!player.isOnGround) {
player.velocityX -= player.speed * 0.3;
}
} else if (deltaX > 50) {
player.moveRight();
// Allow aerial movement with reduced control
if (!player.isOnGround) {
player.velocityX += player.speed * 0.3;
}
}
} else if (x > 512 && x < 1536) {
// Center tap - jump (OK button functionality)
player.jump();
} else if (x <= 512) {
// Left side tap - move left
player.moveLeft();
// Allow aerial movement with reduced control
if (!player.isOnGround) {
player.velocityX -= player.speed * 0.3;
}
} else if (x >= 1536) {
// Right side tap - move right
player.moveRight();
// Allow aerial movement with reduced control
if (!player.isOnGround) {
player.velocityX += player.speed * 0.3;
}
}
};
// Keyboard state tracking - using touch-based simulation
var keys = {
space: false,
enter: false,
left: false,
right: false,
a: false,
d: false
};
// Game update loop
game.update = function () {
// Update current time display
if (gameState === 'playing') {
currentTime = Date.now() - startTime;
timeText.setText('Time: ' + (currentTime / 1000).toFixed(2) + 's');
}
// Camera follow player (simple version for 2D representation of 3D perspective)
if (player && gameState === 'playing') {
// Adjust camera position based on player position
var cameraY = Math.max(0, Math.min(1000, player.y - 1366));
game.y = -cameraY;
}
};