User prompt
Make the bomb display a little smaller and the text a little smaller. make the ready text dark purple. move the ui panel up two levels
User prompt
Make the bomb reload a little smaller and the text a little smaller
User prompt
Make the bomb reload sprite bigger, make the bomb ready text smaller and center it on the bomb reload sprite
User prompt
move the hearts down a little, move the bomb display up a little
User prompt
Move the hearts and bomb display down closer to the bottom edge of the screen. Move the UI panel up a layer
User prompt
Move the ui panel back behind the hearts and bomb display
User prompt
Move the bomb display up and double its size
User prompt
There are two bomb status displays now
User prompt
Make the UI panel 20% bigger and move it up 600 pixels
User prompt
Remove scaling from the UI panel
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'uiPanel.bombText.style.fill = 0x00FF00;' Line Number: 791
User prompt
Add the bomb reload display back in
User prompt
Create a new sprite at the bottom of the screen that uses a brand new image. call it uiPanelBackground
User prompt
The panel should be a brand new image
User prompt
The panel should have a new image
User prompt
The UI panel should have its own sprite
User prompt
The UI panel should use its own sprite and have no text on it
User prompt
Add a single UI panel at the bottom of the screen that is about 33% of the width of the screen and underneath the hearts and bomb
User prompt
Add a black background under the hearts to make them stand out and get rid of their red tint āŖš” Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Move them a little closer together
User prompt
Space the hearts out more
User prompt
Make the hearts bigger
User prompt
move them down by 150
User prompt
Move the hearts up by 400 pixels.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Define a class for scrolling backgrounds var Background = Container.expand(function () { var self = Container.call(this); self.speed = 3; self.asset = null; self.init = function (assetName, startX) { self.asset = self.attachAsset(assetName, { anchorX: 0, anchorY: 0 }); self.x = startX; self.y = 0; }; self.update = function () { self.x -= gameSpeed; // If background has moved completely off screen to the left, reposition it to the right if (self.x <= -1366) { self.x = 1366 * 2; } }; return self; }); // Define a class for bombs dropped by player var Bomb = Container.expand(function () { var self = Container.call(this); // Create bomb graphic var bombGraphics = self.attachAsset('bomb', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); // Track last position and explosion state self.lastY = 0; self.hasExploded = false; self.velocityY = 10; // Update bomb position and check for ground collision self.update = function () { // Store last position before updating self.lastY = self.y; // Apply gravity self.velocityY += 0.8; self.y += self.velocityY; // Check if bomb hits the ground if (self.lastY < floorLevel && self.y >= floorLevel) { self.explode(); } }; // Handle explosion effect and enemy destruction self.explode = function () { if (self.hasExploded) { return; } self.hasExploded = true; // Play explosion sound LK.getSound('explosion').play(); // Create explosion graphic var explosion = LK.getAsset('explosion', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); explosion.x = self.x; explosion.y = floorLevel; game.addChild(explosion); // Check for enemies in explosion radius var enemyHit = false; var children = game.children.slice(); for (var i = 0; i < children.length; i++) { if (children[i] instanceof Enemy) { var enemy = children[i]; // Simple distance check for explosion radius var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 150) { // Explosion radius // Create player hit explosion at enemy's position using playerHitExplosion asset var enemyExplosion = new Container(); var enemyExplosionGraphic = enemyExplosion.attachAsset('playerHitExplosion', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9, scaleX: 0.1, scaleY: 0.1 }); enemyExplosion.x = enemy.x; enemyExplosion.y = enemy.y; enemyExplosion.scrollSpeed = gameSpeed; // Store the current game speed enemyExplosion.update = function () { // Make explosion scroll with background enemyExplosion.x -= enemyExplosion.scrollSpeed; }; game.addChild(enemyExplosion); // Animate explosion growing and fading out tween(enemyExplosionGraphic, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, onFinish: function onFinish() { game.removeChild(enemyExplosion); } }); // Remove enemy game.removeChild(enemy); enemyHit = true; // Play enemy hit sound when enemy is destroyed LK.getSound('enemyHit').play(); // Add 500 points for destroying enemy with bomb LK.setScore(LK.getScore() + 500); scoreText.setText('Score: ' + LK.getScore()); } } } // Remove bomb game.removeChild(self); // Fade out and remove explosion after 500ms tween(explosion, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 500, onFinish: function onFinish() { game.removeChild(explosion); } }); }; return self; }); // Define a class for enemies var Enemy = Container.expand(function () { var self = Container.call(this); // Create enemy using proper enemy sprite var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5 }); // Track last position and collision state self.lastX = 0; self.lastCollided = false; self.update = function () { // Store last position before updating self.lastX = self.x; // Move at the same speed as background self.x -= gameSpeed; // Check if enemy hits left edge of screen if (self.lastX > 0 && self.x <= 0) { // Add 100 to score LK.setScore(LK.getScore() + 100); scoreText.setText('Score: ' + LK.getScore()); // Remove this enemy self.parent.removeChild(self); } // Check collision with player if not previously collided if (!self.lastCollided && self.intersects(player)) { // Set collision flag to prevent multiple hits self.lastCollided = true; // Create player hit explosion at enemy's position using different asset var explosion = new Container(); var explosionGraphic = explosion.attachAsset('playerHitExplosion', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9, scaleX: 0.1, scaleY: 0.1 }); explosion.x = self.x; explosion.y = self.y; explosion.scrollSpeed = gameSpeed; // Store the current game speed explosion.update = function () { // Make explosion scroll with background explosion.x -= explosion.scrollSpeed; }; game.addChild(explosion); // Play explosion sound when player is hit LK.getSound('explosion').play(); // Animate explosion growing and fading out tween(explosionGraphic, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, onFinish: function onFinish() { game.removeChild(explosion); } }); // Remove enemy from game self.parent.removeChild(self); // Reduce player lives if (player.lives > 0) { player.lives--; // Play sound when life is lost LK.getSound('lifeLost').play(); // Update heart display if (player.hearts.length > 0 && player.hearts[player.lives]) { game.removeChild(player.hearts[player.lives]); player.hearts.splice(player.lives, 1); } // Flash player to indicate damage LK.effects.flashObject(player, 0xFF0000, 500); // Game over if no lives left if (player.lives <= 0) { // Hide player player.visible = false; // Create explosion where player was var finalExplosion = new Container(); var finalExplosionGraphic = finalExplosion.attachAsset('playerExplosion', { anchorX: 0.5, anchorY: 0.5, alpha: 1.0, scaleX: 1.0, scaleY: 1.0 }); finalExplosion.x = player.x; finalExplosion.y = player.y; game.addChild(finalExplosion); // Stop game scrolling gameSpeed = 0; // Animate explosion growing and fading out over 1.5 seconds tween(finalExplosionGraphic, { alpha: 0, scaleX: 3.0, scaleY: 3.0 }, { duration: 1500, onFinish: function onFinish() { game.removeChild(finalExplosion); LK.showGameOver(); } }); } } } }; return self; }); // Define a class for missiles that launch at player var Missile = Container.expand(function () { var self = Container.call(this); // Create missile graphic using dedicated missile asset var missileGraphics = self.attachAsset('missile', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.2 }); // Track missile properties self.warningTime = 60; // 1 second warning at 60fps self.isWarning = true; // Start in warning state self.scrollSpeed = 0; // Will be set when missile is created // Create warning indicator self.warningIndicator = new Container(); var warningGraphic = self.warningIndicator.attachAsset('missile', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.0, tint: 0xFF0000 // Red color for warning }); // Add warning text self.warningText = new Text2('!', { size: 60, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 3 }); self.warningText.anchor.set(0.5, 0.5); self.warningIndicator.addChild(self.warningText); // Update method for missile behavior self.update = function () { if (self.isWarning) { // During warning phase, just count down self.warningTime--; // Make warning indicator blink self.warningIndicator.alpha = Math.floor(self.warningTime / 10) % 2 === 0 ? 1.0 : 0.3; // When warning time ends, start moving missile if (self.warningTime <= 0) { self.isWarning = false; game.removeChild(self.warningIndicator); } } else { // Move missile from right to left at 1.5x scroll speed self.x -= self.scrollSpeed; // Check if missile is off screen if (self.x < -50) { if (self.parent) { self.parent.removeChild(self); } return; } // Check for collision with player if (self.intersects(player) && player.lives > 0) { // Create explosion var explosion = new Container(); var explosionGraphic = explosion.attachAsset('playerHitExplosion', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9, scaleX: 0.1, scaleY: 0.1 }); explosion.x = self.x; explosion.y = self.y; explosion.scrollSpeed = gameSpeed; explosion.update = function () { explosion.x -= explosion.scrollSpeed; }; game.addChild(explosion); // Play explosion sound when player is hit by missile LK.getSound('explosion').play(); // Animate explosion tween(explosionGraphic, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, onFinish: function onFinish() { game.removeChild(explosion); } }); // Reduce player lives player.lives--; // Play sound when life is lost LK.getSound('lifeLost').play(); // Update heart display if (player.hearts.length > 0 && player.hearts[player.lives]) { game.removeChild(player.hearts[player.lives]); player.hearts.splice(player.lives, 1); } // Flash player to indicate damage LK.effects.flashObject(player, 0xFF0000, 500); // Game over if no lives left if (player.lives <= 0) { // Hide player player.visible = false; // Create explosion where player was var finalExplosion = new Container(); var finalExplosionGraphic = finalExplosion.attachAsset('playerExplosion', { anchorX: 0.5, anchorY: 0.5, alpha: 1.0, scaleX: 1.0, scaleY: 1.0 }); finalExplosion.x = player.x; finalExplosion.y = player.y; game.addChild(finalExplosion); // Stop game scrolling gameSpeed = 0; // Animate explosion growing and fading out over 1.5 seconds tween(finalExplosionGraphic, { alpha: 0, scaleX: 3.0, scaleY: 3.0 }, { duration: 1500, onFinish: function onFinish() { game.removeChild(finalExplosion); LK.showGameOver(); } }); } // Remove missile if (self.parent) { self.parent.removeChild(self); } } } }; // Initialize missile with warning at the specified position self.init = function (yPosition) { // Position missile at right edge of screen self.x = 2048; self.y = yPosition; // Set missile speed to 1.5x the current game speed self.scrollSpeed = gameSpeed * 1.5; // Position warning indicator at the right edge self.warningIndicator.x = 2048; self.warningIndicator.y = yPosition; // Add warning indicator to game game.addChild(self.warningIndicator); }; return self; }); //<Assets used in the game will automatically appear here> // Define a class for the player character var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); self.speed = 5; self.jumpHeight = 40; self.isJumping = false; self.velocityY = 0; self.lives = 3; // Initialize player with 3 lives self.hearts = []; // Array to store heart icons self.canDropBomb = true; // Track if player can drop a bomb self.activeBomb = null; // Reference to current active bomb self.bombCooldown = 0; // Track cooldown time for bomb reload self.bombReloadTime = 240; // 4 seconds at 60fps self.createHearts = function () { // Create three hearts in the middle of the screen near the bottom for (var i = 0; i < self.lives; i++) { var heart = new Container(); // Create a red heart shape using heart shape var heartShape = heart.attachAsset('heart', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5, tint: 0xFF0000 // Red color for hearts }); // Calculate position in the middle of the screen heart.x = 2048 / 2 + (i - 1) * 200; // Center horizontally with even wider spacing heart.y = 2732 - 200; // Position even closer to the bottom of the screen // Remove heart from player and add to game so it stays fixed self.hearts.push(heart); game.addChild(heart); } }; // Initialize hearts when player is created self.createHearts(); // Create bomb indicator self.bombIndicator = new Container(); var bombGraphic = self.bombIndicator.attachAsset('bomb', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.4, scaleY: 2.4 }); // Add cooldown overlay (starts invisible) self.cooldownOverlay = LK.getAsset('bomb', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.4, scaleY: 2.4, tint: 0x666666, alpha: 0.7 }); self.cooldownOverlay.y = 0; self.cooldownOverlay.height = 0; // Start with no overlay self.bombIndicator.addChild(self.cooldownOverlay); // Add text to show reload progress self.bombReadyText = new Text2('READY', { size: 30, // Smaller text size fill: 0x00FF00, stroke: 0x000000, strokeThickness: 3 }); // Initialize style explicitly to avoid "Cannot set properties of undefined" error self.bombReadyText.style = { fill: 0x00FF00 }; self.bombReadyText.anchor.set(0.5, 0.5); // Center it on the bomb self.bombReadyText.y = 0; // Center it on the bomb self.bombIndicator.addChild(self.bombReadyText); // Position bomb indicator at bottom of screen, doubled in size self.bombIndicator.x = 2048 / 2; self.bombIndicator.y = 2732 - 400; // Position higher up from the bottom of the screen self.bombIndicator.scale.set(2, 2); // Double the size game.addChild(self.bombIndicator); self.update = function () { if (self.isJumping) { self.y += self.velocityY; self.velocityY += 0.7; // Decreased gravity effect by 30% if (self.y >= floorLevel) { // Return to floor level self.y = floorLevel; self.isJumping = false; self.velocityY = 0; self.activeBomb = null; // Clear reference to active bomb } } // Handle bomb cooldown if (self.bombCooldown > 0) { self.bombCooldown--; // Update cooldown overlay height based on remaining cooldown var progress = self.bombCooldown / self.bombReloadTime; self.cooldownOverlay.height = bombGraphic.height * progress; self.cooldownOverlay.y = -(bombGraphic.height / 2) + self.cooldownOverlay.height / 2; // Update text to show progress if (self.bombCooldown <= 0) { self.canDropBomb = true; self.bombReadyText.setText('READY'); self.bombReadyText.style.fill = 0x00FF00; self.cooldownOverlay.height = 0; // Play bomb ready sound when bomb becomes available LK.getSound('bombReady').play(); } else { var secondsLeft = Math.ceil(self.bombCooldown / 60); self.bombReadyText.setText(secondsLeft + 's'); self.bombReadyText.style.fill = 0xFF0000; } } }; self.jump = function () { if (!self.isJumping) { self.isJumping = true; self.velocityY = -self.jumpHeight; // Play jump sound when player jumps LK.getSound('jump').play(); } else if (self.canDropBomb) { // Drop a bomb if in mid-air and haven't dropped one yet self.canDropBomb = false; self.bombCooldown = self.bombReloadTime; // Start cooldown timer (4 seconds) // Create new bomb var bomb = new Bomb(); bomb.x = self.x; bomb.y = self.y + 50; // Position slightly below player bomb.lastY = bomb.y; // Add bomb to game game.addChild(bomb); self.activeBomb = bomb; } }; }); // Define a class for street backgrounds (bottom part) var StreetBackground = Container.expand(function () { var self = Container.call(this); self.speed = 3; self.asset = null; self.init = function (assetName, startX) { self.asset = self.attachAsset(assetName, { anchorX: 0, anchorY: 0, scaleY: 0.5 // Make the background half height }); self.x = startX; self.y = 2732 * 0.5; // Position in the bottom half of the screen }; self.update = function () { self.x -= gameSpeed; // If background has moved completely off screen to the left, reposition it to the right if (self.x <= -2048) { self.x = 2048 * 2 - gameSpeed; } }; return self; }); // UI Panel class var UIPanel = Container.expand(function () { var self = Container.call(this); // Create a panel using a brand new UI panel image var panel = self.attachAsset('uiPanelBackground', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9 }); // Method to update panel content (kept for compatibility) self.updateContent = function (status) { // No text to update anymore }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1A0933 // Dark purple background }); /**** * Game Code ****/ // Game speed control variable var gameSpeed = 5; // Floor level variable (Y position for player and enemies) var floorLevel = 2732 * 0.55 + 400; // 55% of screen height + 400px down // Track enemies var enemies = []; // Create three scrolling backgrounds for the top part var backgrounds = []; // Create three scrolling backgrounds for the bottom part (street) var streetBackgrounds = []; // Create each background and position them for (var i = 0; i < 3; i++) { var bg = new Background(); bg.init('background' + (i + 1), i * 1366); backgrounds.push(bg); game.addChild(bg); // Create street backgrounds using different assets var streetBg = new StreetBackground(); streetBg.init('street' + (i + 1), i * 2048); streetBackgrounds.push(streetBg); game.addChild(streetBg); } // Initialize player var player = game.addChild(new Player()); player.x = 2048 / 2 - 500; // Move player back 500 pixels player.y = floorLevel; // Position player at the floor level // Create and position UI panel var uiPanel = new UIPanel(); uiPanel.x = 2048 / 2; // Center horizontally uiPanel.y = 2732 - 350; // Position closer to the bottom of the screen uiPanel.scale.set(1.2, 1.2); // Make the UI panel 20% bigger // Make sure UI panel is behind hearts and bomb display by adding at a low index game.addChildAt(uiPanel, 0); // Create a new Text2 object to display the score with cyberpunk styling var scoreText = new Text2('Score: 0', { size: 80, fill: 0x00FFFF, // Cyan color for cyberpunk neon effect stroke: 0xFF00FF, // Magenta stroke for contrast strokeThickness: 5, // Thick stroke for glow effect dropShadow: true, dropShadowColor: 0x00FFFF, // Cyan shadow dropShadowBlur: 10, dropShadowAngle: Math.PI / 4, dropShadowDistance: 6, letterSpacing: 3 // Spacing between letters for futuristic look }); // Add the score text to the game GUI at the top right of the screen LK.gui.topRight.addChild(scoreText); // Anchor the text to the right side scoreText.anchor.set(1, 0); // Add padding from the right edge scoreText.x = -20; scoreText.y = 20; // Create a pulsating glow effect for the cyberpunk score display function pulseScoreText() { tween(scoreText, { strokeThickness: 8, dropShadowBlur: 15 }, { duration: 800, onFinish: function onFinish() { tween(scoreText, { strokeThickness: 5, dropShadowBlur: 10 }, { duration: 800, onFinish: pulseScoreText }); } }); } pulseScoreText(); // Handle game updates game.update = function () { // Increase game speed as score increases for difficulty progression gameSpeed = 5 + Math.min(LK.getScore() / 10, 5); // Cap at max 10 speed // Update scrolling backgrounds for (var i = 0; i < backgrounds.length; i++) { backgrounds[i].update(); } // Update street backgrounds for (var i = 0; i < streetBackgrounds.length; i++) { streetBackgrounds[i].update(); } player.update(); // Spawn enemies (wait 5 seconds at the start - 300 frames at 60fps) if (LK.ticks > 300 && LK.ticks % 180 === 0) { // Spawn enemy every 3 seconds (180 frames at 60fps) var enemy = new Enemy(); enemy.x = 2048; // Start at right edge of screen enemy.y = floorLevel; // Position at floor level enemy.lastX = enemy.x; // Initialize lastX game.addChild(enemy); } // Spawn missiles when player score reaches 1500 if (LK.getScore() >= 1500 && LK.ticks % 120 === 0) { // Every 2 seconds (120 frames) // Calculate a y-position for the missile // Should be at least 500px above player but no higher than max jump height var playerMaxHeight = floorLevel - player.jumpHeight * 6; // Approximate max jump height var minMissileHeight = floorLevel - 2800; // At least 500px above player (increased from 300px) var maxMissileHeight = floorLevel - 800; // Don't go too high // Calculate the valid range for missile spawn positions var validRangeMin = Math.max(maxMissileHeight, minMissileHeight); var validRangeMax = floorLevel - 50; // Generate a random position within this range var missileY = validRangeMin + Math.random() * (validRangeMax - validRangeMin); // Ensure missile is within screen bounds missileY = Math.max(100, Math.min(missileY, floorLevel - 50)); // Create missile with warning var missile = new Missile(); missile.init(missileY); game.addChild(missile); } // Update all enemies and bombs var children = game.children.slice(); for (var i = 0; i < children.length; i++) { if (children[i] instanceof Enemy) { children[i].update(); } else if (children[i] instanceof Bomb) { children[i].update(); } else if (children[i] instanceof Missile) { children[i].update(); } else if (children[i].update && children[i].scrollSpeed !== undefined) { // Update any container with scrollSpeed (like our player hit explosions) children[i].update(); } } // Update score display scoreText.setText('Score: ' + LK.getScore()); // Update UI panel is no longer needed - using player's bomb display }; // Handle player jump game.down = function (x, y, obj) { player.jump(); };
===================================================================
--- original.js
+++ change.js
@@ -443,36 +443,37 @@
self.bombIndicator = new Container();
var bombGraphic = self.bombIndicator.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5,
- scaleX: 1.2,
- scaleY: 1.2
+ scaleX: 2.4,
+ scaleY: 2.4
});
// Add cooldown overlay (starts invisible)
self.cooldownOverlay = LK.getAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5,
- scaleX: 1.2,
- scaleY: 1.2,
+ scaleX: 2.4,
+ scaleY: 2.4,
tint: 0x666666,
alpha: 0.7
});
self.cooldownOverlay.y = 0;
self.cooldownOverlay.height = 0; // Start with no overlay
self.bombIndicator.addChild(self.cooldownOverlay);
// Add text to show reload progress
self.bombReadyText = new Text2('READY', {
- size: 40,
+ size: 30,
+ // Smaller text size
fill: 0x00FF00,
stroke: 0x000000,
- strokeThickness: 4
+ strokeThickness: 3
});
// Initialize style explicitly to avoid "Cannot set properties of undefined" error
self.bombReadyText.style = {
fill: 0x00FF00
};
- self.bombReadyText.anchor.set(0.5, 0);
- self.bombReadyText.y = 40;
+ self.bombReadyText.anchor.set(0.5, 0.5); // Center it on the bomb
+ self.bombReadyText.y = 0; // Center it on the bomb
self.bombIndicator.addChild(self.bombReadyText);
// Position bomb indicator at bottom of screen, doubled in size
self.bombIndicator.x = 2048 / 2;
self.bombIndicator.y = 2732 - 400; // Position higher up from the bottom of the screen
cyberpunk pixel art asphalt street. In-Game asset. 2d. High contrast. No shadows, street debris
cyberpunk pixel art asphalt street. In-Game asset. 2d. High contrast. No shadows, street debris
Neon pink techno heart. In-Game asset. 2d. High contrast. No shadows
Side view, angry cyberpunk robot, looking left. full body, cute but aggro In-Game asset. 2d. High contrast. No shadows
Side view, cute female cyberpunk robot, looking right, full body, chibi, riding in a hover sphere with energy glow at bottom, hands on controls In-Game asset. 2d. High contrast. No shadows
cyberpunk explosion with the word "ouch" in the middle. sparks. In-Game asset. 2d. High contrast. No shadows
Glowing energy sphere. Spherical. Yellow and blue. In-Game asset. 2d. High contrast. No shadows
digital explosion, burnt orange neon blue, pixels, sparks. In-Game asset. 2d. High contrast. No shadows
digital explosion. squares. pixels. chaos. neon. sparks. In-Game asset. 2d. High contrast. No shadows