User prompt
make the potent attack proyectiles to be shot in a row ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make potent proyectiles to look like a standing rectangle
User prompt
now make a small animation before shoting the potent attack ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
reduce the potent attack proyectiles range to alf
User prompt
make crouching hit box a little big bigger now
User prompt
make the proyectile from standing to dont hit when crouching
User prompt
make the hit box smaller when crouch
User prompt
a little bit higer
User prompt
make the standing proyectile start a very little bit higer
User prompt
make crouching hit box smell enoug to be able to dodge a range attack shoot from a standing state
User prompt
make crouching hit box a little smaller
User prompt
all the 7 potent attack proyectiles push
User prompt
the potent attack proyectiles
User prompt
i said special attack proyectiles
User prompt
all special attack proyectiles push a little
User prompt
special attack pushes a lor more
User prompt
if one character is behind the another their shot direction swiches direction
User prompt
i mean make they still can shot each other
User prompt
make the jump buttom an arrow pointing up
User prompt
change the crouch buttom simbol to an arrow pointing down
User prompt
move the crouch bottom to the midle of the rigth and left buttom
User prompt
move the moving rigth buttom to the rigth of the left buttom
User prompt
special attack pushes enemy a lot ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the special attack proyectiles be shot one by one ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
divide the special attack into 7 different proyectiles with lower range and 1/7 of the original damage each one ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var EnergyBar = Container.expand(function (fighter, x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.fighter = fighter;
var bgBar = self.attachAsset('energyBarBg', {
anchorX: 0,
anchorY: 0
});
// Create 3 individual energy bars
self.energyBars = [];
for (var i = 0; i < 3; i++) {
var energyBar = self.attachAsset('energyBar', {
anchorX: 0,
anchorY: 0
});
energyBar.x = i * 135; // Space bars evenly (400/3 ≈ 133)
energyBar.width = 125; // Slightly smaller to have gaps
self.energyBars.push(energyBar);
}
self.update = function () {
// Show energy bars based on current energy level (0-3)
var energyLevel = Math.floor(self.fighter.energy / (self.fighter.maxEnergy / 3));
for (var i = 0; i < 3; i++) {
self.energyBars[i].visible = i < energyLevel;
}
};
return self;
});
var Fighter = Container.expand(function (fighterType, isPlayer) {
var self = Container.call(this);
// Fighter properties
self.fighterType = fighterType || 1;
self.isPlayer = isPlayer || false;
self.maxHealth = 100;
self.health = 100;
self.maxEnergy = 3; // Changed to 3 energy units
self.energy = 3; // Start with full energy
self.speed = 3;
self.isBlocking = false;
self.attackCooldown = 0;
self.specialCooldown = 0;
self.maxSpecialCharge = 100;
self.specialCharge = 0;
self.isCrouching = false;
self.isJumping = false;
self.jumpHeight = 0;
self.maxJumpHeight = 100;
self.jumpSpeed = 14;
self.originalY = 0;
self.gravity = 0.25;
self.velocityY = 0;
self.groundY = 2200; // Ground level for all fighters
// Create fighter graphics
var fighterGraphics = self.attachAsset('fighter' + self.fighterType, {
anchorX: 0.5,
anchorY: 1.0
});
// Fighter stats based on type
switch (self.fighterType) {
case 1:
// Red Fighter - Balanced
self.attackDamage = 8;
self.specialDamage = 10;
self.specialCost = 1; // 1 energy bar per special attack
break;
case 2:
// Blue Fighter - Fast
self.attackDamage = 6;
self.specialDamage = 8;
self.specialCost = 1; // 1 energy bar per special attack
self.speed = 4;
break;
case 3:
// Green Fighter - Strong
self.attackDamage = 10;
self.specialDamage = 12;
self.specialCost = 1; // 1 energy bar per special attack
self.speed = 2;
break;
case 4:
// Yellow Fighter - Energy Efficient
self.attackDamage = 7;
self.specialDamage = 9;
self.specialCost = 1; // 1 energy bar per special attack
break;
case 5:
// Purple Fighter - High Health
self.attackDamage = 7;
self.specialDamage = 9;
self.specialCost = 1; // 1 energy bar per special attack
self.maxHealth = 120;
self.health = 120;
break;
}
self.takeDamage = function (damage, isSuperProjectile, attacker) {
if (self.isPlayer && playerIsBlocking) {
// Check if within perfect block window (first 0.7 seconds)
var timeSinceBlockStart = LK.ticks - playerBlockStartTime;
if (timeSinceBlockStart <= 42) {
// 42 ticks = 0.7 seconds at 60fps
damage = 0; // 100% damage reduction
} else {
damage = Math.floor(damage * 0.25); // 25% damage when holding block
}
} else if (self.isBlocking) {
if (isSuperProjectile) {
damage = Math.floor(damage * 0.5); // 50% damage when blocking super projectile
} else {
damage = Math.floor(damage * 0.3);
}
}
self.health = Math.max(0, self.health - damage);
// Charge special attack bar by 2% when taking damage (only if damage > 0)
if (damage > 0) {
self.chargeSpecial(2); // 2% of maxSpecialCharge (100)
}
// Flash red when taking damage
LK.effects.flashObject(fighterGraphics, 0xFF0000, 300);
};
self.useEnergy = function (amount) {
if (self.energy >= amount) {
self.energy -= amount;
return true;
}
return false;
};
self.attack = function () {
if (self.attackCooldown <= 0) {
self.attackCooldown = 30;
return true;
}
return false;
};
self.specialAttack = function () {
if (self.specialCooldown <= 0 && self.useEnergy(self.specialCost)) {
self.specialCooldown = 90;
return true;
}
return false;
};
self.chargeSpecial = function (amount) {
self.specialCharge = Math.min(self.maxSpecialCharge, self.specialCharge + amount);
};
self.canUseSpecialAttack = function () {
return self.specialCharge >= self.maxSpecialCharge;
};
self.useSpecialAttack = function () {
if (self.canUseSpecialAttack()) {
self.specialCharge = 0;
return true;
}
return false;
};
self.crouch = function () {
if (!self.isJumping) {
self.isCrouching = true;
}
};
self.stopCrouch = function () {
self.isCrouching = false;
};
self.jump = function () {
if (!self.isCrouching && !self.isJumping && self.y >= self.groundY) {
self.isJumping = true;
self.velocityY = -self.jumpSpeed; // Negative velocity for upward movement
}
};
self.update = function () {
// Cooldown management
if (self.attackCooldown > 0) self.attackCooldown--;
if (self.specialCooldown > 0) self.specialCooldown--;
// Energy regeneration - regenerate 1 energy every 10 seconds (600 ticks), one bar at a time
if (self.energy < self.maxEnergy && LK.ticks % 600 === 0) {
self.energy = Math.min(self.maxEnergy, self.energy + 1);
}
// Handle jumping and gravity physics
if (self.isJumping) {
// Apply gravity to vertical velocity
self.velocityY += self.gravity;
// Update position based on velocity
self.y += self.velocityY;
// Check if landed on ground
if (self.y >= self.groundY) {
self.y = self.groundY;
self.isJumping = false;
self.velocityY = 0;
}
} else {
// Ensure fighter stays on ground when not jumping
if (self.y > self.groundY) {
self.y = self.groundY;
}
}
// Handle crouching visual effect
if (self.isCrouching && !self.isJumping) {
// Scale down vertically when crouching
if (fighterGraphics.scaleY > 0.7) {
fighterGraphics.scaleY -= 0.05;
}
} else {
// Return to normal scale
if (fighterGraphics.scaleY < 1.0) {
fighterGraphics.scaleY += 0.05;
}
}
};
return self;
});
var HealthBar = Container.expand(function (fighter, x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.fighter = fighter;
var bgBar = self.attachAsset('healthBarBg', {
anchorX: 0,
anchorY: 0
});
var healthBar = self.attachAsset('healthBar', {
anchorX: 0,
anchorY: 0
});
self.update = function () {
var healthPercent = self.fighter.health / self.fighter.maxHealth;
healthBar.width = 400 * healthPercent;
};
return self;
});
var Projectile = Container.expand(function (x, y, direction, damage, owner) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.direction = direction; // 1 for right, -1 for left
self.damage = damage;
self.owner = owner;
self.speed = 8;
var projectileGraphics = self.attachAsset('projectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
self.x += self.speed * self.direction;
};
return self;
});
var SpecialBar = Container.expand(function (fighter, x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.fighter = fighter;
var bgBar = self.attachAsset('specialBarBg', {
anchorX: 0,
anchorY: 0
});
var specialBar = self.attachAsset('specialBar', {
anchorX: 0,
anchorY: 0
});
self.update = function () {
var specialPercent = self.fighter.specialCharge / self.fighter.maxSpecialCharge;
specialBar.width = 400 * specialPercent;
};
return self;
});
var SuperProjectile = Container.expand(function (x, y, direction, damage, owner) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.direction = direction; // 1 for right, -1 for left
self.damage = damage;
self.owner = owner;
self.speed = 6;
self.isSuperProjectile = true;
var projectileGraphics = self.attachAsset('projectile', {
anchorX: 0.5,
anchorY: 0.5
});
projectileGraphics.tint = 0xffaa00; // Orange tint for special projectiles
projectileGraphics.scaleX = 2;
projectileGraphics.scaleY = 2;
self.update = function () {
self.x += self.speed * self.direction;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2C1810
});
/****
* Game Code
****/
// Sounds
// Combat elements
// UI elements
// Character assets
// Game states
var gameState = 'characterSelect'; // 'characterSelect', 'combat', 'gameOver'
var selectedCharacter = 1;
var enemyCharacter = 2;
// Character selection
var characterSelectors = [];
var selectionBorder = null;
// Combat variables
var player = null;
var enemy = null;
var playerHealthBar = null;
var playerEnergyBar = null;
var playerSpecialBar = null;
var enemyHealthBar = null;
var enemyEnergyBar = null;
var enemySpecialBar = null;
var projectiles = [];
var superProjectiles = [];
var punchButton = null;
var kickButton = null;
var rangeButton = null;
var blockButton = null;
var specialButton = null;
var playerBlockStartTime = 0;
var playerIsBlocking = false;
var punchButtonText = null;
var kickButtonText = null;
var rangeButtonText = null;
var blockButtonText = null;
var specialButtonText = null;
var leftMoveButton = null;
var rightMoveButton = null;
var leftMoveButtonText = null;
var rightMoveButtonText = null;
var crouchButton = null;
var jumpButton = null;
var crouchButtonText = null;
var jumpButtonText = null;
var isMovingLeft = false;
var isMovingRight = false;
var enemyIsMovingLeft = false;
var enemyIsMovingRight = false;
var enemyMovementTimer = 0;
// UI elements
var titleText = new Text2('Arena Warriors', {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
LK.gui.top.addChild(titleText);
titleText.y = 50;
var instructionText = new Text2('Select Your Fighter', {
size: 50,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
// Combat controls text
var controlsText = new Text2('Left: Move | Right: Move | Center Left: Punch | Center Right: Kick | Top: Block | Bottom: Special', {
size: 30,
fill: 0xFFFFFF
});
controlsText.anchor.set(0.5, 1);
function initCharacterSelection() {
instructionText.y = 200;
game.addChild(instructionText);
// Create character selection grid
for (var i = 1; i <= 5; i++) {
var fighter = LK.getAsset('fighter' + i, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7,
scaleY: 0.7
});
var col = (i - 1) % 3;
var row = Math.floor((i - 1) / 3);
fighter.x = 400 + col * 300;
fighter.y = 600 + row * 350;
fighter.fighterIndex = i;
characterSelectors.push(fighter);
game.addChild(fighter);
}
// Create selection border
selectionBorder = LK.getAsset('selectionBorder', {
anchorX: 0.5,
anchorY: 0.5
});
selectionBorder.alpha = 0.3;
updateSelectionBorder();
game.addChild(selectionBorder);
}
function updateSelectionBorder() {
if (selectionBorder && characterSelectors[selectedCharacter - 1]) {
selectionBorder.x = characterSelectors[selectedCharacter - 1].x;
selectionBorder.y = characterSelectors[selectedCharacter - 1].y;
}
}
function startCombat() {
gameState = 'combat';
// Clear character selection
game.removeChild(instructionText);
for (var i = 0; i < characterSelectors.length; i++) {
game.removeChild(characterSelectors[i]);
}
game.removeChild(selectionBorder);
// Create fighters
player = game.addChild(new Fighter(selectedCharacter, true));
player.x = 400;
player.y = 2200;
enemy = game.addChild(new Fighter(enemyCharacter, false));
enemy.x = 1648;
enemy.y = 2200;
// Create health and energy bars
playerHealthBar = game.addChild(new HealthBar(player, 150, 150));
playerEnergyBar = game.addChild(new EnergyBar(player, 150, 200));
playerSpecialBar = game.addChild(new SpecialBar(player, 150, 250));
enemyHealthBar = game.addChild(new HealthBar(enemy, 1498, 150));
enemyEnergyBar = game.addChild(new EnergyBar(enemy, 1498, 200));
enemySpecialBar = game.addChild(new SpecialBar(enemy, 1498, 250));
// Create combat control buttons
punchButton = LK.getAsset('punchButton', {
anchorX: 0.5,
anchorY: 0.5
});
punchButton.x = 350;
punchButton.y = 2500;
game.addChild(punchButton);
kickButton = LK.getAsset('kickButton', {
anchorX: 0.5,
anchorY: 0.5
});
kickButton.x = 700;
kickButton.y = 2500;
game.addChild(kickButton);
rangeButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5
});
rangeButton.x = 1400;
rangeButton.y = 2500;
game.addChild(rangeButton);
blockButton = LK.getAsset('blockButton', {
anchorX: 0.5,
anchorY: 0.5
});
blockButton.x = 1050;
blockButton.y = 2400;
game.addChild(blockButton);
specialButton = LK.getAsset('specialButton', {
anchorX: 0.5,
anchorY: 0.5
});
specialButton.x = 1050;
specialButton.y = 2600;
game.addChild(specialButton);
// Create movement buttons on the right side
leftMoveButton = LK.getAsset('leftMoveButton', {
anchorX: 0.5,
anchorY: 0.5
});
leftMoveButton.x = 1650;
leftMoveButton.y = 2450;
game.addChild(leftMoveButton);
rightMoveButton = LK.getAsset('rightMoveButton', {
anchorX: 0.5,
anchorY: 0.5
});
rightMoveButton.x = 1850;
rightMoveButton.y = 2450;
game.addChild(rightMoveButton);
// Create crouch and jump buttons
crouchButton = LK.getAsset('crouchButton', {
anchorX: 0.5,
anchorY: 0.5
});
crouchButton.x = 1750;
crouchButton.y = 2500;
game.addChild(crouchButton);
jumpButton = LK.getAsset('jumpButton', {
anchorX: 0.5,
anchorY: 0.5
});
jumpButton.x = 1750;
jumpButton.y = 2400;
game.addChild(jumpButton);
// Add button labels
punchButtonText = new Text2('PUNCH', {
size: 30,
fill: 0xFFFFFF
});
punchButtonText.anchor.set(0.5, 0.5);
punchButtonText.x = punchButton.x;
punchButtonText.y = punchButton.y;
game.addChild(punchButtonText);
kickButtonText = new Text2('KICK', {
size: 30,
fill: 0xFFFFFF
});
kickButtonText.anchor.set(0.5, 0.5);
kickButtonText.x = kickButton.x;
kickButtonText.y = kickButton.y;
game.addChild(kickButtonText);
rangeButtonText = new Text2('RANGE', {
size: 30,
fill: 0xFFFFFF
});
rangeButtonText.anchor.set(0.5, 0.5);
rangeButtonText.x = rangeButton.x;
rangeButtonText.y = rangeButton.y;
game.addChild(rangeButtonText);
blockButtonText = new Text2('BLOCK', {
size: 30,
fill: 0xFFFFFF
});
blockButtonText.anchor.set(0.5, 0.5);
blockButtonText.x = blockButton.x;
blockButtonText.y = blockButton.y;
game.addChild(blockButtonText);
specialButtonText = new Text2('SPECIAL', {
size: 30,
fill: 0xFFFFFF
});
specialButtonText.anchor.set(0.5, 0.5);
specialButtonText.x = specialButton.x;
specialButtonText.y = specialButton.y;
game.addChild(specialButtonText);
leftMoveButtonText = new Text2('←', {
size: 60,
fill: 0xFFFFFF
});
leftMoveButtonText.anchor.set(0.5, 0.5);
leftMoveButtonText.x = leftMoveButton.x;
leftMoveButtonText.y = leftMoveButton.y;
game.addChild(leftMoveButtonText);
rightMoveButtonText = new Text2('→', {
size: 60,
fill: 0xFFFFFF
});
rightMoveButtonText.anchor.set(0.5, 0.5);
rightMoveButtonText.x = rightMoveButton.x;
rightMoveButtonText.y = rightMoveButton.y;
game.addChild(rightMoveButtonText);
crouchButtonText = new Text2('↓', {
size: 60,
fill: 0xFFFFFF
});
crouchButtonText.anchor.set(0.5, 0.5);
crouchButtonText.x = crouchButton.x;
crouchButtonText.y = crouchButton.y;
game.addChild(crouchButtonText);
jumpButtonText = new Text2('↑', {
size: 60,
fill: 0xFFFFFF
});
jumpButtonText.anchor.set(0.5, 0.5);
jumpButtonText.x = jumpButton.x;
jumpButtonText.y = jumpButton.y;
game.addChild(jumpButtonText);
// Add controls text
controlsText.setText('Tap buttons to fight! Use arrow buttons to move.');
controlsText.y = 2600;
game.addChild(controlsText);
// Add player and enemy name labels
var playerLabel = new Text2('Player', {
size: 40,
fill: 0xFFFFFF
});
playerLabel.anchor.set(0, 0);
playerLabel.x = 150;
playerLabel.y = 100;
game.addChild(playerLabel);
var enemyLabel = new Text2('Enemy', {
size: 40,
fill: 0xFFFFFF
});
enemyLabel.anchor.set(1, 0);
enemyLabel.x = 1898;
enemyLabel.y = 100;
game.addChild(enemyLabel);
}
function handleCombatInput(x, y) {
if (!player || gameState !== 'combat') return;
var gameWidth = 2048;
var gameHeight = 2732;
// Check button presses first
if (punchButton && Math.abs(x - punchButton.x) < 100 && Math.abs(y - punchButton.y) < 40) {
// Punch button pressed
if (player.attack()) {
var hit = checkMeleeHit(player, enemy, Math.floor(player.attackDamage * 0.75), 'punch');
if (hit) player.chargeSpecial(15); // Charge special on successful hit
LK.getSound('punch').play();
}
return;
}
if (kickButton && Math.abs(x - kickButton.x) < 100 && Math.abs(y - kickButton.y) < 40) {
// Kick button pressed - can't kick while crouching
if (!player.isCrouching && player.attack()) {
var hit = checkMeleeHit(player, enemy, Math.floor((player.attackDamage + 1) * 0.75), 'kick');
if (hit) player.chargeSpecial(15); // Charge special on successful hit
LK.getSound('kick').play();
}
return;
}
if (rangeButton && Math.abs(x - rangeButton.x) < 100 && Math.abs(y - rangeButton.y) < 40) {
// Range attack button pressed
// Check if enemy is in front of player (player shoots right, so enemy should be to the right)
if (enemy && enemy.x > player.x && player.specialAttack()) {
// Adjust projectile origin based on player stance
var projectileY = player.y - 100; // Default standing position
if (player.isCrouching && !player.isJumping) {
projectileY = player.y - 50; // Lower origin when crouching
} else if (player.isJumping) {
projectileY = player.y - 150; // Higher origin when jumping
}
var projectile = new Projectile(player.x + 50, projectileY, 1, player.specialDamage, player);
projectiles.push(projectile);
game.addChild(projectile);
player.chargeSpecial(7); // Charge special at 50% rate (15 * 0.5 = 7.5, rounded to 7)
LK.getSound('special').play();
}
return;
}
if (specialButton && Math.abs(x - specialButton.x) < 100 && Math.abs(y - specialButton.y) < 40) {
// Special button pressed
// Check if enemy is in front of player (player shoots right, so enemy should be to the right)
if (enemy && enemy.x > player.x && player.useSpecialAttack()) {
// Adjust super projectile origin based on player stance
var superProjectileY = player.y - 100; // Default standing position
if (player.isCrouching && !player.isJumping) {
superProjectileY = player.y - 50; // Lower origin when crouching
} else if (player.isJumping) {
superProjectileY = player.y - 150; // Higher origin when jumping
}
// Create 7 super projectiles fired sequentially
for (var i = 0; i < 7; i++) {
(function (index) {
LK.setTimeout(function () {
var angleOffset = (index - 3) * 15; // Spread from -45 to +45 degrees
var radians = angleOffset * Math.PI / 180;
var projectileX = player.x + 50;
var projectileYOffset = superProjectileY + (index - 3) * 20; // Vertical spread
var superProjectile = new SuperProjectile(projectileX, projectileYOffset, 1, Math.floor(player.specialDamage * 2 / 7), player);
// Reduce range by modifying speed
superProjectile.speed = 3; // Reduced from 6 to 3 for lower range
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
}, index * 100); // 100ms delay between each projectile
})(i);
}
// Push back the shooter when firing special attack
var shooterPushDirection = -1; // Player pushes back to the left when shooting right
var shooterNewX = player.x + shooterPushDirection * 40;
shooterNewX = Math.max(200, Math.min(1848, shooterNewX));
tween(player, {
x: shooterNewX
}, {
duration: 200,
easing: tween.easeOut
});
LK.getSound('special').play();
}
return;
}
if (blockButton && Math.abs(x - blockButton.x) < 100 && Math.abs(y - blockButton.y) < 40) {
// Block button pressed
if (!playerIsBlocking) {
playerBlockStartTime = LK.ticks;
playerIsBlocking = true;
}
player.isBlocking = true;
LK.getSound('block').play();
return;
}
if (leftMoveButton && Math.abs(x - leftMoveButton.x) < 75 && Math.abs(y - leftMoveButton.y) < 75) {
// Left movement button pressed
if (!playerIsBlocking && player.x > 200) {
player.x -= player.speed * 10;
}
return;
}
if (rightMoveButton && Math.abs(x - rightMoveButton.x) < 75 && Math.abs(y - rightMoveButton.y) < 75) {
// Right movement button pressed
if (!playerIsBlocking && player.x < 1848) {
player.x += player.speed * 10;
}
return;
}
if (crouchButton && Math.abs(x - crouchButton.x) < 75 && Math.abs(y - crouchButton.y) < 40) {
// Crouch button pressed
player.crouch();
return;
}
if (jumpButton && Math.abs(x - jumpButton.x) < 75 && Math.abs(y - jumpButton.y) < 40) {
// Jump button pressed
player.jump();
return;
}
// Movement is now handled by dedicated buttons above
}
function checkMeleeHit(attacker, target, damage, attackType) {
var distance = Math.abs(attacker.x - target.x);
if (distance < 280) {
// Punch attacks can't hit crouching targets
if (attackType === 'punch' && target.isCrouching && !target.isJumping) {
return false; // Punch misses crouching target
}
if (target.isBlocking) {
// Attack was blocked - reduced damage and pushback
target.takeDamage(Math.floor(damage * 0.3));
LK.getSound('block').play();
// Apply pushback to the attacker
var pushDirection = attacker.x < target.x ? -1 : 1;
var pushDistance = 60;
var newX = attacker.x + pushDirection * pushDistance;
// Make sure attacker stays within bounds
newX = Math.max(200, Math.min(1848, newX));
// Animate the pushback using tween
tween(attacker, {
x: newX
}, {
duration: 200,
easing: tween.easeOut
});
// Flash the target to show block effect
LK.effects.flashObject(target, 0x4444ff, 300);
return false; // Hit was blocked
} else {
// Normal hit
target.takeDamage(damage);
return true; // Hit was successful
}
}
return false; // No hit
}
function updateAI() {
if (!enemy || !player) return;
var distance = Math.abs(enemy.x - player.x);
// Handle enemy movement holding
if (enemyMovementTimer > 0) {
enemyMovementTimer--;
if (enemyIsMovingLeft && enemy.x > 200) {
enemy.x -= enemy.speed * 2;
}
if (enemyIsMovingRight && enemy.x < 1848) {
enemy.x += enemy.speed * 2;
}
} else {
enemyIsMovingLeft = false;
enemyIsMovingRight = false;
}
// Enhanced AI behavior - mix of range attacks, melee attacks, movement, jumping and crouching
if (LK.ticks % 30 === 0) {
var action = Math.floor(Math.random() * 12); // Increased range to include jump/crouch actions
// Check if enemy is in melee range (close enough to punch/kick)
if (distance < 280) {
// In melee range - try to attack or block
if (action <= 3 && enemy.attack()) {
// Punch attack
var hit = checkMeleeHit(enemy, player, Math.floor(enemy.attackDamage * 0.75), 'punch');
if (hit) enemy.chargeSpecial(15); // Charge special on successful hit
LK.getSound('punch').play();
} else if (action <= 6 && !enemy.isCrouching && enemy.attack()) {
// Kick attack (slightly more damage) - can't kick while crouching
var hit = checkMeleeHit(enemy, player, Math.floor((enemy.attackDamage + 1) * 0.75), 'kick');
if (hit) enemy.chargeSpecial(15); // Charge special on successful hit
LK.getSound('kick').play();
} else if (action <= 8) {
// Block when not attacking
enemy.isBlocking = true;
} else if (action <= 9) {
// Back away occasionally when too close
if (enemy.x > player.x) {
enemyIsMovingRight = true;
enemyMovementTimer = 20; // Hold movement for 20 ticks
} else {
enemyIsMovingLeft = true;
enemyMovementTimer = 20; // Hold movement for 20 ticks
}
} else if (action <= 10) {
// Jump occasionally in melee range
enemy.jump();
} else {
// Crouch occasionally in melee range
enemy.crouch();
}
} else if (distance < 400) {
// Medium range - move closer for melee or use range attack
if (action <= 4) {
// Move closer to get into melee range
if (enemy.x > player.x) {
enemyIsMovingLeft = true;
enemyMovementTimer = 15; // Hold movement for 15 ticks
} else {
enemyIsMovingRight = true;
enemyMovementTimer = 15; // Hold movement for 15 ticks
}
} else if (action <= 6 && enemy.canUseSpecialAttack() && player.x < enemy.x && enemy.useSpecialAttack()) {
// Use super special attack - only if player is in front (to the left)
// Adjust super projectile origin based on enemy stance
var superProjectileY = enemy.y - 100; // Default standing position
if (enemy.isCrouching && !enemy.isJumping) {
superProjectileY = enemy.y - 50; // Lower origin when crouching
} else if (enemy.isJumping) {
superProjectileY = enemy.y - 150; // Higher origin when jumping
}
// Create 7 super projectiles fired sequentially
for (var i = 0; i < 7; i++) {
(function (index) {
LK.setTimeout(function () {
var angleOffset = (index - 3) * 15; // Spread from -45 to +45 degrees
var radians = angleOffset * Math.PI / 180;
var projectileX = enemy.x - 50;
var projectileYOffset = superProjectileY + (index - 3) * 20; // Vertical spread
var superProjectile = new SuperProjectile(projectileX, projectileYOffset, -1, Math.floor(enemy.specialDamage * 2 / 7), enemy);
// Reduce range by modifying speed
superProjectile.speed = 3; // Reduced from 6 to 3 for lower range
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
}, index * 100); // 100ms delay between each projectile
})(i);
}
// Push back the enemy when firing special attack
var shooterPushDirection = 1; // Enemy pushes back to the right when shooting left
var shooterNewX = enemy.x + shooterPushDirection * 40;
shooterNewX = Math.max(200, Math.min(1848, shooterNewX));
tween(enemy, {
x: shooterNewX
}, {
duration: 200,
easing: tween.easeOut
});
LK.getSound('special').play();
} else if (action <= 6 && enemy.energy >= 1 && player.x < enemy.x && enemy.specialAttack()) {
// Use range attack (reduced frequency) - only if player is in front (to the left)
// Adjust projectile origin based on enemy stance
var projectileY = enemy.y - 100; // Default standing position
if (enemy.isCrouching && !enemy.isJumping) {
projectileY = enemy.y - 50; // Lower origin when crouching
} else if (enemy.isJumping) {
projectileY = enemy.y - 150; // Higher origin when jumping
}
var projectile = new Projectile(enemy.x - 50, projectileY, -1, enemy.specialDamage, enemy);
projectiles.push(projectile);
game.addChild(projectile);
enemy.chargeSpecial(7); // Charge special at 50% rate (15 * 0.5 = 7.5, rounded to 7)
LK.getSound('special').play();
} else if (action <= 8) {
// Block occasionally
enemy.isBlocking = true;
} else if (action <= 9) {
// Jump occasionally at medium range
enemy.jump();
} else {
// Crouch occasionally at medium range
enemy.crouch();
}
} else {
// Long range - use range attacks or move closer
if (action <= 2 && enemy.canUseSpecialAttack() && player.x < enemy.x && enemy.useSpecialAttack()) {
// Use super special attack when available (reduced frequency) - only if player is in front (to the left)
// Adjust super projectile origin based on enemy stance
var superProjectileY = enemy.y - 100; // Default standing position
if (enemy.isCrouching && !enemy.isJumping) {
superProjectileY = enemy.y - 50; // Lower origin when crouching
} else if (enemy.isJumping) {
superProjectileY = enemy.y - 150; // Higher origin when jumping
}
// Create 7 super projectiles fired sequentially
for (var i = 0; i < 7; i++) {
(function (index) {
LK.setTimeout(function () {
var angleOffset = (index - 3) * 15; // Spread from -45 to +45 degrees
var radians = angleOffset * Math.PI / 180;
var projectileX = enemy.x - 50;
var projectileYOffset = superProjectileY + (index - 3) * 20; // Vertical spread
var superProjectile = new SuperProjectile(projectileX, projectileYOffset, -1, Math.floor(enemy.specialDamage * 2 / 7), enemy);
// Reduce range by modifying speed
superProjectile.speed = 3; // Reduced from 6 to 3 for lower range
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
}, index * 100); // 100ms delay between each projectile
})(i);
}
// Push back the enemy when firing special attack
var shooterPushDirection = 1; // Enemy pushes back to the right when shooting left
var shooterNewX = enemy.x + shooterPushDirection * 40;
shooterNewX = Math.max(200, Math.min(1848, shooterNewX));
tween(enemy, {
x: shooterNewX
}, {
duration: 200,
easing: tween.easeOut
});
LK.getSound('special').play();
} else if (action <= 3 && enemy.energy >= 1 && player.x < enemy.x && enemy.specialAttack()) {
// Use range attack when available (reduced frequency) - only if player is in front (to the left)
// Adjust projectile origin based on enemy stance
var projectileY = enemy.y - 100; // Default standing position
if (enemy.isCrouching && !enemy.isJumping) {
projectileY = enemy.y - 50; // Lower origin when crouching
} else if (enemy.isJumping) {
projectileY = enemy.y - 150; // Higher origin when jumping
}
var projectile = new Projectile(enemy.x - 50, projectileY, -1, enemy.specialDamage, enemy);
projectiles.push(projectile);
game.addChild(projectile);
enemy.chargeSpecial(7); // Charge special at 50% rate (15 * 0.5 = 7.5, rounded to 7)
LK.getSound('special').play();
} else if (action <= 8) {
// Move closer to player for melee combat
if (enemy.x > player.x) {
enemyIsMovingLeft = true;
enemyMovementTimer = 25; // Hold movement for 25 ticks
} else {
enemyIsMovingRight = true;
enemyMovementTimer = 25; // Hold movement for 25 ticks
}
} else if (action <= 9) {
// Occasionally block at range
enemy.isBlocking = true;
} else if (action <= 10) {
// Jump occasionally at long range
enemy.jump();
} else {
// Crouch occasionally at long range
enemy.crouch();
}
}
}
// Reset blocking and crouching periodically
if (LK.ticks % 45 === 0) {
enemy.isBlocking = false;
enemy.stopCrouch(); // Release crouch periodically
}
}
function checkGameOver() {
if (player && player.health <= 0) {
LK.showGameOver();
} else if (enemy && enemy.health <= 0) {
LK.showYouWin();
}
}
// Character selection input
game.down = function (x, y, obj) {
if (gameState === 'characterSelect') {
// Check which character was selected
for (var i = 0; i < characterSelectors.length; i++) {
var fighter = characterSelectors[i];
// Use x,y coordinates directly since they're already in game coordinates
if (Math.abs(x - fighter.x) < 100 && Math.abs(y - fighter.y) < 150) {
selectedCharacter = fighter.fighterIndex;
enemyCharacter = selectedCharacter % 5 + 1; // Simple enemy selection
updateSelectionBorder();
// Start combat after selection
LK.setTimeout(function () {
startCombat();
}, 500);
break;
}
}
} else if (gameState === 'combat') {
handleCombatInput(x, y);
}
};
game.move = function (x, y, obj) {
if (gameState === 'combat' && player && !playerIsBlocking) {
// Check if moving over left button
if (leftMoveButton && Math.abs(x - leftMoveButton.x) < 75 && Math.abs(y - leftMoveButton.y) < 75) {
isMovingLeft = true;
} else {
isMovingLeft = false;
}
// Check if moving over right button
if (rightMoveButton && Math.abs(x - rightMoveButton.x) < 75 && Math.abs(y - rightMoveButton.y) < 75) {
isMovingRight = true;
} else {
isMovingRight = false;
}
// Check if holding crouch button
if (crouchButton && Math.abs(x - crouchButton.x) < 75 && Math.abs(y - crouchButton.y) < 40) {
player.crouch();
}
}
};
game.up = function (x, y, obj) {
if (player && gameState === 'combat') {
player.isBlocking = false;
playerIsBlocking = false;
isMovingLeft = false;
isMovingRight = false;
player.stopCrouch();
}
};
game.update = function () {
if (gameState === 'combat') {
// Update fighters
if (player) player.update();
if (enemy) enemy.update();
// Update UI bars
if (playerHealthBar) playerHealthBar.update();
if (playerEnergyBar) playerEnergyBar.update();
if (playerSpecialBar) playerSpecialBar.update();
if (enemyHealthBar) enemyHealthBar.update();
if (enemyEnergyBar) enemyEnergyBar.update();
if (enemySpecialBar) enemySpecialBar.update();
// Update button availability visual feedback
if (rangeButtonText && player) {
if (player.energy >= player.specialCost) {
rangeButtonText.tint = 0xFFFFFF; // White when available
} else {
rangeButtonText.tint = 0x666666; // Gray when not available
}
}
if (specialButtonText && player) {
if (player.canUseSpecialAttack()) {
specialButtonText.tint = 0xFFFFFF; // White when available
} else {
specialButtonText.tint = 0x666666; // Gray when not available
}
}
// Update super projectiles
for (var i = superProjectiles.length - 1; i >= 0; i--) {
var superProj = superProjectiles[i];
superProj.update();
// Check for super projectile clashes
for (var j = superProjectiles.length - 1; j >= 0; j--) {
if (i !== j) {
var otherSuperProj = superProjectiles[j];
if (Math.abs(superProj.x - otherSuperProj.x) < 80 && Math.abs(superProj.y - otherSuperProj.y) < 80) {
// Super projectiles clash - destroy both
LK.effects.flashScreen(0xffffff, 200);
superProj.destroy();
otherSuperProj.destroy();
superProjectiles.splice(Math.max(i, j), 1);
superProjectiles.splice(Math.min(i, j), 1);
i = Math.min(i, j) - 1; // Adjust index
break;
}
}
}
if (i >= 0 && i < superProjectiles.length) {
var superProj = superProjectiles[i];
// Check super projectile hits
var target = superProj.owner === player ? enemy : player;
if (target && Math.abs(superProj.x - target.x) < 100 && Math.abs(superProj.y - target.y) < 150) {
if (target.isBlocking) {
// Super projectile was blocked - apply 50% damage and pushback
target.takeDamage(superProj.damage, true, superProj.owner);
LK.getSound('block').play();
// Push back the shooter (attacker) - increased distance
var shooterPushDirection = superProj.owner.x < target.x ? -1 : 1;
var shooterNewX = superProj.owner.x + shooterPushDirection * 150;
shooterNewX = Math.max(200, Math.min(1848, shooterNewX));
tween(superProj.owner, {
x: shooterNewX
}, {
duration: 400,
easing: tween.easeOut
});
// Push back the receiver (target) - much stronger pushback
var targetPushDirection = target.x < superProj.owner.x ? -1 : 1;
var targetNewX = target.x + targetPushDirection * 200;
targetNewX = Math.max(200, Math.min(1848, targetNewX));
tween(target, {
x: targetNewX
}, {
duration: 500,
easing: tween.easeOut
});
// Flash the target to show block effect
LK.effects.flashObject(target, 0x4444ff, 400);
} else {
// Normal hit
target.takeDamage(superProj.damage, true, superProj.owner);
// Push back the target when receiving super projectile hit - much stronger pushback
var targetPushDirection = target.x < superProj.owner.x ? -1 : 1;
var targetNewX = target.x + targetPushDirection * 250;
targetNewX = Math.max(200, Math.min(1848, targetNewX));
tween(target, {
x: targetNewX
}, {
duration: 600,
easing: tween.easeOut
});
}
superProj.destroy();
superProjectiles.splice(i, 1);
continue;
}
// Remove off-screen super projectiles
if (superProj.x < -50 || superProj.x > 2098) {
superProj.destroy();
superProjectiles.splice(i, 1);
}
}
}
// Update projectiles
for (var i = projectiles.length - 1; i >= 0; i--) {
var proj = projectiles[i];
proj.update();
// Check for projectile clashes (range attacks destroying each other)
for (var j = projectiles.length - 1; j >= 0; j--) {
if (i !== j) {
var otherProj = projectiles[j];
if (Math.abs(proj.x - otherProj.x) < 50 && Math.abs(proj.y - otherProj.y) < 50) {
// Regular projectiles clash - destroy both
LK.effects.flashScreen(0xffffff, 150);
proj.destroy();
otherProj.destroy();
projectiles.splice(Math.max(i, j), 1);
projectiles.splice(Math.min(i, j), 1);
i = Math.min(i, j) - 1; // Adjust index
break;
}
}
}
if (i >= 0 && i < projectiles.length) {
var proj = projectiles[i];
// Check if regular projectile hits super projectile
for (var j = superProjectiles.length - 1; j >= 0; j--) {
var superProj = superProjectiles[j];
if (Math.abs(proj.x - superProj.x) < 60 && Math.abs(proj.y - superProj.y) < 60) {
// Regular projectile destroyed by super projectile
proj.destroy();
projectiles.splice(i, 1);
break;
}
}
}
if (i >= 0 && i < projectiles.length) {
var proj = projectiles[i];
// Check projectile hits
var target = proj.owner === player ? enemy : player;
if (target && Math.abs(proj.x - target.x) < 100 && Math.abs(proj.y - target.y) < 150) {
target.takeDamage(proj.damage);
proj.owner.chargeSpecial(7); // Charge special at 50% rate for successful range hit
proj.destroy();
projectiles.splice(i, 1);
continue;
}
// Remove off-screen projectiles
if (proj.x < -50 || proj.x > 2098) {
proj.destroy();
projectiles.splice(i, 1);
}
}
}
// Handle continuous movement
if (player && !playerIsBlocking) {
if (isMovingLeft && player.x > 200) {
player.x -= player.speed * 3;
}
if (isMovingRight && player.x < 1848) {
player.x += player.speed * 3;
}
}
// Update AI
updateAI();
// Check game over
checkGameOver();
}
};
// Keyboard event handler
LK.on('keydown', function (event) {
if (gameState !== 'combat' || !player) return;
var key = event.key.toLowerCase();
if (key === 'z') {
// Z key - Punch
if (player.attack()) {
checkMeleeHit(player, enemy, Math.floor(player.attackDamage * 0.75), 'punch');
LK.getSound('punch').play();
}
} else if (key === 'x') {
// X key - Kick - can't kick while crouching
if (!player.isCrouching && player.attack()) {
checkMeleeHit(player, enemy, Math.floor((player.attackDamage + 1) * 0.75), 'kick');
LK.getSound('kick').play();
}
} else if (key === 'c') {
// C key - Range attack (special)
// Check if enemy is in front of player (player shoots right, so enemy should be to the right)
if (enemy && enemy.x > player.x && player.specialAttack()) {
// Adjust projectile origin based on player stance
var projectileY = player.y - 100; // Default standing position
if (player.isCrouching && !player.isJumping) {
projectileY = player.y - 50; // Lower origin when crouching
} else if (player.isJumping) {
projectileY = player.y - 150; // Higher origin when jumping
}
var projectile = new Projectile(player.x + 50, projectileY, 1, player.specialDamage, player);
projectiles.push(projectile);
game.addChild(projectile);
player.chargeSpecial(7); // Charge special at 50% rate (15 * 0.5 = 7.5, rounded to 7)
LK.getSound('special').play();
}
} else if (key === 'v') {
// V key - Super special attack
// Check if enemy is in front of player (player shoots right, so enemy should be to the right)
if (enemy && enemy.x > player.x && player.useSpecialAttack()) {
// Adjust super projectile origin based on player stance
var superProjectileY = player.y - 100; // Default standing position
if (player.isCrouching && !player.isJumping) {
superProjectileY = player.y - 50; // Lower origin when crouching
} else if (player.isJumping) {
superProjectileY = player.y - 150; // Higher origin when jumping
}
// Create 7 super projectiles fired sequentially
for (var i = 0; i < 7; i++) {
(function (index) {
LK.setTimeout(function () {
var angleOffset = (index - 3) * 15; // Spread from -45 to +45 degrees
var radians = angleOffset * Math.PI / 180;
var projectileX = player.x + 50;
var projectileYOffset = superProjectileY + (index - 3) * 20; // Vertical spread
var superProjectile = new SuperProjectile(projectileX, projectileYOffset, 1, Math.floor(player.specialDamage * 2 / 7), player);
// Reduce range by modifying speed
superProjectile.speed = 3; // Reduced from 6 to 3 for lower range
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
}, index * 100); // 100ms delay between each projectile
})(i);
}
// Push back the shooter when firing special attack
var shooterPushDirection = -1; // Player pushes back to the left when shooting right
var shooterNewX = player.x + shooterPushDirection * 40;
shooterNewX = Math.max(200, Math.min(1848, shooterNewX));
tween(player, {
x: shooterNewX
}, {
duration: 200,
easing: tween.easeOut
});
LK.getSound('special').play();
}
}
});
// Initialize character selection screen
initCharacterSelection();
; ===================================================================
--- original.js
+++ change.js
@@ -609,9 +609,10 @@
return;
}
if (rangeButton && Math.abs(x - rangeButton.x) < 100 && Math.abs(y - rangeButton.y) < 40) {
// Range attack button pressed
- if (player.specialAttack()) {
+ // Check if enemy is in front of player (player shoots right, so enemy should be to the right)
+ if (enemy && enemy.x > player.x && player.specialAttack()) {
// Adjust projectile origin based on player stance
var projectileY = player.y - 100; // Default standing position
if (player.isCrouching && !player.isJumping) {
projectileY = player.y - 50; // Lower origin when crouching
@@ -627,9 +628,10 @@
return;
}
if (specialButton && Math.abs(x - specialButton.x) < 100 && Math.abs(y - specialButton.y) < 40) {
// Special button pressed
- if (player.useSpecialAttack()) {
+ // Check if enemy is in front of player (player shoots right, so enemy should be to the right)
+ if (enemy && enemy.x > player.x && player.useSpecialAttack()) {
// Adjust super projectile origin based on player stance
var superProjectileY = player.y - 100; // Default standing position
if (player.isCrouching && !player.isJumping) {
superProjectileY = player.y - 50; // Lower origin when crouching
@@ -798,10 +800,10 @@
} else {
enemyIsMovingRight = true;
enemyMovementTimer = 15; // Hold movement for 15 ticks
}
- } else if (action <= 6 && enemy.canUseSpecialAttack() && enemy.useSpecialAttack()) {
- // Use super special attack
+ } else if (action <= 6 && enemy.canUseSpecialAttack() && player.x < enemy.x && enemy.useSpecialAttack()) {
+ // Use super special attack - only if player is in front (to the left)
// Adjust super projectile origin based on enemy stance
var superProjectileY = enemy.y - 100; // Default standing position
if (enemy.isCrouching && !enemy.isJumping) {
superProjectileY = enemy.y - 50; // Lower origin when crouching
@@ -834,10 +836,10 @@
duration: 200,
easing: tween.easeOut
});
LK.getSound('special').play();
- } else if (action <= 6 && enemy.energy >= 1 && enemy.specialAttack()) {
- // Use range attack (reduced frequency)
+ } else if (action <= 6 && enemy.energy >= 1 && player.x < enemy.x && enemy.specialAttack()) {
+ // Use range attack (reduced frequency) - only if player is in front (to the left)
// Adjust projectile origin based on enemy stance
var projectileY = enemy.y - 100; // Default standing position
if (enemy.isCrouching && !enemy.isJumping) {
projectileY = enemy.y - 50; // Lower origin when crouching
@@ -860,10 +862,10 @@
enemy.crouch();
}
} else {
// Long range - use range attacks or move closer
- if (action <= 2 && enemy.canUseSpecialAttack() && enemy.useSpecialAttack()) {
- // Use super special attack when available (reduced frequency)
+ if (action <= 2 && enemy.canUseSpecialAttack() && player.x < enemy.x && enemy.useSpecialAttack()) {
+ // Use super special attack when available (reduced frequency) - only if player is in front (to the left)
// Adjust super projectile origin based on enemy stance
var superProjectileY = enemy.y - 100; // Default standing position
if (enemy.isCrouching && !enemy.isJumping) {
superProjectileY = enemy.y - 50; // Lower origin when crouching
@@ -896,10 +898,10 @@
duration: 200,
easing: tween.easeOut
});
LK.getSound('special').play();
- } else if (action <= 3 && enemy.energy >= 1 && enemy.specialAttack()) {
- // Use range attack when available (reduced frequency)
+ } else if (action <= 3 && enemy.energy >= 1 && player.x < enemy.x && enemy.specialAttack()) {
+ // Use range attack when available (reduced frequency) - only if player is in front (to the left)
// Adjust projectile origin based on enemy stance
var projectileY = enemy.y - 100; // Default standing position
if (enemy.isCrouching && !enemy.isJumping) {
projectileY = enemy.y - 50; // Lower origin when crouching
@@ -1182,9 +1184,10 @@
LK.getSound('kick').play();
}
} else if (key === 'c') {
// C key - Range attack (special)
- if (player.specialAttack()) {
+ // Check if enemy is in front of player (player shoots right, so enemy should be to the right)
+ if (enemy && enemy.x > player.x && player.specialAttack()) {
// Adjust projectile origin based on player stance
var projectileY = player.y - 100; // Default standing position
if (player.isCrouching && !player.isJumping) {
projectileY = player.y - 50; // Lower origin when crouching
@@ -1198,9 +1201,10 @@
LK.getSound('special').play();
}
} else if (key === 'v') {
// V key - Super special attack
- if (player.useSpecialAttack()) {
+ // Check if enemy is in front of player (player shoots right, so enemy should be to the right)
+ if (enemy && enemy.x > player.x && player.useSpecialAttack()) {
// Adjust super projectile origin based on player stance
var superProjectileY = player.y - 100; // Default standing position
if (player.isCrouching && !player.isJumping) {
superProjectileY = player.y - 50; // Lower origin when crouching
transparent bubble. In-Game asset. 2d. High contrast. No shadows
shield
arm with a fist
band-aid
a little bit smaller image
hornless
whitte
whole gloves
fire
transparent kicking feet simbol. In-Game asset. 2d. High contrast. No shadows
red
2D
crouching with blue background
teeth close to bite
scratch attack
teeth
toothless open mouth
shark teeth. In-Game asset. 2d. High contrast. No shadows
simbolo transparente de bala. In-Game asset. 2d. High contrast. No shadows
transparent fist simbol. In-Game asset. 2d. High contrast. No shadows
transparent fire simbol. In-Game asset. 2d. High contrast. No shadows
right arrow. In-Game asset. 2d. High contrast. No shadows
add sand
building roof