User prompt
a bit less
User prompt
a bit less
User prompt
a bit less
User prompt
a bit more
User prompt
move the player healt energy and special attack bars to the left
User prompt
move it to the top center of the screen
User prompt
move the menu buttom in the combat a bit to the right
User prompt
make hard mode enemy ai smarter and let it predict a few attacks
User prompt
fix: normal difficulty selected doesnt let start combat
User prompt
add again the mechanic to dont be able to start combat untill a character and difficulty are selected
User prompt
move combat buttoms a bit to the right and movement a bit to the left
User prompt
make movement buttoms bigger and separate them enougth to dont be over each other
User prompt
make punch ASSET smaller and make movement buttoms bigger
User prompt
separate them more and make them a bit bigger
User prompt
setarate all combat buttoms a bit
User prompt
move the punch,kick,block,range and special buttoms higer and make movement buttoms bigger
User prompt
make the buttoms a bit bigger
User prompt
put some separation bethwhen the punch,kick,block range and special buttoms
User prompt
a bit bigger
User prompt
make all combat buttoms bigger
User prompt
move figthers (only in combat) higer
User prompt
add jump
User prompt
un-do that and re-add the jump mechanic
User prompt
fix jump buttom
User prompt
un-do the zise change
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.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 * 335; // Space bars evenly (1000/3 ≈ 333)
energyBar.width = 310; // 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 = 7;
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 = 15;
self.originalY = 0;
self.gravity = 0.12;
self.velocityY = 0;
self.groundY = 1800; // Ground level for all fighters - adjusted for horizontal layout and moved higher
// Create fighter graphics
var fighterGraphics = self.attachAsset('fighter' + self.fighterType, {
anchorX: 0.5,
anchorY: 1.0
});
// Create blocking shield (initially hidden)
var blockingShield = self.attachAsset('blockAsset', {
anchorX: 0.5,
anchorY: 1.0,
alpha: 0.0
});
blockingShield.visible = false;
// Animation properties
self.currentAnimation = 'normal';
self.animationTimer = 0;
self.animationDuration = 0;
self.isWalking = false;
self.isCrouchingAnimated = false;
self.lastX = self.x;
self.walkingAnimationTimer = 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;
}
// Apply difficulty modifiers for enemy fighters
if (!self.isPlayer && gameDifficulty) {
if (gameDifficulty === 'easy') {
self.attackDamage = Math.floor(self.attackDamage * 0.7);
self.specialDamage = Math.floor(self.specialDamage * 0.7);
self.speed = Math.floor(self.speed * 0.8);
self.maxHealth = Math.floor(self.maxHealth * 0.8);
self.health = self.maxHealth;
} else if (gameDifficulty === 'hard') {
self.attackDamage = Math.floor(self.attackDamage * 1.3);
self.specialDamage = Math.floor(self.specialDamage * 1.3);
self.speed = Math.floor(self.speed * 1.2);
self.maxHealth = Math.floor(self.maxHealth * 1.2);
self.health = self.maxHealth;
}
}
// Track if this fighter has taken damage yet
self.hasBeenDamaged = false;
self.takeDamage = function (damage, isSuperProjectile, attacker) {
// Prevent multiple damage calls when fighter is already defeated
if (self.health <= 0 || self.isBeingDefeated) {
return; // No damage taken, fighter is already defeated or being defeated
}
// In team battle mode, prevent damage to fighters that haven't been damaged yet unless they are the current active fighter
if (gameMode === 'teamBattle') {
var isCurrentPlayerFighter = self.isPlayer && self === player;
var isCurrentEnemyFighter = !self.isPlayer && self === enemy;
var isCurrentActiveFighter = isCurrentPlayerFighter || isCurrentEnemyFighter;
// If this fighter hasn't been damaged yet and isn't the current active fighter, make them invulnerable
if (!self.hasBeenDamaged && !isCurrentActiveFighter) {
return; // No damage taken, fighter is invulnerable
}
}
if (self.isPlayer && playerIsBlocking) {
// Check if within perfect block window (0.5 seconds = 30 ticks at 60fps)
var timeSinceBlockStart = LK.ticks - playerBlockStartTime;
if (timeSinceBlockStart <= 30) {
// 30 ticks = 0.5 seconds at 60fps
damage = Math.floor(damage * 0.5); // 50% damage reduction (reduced from 100%)
// Show brief white flash effect during immunity period (like blue flash when blocked)
LK.effects.flashObject(fighterGraphics, 0xffffff, 200);
} else {
if (isSuperProjectile) {
damage = Math.floor(damage * 0.85); // Only 15% damage reduction for super projectiles after perfect block window (85% damage goes through)
} else {
damage = Math.floor(damage * 0.7); // 30% damage reduction for regular attacks after perfect block window
}
}
} else if (self.isBlocking) {
if (isSuperProjectile) {
damage = Math.floor(damage * 0.85); // Only 15% damage reduction when blocking super projectile (85% damage goes through)
} else {
damage = Math.floor(damage * 0.7); // 30% damage reduction for normal blocking (reduced from 50%)
}
}
// Mark fighter as having been damaged (once they take any damage)
if (damage > 0) {
self.hasBeenDamaged = true;
}
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 (attackType) {
if (self.attackCooldown <= 0) {
self.attackCooldown = 30;
self.lastAttackType = attackType || 'punch';
return true;
}
return false;
};
self.specialAttack = function (specialType) {
if (self.specialCooldown <= 0 && self.useEnergy(self.specialCost)) {
self.specialCooldown = 90;
self.lastSpecialType = specialType || 'range';
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;
if (self.currentAnimation === 'normal') {
self.setAnimation('crouching');
self.isCrouchingAnimated = true;
}
}
};
self.stopCrouch = function () {
self.isCrouching = false;
if (self.isCrouchingAnimated && self.currentAnimation === 'crouching') {
self.setAnimation('normal');
self.isCrouchingAnimated = 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.setAnimation = function (animationType, duration) {
if (animationType === self.currentAnimation) return;
self.currentAnimation = animationType;
self.animationTimer = duration || 0;
// Store current direction before removing graphics
var currentDirection = fighterGraphics.scaleX;
// Remove current graphics
self.removeChild(fighterGraphics);
// Add new graphics based on animation
var assetName = 'fighter' + self.fighterType;
if (animationType === 'punching') {
assetName = 'punchingAnimation' + self.fighterType;
} else if (animationType === 'kicking') {
assetName = 'kickAnimation' + self.fighterType;
} else if (animationType === 'walking') {
assetName = 'walkingAnimation' + self.fighterType;
} else if (animationType === 'crouching') {
assetName = 'crouchingAnimation' + self.fighterType;
} else if (animationType === 'rangeShooting') {
assetName = 'rangeShoot' + self.fighterType;
} else if (animationType === 'potentShooting') {
assetName = 'potentShoot' + self.fighterType;
}
fighterGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 1.0
});
// Maintain direction after asset change
fighterGraphics.scaleX = currentDirection;
};
self.update = function () {
// Direction checking - determine if asset should face left or right
if (player && enemy) {
var shouldFaceRight = false;
if (self === player) {
shouldFaceRight = enemy.x > player.x; // Player faces enemy
} else if (self === enemy) {
shouldFaceRight = player.x > enemy.x; // Enemy faces player
}
// Update asset direction only when needed to prevent flashing
var currentFacingRight = fighterGraphics.scaleX > 0;
if (currentFacingRight !== shouldFaceRight) {
if (shouldFaceRight) {
fighterGraphics.scaleX = Math.abs(fighterGraphics.scaleX); // Face right
} else {
fighterGraphics.scaleX = -Math.abs(fighterGraphics.scaleX); // Face left
}
}
}
// Walking animation detection
var currentlyWalking = Math.abs(self.x - self.lastX) > 0.5;
if (currentlyWalking && !self.isWalking && self.currentAnimation === 'normal') {
self.setAnimation('walking');
self.isWalking = true;
self.walkingAnimationTimer = 0;
} else if (!currentlyWalking && self.isWalking && self.currentAnimation === 'walking') {
self.setAnimation('normal');
self.isWalking = false;
}
// Crouching animation detection
if (self.isCrouching && !self.isCrouchingAnimated && self.currentAnimation === 'normal') {
self.setAnimation('crouching');
self.isCrouchingAnimated = true;
} else if (!self.isCrouching && self.isCrouchingAnimated && self.currentAnimation === 'crouching') {
self.setAnimation('normal');
self.isCrouchingAnimated = false;
}
self.lastX = self.x;
// Animation management
if (self.animationTimer > 0) {
self.animationTimer--;
if (self.animationTimer <= 0) {
self.setAnimation('normal');
self.isWalking = false;
}
}
// Cooldown management
if (self.attackCooldown > 0) self.attackCooldown--;
if (self.specialCooldown > 0) self.specialCooldown--;
// Energy regeneration - regenerate 1 energy bar every 10 seconds (600 ticks), only one bar at a time
// Initialize lastEnergyRegenTime if not set
if (self.lastEnergyRegenTime === undefined) {
self.lastEnergyRegenTime = 0;
}
// Check if 10 seconds (600 ticks) have passed since last regeneration
if (self.energy < self.maxEnergy && LK.ticks - self.lastEnergyRegenTime >= 600) {
// Only regenerate if we're exactly at a whole number threshold (0, 1, or 2)
var currentEnergyLevel = Math.floor(self.energy);
// Only regenerate if current energy is exactly at the integer threshold
// This ensures sequential regeneration: 0->1, then 1->2, then 2->3
if (self.energy === currentEnergyLevel && currentEnergyLevel < self.maxEnergy) {
self.energy = currentEnergyLevel + 1;
self.lastEnergyRegenTime = LK.ticks; // Update last regeneration time
}
}
// 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 blocking visual effect
if (self.isBlocking) {
// Show blocking shield
if (!blockingShield.visible) {
blockingShield.visible = true;
blockingShield.alpha = 0.7;
}
// Position shield to always point toward opponent
if (player && enemy) {
var opponent = self === player ? enemy : player;
// Shield always points toward opponent regardless of fighter facing direction
if (opponent.x > self.x) {
blockingShield.x = 100; // Shield on right side (facing right toward opponent)
blockingShield.scaleX = Math.abs(blockingShield.scaleX); // Face right
} else {
blockingShield.x = -100; // Shield on left side (facing left toward opponent)
blockingShield.scaleX = -Math.abs(blockingShield.scaleX); // Face left
}
}
} else {
// Hide blocking shield
if (blockingShield.visible) {
blockingShield.visible = false;
blockingShield.alpha = 0.0;
}
}
// Handle crouching visual effect
if (self.isCrouching && !self.isJumping) {
// Scale down vertically when crouching - slightly bigger hitbox than before
if (fighterGraphics.scaleY > 0.25) {
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 = 1000 * 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 projectileAsset = 'projectile' + owner.fighterType;
var projectileGraphics = self.attachAsset(projectileAsset, {
anchorX: 0.5,
anchorY: 0.5
});
// Set projectile direction to match shoot direction
if (direction < 0) {
projectileGraphics.scaleX = -Math.abs(projectileGraphics.scaleX); // Face left
} else {
projectileGraphics.scaleX = Math.abs(projectileGraphics.scaleX); // Face right
}
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 = 1000 * 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 superProjectileAsset = 'superProjectile' + owner.fighterType;
var superProjectileGraphics = self.attachAsset(superProjectileAsset, {
anchorX: 0.5,
anchorY: 0.5
});
// Set super projectile direction to match shoot direction
if (direction < 0) {
superProjectileGraphics.scaleX = -Math.abs(superProjectileGraphics.scaleX); // Face left
} else {
superProjectileGraphics.scaleX = Math.abs(superProjectileGraphics.scaleX); // Face right
}
self.update = function () {
self.x += self.speed * self.direction;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2C1810
});
/****
* Game Code
****/
// Add background with random selection for fights - adjusted for horizontal gameplay
var currentBackgroundAsset = 'background'; // Default background
var gameBackground = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
scaleX: 1.0,
scaleY: 1.0
});
game.addChild(gameBackground);
// Add menu background (initially visible)
var menuBackground = LK.getAsset('menuBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(menuBackground);
// Sounds
// Combat elements
// UI elements
// Character assets
// Game states
// Animation assets for different actions
var gameState = 'titleScreen'; // 'titleScreen', 'characterSelect', 'playerSelect', 'teamSelect', 'combat', 'gameOver'
var selectedCharacter = 0; // Initialize to 0 to require selection
var enemyCharacter = 2;
var gameMode = 'normal'; // 'normal', 'playerVsPlayer', 'teamBattle'
var gameDifficulty = ''; // Initialize to empty to require selection
var playerTeam = [];
var enemyTeam = [];
var currentPlayerSelection = 1;
var currentEnemySelection = 1;
var teamSize = 2;
var selectedTeamIndex = 0;
var titleButtons = [];
// 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;
var currentPlayerTeamIndex = 0;
var currentEnemyTeamIndex = 0;
var teamPlayerDisplays = [];
var teamEnemyDisplays = [];
var lastPlayerDefeatCheck = -1;
var lastEnemyDefeatCheck = -1;
// UI elements
var titleText = new Text2('AI.nimal Brawlers', {
size: 60,
fill: 0xff0000
});
titleText.anchor.set(0.5, 0);
LK.gui.top.addChild(titleText);
titleText.y = 30;
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 initTitleScreen() {
// Show menu background, hide game background
if (menuBackground) menuBackground.visible = true;
if (gameBackground) gameBackground.visible = false;
// Start menu music
LK.playMusic('menuMusic', {
loop: true
});
titleText.setText('AI.nimal Brawlers');
titleText.y = 200;
// Create title screen buttons
var normalButton = LK.getAsset('playNormalButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
normalButton.x = 1024;
normalButton.y = 800;
normalButton.buttonType = 'normal';
game.addChild(normalButton);
titleButtons.push(normalButton);
var normalButtonText = new Text2('PLAY NORMAL', {
size: 30,
fill: 0xFFFFFF
});
normalButtonText.anchor.set(0.5, 0.5);
normalButtonText.x = normalButton.x;
normalButtonText.y = normalButton.y;
game.addChild(normalButtonText);
var selectButton = LK.getAsset('selectFightersButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
selectButton.x = 1024;
selectButton.y = 1000;
selectButton.buttonType = 'select';
game.addChild(selectButton);
titleButtons.push(selectButton);
var selectButtonText = new Text2('SELECT FIGHTERS', {
size: 30,
fill: 0xFFFFFF
});
selectButtonText.anchor.set(0.5, 0.5);
selectButtonText.x = selectButton.x;
selectButtonText.y = selectButton.y;
game.addChild(selectButtonText);
var teamButton = LK.getAsset('teamBattleButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
teamButton.x = 1024;
teamButton.y = 1200;
teamButton.buttonType = 'team';
game.addChild(teamButton);
titleButtons.push(teamButton);
var teamButtonText = new Text2('TEAM BATTLE', {
size: 30,
fill: 0xFFFFFF
});
teamButtonText.anchor.set(0.5, 0.5);
teamButtonText.x = teamButton.x;
teamButtonText.y = teamButton.y;
game.addChild(teamButtonText);
var instructionsText = new Text2('Choose your game mode', {
size: 40,
fill: 0xFFFFFF
});
instructionsText.anchor.set(0.5, 0.5);
instructionsText.x = 1024;
instructionsText.y = 500;
game.addChild(instructionsText);
}
function clearTitleScreen() {
for (var i = 0; i < titleButtons.length; i++) {
game.removeChild(titleButtons[i]);
}
titleButtons = [];
// Remove all text elements by checking children
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
if (child instanceof Text2) {
game.removeChild(child);
}
}
}
function initPlayerSelection() {
instructionText.setText('Player 1: Select Fighter');
instructionText.y = 150;
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.6,
scaleY: 0.6
});
var col = (i - 1) % 5;
var row = Math.floor((i - 1) / 5);
fighter.x = 300 + col * 280;
fighter.y = 400 + row * 300;
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);
// Add difficulty selection for player vs player mode
// Add difficulty selection text
var difficultyText = new Text2('Select Difficulty:', {
size: 35,
fill: 0xFFFFFF
});
difficultyText.anchor.set(0.5, 0.5);
difficultyText.x = 1024;
difficultyText.y = 1800;
game.addChild(difficultyText);
// Easy difficulty button
var easyButton = LK.getAsset('difficultyButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
easyButton.x = 600;
easyButton.y = 2400;
easyButton.buttonType = 'easy';
if (gameDifficulty === 'easy') {
easyButton.tint = 0xff9500; // Lighter orange when selected
}
game.addChild(easyButton);
titleButtons.push(easyButton);
var easyButtonText = new Text2('EASY', {
size: 30,
fill: 0xFFFFFF
});
easyButtonText.anchor.set(0.5, 0.5);
easyButtonText.x = easyButton.x;
easyButtonText.y = easyButton.y;
game.addChild(easyButtonText);
// Normal difficulty button
var normalDiffButton = LK.getAsset('difficultyButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
normalDiffButton.x = 1024;
normalDiffButton.y = 2400;
normalDiffButton.buttonType = 'normalDiff';
game.addChild(normalDiffButton);
titleButtons.push(normalDiffButton);
var normalDiffButtonText = new Text2('NORMAL', {
size: 30,
fill: 0xFFFFFF
});
normalDiffButtonText.anchor.set(0.5, 0.5);
normalDiffButtonText.x = normalDiffButton.x;
normalDiffButtonText.y = normalDiffButton.y;
game.addChild(normalDiffButtonText);
// Hard difficulty button
var hardButton = LK.getAsset('difficultyButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
hardButton.x = 1448;
hardButton.y = 2400;
hardButton.buttonType = 'hard';
game.addChild(hardButton);
titleButtons.push(hardButton);
var hardButtonText = new Text2('HARD', {
size: 30,
fill: 0xFFFFFF
});
hardButtonText.anchor.set(0.5, 0.5);
hardButtonText.x = hardButton.x;
hardButtonText.y = hardButton.y;
game.addChild(hardButtonText);
// Add start combat button
var startCombatButton = LK.getAsset('startCombatButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
startCombatButton.x = 1024;
startCombatButton.y = 2300;
startCombatButton.buttonType = 'startCombat';
game.addChild(startCombatButton);
titleButtons.push(startCombatButton);
var startCombatButtonText = new Text2('START COMBAT', {
size: 30,
fill: 0xFFFFFF
});
startCombatButtonText.anchor.set(0.5, 0.5);
startCombatButtonText.x = startCombatButton.x;
startCombatButtonText.y = startCombatButton.y;
game.addChild(startCombatButtonText);
// Add back to menu button
var backButton = LK.getAsset('backToMenuButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
backButton.x = 1024;
backButton.y = 2600;
backButton.buttonType = 'backToMenu';
game.addChild(backButton);
titleButtons.push(backButton);
var backButtonText = new Text2('BACK TO MENU', {
size: 30,
fill: 0xFFFFFF
});
backButtonText.anchor.set(0.5, 0.5);
backButtonText.x = backButton.x;
backButtonText.y = backButton.y;
game.addChild(backButtonText);
}
function initTeamSelection() {
instructionText.setText('Select Team Size: ' + teamSize + ' vs ' + teamSize);
instructionText.y = 100;
game.addChild(instructionText);
// Team size buttons
var size2Button = LK.getAsset('team2v2Button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
size2Button.x = 400;
size2Button.y = 200;
size2Button.buttonType = 'size2';
if (teamSize === 2) {
size2Button.tint = 0x44ff44; // Green when selected
}
game.addChild(size2Button);
titleButtons.push(size2Button);
var size2Text = new Text2('2 vs 2', {
size: 30,
fill: 0xFFFFFF
});
size2Text.anchor.set(0.5, 0.5);
size2Text.x = size2Button.x;
size2Text.y = size2Button.y;
game.addChild(size2Text);
var size3Button = LK.getAsset('team3v3Button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
size3Button.x = 800;
size3Button.y = 200;
size3Button.buttonType = 'size3';
if (teamSize === 3) {
size3Button.tint = 0x44ff44; // Green when selected
}
game.addChild(size3Button);
titleButtons.push(size3Button);
var size3Text = new Text2('3 vs 3', {
size: 30,
fill: 0xFFFFFF
});
size3Text.anchor.set(0.5, 0.5);
size3Text.x = size3Button.x;
size3Text.y = size3Button.y;
game.addChild(size3Text);
// Add back to menu button
var backButton = LK.getAsset('backToMenuButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
backButton.x = 1024;
backButton.y = 1900;
backButton.buttonType = 'backToMenu';
game.addChild(backButton);
titleButtons.push(backButton);
var backButtonText = new Text2('BACK TO MENU', {
size: 30,
fill: 0xFFFFFF
});
backButtonText.anchor.set(0.5, 0.5);
backButtonText.x = backButton.x;
backButtonText.y = backButton.y;
game.addChild(backButtonText);
var startButton = LK.getAsset('startTeamSelectionButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
startButton.x = 1024;
startButton.y = 1700;
startButton.buttonType = 'startTeam';
game.addChild(startButton);
titleButtons.push(startButton);
var startText = new Text2('START TEAM SELECTION', {
size: 30,
fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
startText.x = startButton.x;
startText.y = startButton.y;
game.addChild(startText);
// Show current teams
updateTeamDisplay();
}
function initTeamFighterSelection() {
// Clear previous state
selectedTeamIndex = 0;
var currentTeam = selectedTeamIndex < teamSize ? 'player' : 'enemy';
var fighterNumber = selectedTeamIndex % teamSize + 1;
var teamName = currentTeam === 'player' ? 'Player' : 'Enemy';
instructionText.setText(teamName + ' Team - Select Fighter ' + fighterNumber);
instructionText.y = 150;
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.6,
scaleY: 0.6
});
var col = (i - 1) % 5;
var row = Math.floor((i - 1) / 5);
fighter.x = 300 + col * 280;
fighter.y = 600 + row * 300;
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;
selectionBorder.x = characterSelectors[0].x;
selectionBorder.y = characterSelectors[0].y;
game.addChild(selectionBorder);
// Show current team selections below the character grid
updateTeamBattleDisplay();
// Add start combat button
var startCombatButton = LK.getAsset('startCombatButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
startCombatButton.x = 1024;
startCombatButton.y = 1700;
startCombatButton.buttonType = 'startCombat';
game.addChild(startCombatButton);
titleButtons.push(startCombatButton);
var startCombatButtonText = new Text2('START COMBAT', {
size: 30,
fill: 0xFFFFFF
});
startCombatButtonText.anchor.set(0.5, 0.5);
startCombatButtonText.x = startCombatButton.x;
startCombatButtonText.y = startCombatButton.y;
game.addChild(startCombatButtonText);
// Add next selection button
var nextButton = LK.getAsset('rightArrowButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
nextButton.x = 1300;
nextButton.y = 1400;
nextButton.buttonType = 'nextSelection';
game.addChild(nextButton);
titleButtons.push(nextButton);
var nextButtonText = new Text2('NEXT', {
size: 30,
fill: 0xFFFFFF
});
nextButtonText.anchor.set(0.5, 0.5);
nextButtonText.x = nextButton.x;
nextButtonText.y = nextButton.y;
game.addChild(nextButtonText);
// Add previous selection button
var prevButton = LK.getAsset('leftArrowButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
prevButton.x = 700;
prevButton.y = 1400;
prevButton.buttonType = 'prevSelection';
game.addChild(prevButton);
titleButtons.push(prevButton);
var prevButtonText = new Text2('PREV', {
size: 30,
fill: 0xFFFFFF
});
prevButtonText.anchor.set(0.5, 0.5);
prevButtonText.x = prevButton.x;
prevButtonText.y = prevButton.y;
game.addChild(prevButtonText);
// Add back to menu button
var backButton = LK.getAsset('backToMenuButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
backButton.x = 1024;
backButton.y = 2100;
backButton.buttonType = 'backToMenu';
game.addChild(backButton);
titleButtons.push(backButton);
var backButtonText = new Text2('BACK TO MENU', {
size: 30,
fill: 0xFFFFFF
});
backButtonText.anchor.set(0.5, 0.5);
backButtonText.x = backButton.x;
backButtonText.y = backButton.y;
game.addChild(backButtonText);
// Add difficulty selection for team battle mode below back button
// Easy difficulty button
var easyButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
easyButton.x = 600;
easyButton.y = 1900;
easyButton.buttonType = 'easy';
if (gameDifficulty === 'easy') {
easyButton.tint = 0xff9500; // Lighter orange when selected
}
game.addChild(easyButton);
titleButtons.push(easyButton);
var easyButtonText = new Text2('EASY', {
size: 30,
fill: 0xFFFFFF
});
easyButtonText.anchor.set(0.5, 0.5);
easyButtonText.x = easyButton.x;
easyButtonText.y = easyButton.y;
game.addChild(easyButtonText);
// Normal difficulty button
var normalDiffButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
normalDiffButton.x = 1024;
normalDiffButton.y = 1900;
normalDiffButton.buttonType = 'normalDiff';
if (gameDifficulty === 'normal') {
normalDiffButton.tint = 0xcc6600; // Darker orange when selected
}
game.addChild(normalDiffButton);
titleButtons.push(normalDiffButton);
var normalDiffButtonText = new Text2('NORMAL', {
size: 30,
fill: 0xFFFFFF
});
normalDiffButtonText.anchor.set(0.5, 0.5);
normalDiffButtonText.x = normalDiffButton.x;
normalDiffButtonText.y = normalDiffButton.y;
game.addChild(normalDiffButtonText);
// Hard difficulty button
var hardButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
hardButton.x = 1448;
hardButton.y = 1900;
hardButton.buttonType = 'hard';
if (gameDifficulty === 'hard') {
hardButton.tint = 0xff0000; // Red when selected
}
game.addChild(hardButton);
titleButtons.push(hardButton);
var hardButtonText = new Text2('HARD', {
size: 30,
fill: 0xFFFFFF
});
hardButtonText.anchor.set(0.5, 0.5);
hardButtonText.x = hardButton.x;
hardButtonText.y = hardButton.y;
game.addChild(hardButtonText);
}
function updateTeamBattleDisplay() {
// Remove existing team battle display
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
if (child.isTeamBattleDisplay) {
game.removeChild(child);
}
}
// Player team display
var playerTeamText = new Text2('Player Team:', {
size: 35,
fill: 0x44ff44
});
playerTeamText.anchor.set(0.5, 0);
playerTeamText.x = 500;
playerTeamText.y = 900;
playerTeamText.isTeamBattleDisplay = true;
game.addChild(playerTeamText);
for (var i = 0; i < teamSize; i++) {
var fighterType = playerTeam[i] || 1;
var teamFighter = LK.getAsset('fighter' + fighterType, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.35,
scaleY: 0.35
});
teamFighter.x = 250 + i * 120;
teamFighter.y = 1100;
teamFighter.isTeamBattleDisplay = true;
// Add selection indicator for current selection
if (selectedTeamIndex === i) {
var selectionIndicator = LK.getAsset('selectionBorder', {
anchorX: 0.5,
anchorY: 0.5
});
selectionIndicator.alpha = 0.6;
selectionIndicator.tint = 0x00ff00;
selectionIndicator.x = teamFighter.x;
selectionIndicator.y = teamFighter.y;
selectionIndicator.scaleX = 0.4;
selectionIndicator.scaleY = 0.4;
selectionIndicator.isTeamBattleDisplay = true;
game.addChild(selectionIndicator);
}
game.addChild(teamFighter);
}
// Enemy team display
var enemyTeamText = new Text2('Enemy Team:', {
size: 35,
fill: 0xff4444
});
enemyTeamText.anchor.set(0.5, 0);
enemyTeamText.x = 1500;
enemyTeamText.y = 900;
enemyTeamText.isTeamBattleDisplay = true;
game.addChild(enemyTeamText);
for (var i = 0; i < teamSize; i++) {
var fighterType = enemyTeam[i] || (i + 1) % 5 + 1;
var teamFighter = LK.getAsset('fighter' + fighterType, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.35,
scaleY: 0.35
});
teamFighter.x = 1250 + i * 120;
teamFighter.y = 1100;
teamFighter.isTeamBattleDisplay = true;
// Add selection indicator for current selection
if (selectedTeamIndex === teamSize + i) {
var selectionIndicator = LK.getAsset('selectionBorder', {
anchorX: 0.5,
anchorY: 0.5
});
selectionIndicator.alpha = 0.6;
selectionIndicator.tint = 0xff0000;
selectionIndicator.x = teamFighter.x;
selectionIndicator.y = teamFighter.y;
selectionIndicator.scaleX = 0.4;
selectionIndicator.scaleY = 0.4;
selectionIndicator.isTeamBattleDisplay = true;
game.addChild(selectionIndicator);
}
game.addChild(teamFighter);
}
}
function updateTeamDisplay() {
// Remove existing team display
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
if (child.isTeamDisplay) {
game.removeChild(child);
}
}
// Player team display
var playerTeamText = new Text2('Player Team:', {
size: 40,
fill: 0x44ff44
});
playerTeamText.anchor.set(0.5, 0);
playerTeamText.x = 500;
playerTeamText.y = 400;
playerTeamText.isTeamDisplay = true;
game.addChild(playerTeamText);
for (var i = 0; i < teamSize; i++) {
var fighterType = playerTeam[i] || i + 1;
var teamFighter = LK.getAsset('fighter' + fighterType, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.4
});
teamFighter.x = 300 + i * 150;
teamFighter.y = 500;
teamFighter.isTeamDisplay = true;
game.addChild(teamFighter);
}
// Enemy team display
var enemyTeamText = new Text2('Enemy Team:', {
size: 40,
fill: 0xff4444
});
enemyTeamText.anchor.set(0.5, 0);
enemyTeamText.x = 1500;
enemyTeamText.y = 400;
enemyTeamText.isTeamDisplay = true;
game.addChild(enemyTeamText);
for (var i = 0; i < teamSize; i++) {
var fighterType = enemyTeam[i] || (i + 2) % 5 + 1;
var teamFighter = LK.getAsset('fighter' + fighterType, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.4
});
teamFighter.x = 1300 + i * 150;
teamFighter.y = 500;
teamFighter.isTeamDisplay = true;
game.addChild(teamFighter);
}
}
function initCharacterSelection() {
instructionText.y = 150;
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.6,
scaleY: 0.6
});
var col = (i - 1) % 5;
var row = Math.floor((i - 1) / 5);
fighter.x = 300 + col * 280;
fighter.y = 400 + row * 300;
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);
// Add difficulty selection if in normal mode
if (gameMode === 'normal') {
// Add difficulty selection text
var difficultyText = new Text2('Select Difficulty:', {
size: 35,
fill: 0xFFFFFF
});
difficultyText.anchor.set(0.5, 0.5);
difficultyText.x = 1024;
difficultyText.y = 700;
game.addChild(difficultyText);
// Easy difficulty button
var easyButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
easyButton.x = 600;
easyButton.y = 2000;
easyButton.buttonType = 'easy';
if (gameDifficulty === 'easy') {
easyButton.tint = 0xff9500; // Lighter orange when selected
}
game.addChild(easyButton);
titleButtons.push(easyButton);
var easyButtonText = new Text2('EASY', {
size: 30,
fill: 0xFFFFFF
});
easyButtonText.anchor.set(0.5, 0.5);
easyButtonText.x = easyButton.x;
easyButtonText.y = easyButton.y;
game.addChild(easyButtonText);
// Normal difficulty button
var normalDiffButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
normalDiffButton.x = 1024;
normalDiffButton.y = 2000;
normalDiffButton.buttonType = 'normalDiff';
game.addChild(normalDiffButton);
titleButtons.push(normalDiffButton);
var normalDiffButtonText = new Text2('NORMAL', {
size: 30,
fill: 0xFFFFFF
});
normalDiffButtonText.anchor.set(0.5, 0.5);
normalDiffButtonText.x = normalDiffButton.x;
normalDiffButtonText.y = normalDiffButton.y;
game.addChild(normalDiffButtonText);
// Hard difficulty button
var hardButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
hardButton.x = 1448;
hardButton.y = 2000;
hardButton.buttonType = 'hard';
game.addChild(hardButton);
titleButtons.push(hardButton);
var hardButtonText = new Text2('HARD', {
size: 30,
fill: 0xFFFFFF
});
hardButtonText.anchor.set(0.5, 0.5);
hardButtonText.x = hardButton.x;
hardButtonText.y = hardButton.y;
game.addChild(hardButtonText);
}
// Add start combat button
var startCombatButton = LK.getAsset('startCombatButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
startCombatButton.x = 1024;
startCombatButton.y = gameMode === 'normal' ? 1850 : 1800;
startCombatButton.buttonType = 'startCombat';
game.addChild(startCombatButton);
titleButtons.push(startCombatButton);
var startCombatButtonText = new Text2('START COMBAT', {
size: 30,
fill: 0xFFFFFF
});
startCombatButtonText.anchor.set(0.5, 0.5);
startCombatButtonText.x = startCombatButton.x;
startCombatButtonText.y = startCombatButton.y;
game.addChild(startCombatButtonText);
// Add back to menu button
var backButton = LK.getAsset('backToMenuButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
backButton.x = 1024;
backButton.y = gameMode === 'normal' ? 2200 : 2000;
backButton.buttonType = 'backToMenu';
game.addChild(backButton);
titleButtons.push(backButton);
var backButtonText = new Text2('BACK TO MENU', {
size: 30,
fill: 0xFFFFFF
});
backButtonText.anchor.set(0.5, 0.5);
backButtonText.x = backButton.x;
backButtonText.y = backButton.y;
game.addChild(backButtonText);
}
function updateSelectionBorder() {
if (selectionBorder && characterSelectors[selectedCharacter - 1]) {
selectionBorder.x = characterSelectors[selectedCharacter - 1].x;
selectionBorder.y = characterSelectors[selectedCharacter - 1].y;
}
}
function startCombat() {
gameState = 'combat';
// Stop menu music when entering combat
LK.stopMusic();
// Start combat music
LK.playMusic('combatMusic', {
loop: true
});
// Randomly select background for this fight
var backgroundOptions = ['background', 'background2', 'background3'];
var randomBackgroundIndex = Math.floor(Math.random() * backgroundOptions.length);
var selectedBackground = backgroundOptions[randomBackgroundIndex];
currentBackgroundAsset = selectedBackground;
// Remove current game background and create new one with selected background
if (gameBackground) {
game.removeChild(gameBackground);
}
gameBackground = LK.getAsset(selectedBackground, {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
scaleX: 1.33,
scaleY: 0.75
});
game.addChild(gameBackground);
// Show game background, hide menu background
if (menuBackground) menuBackground.visible = false;
if (gameBackground) gameBackground.visible = true;
// Clear character selection
game.removeChild(instructionText);
for (var i = 0; i < characterSelectors.length; i++) {
game.removeChild(characterSelectors[i]);
}
game.removeChild(selectionBorder);
// Clear title screen and team displays when starting combat
titleText.visible = false;
clearTitleScreen();
// Remove team battle displays
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
if (child.isTeamDisplay || child.isTeamBattleDisplay) {
game.removeChild(child);
}
}
// Reset defeat tracking
lastPlayerDefeatCheck = -1;
lastEnemyDefeatCheck = -1;
// Create fighters - positioned for horizontal gameplay
player = game.addChild(new Fighter(selectedCharacter, true));
player.x = 400;
player.y = 1800;
enemy = game.addChild(new Fighter(enemyCharacter, false));
enemy.x = 1648;
enemy.y = 1800;
// Create health and energy bars - repositioned for horizontal layout
playerHealthBar = game.addChild(new HealthBar(player, 50, 50));
playerEnergyBar = game.addChild(new EnergyBar(player, 50, 90));
playerSpecialBar = game.addChild(new SpecialBar(player, 50, 130));
enemyHealthBar = game.addChild(new HealthBar(enemy, 1100, 50));
enemyEnergyBar = game.addChild(new EnergyBar(enemy, 1100, 90));
enemySpecialBar = game.addChild(new SpecialBar(enemy, 1100, 130));
// Create combat control buttons arranged for horizontal mobile layout (moved to left side)
punchButton = LK.getAsset('punchButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8
});
punchButton.x = 220;
punchButton.y = 2200;
game.addChild(punchButton);
kickButton = LK.getAsset('kickButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.1,
scaleY: 2.1
});
kickButton.x = 600;
kickButton.y = 2200;
game.addChild(kickButton);
blockButton = LK.getAsset('blockButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.1,
scaleY: 2.1
});
blockButton.x = 980;
blockButton.y = 2200;
game.addChild(blockButton);
rangeButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.1,
scaleY: 2.1
});
rangeButton.x = 220;
rangeButton.y = 2400;
game.addChild(rangeButton);
specialButton = LK.getAsset('specialButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.1,
scaleY: 2.1
});
specialButton.x = 600;
specialButton.y = 2400;
game.addChild(specialButton);
// Create movement buttons arranged for horizontal layout (moved to right side)
leftMoveButton = LK.getAsset('leftArrowButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.9,
scaleY: 1.9
});
leftMoveButton.x = 1550;
leftMoveButton.y = 2400;
game.addChild(leftMoveButton);
rightMoveButton = LK.getAsset('rightArrowButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.9,
scaleY: 1.9
});
rightMoveButton.x = 1850;
rightMoveButton.y = 2400;
game.addChild(rightMoveButton);
// Jump button positioned above movement buttons
jumpButton = LK.getAsset('leftArrowButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.9,
scaleY: 1.9
});
jumpButton.x = 1700;
jumpButton.y = 2150;
game.addChild(jumpButton);
// Crouch button positioned below movement buttons
crouchButton = LK.getAsset('leftArrowButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.9,
scaleY: 1.9
});
crouchButton.x = 1700;
crouchButton.y = 2650;
game.addChild(crouchButton);
// 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 back to menu button positioned for horizontal layout
var backButton = LK.getAsset('backToMenuButton', {
anchorX: 0.5,
anchorY: 0.5
});
backButton.x = 1024; // Center of screen horizontally
backButton.y = 50; // Top of screen
backButton.buttonType = 'backToMenu';
game.addChild(backButton);
var backButtonText = new Text2('MENU', {
size: 30,
fill: 0xFFFFFF
});
backButtonText.anchor.set(0.5, 0.5);
backButtonText.x = backButton.x;
backButtonText.y = backButton.y;
game.addChild(backButtonText);
// Add controls text positioned for horizontal layout
controlsText.setText('Left side: Combat actions | Right side: Move & Jump/Crouch');
controlsText.y = 2700;
game.addChild(controlsText);
// Add player and enemy name labels positioned for horizontal layout
var playerLabel = new Text2('Player', {
size: 40,
fill: 0xFFFFFF
});
playerLabel.anchor.set(0, 0);
playerLabel.x = 50;
playerLabel.y = 20;
game.addChild(playerLabel);
var enemyLabel = new Text2('Enemy', {
size: 40,
fill: 0xFFFFFF
});
enemyLabel.anchor.set(1, 0);
enemyLabel.x = 1998;
enemyLabel.y = 20;
game.addChild(enemyLabel);
// Add team displays if in team battle mode
if (gameMode === 'teamBattle') {
// Player team display positioned for horizontal layout
for (var i = 0; i < playerTeam.length; i++) {
var baseScale = 0.3;
var isCurrentFighter = i === currentPlayerTeamIndex;
var teamFighter = LK.getAsset('fighter' + playerTeam[i], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: isCurrentFighter ? baseScale * 1.2 : baseScale,
scaleY: isCurrentFighter ? baseScale * 1.2 : baseScale
});
teamFighter.x = 100 + i * 60;
teamFighter.y = 200;
teamFighter.teamIndex = i;
teamFighter.isTeamDisplay = true;
teamFighter.tint = 0xffffff; // Normal color for all fighters initially
teamPlayerDisplays.push(teamFighter);
game.addChild(teamFighter);
}
// Enemy team display positioned for horizontal layout
for (var i = 0; i < enemyTeam.length; i++) {
var baseScale = 0.3;
var isCurrentFighter = i === currentEnemyTeamIndex;
var teamFighter = LK.getAsset('fighter' + enemyTeam[i], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: isCurrentFighter ? baseScale * 1.2 : baseScale,
scaleY: isCurrentFighter ? baseScale * 1.2 : baseScale
});
teamFighter.x = 1600 + i * 60;
teamFighter.y = 200;
teamFighter.teamIndex = i;
teamFighter.isTeamDisplay = true;
teamFighter.tint = 0xffffff; // Normal color for all fighters initially
teamEnemyDisplays.push(teamFighter);
game.addChild(teamFighter);
}
}
}
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) < 180 && Math.abs(y - punchButton.y) < 72) {
// Punch button pressed
if (player.attack('punch')) {
player.setAnimation('punching', 20); // 20 ticks punch animation
var hit = checkMeleeHit(player, enemy, Math.floor(player.attackDamage * 0.75), 'punch');
if (hit) player.chargeSpecial(15); // Charge special on successful hit
LK.getSound('punchSound').play();
}
return;
}
if (kickButton && Math.abs(x - kickButton.x) < 210 && Math.abs(y - kickButton.y) < 84) {
// Kick button pressed - can't kick while crouching
if (!player.isCrouching && player.attack('kick')) {
player.setAnimation('kicking', 25); // 25 ticks kick animation (slightly longer)
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('kickSound').play();
}
return;
}
if (rangeButton && Math.abs(x - rangeButton.x) < 208 && Math.abs(y - rangeButton.y) < 83) {
// Range attack button pressed
if (enemy && player.specialAttack('range')) {
player.setAnimation('rangeShooting', 15); // 15 ticks range shooting animation
// Determine shoot direction based on enemy position
var shootDirection = enemy.x > player.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
// Adjust projectile origin based on player stance
var projectileY = player.y - 280; // Default standing position - adjusted for 2x bigger fighters
if (player.isCrouching && !player.isJumping) {
projectileY = player.y - 100; // Lower origin when crouching - adjusted for 2x bigger fighters
} else if (player.isJumping) {
projectileY = player.y - 300; // Higher origin when jumping - adjusted for 2x bigger fighters
}
var projectile = new Projectile(player.x + projectileXOffset, projectileY, shootDirection, 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('rangeShoot').play();
}
return;
}
if (specialButton && Math.abs(x - specialButton.x) < 210 && Math.abs(y - specialButton.y) < 84) {
// Special button pressed
if (enemy && player.useSpecialAttack()) {
player.lastSpecialType = 'potent';
// Start charging animation before firing
tween(player, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xffaa00
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Set potent shooting animation
player.setAnimation('potentShooting', 50); // 50 ticks potent shooting animation - extended duration
// Return to normal size and color after charging
tween(player, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xffffff
}, {
duration: 200,
easing: tween.easeIn
});
// Determine shoot direction based on enemy position
var shootDirection = enemy.x > player.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
// Adjust super projectile origin based on player stance
var superProjectileY = player.y - 280; // Default standing position - adjusted for 2x bigger fighters
if (player.isCrouching && !player.isJumping) {
superProjectileY = player.y - 100; // Lower origin when crouching - adjusted for 2x bigger fighters
} else if (player.isJumping) {
superProjectileY = player.y - 300; // Higher origin when jumping - adjusted for 2x bigger fighters
}
// Create 7 super projectiles fired with spacing
for (var i = 0; i < 7; i++) {
(function (index) {
LK.setTimeout(function () {
var projectileX = player.x + projectileXOffset + (index - 3) * 60; // Horizontal spread in a row
var projectileYOffset = superProjectileY + (index - 3) * 15; // Add vertical spacing between projectiles
var superProjectile = new SuperProjectile(projectileX, projectileYOffset, shootDirection, Math.floor(player.specialDamage * 2 / 7), player);
// Increase speed for potent projectiles
superProjectile.speed = 8; // Increased speed to match regular projectiles
// Add laser effects for fighter 3
if (player.fighterType === 3) {
// Initial bright laser effect
tween(superProjectile, {
tint: 0xff0000
}, {
duration: 50
});
// Pulsing laser effect
tween(superProjectile, {
scaleY: 2.0
}, {
duration: 100,
easing: tween.easeInOut
});
tween(superProjectile, {
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeInOut
});
}
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
LK.getSound('specialShoot').play();
}, index * 80); // 80ms delay between each projectile
})(i);
}
// No pushback when firing potent projectiles
// Sound will be played with each projectile instead
}
});
}
return;
}
if (blockButton && Math.abs(x - blockButton.x) < 420 && Math.abs(y - blockButton.y) < 525) {
// 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) < 142 && Math.abs(y - leftMoveButton.y) < 142) {
// Left movement button pressed
if (!playerIsBlocking && player.x > 200) {
player.stopCrouch(); // Stop crouching when moving left
player.x -= player.speed * 10;
if (player.currentAnimation === 'normal') {
player.setAnimation('walking');
}
}
return;
}
if (rightMoveButton && Math.abs(x - rightMoveButton.x) < 142 && Math.abs(y - rightMoveButton.y) < 142) {
// Right movement button pressed
if (!playerIsBlocking && player.x < 2532) {
player.stopCrouch(); // Stop crouching when moving right
player.x += player.speed * 10;
if (player.currentAnimation === 'normal') {
player.setAnimation('walking');
}
}
return;
}
if (crouchButton && Math.abs(x - crouchButton.x) < 142 && Math.abs(y - crouchButton.y) < 142) {
// Crouch button pressed
player.crouch();
return;
}
if (jumpButton && Math.abs(x - jumpButton.x) < 142 && Math.abs(y - jumpButton.y) < 142) {
// Jump button pressed
player.jump();
if (player.currentAnimation === 'normal') {
player.setAnimation('walking', 30);
}
return;
}
// Movement is now handled by dedicated buttons above
}
function checkMeleeHit(attacker, target, damage, attackType) {
var horizontalDistance = Math.abs(attacker.x - target.x);
var verticalDistance = Math.abs(attacker.y - target.y);
// Bigger horizontal range (600) but smaller vertical range (250)
if (horizontalDistance < 600 && verticalDistance < 250) {
// 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.7)); // 30% damage reduction for normal blocking (increased from 70% reduction)
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;
// Set walking animation when moving
if (enemy.currentAnimation === 'normal') {
enemy.setAnimation('walking');
}
}
if (enemyIsMovingRight && enemy.x < 2532) {
enemy.x += enemy.speed * 2;
// Set walking animation when moving
if (enemy.currentAnimation === 'normal') {
enemy.setAnimation('walking');
}
}
} else {
enemyIsMovingLeft = false;
enemyIsMovingRight = false;
// Reset walking animation when movement stops
if (enemy.currentAnimation === 'walking') {
enemy.setAnimation('normal');
}
}
// Enhanced AI behavior - mix of range attacks, melee attacks, movement, jumping and crouching
var aiUpdateFrequency = 30;
if (gameDifficulty === 'easy') {
aiUpdateFrequency = 45; // Slower AI reactions
} else if (gameDifficulty === 'hard') {
aiUpdateFrequency = 8; // Much faster AI reactions for hard mode - increased from 15
}
// Check for player actions to react to (normal and hard modes only)
var reactToPlayerAction = false;
if (gameDifficulty === 'normal' || gameDifficulty === 'hard') {
// Hard mode AI tries to block all attacks
if (gameDifficulty === 'hard') {
// Try to block all incoming attacks with perfect timing
if (player.currentAnimation === 'punching' || player.currentAnimation === 'kicking' || player.currentAnimation === 'rangeShooting' || player.currentAnimation === 'potentShooting') {
if (distance < 1000) {
// Even wider detection range for hard mode - increased from 800
enemy.isBlocking = true;
reactToPlayerAction = true;
}
}
// Try to maintain distance for range attacks - more aggressive
if (distance < 500 && Math.random() < 0.95) {
if (enemy.x > player.x) {
enemyIsMovingRight = true;
enemyMovementTimer = 35; // Hold movement even longer - increased from 25
} else {
enemyIsMovingLeft = true;
enemyMovementTimer = 35; // Hold movement even longer - increased from 25
}
reactToPlayerAction = true;
}
// Jump and crouch to avoid projectiles - much more frequently
if (player.currentAnimation === 'rangeShooting' || player.currentAnimation === 'potentShooting') {
if (Math.random() < 0.85) {
if (Math.random() < 0.5) {
enemy.jump(); // Jump to avoid projectiles
} else {
enemy.crouch(); // Crouch to avoid projectiles
}
reactToPlayerAction = true;
}
}
// Attack player based on their position - more aggressively
if (player.isCrouching && distance < 560 && Math.random() < 0.98) {
if (enemy.attack('kick')) {
enemy.setAnimation('kicking', 25);
var hit = checkMeleeHit(enemy, player, Math.floor((enemy.attackDamage + 1) * 0.75), 'kick');
if (hit) enemy.chargeSpecial(15);
LK.getSound('kickSound').play();
reactToPlayerAction = true;
}
}
// Attack jumping player with range/potent attacks - more frequently
if (player.isJumping && distance > 200 && distance < 800) {
if (enemy.energy >= 1 && enemy.specialAttack() && Math.random() < 0.9) {
enemy.setAnimation('rangeShooting', 15);
var shootDirection = player.x > enemy.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
var projectileY = enemy.y - 300; // Aim higher for jumping player
var projectile = new Projectile(enemy.x + projectileXOffset, projectileY, shootDirection, enemy.specialDamage, enemy);
projectiles.push(projectile);
game.addChild(projectile);
enemy.chargeSpecial(7);
LK.getSound('rangeShoot').play();
reactToPlayerAction = true;
}
}
// Counter-attack immediately after blocking
if (enemy.isBlocking && distance < 560 && Math.random() < 0.7) {
// Stop blocking and counter-attack
enemy.isBlocking = false;
if (enemy.attack('punch')) {
enemy.setAnimation('punching', 20);
var hit = checkMeleeHit(enemy, player, Math.floor(enemy.attackDamage * 0.75), 'punch');
if (hit) enemy.chargeSpecial(15);
LK.getSound('punchSound').play();
reactToPlayerAction = true;
}
}
// Use special attacks more aggressively when player is vulnerable
if (player.currentAnimation === 'punching' || player.currentAnimation === 'kicking') {
if (distance > 400 && distance < 700 && enemy.canUseSpecialAttack() && Math.random() < 0.6) {
if (enemy.useSpecialAttack()) {
enemy.setAnimation('potentShooting', 30);
var shootDirection = player.x > enemy.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
var superProjectileY = enemy.y - 280;
for (var i = 0; i < 7; i++) {
(function (index) {
LK.setTimeout(function () {
if (!enemy) return; // Safety check to prevent null access
var projectileX = enemy.x + projectileXOffset + (index - 3) * 60;
var projectileYOffset = superProjectileY + (index - 3) * 15; // Add vertical spacing between projectiles
var superProjectile = new SuperProjectile(projectileX, projectileYOffset, shootDirection, Math.floor(enemy.specialDamage * 2 / 7), enemy);
superProjectile.speed = 10; // Even faster super projectiles in hard mode
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
LK.getSound('specialShoot').play();
}, index * 80); // 80ms delay between each projectile
})(i);
}
// Sound will be played with each projectile instead
reactToPlayerAction = true;
}
}
}
} else {
// Normal mode behavior (existing)
// Check if player is punching - try to crouch
if (player.currentAnimation === 'punching' && distance < 560) {
if (Math.random() < 0.7) {
enemy.crouch();
reactToPlayerAction = true;
}
}
// Check if player is kicking - try to jump
else if (player.currentAnimation === 'kicking' && distance < 560) {
if (Math.random() < 0.7) {
enemy.jump();
reactToPlayerAction = true;
}
}
// Check if player is shooting range attacks - try to block
else if (player.currentAnimation === 'rangeShooting') {
if (Math.random() < 0.8) {
enemy.isBlocking = true;
reactToPlayerAction = true;
}
}
// Check if player is crouching - try to kick
else if (player.isCrouching && distance < 560) {
if (Math.random() < 0.6) {
if (enemy.attack('kick')) {
enemy.setAnimation('kicking', 25);
var hit = checkMeleeHit(enemy, player, Math.floor((enemy.attackDamage + 1) * 0.75), 'kick');
if (hit) enemy.chargeSpecial(15);
LK.getSound('kickSound').play();
reactToPlayerAction = true;
}
}
}
}
}
if (LK.ticks % aiUpdateFrequency === 0 && !reactToPlayerAction) {
var actionRange = 12;
if (gameDifficulty === 'easy') {
actionRange = 8; // Less varied AI behavior
} else if (gameDifficulty === 'hard') {
actionRange = 25; // Much more varied and aggressive AI behavior for hard mode - increased from 20
}
var action = Math.floor(Math.random() * actionRange);
// Check if enemy is in melee range (close enough to punch/kick)
if (distance < 560) {
// In melee range - try to attack or block
if (gameDifficulty === 'hard') {
// Hard mode: much more aggressive melee combat
if (action <= 8 && enemy.attack()) {
// More frequent punch attacks in hard mode
enemy.setAnimation('punching', 20); // 20 ticks punch animation
var hit = checkMeleeHit(enemy, player, Math.floor(enemy.attackDamage * 0.75), 'punch');
if (hit) enemy.chargeSpecial(15); // Charge special on successful hit
LK.getSound('punchSound').play();
} else if (action <= 15 && !enemy.isCrouching && enemy.attack()) {
// Much more frequent kick attacks in hard mode
enemy.setAnimation('kicking', 25); // 25 ticks kick animation (slightly longer)
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 <= 18) {
// Block when not attacking
enemy.isBlocking = true;
} else if (action <= 20) {
// Back away occasionally when too close
if (enemy.x > player.x) {
enemyIsMovingRight = true;
enemyMovementTimer = 15; // Shorter movement in hard mode for more aggression
} else {
enemyIsMovingLeft = true;
enemyMovementTimer = 15; // Shorter movement in hard mode for more aggression
}
} else if (action <= 22) {
// Jump more frequently in melee range in hard mode
enemy.jump();
} else {
// Crouch more frequently in melee range in hard mode
enemy.crouch();
}
} else {
// Normal and easy mode: existing behavior
if (action <= 3 && enemy.attack()) {
// Punch attack
enemy.setAnimation('punching', 20); // 20 ticks punch animation
var hit = checkMeleeHit(enemy, player, Math.floor(enemy.attackDamage * 0.75), 'punch');
if (hit) enemy.chargeSpecial(15); // Charge special on successful hit
LK.getSound('punchSound').play();
} else if (action <= 6 && !enemy.isCrouching && enemy.attack()) {
// Kick attack (slightly more damage) - can't kick while crouching
enemy.setAnimation('kicking', 25); // 25 ticks kick animation (slightly longer)
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('kickSound').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() && enemy.useSpecialAttack()) {
// Use super special attack with charging animation
tween(enemy, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xffaa00
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Set potent shooting animation
enemy.setAnimation('potentShooting', 50); // 50 ticks potent shooting animation - extended duration
// Return to normal size and color after charging
tween(enemy, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xffffff
}, {
duration: 200,
easing: tween.easeIn
});
// Determine shoot direction based on player position
var shootDirection = player.x > enemy.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
// Adjust super projectile origin based on enemy stance
var superProjectileY = enemy.y - 280; // Default standing position - adjusted for 2x bigger fighters
if (enemy.isCrouching && !enemy.isJumping) {
superProjectileY = enemy.y - 100; // Lower origin when crouching - adjusted for 2x bigger fighters
} else if (enemy.isJumping) {
superProjectileY = enemy.y - 300; // Higher origin when jumping - adjusted for 2x bigger fighters
}
// Create 7 super projectiles fired with spacing
for (var i = 0; i < 7; i++) {
(function (index) {
LK.setTimeout(function () {
if (!enemy) return; // Safety check to prevent null access
var projectileX = enemy.x + projectileXOffset + (index - 3) * 60; // Horizontal spread in a row
var projectileYOffset = superProjectileY + (index - 3) * 15; // Add vertical spacing between projectiles
var superProjectile = new SuperProjectile(projectileX, projectileYOffset, shootDirection, Math.floor(enemy.specialDamage * 2 / 7), enemy);
// Increase speed for AI potent projectiles
superProjectile.speed = 8; // Increased speed to match regular projectiles
// Add laser effects for fighter 3
if (enemy.fighterType === 3) {
// Initial bright laser effect
tween(superProjectile, {
tint: 0xff0000
}, {
duration: 50
});
// Pulsing laser effect
tween(superProjectile, {
scaleY: 2.0
}, {
duration: 100,
easing: tween.easeInOut
});
tween(superProjectile, {
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeInOut
});
}
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
LK.getSound('specialShoot').play();
}, index * 80); // 80ms delay between each projectile
})(i);
}
// No pushback when firing potent projectiles
// Sound will be played with each projectile instead
}
});
} else if (action <= 6 && enemy.energy >= 1 && enemy.specialAttack()) {
// Use range attack (reduced frequency)
enemy.setAnimation('rangeShooting', 15); // 15 ticks range shooting animation
// Determine shoot direction based on player position
var shootDirection = player.x > enemy.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
// Adjust projectile origin based on enemy stance
var projectileY = enemy.y - 280; // Default standing position - adjusted for 2x bigger fighters
if (enemy.isCrouching && !enemy.isJumping) {
projectileY = enemy.y - 100; // Lower origin when crouching - adjusted for 2x bigger fighters
} else if (enemy.isJumping) {
projectileY = enemy.y - 300; // Higher origin when jumping - adjusted for 2x bigger fighters
}
var projectile = new Projectile(enemy.x + projectileXOffset, projectileY, shootDirection, 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('rangeShoot').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() && enemy.useSpecialAttack()) {
// Use super special attack when available (reduced frequency) with charging animation
tween(enemy, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xffaa00
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Set potent shooting animation
enemy.setAnimation('potentShooting', 50); // 50 ticks potent shooting animation - extended duration
// Return to normal size and color after charging
tween(enemy, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xffffff
}, {
duration: 200,
easing: tween.easeIn
});
// Determine shoot direction based on player position
var shootDirection = player.x > enemy.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
// Adjust super projectile origin based on enemy stance
var superProjectileY = enemy.y - 280; // Default standing position - adjusted for 2x bigger fighters
if (enemy.isCrouching && !enemy.isJumping) {
superProjectileY = enemy.y - 100; // Lower origin when crouching - adjusted for 2x bigger fighters
} else if (enemy.isJumping) {
superProjectileY = enemy.y - 300; // Higher origin when jumping - adjusted for 2x bigger fighters
}
// Create 7 super projectiles fired with spacing
for (var i = 0; i < 7; i++) {
(function (index) {
LK.setTimeout(function () {
if (!enemy) return; // Safety check to prevent null access
var projectileX = enemy.x + projectileXOffset + (index - 3) * 60; // Horizontal spread in a row
var projectileYOffset = superProjectileY + (index - 3) * 15; // Add vertical spacing between projectiles
var superProjectile = new SuperProjectile(projectileX, projectileYOffset, shootDirection, Math.floor(enemy.specialDamage * 2 / 7), enemy);
// Increase speed for AI long range potent projectiles
superProjectile.speed = 8; // Increased speed to match regular projectiles
// Add laser effects for fighter 3
if (enemy.fighterType === 3) {
// Initial bright laser effect
tween(superProjectile, {
tint: 0xff0000
}, {
duration: 50
});
// Pulsing laser effect
tween(superProjectile, {
scaleY: 2.0
}, {
duration: 100,
easing: tween.easeInOut
});
tween(superProjectile, {
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeInOut
});
}
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
LK.getSound('specialShoot').play();
}, index * 80); // 80ms delay between each projectile
})(i);
}
// No pushback when firing potent projectiles
// Sound will be played with each projectile instead
}
});
} else if (action <= 3 && enemy.energy >= 1 && enemy.specialAttack()) {
// Use range attack when available (reduced frequency)
enemy.setAnimation('rangeShooting', 15); // 15 ticks range shooting animation
// Determine shoot direction based on player position
var shootDirection = player.x > enemy.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
// Adjust super projectile origin based on enemy stance
var projectileY = enemy.y - 280; // Default standing position - adjusted for 2x bigger fighters
if (enemy.isCrouching && !enemy.isJumping) {
projectileY = enemy.y - 100; // Lower origin when crouching - adjusted for 2x bigger fighters
} else if (enemy.isJumping) {
projectileY = enemy.y - 300; // Higher origin when jumping - adjusted for 2x bigger fighters
}
var projectile = new Projectile(enemy.x + projectileXOffset, projectileY, shootDirection, 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('rangeShoot').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
var resetFrequency = 45;
if (gameDifficulty === 'hard') {
resetFrequency = 25; // Much faster reset in hard mode for more responsive AI
}
if (LK.ticks % resetFrequency === 0) {
enemy.isBlocking = false;
enemy.stopCrouch(); // Release crouch periodically
}
}
function updateCombatTeamDisplays() {
if (gameMode !== 'teamBattle') return;
var baseScale = 0.3;
var activeScale = baseScale * 1.2;
// Update player team displays
for (var i = 0; i < teamPlayerDisplays.length; i++) {
var fighter = teamPlayerDisplays[i];
if (i < currentPlayerTeamIndex) {
// Defeated fighter - grey tint
tween(fighter, {
tint: 0x666666,
scaleX: baseScale,
scaleY: baseScale
}, {
duration: 300,
easing: tween.easeOut
});
} else if (i === currentPlayerTeamIndex) {
// Active fighter - normal color and bigger
tween(fighter, {
tint: 0xffffff,
scaleX: activeScale,
scaleY: activeScale
}, {
duration: 300,
easing: tween.easeOut
});
} else {
// Not yet active fighter - normal color and size
tween(fighter, {
tint: 0xffffff,
scaleX: baseScale,
scaleY: baseScale
}, {
duration: 300,
easing: tween.easeOut
});
}
}
// Update enemy team displays
for (var i = 0; i < teamEnemyDisplays.length; i++) {
var fighter = teamEnemyDisplays[i];
if (i < currentEnemyTeamIndex) {
// Defeated fighter - grey tint
tween(fighter, {
tint: 0x666666,
scaleX: baseScale,
scaleY: baseScale
}, {
duration: 300,
easing: tween.easeOut
});
} else if (i === currentEnemyTeamIndex) {
// Active fighter - normal color and bigger
tween(fighter, {
tint: 0xffffff,
scaleX: activeScale,
scaleY: activeScale
}, {
duration: 300,
easing: tween.easeOut
});
} else {
// Not yet active fighter - normal color and size
tween(fighter, {
tint: 0xffffff,
scaleX: baseScale,
scaleY: baseScale
}, {
duration: 300,
easing: tween.easeOut
});
}
}
}
function switchToNextTeamFighter(isPlayer) {
if (gameMode !== 'teamBattle') return false;
if (isPlayer) {
// Check if player is already being defeated to prevent double switching
if (player.isBeingDefeated || lastPlayerDefeatCheck === currentPlayerTeamIndex) return false;
player.isBeingDefeated = true;
lastPlayerDefeatCheck = currentPlayerTeamIndex;
// Flash defeated fighter red before switching
LK.getSound('defeated').play();
tween(player, {
tint: 0xff0000
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Mark current fighter as defeated (grey)
if (teamPlayerDisplays[currentPlayerTeamIndex]) {
tween(teamPlayerDisplays[currentPlayerTeamIndex], {
tint: 0x333333
}, {
duration: 500,
easing: tween.easeOut
});
}
currentPlayerTeamIndex++;
if (currentPlayerTeamIndex < playerTeam.length) {
// Switch to next player team fighter
selectedCharacter = playerTeam[currentPlayerTeamIndex];
// Remove current player
player.destroy();
game.removeChild(player);
// Create new player
player = game.addChild(new Fighter(selectedCharacter, true));
player.x = 300;
player.y = 1800;
// Flash new fighter with immunity
tween(player, {
tint: 0xffffff,
alpha: 0.5
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(player, {
alpha: 1.0,
tint: 0x44ff44
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(player, {
tint: 0xffffff
}, {
duration: 400,
easing: tween.easeOut
});
}
});
}
});
// Update health bars to reference new fighter
playerHealthBar.fighter = player;
playerEnergyBar.fighter = player;
playerSpecialBar.fighter = player;
// Update team displays to show new states
updateCombatTeamDisplays();
}
}
});
return true;
} else {
// Check if enemy is already being defeated to prevent double switching
if (enemy.isBeingDefeated || lastEnemyDefeatCheck === currentEnemyTeamIndex) return false;
enemy.isBeingDefeated = true;
lastEnemyDefeatCheck = currentEnemyTeamIndex;
// Flash defeated fighter red before switching
LK.getSound('defeated').play();
tween(enemy, {
tint: 0xff0000
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Mark current fighter as defeated (grey)
if (teamEnemyDisplays[currentEnemyTeamIndex]) {
tween(teamEnemyDisplays[currentEnemyTeamIndex], {
tint: 0x333333
}, {
duration: 500,
easing: tween.easeOut
});
}
currentEnemyTeamIndex++;
if (currentEnemyTeamIndex < enemyTeam.length) {
// Switch to next enemy team fighter
enemyCharacter = enemyTeam[currentEnemyTeamIndex];
// Remove current enemy
enemy.destroy();
game.removeChild(enemy);
// Create new enemy
enemy = game.addChild(new Fighter(enemyCharacter, false));
enemy.x = 2432;
enemy.y = 1800;
// Flash new fighter with immunity
tween(enemy, {
tint: 0xffffff,
alpha: 0.5
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(enemy, {
alpha: 1.0,
tint: 0x44ff44
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(enemy, {
tint: 0xffffff
}, {
duration: 400,
easing: tween.easeOut
});
}
});
}
});
// Update health bars to reference new fighter
enemyHealthBar.fighter = enemy;
enemyEnergyBar.fighter = enemy;
enemySpecialBar.fighter = enemy;
// Update team displays to show new states
updateCombatTeamDisplays();
}
}
});
return true;
}
return false;
}
function checkGameOver() {
if (player && player.health <= 0) {
// Try to switch to next team fighter
if (gameMode === 'teamBattle') {
// Only check game over if we can't switch to another fighter
var switched = switchToNextTeamFighter(true);
if (!switched) {
// Check if all team fighters are actually defeated
var allPlayerDefeated = true;
for (var i = 0; i < playerTeam.length; i++) {
if (i > currentPlayerTeamIndex) {
allPlayerDefeated = false;
break;
}
}
if (allPlayerDefeated) {
// All team fighters defeated - game over
LK.showGameOver();
}
}
} else {
LK.getSound('defeated').play();
LK.showGameOver();
}
} else if (enemy && enemy.health <= 0) {
// Try to switch to next team fighter
if (gameMode === 'teamBattle') {
// Only check win condition if we can't switch to another fighter
var switched = switchToNextTeamFighter(false);
if (!switched) {
// Check if all enemy team fighters are actually defeated
var allEnemyDefeated = true;
for (var i = 0; i < enemyTeam.length; i++) {
if (i > currentEnemyTeamIndex) {
allEnemyDefeated = false;
break;
}
}
if (allEnemyDefeated) {
// All team fighters defeated - player wins
LK.showYouWin();
}
}
} else {
LK.getSound('defeated').play();
LK.showYouWin();
}
}
}
// Character selection input
game.down = function (x, y, obj) {
// Check back to menu button for all states
for (var i = 0; i < game.children.length; i++) {
var child = game.children[i];
if (child.buttonType === 'backToMenu' && Math.abs(x - child.x) < 200 && Math.abs(y - child.y) < 80) {
// Clear current game state and return to title screen
gameState = 'titleScreen';
// Remove all game objects
for (var k = game.children.length - 1; k >= 0; k--) {
game.removeChild(game.children[k]);
}
game.addChild(gameBackground);
game.addChild(menuBackground);
// Show menu background, hide game background
if (menuBackground) menuBackground.visible = true;
if (gameBackground) gameBackground.visible = false;
// Reset variables
player = null;
enemy = null;
projectiles = [];
superProjectiles = [];
teamPlayerDisplays = [];
teamEnemyDisplays = [];
currentPlayerTeamIndex = 0;
currentEnemyTeamIndex = 0;
selectedTeamIndex = 0;
characterSelectors = [];
titleButtons = [];
selectionBorder = null;
currentPlayerSelection = 1;
titleText.visible = true;
// Restart menu music when returning to title screen
LK.playMusic('menuMusic', {
loop: true
});
initTitleScreen();
return;
}
}
if (gameState === 'titleScreen') {
// Check title screen buttons
for (var i = 0; i < titleButtons.length; i++) {
var button = titleButtons[i];
if (Math.abs(x - button.x) < 200 && Math.abs(y - button.y) < 80) {
if (button.buttonType === 'normal') {
gameMode = 'normal';
titleText.visible = false;
clearTitleScreen();
gameState = 'characterSelect';
initCharacterSelection();
} else if (button.buttonType === 'select') {
gameMode = 'teamBattle';
teamSize = 1;
titleText.visible = false;
clearTitleScreen();
gameState = 'teamFighterSelect';
// Initialize teams for 1v1
playerTeam = [];
enemyTeam = [];
selectedTeamIndex = 0;
initTeamFighterSelection();
} else if (button.buttonType === 'team') {
gameMode = 'teamBattle';
titleText.visible = false;
clearTitleScreen();
gameState = 'teamSelect';
initTeamSelection();
}
break;
}
}
} else if (gameState === 'teamSelect') {
// Check team selection buttons
for (var i = 0; i < titleButtons.length; i++) {
var button = titleButtons[i];
if (Math.abs(x - button.x) < 200 && Math.abs(y - button.y) < 80) {
if (button.buttonType === 'easy') {
gameDifficulty = 'easy';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'easy') {
diffButton.tint = 0xff9500; // Lighter orange for easy
} else if (diffButton.buttonType === 'normalDiff' || diffButton.buttonType === 'hard') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
} else if (button.buttonType === 'normalDiff') {
gameDifficulty = 'normal';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'normalDiff') {
diffButton.tint = 0xcc6600; // Darker orange for normal
} else if (diffButton.buttonType === 'easy' || diffButton.buttonType === 'hard') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
} else if (button.buttonType === 'hard') {
gameDifficulty = 'hard';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'hard') {
diffButton.tint = 0xff0000; // Red for hard
} else if (diffButton.buttonType === 'easy' || diffButton.buttonType === 'normalDiff') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
} else if (button.buttonType === 'size2') {
teamSize = 2;
playerTeam = [];
enemyTeam = [];
instructionText.setText('Select Team Size: ' + teamSize + ' vs ' + teamSize);
updateTeamDisplay();
// Update button colors to show selection
for (var k = 0; k < titleButtons.length; k++) {
var sizeButton = titleButtons[k];
if (sizeButton.buttonType === 'size2') {
sizeButton.tint = 0x44ff44; // Green when selected
} else if (sizeButton.buttonType === 'size3') {
sizeButton.tint = 0xffffff; // White when not selected
}
}
} else if (button.buttonType === 'size3') {
teamSize = 3;
playerTeam = [];
enemyTeam = [];
instructionText.setText('Select Team Size: ' + teamSize + ' vs ' + teamSize);
updateTeamDisplay();
// Update button colors to show selection
for (var k = 0; k < titleButtons.length; k++) {
var sizeButton = titleButtons[k];
if (sizeButton.buttonType === 'size3') {
sizeButton.tint = 0x44ff44; // Green when selected
} else if (sizeButton.buttonType === 'size2') {
sizeButton.tint = 0xffffff; // White when not selected
}
}
} else if (button.buttonType === 'startTeam') {
// Remove team display elements
for (var k = game.children.length - 1; k >= 0; k--) {
var child = game.children[k];
if (child.isTeamDisplay) {
game.removeChild(child);
}
}
// Initialize teams if empty
for (var j = 0; j < teamSize; j++) {
if (!playerTeam[j]) playerTeam[j] = j + 1;
if (!enemyTeam[j]) enemyTeam[j] = (j + 2) % 5 + 1;
}
// Reset team indices
currentPlayerTeamIndex = 0;
currentEnemyTeamIndex = 0;
clearTitleScreen();
gameState = 'teamFighterSelect';
initTeamFighterSelection();
}
break;
}
}
} else if (gameState === 'characterSelect') {
// Check difficulty buttons first
for (var i = 0; i < titleButtons.length; i++) {
var button = titleButtons[i];
if (Math.abs(x - button.x) < 200 && Math.abs(y - button.y) < 80) {
if (button.buttonType === 'easy') {
gameDifficulty = 'easy';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'easy') {
diffButton.tint = 0xff9500; // Lighter orange for easy
} else if (diffButton.buttonType === 'normalDiff' || diffButton.buttonType === 'hard') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
} else if (button.buttonType === 'normalDiff') {
gameDifficulty = 'normal';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'normalDiff') {
diffButton.tint = 0xcc6600; // Darker orange for normal
} else if (diffButton.buttonType === 'easy' || diffButton.buttonType === 'hard') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
} else if (button.buttonType === 'hard') {
gameDifficulty = 'hard';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'hard') {
diffButton.tint = 0xff0000; // Red for hard
} else if (diffButton.buttonType === 'easy' || diffButton.buttonType === 'normalDiff') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
}
}
}
// Check for start combat button
for (var i = 0; i < titleButtons.length; i++) {
var button = titleButtons[i];
if (button.buttonType === 'startCombat' && Math.abs(x - button.x) < 200 && Math.abs(y - button.y) < 80) {
// Check if character is selected and difficulty is selected before starting combat
if (!selectedCharacter || selectedCharacter === 0) {
// Flash screen to indicate character must be selected
LK.effects.flashScreen(0xff0000, 500);
return;
}
if (!gameDifficulty || gameDifficulty === '') {
// Flash screen to indicate difficulty must be selected
LK.effects.flashScreen(0xff0000, 500);
return;
}
enemyCharacter = selectedCharacter % 5 + 1; // Simple enemy selection
storage.lastPlayerFighter = selectedCharacter;
storage.lastEnemyFighter = enemyCharacter;
// Clear character selection
game.removeChild(instructionText);
for (var j = 0; j < characterSelectors.length; j++) {
game.removeChild(characterSelectors[j]);
}
game.removeChild(selectionBorder);
characterSelectors = [];
gameState = 'combat';
startCombat();
return;
}
}
// 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;
storage.lastPlayerFighter = selectedCharacter;
updateSelectionBorder();
break;
}
}
} else if (gameState === 'playerSelect') {
// Check difficulty buttons first
for (var i = 0; i < titleButtons.length; i++) {
var button = titleButtons[i];
if (Math.abs(x - button.x) < 200 && Math.abs(y - button.y) < 80) {
if (button.buttonType === 'easy') {
gameDifficulty = 'easy';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'easy') {
diffButton.tint = 0xff9500; // Lighter orange for easy
} else if (diffButton.buttonType === 'normalDiff' || diffButton.buttonType === 'hard') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
} else if (button.buttonType === 'normalDiff') {
gameDifficulty = 'normal';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'normalDiff') {
diffButton.tint = 0xcc6600; // Darker orange for normal
} else if (diffButton.buttonType === 'easy' || diffButton.buttonType === 'hard') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
} else if (button.buttonType === 'hard') {
gameDifficulty = 'hard';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'hard') {
diffButton.tint = 0xff0000; // Red for hard
} else if (diffButton.buttonType === 'easy' || diffButton.buttonType === 'normalDiff') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
}
}
}
// Check for start combat button
for (var i = 0; i < titleButtons.length; i++) {
var button = titleButtons[i];
if (button.buttonType === 'startCombat' && Math.abs(x - button.x) < 200 && Math.abs(y - button.y) < 80) {
// Check if both characters are selected and difficulty is selected before starting combat
if (currentPlayerSelection !== 2 || !enemyCharacter) {
// Flash screen to indicate both characters must be selected
LK.effects.flashScreen(0xff0000, 500);
return;
}
if (!gameDifficulty || gameDifficulty === '') {
// Flash screen to indicate difficulty must be selected
LK.effects.flashScreen(0xff0000, 500);
return;
}
storage.lastEnemyFighter = enemyCharacter;
// Clear character selection
game.removeChild(instructionText);
for (var j = 0; j < characterSelectors.length; j++) {
game.removeChild(characterSelectors[j]);
}
game.removeChild(selectionBorder);
characterSelectors = [];
gameState = 'combat';
startCombat();
return;
}
}
// Check which character was selected for player vs player
for (var i = 0; i < characterSelectors.length; i++) {
var fighter = characterSelectors[i];
if (Math.abs(x - fighter.x) < 100 && Math.abs(y - fighter.y) < 150) {
if (currentPlayerSelection === 1) {
selectedCharacter = fighter.fighterIndex;
storage.lastPlayerFighter = selectedCharacter;
currentPlayerSelection = 2;
instructionText.setText('Player 2: Select Fighter');
} else {
enemyCharacter = fighter.fighterIndex;
}
updateSelectionBorder();
break;
}
}
} else if (gameState === 'teamFighterSelect') {
// Check difficulty buttons first
for (var i = 0; i < titleButtons.length; i++) {
var button = titleButtons[i];
if (Math.abs(x - button.x) < 200 && Math.abs(y - button.y) < 80) {
if (button.buttonType === 'easy') {
gameDifficulty = 'easy';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'easy') {
diffButton.tint = 0xff9500; // Lighter orange for easy
} else if (diffButton.buttonType === 'normalDiff' || diffButton.buttonType === 'hard') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
} else if (button.buttonType === 'normalDiff') {
gameDifficulty = 'normal';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'normalDiff') {
diffButton.tint = 0xcc6600; // Darker orange for normal
} else if (diffButton.buttonType === 'easy' || diffButton.buttonType === 'hard') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
} else if (button.buttonType === 'hard') {
gameDifficulty = 'hard';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'hard') {
diffButton.tint = 0xff0000; // Red for hard
} else if (diffButton.buttonType === 'easy' || diffButton.buttonType === 'normalDiff') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
}
}
}
// Check for next/previous selection buttons
for (var i = 0; i < titleButtons.length; i++) {
var button = titleButtons[i];
if (Math.abs(x - button.x) < 150 && Math.abs(y - button.y) < 150) {
if (button.buttonType === 'nextSelection') {
// Move to next selection if not at the end
if (selectedTeamIndex < teamSize * 2 - 1) {
selectedTeamIndex++;
var currentTeam = selectedTeamIndex < teamSize ? 'player' : 'enemy';
var fighterNumber = selectedTeamIndex % teamSize + 1;
var teamName = currentTeam === 'player' ? 'Player' : 'Enemy';
instructionText.setText(teamName + ' Team - Select Fighter ' + fighterNumber);
updateTeamBattleDisplay();
}
return;
} else if (button.buttonType === 'prevSelection') {
// Move to previous selection if not at the beginning
if (selectedTeamIndex > 0) {
selectedTeamIndex--;
var currentTeam = selectedTeamIndex < teamSize ? 'player' : 'enemy';
var fighterNumber = selectedTeamIndex % teamSize + 1;
var teamName = currentTeam === 'player' ? 'Player' : 'Enemy';
instructionText.setText(teamName + ' Team - Select Fighter ' + fighterNumber);
updateTeamBattleDisplay();
}
return;
}
}
}
// Check for start combat button
for (var i = 0; i < titleButtons.length; i++) {
var button = titleButtons[i];
if (button.buttonType === 'startCombat' && Math.abs(x - button.x) < 200 && Math.abs(y - button.y) < 80) {
// Check if all fighters are selected and difficulty is selected before starting combat
// Need to check if both teams have at least one fighter selected
var playerTeamComplete = true;
var enemyTeamComplete = true;
for (var t = 0; t < teamSize; t++) {
if (!playerTeam[t] || playerTeam[t] === 0) playerTeamComplete = false;
if (!enemyTeam[t] || enemyTeam[t] === 0) enemyTeamComplete = false;
}
if (!playerTeamComplete || !enemyTeamComplete) {
// Flash screen to indicate all fighters must be selected
LK.effects.flashScreen(0xff0000, 500);
return;
}
if (!gameDifficulty || gameDifficulty === '') {
// Flash screen to indicate difficulty must be selected
LK.effects.flashScreen(0xff0000, 500);
return;
}
// All fighters selected, start combat
// Clear character selection
game.removeChild(instructionText);
for (var j = 0; j < characterSelectors.length; j++) {
game.removeChild(characterSelectors[j]);
}
game.removeChild(selectionBorder);
characterSelectors = [];
gameState = 'combat';
selectedCharacter = playerTeam[0];
enemyCharacter = enemyTeam[0];
startCombat();
return;
}
}
// Check which character was selected for team battle
for (var i = 0; i < characterSelectors.length; i++) {
var fighter = characterSelectors[i];
if (Math.abs(x - fighter.x) < 100 && Math.abs(y - fighter.y) < 150) {
// Determine which team and position we're selecting for
if (selectedTeamIndex < teamSize) {
// Selecting for player team
playerTeam[selectedTeamIndex] = fighter.fighterIndex;
} else {
// Selecting for enemy team
enemyTeam[selectedTeamIndex - teamSize] = fighter.fighterIndex;
}
// Don't auto-advance selectedTeamIndex - let user manually advance or change selection
// Update display for current selection
var currentTeam = selectedTeamIndex < teamSize ? 'player' : 'enemy';
var fighterNumber = selectedTeamIndex % teamSize + 1;
var teamName = currentTeam === 'player' ? 'Player' : 'Enemy';
instructionText.setText(teamName + ' Team - Fighter ' + fighterNumber + ' selected. Click another fighter to change or advance to next selection.');
updateTeamBattleDisplay();
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) < 142 && Math.abs(y - leftMoveButton.y) < 142) {
isMovingLeft = true;
player.stopCrouch(); // Stop crouching when moving left
} else {
isMovingLeft = false;
}
// Check if moving over right button
if (rightMoveButton && Math.abs(x - rightMoveButton.x) < 142 && Math.abs(y - rightMoveButton.y) < 142) {
isMovingRight = true;
player.stopCrouch(); // Stop crouching when moving right
} else {
isMovingRight = false;
}
// Check if holding crouch button
if (crouchButton && Math.abs(x - crouchButton.x) < 142 && Math.abs(y - crouchButton.y) < 142) {
player.crouch();
}
}
};
game.up = function (x, y, obj) {
if (player && gameState === 'combat') {
player.isBlocking = false;
playerIsBlocking = false;
isMovingLeft = false;
isMovingRight = false;
player.stopCrouch();
// Reset walking animation to normal when movement stops
if (player.currentAnimation === 'walking') {
player.setAnimation('normal');
}
}
};
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 (rangeButton && rangeButtonText && player) {
if (player.energy >= player.specialCost) {
// Available - normal colors
tween.stop(rangeButton, {
tint: true
});
tween.stop(rangeButtonText, {
tint: true
});
rangeButton.tint = 0xFFFFFF; // White button when available
rangeButtonText.tint = 0xFFFFFF; // White text when available
} else {
// Not available - grey colors
tween.stop(rangeButton, {
tint: true
});
tween.stop(rangeButtonText, {
tint: true
});
rangeButton.tint = 0x666666; // Gray button when not available
rangeButtonText.tint = 0x666666; // Gray text when not available
}
}
if (specialButton && specialButtonText && player) {
if (player.canUseSpecialAttack()) {
// Available - normal colors
tween.stop(specialButton, {
tint: true
});
tween.stop(specialButtonText, {
tint: true
});
specialButton.tint = 0xFFFFFF; // White button when available
specialButtonText.tint = 0xFFFFFF; // White text when available
} else {
// Not available - grey colors
tween.stop(specialButton, {
tint: true
});
tween.stop(specialButtonText, {
tint: true
});
specialButton.tint = 0x666666; // Gray button when not available
specialButtonText.tint = 0x666666; // Gray text 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);
LK.getSound('projectileClash').play();
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) < 200 && Math.abs(superProj.y - target.y) < 300) {
// Check if super projectile should miss crouching target
// Standing super projectiles (fired from y-280) should miss crouching targets
var superProjectileFromStanding = Math.abs(superProj.y - (superProj.owner.y - 280)) < 20;
if (target.isCrouching && !target.isJumping && superProjectileFromStanding) {
// Super projectile passes over crouching target - no hit
// Remove off-screen super projectiles
if (superProj.x < -50 || superProj.x > 2782) {
superProj.destroy();
superProjectiles.splice(i, 1);
}
continue; // Skip hit detection for crouching dodge
}
if (target.isBlocking) {
// Super projectile was blocked - apply 50% damage and pushback
target.takeDamage(superProj.damage, true, superProj.owner);
LK.getSound('block').play();
// No pushback for shooter when projectile impacts on block
// Push back the receiver (target) - much stronger pushback
var targetPushDirection = target.x < superProj.owner.x ? -1 : 1;
var targetNewX = target.x + targetPushDirection * 450;
targetNewX = Math.max(200, Math.min(1848, targetNewX));
tween(target, {
x: targetNewX
}, {
duration: 800,
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);
LK.getSound('specialImpact').play();
// 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 * 500;
targetNewX = Math.max(200, Math.min(1848, targetNewX));
tween(target, {
x: targetNewX
}, {
duration: 900,
easing: tween.easeOut
});
// Also push back the shooter (attacker) when hitting unblocked target
var shooterPushDirection = superProj.owner.x < target.x ? -1 : 1;
var shooterNewX = superProj.owner.x + shooterPushDirection * 180;
shooterNewX = Math.max(200, Math.min(1848, shooterNewX));
tween(superProj.owner, {
x: shooterNewX
}, {
duration: 600,
easing: tween.easeOut
});
}
superProj.destroy();
superProjectiles.splice(i, 1);
continue;
}
// Remove off-screen super projectiles
if (superProj.x < -50 || superProj.x > 2782) {
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);
LK.getSound('projectileClash').play();
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) < 200 && Math.abs(proj.y - target.y) < 300) {
// Check if projectile should miss crouching target
// Standing projectiles (fired from y-280) should miss crouching targets
var projectileFromStanding = Math.abs(proj.y - (proj.owner.y - 280)) < 20;
if (target.isCrouching && !target.isJumping && projectileFromStanding) {
// Projectile passes over crouching target - no hit
// Remove off-screen projectiles
if (proj.x < -50 || proj.x > 2782) {
proj.destroy();
projectiles.splice(i, 1);
}
continue; // Skip hit detection for crouching dodge
}
if (target.isBlocking) {
// Projectile was blocked - apply reduced damage and pushback
target.takeDamage(Math.floor(proj.damage * 0.7)); // 30% damage reduction for normal blocking (increased from 70% reduction)
LK.getSound('block').play();
// No pushback for shooter when projectile impacts on block
// Push back the receiver (target)
var targetPushDirection = target.x < proj.owner.x ? -1 : 1;
var targetNewX = target.x + targetPushDirection * 120;
targetNewX = Math.max(200, Math.min(1848, targetNewX));
tween(target, {
x: targetNewX
}, {
duration: 400,
easing: tween.easeOut
});
// Flash the target to show block effect
LK.effects.flashObject(target, 0x4444ff, 300);
} else {
// Normal hit
target.takeDamage(proj.damage);
LK.getSound('rangeImpact').play();
// Push back the target when hit by regular projectile
var targetPushDirection = target.x < proj.owner.x ? -1 : 1;
var targetNewX = target.x + targetPushDirection * 120;
targetNewX = Math.max(200, Math.min(1848, targetNewX));
tween(target, {
x: targetNewX
}, {
duration: 400,
easing: tween.easeOut
});
}
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 > 2782) {
proj.destroy();
projectiles.splice(i, 1);
}
}
}
// Handle continuous movement
if (player && !playerIsBlocking) {
if (isMovingLeft && player.x > 200) {
player.stopCrouch(); // Stop crouching when moving left
player.x -= player.speed * 3;
if (player.currentAnimation === 'normal') {
player.setAnimation('walking');
}
} else if (isMovingRight && player.x < 2532) {
player.stopCrouch(); // Stop crouching when moving right
player.x += player.speed * 3;
if (player.currentAnimation === 'normal') {
player.setAnimation('walking');
}
} else {
// Neither left nor right movement is active, reset walking animation
if (player.currentAnimation === 'walking') {
player.setAnimation('normal');
}
}
}
// Update AI
updateAI();
// Check game over with debounce protection (only check every 10 ticks to prevent rapid multiple calls)
if (LK.ticks % 10 === 0) {
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()) {
player.setAnimation('punching', 20); // 20 ticks punch animation
checkMeleeHit(player, enemy, Math.floor(player.attackDamage * 0.75), 'punch');
LK.getSound('punchSound').play();
}
} else if (key === 'x') {
// X key - Kick - can't kick while crouching
if (!player.isCrouching && player.attack()) {
player.setAnimation('kicking', 25); // 25 ticks kick animation (slightly longer)
checkMeleeHit(player, enemy, Math.floor((player.attackDamage + 1) * 0.75), 'kick');
LK.getSound('kickSound').play();
}
} else if (key === 'c') {
// C key - Range attack (special)
if (enemy && player.specialAttack()) {
player.setAnimation('rangeShooting', 15); // 15 ticks range shooting animation
// Determine shoot direction based on enemy position
var shootDirection = enemy.x > player.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
// Adjust projectile origin based on player stance
var projectileY = player.y - 280; // Default standing position - adjusted for 2x bigger fighters
if (player.isCrouching && !player.isJumping) {
projectileY = player.y - 100; // Lower origin when crouching - adjusted for 2x bigger fighters
} else if (player.isJumping) {
projectileY = player.y - 300; // Higher origin when jumping - adjusted for 2x bigger fighters
}
var projectile = new Projectile(player.x + projectileXOffset, projectileY, shootDirection, 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('rangeShoot').play();
}
} else if (key === 'v') {
// V key - Super special attack
if (enemy && player.useSpecialAttack()) {
// Start charging animation before firing
tween(player, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xffaa00
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Set potent shooting animation
player.setAnimation('potentShooting', 50); // 50 ticks potent shooting animation - extended duration
// Return to normal size and color after charging
tween(player, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xffffff
}, {
duration: 200,
easing: tween.easeIn
});
// Determine shoot direction based on enemy position
var shootDirection = enemy.x > player.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
// Adjust super projectile origin based on player stance
var superProjectileY = player.y - 280; // Default standing position - adjusted for 2x bigger fighters
if (player.isCrouching && !player.isJumping) {
superProjectileY = player.y - 100; // Lower origin when crouching - adjusted for 2x bigger fighters
} else if (player.isJumping) {
superProjectileY = player.y - 300; // Higher origin when jumping - adjusted for 2x bigger fighters
}
// Create 7 super projectiles fired with spacing
for (var i = 0; i < 7; i++) {
(function (index) {
LK.setTimeout(function () {
var projectileX = player.x + projectileXOffset + (index - 3) * 60; // Horizontal spread in a row
var projectileYOffset = superProjectileY + (index - 3) * 15; // Add vertical spacing between projectiles
var superProjectile = new SuperProjectile(projectileX, projectileYOffset, shootDirection, Math.floor(player.specialDamage * 2 / 7), player);
// Increase speed for keyboard potent projectiles
superProjectile.speed = 8; // Increased speed to match regular projectiles
// Add laser effects for fighter 3
if (player.fighterType === 3) {
// Initial bright laser effect
tween(superProjectile, {
tint: 0xff0000
}, {
duration: 50
});
// Pulsing laser effect
tween(superProjectile, {
scaleY: 2.0
}, {
duration: 100,
easing: tween.easeInOut
});
tween(superProjectile, {
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeInOut
});
}
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
LK.getSound('specialShoot').play();
}, index * 80); // 80ms delay between each projectile
})(i);
}
// No pushback when firing potent projectiles
// Sound will be played with each projectile instead
}
});
}
}
});
// Initialize title screen
initTitleScreen();
; ===================================================================
--- original.js
+++ change.js
@@ -2870,9 +2870,9 @@
// Flash screen to indicate character must be selected
LK.effects.flashScreen(0xff0000, 500);
return;
}
- if (!gameDifficulty || gameDifficulty === '' || gameDifficulty === 'normal') {
+ if (!gameDifficulty || gameDifficulty === '') {
// Flash screen to indicate difficulty must be selected
LK.effects.flashScreen(0xff0000, 500);
return;
}
@@ -3079,9 +3079,9 @@
// Flash screen to indicate all fighters must be selected
LK.effects.flashScreen(0xff0000, 500);
return;
}
- if (!gameDifficulty || gameDifficulty === '' || gameDifficulty === 'normal') {
+ if (!gameDifficulty || gameDifficulty === '') {
// Flash screen to indicate difficulty must be selected
LK.effects.flashScreen(0xff0000, 500);
return;
}
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