User prompt
punch cant land if enemy crouching and cant use kick while crouching
User prompt
enemy can jump and crouch tho ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make jump a little higer and gravity a little bit lower
User prompt
make gravity lower and jump higer
User prompt
the proyectiles change their origing acording if youre standing jumping or crouching ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add gravity ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add crouch and jump and enemy can also hold movement ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
if shoting or reseiving a special attack you get pushed ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
if two range attacks clash they destroy each other and you can hold the movement buttoms ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
every hit received fills 2% of the special attack bar
User prompt
if the potent attack is blocked it will only deal 50% damage and will push away the one shoting it and will push the one receiving it just when it lands ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
range attack also fills the special attack bar but 50% less than melee attacks ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
punch and kick deal less damage
User prompt
enemy doesnt use range attacks so often
User prompt
add a third bar and a buttom for an special attack, the bar is empty but it slowly fills with every attack landed, enemy can also use it, using it shots a potent attack, if two potent attacks clash to each other both are destroyed ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
cant move while blocking
User prompt
add if you use the block buttom reduces damage received to 25% when you hold it and reduces a 100% damage the first 0,7 seconds you touch it ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add behaivior that makes enemy try to kick and punch the player
User prompt
enemy still tries to get close to you
User prompt
enemy still tries to get closer to punch and kick you, only tries to move away to use range attacks
User prompt
enemy can use range attack all the time and will try to block attacks, if kick or punch are blocked the one attacking gets pushes a litle bit ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
enemy can use range attack with a lot of range
User prompt
punch and kick have a little bit more range
User prompt
enemy can use range attacks from far away
User prompt
attacks deal less damage
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var EnergyBar = Container.expand(function (fighter, x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.fighter = fighter;
var bgBar = self.attachAsset('energyBarBg', {
anchorX: 0,
anchorY: 0
});
// Create 3 individual energy bars
self.energyBars = [];
for (var i = 0; i < 3; i++) {
var energyBar = self.attachAsset('energyBar', {
anchorX: 0,
anchorY: 0
});
energyBar.x = i * 135; // Space bars evenly (400/3 ≈ 133)
energyBar.width = 125; // Slightly smaller to have gaps
self.energyBars.push(energyBar);
}
self.update = function () {
// Show energy bars based on current energy level (0-3)
var energyLevel = Math.floor(self.fighter.energy / (self.fighter.maxEnergy / 3));
for (var i = 0; i < 3; i++) {
self.energyBars[i].visible = i < energyLevel;
}
};
return self;
});
var Fighter = Container.expand(function (fighterType, isPlayer) {
var self = Container.call(this);
// Fighter properties
self.fighterType = fighterType || 1;
self.isPlayer = isPlayer || false;
self.maxHealth = 100;
self.health = 100;
self.maxEnergy = 3; // Changed to 3 energy units
self.energy = 3; // Start with full energy
self.speed = 3;
self.isBlocking = false;
self.attackCooldown = 0;
self.specialCooldown = 0;
self.maxSpecialCharge = 100;
self.specialCharge = 0;
// Create fighter graphics
var fighterGraphics = self.attachAsset('fighter' + self.fighterType, {
anchorX: 0.5,
anchorY: 1.0
});
// Fighter stats based on type
switch (self.fighterType) {
case 1:
// Red Fighter - Balanced
self.attackDamage = 8;
self.specialDamage = 10;
self.specialCost = 1; // 1 energy bar per special attack
break;
case 2:
// Blue Fighter - Fast
self.attackDamage = 6;
self.specialDamage = 8;
self.specialCost = 1; // 1 energy bar per special attack
self.speed = 4;
break;
case 3:
// Green Fighter - Strong
self.attackDamage = 10;
self.specialDamage = 12;
self.specialCost = 1; // 1 energy bar per special attack
self.speed = 2;
break;
case 4:
// Yellow Fighter - Energy Efficient
self.attackDamage = 7;
self.specialDamage = 9;
self.specialCost = 1; // 1 energy bar per special attack
break;
case 5:
// Purple Fighter - High Health
self.attackDamage = 7;
self.specialDamage = 9;
self.specialCost = 1; // 1 energy bar per special attack
self.maxHealth = 120;
self.health = 120;
break;
}
self.takeDamage = function (damage, isSuperProjectile, attacker) {
if (self.isPlayer && playerIsBlocking) {
// Check if within perfect block window (first 0.7 seconds)
var timeSinceBlockStart = LK.ticks - playerBlockStartTime;
if (timeSinceBlockStart <= 42) {
// 42 ticks = 0.7 seconds at 60fps
damage = 0; // 100% damage reduction
} else {
damage = Math.floor(damage * 0.25); // 25% damage when holding block
}
} else if (self.isBlocking) {
if (isSuperProjectile) {
damage = Math.floor(damage * 0.5); // 50% damage when blocking super projectile
} else {
damage = Math.floor(damage * 0.3);
}
}
self.health = Math.max(0, self.health - damage);
// Flash red when taking damage
LK.effects.flashObject(fighterGraphics, 0xFF0000, 300);
};
self.useEnergy = function (amount) {
if (self.energy >= amount) {
self.energy -= amount;
return true;
}
return false;
};
self.attack = function () {
if (self.attackCooldown <= 0) {
self.attackCooldown = 30;
return true;
}
return false;
};
self.specialAttack = function () {
if (self.specialCooldown <= 0 && self.useEnergy(self.specialCost)) {
self.specialCooldown = 90;
return true;
}
return false;
};
self.chargeSpecial = function (amount) {
self.specialCharge = Math.min(self.maxSpecialCharge, self.specialCharge + amount);
};
self.canUseSpecialAttack = function () {
return self.specialCharge >= self.maxSpecialCharge;
};
self.useSpecialAttack = function () {
if (self.canUseSpecialAttack()) {
self.specialCharge = 0;
return true;
}
return false;
};
self.update = function () {
// Cooldown management
if (self.attackCooldown > 0) self.attackCooldown--;
if (self.specialCooldown > 0) self.specialCooldown--;
// Energy regeneration - regenerate 1 energy every 10 seconds (600 ticks), one bar at a time
if (self.energy < self.maxEnergy && LK.ticks % 600 === 0) {
self.energy = Math.min(self.maxEnergy, self.energy + 1);
}
};
return self;
});
var HealthBar = Container.expand(function (fighter, x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.fighter = fighter;
var bgBar = self.attachAsset('healthBarBg', {
anchorX: 0,
anchorY: 0
});
var healthBar = self.attachAsset('healthBar', {
anchorX: 0,
anchorY: 0
});
self.update = function () {
var healthPercent = self.fighter.health / self.fighter.maxHealth;
healthBar.width = 400 * healthPercent;
};
return self;
});
var Projectile = Container.expand(function (x, y, direction, damage, owner) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.direction = direction; // 1 for right, -1 for left
self.damage = damage;
self.owner = owner;
self.speed = 8;
var projectileGraphics = self.attachAsset('projectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
self.x += self.speed * self.direction;
};
return self;
});
var SpecialBar = Container.expand(function (fighter, x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.fighter = fighter;
var bgBar = self.attachAsset('specialBarBg', {
anchorX: 0,
anchorY: 0
});
var specialBar = self.attachAsset('specialBar', {
anchorX: 0,
anchorY: 0
});
self.update = function () {
var specialPercent = self.fighter.specialCharge / self.fighter.maxSpecialCharge;
specialBar.width = 400 * specialPercent;
};
return self;
});
var SuperProjectile = Container.expand(function (x, y, direction, damage, owner) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.direction = direction; // 1 for right, -1 for left
self.damage = damage;
self.owner = owner;
self.speed = 6;
self.isSuperProjectile = true;
var projectileGraphics = self.attachAsset('projectile', {
anchorX: 0.5,
anchorY: 0.5
});
projectileGraphics.tint = 0xffaa00; // Orange tint for special projectiles
projectileGraphics.scaleX = 2;
projectileGraphics.scaleY = 2;
self.update = function () {
self.x += self.speed * self.direction;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2C1810
});
/****
* Game Code
****/
// Sounds
// Combat elements
// UI elements
// Character assets
// Game states
var gameState = 'characterSelect'; // 'characterSelect', 'combat', 'gameOver'
var selectedCharacter = 1;
var enemyCharacter = 2;
// Character selection
var characterSelectors = [];
var selectionBorder = null;
// Combat variables
var player = null;
var enemy = null;
var playerHealthBar = null;
var playerEnergyBar = null;
var playerSpecialBar = null;
var enemyHealthBar = null;
var enemyEnergyBar = null;
var enemySpecialBar = null;
var projectiles = [];
var superProjectiles = [];
var punchButton = null;
var kickButton = null;
var rangeButton = null;
var blockButton = null;
var specialButton = null;
var playerBlockStartTime = 0;
var playerIsBlocking = false;
var punchButtonText = null;
var kickButtonText = null;
var rangeButtonText = null;
var blockButtonText = null;
var specialButtonText = null;
var leftMoveButton = null;
var rightMoveButton = null;
var leftMoveButtonText = null;
var rightMoveButtonText = null;
// UI elements
var titleText = new Text2('Arena Warriors', {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
LK.gui.top.addChild(titleText);
titleText.y = 50;
var instructionText = new Text2('Select Your Fighter', {
size: 50,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
// Combat controls text
var controlsText = new Text2('Left: Move | Right: Move | Center Left: Punch | Center Right: Kick | Top: Block | Bottom: Special', {
size: 30,
fill: 0xFFFFFF
});
controlsText.anchor.set(0.5, 1);
function initCharacterSelection() {
instructionText.y = 200;
game.addChild(instructionText);
// Create character selection grid
for (var i = 1; i <= 5; i++) {
var fighter = LK.getAsset('fighter' + i, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7,
scaleY: 0.7
});
var col = (i - 1) % 3;
var row = Math.floor((i - 1) / 3);
fighter.x = 400 + col * 300;
fighter.y = 600 + row * 350;
fighter.fighterIndex = i;
characterSelectors.push(fighter);
game.addChild(fighter);
}
// Create selection border
selectionBorder = LK.getAsset('selectionBorder', {
anchorX: 0.5,
anchorY: 0.5
});
selectionBorder.alpha = 0.3;
updateSelectionBorder();
game.addChild(selectionBorder);
}
function updateSelectionBorder() {
if (selectionBorder && characterSelectors[selectedCharacter - 1]) {
selectionBorder.x = characterSelectors[selectedCharacter - 1].x;
selectionBorder.y = characterSelectors[selectedCharacter - 1].y;
}
}
function startCombat() {
gameState = 'combat';
// Clear character selection
game.removeChild(instructionText);
for (var i = 0; i < characterSelectors.length; i++) {
game.removeChild(characterSelectors[i]);
}
game.removeChild(selectionBorder);
// Create fighters
player = game.addChild(new Fighter(selectedCharacter, true));
player.x = 400;
player.y = 2200;
enemy = game.addChild(new Fighter(enemyCharacter, false));
enemy.x = 1648;
enemy.y = 2200;
// Create health and energy bars
playerHealthBar = game.addChild(new HealthBar(player, 150, 150));
playerEnergyBar = game.addChild(new EnergyBar(player, 150, 200));
playerSpecialBar = game.addChild(new SpecialBar(player, 150, 250));
enemyHealthBar = game.addChild(new HealthBar(enemy, 1498, 150));
enemyEnergyBar = game.addChild(new EnergyBar(enemy, 1498, 200));
enemySpecialBar = game.addChild(new SpecialBar(enemy, 1498, 250));
// Create combat control buttons
punchButton = LK.getAsset('punchButton', {
anchorX: 0.5,
anchorY: 0.5
});
punchButton.x = 350;
punchButton.y = 2500;
game.addChild(punchButton);
kickButton = LK.getAsset('kickButton', {
anchorX: 0.5,
anchorY: 0.5
});
kickButton.x = 700;
kickButton.y = 2500;
game.addChild(kickButton);
rangeButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5
});
rangeButton.x = 1400;
rangeButton.y = 2500;
game.addChild(rangeButton);
blockButton = LK.getAsset('blockButton', {
anchorX: 0.5,
anchorY: 0.5
});
blockButton.x = 1050;
blockButton.y = 2400;
game.addChild(blockButton);
specialButton = LK.getAsset('specialButton', {
anchorX: 0.5,
anchorY: 0.5
});
specialButton.x = 1050;
specialButton.y = 2600;
game.addChild(specialButton);
// Create movement buttons on the right side
leftMoveButton = LK.getAsset('leftMoveButton', {
anchorX: 0.5,
anchorY: 0.5
});
leftMoveButton.x = 1750;
leftMoveButton.y = 2350;
game.addChild(leftMoveButton);
rightMoveButton = LK.getAsset('rightMoveButton', {
anchorX: 0.5,
anchorY: 0.5
});
rightMoveButton.x = 1750;
rightMoveButton.y = 2550;
game.addChild(rightMoveButton);
// 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);
// Add controls text
controlsText.setText('Tap buttons to fight! Use arrow buttons to move.');
controlsText.y = 2600;
game.addChild(controlsText);
// Add player and enemy name labels
var playerLabel = new Text2('Player', {
size: 40,
fill: 0xFFFFFF
});
playerLabel.anchor.set(0, 0);
playerLabel.x = 150;
playerLabel.y = 100;
game.addChild(playerLabel);
var enemyLabel = new Text2('Enemy', {
size: 40,
fill: 0xFFFFFF
});
enemyLabel.anchor.set(1, 0);
enemyLabel.x = 1898;
enemyLabel.y = 100;
game.addChild(enemyLabel);
}
function handleCombatInput(x, y) {
if (!player || gameState !== 'combat') return;
var gameWidth = 2048;
var gameHeight = 2732;
// Check button presses first
if (punchButton && Math.abs(x - punchButton.x) < 100 && Math.abs(y - punchButton.y) < 40) {
// Punch button pressed
if (player.attack()) {
var hit = checkMeleeHit(player, enemy, Math.floor(player.attackDamage * 0.75));
if (hit) player.chargeSpecial(15); // Charge special on successful hit
LK.getSound('punch').play();
}
return;
}
if (kickButton && Math.abs(x - kickButton.x) < 100 && Math.abs(y - kickButton.y) < 40) {
// Kick button pressed
if (player.attack()) {
var hit = checkMeleeHit(player, enemy, Math.floor((player.attackDamage + 1) * 0.75));
if (hit) player.chargeSpecial(15); // Charge special on successful hit
LK.getSound('kick').play();
}
return;
}
if (rangeButton && Math.abs(x - rangeButton.x) < 100 && Math.abs(y - rangeButton.y) < 40) {
// Range attack button pressed
if (player.specialAttack()) {
var projectile = new Projectile(player.x + 50, player.y - 100, 1, player.specialDamage, player);
projectiles.push(projectile);
game.addChild(projectile);
player.chargeSpecial(7); // Charge special at 50% rate (15 * 0.5 = 7.5, rounded to 7)
LK.getSound('special').play();
}
return;
}
if (specialButton && Math.abs(x - specialButton.x) < 100 && Math.abs(y - specialButton.y) < 40) {
// Special button pressed
if (player.useSpecialAttack()) {
var superProjectile = new SuperProjectile(player.x + 50, player.y - 100, 1, player.specialDamage * 2, player);
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
LK.getSound('special').play();
}
return;
}
if (blockButton && Math.abs(x - blockButton.x) < 100 && Math.abs(y - blockButton.y) < 40) {
// Block button pressed
if (!playerIsBlocking) {
playerBlockStartTime = LK.ticks;
playerIsBlocking = true;
}
player.isBlocking = true;
LK.getSound('block').play();
return;
}
if (leftMoveButton && Math.abs(x - leftMoveButton.x) < 75 && Math.abs(y - leftMoveButton.y) < 75) {
// Left movement button pressed
if (!playerIsBlocking && player.x > 200) {
player.x -= player.speed * 10;
}
return;
}
if (rightMoveButton && Math.abs(x - rightMoveButton.x) < 75 && Math.abs(y - rightMoveButton.y) < 75) {
// Right movement button pressed
if (!playerIsBlocking && player.x < 1848) {
player.x += player.speed * 10;
}
return;
}
// Movement is now handled by dedicated buttons above
}
function checkMeleeHit(attacker, target, damage) {
var distance = Math.abs(attacker.x - target.x);
if (distance < 280) {
if (target.isBlocking) {
// Attack was blocked - reduced damage and pushback
target.takeDamage(Math.floor(damage * 0.3));
LK.getSound('block').play();
// Apply pushback to the attacker
var pushDirection = attacker.x < target.x ? -1 : 1;
var pushDistance = 60;
var newX = attacker.x + pushDirection * pushDistance;
// Make sure attacker stays within bounds
newX = Math.max(200, Math.min(1848, newX));
// Animate the pushback using tween
tween(attacker, {
x: newX
}, {
duration: 200,
easing: tween.easeOut
});
// Flash the target to show block effect
LK.effects.flashObject(target, 0x4444ff, 300);
return false; // Hit was blocked
} else {
// Normal hit
target.takeDamage(damage);
return true; // Hit was successful
}
}
return false; // No hit
}
function updateAI() {
if (!enemy || !player) return;
var distance = Math.abs(enemy.x - player.x);
// Enhanced AI behavior - mix of range attacks, melee attacks, and movement
if (LK.ticks % 30 === 0) {
var action = Math.floor(Math.random() * 10);
// Check if enemy is in melee range (close enough to punch/kick)
if (distance < 280) {
// In melee range - try to attack or block
if (action <= 3 && enemy.attack()) {
// Punch attack
var hit = checkMeleeHit(enemy, player, Math.floor(enemy.attackDamage * 0.75));
if (hit) enemy.chargeSpecial(15); // Charge special on successful hit
LK.getSound('punch').play();
} else if (action <= 6 && enemy.attack()) {
// Kick attack (slightly more damage)
var hit = checkMeleeHit(enemy, player, Math.floor((enemy.attackDamage + 1) * 0.75));
if (hit) enemy.chargeSpecial(15); // Charge special on successful hit
LK.getSound('kick').play();
} else if (action <= 8) {
// Block when not attacking
enemy.isBlocking = true;
} else {
// Back away occasionally when too close
if (enemy.x > player.x) {
enemy.x += enemy.speed * 6;
} else {
enemy.x -= enemy.speed * 6;
}
}
} 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) {
enemy.x -= enemy.speed * 6;
} else {
enemy.x += enemy.speed * 6;
}
} else if (action <= 6 && enemy.canUseSpecialAttack() && enemy.useSpecialAttack()) {
// Use super special attack
var superProjectile = new SuperProjectile(enemy.x - 50, enemy.y - 100, -1, enemy.specialDamage * 2, enemy);
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
LK.getSound('special').play();
} else if (action <= 6 && enemy.energy >= 1 && enemy.specialAttack()) {
// Use range attack (reduced frequency)
var projectile = new Projectile(enemy.x - 50, enemy.y - 100, -1, enemy.specialDamage, enemy);
projectiles.push(projectile);
game.addChild(projectile);
enemy.chargeSpecial(7); // Charge special at 50% rate (15 * 0.5 = 7.5, rounded to 7)
LK.getSound('special').play();
} else {
// Block occasionally
enemy.isBlocking = true;
}
} else {
// Long range - use range attacks or move closer
if (action <= 2 && enemy.canUseSpecialAttack() && enemy.useSpecialAttack()) {
// Use super special attack when available (reduced frequency)
var superProjectile = new SuperProjectile(enemy.x - 50, enemy.y - 100, -1, enemy.specialDamage * 2, enemy);
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
LK.getSound('special').play();
} else if (action <= 3 && enemy.energy >= 1 && enemy.specialAttack()) {
// Use range attack when available (reduced frequency)
var projectile = new Projectile(enemy.x - 50, enemy.y - 100, -1, enemy.specialDamage, enemy);
projectiles.push(projectile);
game.addChild(projectile);
enemy.chargeSpecial(7); // Charge special at 50% rate (15 * 0.5 = 7.5, rounded to 7)
LK.getSound('special').play();
} else if (action <= 8) {
// Move closer to player for melee combat
if (enemy.x > player.x) {
enemy.x -= enemy.speed * 6;
} else {
enemy.x += enemy.speed * 6;
}
} else {
// Occasionally block at range
enemy.isBlocking = true;
}
}
}
// Reset blocking periodically
if (LK.ticks % 45 === 0) {
enemy.isBlocking = false;
}
}
function checkGameOver() {
if (player && player.health <= 0) {
LK.showGameOver();
} else if (enemy && enemy.health <= 0) {
LK.showYouWin();
}
}
// Character selection input
game.down = function (x, y, obj) {
if (gameState === 'characterSelect') {
// Check which character was selected
for (var i = 0; i < characterSelectors.length; i++) {
var fighter = characterSelectors[i];
// Use x,y coordinates directly since they're already in game coordinates
if (Math.abs(x - fighter.x) < 100 && Math.abs(y - fighter.y) < 150) {
selectedCharacter = fighter.fighterIndex;
enemyCharacter = selectedCharacter % 5 + 1; // Simple enemy selection
updateSelectionBorder();
// Start combat after selection
LK.setTimeout(function () {
startCombat();
}, 500);
break;
}
}
} else if (gameState === 'combat') {
handleCombatInput(x, y);
}
};
game.up = function (x, y, obj) {
if (player && gameState === 'combat') {
player.isBlocking = false;
playerIsBlocking = false;
}
};
game.update = function () {
if (gameState === 'combat') {
// Update fighters
if (player) player.update();
if (enemy) enemy.update();
// Update UI bars
if (playerHealthBar) playerHealthBar.update();
if (playerEnergyBar) playerEnergyBar.update();
if (playerSpecialBar) playerSpecialBar.update();
if (enemyHealthBar) enemyHealthBar.update();
if (enemyEnergyBar) enemyEnergyBar.update();
if (enemySpecialBar) enemySpecialBar.update();
// Update button availability visual feedback
if (rangeButtonText && player) {
if (player.energy >= player.specialCost) {
rangeButtonText.tint = 0xFFFFFF; // White when available
} else {
rangeButtonText.tint = 0x666666; // Gray when not available
}
}
if (specialButtonText && player) {
if (player.canUseSpecialAttack()) {
specialButtonText.tint = 0xFFFFFF; // White when available
} else {
specialButtonText.tint = 0x666666; // Gray when not available
}
}
// Update super projectiles
for (var i = superProjectiles.length - 1; i >= 0; i--) {
var superProj = superProjectiles[i];
superProj.update();
// Check for super projectile clashes
for (var j = superProjectiles.length - 1; j >= 0; j--) {
if (i !== j) {
var otherSuperProj = superProjectiles[j];
if (Math.abs(superProj.x - otherSuperProj.x) < 80 && Math.abs(superProj.y - otherSuperProj.y) < 80) {
// Super projectiles clash - destroy both
LK.effects.flashScreen(0xffffff, 200);
superProj.destroy();
otherSuperProj.destroy();
superProjectiles.splice(Math.max(i, j), 1);
superProjectiles.splice(Math.min(i, j), 1);
i = Math.min(i, j) - 1; // Adjust index
break;
}
}
}
if (i >= 0 && i < superProjectiles.length) {
var superProj = superProjectiles[i];
// Check super projectile hits
var target = superProj.owner === player ? enemy : player;
if (target && Math.abs(superProj.x - target.x) < 100 && Math.abs(superProj.y - target.y) < 150) {
if (target.isBlocking) {
// Super projectile was blocked - apply 50% damage and pushback
target.takeDamage(superProj.damage, true, superProj.owner);
LK.getSound('block').play();
// Push back the shooter (attacker)
var shooterPushDirection = superProj.owner.x < target.x ? -1 : 1;
var shooterNewX = superProj.owner.x + shooterPushDirection * 80;
shooterNewX = Math.max(200, Math.min(1848, shooterNewX));
tween(superProj.owner, {
x: shooterNewX
}, {
duration: 300,
easing: tween.easeOut
});
// Push back the receiver (target)
var targetPushDirection = target.x < superProj.owner.x ? -1 : 1;
var targetNewX = target.x + targetPushDirection * 60;
targetNewX = Math.max(200, Math.min(1848, targetNewX));
tween(target, {
x: targetNewX
}, {
duration: 250,
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);
}
superProj.destroy();
superProjectiles.splice(i, 1);
continue;
}
// Remove off-screen super projectiles
if (superProj.x < -50 || superProj.x > 2098) {
superProj.destroy();
superProjectiles.splice(i, 1);
}
}
}
// Update projectiles
for (var i = projectiles.length - 1; i >= 0; i--) {
var proj = projectiles[i];
proj.update();
// Check if regular projectile hits super projectile
for (var j = superProjectiles.length - 1; j >= 0; j--) {
var superProj = superProjectiles[j];
if (Math.abs(proj.x - superProj.x) < 60 && Math.abs(proj.y - superProj.y) < 60) {
// Regular projectile destroyed by super projectile
proj.destroy();
projectiles.splice(i, 1);
break;
}
}
if (i >= 0 && i < projectiles.length) {
var proj = projectiles[i];
// Check projectile hits
var target = proj.owner === player ? enemy : player;
if (target && Math.abs(proj.x - target.x) < 100 && Math.abs(proj.y - target.y) < 150) {
target.takeDamage(proj.damage);
proj.owner.chargeSpecial(7); // Charge special at 50% rate for successful range hit
proj.destroy();
projectiles.splice(i, 1);
continue;
}
// Remove off-screen projectiles
if (proj.x < -50 || proj.x > 2098) {
proj.destroy();
projectiles.splice(i, 1);
}
}
}
// Update AI
updateAI();
// Check game over
checkGameOver();
}
};
// Keyboard event handler
LK.on('keydown', function (event) {
if (gameState !== 'combat' || !player) return;
var key = event.key.toLowerCase();
if (key === 'z') {
// Z key - Punch
if (player.attack()) {
checkMeleeHit(player, enemy, Math.floor(player.attackDamage * 0.75));
LK.getSound('punch').play();
}
} else if (key === 'x') {
// X key - Kick
if (player.attack()) {
checkMeleeHit(player, enemy, Math.floor((player.attackDamage + 1) * 0.75));
LK.getSound('kick').play();
}
} else if (key === 'c') {
// C key - Range attack (special)
if (player.specialAttack()) {
var projectile = new Projectile(player.x + 50, player.y - 100, 1, player.specialDamage, player);
projectiles.push(projectile);
game.addChild(projectile);
player.chargeSpecial(7); // Charge special at 50% rate (15 * 0.5 = 7.5, rounded to 7)
LK.getSound('special').play();
}
} else if (key === 'v') {
// V key - Super special attack
if (player.useSpecialAttack()) {
var superProjectile = new SuperProjectile(player.x + 50, player.y - 100, 1, player.specialDamage * 2, player);
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
LK.getSound('special').play();
}
}
});
// Initialize character selection screen
initCharacterSelection();
; ===================================================================
--- original.js
+++ change.js
@@ -91,9 +91,9 @@
self.maxHealth = 120;
self.health = 120;
break;
}
- self.takeDamage = function (damage) {
+ self.takeDamage = function (damage, isSuperProjectile, attacker) {
if (self.isPlayer && playerIsBlocking) {
// Check if within perfect block window (first 0.7 seconds)
var timeSinceBlockStart = LK.ticks - playerBlockStartTime;
if (timeSinceBlockStart <= 42) {
@@ -102,9 +102,13 @@
} else {
damage = Math.floor(damage * 0.25); // 25% damage when holding block
}
} else if (self.isBlocking) {
- damage = Math.floor(damage * 0.3);
+ if (isSuperProjectile) {
+ damage = Math.floor(damage * 0.5); // 50% damage when blocking super projectile
+ } else {
+ damage = Math.floor(damage * 0.3);
+ }
}
self.health = Math.max(0, self.health - damage);
// Flash red when taking damage
LK.effects.flashObject(fighterGraphics, 0xFF0000, 300);
@@ -240,13 +244,13 @@
/****
* Game Code
****/
-// Game states
-// Character assets
-// UI elements
-// Combat elements
// Sounds
+// Combat elements
+// UI elements
+// Character assets
+// Game states
var gameState = 'characterSelect'; // 'characterSelect', 'combat', 'gameOver'
var selectedCharacter = 1;
var enemyCharacter = 2;
// Character selection
@@ -760,9 +764,38 @@
var superProj = superProjectiles[i];
// Check super projectile hits
var target = superProj.owner === player ? enemy : player;
if (target && Math.abs(superProj.x - target.x) < 100 && Math.abs(superProj.y - target.y) < 150) {
- target.takeDamage(superProj.damage);
+ if (target.isBlocking) {
+ // Super projectile was blocked - apply 50% damage and pushback
+ target.takeDamage(superProj.damage, true, superProj.owner);
+ LK.getSound('block').play();
+ // Push back the shooter (attacker)
+ var shooterPushDirection = superProj.owner.x < target.x ? -1 : 1;
+ var shooterNewX = superProj.owner.x + shooterPushDirection * 80;
+ shooterNewX = Math.max(200, Math.min(1848, shooterNewX));
+ tween(superProj.owner, {
+ x: shooterNewX
+ }, {
+ duration: 300,
+ easing: tween.easeOut
+ });
+ // Push back the receiver (target)
+ var targetPushDirection = target.x < superProj.owner.x ? -1 : 1;
+ var targetNewX = target.x + targetPushDirection * 60;
+ targetNewX = Math.max(200, Math.min(1848, targetNewX));
+ tween(target, {
+ x: targetNewX
+ }, {
+ duration: 250,
+ 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);
+ }
superProj.destroy();
superProjectiles.splice(i, 1);
continue;
}
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