Code edit (1 edits merged)
Please save this source code
User prompt
Reverse how you draw the bullets
User prompt
No. Bullets start separated and they merge on the way down. That' can't be, bullets can't merge closer to me! They can only merge closer to the horizon due to the perspective
User prompt
It's weird, should the bullets be drawn the other way around? They merge closer to the horizon (centerY) not closer to the bottom of the screen that is where I am
User prompt
Ok I want to implement a road lines in the middle of my lane, that give a sense my car is moving. The view is almost 3d, that is, the road looks like this / \ So the lines would be in the middle / | \ My idea is to have discontinuos lines like: | | | However, as it's 3d, we have a perspective, further away lines (top) would look different than closer ones (bottom). The horizon is at centerY. Please implement them ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Remove all logic for roadLines and roadLInesGroup
Code edit (11 edits merged)
Please save this source code
User prompt
Implement those except the starting point, which should be kept as it is.
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
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
/**** * 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 = 1300; // 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 = 1 + progress * 4; // 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 < 20; i++) { // Reduced from 40 to 20 as requested var line = LK.getAsset('roadLine', { anchorX: 0.5, anchorY: 0.5 }); line.x = 2048 / 2; // Center of the screen (50% x) // Calculate position with improved perspective effect var progress = i / 20; // 0 to 1 // Exponential spacing - lines get much closer together at horizon var spacing = 50 + progress * progress * 400; // Start tighter at horizon // Position lines on a perspective curve starting from horizon var horizon = centerY - 500; // Higher up on screen for better perspective var yPos = i > 0 ? roadLines[i - 1].y + spacing : horizon; line.y = yPos; // Initial scale based on position (much smaller at horizon, larger as they approach) var scaleX = 0.5 + progress * 2.5; // Width increases with progress (0.5 to 3.0) var scaleY = 0.3 + progress * 2.7; // Height increases with progress (0.3 to 3.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: 2732 / 2 y: 1000 }); 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" ? -12000 : 14500; // 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: 7000, // Same fixed duration for all palms: 6 seconds (half speed) 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.005); // 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; // Speed increases as line moves down for accelerating perspective effect var lineProgress = line.y / 2732; // 0 at top, 1 at bottom var speedMultiplier = 1 + lineProgress * 2; // Speed increases as line approaches player line.y += 5 * gameSpeed / 10 * speedMultiplier; // If line goes off screen, reset to horizon point in center screen if (line.y > 2732) { line.x = 2048 / 2; // Center of the screen (50% x) // Reset to centerY (not top of screen) as requested line.y = centerY - 500; // Reset to horizon point // Reset scale to smallest (appear at horizon) line.scale.set(0.5, 0.3); } // Update scale based on Y position for more dramatic perspective var progress = (line.y - (centerY - 500)) / (2732 - (centerY - 500)); // 0 at horizon, 1 at bottom progress = Math.max(0, Math.min(1, progress)); // Clamp between 0 and 1 // Dramatic scaling for better perspective (small at horizon, large at bottom) var scaleY = 0.3 + progress * 2.7; // Height increases as it moves down (0.3 to 3.0) var scaleX = 3.0; // Keep width constant as requested (don't downscale on x) // Keep position fixed at center 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
@@ -153,24 +153,26 @@
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 < 10; i++) {
+for (var i = 0; i < 20; i++) {
+ // Reduced from 40 to 20 as requested
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)
+ // Calculate position with improved perspective effect
var progress = i / 20; // 0 to 1
- // Exponential spacing - lines get further apart as they go down
- var spacing = 140 + progress * progress * 200;
- // Start from centerY instead of 0
- var yPos = i > 0 ? roadLines[i - 1].y + spacing : centerY;
+ // Exponential spacing - lines get much closer together at horizon
+ var spacing = 50 + progress * progress * 400; // Start tighter at horizon
+ // Position lines on a perspective curve starting from horizon
+ var horizon = centerY - 500; // Higher up on screen for better perspective
+ var yPos = i > 0 ? roadLines[i - 1].y + spacing : horizon;
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)
+ // Initial scale based on position (much smaller at horizon, larger as they approach)
+ var scaleX = 0.5 + progress * 2.5; // Width increases with progress (0.5 to 3.0)
+ var scaleY = 0.3 + progress * 2.7; // Height increases with progress (0.3 to 3.0)
line.scale.set(scaleX, scaleY);
line.lastY = line.y;
roadLines.push(line);
roadLineGroup.addChild(line);
@@ -181,9 +183,10 @@
var road = LK.getAsset('road', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
- y: 1100
+ //y: 2732 / 2
+ y: 1000
});
game.addChild(road);
game.addChild(palmGroup);
game.addChild(roadLineGroup);
@@ -318,9 +321,9 @@
y: targetY,
scaleX: targetScale * (lastSpawnSide === "right" ? 1 : -1),
scaleY: targetScale
}, {
- duration: 5000,
+ duration: 7000,
// Same fixed duration for all palms: 6 seconds (half speed)
easing: tween.easeIn // Removed onFinish callback
});
}
@@ -360,22 +363,27 @@
// Move road lines
for (var r = 0; r < roadLines.length; r++) {
var line = roadLines[r];
line.lastY = line.y;
- line.y += 5 * gameSpeed / 10;
+ // Speed increases as line moves down for accelerating perspective effect
+ var lineProgress = line.y / 2732; // 0 at top, 1 at bottom
+ var speedMultiplier = 1 + lineProgress * 2; // Speed increases as line approaches player
+ line.y += 5 * gameSpeed / 10 * speedMultiplier;
+ // If line goes off screen, reset to horizon point in center screen
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);
+ // Reset to centerY (not top of screen) as requested
+ line.y = centerY - 500; // Reset to horizon point
+ // Reset scale to smallest (appear at horizon)
+ line.scale.set(0.5, 0.3);
}
- // Update scale based on Y position to create reverse perspective
- var progress = line.y / 2732; // 0 at top, 1 at bottom
+ // Update scale based on Y position for more dramatic perspective
+ var progress = (line.y - (centerY - 500)) / (2732 - (centerY - 500)); // 0 at horizon, 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; // Keep width constant at 3.0 (don't downscale on x-axis)
- // Keep position fixed at center - no spreading
+ // Dramatic scaling for better perspective (small at horizon, large at bottom)
+ var scaleY = 0.3 + progress * 2.7; // Height increases as it moves down (0.3 to 3.0)
+ var scaleX = 3.0; // Keep width constant as requested (don't downscale on x)
+ // Keep position fixed at center
line.x = 2048 / 2; // Keep all lines at center
line.scale.set(scaleX, scaleY);
}
}