User prompt
Track players high score ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Projectile move speed are slightly randomized
User prompt
Reduce the number of enemies
Code edit (1 edits merged)
Please save this source code
User prompt
Add additional enemy spawn patterns
User prompt
Add more color variations to enemy palette
User prompt
Use less intense colors for enemy palette
User prompt
Please fix the bug: 'TypeError: self.isFullyOnScreen is not a function. (In 'self.isFullyOnScreen()', 'self.isFullyOnScreen' is undefined)' in or related to this line: 'if (self.intersects(enemies[i]) && self.isFullyOnScreen()) {' Line Number: 56
User prompt
Enemies are invulnerable until their entire sprite is on the screen
User prompt
Please fix the bug: 'Can't find variable: getGameCodeContent' in or related to this line: 'github.push({' Line Number: 456
User prompt
Please fix the bug: 'Can't find variable: github' in or related to this line: 'github.push({' Line Number: 448
User prompt
Push code to a github repo
User prompt
Make a backup of existing code and assets
User prompt
Make player ship feel sluggish
User prompt
Still no limit on movement speed
User prompt
Still not working
User prompt
Check maxspeed before moving player
User prompt
Further limit player movement speed
Code edit (1 edits merged)
Please save this source code
User prompt
Fix bugs
User prompt
Limit player move speed
User prompt
Increase enemy tint brightness
User prompt
Increase tint opacity on enemies
User prompt
Ensure enemies return to original tint after taking damage
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0 }); /**** * Classes ****/ // Bullet class var Bullet = Container.expand(function () { var self = Container.call(this); // Attach the bullet sprite var bulletSprite = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); // Set bullet speed self.speed = -10 + Math.random() * 2 - 1; // Randomize speed slightly between -11 and -9 // This is automatically called every game tick, if the bullet is attached! self.update = function () { self.y += self.speed; // Destroy the bullet if it goes off the screen if (self.y < -self.height) { if (self.hitbox) { if (self.hitbox.hitboxGraphics) { self.hitbox.hitboxGraphics.destroy(); // Ensure hitbox graphics are removed when bullet is destroyed } self.hitbox.destroy(); // Ensure hitbox is removed when bullet is destroyed } self.destroy(); // Ensure bullet container is removed from the bullets array var index = bullets.indexOf(self); if (index > -1) { bullets.splice(index, 1); } } // Check for collision with enemies for (var i = 0; i < enemies.length; i++) { if (self.intersects(enemies[i]) && enemies[i].isFullyOnScreen()) { enemies[i].takeDamage(); if (self.hitbox) { if (self.hitbox.hitboxGraphics) { self.hitbox.hitboxGraphics.destroy(); // Ensure hitbox graphics are removed when bullet is destroyed upon collision } self.hitbox.destroy(); // Ensure hitbox is removed when bullet is destroyed upon collision } self.destroy(); break; } } }; }); // CityTiles class var CityTiles = Container.expand(function () { var self = Container.call(this); // Attach the city tiles sprite var cityTilesSprite = self.attachAsset('CityTiles', { anchorX: 0.5, anchorY: 0.5, scaleX: 4, scaleY: 4 }); // Set city tiles speed self.speed = 0.1; // This is automatically called every game tick, if the city tiles are attached! self.update = function () { self.y += self.speed; // Reset the position if the city tiles go off the screen if (self.y > 2732 + self.height / 2) { self.y = -self.height / 2; } }; }); // Cloud class var Cloud = Container.expand(function () { var self = Container.call(this); // Randomly assign cloud asset var cloudAssets = ['cloud1', 'cloud2', 'cloud3', 'cloud4', 'cloud5']; var randomCloud = cloudAssets.splice(Math.floor(Math.random() * cloudAssets.length), 1)[0]; var scale = Math.random() * 0.5 + 0.5; // Mirror cloud sprites 50% of the time var flipX = Math.random() > 0.5 ? -1 : 1; var cloudSprite = self.attachAsset(randomCloud, { anchorX: 0.5, anchorY: 0.5, scaleX: scale * flipX, scaleY: scale }); // Set cloud sprite to be 70% transparent cloudSprite.alpha = 0.1; // Set cloud speed self.speed = Math.random() * 3 + 2; // This is automatically called every game tick, if the cloud is attached! self.update = function () { self.y += self.speed * 2 * (1 + self.x / 2048 * 0.5); // Remove the cloud if it goes off the screen if (self.y > 2732 + self.height / 2) { // Remove the cloud from the clouds array var index = clouds.indexOf(self); if (index > -1) { clouds.splice(index, 1); } cloudAssets.push(randomCloud); // Add the cloud back to the cloudAssets array // Destroy the cloud self.destroy(); } }; }); // Enemy class var Enemy = Container.expand(function () { var self = Container.call(this); self.isFullyOnScreen = function () { return self.x - self.width / 2 >= 0 && self.x + self.width / 2 <= 2048 && self.y - self.height / 2 >= 0 && self.y + self.height / 2 <= 2732; }; // This is automatically called every game tick, if the enemy is attached! var enemyColors = [0xCC6666, 0x66CC66, 0x6666CC, 0xCCCC66, 0xCC66CC, 0x66CCCC, 0xCC9966, 0x99CC66, 0x6699CC, 0x9966CC]; // Define a more varied palette of colors var randomColor = enemyColors[Math.floor(Math.random() * enemyColors.length)]; // Randomly select a color var enemySprite = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5, tint: randomColor // Apply the random color as a tint }); // Create a hitbox for collision detection self.hitbox = new Container(); self.hitbox.width = enemySprite.width * 0.5; self.hitbox.height = enemySprite.height * 0.5; self.hitbox.x = -self.hitbox.width / 2; // Center the hitbox self.hitbox.y = -self.hitbox.height / 2; // Center the hitbox self.addChild(self.hitbox); // Draw the hitbox for visualization var hitboxGraphics = LK.getAsset('enemy', { width: self.hitbox.width, height: self.hitbox.height, color: 0xff0000, // Red color for hitbox shape: 'box' }); self.hitbox.hitboxGraphics = hitboxGraphics; self.hitbox.addChild(self.hitbox.hitboxGraphics); // Set enemy speed self.speed = 2; // Initialize hit points self.hitPoints = 3; // Method to handle enemy damage self.takeDamage = function () { self.hitPoints -= 1; // Flash enemy yellow when hit tween(self, { tint: 0xFFFF00 }, { duration: 100, easing: tween.linear, onFinish: function onFinish() { tween(self, { tint: randomColor // Return to original random color }, { duration: 100, easing: tween.linear }); } }); if (self.hitPoints <= 0) { if (self.hitbox) { self.hitbox.destroy(); // Ensure hitbox is removed when enemy is destroyed } self.destroy(); score += 10; // Increase score by 10 for each enemy destroyed if (typeof scoreTxt !== 'undefined') { scoreTxt.setText(score.toString()); // Update score display if (score > highScore) { highScore = score; storage.highScore = highScore; // Persist new high score } } // Ensure the enemy container is removed from the enemies array var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } } }; // This is automatically called every game tick, if the enemy is attached! self.update = function () { self.y += self.speed; if (typeof self.speedX !== 'undefined') { self.x += self.speedX; // Move horizontally if speedX is defined if (self.x < 0 || self.x > 2048) { self.speedX *= -1; // Reverse direction if hitting screen edge } } // Check for overlap with other enemies and adjust position for (var i = 0; i < enemies.length; i++) { if (enemies[i] !== self) { var dx = self.x - enemies[i].x; var dy = self.y - enemies[i].y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < self.width) { if (dx < 0) { self.x -= 1; // Move left to avoid overlap } else { self.x += 1; // Move right to avoid overlap } } } } // Implement dodging behavior if (typeof playerVehicle !== 'undefined') { if (self.x < playerVehicle.x && self.x < 2048 - self.width / 2) { self.x += 1; // Move right to dodge } else if (self.x > playerVehicle.x && self.x > self.width / 2) { self.x -= 1; // Move left to dodge } } // Destroy the enemy if it goes off the screen if (self.y > 2732 + self.height) { self.destroy(); } // Fire a projectile every 180 ticks if (typeof self.lastTick === 'undefined') { self.lastTick = LK.ticks; } if (LK.ticks % 180 === 0) { var projectile = new Projectile(); projectile.x = self.x; projectile.y = self.y + self.height / 2 + projectile.height / 2; game.addChild(projectile); self.lastTick = LK.ticks; } }; }); // PlayerLifeBar class var PlayerLifeBar = Container.expand(function () { var self = Container.call(this); // Create a background bar var backgroundBar = self.attachAsset('playerHealthBackground', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 1.0 }); backgroundBar.alpha = 0.5; // Set semi-transparency // Create an array to hold the life segments self.lifeSegments = []; for (var i = 0; i < 10; i++) { var lifeSegment = self.attachAsset('playerHealthBar', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, // Keep original scale for life segments scaleY: 1.0, color: 0x00ff00, // Green for life alpha: 0.5 // Set semi-transparency }); lifeSegment.x = (i - 4.5) * 100; // Position segments from left to right with 100px width self.lifeSegments.push(lifeSegment); } // Method to update the life bar based on player's hit points self.updateLife = function (hitPoints) { for (var i = 0; i < self.lifeSegments.length; i++) { self.lifeSegments[i].visible = i < hitPoints; // Show segments based on hit points } }; }); // Player's vehicle class var PlayerVehicle = Container.expand(function () { var self = Container.call(this); // Attach the player's vehicle sprite var vehicleSprite = self.attachAsset('playerVehicle', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2 }); // This is automatically called every game tick, if the player's vehicle is attached! self.update = function () { // Fire a bullet every 30 ticks if (LK.ticks % 30 == 0) { var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y - self.height / 2 - bullet.height / 2; game.addChild(bullet); bullets.push(bullet); } }; // Add touch event handlers to the player's vehicle to enable dragging self.down = function (x, y, obj) { // Store the initial touch position self.initialTouchPosition = { x: x, y: y }; // Store the initial position of the player's vehicle self.initialPosition = { x: self.x, y: self.y }; }; self.move = function (x, y, obj) { // Update the position of the player's vehicle relative to the speed and direction at which the player moves their finger // Calculate the intended movement var intendedX = self.initialPosition.x + (x - self.initialTouchPosition.x); var intendedY = self.initialPosition.y + (y - self.initialTouchPosition.y); // Calculate the distance to move var deltaX = intendedX - self.x; var deltaY = intendedY - self.y; // Calculate the speed limit var maxSpeed = 10; // Maximum speed per frame // Calculate the actual movement based on the speed limit var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance > maxSpeed) { var ratio = maxSpeed / distance; deltaX *= ratio; deltaY *= ratio; } // Update the position with the limited speed self.x += deltaX; self.y += deltaY; }; self.up = function (x, y, obj) { // Reset the initial touch position and the initial position of the player's vehicle self.initialTouchPosition = null; self.initialPosition = null; }; // Method to handle player damage self.hitPoints = 10; // Initialize player hit points self.takeDamage = function () { self.hitPoints -= 1; if (typeof playerLifeBar !== 'undefined') { playerLifeBar.updateLife(self.hitPoints); // Update the life bar if (self.hitPoints < playerLifeBar.lifeSegments.length) { playerLifeBar.lifeSegments[self.hitPoints].visible = false; // Hide the rightmost segment } } // Blink effect using tween tween(self, { alpha: 0.5 }, { duration: 100, easing: tween.linear, onFinish: function onFinish() { tween(self, { alpha: 1 }, { duration: 100, easing: tween.linear }); } }); if (self.hitPoints <= 0) { self.destroy(); // Destroy the player vehicle if hit points reach zero LK.showGameOver(); // Trigger game over when player health is depleted } }; }); // Projectile class var Projectile = Container.expand(function () { var self = Container.call(this); // Attach the projectile sprite var projectileSprite = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, // Keep original scale for sprite scaleY: 1.0, // Keep original scale for sprite width: 100, // Set sprite width to 100 height: 100 // Set sprite height to 100 }); // Create a hitbox for collision detection var hitbox = new Container(); hitbox.width = projectileSprite.width * 0.5; hitbox.height = projectileSprite.height * 0.5; hitbox.x = -hitbox.width / 2; // Center the hitbox hitbox.y = -hitbox.height / 2; // Center the hitbox self.addChild(hitbox); // Draw the hitbox for visualization var hitboxGraphics = LK.getAsset('projectile', { width: hitbox.width, height: hitbox.height, color: 0xff0000, // Red color for hitbox shape: 'box' }); hitbox.addChild(hitboxGraphics); // Set projectile speed self.speed = 5; // This is automatically called every game tick, if the projectile is attached! self.update = function () { if (self.lastX === undefined) { self.lastX = self.x; } if (self.lastY === undefined) { self.lastY = self.y; } self.y += self.speed; self.lastX = self.x; self.lastY = self.y; // Destroy the projectile if it goes off the screen if (self.y > 2732 + self.height / 2) { self.destroy(); } // Check for collision with player // Ensure playerVehicle is defined before checking intersection if (typeof playerVehicle !== 'undefined' && self.intersects(playerVehicle.hitbox)) { // Damage the player playerVehicle.takeDamage(); // Destroy the projectile self.destroy(); if (self.hitbox) { self.hitbox.destroy(); // Ensure hitbox is removed when projectile is destroyed if (self.hitbox.hitboxGraphics) { self.hitbox.hitboxGraphics.destroy(); // Ensure hitbox graphics are removed when projectile is destroyed } } } // Check for collision with bullets for (var i = 0; i < bullets.length; i++) { var dx = self.x - bullets[i].x; var dy = self.y - bullets[i].y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < self.width / 2 + bullets[i].width / 2) { // Allow bullets to pass through projectiles without being destroyed continue; } } }; }); /**** * Initialize Game ****/ // Add player's vehicle to the game var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Initialize score and display it at the top of the screen var score = 0; var highScore = storage.highScore || 0; var scoreTxt = new Text2(score.toString(), { size: 100, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); var highScoreTxt = new Text2("High Score: " + highScore.toString(), { size: 50, fill: 0xFFFFFF }); highScoreTxt.anchor.set(0.5, 0); highScoreTxt.y = scoreTxt.height; // Position below the score LK.gui.top.addChild(highScoreTxt); LK.gui.top.addChild(scoreTxt); // Create an array to store the bullets var bullets = []; // Create an array to store the enemies var enemies = []; // Create a timer to add enemies in waves var enemyWaveTimer = LK.setInterval(function () { // Add a wave of 3 enemies to reduce on-screen enemies for (var i = 0; i < 2; i++) { var enemy = game.addChild(new Enemy()); enemy.y = -enemy.height; enemy.x = (i + 1) * (2048 / 6); // Add the new enemy to the enemies array enemies.push(enemy); } // Add diagonal spawn pattern for (var i = 0; i < 2; i++) { var enemy = game.addChild(new Enemy()); enemy.y = -enemy.height - i * 100; // Staggered start positions enemy.x = i % 2 === 0 ? 0 : 2048; // Alternate starting from left and right enemy.speedX = i % 2 === 0 ? 1 : -1; // Move right if starting from left, left if starting from right enemies.push(enemy); } // Set a new random interval for the next wave LK.clearInterval(enemyWaveTimer); enemyWaveTimer = LK.setInterval(arguments.callee, Math.random() * 2000 + 4000); // Random interval between 4 and 6 seconds }, Math.random() * 2000 + 4000); // Initial random interval between 4 and 6 seconds // Increase enemy speed and spawn rate every time score reaches a multiple of 200 if (score % 200 === 0 && score !== 0) { enemies.forEach(function (enemy) { enemy.speed += 0.5; // Increase enemy speed }); LK.clearInterval(enemyWaveTimer); enemyWaveTimer = LK.setInterval(function () { for (var i = 0; i < 3; i++) { var enemy = game.addChild(new Enemy()); enemy.y = -enemy.height; enemy.x = (i + 1) * (2048 / 6); enemies.push(enemy); } // Add zigzag spawn pattern for (var i = 0; i < 2; i++) { var enemy = game.addChild(new Enemy()); enemy.y = -enemy.height; enemy.x = i % 2 === 0 ? 0 : 2048; // Start from left or right enemy.speedX = i % 2 === 0 ? 2 : -2; // Move in zigzag pattern enemies.push(enemy); } }, Math.max(1000, 5000 - score / 200 * 500)); // Decrease interval time } // Add CityTiles to the game and repeat to fill the screen horizontally var cityTilesArray = []; for (var i = 0; i < Math.ceil(2048 / 804) + 1; i++) { // 804 is the new width of a single CityTile for (var j = 0; j < Math.ceil(2732 / 804) + 1; j++) { // 804 is the new height of a single CityTile var cityTile = game.addChild(new CityTiles()); cityTile.x = i * 804 - 402; // Adjust position for seamless tiling cityTile.y = j * 804 - 402; // Adjust position for seamless tiling cityTilesArray.push(cityTile); } } // Add player's vehicle to the game var playerVehicle = game.addChild(new PlayerVehicle()); playerVehicle.hitbox = new Container(); playerVehicle.hitbox.width = playerVehicle.width * 0.5; // Define hitbox size playerVehicle.hitbox.height = playerVehicle.height * 0.5; // Define hitbox size playerVehicle.hitbox.x = -playerVehicle.hitbox.width / 2; // Center the hitbox playerVehicle.hitbox.y = -playerVehicle.hitbox.height / 2; // Center the hitbox playerVehicle.addChild(playerVehicle.hitbox); // Draw the hitbox for visualization var playerHitboxGraphics = LK.getAsset('playerHitbox', { width: playerVehicle.hitbox.width, height: playerVehicle.hitbox.height, color: 0x00ff00, // Green color for hitbox shape: 'box' }); playerVehicle.hitbox.addChild(playerHitboxGraphics); playerVehicle.x = 2048 / 2; playerVehicle.y = 2732 - playerVehicle.height / 2; // Add player's life bar to the game var playerLifeBar = game.addChild(new PlayerLifeBar()); playerLifeBar.x = playerLifeBar.width / 2 + 10; // Position the life bar at the lower left corner with a 10 pixel margin playerLifeBar.y = 2732 - playerLifeBar.height / 2 - 10; // Adjust y position to be at the bottom with a 10 pixel margin var dragNode = null; game.down = function (x, y, obj) { dragNode = playerVehicle; dragNode.initialTouchPosition = { x: x, y: y }; dragNode.initialPosition = { x: playerVehicle.x, y: playerVehicle.y }; }; game.move = function (x, y, obj) { if (dragNode && typeof playerVehicle !== 'undefined') { var newX = dragNode.initialPosition.x + (x - dragNode.initialTouchPosition.x); var newY = dragNode.initialPosition.y + (y - dragNode.initialTouchPosition.y); // Limit player vehicle movement to within the screen newX = Math.max(Math.min(newX, 2048 - dragNode.width / 2), dragNode.width / 2); newY = Math.max(Math.min(newY, 2732 - dragNode.height / 2), dragNode.height / 2); dragNode.x = newX; dragNode.y = newY; } }; game.up = function (x, y, obj) { if (dragNode) { dragNode = null; } }; // Create an array to store the clouds var clouds = []; // Create a timer to add clouds at random intervals between 1 and 5 seconds var cloudTimer = LK.setInterval(function () { // Check if there are less than 4 clouds on screen if (clouds.length < 4) { var cloud = game.addChild(new Cloud()); cloud.y = -cloud.height; cloud.x = Math.random() * 2048; // Add the new cloud to the clouds array clouds.push(cloud); } }, Math.random() * 4000 + 1000);
===================================================================
--- original.js
+++ change.js
@@ -1,8 +1,11 @@
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ highScore: 0
+});
/****
* Classes
****/
@@ -166,8 +169,12 @@
self.destroy();
score += 10; // Increase score by 10 for each enemy destroyed
if (typeof scoreTxt !== 'undefined') {
scoreTxt.setText(score.toString()); // Update score display
+ if (score > highScore) {
+ highScore = score;
+ storage.highScore = highScore; // Persist new high score
+ }
}
// Ensure the enemy container is removed from the enemies array
var index = enemies.indexOf(self);
if (index > -1) {
@@ -436,13 +443,21 @@
* Game Code
****/
// Initialize score and display it at the top of the screen
var score = 0;
+var highScore = storage.highScore || 0;
var scoreTxt = new Text2(score.toString(), {
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
+var highScoreTxt = new Text2("High Score: " + highScore.toString(), {
+ size: 50,
+ fill: 0xFFFFFF
+});
+highScoreTxt.anchor.set(0.5, 0);
+highScoreTxt.y = scoreTxt.height; // Position below the score
+LK.gui.top.addChild(highScoreTxt);
LK.gui.top.addChild(scoreTxt);
// Create an array to store the bullets
var bullets = [];
// Create an array to store the enemies
Neon cyberpunk flying car. Single Game Texture. Blank background. High contrast. No shadows. Top-down
Fluffy cloud viewed from the top. Single Game Sprite Texture. No background.
This type of cloud but in a fine mist
One single Fluffy cloud viewed from the top. Single Game Sprite. No background. No shadow
Mini rocket projectile from a video game. No background.
Terminator style 2D enemy ship. Facing dead south. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Circular ball projectile from a video game. No background.
Make it look like night time