Code edit (9 edits merged)
Please save this source code
User prompt
Make the speed of the palms half
Code edit (3 edits merged)
Please save this source code
User prompt
don't downscale on x the roadlines as they progress
Code edit (2 edits merged)
Please save this source code
User prompt
There are too many roadlines, spawn half of those
User prompt
Make sure all the roadlines start on y center, never on top of the screen!
User prompt
The roadlines should start on the y center
Code edit (4 edits merged)
Please save this source code
User prompt
The roadline looks the opposite - what I need is the more above they are, the more close to each other, almost like points. As they go down, the more separation they have. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (23 edits merged)
Please save this source code
User prompt
Create double the number of roadlines as now
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
Palms are not destroyed now :(
User prompt
Palms are stuck on the bottom and not destroyed. This is abug with the onFinish. Better please check the y somehow separately.
User prompt
Something is not right: I get at start 10 palms, but they only palms on the right being spawned one at a time and some of them stucking on the bottom.
Code edit (3 edits merged)
Please save this source code
User prompt
You are not destroying the palms when reaching the bottom.
User prompt
Please follow this instructions carefully: 1. Initialize PALM_COUNT to 10. 2. Create an array of palms. 3. Start generating palms as times goes by and adding them to the array. 1, 2, 3 ... until 10. 4. Check if a palm has reached the bottom. If so, destory. You will have 9, with a free slot in the palm array again . Generate another one. Add it to the array. 5. And that continuously!
User prompt
Please follow this instructions carefully: 1. Initialize PALM_COUNT to 10. 2. Create an array of palms. 3. Start generating palms as times goes by and adding them to the array. 1, 2, 3 ... until 10. 4. Check if a palm has reached the bottom. If so, destory. You will have 9, with a free slot in the palm array again . Generate another one. Add it to the array. 5. And that continuously!
User prompt
palms = []; ???? You are not generating any palm
User prompt
I only see 2 palms and they are nos being destroyed when reaching the bottom :(
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var Palm = Container.expand(function () {
var self = Container.call(this);
var palmGraphics = self.attachAsset('palm', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = palmGraphics.width;
self.height = palmGraphics.height;
self.isMoving = false;
self.direction = "left"; // Default direction
self.lastY = 0;
self.update = function () {
// Animation will be handled by tweens
// This just ensures we have an update method for tracking
};
return self;
});
var PlayerCar = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = carGraphics.width;
self.height = carGraphics.height;
self.speed = 0;
self.maxSpeed = 15;
self.steering = 0;
self.crashed = false;
self.crash = function () {
if (!self.crashed) {
self.crashed = true;
LK.getSound('crash').play();
LK.effects.flashObject(self, 0xFF0000, 1000);
self.speed = Math.max(0, self.speed - 5);
// Reset crash state after 1 second
LK.setTimeout(function () {
self.crashed = false;
}, 1000);
}
};
self.update = function () {
// Handle car physics
if (!self.crashed) {
self.speed = Math.min(self.maxSpeed, self.speed + 0.1);
}
// Apply steering if not crashed
if (!self.crashed) {
self.x += self.steering;
}
// Keep car within bounds
if (self.x < self.width / 2) {
self.x = self.width / 2;
}
if (self.x > 2048 - self.width / 2) {
self.x = 2048 - self.width / 2;
}
};
return self;
});
var TrafficCar = Container.expand(function () {
var self = Container.call(this);
// Randomly select one of the available traffic car assets
var carAssets = ['trafficCar', 'trafficCar2', 'trafficCar3', 'trafficCar4'];
var selectedCarAsset = carAssets[Math.floor(Math.random() * carAssets.length)];
var carGraphics = self.attachAsset(selectedCarAsset, {
anchorX: 0.5,
anchorY: 0.5
});
self.width = carGraphics.width;
self.height = carGraphics.height;
self.speed = 5;
self.direction = Math.random() > 0.5 ? 1 : -1; // Random direction: -1 = left, 1 = right
self.startY = 1400; // Starting Y position (further up the screen)
self.targetY = 2732 + self.height; // Y position when fully off-screen (bottom)
self.initialScale = 0.1;
self.targetScale = 2.0;
// Set target X position in one of the specified ranges
self.targetX = Math.random() > 0.5 ? Math.random() * 500 + 2000 : Math.random() * 100;
// Set initial scale
self.scale.set(self.initialScale);
self.update = function () {
// Calculate progress towards target Y
var progress = (self.y - self.startY) / (self.targetY - self.startY);
progress = Math.max(0, Math.min(1, progress)); // Clamp between 0 and 1
// Interpolate scale based on progress
var currentScale = self.initialScale + (self.targetScale - self.initialScale) * progress;
self.scale.set(currentScale);
// Calculate X position based on progress (linear interpolation)
var startX = 2048 / 2; // Center of screen
self.x = startX + (self.targetX - startX) * progress;
// Increase speed as car progresses - starting slow and getting faster
var speedMultiplier = 0.5 + progress * 5; // Starts at 0.5 when progress=0, ends at 3.0 when progress=1
// Update Y position with increasing speed
self.y += (gameSpeed - self.speed) * speedMultiplier;
// Destroy if off screen
if (self.y > self.targetY) {
// Check against targetY
// Find and remove self from trafficCars array
var index = trafficCars.indexOf(self);
if (index > -1) {
trafficCars.splice(index, 1);
}
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game state variables
var gameSpeed = 10;
var gameStarted = false;
var gameTime = 30; // Initial time in seconds
var distance = 0;
var level = 1;
var checkpointDistance = 500; // Distance between checkpoints
var nextCheckpointAt = checkpointDistance;
var trafficCars = [];
var obstacles = [];
var checkpoints = [];
var timeBonuses = [];
var difficultyTimer;
// Create container groups
var palmGroup = new Container();
var roadLineGroup = new Container();
// Create palm trees
var PALM_COUNT = 10;
var palms = [];
var centerX = 2048 / 2; // Center of screen X
var centerY = 2732 / 2; // Center of screen Y
var palmSpawnCooldown = 30; // Spawn a palm every 0.5 seconds if needed
var palmSpawnTimer = 0; // Timer to track cooldown
var lastSpawnSide = "right"; // Track the last side a palm was spawned on
// Create Road Lines
var roadLines = [];
for (var i = 0; i < 40; i++) {
var line = LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5
});
line.x = 2048 / 2; // Center of the screen (50% x)
// Calculate position with variable spacing (closer together at top)
var progress = i / 40; // 0 to 1
// Exponential spacing - lines get further apart as they go down
var spacing = 40 + progress * progress * 200;
// Start from centerY instead of 0
var yPos = i > 0 ? roadLines[i - 1].y + spacing : centerY;
line.y = yPos;
// Initial scale based on position (larger at top, smaller at bottom)
var scaleX = 3.0 - progress * 2.5; // Width decreases with progress (3.0 to 0.5)
var scaleY = 3.0 - progress * 2.0; // Height decreases with progress (3.0 to 1.0)
line.scale.set(scaleX, scaleY);
line.lastY = line.y;
roadLines.push(line);
roadLineGroup.addChild(line);
}
// Sway parameters
var swayCounter = 0;
// Create road
var road = LK.getAsset('road', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 1100
});
game.addChild(road);
game.addChild(palmGroup);
game.addChild(roadLineGroup);
// Create player car
var player = new PlayerCar();
player.x = 2048 / 2;
player.y = 2732 - 300;
game.addChild(player);
// Create UI elements
var timeText = new Text2('Time: 30', {
size: 80,
fill: 0xFFFFFF
});
timeText.anchor.set(0, 0);
LK.gui.topRight.addChild(timeText);
timeText.x = -250; // Offset from right edge
var scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.top.addChild(scoreText);
var levelText = new Text2('Level: 1', {
size: 80,
fill: 0xFFFFFF
});
levelText.anchor.set(0, 0);
LK.gui.topRight.addChild(levelText);
levelText.y = 100; // Offset below time
levelText.x = -250; // Offset from right edge
var startText = new Text2('TAP TO START', {
size: 120,
fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(startText);
// Functions to spawn game elements
function spawnTrafficCar() {
// Only spawn a new car if there are no cars on screen
if (trafficCars.length === 0) {
var car = new TrafficCar();
car.x = 2048 / 2; // Start in the middle of the screen
car.y = car.startY; // Start at the defined startY
car.speed = 3 + Math.random() * 5; // Random speed
trafficCars.push(car);
game.addChild(car);
}
// Schedule next check for spawning
var nextSpawnTime = 1000; // Check every second
LK.setTimeout(spawnTrafficCar, nextSpawnTime);
}
// Start game function
function startGame() {
gameStarted = true;
gameTime = 30;
distance = 0;
level = 1;
gameSpeed = 10;
nextCheckpointAt = checkpointDistance;
LK.setScore(0);
// Update UI
scoreText.setText('Score: 0');
timeText.setText('Time: ' + Math.ceil(gameTime));
levelText.setText('Level: ' + level);
// Remove start text
LK.gui.center.removeChild(startText);
// Start spawning game elements
spawnTrafficCar();
// Set timer to increase difficulty
difficultyTimer = LK.setInterval(function () {
if (gameStarted) {
level++;
gameSpeed += 1;
levelText.setText('Level: ' + level);
}
}, 30000); // Increase difficulty every 30 seconds
// Play background music
LK.playMusic('bgmusic');
// Palm spawning is handled in the update function
}
// Handle touch input
game.down = function (x, y) {
if (!gameStarted) {
startGame();
return;
}
};
game.move = function (x, y) {
if (!gameStarted) {
return;
}
// Move player car directly to mouse X position
var targetX = x;
// Apply smooth movement by calculating the difference
var deltaX = targetX - player.x;
player.steering = deltaX * 0.1; // Smooth movement factor
};
game.up = function () {
if (gameStarted) {
// No need to reset steering as we'll continue to follow mouse
}
};
// Main game update function
game.update = function () {
if (!gameStarted) {
return;
}
// Update game time
gameTime -= 1 / 60; // Assuming 60 FPS
timeText.setText('Time: ' + Math.ceil(gameTime));
// Update distance
if (gameStarted) {
distance += gameSpeed;
LK.setScore(Math.floor(distance / 10));
scoreText.setText('Score: ' + LK.getScore());
// Update palm animations
for (var p = palms.length - 1; p >= 0; p--) {
var palm = palms[p];
// Check if palm exists before accessing its properties
if (palm) {
palm.lastY = palm.y;
// Start a new palm animation if palm is not already moving
if (palm.isMoving === false) {
palm.isMoving = true;
// Set target position based on direction (left or right corner)
var targetX = palm.direction === "left" ? -4500 : 5500; // Left or right edge
var targetY = 2732 + 100; // Below bottom of screen
var targetScale = 2.0; // End larger
// Create tween animation with perspective effect - use same duration for all palms
tween(palm, {
x: targetX,
y: targetY,
scaleX: targetScale * (lastSpawnSide === "right" ? 1 : -1),
scaleY: targetScale
}, {
duration: 3000,
// Same fixed duration for all palms: 3 seconds
easing: tween.easeIn // Removed onFinish callback
});
}
// Check if palm has moved significantly past the bottom of the screen and destroy it
var destroyYPosition = 2500; // Check if center is 150px below the bottom edge
if (palm.isMoving && palm.y > destroyYPosition) {
// Palm is off-screen, destroy it
var index = palms.indexOf(palm);
if (index > -1) {
palmGroup.removeChild(palm);
palms.splice(index, 1);
palm.destroy();
}
// Skip to next palm as this one is destroyed
continue;
}
}
} // End of loop processing existing palms
// Update palm spawn timer and generate new palms if needed
palmSpawnTimer -= 1;
if (palmSpawnTimer <= 0 && palms.length < PALM_COUNT) {
palmSpawnTimer = palmSpawnCooldown; // Reset timer
var newPalm = new Palm();
// Alternate spawn side based on the last spawned side
lastSpawnSide = lastSpawnSide === "right" ? "left" : "right";
// Start from exact center point
newPalm.x = centerX + (lastSpawnSide === "right" ? 50 : -50);
newPalm.y = centerY - 100; // Start at center
newPalm.scale.set(0.1); // Start small
newPalm.scaleX *= lastSpawnSide === "right" ? 1 : -1;
newPalm.lastY = newPalm.y;
newPalm.direction = lastSpawnSide; // Use the determined side
newPalm.isMoving = false; // Flag to track if palm is currently animating
palms.push(newPalm);
palmGroup.addChild(newPalm);
}
// Move road lines
for (var r = 0; r < roadLines.length; r++) {
var line = roadLines[r];
line.lastY = line.y;
line.y += 5 * gameSpeed / 10;
if (line.y > 2732) {
line.x = 2048 / 2; // Center of the screen (50% x)
line.y = centerY; // Reset to center of screen
// Reset scale to largest for lines that just respawned (they're at the top/horizon)
line.scale.set(3.0, 1.0);
}
// Update scale based on Y position to create reverse perspective
var progress = line.y / 2732; // 0 at top, 1 at bottom
progress = Math.max(0, Math.min(1, progress)); // Clamp between 0 and 1
// Scale decreases with progress (large at top, small at bottom)
var scaleY = 1.0 + (1.0 - progress) * 2.0; // Height decreases as it moves down
var scaleX = 3.0 - progress * 2.5; // Width decreases as it moves down (3.0 to 0.5)
// Keep position fixed at center - no spreading
line.x = 2048 / 2; // Keep all lines at center
line.scale.set(scaleX, scaleY);
}
}
// Game will continue indefinitely - removed game over condition
gameTime = Math.max(gameTime, 0.1); // Keep time from reaching zero
// Check collisions with traffic cars but just trigger visual effect without ending game
for (var i = trafficCars.length - 1; i >= 0; i--) {
var car = trafficCars[i];
if (player.intersects(car) && !player.crashed) {
player.crash();
trafficCars.splice(i, 1);
car.destroy();
// Add small time bonus on collision instead of ending game
gameTime += 1;
}
}
};
function endGame() {
if (!gameStarted) {
return;
}
// Just save high score without ending the game
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
}
// Game continues - no game over screen
} ===================================================================
--- original.js
+++ change.js
@@ -363,9 +363,9 @@
line.lastY = line.y;
line.y += 5 * gameSpeed / 10;
if (line.y > 2732) {
line.x = 2048 / 2; // Center of the screen (50% x)
- line.y = 0; // Reset to top of screen
+ line.y = centerY; // Reset to center of screen
// Reset scale to largest for lines that just respawned (they're at the top/horizon)
line.scale.set(3.0, 1.0);
}
// Update scale based on Y position to create reverse perspective