/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Fighter = Container.expand(function (isPlayer) {
var self = Container.call(this);
self.isPlayer = isPlayer || false;
self.maxHealth = 100;
self.health = self.maxHealth;
self.isAttacking = false;
self.isBlocking = false;
self.attackCooldown = 0;
self.blockCooldown = 0;
self.combo = 0;
self.lastAttackTime = 0;
var fighterGraphics = self.attachAsset(isPlayer ? 'playerFighter' : 'enemyFighter', {
anchorX: 0.5,
anchorY: 1.0
});
self.takeDamage = function (damage) {
if (self.isBlocking && LK.ticks - self.lastAttackTime > 10) {
damage = damage * 0.3;
self.showBlockEffect();
}
self.health -= damage;
if (self.health < 0) self.health = 0;
LK.effects.flashObject(self, 0xFF0000, 300);
if (self.health <= 0) {
self.defeated = true;
}
return damage;
};
self.punch = function () {
if (self.attackCooldown > 0) return false;
self.isAttacking = true;
self.attackCooldown = 30;
self.lastAttackTime = LK.ticks;
var effect = self.parent.addChild(LK.getAsset('punchEffect', {
anchorX: 0.5,
anchorY: 0.5
}));
if (self.isPlayer) {
effect.x = self.x + 100;
} else {
effect.x = self.x - 100;
}
effect.y = self.y - 150;
tween(effect, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
onFinish: function onFinish() {
effect.destroy();
}
});
LK.getSound('punch').play();
return true;
};
self.kick = function () {
if (self.attackCooldown > 0) return false;
self.isAttacking = true;
self.attackCooldown = 45;
self.lastAttackTime = LK.ticks;
var effect = self.parent.addChild(LK.getAsset('kickEffect', {
anchorX: 0.5,
anchorY: 0.5
}));
if (self.isPlayer) {
effect.x = self.x + 120;
} else {
effect.x = self.x - 120;
}
effect.y = self.y - 100;
tween(effect, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 400,
onFinish: function onFinish() {
effect.destroy();
}
});
LK.getSound('kick').play();
return true;
};
self.block = function () {
if (self.blockCooldown > 0) return false;
self.isBlocking = true;
self.blockCooldown = 60;
return true;
};
self.showBlockEffect = function () {
var effect = self.parent.addChild(LK.getAsset('blockEffect', {
anchorX: 0.5,
anchorY: 0.5
}));
effect.x = self.x;
effect.y = self.y - 150;
tween(effect, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
onFinish: function onFinish() {
effect.destroy();
}
});
LK.getSound('block').play();
};
self.specialMove = function () {
if (self.attackCooldown > 0 || self.combo < 3) return false;
self.isAttacking = true;
self.attackCooldown = 60;
self.lastAttackTime = LK.ticks;
// Create multiple effects for special move
for (var i = 0; i < 3; i++) {
var effect = self.parent.addChild(LK.getAsset('punchEffect', {
anchorX: 0.5,
anchorY: 0.5
}));
effect.tint = 0xFF00FF; // Purple tint for special move
if (self.isPlayer) {
effect.x = self.x + 80 + i * 40;
} else {
effect.x = self.x - 80 - i * 40;
}
effect.y = self.y - 150 + i * 20;
tween(effect, {
alpha: 0,
scaleX: 2.5,
scaleY: 2.5
}, {
duration: 500,
delay: i * 100,
onFinish: function onFinish() {
effect.destroy();
}
});
}
LK.getSound('punch').play();
return true;
};
self.update = function () {
if (self.attackCooldown > 0) {
self.attackCooldown--;
if (self.attackCooldown <= 0) {
self.isAttacking = false;
}
}
if (self.blockCooldown > 0) {
self.blockCooldown--;
if (self.blockCooldown <= 0) {
self.isBlocking = false;
}
}
if (!self.isPlayer && !self.defeated) {
self.aiUpdate();
}
};
self.aiUpdate = function () {
if (gameState !== 'fighting') return;
var distanceToPlayer = Math.abs(self.x - player.x);
var random = Math.random();
var healthPercentage = self.health / self.maxHealth;
if (distanceToPlayer < 250) {
// More aggressive AI at lower health
var aggressionMultiplier = 1 + (1 - healthPercentage);
if (random < 0.015 * aggressionMultiplier) {
self.punch();
} else if (random < 0.025 * aggressionMultiplier) {
self.kick();
} else if (random < 0.04 && healthPercentage < 0.5) {
// Block more when low on health
self.block();
}
}
};
return self;
});
var HealthBar = Container.expand(function (isPlayer) {
var self = Container.call(this);
self.isPlayer = isPlayer;
var background = self.attachAsset('healthBarBg', {
anchorX: 0.0,
anchorY: 0.0
});
var fill = self.attachAsset('healthBarFill', {
anchorX: 0.0,
anchorY: 0.0
});
self.fill = fill;
self.updateHealth = function (health, maxHealth) {
var percentage = health / maxHealth;
self.fill.width = 600 * percentage;
if (percentage > 0.6) {
self.fill.tint = 0x00FF00;
} else if (percentage > 0.3) {
self.fill.tint = 0xFFFF00;
} else {
self.fill.tint = 0xFF0000;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2C3E50
});
/****
* Game Code
****/
var gameState = 'fighting';
var round = 1;
var maxRounds = 3;
var playerWins = 0;
var enemyWins = 0;
var comboTimer = 0;
var lastHitTime = 0;
var player = game.addChild(new Fighter(true));
player.x = 512;
player.y = 2200;
var enemy = game.addChild(new Fighter(false));
enemy.x = 1536;
enemy.y = 2200;
var playerHealthBar = new HealthBar(true);
playerHealthBar.x = 200;
playerHealthBar.y = 100;
LK.gui.top.addChild(playerHealthBar);
var enemyHealthBar = new HealthBar(false);
enemyHealthBar.x = 1248;
enemyHealthBar.y = 100;
LK.gui.top.addChild(enemyHealthBar);
var roundText = new Text2('Round ' + round, {
size: 80,
fill: 0xFFFFFF
});
roundText.anchor.set(0.5, 0);
roundText.x = 0; // This will be centered by LK.gui.top
LK.gui.top.addChild(roundText);
var comboText = new Text2('', {
size: 60,
fill: 0xFFD700
});
comboText.anchor.set(0.5, 0);
comboText.x = 0; // This will be centered by LK.gui.top
comboText.y = 200;
LK.gui.top.addChild(comboText);
// Add visual control indicators
var controlArea = game.addChild(LK.getAsset('controlArea', {
anchorX: 0,
anchorY: 0
}));
controlArea.x = 0;
controlArea.y = 1800;
controlArea.alpha = 0.3;
var punchLabel = new Text2('PUNCH', {
size: 40,
fill: 0xFFFFFF
});
punchLabel.anchor.set(0.5, 0.5);
punchLabel.x = 512;
punchLabel.y = 1900;
game.addChild(punchLabel);
var kickLabel = new Text2('KICK', {
size: 40,
fill: 0xFFFFFF
});
kickLabel.anchor.set(0.5, 0.5);
kickLabel.x = 512;
kickLabel.y = 2100;
game.addChild(kickLabel);
var blockLabel = new Text2('BLOCK', {
size: 40,
fill: 0xFFFFFF
});
blockLabel.anchor.set(0.5, 0.5);
blockLabel.x = 512;
blockLabel.y = 2500;
game.addChild(blockLabel);
function checkCombat() {
var playerAttackRange = 250;
var enemyAttackRange = 250;
var distance = Math.abs(player.x - enemy.x);
if (player.isAttacking && distance < playerAttackRange && !enemy.defeated) {
var damage = 15;
if (player.combo > 0) {
damage += player.combo * 2;
}
// Special move does more damage
if (player.combo >= 3 && player.attackCooldown >= 50) {
damage = damage * 2;
}
var actualDamage = enemy.takeDamage(damage);
if (actualDamage > damage * 0.8) {
player.combo++;
comboTimer = 180;
LK.setScore(LK.getScore() + damage * player.combo);
if (player.combo > 1) {
if (player.combo >= 3) {
comboText.setText('Combo x' + player.combo + ' - SPECIAL READY!');
} else {
comboText.setText('Combo x' + player.combo);
}
}
}
LK.getSound('hit').play();
lastHitTime = LK.ticks;
}
if (enemy.isAttacking && distance < enemyAttackRange && !player.defeated) {
var damage = 12 + (round - 1) * 3;
player.takeDamage(damage);
LK.getSound('hit').play();
}
}
function resetCombo() {
player.combo = 0;
comboText.setText('');
}
function nextRound() {
round++;
if (round > maxRounds) {
if (playerWins > enemyWins) {
LK.showYouWin();
} else {
LK.showGameOver();
}
return;
}
// Reset fighters for next round
player.health = player.maxHealth;
enemy.health = enemy.maxHealth;
enemy.defeated = false;
player.defeated = false;
player.isAttacking = false;
player.isBlocking = false;
enemy.isAttacking = false;
enemy.isBlocking = false;
player.attackCooldown = 0;
player.blockCooldown = 0;
enemy.attackCooldown = 0;
enemy.blockCooldown = 0;
roundText.setText('Round ' + round);
gameState = 'roundStart';
resetCombo();
// Add countdown before next round starts
LK.setTimeout(function () {
gameState = 'fighting';
}, 1000);
}
function checkRoundEnd() {
if (player.defeated && enemyWins < maxRounds) {
enemyWins++;
LK.setTimeout(nextRound, 2000);
gameState = 'roundEnd';
} else if (enemy.defeated && playerWins < maxRounds) {
playerWins++;
LK.setTimeout(nextRound, 2000);
gameState = 'roundEnd';
}
if (playerWins >= 2) {
LK.showYouWin();
} else if (enemyWins >= 2) {
LK.showGameOver();
}
}
game.down = function (x, y, obj) {
if (gameState !== 'fighting' || player.defeated) return;
var localPos = game.toLocal(obj.parent.toGlobal(obj.position));
if (localPos.x < 1024) {
if (localPos.y < 1800) {
player.punch();
} else if (localPos.y < 2400) {
player.kick();
} else {
player.block();
}
} else if (localPos.x > 1024 && player.combo >= 3) {
// Right side tap for special move when combo is high enough
player.specialMove();
}
};
game.update = function () {
if (gameState === 'fighting') {
checkCombat();
checkRoundEnd();
if (comboTimer > 0) {
comboTimer--;
if (comboTimer <= 0) {
resetCombo();
}
}
if (LK.ticks - lastHitTime > 120) {
resetCombo();
}
}
playerHealthBar.updateHealth(player.health, player.maxHealth);
enemyHealthBar.updateHealth(enemy.health, enemy.maxHealth);
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Fighter = Container.expand(function (isPlayer) {
var self = Container.call(this);
self.isPlayer = isPlayer || false;
self.maxHealth = 100;
self.health = self.maxHealth;
self.isAttacking = false;
self.isBlocking = false;
self.attackCooldown = 0;
self.blockCooldown = 0;
self.combo = 0;
self.lastAttackTime = 0;
var fighterGraphics = self.attachAsset(isPlayer ? 'playerFighter' : 'enemyFighter', {
anchorX: 0.5,
anchorY: 1.0
});
self.takeDamage = function (damage) {
if (self.isBlocking && LK.ticks - self.lastAttackTime > 10) {
damage = damage * 0.3;
self.showBlockEffect();
}
self.health -= damage;
if (self.health < 0) self.health = 0;
LK.effects.flashObject(self, 0xFF0000, 300);
if (self.health <= 0) {
self.defeated = true;
}
return damage;
};
self.punch = function () {
if (self.attackCooldown > 0) return false;
self.isAttacking = true;
self.attackCooldown = 30;
self.lastAttackTime = LK.ticks;
var effect = self.parent.addChild(LK.getAsset('punchEffect', {
anchorX: 0.5,
anchorY: 0.5
}));
if (self.isPlayer) {
effect.x = self.x + 100;
} else {
effect.x = self.x - 100;
}
effect.y = self.y - 150;
tween(effect, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
onFinish: function onFinish() {
effect.destroy();
}
});
LK.getSound('punch').play();
return true;
};
self.kick = function () {
if (self.attackCooldown > 0) return false;
self.isAttacking = true;
self.attackCooldown = 45;
self.lastAttackTime = LK.ticks;
var effect = self.parent.addChild(LK.getAsset('kickEffect', {
anchorX: 0.5,
anchorY: 0.5
}));
if (self.isPlayer) {
effect.x = self.x + 120;
} else {
effect.x = self.x - 120;
}
effect.y = self.y - 100;
tween(effect, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 400,
onFinish: function onFinish() {
effect.destroy();
}
});
LK.getSound('kick').play();
return true;
};
self.block = function () {
if (self.blockCooldown > 0) return false;
self.isBlocking = true;
self.blockCooldown = 60;
return true;
};
self.showBlockEffect = function () {
var effect = self.parent.addChild(LK.getAsset('blockEffect', {
anchorX: 0.5,
anchorY: 0.5
}));
effect.x = self.x;
effect.y = self.y - 150;
tween(effect, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
onFinish: function onFinish() {
effect.destroy();
}
});
LK.getSound('block').play();
};
self.specialMove = function () {
if (self.attackCooldown > 0 || self.combo < 3) return false;
self.isAttacking = true;
self.attackCooldown = 60;
self.lastAttackTime = LK.ticks;
// Create multiple effects for special move
for (var i = 0; i < 3; i++) {
var effect = self.parent.addChild(LK.getAsset('punchEffect', {
anchorX: 0.5,
anchorY: 0.5
}));
effect.tint = 0xFF00FF; // Purple tint for special move
if (self.isPlayer) {
effect.x = self.x + 80 + i * 40;
} else {
effect.x = self.x - 80 - i * 40;
}
effect.y = self.y - 150 + i * 20;
tween(effect, {
alpha: 0,
scaleX: 2.5,
scaleY: 2.5
}, {
duration: 500,
delay: i * 100,
onFinish: function onFinish() {
effect.destroy();
}
});
}
LK.getSound('punch').play();
return true;
};
self.update = function () {
if (self.attackCooldown > 0) {
self.attackCooldown--;
if (self.attackCooldown <= 0) {
self.isAttacking = false;
}
}
if (self.blockCooldown > 0) {
self.blockCooldown--;
if (self.blockCooldown <= 0) {
self.isBlocking = false;
}
}
if (!self.isPlayer && !self.defeated) {
self.aiUpdate();
}
};
self.aiUpdate = function () {
if (gameState !== 'fighting') return;
var distanceToPlayer = Math.abs(self.x - player.x);
var random = Math.random();
var healthPercentage = self.health / self.maxHealth;
if (distanceToPlayer < 250) {
// More aggressive AI at lower health
var aggressionMultiplier = 1 + (1 - healthPercentage);
if (random < 0.015 * aggressionMultiplier) {
self.punch();
} else if (random < 0.025 * aggressionMultiplier) {
self.kick();
} else if (random < 0.04 && healthPercentage < 0.5) {
// Block more when low on health
self.block();
}
}
};
return self;
});
var HealthBar = Container.expand(function (isPlayer) {
var self = Container.call(this);
self.isPlayer = isPlayer;
var background = self.attachAsset('healthBarBg', {
anchorX: 0.0,
anchorY: 0.0
});
var fill = self.attachAsset('healthBarFill', {
anchorX: 0.0,
anchorY: 0.0
});
self.fill = fill;
self.updateHealth = function (health, maxHealth) {
var percentage = health / maxHealth;
self.fill.width = 600 * percentage;
if (percentage > 0.6) {
self.fill.tint = 0x00FF00;
} else if (percentage > 0.3) {
self.fill.tint = 0xFFFF00;
} else {
self.fill.tint = 0xFF0000;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2C3E50
});
/****
* Game Code
****/
var gameState = 'fighting';
var round = 1;
var maxRounds = 3;
var playerWins = 0;
var enemyWins = 0;
var comboTimer = 0;
var lastHitTime = 0;
var player = game.addChild(new Fighter(true));
player.x = 512;
player.y = 2200;
var enemy = game.addChild(new Fighter(false));
enemy.x = 1536;
enemy.y = 2200;
var playerHealthBar = new HealthBar(true);
playerHealthBar.x = 200;
playerHealthBar.y = 100;
LK.gui.top.addChild(playerHealthBar);
var enemyHealthBar = new HealthBar(false);
enemyHealthBar.x = 1248;
enemyHealthBar.y = 100;
LK.gui.top.addChild(enemyHealthBar);
var roundText = new Text2('Round ' + round, {
size: 80,
fill: 0xFFFFFF
});
roundText.anchor.set(0.5, 0);
roundText.x = 0; // This will be centered by LK.gui.top
LK.gui.top.addChild(roundText);
var comboText = new Text2('', {
size: 60,
fill: 0xFFD700
});
comboText.anchor.set(0.5, 0);
comboText.x = 0; // This will be centered by LK.gui.top
comboText.y = 200;
LK.gui.top.addChild(comboText);
// Add visual control indicators
var controlArea = game.addChild(LK.getAsset('controlArea', {
anchorX: 0,
anchorY: 0
}));
controlArea.x = 0;
controlArea.y = 1800;
controlArea.alpha = 0.3;
var punchLabel = new Text2('PUNCH', {
size: 40,
fill: 0xFFFFFF
});
punchLabel.anchor.set(0.5, 0.5);
punchLabel.x = 512;
punchLabel.y = 1900;
game.addChild(punchLabel);
var kickLabel = new Text2('KICK', {
size: 40,
fill: 0xFFFFFF
});
kickLabel.anchor.set(0.5, 0.5);
kickLabel.x = 512;
kickLabel.y = 2100;
game.addChild(kickLabel);
var blockLabel = new Text2('BLOCK', {
size: 40,
fill: 0xFFFFFF
});
blockLabel.anchor.set(0.5, 0.5);
blockLabel.x = 512;
blockLabel.y = 2500;
game.addChild(blockLabel);
function checkCombat() {
var playerAttackRange = 250;
var enemyAttackRange = 250;
var distance = Math.abs(player.x - enemy.x);
if (player.isAttacking && distance < playerAttackRange && !enemy.defeated) {
var damage = 15;
if (player.combo > 0) {
damage += player.combo * 2;
}
// Special move does more damage
if (player.combo >= 3 && player.attackCooldown >= 50) {
damage = damage * 2;
}
var actualDamage = enemy.takeDamage(damage);
if (actualDamage > damage * 0.8) {
player.combo++;
comboTimer = 180;
LK.setScore(LK.getScore() + damage * player.combo);
if (player.combo > 1) {
if (player.combo >= 3) {
comboText.setText('Combo x' + player.combo + ' - SPECIAL READY!');
} else {
comboText.setText('Combo x' + player.combo);
}
}
}
LK.getSound('hit').play();
lastHitTime = LK.ticks;
}
if (enemy.isAttacking && distance < enemyAttackRange && !player.defeated) {
var damage = 12 + (round - 1) * 3;
player.takeDamage(damage);
LK.getSound('hit').play();
}
}
function resetCombo() {
player.combo = 0;
comboText.setText('');
}
function nextRound() {
round++;
if (round > maxRounds) {
if (playerWins > enemyWins) {
LK.showYouWin();
} else {
LK.showGameOver();
}
return;
}
// Reset fighters for next round
player.health = player.maxHealth;
enemy.health = enemy.maxHealth;
enemy.defeated = false;
player.defeated = false;
player.isAttacking = false;
player.isBlocking = false;
enemy.isAttacking = false;
enemy.isBlocking = false;
player.attackCooldown = 0;
player.blockCooldown = 0;
enemy.attackCooldown = 0;
enemy.blockCooldown = 0;
roundText.setText('Round ' + round);
gameState = 'roundStart';
resetCombo();
// Add countdown before next round starts
LK.setTimeout(function () {
gameState = 'fighting';
}, 1000);
}
function checkRoundEnd() {
if (player.defeated && enemyWins < maxRounds) {
enemyWins++;
LK.setTimeout(nextRound, 2000);
gameState = 'roundEnd';
} else if (enemy.defeated && playerWins < maxRounds) {
playerWins++;
LK.setTimeout(nextRound, 2000);
gameState = 'roundEnd';
}
if (playerWins >= 2) {
LK.showYouWin();
} else if (enemyWins >= 2) {
LK.showGameOver();
}
}
game.down = function (x, y, obj) {
if (gameState !== 'fighting' || player.defeated) return;
var localPos = game.toLocal(obj.parent.toGlobal(obj.position));
if (localPos.x < 1024) {
if (localPos.y < 1800) {
player.punch();
} else if (localPos.y < 2400) {
player.kick();
} else {
player.block();
}
} else if (localPos.x > 1024 && player.combo >= 3) {
// Right side tap for special move when combo is high enough
player.specialMove();
}
};
game.update = function () {
if (gameState === 'fighting') {
checkCombat();
checkRoundEnd();
if (comboTimer > 0) {
comboTimer--;
if (comboTimer <= 0) {
resetCombo();
}
}
if (LK.ticks - lastHitTime > 120) {
resetCombo();
}
}
playerHealthBar.updateHealth(player.health, player.maxHealth);
enemyHealthBar.updateHealth(enemy.health, enemy.maxHealth);
};