User prompt
it doesntttttt
User prompt
Fix health bar initialization to ensure it's green at the start
User prompt
bug : tha bar is not green
User prompt
Update player health bar initialization to show full health at start
User prompt
when starting, the bar should be fully green
User prompt
make that player is full health while starting the game and he have 3 stats of health : Green (full) yellow and red, after red he dies and when player obteins a heart, his health changes to the next stat ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
when we start, the health bar should be full and green and when we touch a laser we loose health and when no health it's game over
User prompt
remove shields after using them
User prompt
make less enemies spawn on a wave
User prompt
make player shoot less lasers per sec
User prompt
add a health bar on the player and a heart that restore a part of the health, it can be obtained while killing a boss
User prompt
bug : level 16-30 should be the enemyCat2 not enemyCat
User prompt
1-15 was GrumpyCat, 16-30 is Maxwell (enemyCat2) and new bosses r boss2. Make 16-30 levels harder than 1-15
User prompt
make the game harder
User prompt
make that boss move slowly to players position and make it throw less lasers
User prompt
make that some enemies throw lasers and boss too and make the first boss has 50 HP and the last one 100HP ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
bug : some enemies doesnt fall
User prompt
When boss comes, play boss music
Code edit (1 edits merged)
Please save this source code
User prompt
Meme Cat Invasion
Initial prompt
Game Title: Meme Cat Invasion Description: A hilarious and slightly terrifying game where you fend off an army of meme cats threatening to take over the world. Can you stop them before it’s too late?
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemyCat', { anchorX: 0.5, anchorY: 0.5 }); self.type = 'basic'; self.health = 1; self.speed = 2; self.pointValue = 10; self.isActive = true; self.movePattern = 'straight'; self.movementTime = 0; self.direction = 1; // 1 right, -1 left self.update = function () { if (self.isActive) { self.movementTime++; // Move based on pattern if (self.movePattern === 'straight') { self.y += self.speed; } else if (self.movePattern === 'zigzag') { self.y += self.speed; self.x += Math.sin(self.movementTime * 0.05) * 3; } else if (self.movePattern === 'teleport') { // Always move down self.y += self.speed; // And occasionally teleport horizontally if (self.movementTime % 120 === 0) { // Teleport every 2 seconds self.x = 100 + Math.random() * (2048 - 200); LK.effects.flashObject(self, 0xffffff, 300); } } // Advanced enemies occasionally shoot lasers if ((self.type === 'zigzag' || self.type === 'teleport') && Math.random() < 0.005) { var laser = new EnemyLaser(); laser.x = self.x; laser.y = self.y + 30; enemyLasers.push(laser); game.addChild(laser); } // Remove enemy when it goes off screen if (self.y > 2732 + 50) { self.isActive = false; } } }; self.takeDamage = function (damage) { self.health -= damage; // Flash the enemy red when hit LK.effects.flashObject(self, 0xff0000, 300); if (self.health <= 0) { // Play explosion sound LK.getSound('explosion').play(); // Chance to drop power-up (15%) if (Math.random() < 0.15) { var powerUp = new PowerUp(); powerUp.x = self.x; powerUp.y = self.y; // Randomly choose power-up type var powerType = Math.random(); if (powerType < 0.5) { powerUp.setType('spreadshot'); } else if (powerType < 0.8) { powerUp.setType('shield'); } else { powerUp.setType('bomb'); } powerUps.push(powerUp); game.addChild(powerUp); } self.isActive = false; } }; self.setType = function (newType) { self.type = newType; if (newType === 'basic') { enemyGraphics.tint = 0xffcc00; self.health = 1; self.speed = 2; self.pointValue = 10; self.movePattern = 'straight'; } else if (newType === 'fast') { enemyGraphics.tint = 0xff9900; self.health = 1; self.speed = 4; self.pointValue = 15; self.movePattern = 'straight'; } else if (newType === 'zigzag') { enemyGraphics.tint = 0x66cc00; self.health = 2; self.speed = 2; self.pointValue = 20; self.movePattern = 'zigzag'; } else if (newType === 'teleport') { enemyGraphics.tint = 0xcc33ff; self.health = 2; self.speed = 1.5; self.pointValue = 30; self.movePattern = 'teleport'; } }; return self; }); var BossCat = Enemy.expand(function () { var self = Enemy.call(this); // Remove the previous graphic and add boss graphic self.removeChildren(); var bossGraphics = self.attachAsset('bossCat', { anchorX: 0.5, anchorY: 0.5 }); self.type = 'boss'; self.health = 50; // First boss has 50 HP self.speed = 1; self.pointValue = 200; self.movePattern = 'boss'; self.phase = 0; self.shootCooldown = 0; self.isFinalBoss = false; // Track if this is the final boss // Override update method self.update = function () { if (self.isActive) { self.movementTime++; // Boss movement pattern if (self.phase === 0) { // Move down to position self.y += self.speed; if (self.y >= 300) { self.phase = 1; self.movementTime = 0; } } else if (self.phase === 1) { // Side to side movement self.x += Math.sin(self.movementTime * 0.02) * 3; // Phase transition based on health percentage var healthPercent = self.isFinalBoss ? self.health / 100 : self.health / 50; if (healthPercent <= 0.5 && self.phase < 2) { self.phase = 2; self.speed = 1.5; LK.effects.flashObject(self, 0xff0000, 1000); } } else if (self.phase === 2) { // More aggressive movement self.x += Math.sin(self.movementTime * 0.03) * 5; self.y += Math.sin(self.movementTime * 0.02) * 2; } // Boss shooting logic self.shootCooldown--; if (self.shootCooldown <= 0) { // Shoot pattern based on phase if (self.phase === 1) { // Single shot during phase 1 self.shootLaser(); self.shootCooldown = 90; // 1.5 seconds } else if (self.phase === 2) { // Triple shot during phase 2 self.shootLaser(); self.shootLaser(-30, 0.3); self.shootLaser(30, -0.3); self.shootCooldown = 60; // 1 second } } } }; // Boss shooting method self.shootLaser = function (offsetX, rotation) { offsetX = offsetX || 0; rotation = rotation || 0; var laser = new EnemyLaser(); laser.x = self.x + offsetX; laser.y = self.y + 100; if (rotation !== 0) { laser.rotation = rotation; } enemyLasers.push(laser); game.addChild(laser); }; // Set boss as final boss self.setAsFinalBoss = function () { self.isFinalBoss = true; self.health = 100; // Final boss has 100 HP self.pointValue = 500; tween(bossGraphics, { tint: 0xff0000 }, { duration: 1000 }); }; // Override takeDamage to show health var originalTakeDamage = self.takeDamage; self.takeDamage = function (damage) { originalTakeDamage.call(self, damage); // Update boss health display if (bossHealthText) { bossHealthText.setText("Boss HP: " + self.health); } }; return self; }); var EnemyLaser = Container.expand(function () { var self = Container.call(this); var laserGraphics = self.attachAsset('laser', { anchorX: 0.5, anchorY: 0.5, tint: 0xff6600 }); self.speed = 8; self.damage = 1; self.isActive = true; self.update = function () { if (self.isActive) { self.y += self.speed; // Remove laser when it goes off screen if (self.y > 2732 + 50) { self.isActive = false; } } }; return self; }); var Laser = Container.expand(function () { var self = Container.call(this); var laserGraphics = self.attachAsset('laser', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -15; self.damage = 1; self.isActive = true; self.update = function () { if (self.isActive) { self.y += self.speed; // Remove laser when it goes off screen if (self.y < -50) { self.isActive = false; } } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.shootCooldown = 0; self.cooldownTime = 15; // Frames between shots self.hasShield = false; self.hasSpreadshot = false; self.spreadDuration = 0; self.shield = null; self.update = function () { // Decrease cooldown if (self.shootCooldown > 0) { self.shootCooldown--; } // Decrease spreadshot duration if (self.hasSpreadshot) { self.spreadDuration--; if (self.spreadDuration <= 0) { self.hasSpreadshot = false; } } }; self.shoot = function () { if (self.shootCooldown <= 0) { if (self.hasSpreadshot) { // Create spread shot (3 lasers) var centerLaser = new Laser(); centerLaser.x = self.x; centerLaser.y = self.y - 40; lasers.push(centerLaser); game.addChild(centerLaser); var leftLaser = new Laser(); leftLaser.x = self.x - 30; leftLaser.y = self.y - 30; leftLaser.rotation = -0.3; lasers.push(leftLaser); game.addChild(leftLaser); var rightLaser = new Laser(); rightLaser.x = self.x + 30; rightLaser.y = self.y - 30; rightLaser.rotation = 0.3; lasers.push(rightLaser); game.addChild(rightLaser); } else { // Create single laser var laser = new Laser(); laser.x = self.x; laser.y = self.y - 40; lasers.push(laser); game.addChild(laser); } LK.getSound('shoot').play(); self.shootCooldown = self.cooldownTime; } }; self.activateShield = function () { // Remove existing shield if there is one if (self.shield && self.shield.isActive) { self.shield.isActive = false; game.removeChild(self.shield); } // Create new shield self.hasShield = true; self.shield = new Shield(); self.shield.x = self.x; self.shield.y = self.y; game.addChild(self.shield); return self.shield; }; self.activateSpreadshot = function () { self.hasSpreadshot = true; self.spreadDuration = 300; // 5 seconds at 60fps }; self.activateBomb = function () { // Destroy all enemies on screen for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (enemy.isActive) { enemy.takeDamage(999); // Instant kill LK.setScore(LK.getScore() + enemy.pointValue); } } // Visual effect for bomb LK.effects.flashScreen(0xff0000, 500); }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerUpGraphics = self.attachAsset('powerUp', { anchorX: 0.5, anchorY: 0.5 }); self.type = 'spreadshot'; // Default type self.speed = 3; self.isActive = true; self.update = function () { if (self.isActive) { self.y += self.speed; // Rotate the power-up for visual effect powerUpGraphics.rotation += 0.05; // Remove power-up when it goes off screen if (self.y > 2732 + 50) { self.isActive = false; } } }; self.setType = function (newType) { self.type = newType; // Change appearance based on type if (newType === 'spreadshot') { powerUpGraphics.tint = 0xff9900; } else if (newType === 'shield') { powerUpGraphics.tint = 0x33ccff; } else if (newType === 'bomb') { powerUpGraphics.tint = 0xff3300; } }; return self; }); var Shield = Container.expand(function () { var self = Container.call(this); var shieldGraphics = self.attachAsset('shield', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5 }); self.duration = 5000; // Shield lasts 5 seconds self.timeLeft = self.duration; self.isActive = true; self.update = function () { if (self.isActive) { self.timeLeft -= 1000 / 60; // Decrease time left (60 fps) // Fade out as shield expires shieldGraphics.alpha = 0.2 + self.timeLeft / self.duration * 0.5; // Rotate the shield for visual effect shieldGraphics.rotation += 0.01; // Deactivate shield when time runs out if (self.timeLeft <= 0) { self.isActive = false; } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000033 }); /**** * Game Code ****/ // Game state variables var player; var lasers = []; var enemyLasers = []; var enemies = []; var powerUps = []; var wave = 1; var enemiesInWave = 5; var enemiesSpawned = 0; var spawnCooldown = 0; var gameActive = true; var bossWave = false; var bossHealthText; // UI elements var scoreTxt = new Text2('0', { size: 80, fill: 0xFFFFFF }); scoreTxt.setText("Score: " + LK.getScore()); scoreTxt.anchor.set(0, 0); LK.gui.topRight.addChild(scoreTxt); var waveTxt = new Text2('Wave: 1', { size: 80, fill: 0xFFFFFF }); waveTxt.anchor.set(1, 0); LK.gui.topLeft.addChild(waveTxt); // Position it away from the top left corner (reserved for menu icon) waveTxt.x = 250; // Create player player = new Player(); player.x = 2048 / 2; player.y = 2732 - 200; game.addChild(player); // Start background music LK.playMusic('gameMusic'); // Game input handlers game.down = function (x, y, obj) { // Shoot when tapping anywhere player.shoot(); }; game.move = function (x, y, obj) { // Move player horizontally (keep vertical position fixed) if (gameActive) { player.x = x; // Keep player within game bounds if (player.x < 75) { player.x = 75; } if (player.x > 2048 - 75) { player.x = 2048 - 75; } // Update shield position if active if (player.shield && player.shield.isActive) { player.shield.x = player.x; player.shield.y = player.y; } } }; // Spawn enemies function spawnEnemy() { var enemy; if (bossWave) { enemy = new BossCat(); enemy.x = 2048 / 2; enemy.y = -200; // If this is the final boss (wave 10), set it to have 100 HP if (wave === 10) { enemy.setAsFinalBoss(); } // Play boss music when boss appears LK.getSound('boss').play(); // Create boss health display bossHealthText = new Text2("Boss HP: " + enemy.health, { size: 60, fill: 0xFF6600 }); bossHealthText.anchor.set(0.5, 0); bossHealthText.y = 150; LK.gui.top.addChild(bossHealthText); } else { enemy = new Enemy(); enemy.x = 100 + Math.random() * (2048 - 200); enemy.y = -100; // Set random enemy type based on current wave var typeRoll = Math.random(); if (wave <= 2) { // Waves 1-2: Only basic enemies enemy.setType('basic'); } else if (wave <= 4) { // Waves 3-4: Basic and fast enemies if (typeRoll < 0.6) { enemy.setType('basic'); } else { enemy.setType('fast'); } } else if (wave <= 6) { // Waves 5-6: Add zigzag enemies if (typeRoll < 0.4) { enemy.setType('basic'); } else if (typeRoll < 0.7) { enemy.setType('fast'); } else { enemy.setType('zigzag'); } } else { // Waves 7+: All enemy types if (typeRoll < 0.3) { enemy.setType('basic'); } else if (typeRoll < 0.5) { enemy.setType('fast'); } else if (typeRoll < 0.8) { enemy.setType('zigzag'); } else { enemy.setType('teleport'); } } } enemies.push(enemy); game.addChild(enemy); enemiesSpawned++; } // Main game update loop game.update = function () { if (!gameActive) { return; } // Update player player.update(); // Update shield if active if (player.shield && player.shield.isActive) { player.shield.update(); if (!player.shield.isActive) { player.hasShield = false; game.removeChild(player.shield); player.shield = null; } } // Handle enemy spawning if (spawnCooldown <= 0) { if (enemiesSpawned < enemiesInWave) { spawnEnemy(); // Cooldown between spawns if (bossWave) { spawnCooldown = 1; // Boss spawns immediately } else { spawnCooldown = 60; // 1 second between normal enemy spawns } } } else { spawnCooldown--; } // Update lasers and check for collisions for (var i = lasers.length - 1; i >= 0; i--) { var laser = lasers[i]; laser.update(); if (!laser.isActive) { game.removeChild(laser); lasers.splice(i, 1); continue; } // Check for collisions with enemies for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (enemy.isActive && laser.isActive && laser.intersects(enemy)) { enemy.takeDamage(laser.damage); laser.isActive = false; if (!enemy.isActive) { LK.setScore(LK.getScore() + enemy.pointValue); scoreTxt.setText("Score: " + LK.getScore()); game.removeChild(enemy); enemies.splice(j, 1); } break; } } } // Update enemy lasers and check for collisions with player for (var el = enemyLasers.length - 1; el >= 0; el--) { var enemyLaser = enemyLasers[el]; enemyLaser.update(); if (!enemyLaser.isActive) { game.removeChild(enemyLaser); enemyLasers.splice(el, 1); continue; } // Check for collision with player if (enemyLaser.intersects(player)) { // If player has shield, block the laser if (player.hasShield) { enemyLaser.isActive = false; game.removeChild(enemyLaser); enemyLasers.splice(el, 1); // Flash shield to show impact if (player.shield) { LK.effects.flashObject(player.shield, 0xffff00, 300); } } else { // Game over if player is hit gameActive = false; LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } } } // Update enemies var activeEnemies = 0; for (var k = enemies.length - 1; k >= 0; k--) { var enemy = enemies[k]; enemy.update(); if (!enemy.isActive) { game.removeChild(enemy); enemies.splice(k, 1); continue; } activeEnemies++; // Check collision with player if (enemy.intersects(player) && !player.hasShield) { // Game over if player is hit gameActive = false; LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } } // Update power-ups for (var l = powerUps.length - 1; l >= 0; l--) { var powerUp = powerUps[l]; powerUp.update(); if (!powerUp.isActive) { game.removeChild(powerUp); powerUps.splice(l, 1); continue; } // Check collision with player if (powerUp.intersects(player)) { // Apply power-up effect if (powerUp.type === 'spreadshot') { player.activateSpreadshot(); } else if (powerUp.type === 'shield') { player.activateShield(); } else if (powerUp.type === 'bomb') { player.activateBomb(); } LK.getSound('powerup').play(); powerUp.isActive = false; game.removeChild(powerUp); powerUps.splice(l, 1); } } // Check if wave is complete if (enemiesSpawned >= enemiesInWave && activeEnemies === 0) { // Wave complete, start next wave wave++; waveTxt.setText("Wave: " + wave); // Every 5th wave is a boss wave if (wave % 5 === 0) { bossWave = true; enemiesInWave = 1; } else { bossWave = false; enemiesInWave = 5 + Math.floor(wave * 1.5); // Remove boss health display if it exists if (bossHealthText) { LK.gui.top.removeChild(bossHealthText); bossHealthText = null; } } enemiesSpawned = 0; spawnCooldown = 120; // 2 second delay between waves // Win condition - player has survived 10 waves if (wave > 10) { LK.showYouWin(); return; } } // Auto fire if player holds down finger if (LK.ticks % 15 === 0) { player.shoot(); } };
===================================================================
--- original.js
+++ change.js
@@ -39,8 +39,16 @@
self.x = 100 + Math.random() * (2048 - 200);
LK.effects.flashObject(self, 0xffffff, 300);
}
}
+ // Advanced enemies occasionally shoot lasers
+ if ((self.type === 'zigzag' || self.type === 'teleport') && Math.random() < 0.005) {
+ var laser = new EnemyLaser();
+ laser.x = self.x;
+ laser.y = self.y + 30;
+ enemyLasers.push(laser);
+ game.addChild(laser);
+ }
// Remove enemy when it goes off screen
if (self.y > 2732 + 50) {
self.isActive = false;
}
@@ -111,13 +119,15 @@
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'boss';
- self.health = 20;
+ self.health = 50; // First boss has 50 HP
self.speed = 1;
self.pointValue = 200;
self.movePattern = 'boss';
self.phase = 0;
+ self.shootCooldown = 0;
+ self.isFinalBoss = false; // Track if this is the final boss
// Override update method
self.update = function () {
if (self.isActive) {
self.movementTime++;
@@ -131,10 +141,11 @@
}
} else if (self.phase === 1) {
// Side to side movement
self.x += Math.sin(self.movementTime * 0.02) * 3;
- // Phase transition based on health
- if (self.health <= 10 && self.phase < 2) {
+ // Phase transition based on health percentage
+ var healthPercent = self.isFinalBoss ? self.health / 100 : self.health / 50;
+ if (healthPercent <= 0.5 && self.phase < 2) {
self.phase = 2;
self.speed = 1.5;
LK.effects.flashObject(self, 0xff0000, 1000);
}
@@ -142,10 +153,50 @@
// More aggressive movement
self.x += Math.sin(self.movementTime * 0.03) * 5;
self.y += Math.sin(self.movementTime * 0.02) * 2;
}
+ // Boss shooting logic
+ self.shootCooldown--;
+ if (self.shootCooldown <= 0) {
+ // Shoot pattern based on phase
+ if (self.phase === 1) {
+ // Single shot during phase 1
+ self.shootLaser();
+ self.shootCooldown = 90; // 1.5 seconds
+ } else if (self.phase === 2) {
+ // Triple shot during phase 2
+ self.shootLaser();
+ self.shootLaser(-30, 0.3);
+ self.shootLaser(30, -0.3);
+ self.shootCooldown = 60; // 1 second
+ }
+ }
}
};
+ // Boss shooting method
+ self.shootLaser = function (offsetX, rotation) {
+ offsetX = offsetX || 0;
+ rotation = rotation || 0;
+ var laser = new EnemyLaser();
+ laser.x = self.x + offsetX;
+ laser.y = self.y + 100;
+ if (rotation !== 0) {
+ laser.rotation = rotation;
+ }
+ enemyLasers.push(laser);
+ game.addChild(laser);
+ };
+ // Set boss as final boss
+ self.setAsFinalBoss = function () {
+ self.isFinalBoss = true;
+ self.health = 100; // Final boss has 100 HP
+ self.pointValue = 500;
+ tween(bossGraphics, {
+ tint: 0xff0000
+ }, {
+ duration: 1000
+ });
+ };
// Override takeDamage to show health
var originalTakeDamage = self.takeDamage;
self.takeDamage = function (damage) {
originalTakeDamage.call(self, damage);
@@ -155,8 +206,29 @@
}
};
return self;
});
+var EnemyLaser = Container.expand(function () {
+ var self = Container.call(this);
+ var laserGraphics = self.attachAsset('laser', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ tint: 0xff6600
+ });
+ self.speed = 8;
+ self.damage = 1;
+ self.isActive = true;
+ self.update = function () {
+ if (self.isActive) {
+ self.y += self.speed;
+ // Remove laser when it goes off screen
+ if (self.y > 2732 + 50) {
+ self.isActive = false;
+ }
+ }
+ };
+ return self;
+});
var Laser = Container.expand(function () {
var self = Container.call(this);
var laserGraphics = self.attachAsset('laser', {
anchorX: 0.5,
@@ -337,8 +409,9 @@
****/
// Game state variables
var player;
var lasers = [];
+var enemyLasers = [];
var enemies = [];
var powerUps = [];
var wave = 1;
var enemiesInWave = 5;
@@ -399,8 +472,12 @@
if (bossWave) {
enemy = new BossCat();
enemy.x = 2048 / 2;
enemy.y = -200;
+ // If this is the final boss (wave 10), set it to have 100 HP
+ if (wave === 10) {
+ enemy.setAsFinalBoss();
+ }
// Play boss music when boss appears
LK.getSound('boss').play();
// Create boss health display
bossHealthText = new Text2("Boss HP: " + enemy.health, {
@@ -506,8 +583,37 @@
break;
}
}
}
+ // Update enemy lasers and check for collisions with player
+ for (var el = enemyLasers.length - 1; el >= 0; el--) {
+ var enemyLaser = enemyLasers[el];
+ enemyLaser.update();
+ if (!enemyLaser.isActive) {
+ game.removeChild(enemyLaser);
+ enemyLasers.splice(el, 1);
+ continue;
+ }
+ // Check for collision with player
+ if (enemyLaser.intersects(player)) {
+ // If player has shield, block the laser
+ if (player.hasShield) {
+ enemyLaser.isActive = false;
+ game.removeChild(enemyLaser);
+ enemyLasers.splice(el, 1);
+ // Flash shield to show impact
+ if (player.shield) {
+ LK.effects.flashObject(player.shield, 0xffff00, 300);
+ }
+ } else {
+ // Game over if player is hit
+ gameActive = false;
+ LK.effects.flashScreen(0xff0000, 1000);
+ LK.showGameOver();
+ return;
+ }
+ }
+ }
// Update enemies
var activeEnemies = 0;
for (var k = enemies.length - 1; k >= 0; k--) {
var enemy = enemies[k];
explosion 💥. In-Game asset. 2d. High contrast. No shadows
a cat head. In-Game asset. 2d. High contrast
make this cat expression goes silly but angry
2 cucumbers inside a glass bubble. In-Game asset. 2d. High contrast. No shadows
a shield inside a glass bubble. In-Game asset. 2d. High contrast. No shadows
an explosion inside a glass bubble. In-Game asset. 2d. High contrast. No shadows
a heart inside a glass bubble. In-Game asset. 2d. High contrast. No shadows