User prompt
show the game icon and the startbutton in the main menu
User prompt
create an image for the icon and an image for the start button
User prompt
Create a Main Menu where it displays an image that will be the icon of the game and an image as a play button, and make all elements of game invisible except the background and make them visible once the player presses start/play button to initiate the game ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
ensure this technique work for every spawned hole
User prompt
the hole image should be shown in the heirarchy under everything except the background
User prompt
make the bullets not destroy when the hit the hole, it must pass through, but just the hole
User prompt
create an image for the hole
User prompt
add an image for the hole
Code edit (6 edits merged)
Please save this source code
User prompt
remove completely the rim graphics from the whole, i just want one image
User prompt
Please fix the bug: 'ReferenceError: rimGraphics is not defined' in or related to this line: 'rimGraphics.tint = 0x666666; // Lighter as it takes damage' Line Number: 235
Code edit (1 edits merged)
Please save this source code
User prompt
update the code to NOT spawn more than one enemy in the same lane, until the current is dead or off screen
User prompt
set to if theres any obstacle in one lane, it cant spawn another obstacle or enemy in the same lane until the obstacle is detroyed or off screen
User prompt
set the enemy in a way that can only spawn a new enemy in the same lane after the enemy in that lane died or is off screen
Code edit (1 edits merged)
Please save this source code
User prompt
make a function with the spawnRate for each enemy, and each obstacle
User prompt
the score UI must show above all images
User prompt
cant destroy the whole with bullets, refine that
User prompt
add a new type of obstacle that the player can destroy, its a hole, if the player dont avoid it, he will take damage
User prompt
adjust the hit effect for, just make the player sprite turn red for 0.2 seconds and turn back to normal. and only when the player dies you can blink the screen with the red effect ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
define the updateHealthDisplay before calling it
User prompt
create an function that updates the health display for when the player hit an obstacle or get hit by an enemy bullet
User prompt
Please fix the bug: 'ReferenceError: updateHealthDisplay is not defined' in or related to this line: 'updateHealthDisplay();' Line Number: 243
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Background elements that scrolls to create movement illusion var BackgroundTile = Container.expand(function () { var self = Container.call(this); var tileGraphics = self.attachAsset('backgroundTile', { anchorX: 0.5, anchorY: 0 }); self.speed = 2; //{6} // Start with slower speed self.update = function () { self.y += self.speed; // Reset position when it goes out of view if (self.y >= 2732) { // Calculate the exact position needed for seamless tiling // Find the tile that's highest up (lowest y value) var highestTile = self; var highestY = self.y; for (var i = 0; i < backgroundTiles.length; i++) { var tile = backgroundTiles[i]; if (tile !== self && tile.y < highestY) { highestTile = tile; highestY = tile.y; } } // Position this tile directly above the highest tile self.y = highestY - tileGraphics.height; } }; return self; }); // Game variables // Barrier obstacle var Barrier = Container.expand(function () { var self = Container.call(this); var barrierGraphics = self.attachAsset('barrier', { anchorX: 0.5, anchorY: 0.5 }); // Barrier properties self.health = 5; self.speed = 2; //{i} // Start with slower speed // Last position tracking for collision detection self.lastX = 0; self.lastY = 0; self.lastWasIntersecting = false; // Take damage self.takeDamage = function () { self.health--; if (self.health <= 0) { LK.getSound('explosion').play(); LK.setScore(LK.getScore() + 2); return true; // Barrier destroyed } return false; // Barrier still intact }; // Update called every frame self.update = function () { self.lastX = self.x; self.lastY = self.y; // Move downward self.y += self.speed; }; return self; }); // Enemy class var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics; // Enemy properties self.health = 1; self.speed = 5; self.shootChance = 1; // 1% chance per frame self.lane = 0; self.type = 'basic'; // basic, shooter, tank // Last position tracking for collision detection self.lastX = 0; self.lastY = 0; self.lastWasIntersecting = false; // Initialize enemy with type self.init = function (type, lane) { self.type = type; self.lane = lane; // Remove previous graphics if exists if (enemyGraphics) { self.removeChild(enemyGraphics); } if (type === 'basic') { enemyGraphics = self.attachAsset('enemyBasic', { anchorX: 0.5, anchorY: 0.5 }); self.health = 1; self.speed = 3; //{P} // Slower starting speed self.shootRate = 100; // Shots per second } else if (type === 'shooter') { enemyGraphics = self.attachAsset('enemyShooter', { anchorX: 0.5, anchorY: 0.5 }); self.health = 1; self.speed = 2.5; // Slower starting speed self.shootRate = 80; // Moderate fire rate } else if (type === 'tank') { enemyGraphics = self.attachAsset('enemyTank', { anchorX: 0.5, anchorY: 0.5 }); self.health = 30; self.speed = 2; // Slower starting speed self.shootRate = 200; // Slow fire rate } }; // Shoot method for enemies self.shootRate = 100; // Base shoot rate (bullets per frame at 60fps) self.shootCooldown = 0; self.tryShoot = function () { // Create bullet with a rate based on shootRate and normalized for 60fps // shootRate is # of frames between shots at 60 FPS // Higher shootRate = slower shooting // Lower shootRate = faster shooting if (Math.random() < 1 / self.shootRate * 60 * LK.deltaTime) { var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y + 60; game.addChild(bullet); enemyBullets.push(bullet); } }; // Take damage self.takeDamage = function () { self.health--; if (self.health <= 0) { LK.getSound('explosion').play(); LK.setScore(LK.getScore() + 1); return true; // Enemy destroyed } return false; // Enemy still alive }; // Update called every frame self.update = function () { self.lastX = self.x; self.lastY = self.y; // Move downward self.y += self.speed; // Update shooting cooldown if (self.shootCooldown > 0) { self.shootCooldown -= LK.deltaTime; } // Try to shoot if we're a shooting type if ((self.type === 'shooter' || self.type === 'tank' || self.type === 'basic') && self.y > 0) { self.tryShoot(); } }; return self; }); // Enemy bullet var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('enemyBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 10; // Last position tracking for collision detection self.lastX = 0; self.lastY = 0; self.lastWasIntersecting = false; self.update = function () { self.lastX = self.x; self.lastY = self.y; // Move bullet downward using delta time var frameRate = 60; // Base frame rate var speedMultiplier = LK.deltaTime * frameRate; // Adjust speed based on actual frame time self.y += self.speed * speedMultiplier; }; return self; }); // Hole obstacle class var Hole = Container.expand(function () { var self = Container.call(this); // Create a shape for the hole (black circle) var holeGraphics = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, tint: 0x000000, // Black color for hole scaleX: 2, scaleY: 0.5 // Elliptical shape to look like a hole }); self.addChild(holeGraphics); // Add highlight rim around the hole var rimGraphics = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, tint: 0x333333, // Dark gray rim scaleX: 2.2, scaleY: 0.55 }); self.addChild(rimGraphics); self.setChildIndex(holeGraphics, 1); // Make sure hole is above rim // Hole properties self.health = 3; self.speed = 2; // Start with slower speed // Last position tracking for collision detection self.lastX = 0; self.lastY = 0; self.lastWasIntersecting = false; // Take damage self.takeDamage = function () { // Reduce hole health by 1 self.health--; // Show damage by changing rim color if (self.health === 2) { rimGraphics.tint = 0x666666; // Lighter as it takes damage } else if (self.health === 1) { rimGraphics.tint = 0x999999; // Even lighter } // Check if hole is completely destroyed if (self.health <= 0) { LK.getSound('explosion').play(); LK.setScore(LK.getScore() + 3); // More points than barriers return true; // Hole destroyed } return false; // Hole still intact }; // Update called every frame self.update = function () { self.lastX = self.x; self.lastY = self.y; // Move downward self.y += self.speed; }; return self; }); // Lane definitions for positioning var Lane = Container.expand(function () { var self = Container.call(this); var laneGraphics = self.attachAsset('lane', { anchorX: 0.5, anchorY: 0 }); return self; }); // Function to update health display // Player class var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); // Player properties self.currentLane = 1; // 0=left, 1=center, 2=right self.shootCooldown = 0; self.shootRate = 50; // Configurable shoot rate (bullets per second) self.bulletType = 'normal'; // normal, double, triple self.powerUpTimer = 0; self.isAlive = true; self.maxHealth = 3; // Maximum health points self.health = self.maxHealth; // Current health // Last position tracking for collision detection self.lastX = 0; self.lastY = 0; self.lastWasIntersecting = false; // Method to handle damage and health reduction self.takeDamage = function () { if (!self.isAlive) { return; } // Don't take damage if already dead self.health--; // Subtract health by 1 // Update health display updateHealthDisplay(); // Turn player sprite red briefly to indicate damage tween(playerGraphics, { tint: 0xFF0000 }, { duration: 200, onFinish: function onFinish() { tween(playerGraphics, { tint: 0xFFFFFF }, { duration: 100 }); } }); // Check if player is dead if (self.health <= 0) { self.isAlive = false; // Flash screen red for game over LK.effects.flashScreen(0xff0000, 1000); LK.setTimeout(function () { LK.showGameOver(); }, 1000); } return self.health <= 0; // Return true if player died }; // Movement handling self.moveTo = function (laneIndex) { if (laneIndex >= 0 && laneIndex <= 2) { self.currentLane = laneIndex; } }; // Shoot method self.shoot = function () { // Use the configurable shootRate variable instead of hard-coded value if (self.shootCooldown <= 0) { LK.getSound('shoot').play(); if (self.bulletType === 'normal') { // Create a single bullet var bullet = new PlayerBullet(); bullet.x = self.x; bullet.y = self.y - 60; game.addChild(bullet); playerBullets.push(bullet); } else if (self.bulletType === 'double') { // Create two side-by-side bullets var bullet1 = new PlayerBullet(); bullet1.x = self.x - 30; bullet1.y = self.y - 60; game.addChild(bullet1); playerBullets.push(bullet1); var bullet2 = new PlayerBullet(); bullet2.x = self.x + 30; bullet2.y = self.y - 60; game.addChild(bullet2); playerBullets.push(bullet2); } else if (self.bulletType === 'triple') { // Create three bullets - one forward and two diagonal var bulletCenter = new PlayerBullet(); bulletCenter.x = self.x; bulletCenter.y = self.y - 60; game.addChild(bulletCenter); playerBullets.push(bulletCenter); var bulletLeft = new PlayerBullet(); bulletLeft.x = self.x - 30; bulletLeft.y = self.y - 60; bulletLeft.angle = -15; // Diagonal left game.addChild(bulletLeft); playerBullets.push(bulletLeft); var bulletRight = new PlayerBullet(); bulletRight.x = self.x + 30; bulletRight.y = self.y - 60; bulletRight.angle = 15; // Diagonal right game.addChild(bulletRight); playerBullets.push(bulletRight); } // Set cooldown based on the configurable shootRate variable self.shootCooldown = self.shootRate / 60; // Normalize to 60 fps } }; // Power-up activation self.activatePowerUp = function (type) { LK.getSound('powerUp').play(); if (type === 'fastShoot') { self.setShootRate(25); // Set faster shooting rate self.bulletType = 'normal'; // Keep normal bullet type } else { self.bulletType = type; self.setShootRate(50); // Reset to default rate } self.powerUpTimer = 600; // 5 seconds at 60fps }; // Method to change the shoot rate self.setShootRate = function (rate) { if (rate > 0) { self.shootRate = rate; } }; // Update called every frame self.update = function () { self.lastX = self.x; self.lastY = self.y; // Handle cooldowns directly (not converting from frames) if (self.shootCooldown > 0) { self.shootCooldown -= LK.deltaTime; } // Power-up timer using delta time if (self.powerUpTimer > 0) { self.powerUpTimer -= 1; // Decrease by 1 each frame at 60fps if (self.powerUpTimer <= 0) { self.bulletType = 'normal'; self.setShootRate(50); // Reset shooting rate to default } } // Auto-shoot self.shoot(); }; return self; }); // Player bullet var PlayerBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 20; self.angle = 0; // 0 = straight, positive/negative for diagonal // Last position tracking for collision detection self.lastX = 0; self.lastY = 0; self.lastWasIntersecting = false; self.update = function () { self.lastX = self.x; self.lastY = self.y; // Move bullet based on angle using delta time var radians = self.angle * (Math.PI / 180); var frameRate = 60; // Base frame rate var speedMultiplier = LK.deltaTime * frameRate; // Adjust speed based on actual frame time self.x += Math.sin(radians) * self.speed * speedMultiplier; self.y -= Math.cos(radians) * self.speed * speedMultiplier; }; return self; }); // Power-up class var PowerUp = Container.expand(function () { var self = Container.call(this); // Start with a placeholder that will be replaced in init() var powerUpGraphics = self.attachAsset('doublePowerUp', { anchorX: 0.5, anchorY: 0.5 }); // Power-up properties self.type = 'double'; // double, triple self.speed = 2; //{2h} // Start with slower speed // Last position tracking for collision detection self.lastX = 0; self.lastY = 0; self.lastWasIntersecting = false; // Initialize power-up with type self.init = function (type) { self.type = type; // Remove existing graphics self.removeChild(powerUpGraphics); // Use appropriate image based on power-up type if (type === 'double') { powerUpGraphics = self.attachAsset('doublePowerUp', { anchorX: 0.5, anchorY: 0.5 }); } else if (type === 'triple') { powerUpGraphics = self.attachAsset('triplePowerUp', { anchorX: 0.5, anchorY: 0.5 }); } else if (type === 'fastShoot') { powerUpGraphics = self.attachAsset('fastShootPowerUp', { anchorX: 0.5, anchorY: 0.5 }); } // Add pulsating animation to the power-up function startPulseAnimation() { // Grow slightly tween(powerUpGraphics, { scaleX: 1.1, scaleY: 1.1 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { // Shrink back tween(powerUpGraphics, { scaleX: 0.9, scaleY: 0.9 }, { duration: 800, easing: tween.easeInOut, onFinish: startPulseAnimation }); } }); } // Start the animation startPulseAnimation(); }; // Update called every frame self.update = function () { self.lastX = self.x; self.lastY = self.y; // Move downward self.y += self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Function to update health display // Add deltaTime calculation if it's not provided by LK engine // Game variables // Background // Sounds // Power-ups // Environment and obstacles // Player, enemies and bullets // Import tween plugin function updateHealthDisplay() { // Clear existing health images for (var i = 0; i < healthImages.length; i++) { healthImages[i].destroy(); } healthImages = []; // Create new health images based on current health for (var i = 0; i < player.health; i++) { var heartImage = LK.getAsset('heart', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); // Position hearts at the top right with spacing heartImage.x = 1800 - i * 80; // Increased spacing to account for larger hearts heartImage.y = 80; game.addChild(heartImage); healthImages.push(heartImage); } } if (typeof LK.deltaTime === 'undefined') { LK.lastTime = Date.now(); LK.deltaTime = 1 / 60; // Default to 60fps LK.targetFPS = 60; // Update deltaTime before each frame LK.on('tick', function () { var now = Date.now(); LK.deltaTime = Math.min(0.1, (now - LK.lastTime) / 1000); // Cap at 0.1s to prevent huge jumps LK.lastTime = now; // Lock to 60fps if (LK.deltaTime < 1 / LK.targetFPS) { LK.deltaTime = 1 / LK.targetFPS; } }); } var player; var lanes = []; var lanePositions = [512, 1024, 1536]; // The three lanes X positions var playerBullets = []; var enemies = []; var enemyBullets = []; var barriers = []; var holes = []; // Array to track hole obstacles var powerUps = []; var backgroundTiles = []; var healthImages = []; var gameSpeed = 2; // Start with slower speed var difficulty = 0.5; // Start with lower difficulty var spawnTimer = 0; var barrierTimer = 0; var holeTimer = 0; // Timer for spawning holes var powerUpTimer = 0; var difficultyIncreaseRate = 0.05; // How fast difficulty increases var maxDifficulty = 6; // Cap on maximum difficulty // Touch tracking for swipe detection var touchStartX = null; var touchStartY = null; // Initialize the game elements function initGame() { // Play background music with loop LK.playMusic('bgMusic', { fade: { start: 0, end: 0.7, duration: 1000 } }); // Set up background var bgTileHeight = LK.getAsset('backgroundTile', {}).height; var numTilesNeeded = Math.ceil(2732 / bgTileHeight) + 1; // One extra for seamless scrolling for (var i = 0; i < numTilesNeeded; i++) { var bgTile = new BackgroundTile(); bgTile.x = 1024; // Center of screen bgTile.y = i * bgTileHeight; // Position tiles exactly adjacent to each other backgroundTiles.push(bgTile); game.addChild(bgTile); } // Create the lane markers for (var i = 0; i < 2; i++) { var lane = new Lane(); lane.x = lanePositions[i] + (lanePositions[1] - lanePositions[0]) / 2; // Position between lanes lane.y = 0; lane.alpha = 0.3; lanes.push(lane); game.addChild(lane); } // Create the player player = new Player(); player.x = lanePositions[1]; // Start in center lane player.y = 2732 - 300; // Near bottom of screen player.health = player.maxHealth; // Ensure health is set to maximum game.addChild(player); // Initialize score display var scoreBackground = game.addChild(LK.getAsset('scoreBackground', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 80, alpha: 0.7 })); var scoreTxt = new Text2('0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0.5); scoreTxt.x = 1024; scoreTxt.y = 80; game.addChild(scoreTxt); // Define updateHealthDisplay function in global scope function updateHealthDisplay() { // Clear existing health images for (var i = 0; i < healthImages.length; i++) { healthImages[i].destroy(); } healthImages = []; // Create new health images based on current health for (var i = 0; i < player.health; i++) { var heartImage = LK.getAsset('heart', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); // Position hearts at the top right with spacing heartImage.x = 1800 - i * 80; // Increased spacing to account for larger hearts heartImage.y = 80; game.addChild(heartImage); healthImages.push(heartImage); } } // Call updateHealthDisplay to initialize health display updateHealthDisplay(); // Update score display every second LK.setInterval(function () { scoreTxt.setText("SCORE: " + LK.getScore()); }, 1000); } // Spawn a new enemy with type based on difficulty function spawnEnemy() { // Check which lanes already have enemies var occupiedLanes = [false, false, false]; for (var i = 0; i < enemies.length; i++) { // Check if enemy is in any part of the visible screen (not just spawning area) // This ensures only one enemy per lane until it's off screen or dead occupiedLanes[enemies[i].lane] = true; } // Get available lanes var availableLanes = []; for (var i = 0; i < 3; i++) { if (!occupiedLanes[i]) { availableLanes.push(i); } } // If no lanes available, return without spawning if (availableLanes.length === 0) { return; } // Choose a random available lane var laneIndex = availableLanes[Math.floor(Math.random() * availableLanes.length)]; var enemyType = 'basic'; // Determine enemy type distribution based on current difficulty var typeRoll = Math.random(); if (difficulty < 2) { // Early game - mostly basic enemies (100%) enemyType = 'basic'; } else if (difficulty < 3) { // Mid game - introduce shooters (30% shooter, 70% basic) if (typeRoll < 0.3) { enemyType = 'shooter'; } } else if (difficulty < 4) { // Late-mid game - introduce tanks (20% shooter, 10% tank, 70% basic) if (typeRoll < 0.2) { enemyType = 'shooter'; } else if (typeRoll < 0.3) { enemyType = 'tank'; } } else { // Late game - more challenging mix (30% shooter, 15% tank, 55% basic) if (typeRoll < 0.3) { enemyType = 'shooter'; } else if (typeRoll < 0.45) { enemyType = 'tank'; } } var enemy = new Enemy(); enemy.init(enemyType, laneIndex); enemy.x = lanePositions[laneIndex]; enemy.y = -100; game.addChild(enemy); enemies.push(enemy); } // Spawn a barrier across all lanes function spawnBarrier() { // Check if there are any obstacles (holes, barriers or enemies) at the top of the screen var obstaclesNearTop = false; // Check holes near top for (var i = 0; i < holes.length; i++) { if (holes[i].y < 300) { obstaclesNearTop = true; break; } } // Check barriers near top for (var i = 0; i < barriers.length; i++) { if (barriers[i].y < 300) { obstaclesNearTop = true; break; } } // Check enemies near top for (var i = 0; i < enemies.length; i++) { if (enemies[i].y < 300) { obstaclesNearTop = true; break; } } // If there are obstacles near the top, don't spawn a barrier if (obstaclesNearTop) { return; } var barrier = new Barrier(); barrier.x = 1024; // Center of screen barrier.y = -100; game.addChild(barrier); barriers.push(barrier); } // Spawn a hole in a random lane function spawnHole() { // Check which lanes already have obstacles (holes, barriers or enemies) var occupiedLanes = [false, false, false]; // Check holes for (var i = 0; i < holes.length; i++) { // Find which lane this hole is in for (var j = 0; j < 3; j++) { if (Math.abs(holes[i].x - lanePositions[j]) < 50) { occupiedLanes[j] = true; break; } } } // Check barriers - they block all lanes if (barriers.length > 0) { for (var i = 0; i < barriers.length; i++) { if (barriers[i].y < 300) { // Only consider barriers near the top // Barriers block all lanes occupiedLanes = [true, true, true]; break; } } } // Get available lanes var availableLanes = []; for (var i = 0; i < 3; i++) { if (!occupiedLanes[i]) { availableLanes.push(i); } } // If no lanes available, return without spawning if (availableLanes.length === 0) { return; } // Choose a random available lane var laneIndex = availableLanes[Math.floor(Math.random() * availableLanes.length)]; var hole = new Hole(); hole.x = lanePositions[laneIndex]; hole.y = -100; hole.lane = laneIndex; // Track which lane this hole belongs to game.addChild(hole); holes.push(hole); } // Spawn a power-up function spawnPowerUp() { // Check which lanes already have obstacles (holes, barriers or enemies) var occupiedLanes = [false, false, false]; // Check holes for (var i = 0; i < holes.length; i++) { // Find which lane this hole is in for (var j = 0; j < 3; j++) { if (Math.abs(holes[i].x - lanePositions[j]) < 50 && holes[i].y < 300) { occupiedLanes[j] = true; break; } } } // Check enemies for (var i = 0; i < enemies.length; i++) { if (enemies[i].y < 300) { occupiedLanes[enemies[i].lane] = true; } } // Check barriers - they block all lanes for (var i = 0; i < barriers.length; i++) { if (barriers[i].y < 300) { occupiedLanes = [true, true, true]; break; } } // Get available lanes var availableLanes = []; for (var i = 0; i < 3; i++) { if (!occupiedLanes[i]) { availableLanes.push(i); } } // If no lanes available, return without spawning if (availableLanes.length === 0) { return; } // Choose a random available lane var laneIndex = availableLanes[Math.floor(Math.random() * availableLanes.length)]; var randomValue = Math.random(); var powerUpType; if (randomValue < 0.33) { powerUpType = 'double'; } else if (randomValue < 0.66) { powerUpType = 'triple'; } else { powerUpType = 'fastShoot'; // Add fast shoot power-up type } var powerUp = new PowerUp(); powerUp.init(powerUpType); powerUp.x = lanePositions[laneIndex]; powerUp.y = -100; powerUp.lane = laneIndex; // Track which lane this power-up belongs to game.addChild(powerUp); powerUps.push(powerUp); } // Increase difficulty over time function updateDifficulty() { // More gradual difficulty increase based on score var targetDifficulty = Math.min(maxDifficulty, 0.5 + LK.getScore() / 20); // Smooth difficulty transition instead of sudden jumps difficulty += (targetDifficulty - difficulty) * difficultyIncreaseRate; // Calculate game speed based on smoothed difficulty var targetSpeed = 2 + Math.min(difficulty, 4); gameSpeed += (targetSpeed - gameSpeed) * 0.05; // Update game elements with new speed for (var i = 0; i < backgroundTiles.length; i++) { backgroundTiles[i].speed = gameSpeed; } for (var i = 0; i < enemies.length; i++) { var speedModifier = enemies[i].type === 'basic' ? 1 : 0; var targetEnemySpeed = gameSpeed + speedModifier; enemies[i].speed = targetEnemySpeed; } for (var i = 0; i < barriers.length; i++) { barriers[i].speed = gameSpeed; } for (var i = 0; i < holes.length; i++) { holes[i].speed = gameSpeed; } for (var i = 0; i < powerUps.length; i++) { powerUps[i].speed = gameSpeed; } } // Handle touch input for lane changing game.down = function (x, y, obj) { // Store touch start position for swipe detection game.touchStartX = x; game.touchStartY = y; }; // Handle touch move events for swipe detection game.move = function (x, y, obj) { // Skip if no touch start position is recorded if (!game.touchStartX) { return; } }; // Handle touch up events for swipe detection game.up = function (x, y, obj) { // Skip if no touch start position is recorded if (!game.touchStartX) { return; } // Calculate horizontal distance moved var deltaX = x - game.touchStartX; var deltaY = y - game.touchStartY; // Only process horizontal swipes (ignore vertical) if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > 50) { if (deltaX < 0 && player.currentLane > 0) { // Swipe left - move to left lane player.moveTo(player.currentLane - 1); } else if (deltaX > 0 && player.currentLane < 2) { // Swipe right - move to right lane player.moveTo(player.currentLane + 1); } } // Reset touch start position game.touchStartX = null; game.touchStartY = null; }; // Main update function game.update = function () { // Initialize game on first update if (!player) { initGame(); return; } // Update player position based on current lane var targetX = lanePositions[player.currentLane]; player.x += (targetX - player.x) * 0.2; // Smooth movement // Update all game elements player.update(); // Update background tiles for (var i = 0; i < backgroundTiles.length; i++) { backgroundTiles[i].update(); } // Update and check player bullets for (var i = playerBullets.length - 1; i >= 0; i--) { var bullet = playerBullets[i]; bullet.update(); // Remove bullets that go off screen if (bullet.y < -50) { bullet.destroy(); playerBullets.splice(i, 1); continue; } // Check for collisions with enemies var hitEnemy = false; for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (!bullet.lastWasIntersecting && bullet.intersects(enemy)) { bullet.lastWasIntersecting = true; if (enemy.takeDamage()) { enemy.destroy(); enemies.splice(j, 1); } hitEnemy = true; break; } } // Check for collisions with barriers if (!hitEnemy) { for (var j = barriers.length - 1; j >= 0; j--) { var barrier = barriers[j]; if (!bullet.lastWasIntersecting && bullet.intersects(barrier)) { bullet.lastWasIntersecting = true; if (barrier.takeDamage()) { barrier.destroy(); barriers.splice(j, 1); } hitEnemy = true; break; } } } // Remove bullet if it hit something if (hitEnemy) { bullet.destroy(); playerBullets.splice(i, 1); } } // Update and check enemy bullets for (var i = enemyBullets.length - 1; i >= 0; i--) { var bullet = enemyBullets[i]; bullet.update(); // Remove bullets that go off screen if (bullet.y > 2732 + 50) { bullet.destroy(); enemyBullets.splice(i, 1); continue; } // Check for collision with player if (!bullet.lastWasIntersecting && bullet.intersects(player) && player.isAlive) { bullet.lastWasIntersecting = true; // Player hit by enemy bullet - use the takeDamage function player.takeDamage(); bullet.destroy(); enemyBullets.splice(i, 1); break; } } // Update and check enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; enemy.update(); // Remove enemies that go off screen if (enemy.y > 2732 + 100) { enemy.destroy(); enemies.splice(i, 1); continue; } // Check for collision with player if (!enemy.lastWasIntersecting && enemy.intersects(player) && player.isAlive) { enemy.lastWasIntersecting = true; // Player hit by enemy - use the takeDamage function player.takeDamage(); break; } } // Update and check barriers for (var i = barriers.length - 1; i >= 0; i--) { var barrier = barriers[i]; barrier.update(); // Remove barriers that go off screen if (barrier.y > 2732 + 100) { barrier.destroy(); barriers.splice(i, 1); continue; } // Check for collision with player if (!barrier.lastWasIntersecting && barrier.intersects(player) && player.isAlive) { barrier.lastWasIntersecting = true; // Player hit by barrier - use the takeDamage function player.takeDamage(); break; } } // Update and check holes for (var i = holes.length - 1; i >= 0; i--) { var hole = holes[i]; hole.update(); // Remove holes that go off screen if (hole.y > 2732 + 100) { hole.destroy(); holes.splice(i, 1); continue; } // Check for collision with player if (!hole.lastWasIntersecting && hole.intersects(player) && player.isAlive) { hole.lastWasIntersecting = true; // Player hit by hole - use the takeDamage function player.takeDamage(); break; } } // Check for player bullets hitting holes for (var i = playerBullets.length - 1; i >= 0; i--) { var bullet = playerBullets[i]; var hitHole = false; for (var j = holes.length - 1; j >= 0; j--) { var hole = holes[j]; if (!bullet.lastWasIntersecting && bullet.intersects(hole)) { bullet.lastWasIntersecting = true; if (hole.takeDamage()) { hole.destroy(); holes.splice(j, 1); } hitHole = true; break; } } // Remove bullet if it hit a hole if (hitHole) { bullet.destroy(); playerBullets.splice(i, 1); } } // Update and check power-ups for (var i = powerUps.length - 1; i >= 0; i--) { var powerUp = powerUps[i]; powerUp.update(); // Remove power-ups that go off screen if (powerUp.y > 2732 + 100) { powerUp.destroy(); powerUps.splice(i, 1); continue; } // Check for collision with player if (!powerUp.lastWasIntersecting && powerUp.intersects(player)) { powerUp.lastWasIntersecting = true; // Player got power-up player.activatePowerUp(powerUp.type); // Restore 1 health point when getting a power-up, up to max health if (player.health < player.maxHealth) { player.health++; // Update health display updateHealthDisplay(); } powerUp.destroy(); powerUps.splice(i, 1); } } // Function to manage spawn rates for different game elements function manageSpawnRates() { var frameStep = 60 * LK.deltaTime; // Update all spawn timers spawnTimer -= frameStep; barrierTimer -= frameStep; holeTimer -= frameStep; powerUpTimer -= frameStep; // Spawn enemies with rates dependent on difficulty if (spawnTimer <= 0) { spawnEnemy(); // Base spawn rate that changes with difficulty var baseEnemyRate = Math.max(60, 120 - difficulty * 8); // Adjust rate based on current difficulty level if (difficulty < 2) { // Early game - slower enemy spawns spawnTimer = baseEnemyRate * 1.2; } else if (difficulty < 4) { // Mid game - normal enemy spawns spawnTimer = baseEnemyRate; } else { // Late game - faster enemy spawns spawnTimer = baseEnemyRate * 0.8; } } // Spawn barriers with difficulty-based threshold if (barrierTimer <= 0) { // Different difficulty thresholds for barriers if (difficulty >= 0) { spawnBarrier(); // Adjust barrier spawn rate based on difficulty barrierTimer = Math.max(300, 400 - difficulty * 15); } else { // Reset timer without spawning if below threshold barrierTimer = 200; } } // Spawn holes with difficulty-based threshold if (holeTimer <= 0) { if (difficulty >= 0) { spawnHole(); // Adjust hole spawn rate based on difficulty holeTimer = Math.max(250, 350 - difficulty * 20); } else { // Reset timer without spawning if below threshold holeTimer = 150; } } // Spawn power-ups with variable timing if (powerUpTimer <= 0) { spawnPowerUp(); // Power-ups more frequent as game progresses but with a minimum interval powerUpTimer = Math.max(450, 600 + Math.max(0, 300 - difficulty * 50)); } } // Call the spawn rate manager manageSpawnRates(); // Update difficulty based on score updateDifficulty(); };
===================================================================
--- original.js
+++ change.js
@@ -653,12 +653,11 @@
function spawnEnemy() {
// Check which lanes already have enemies
var occupiedLanes = [false, false, false];
for (var i = 0; i < enemies.length; i++) {
- // Check if enemy is still in spawning area (top portion of screen)
- if (enemies[i].y < 300) {
- occupiedLanes[enemies[i].lane] = true;
- }
+ // Check if enemy is in any part of the visible screen (not just spawning area)
+ // This ensures only one enemy per lane until it's off screen or dead
+ occupiedLanes[enemies[i].lane] = true;
}
// Get available lanes
var availableLanes = [];
for (var i = 0; i < 3; i++) {
an 16bit 20x40 yellow bullet. In-Game asset. 2d. High contrast. No shadows
a tank from a top down view in realistic 16bit 90s retro game style. the tank should have its bazooka point straight forward, it should be seen from above so no wheels should be seen. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
make it redish like a ruby
make it so there are 2 bullets side by side
make it so that there are 3 bullets, the one on the left inclined diagonally to the left, the one in the middle forward and the one on the right inclined diagonally to the right
make it so that there are two bullets one above the other like this 2 dots, :
an 16bit 20x40 red heart. In-Game asset. 2d. High contrast. No shadows
make it just an round hole with spikes in it seen from above
create an simple retangular play button image writen "play" in it, make it in a 16bit style. In-Game asset. 2d. High contrast. No shadows
Create an title image written "Bullet Rush" in it, add some elements of war like bulets and make it in a semirealistic 16bit style. In-Game asset. 2d. High contrast. No shadows
make soldier laying in with belly up dead