User prompt
right now you only play the Pop_1 sound when an enemy is destroyed. when an enemy explodes, instead of just playing the sound Pop_1, play a random sound between Pop_1 to Pop_3. Create a weighting mechanism so once one of the sounds has played, exclude it from the list, so that the reamining ones play. after all sounds from the list played, refill the list, reset the list and pick a random one. this applies to when an enemies dies from both bullets or explosions from other enemies
User prompt
right now you only play the Pop_1 sound when an enemy is destroyed. when an enemy explodes, instead of just playing the sound Pop_1, play a random sound between Pop_1 to Pop_3. Create a weighting mechanism so once one of the sounds has played, exclude it from the list, so that the reamining ones play. after all sounds from the list played, refill the list, reset the list and pick a random one. so make sure the same sound dowsn't play consecutively one after the other
User prompt
right now you only play the Pop_1 sound when an enemy is destroyed. when an enemy explodes, instead of just playing the sound Pop_1, play a random sound between Pop_1 to Pop_3. Create a weighting mechanism so once one of the sounds has played, exclude it from the list, so that the reamining ones play. after all sounds from the list played, refill the list, reset the list and pick a random one
User prompt
when an enemy explodes, instead of just playing the sound Pop_1, play a random sound between Pop_1 to Pop_3. Create a weighting mechanism so once one of the sounds has played, exclude it from the list, so that the reamining ones play. after all sounds from the list played, refill the list, reset the list and pick a random one
User prompt
improve the collision system between the player and the enemy
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'foregroundContainer.addChild(musical);' Line Number: 305
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'foregroundContainer.addChild(musical);' Line Number: 305
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'foregroundContainer.addChild(musical);' Line Number: 305
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'foregroundContainer.addChild(musical);' Line Number: 305
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'foregroundContainer.addChild(musical);' Line Number: 305
User prompt
attach the musical asset in the foregroundcontainer. at the start of the game, position the Musical asset in the center of the screen. it needs to have a size of 1 pixel. this asset needs to grow to it's full size over a period of 10 seconds. when it hits any of the screen edges, estroy it and repeat this process. basically creatin it again at the size of 1 pixel and start growing it again.
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'var musical = midgroundContainer.addChild(new Musical());' Line Number: 310
User prompt
at the start of the game, position the Musical asset in the center of the screen. it needs to have a size of 1 pixel. this asset needs to grow to it's full size over a period of 10 seconds. when it hits any of the screen edges, estroy it and repeat this process. basically creatin it again at the size of 1 pixel and start growing it again.
User prompt
Create a new class called "MusicController". In the MusicController class, define an asset named "Musical". Position the "Musical" asset at the center of the screen with an initial size of 1 pixel by 1 pixel. Implement a mechanism to gradually expand the size of the "Musical" asset over 10 seconds. Track the size of the "Musical" asset, and when its dimensions match or exceed the screen size, destroy the asset. Immediately after destroying the "Musical" asset, create a new one with the initial size of 1 pixel by 1 pixel, positioned at the center of the screen. Ensure the MusicController class's update method is called in the game's main update loop to handle the expansion and resetting logic.
User prompt
create a new class for the Musical asset named MusicController. This asset starts at the center of the screen as a 1 pixel dot, and over the course of 10 seconds grows to the size of the screen. when any of it's sides touches any edges of the screen, destroy it. on tick check if the Musical is still on the screen, if not create it again and start expending it again. this loops indefinitely. so the cycle is, start as a 1 pixel dot, grow over 10 seconds, when it hits the edges of the screen destroy it, and when destroyed grow it again from the size of a pixel
User prompt
the musical assets needs to shrink down to the size of a pixel over a period of 10 seconds. after 10 seconds have elapsed, destroy the musical asset and generate a new one. as soon as this one is generated, it also needs to shrink down over a period of 10 seconds. repeat this process infinitely. add a flag to the creation of the Musical asset to ensure only one is created at a time
User prompt
the second generated musical asset is not destroyed by the enemy, and I think it also keeps generating multiple ones. just generate a single one asset which can be destroyed by enemies
User prompt
when an enemy touches the Musical asset, destroy the Musical asset and start a 10 seconds timer. after 10 seconds, spawn a new Musical asset
User prompt
when an enemy touches the Musical asset, destroy it and start a 10 seconds timer. after 10 seconds, spawn a new Musical asset
User prompt
create a new asset named Musical and place it in the Foreground container
User prompt
create a new asset named MusicController
User prompt
create a new class named SoundController. this class contains a timer that runs for 10 seconds then it's destroyed. as soon as it's destroyed, create a new timer which runs for another 10 seconds. this repeats indefinitely. when this timer is generated, play the Music sound. this is initialized at the start of the game
User prompt
Create a new class within the Game Code, called "SoundManager". In the SoundManager class, initialize a variable called soundTimer and set its initial value to 0. In the game’s main update loop, call a method within the SoundManager class that updates the soundTimer. This method should increment soundTimer by the time elapsed since the last tick. Create a method within the SoundManager class that checks if soundTimer has reached or exceeded 10 seconds. If soundTimer is greater than or equal to 10 seconds, stop the playback of "Music". Immediately after stopping the sound, reset soundTimer to 0 and restart the playback of "Music". Ensure the SoundManager class is instantiated and its update method is called within the game’s main update loop.
User prompt
play the Music sound when the game starts
/****
* Classes
****/
// Ammo class
var Ammo = Container.expand(function () {
var self = Container.call(this);
var ammoGraphics = self.attachAsset('ammo', {
anchorX: 0.5,
anchorY: 0.5
});
});
// Define constants for ammo UI positioning and spacing
// AmmoUI class
var AmmoUI = Container.expand(function () {
var self = Container.call(this);
self.ammoCount = 10;
self.ammoDisplay = [];
self.init = function () {
for (var i = 0; i < self.ammoCount; i++) {
var ammo = new Ammo();
ammo.x = AMMO_X_POSITION; // Position to the left
ammo.y = AMMO_Y_START_POSITION - i * (AMMO_SPACING + 30); // Increase gap between ammo units
ammo.alpha = 1;
self.ammoDisplay.push(ammo);
self.addChild(ammo);
}
};
self.decreaseAmmo = function () {
if (self.ammoCount > 0) {
self.ammoCount--;
self.updateAmmoAlpha();
}
};
self.increaseAmmo = function () {
if (self.ammoCount < 10) {
self.ammoCount++;
self.updateAmmoAlpha();
}
};
self.updateAmmoAlpha = function () {
for (var i = 0; i < self.ammoDisplay.length; i++) {
self.ammoDisplay[i].alpha = i < self.ammoCount ? 1 : 0.5;
}
};
self.init();
});
// BackgroundContainer class
var BackgroundContainer = Container.expand(function () {
var self = Container.call(this);
});
//<Assets used in the game will automatically appear here>
// Bullet class
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 20;
self.direction = {
x: 0,
y: -1
}; // Default direction
self.targetedEnemy = null; // Add a flag to store the targeted enemy
self.update = function () {
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
};
});
// Enemy class
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1;
self.acceleration = 0.005; // Decrease acceleration property
self.scoreIncreased = false; // Add a flag to check if the score has been increased
self.fullyInsideScreen = false; // Add a flag to check if the enemy is fully inside the screen
// Add animation frames
var frame1 = enemyGraphics;
var frame2 = LK.getAsset('obstacle_2', {
anchorX: 0.5,
anchorY: 0.5
});
var currentFrame = 1;
var lastFrameChange = Date.now();
self.update = function () {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.speed) {
self.speed += self.acceleration; // Increase speed by acceleration
self.x += dx * self.speed / distance;
self.y += dy * self.speed / distance;
self.fullyInsideScreen = self.x >= 0 && self.x <= 2048 && self.y >= 0 && self.y <= 2732;
}
// Magnetic attraction and repulsion between enemies
for (var i = 0; i < enemySpawners.length; i++) {
if (enemySpawners[i] !== self) {
var otherEnemy = enemySpawners[i];
var dxEnemy = otherEnemy.x - self.x;
var dyEnemy = otherEnemy.y - self.y;
var distanceEnemy = Math.sqrt(dxEnemy * dxEnemy + dyEnemy * dyEnemy);
if (distanceEnemy < 200) {
// Magnetic attraction
var attractionForce = 0.1; // Adjust this value to control the attraction speed
self.x += dxEnemy / distanceEnemy * attractionForce;
self.y += dyEnemy / distanceEnemy * attractionForce;
otherEnemy.x -= dxEnemy / distanceEnemy * attractionForce;
otherEnemy.y -= dyEnemy / distanceEnemy * attractionForce;
}
if (distanceEnemy < 150) {
// Repel overlapping enemies
var repelForce = 1; // Adjust this value to control the repelling speed
self.x -= dxEnemy / distanceEnemy * repelForce;
self.y -= dyEnemy / distanceEnemy * repelForce;
otherEnemy.x += dxEnemy / distanceEnemy * repelForce;
otherEnemy.y += dyEnemy / distanceEnemy * repelForce;
}
}
}
// Handle frame animation
if (Date.now() - lastFrameChange >= 100) {
if (currentFrame === 1) {
self.removeChild(frame1);
self.addChild(frame2);
currentFrame = 2;
} else {
self.removeChild(frame2);
self.addChild(frame1);
currentFrame = 1;
}
lastFrameChange = Date.now();
}
};
});
// Explosion class
var Explosion = Container.expand(function () {
var self = Container.call(this);
var explosionGraphics = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.01,
scaleY: 0.01
});
self.expandTime = 120; // 200 milliseconds
self.startTime = Date.now();
self.hitboxIntersects = function (target) {
var selfBounds = self.getBounds();
var targetBounds = target.getBounds();
return selfBounds.x < targetBounds.x + targetBounds.width && selfBounds.x + selfBounds.width > targetBounds.x && selfBounds.y < targetBounds.y + targetBounds.height && selfBounds.y + selfBounds.height > targetBounds.y;
};
self.update = function () {
var elapsedTime = Date.now() - self.startTime;
var scale = Math.min(1, elapsedTime / self.expandTime);
explosionGraphics.scale.set(scale, scale);
if (scale >= 1) {
// Check for collisions with enemies
for (var i = enemySpawners.length - 1; i >= 0; i--) {
if (self.hitboxIntersects(enemySpawners[i]) && enemySpawners[i].fullyInsideScreen) {
var newExplosion = new Explosion();
newExplosion.x = enemySpawners[i].x;
newExplosion.y = enemySpawners[i].y;
midgroundContainer.addChild(newExplosion);
if (!enemySpawners[i].scoreIncreased) {
increaseScore(1, 1.1);
enemySpawners[i].scoreIncreased = true;
}
LK.getSound('Pop_1').play();
enemySpawners[i].destroy();
enemySpawners.splice(i, 1);
}
}
increaseScore(1, 1.2);
self.destroy();
}
};
});
// ForegroundContainer class
var ForegroundContainer = Container.expand(function () {
var self = Container.call(this);
});
// MidgroundContainer class
var MidgroundContainer = Container.expand(function () {
var self = Container.call(this);
});
// Obstacle class
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5;
self.update = function () {
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
};
});
// Player class
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.shoot = function () {
var newBullet = new Bullet();
newBullet.x = self.x;
newBullet.y = self.y;
// Find the closest enemy that hasn't been targeted
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemySpawners.length; i++) {
// Check if the enemy is within the screen bounds
if (enemySpawners[i].x < 0 || enemySpawners[i].x > 2048 || enemySpawners[i].y < 0 || enemySpawners[i].y > 2732) {
continue; // Skip enemies outside the screen area
}
var alreadyTargeted = bullets.some(function (bullet) {
return bullet.targetedEnemy === enemySpawners[i];
});
if (alreadyTargeted) {
continue; // Skip already targeted enemies
}
var distance = Math.sqrt(Math.pow(enemySpawners[i].x - self.x, 2) + Math.pow(enemySpawners[i].y - self.y, 2));
if (distance < closestDistance) {
closestEnemy = enemySpawners[i];
closestDistance = distance;
}
}
if (closestEnemy === null) {
return; // No enemies to target
}
if (ammoUI.ammoCount <= 0) {
console.log("Out of ammo!");
return; // Out of ammo
}
ammoUI.decreaseAmmo();
// Set the bullet's direction towards the closest enemy
var dx = closestEnemy.x - self.x;
var dy = closestEnemy.y - self.y;
var magnitude = Math.sqrt(dx * dx + dy * dy);
newBullet.direction = {
x: dx / magnitude,
y: dy / magnitude
};
newBullet.targetedEnemy = closestEnemy; // Mark the enemy as targeted
bullets.push(newBullet);
midgroundContainer.addChild(newBullet);
LK.getSound('Shoot').play();
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x7cc3ca //Init game with new background color
});
/****
* Game Code
****/
// Define constants for ammo UI positioning and spacing
// Play the Music sound when the game starts
LK.getSound('Music').play();
// Initialize arrays and variables
function increaseScore(points, scale) {
LK.setScore(LK.getScore() + points);
scoreTxt.setText(LK.getScore());
scoreTxt.scale.set(scale, scale); // Increase the size of the score text
LK.setTimeout(function () {
scoreTxt.scale.set(1, 1); // Reset the size of the score text after a short delay
}, 50);
}
var AMMO_X_POSITION = 70;
var AMMO_Y_START_POSITION = 2732 - 60;
var AMMO_SPACING = 80;
var AMMO_PADDING_X = 300;
var AMMO_PADDING_Y = 400;
var AMMO_SPAWN_WIDTH = 2048 - 1200;
var AMMO_SPAWN_HEIGHT = 2732 - 1600;
var AMMO_MIN_DISTANCE = 700;
var bullets = [];
var obstacles = [];
var enemySpawners = [];
var ammos = [];
var backgroundContainer = game.addChild(new BackgroundContainer());
var background = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1,
scaleY: 1,
x: 2048 / 2,
y: 2732
});
backgroundContainer.addChild(background);
var midgroundContainer = game.addChild(new MidgroundContainer());
var foregroundContainer = game.addChild(new ForegroundContainer());
var ammoUI = foregroundContainer.addChild(new AmmoUI());
var player = foregroundContainer.addChild(new Player());
player.x = 2048 / 2;
player.y = 2732 - 200;
for (var i = 0; i < bullets.length; i++) {
midgroundContainer.addChild(bullets[i]);
}
for (var i = 0; i < enemySpawners.length; i++) {
midgroundContainer.addChild(enemySpawners[i]);
}
var scoreTxt = new Text2('0', {
size: 150,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 15
});
scoreTxt.anchor.set(0.5, 0.5);
scoreTxt.y += 100;
LK.gui.top.addChild(scoreTxt);
// Handle touch down event
game.down = function (x, y, obj) {
player.shoot();
};
// Update game state
game.update = function () {
// Player moves towards the oldest Ammo
if (ammos.length > 0) {
var oldestAmmo = ammos[0]; // The oldest ammo is the first one in the array
var dx = oldestAmmo.x - player.x;
var dy = oldestAmmo.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var speed = 10;
if (distance > speed) {
player.x += dx * speed / distance;
player.y += dy * speed / distance;
if (dx > 0) {
player.scale.x = -1; // Flip the player asset on x-axis when moving right
} else {
player.scale.x = 1; // Revert the player asset on x-axis when moving left
}
}
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
bullets[i].update();
if (bullets[i].y < -50) {
bullets[i].destroy();
bullets.splice(i, 1);
}
}
// Update obstacles
for (var j = obstacles.length - 1; j >= 0; j--) {
obstacles[j].update();
if (obstacles[j].y > 2732 + 50) {
obstacles[j].destroy();
obstacles.splice(j, 1);
}
}
// Update explosions
for (var e = midgroundContainer.children.length - 1; e >= 0; e--) {
if (midgroundContainer.children[e] instanceof Explosion) {
midgroundContainer.children[e].update();
}
}
// Check for collisions
for (var k = bullets.length - 1; k >= 0; k--) {
for (var l = enemySpawners.length - 1; l >= 0; l--) {
// Check if the enemy is within the screen bounds
if (enemySpawners[l].x >= 0 && enemySpawners[l].x <= 2048 && enemySpawners[l].y >= 0 && enemySpawners[l].y <= 2732 && bullets[k].intersects(enemySpawners[l])) {
bullets[k].destroy();
var explosion = new Explosion();
explosion.x = enemySpawners[l].x;
explosion.y = enemySpawners[l].y;
foregroundContainer.addChild(explosion);
LK.getSound('Pop_1').play();
enemySpawners[l].destroy();
bullets.splice(k, 1);
enemySpawners.splice(l, 1);
// Score update removed from bullet collision
break;
}
}
}
// Spawn new enemy spawners
if (LK.ticks % Math.max(10, 40 - Math.floor(LK.getScore() * 0.2)) == 0) {
var newEnemy = new Enemy();
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
// Top edge
newEnemy.x = Math.random() * 2048;
newEnemy.y = -50;
break;
case 1:
// Right edge
newEnemy.x = 2048 + 50;
newEnemy.y = Math.random() * 2732;
break;
case 2:
// Bottom edge
newEnemy.x = Math.random() * 2048;
newEnemy.y = 2732 + 50;
break;
case 3:
// Left edge
newEnemy.x = -50;
newEnemy.y = Math.random() * 2732;
break;
}
enemySpawners.push(newEnemy);
midgroundContainer.addChild(newEnemy);
}
// Generate new ammo to maintain 2 on the screen
if (ammos.length < 2) {
while (ammos.length < 2) {
var newAmmo = new Ammo();
var validPosition = false;
while (!validPosition) {
newAmmo.x = AMMO_PADDING_X + Math.random() * (2048 - 2 * AMMO_PADDING_X);
newAmmo.y = AMMO_PADDING_Y + Math.random() * (2732 - 2 * AMMO_PADDING_Y);
validPosition = true;
for (var i = 0; i < ammos.length; i++) {
var dx = newAmmo.x - ammos[i].x;
var dy = newAmmo.y - ammos[i].y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < AMMO_MIN_DISTANCE) {
validPosition = false;
break;
}
}
}
ammos.push(newAmmo);
foregroundContainer.addChild(newAmmo);
}
}
// Check for game over
for (var m = obstacles.length - 1; m >= 0; m--) {
if (obstacles[m].intersects(player)) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
}
for (var n = enemySpawners.length - 1; n >= 0; n--) {
if (enemySpawners[n].intersects(player)) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
}
// Check for Ammo collection
for (var n = ammos.length - 1; n >= 0; n--) {
if (ammos[n].intersects(player)) {
LK.getSound('Ammo').play(); // Play Ammo sound
ammos[n].destroy();
ammos.splice(n, 1);
ammoUI.increaseAmmo();
// Determine direction to the next ammo
if (ammos.length > 0) {
var nextAmmo = ammos[0];
var dx = nextAmmo.x - player.x;
if (dx > 0) {
player.scale.x = -1; // Flip the player asset on x-axis when moving right
} else {
player.scale.x = 1; // Revert the player asset on x-axis when moving left
}
}
// Generate new ammo to maintain 3 on the screen
var newAmmo = new Ammo();
var validPosition = false;
while (!validPosition) {
newAmmo.x = AMMO_PADDING_X + Math.random() * (2048 - 2 * AMMO_PADDING_X);
newAmmo.y = AMMO_PADDING_Y + Math.random() * (2732 - 2 * AMMO_PADDING_Y);
validPosition = true;
for (var i = 0; i < ammos.length; i++) {
var dx = newAmmo.x - ammos[i].x;
var dy = newAmmo.y - ammos[i].y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 400) {
validPosition = false;
break;
}
}
}
ammos.push(newAmmo);
midgroundContainer.addChild(newAmmo);
}
}
};
8-bit pixelated isometric cute watermelon with a rotor above. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
8-bit pixelated radial watermelon red juice explosion splash. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
8-bit pixelated isometric blueberry-shaped UFO with a cute fruit inside. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
8-bit pixelated isometric blueberry projectile. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
8-bit pixelated isometric blueberry projectile icon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Create a minimal and stylized 8-bit pixelated background of an alien village made of pineapple-shaped huts, viewed from a distance so the buildings appear small and occupy a small lower part of the background. The sky should be light blue and occupy the majority of the image, with the huts constructed from various fruits and having primitive shapes. Use a softer color palette to ensure the background does not distract from the main game elements, capturing the essence of classic 8-bit era video games. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.