/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
coins: 0
});
/****
* Classes
****/
var Coin = Container.expand(function () {
var self = Container.call(this);
self.lane = Math.floor(Math.random() * 3);
self.speed = 0;
self.collected = false;
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
self.y += self.speed;
// Spinning animation
coinGraphics.scaleX = Math.abs(Math.sin(LK.ticks * 0.05)) * 0.5 + 0.5;
};
self.collect = function () {
if (self.collected) {
return;
}
self.collected = true;
LK.getSound('collect').play();
// Animate collection
tween(self, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeOut
});
};
self.getCollisionBox = function () {
var box = {
x: self.x - coinGraphics.width * 0.5 * 0.8,
y: self.y - coinGraphics.height * 0.5 * 0.8,
width: coinGraphics.width * 0.8,
height: coinGraphics.height * 0.8
};
return box;
};
return self;
});
var Obstacle = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'regular'; // regular, low, high
self.lane = Math.floor(Math.random() * 3);
self.speed = 0;
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
// Adjust obstacle appearance based on type
if (self.type === 'low') {
obstacleGraphics.scaleY = 0.5;
obstacleGraphics.y = obstacleGraphics.height * 0.25;
} else if (self.type === 'high') {
obstacleGraphics.scaleY = 0.5;
obstacleGraphics.y = -obstacleGraphics.height * 0.25;
}
self.update = function () {
self.y += self.speed;
};
self.getCollisionBox = function () {
var box = {
x: self.x - obstacleGraphics.width * 0.5 * 0.9,
y: self.y - obstacleGraphics.height * 0.5 * 0.9 + (self.type === 'low' ? obstacleGraphics.height * 0.25 : self.type === 'high' ? -obstacleGraphics.height * 0.25 : 0),
width: obstacleGraphics.width * 0.9,
height: obstacleGraphics.height * 0.9 * (self.type === 'low' || self.type === 'high' ? 0.5 : 1)
};
return box;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
// Player states
self.isJumping = false;
self.isSliding = false;
self.lane = 1; // 0: left, 1: center, 2: right
self.speed = 10;
self.jumpHeight = 200;
self.jumpDuration = 500;
self.slideDuration = 600;
self.powerupActive = false;
self.powerupType = null;
self.powerupDuration = 0;
// Player graphics
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// Methods for player actions
self.switchLane = function (targetLane) {
if (targetLane < 0 || targetLane > 2 || self.lane === targetLane) {
return;
}
var targetX = LANE_POSITIONS[targetLane];
tween.stop(self, {
x: true
});
tween(self, {
x: targetX
}, {
duration: 200,
easing: tween.easeOut
});
self.lane = targetLane;
};
self.jump = function () {
if (self.isJumping || self.isSliding) {
return;
}
self.isJumping = true;
LK.getSound('jump').play();
var initialY = self.y;
// Jump up
tween(self, {
y: initialY - self.jumpHeight
}, {
duration: self.jumpDuration / 2,
easing: tween.easeOut,
onFinish: function onFinish() {
// Fall down
tween(self, {
y: initialY
}, {
duration: self.jumpDuration / 2,
easing: tween.easeIn,
onFinish: function onFinish() {
self.isJumping = false;
}
});
}
});
};
self.slide = function () {
if (self.isJumping || self.isSliding) {
return;
}
self.isSliding = true;
LK.getSound('slide').play();
// Shrink player height for sliding
tween(playerGraphics, {
scaleY: 0.5
}, {
duration: 200,
easing: tween.linear
});
// Return to normal after slide duration
LK.setTimeout(function () {
tween(playerGraphics, {
scaleY: 1
}, {
duration: 200,
easing: tween.linear,
onFinish: function onFinish() {
self.isSliding = false;
}
});
}, self.slideDuration);
};
self.activatePowerup = function (type) {
self.powerupActive = true;
self.powerupType = type;
switch (type) {
case 'magnet':
self.powerupDuration = 5000;
break;
case 'multiplier':
self.powerupDuration = 8000;
break;
case 'invincibility':
self.powerupDuration = 4000;
playerGraphics.alpha = 0.7;
break;
}
LK.getSound('powerup').play();
};
self.updatePowerup = function () {
if (!self.powerupActive) {
return;
}
self.powerupDuration -= 16.67; // Approximate ms per frame at 60fps
if (self.powerupDuration <= 0) {
self.powerupActive = false;
self.powerupType = null;
playerGraphics.alpha = 1;
}
};
// Collision detection utility
self.getCollisionBox = function () {
var box = {
x: self.x - playerGraphics.width * 0.5 * 0.8,
y: self.y - playerGraphics.height * 0.5 * (self.isSliding ? 0.5 : 0.9),
width: playerGraphics.width * 0.8,
height: playerGraphics.height * (self.isSliding ? 0.5 : 0.9)
};
return box;
};
return self;
});
var Powerup = Container.expand(function () {
var self = Container.call(this);
self.lane = Math.floor(Math.random() * 3);
self.speed = 0;
self.collected = false;
// Random powerup type
var types = ['magnet', 'multiplier', 'invincibility'];
self.type = types[Math.floor(Math.random() * types.length)];
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
// Different colors for different powerups
if (self.type === 'magnet') {
powerupGraphics.tint = 0x0088ff;
} else if (self.type === 'multiplier') {
powerupGraphics.tint = 0xff8800;
} else if (self.type === 'invincibility') {
powerupGraphics.tint = 0xff00ff;
}
self.update = function () {
self.y += self.speed;
// Pulsing animation
var pulse = Math.sin(LK.ticks * 0.1) * 0.1 + 1;
powerupGraphics.scale.set(pulse, pulse);
};
self.collect = function () {
if (self.collected) {
return;
}
self.collected = true;
LK.getSound('powerup').play();
// Animate collection
tween(self, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
easing: tween.easeOut
});
};
self.getCollisionBox = function () {
var box = {
x: self.x - powerupGraphics.width * 0.5 * 0.8,
y: self.y - powerupGraphics.height * 0.5 * 0.8,
width: powerupGraphics.width * 0.8,
height: powerupGraphics.height * 0.8
};
return box;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x202020
});
/****
* Game Code
****/
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var PLAYER_START_Y = GAME_HEIGHT - 400;
var LANE_WIDTH = 200;
var LANE_POSITIONS = [GAME_WIDTH / 2 - LANE_WIDTH, GAME_WIDTH / 2, GAME_WIDTH / 2 + LANE_WIDTH];
var SPAWN_Y = -200;
var DESPAWN_Y = GAME_HEIGHT + 200;
// Game variables
var gameStarted = false;
var gameSpeed = 10;
var score = 0;
var distance = 0;
var coins = 0;
var multiplier = 1;
var lastObstacleSpawn = 0;
var lastCoinSpawn = 0;
var lastPowerupSpawn = 0;
var obstacleSpawnRate = 1500; // ms
var coinSpawnRate = 1000; // ms
var powerupSpawnRate = 10000; // ms
var playerSwipeStartY = 0;
var playerSwipeStartX = 0;
var MIN_SWIPE_DISTANCE = 50;
// Game elements
var player;
var obstacles = [];
var coinsArray = [];
var powerups = [];
var swipeDirection = null;
// Create lanes and background
var background = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0
});
game.addChild(background);
for (var i = 0; i < 3; i++) {
var lane = LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0,
alpha: 0.3
});
lane.x = LANE_POSITIONS[i];
lane.y = 0;
game.addChild(lane);
}
// Create UI elements
var scoreText = new Text2('SCORE: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
scoreText.x = GAME_WIDTH / 2;
scoreText.y = 50;
LK.gui.top.addChild(scoreText);
var coinText = new Text2('COINS: 0', {
size: 80,
fill: 0xFFD700
});
coinText.anchor.set(0, 0);
coinText.x = 150;
coinText.y = 50;
LK.gui.top.addChild(coinText);
var highScoreText = new Text2('HIGH SCORE: ' + storage.highScore, {
size: 60,
fill: 0xFFAA00
});
highScoreText.anchor.set(1, 0);
highScoreText.x = GAME_WIDTH - 150;
highScoreText.y = 50;
LK.gui.top.addChild(highScoreText);
var powerupText = new Text2('', {
size: 70,
fill: 0x83DE44
});
powerupText.anchor.set(0.5, 0);
powerupText.x = GAME_WIDTH / 2;
powerupText.y = 150;
powerupText.alpha = 0;
LK.gui.top.addChild(powerupText);
var tapToStartText = new Text2('TAP TO START', {
size: 120,
fill: 0xFFFFFF
});
tapToStartText.anchor.set(0.5, 0.5);
tapToStartText.x = GAME_WIDTH / 2;
tapToStartText.y = GAME_HEIGHT / 2;
LK.gui.center.addChild(tapToStartText);
// Initialize player
function initPlayer() {
player = new Player();
player.x = LANE_POSITIONS[1]; // Start in center lane
player.y = PLAYER_START_Y;
game.addChild(player);
}
// Spawn obstacle
function spawnObstacle() {
var now = Date.now();
if (now - lastObstacleSpawn < obstacleSpawnRate) {
return;
}
lastObstacleSpawn = now;
// Determine obstacle type
var types = ['regular', 'low', 'high'];
var type = types[Math.floor(Math.random() * types.length)];
var obstacle = new Obstacle(type);
obstacle.x = LANE_POSITIONS[obstacle.lane];
obstacle.y = SPAWN_Y;
obstacle.speed = gameSpeed;
obstacles.push(obstacle);
game.addChild(obstacle);
// Gradually increase spawn rate
obstacleSpawnRate = Math.max(800, obstacleSpawnRate - 5);
}
// Spawn coin
function spawnCoin() {
var now = Date.now();
if (now - lastCoinSpawn < coinSpawnRate) {
return;
}
lastCoinSpawn = now;
// Spawn 1-3 coins in a row or pattern
var coinCount = Math.floor(Math.random() * 3) + 1;
var lane = Math.floor(Math.random() * 3);
for (var i = 0; i < coinCount; i++) {
var coin = new Coin();
// Determine pattern type
var patternType = Math.floor(Math.random() * 3);
if (patternType === 0) {
// Straight line in same lane
coin.lane = lane;
} else if (patternType === 1) {
// Diagonal pattern
coin.lane = (lane + i) % 3;
} else {
// Random lanes
coin.lane = Math.floor(Math.random() * 3);
}
coin.x = LANE_POSITIONS[coin.lane];
coin.y = SPAWN_Y - i * 120; // Spaced out vertically
coin.speed = gameSpeed;
coinsArray.push(coin);
game.addChild(coin);
}
}
// Spawn powerup
function spawnPowerup() {
var now = Date.now();
if (now - lastPowerupSpawn < powerupSpawnRate) {
return;
}
lastPowerupSpawn = now;
var powerup = new Powerup();
powerup.x = LANE_POSITIONS[powerup.lane];
powerup.y = SPAWN_Y;
powerup.speed = gameSpeed;
powerups.push(powerup);
game.addChild(powerup);
}
// Check collision between two objects using their collision boxes
function checkCollision(obj1, obj2) {
var box1 = obj1.getCollisionBox();
var box2 = obj2.getCollisionBox();
return box1.x < box2.x + box2.width && box1.x + box1.width > box2.x && box1.y < box2.y + box2.height && box1.y + box1.height > box2.y;
}
// Handle collisions
function handleCollisions() {
if (!player) {
return;
}
// Check obstacle collisions
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
if (checkCollision(player, obstacle)) {
if (player.powerupActive && player.powerupType === 'invincibility') {
// Destroy obstacle if player is invincible
obstacle.destroy();
obstacles.splice(i, 1);
// Add points for destroying obstacle
addScore(50);
} else {
// Game over on collision
LK.getSound('crash').play();
LK.effects.flashScreen(0xff0000, 500);
// Update high score
if (score > storage.highScore) {
storage.highScore = score;
highScoreText.setText('HIGH SCORE: ' + storage.highScore);
}
// Update total coins
storage.coins += coins;
LK.showGameOver();
return;
}
}
}
// Check coin collisions
for (var j = coinsArray.length - 1; j >= 0; j--) {
var coin = coinsArray[j];
// For magnet powerup, attract nearby coins
if (player.powerupActive && player.powerupType === 'magnet') {
var dx = player.x - coin.x;
var dy = player.y - coin.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 400) {
// Move coin towards player
var speed = 0.1;
coin.x += dx * speed;
coin.y += dy * speed;
}
}
if (checkCollision(player, coin)) {
coin.collect();
coinsArray.splice(j, 1);
// Add coin and points
coins++;
coinText.setText('COINS: ' + coins);
addScore(10);
}
}
// Check powerup collisions
for (var k = powerups.length - 1; k >= 0; k--) {
var powerup = powerups[k];
if (checkCollision(player, powerup)) {
powerup.collect();
player.activatePowerup(powerup.type);
powerups.splice(k, 1);
// Show powerup text
var powerupName = powerup.type.charAt(0).toUpperCase() + powerup.type.slice(1);
powerupText.setText(powerupName + ' ACTIVATED!');
powerupText.alpha = 1;
// Fade out powerup text
tween(powerupText, {
alpha: 0
}, {
duration: 2000,
easing: tween.linear
});
// Set multiplier if applicable
if (powerup.type === 'multiplier') {
multiplier = 2;
}
}
}
}
// Add to score
function addScore(points) {
score += points * multiplier;
scoreText.setText('SCORE: ' + score);
}
// Handle touch/mouse events
game.down = function (x, y, obj) {
if (!gameStarted) {
startGame();
return;
}
playerSwipeStartX = x;
playerSwipeStartY = y;
swipeDirection = null;
};
game.move = function (x, y, obj) {
if (!gameStarted || !player) {
return;
}
// Make player follow mouse/touch position horizontally
// Find the closest lane based on x position
var closestLane = 0;
var closestDist = Math.abs(x - LANE_POSITIONS[0]);
for (var i = 1; i < LANE_POSITIONS.length; i++) {
var dist = Math.abs(x - LANE_POSITIONS[i]);
if (dist < closestDist) {
closestDist = dist;
closestLane = i;
}
}
// Only change lane if needed
if (player.lane !== closestLane) {
player.switchLane(closestLane);
}
};
game.up = function (x, y, obj) {
// Reset swipe state
swipeDirection = null;
};
// Start the game
function startGame() {
if (gameStarted) {
return;
}
gameStarted = true;
// Hide start text
tween(tapToStartText, {
alpha: 0
}, {
duration: 500,
easing: tween.easeOut
});
// Initialize game variables
score = 0;
distance = 0;
coins = 0;
multiplier = 1;
gameSpeed = 10;
// Update UI
scoreText.setText('SCORE: 0');
coinText.setText('COINS: 0');
highScoreText.setText('HIGH SCORE: ' + storage.highScore);
// Initialize player
initPlayer();
// Play music
LK.playMusic('gameMusic');
}
// Game update function
game.update = function () {
if (!gameStarted) {
return;
}
// Increase distance and score
distance += gameSpeed;
if (LK.ticks % 10 === 0) {
addScore(1);
}
// Gradually increase game speed
if (LK.ticks % 300 === 0) {
gameSpeed += 0.2;
}
// Spawn game elements
spawnObstacle();
spawnCoin();
spawnPowerup();
// Update powerup status
if (player) {
player.updatePowerup();
// Reset multiplier when powerup ends
if (!player.powerupActive && player.powerupType === 'multiplier') {
multiplier = 1;
}
}
// Update and clean up obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
if (obstacle.y > DESPAWN_Y) {
obstacle.destroy();
obstacles.splice(i, 1);
}
}
// Update and clean up coins
for (var j = coinsArray.length - 1; j >= 0; j--) {
var coin = coinsArray[j];
if (coin.y > DESPAWN_Y || coin.collected) {
coin.destroy();
coinsArray.splice(j, 1);
}
}
// Update and clean up powerups
for (var k = powerups.length - 1; k >= 0; k--) {
var powerup = powerups[k];
if (powerup.y > DESPAWN_Y || powerup.collected) {
powerup.destroy();
powerups.splice(k, 1);
}
}
// Check for collisions
handleCollisions();
}; ===================================================================
--- original.js
+++ change.js
@@ -537,32 +537,23 @@
game.move = function (x, y, obj) {
if (!gameStarted || !player) {
return;
}
- // Calculate swipe distance
- var dx = x - playerSwipeStartX;
- var dy = y - playerSwipeStartY;
- var absDx = Math.abs(dx);
- var absDy = Math.abs(dy);
- // Only register swipe if it's long enough and we haven't already processed this swipe
- if (swipeDirection === null && (absDx > MIN_SWIPE_DISTANCE || absDy > MIN_SWIPE_DISTANCE)) {
- if (absDx > absDy) {
- // Horizontal swipe (lane change)
- swipeDirection = dx > 0 ? 'right' : 'left';
- var newLane = player.lane + (dx > 0 ? 1 : -1);
- if (newLane >= 0 && newLane <= 2) {
- player.switchLane(newLane);
- }
- } else {
- // Vertical swipe (jump or slide)
- swipeDirection = dy > 0 ? 'down' : 'up';
- if (dy < 0) {
- player.jump();
- } else {
- player.slide();
- }
+ // Make player follow mouse/touch position horizontally
+ // Find the closest lane based on x position
+ var closestLane = 0;
+ var closestDist = Math.abs(x - LANE_POSITIONS[0]);
+ for (var i = 1; i < LANE_POSITIONS.length; i++) {
+ var dist = Math.abs(x - LANE_POSITIONS[i]);
+ if (dist < closestDist) {
+ closestDist = dist;
+ closestLane = i;
}
}
+ // Only change lane if needed
+ if (player.lane !== closestLane) {
+ player.switchLane(closestLane);
+ }
};
game.up = function (x, y, obj) {
// Reset swipe state
swipeDirection = null;