/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Attack class (for both player and enemy)
var Attack = Container.expand(function () {
var self = Container.call(this);
// type: 'basic', 'special', 'enemy'
self.type = 'basic';
self.owner = null; // player or enemy
self.dmg = 10;
self.speed = 30;
self.radius = 30;
self.dirY = -1; // -1 up, 1 down
// Attach asset
self.setType = function (type) {
self.type = type;
if (type === 'basic') {
self.removeChildren();
self.attachAsset('attack_basic', {
anchorX: 0.5,
anchorY: 0.5
});
self.dmg = 10;
self.speed = 36;
self.radius = 30;
self.dirY = -1;
} else if (type === 'special') {
self.removeChildren();
self.attachAsset('attack_special', {
anchorX: 0.5,
anchorY: 0.5
});
self.dmg = 22;
self.speed = 24;
self.radius = 40;
self.dirY = -1;
} else if (type === 'enemy') {
self.removeChildren();
self.attachAsset('attack_enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.dmg = 12;
self.speed = 28;
self.radius = 30;
self.dirY = 1;
}
};
// Update
self.update = function () {
self.y += self.speed * self.dirY;
};
return self;
});
// Enemy Pokemon class (AI)
var EnemyPokemon = Container.expand(function () {
var self = Container.call(this);
// Attach enemy asset
var sprite = self.attachAsset('poke_enemy', {
anchorX: 0.5,
anchorY: 0.5
});
// Stats
self.maxHP = 100;
self.hp = 100;
self.speed = 12; // px per move
self.radius = sprite.width / 2;
// For attack cooldowns
self.basicCooldown = 0;
self.specialCooldown = 0;
// For invulnerability after hit
self.invuln = 0;
// Move to (x, y) with bounds
self.moveTo = function (x, y) {
// Clamp to arena bounds (leave 20px margin)
var minX = 20 + self.radius;
var maxX = 2048 - 20 - self.radius;
var minY = 20 + self.radius;
var maxY = 1366 - 20 - self.radius; // top half
self.x = Math.max(minX, Math.min(maxX, x));
self.y = Math.max(minY, Math.min(maxY, y));
};
// Take damage
self.takeDamage = function (dmg) {
if (self.invuln > 0) return;
self.hp -= dmg;
if (self.hp < 0) self.hp = 0;
self.invuln = 30; // 0.5s invuln
LK.effects.flashObject(self, 0xffffff, 200);
};
return self;
});
// Player Pokemon class
var PlayerPokemon = Container.expand(function () {
var self = Container.call(this);
// Attach player asset
var sprite = self.attachAsset('poke_player', {
anchorX: 0.5,
anchorY: 0.5
});
// Stats
self.maxHP = 100;
self.hp = 100;
self.speed = 18; // px per move
self.radius = sprite.width / 2;
// For drag
self.isDragging = false;
// For attack cooldowns
self.basicCooldown = 0;
self.specialCooldown = 0;
// For invulnerability after hit
self.invuln = 0;
// Move to (x, y) with bounds
self.moveTo = function (x, y) {
// Clamp to arena bounds (leave 20px margin)
var minX = 20 + self.radius;
var maxX = 2048 - 20 - self.radius;
var minY = 1366 + 20 + self.radius; // bottom half
var maxY = 2732 - 20 - self.radius;
self.x = Math.max(minX, Math.min(maxX, x));
self.y = Math.max(minY, Math.min(maxY, y));
};
// Take damage
self.takeDamage = function (dmg) {
if (self.invuln > 0) return;
self.hp -= dmg;
if (self.hp < 0) self.hp = 0;
self.invuln = 30; // 0.5s invuln
LK.effects.flashObject(self, 0xffffff, 200);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xf5f5f5
});
/****
* Game Code
****/
// Attack SFX
// Pokemon shapes (simple for MVP)
// Arena background
var arenaBg = LK.getAsset('arena_bg', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(arenaBg);
// Player and enemy
var player = new PlayerPokemon();
var enemy = new EnemyPokemon();
game.addChild(player);
game.addChild(enemy);
// Initial positions
player.moveTo(2048 / 2, 2732 - 300);
enemy.moveTo(2048 / 2, 300);
// HP bars
var playerHpBg = LK.getAsset('hp_bar_bg', {
anchorX: 0,
anchorY: 0.5,
x: 100,
y: 2732 - 100
});
var playerHpFg = LK.getAsset('hp_bar_fg', {
anchorX: 0,
anchorY: 0.5,
x: 100,
y: 2732 - 100
});
game.addChild(playerHpBg);
game.addChild(playerHpFg);
var enemyHpBg = LK.getAsset('hp_bar_bg', {
anchorX: 0,
anchorY: 0.5,
x: 100,
y: 100
});
var enemyHpFg = LK.getAsset('hp_bar_fg_enemy', {
anchorX: 0,
anchorY: 0.5,
x: 100,
y: 100
});
game.addChild(enemyHpBg);
game.addChild(enemyHpFg);
// HP text
var playerHpTxt = new Text2('100/100', {
size: 60,
fill: "#222"
});
playerHpTxt.anchor.set(0, 0.5);
playerHpTxt.x = 520;
playerHpTxt.y = 2732 - 100;
game.addChild(playerHpTxt);
var enemyHpTxt = new Text2('100/100', {
size: 60,
fill: "#222"
});
enemyHpTxt.anchor.set(0, 0.5);
enemyHpTxt.x = 520;
enemyHpTxt.y = 100;
game.addChild(enemyHpTxt);
// Attack buttons (GUI)
var atkBtn = new Text2('Attack', {
size: 90,
fill: "#fff"
});
atkBtn.anchor.set(0.5, 0.5);
atkBtn.x = 2048 / 2 - 200;
atkBtn.y = 2732 - 220;
atkBtn.bg = LK.getAsset('hp_bar_bg', {
anchorX: 0.5,
anchorY: 0.5,
x: atkBtn.x,
y: atkBtn.y,
width: 260,
height: 120
});
game.addChild(atkBtn.bg);
game.addChild(atkBtn);
var spcBtn = new Text2('Special', {
size: 90,
fill: "#fff"
});
spcBtn.anchor.set(0.5, 0.5);
spcBtn.x = 2048 / 2 + 200;
spcBtn.y = 2732 - 220;
spcBtn.bg = LK.getAsset('hp_bar_bg', {
anchorX: 0.5,
anchorY: 0.5,
x: spcBtn.x,
y: spcBtn.y,
width: 260,
height: 120
});
game.addChild(spcBtn.bg);
game.addChild(spcBtn);
// Attack cooldown overlays
var atkBtnCd = LK.getAsset('hp_bar_fg', {
anchorX: 0.5,
anchorY: 0.5,
x: atkBtn.x,
y: atkBtn.y,
width: 260,
height: 120
});
atkBtnCd.alpha = 0.5;
game.addChild(atkBtnCd);
atkBtnCd.visible = false;
var spcBtnCd = LK.getAsset('hp_bar_fg_enemy', {
anchorX: 0.5,
anchorY: 0.5,
x: spcBtn.x,
y: spcBtn.y,
width: 260,
height: 120
});
spcBtnCd.alpha = 0.5;
game.addChild(spcBtnCd);
spcBtnCd.visible = false;
// Attacks array
var attacks = [];
var enemyAttacks = [];
// Dragging
var dragNode = null;
// Touch/move handlers
function handleMove(x, y, obj) {
// Drag player
if (dragNode === player) {
player.moveTo(x, y);
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// If on attack button
if (atkBtn.bg.containsPoint({
x: x,
y: y
})) {
// Fire basic attack if not on cooldown
if (player.basicCooldown <= 0) {
var atk = new Attack();
atk.setType('basic');
atk.owner = 'player';
atk.x = player.x;
atk.y = player.y - player.radius - 40;
attacks.push(atk);
game.addChild(atk);
player.basicCooldown = 30; // 0.5s
LK.getSound('atk_basic').play();
}
return;
}
if (spcBtn.bg.containsPoint({
x: x,
y: y
})) {
// Fire special attack if not on cooldown
if (player.specialCooldown <= 0) {
var atk = new Attack();
atk.setType('special');
atk.owner = 'player';
atk.x = player.x;
atk.y = player.y - player.radius - 40;
attacks.push(atk);
game.addChild(atk);
player.specialCooldown = 120; // 2s
LK.getSound('atk_special').play();
}
return;
}
// If on player, start drag
var local = player.toLocal({
x: x,
y: y
});
if (local.x * local.x + local.y * local.y <= player.radius * player.radius) {
dragNode = player;
handleMove(x, y, obj);
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Helper: collision between two circles
function circlesCollide(a, b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
var dist = Math.sqrt(dx * dx + dy * dy);
return dist < a.radius + b.radius - 10;
}
// AI logic
function enemyAI() {
// Move towards player x
var dx = player.x - enemy.x;
if (Math.abs(dx) > 10) {
var dir = dx > 0 ? 1 : -1;
enemy.moveTo(enemy.x + dir * enemy.speed, enemy.y);
}
// Randomly fire attack
if (enemy.basicCooldown <= 0 && Math.random() < 0.04) {
var atk = new Attack();
atk.setType('enemy');
atk.owner = 'enemy';
atk.x = enemy.x;
atk.y = enemy.y + enemy.radius + 40;
enemyAttacks.push(atk);
game.addChild(atk);
enemy.basicCooldown = 36 + Math.floor(Math.random() * 24); // 0.6-1s
LK.getSound('atk_enemy').play();
}
// Special attack less often
if (enemy.specialCooldown <= 0 && Math.random() < 0.01) {
var atk = new Attack();
atk.setType('enemy');
atk.owner = 'enemy';
atk.dmg = 22;
atk.speed = 20;
atk.radius = 40;
atk.x = enemy.x;
atk.y = enemy.y + enemy.radius + 40;
enemyAttacks.push(atk);
game.addChild(atk);
enemy.specialCooldown = 120 + Math.floor(Math.random() * 60);
LK.getSound('atk_enemy').play();
}
}
// Main update
game.update = function () {
// Cooldowns
if (player.basicCooldown > 0) player.basicCooldown--;
if (player.specialCooldown > 0) player.specialCooldown--;
if (player.invuln > 0) player.invuln--;
if (enemy.basicCooldown > 0) enemy.basicCooldown--;
if (enemy.specialCooldown > 0) enemy.specialCooldown--;
if (enemy.invuln > 0) enemy.invuln--;
// Update attack cooldown overlays
atkBtnCd.visible = player.basicCooldown > 0;
if (atkBtnCd.visible) {
atkBtnCd.width = 260 * (player.basicCooldown / 30);
}
spcBtnCd.visible = player.specialCooldown > 0;
if (spcBtnCd.visible) {
spcBtnCd.width = 260 * (player.specialCooldown / 120);
}
// Update attacks
for (var i = attacks.length - 1; i >= 0; i--) {
var atk = attacks[i];
atk.update();
// Remove if off screen
if (atk.y < -100) {
atk.destroy();
attacks.splice(i, 1);
continue;
}
// Hit enemy
if (circlesCollide(atk, enemy) && enemy.hp > 0) {
enemy.takeDamage(atk.dmg);
atk.destroy();
attacks.splice(i, 1);
continue;
}
}
for (var i = enemyAttacks.length - 1; i >= 0; i--) {
var atk = enemyAttacks[i];
atk.update();
// Remove if off screen
if (atk.y > 2732 + 100) {
atk.destroy();
enemyAttacks.splice(i, 1);
continue;
}
// Hit player
if (circlesCollide(atk, player) && player.hp > 0) {
player.takeDamage(atk.dmg);
atk.destroy();
enemyAttacks.splice(i, 1);
continue;
}
}
// Enemy AI
if (enemy.hp > 0) {
enemyAI();
}
// Update HP bars
playerHpFg.width = 400 * (player.hp / player.maxHP);
playerHpTxt.setText(player.hp + '/' + player.maxHP);
enemyHpFg.width = 400 * (enemy.hp / enemy.maxHP);
enemyHpTxt.setText(enemy.hp + '/' + enemy.maxHP);
// Win/lose
if (player.hp <= 0) {
LK.effects.flashScreen(0xe53935, 800);
LK.showGameOver();
return;
}
if (enemy.hp <= 0) {
LK.effects.flashScreen(0x4caf50, 800);
LK.setScore(1);
LK.showYouWin();
return;
}
};
// GUI: show player and enemy names
var playerName = new Text2('You', {
size: 60,
fill: 0x3B4CCA
});
playerName.anchor.set(0, 1);
playerName.x = 100;
playerName.y = 2732 - 160;
game.addChild(playerName);
var enemyName = new Text2('Enemy', {
size: 60,
fill: 0xE53935
});
enemyName.anchor.set(0, 0);
enemyName.x = 100;
enemyName.y = 160;
game.addChild(enemyName);
// Center arena (no scrolling, so nothing to do) ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,470 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Attack class (for both player and enemy)
+var Attack = Container.expand(function () {
+ var self = Container.call(this);
+ // type: 'basic', 'special', 'enemy'
+ self.type = 'basic';
+ self.owner = null; // player or enemy
+ self.dmg = 10;
+ self.speed = 30;
+ self.radius = 30;
+ self.dirY = -1; // -1 up, 1 down
+ // Attach asset
+ self.setType = function (type) {
+ self.type = type;
+ if (type === 'basic') {
+ self.removeChildren();
+ self.attachAsset('attack_basic', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.dmg = 10;
+ self.speed = 36;
+ self.radius = 30;
+ self.dirY = -1;
+ } else if (type === 'special') {
+ self.removeChildren();
+ self.attachAsset('attack_special', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.dmg = 22;
+ self.speed = 24;
+ self.radius = 40;
+ self.dirY = -1;
+ } else if (type === 'enemy') {
+ self.removeChildren();
+ self.attachAsset('attack_enemy', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.dmg = 12;
+ self.speed = 28;
+ self.radius = 30;
+ self.dirY = 1;
+ }
+ };
+ // Update
+ self.update = function () {
+ self.y += self.speed * self.dirY;
+ };
+ return self;
+});
+// Enemy Pokemon class (AI)
+var EnemyPokemon = Container.expand(function () {
+ var self = Container.call(this);
+ // Attach enemy asset
+ var sprite = self.attachAsset('poke_enemy', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Stats
+ self.maxHP = 100;
+ self.hp = 100;
+ self.speed = 12; // px per move
+ self.radius = sprite.width / 2;
+ // For attack cooldowns
+ self.basicCooldown = 0;
+ self.specialCooldown = 0;
+ // For invulnerability after hit
+ self.invuln = 0;
+ // Move to (x, y) with bounds
+ self.moveTo = function (x, y) {
+ // Clamp to arena bounds (leave 20px margin)
+ var minX = 20 + self.radius;
+ var maxX = 2048 - 20 - self.radius;
+ var minY = 20 + self.radius;
+ var maxY = 1366 - 20 - self.radius; // top half
+ self.x = Math.max(minX, Math.min(maxX, x));
+ self.y = Math.max(minY, Math.min(maxY, y));
+ };
+ // Take damage
+ self.takeDamage = function (dmg) {
+ if (self.invuln > 0) return;
+ self.hp -= dmg;
+ if (self.hp < 0) self.hp = 0;
+ self.invuln = 30; // 0.5s invuln
+ LK.effects.flashObject(self, 0xffffff, 200);
+ };
+ return self;
+});
+// Player Pokemon class
+var PlayerPokemon = Container.expand(function () {
+ var self = Container.call(this);
+ // Attach player asset
+ var sprite = self.attachAsset('poke_player', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Stats
+ self.maxHP = 100;
+ self.hp = 100;
+ self.speed = 18; // px per move
+ self.radius = sprite.width / 2;
+ // For drag
+ self.isDragging = false;
+ // For attack cooldowns
+ self.basicCooldown = 0;
+ self.specialCooldown = 0;
+ // For invulnerability after hit
+ self.invuln = 0;
+ // Move to (x, y) with bounds
+ self.moveTo = function (x, y) {
+ // Clamp to arena bounds (leave 20px margin)
+ var minX = 20 + self.radius;
+ var maxX = 2048 - 20 - self.radius;
+ var minY = 1366 + 20 + self.radius; // bottom half
+ var maxY = 2732 - 20 - self.radius;
+ self.x = Math.max(minX, Math.min(maxX, x));
+ self.y = Math.max(minY, Math.min(maxY, y));
+ };
+ // Take damage
+ self.takeDamage = function (dmg) {
+ if (self.invuln > 0) return;
+ self.hp -= dmg;
+ if (self.hp < 0) self.hp = 0;
+ self.invuln = 30; // 0.5s invuln
+ LK.effects.flashObject(self, 0xffffff, 200);
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0xf5f5f5
+});
+
+/****
+* Game Code
+****/
+// Attack SFX
+// Pokemon shapes (simple for MVP)
+// Arena background
+var arenaBg = LK.getAsset('arena_bg', {
+ anchorX: 0,
+ anchorY: 0,
+ x: 0,
+ y: 0
+});
+game.addChild(arenaBg);
+// Player and enemy
+var player = new PlayerPokemon();
+var enemy = new EnemyPokemon();
+game.addChild(player);
+game.addChild(enemy);
+// Initial positions
+player.moveTo(2048 / 2, 2732 - 300);
+enemy.moveTo(2048 / 2, 300);
+// HP bars
+var playerHpBg = LK.getAsset('hp_bar_bg', {
+ anchorX: 0,
+ anchorY: 0.5,
+ x: 100,
+ y: 2732 - 100
+});
+var playerHpFg = LK.getAsset('hp_bar_fg', {
+ anchorX: 0,
+ anchorY: 0.5,
+ x: 100,
+ y: 2732 - 100
+});
+game.addChild(playerHpBg);
+game.addChild(playerHpFg);
+var enemyHpBg = LK.getAsset('hp_bar_bg', {
+ anchorX: 0,
+ anchorY: 0.5,
+ x: 100,
+ y: 100
+});
+var enemyHpFg = LK.getAsset('hp_bar_fg_enemy', {
+ anchorX: 0,
+ anchorY: 0.5,
+ x: 100,
+ y: 100
+});
+game.addChild(enemyHpBg);
+game.addChild(enemyHpFg);
+// HP text
+var playerHpTxt = new Text2('100/100', {
+ size: 60,
+ fill: "#222"
+});
+playerHpTxt.anchor.set(0, 0.5);
+playerHpTxt.x = 520;
+playerHpTxt.y = 2732 - 100;
+game.addChild(playerHpTxt);
+var enemyHpTxt = new Text2('100/100', {
+ size: 60,
+ fill: "#222"
+});
+enemyHpTxt.anchor.set(0, 0.5);
+enemyHpTxt.x = 520;
+enemyHpTxt.y = 100;
+game.addChild(enemyHpTxt);
+// Attack buttons (GUI)
+var atkBtn = new Text2('Attack', {
+ size: 90,
+ fill: "#fff"
+});
+atkBtn.anchor.set(0.5, 0.5);
+atkBtn.x = 2048 / 2 - 200;
+atkBtn.y = 2732 - 220;
+atkBtn.bg = LK.getAsset('hp_bar_bg', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: atkBtn.x,
+ y: atkBtn.y,
+ width: 260,
+ height: 120
+});
+game.addChild(atkBtn.bg);
+game.addChild(atkBtn);
+var spcBtn = new Text2('Special', {
+ size: 90,
+ fill: "#fff"
+});
+spcBtn.anchor.set(0.5, 0.5);
+spcBtn.x = 2048 / 2 + 200;
+spcBtn.y = 2732 - 220;
+spcBtn.bg = LK.getAsset('hp_bar_bg', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: spcBtn.x,
+ y: spcBtn.y,
+ width: 260,
+ height: 120
+});
+game.addChild(spcBtn.bg);
+game.addChild(spcBtn);
+// Attack cooldown overlays
+var atkBtnCd = LK.getAsset('hp_bar_fg', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: atkBtn.x,
+ y: atkBtn.y,
+ width: 260,
+ height: 120
+});
+atkBtnCd.alpha = 0.5;
+game.addChild(atkBtnCd);
+atkBtnCd.visible = false;
+var spcBtnCd = LK.getAsset('hp_bar_fg_enemy', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: spcBtn.x,
+ y: spcBtn.y,
+ width: 260,
+ height: 120
+});
+spcBtnCd.alpha = 0.5;
+game.addChild(spcBtnCd);
+spcBtnCd.visible = false;
+// Attacks array
+var attacks = [];
+var enemyAttacks = [];
+// Dragging
+var dragNode = null;
+// Touch/move handlers
+function handleMove(x, y, obj) {
+ // Drag player
+ if (dragNode === player) {
+ player.moveTo(x, y);
+ }
+}
+game.move = handleMove;
+game.down = function (x, y, obj) {
+ // If on attack button
+ if (atkBtn.bg.containsPoint({
+ x: x,
+ y: y
+ })) {
+ // Fire basic attack if not on cooldown
+ if (player.basicCooldown <= 0) {
+ var atk = new Attack();
+ atk.setType('basic');
+ atk.owner = 'player';
+ atk.x = player.x;
+ atk.y = player.y - player.radius - 40;
+ attacks.push(atk);
+ game.addChild(atk);
+ player.basicCooldown = 30; // 0.5s
+ LK.getSound('atk_basic').play();
+ }
+ return;
+ }
+ if (spcBtn.bg.containsPoint({
+ x: x,
+ y: y
+ })) {
+ // Fire special attack if not on cooldown
+ if (player.specialCooldown <= 0) {
+ var atk = new Attack();
+ atk.setType('special');
+ atk.owner = 'player';
+ atk.x = player.x;
+ atk.y = player.y - player.radius - 40;
+ attacks.push(atk);
+ game.addChild(atk);
+ player.specialCooldown = 120; // 2s
+ LK.getSound('atk_special').play();
+ }
+ return;
+ }
+ // If on player, start drag
+ var local = player.toLocal({
+ x: x,
+ y: y
+ });
+ if (local.x * local.x + local.y * local.y <= player.radius * player.radius) {
+ dragNode = player;
+ handleMove(x, y, obj);
+ }
+};
+game.up = function (x, y, obj) {
+ dragNode = null;
+};
+// Helper: collision between two circles
+function circlesCollide(a, b) {
+ var dx = a.x - b.x;
+ var dy = a.y - b.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ return dist < a.radius + b.radius - 10;
+}
+// AI logic
+function enemyAI() {
+ // Move towards player x
+ var dx = player.x - enemy.x;
+ if (Math.abs(dx) > 10) {
+ var dir = dx > 0 ? 1 : -1;
+ enemy.moveTo(enemy.x + dir * enemy.speed, enemy.y);
+ }
+ // Randomly fire attack
+ if (enemy.basicCooldown <= 0 && Math.random() < 0.04) {
+ var atk = new Attack();
+ atk.setType('enemy');
+ atk.owner = 'enemy';
+ atk.x = enemy.x;
+ atk.y = enemy.y + enemy.radius + 40;
+ enemyAttacks.push(atk);
+ game.addChild(atk);
+ enemy.basicCooldown = 36 + Math.floor(Math.random() * 24); // 0.6-1s
+ LK.getSound('atk_enemy').play();
+ }
+ // Special attack less often
+ if (enemy.specialCooldown <= 0 && Math.random() < 0.01) {
+ var atk = new Attack();
+ atk.setType('enemy');
+ atk.owner = 'enemy';
+ atk.dmg = 22;
+ atk.speed = 20;
+ atk.radius = 40;
+ atk.x = enemy.x;
+ atk.y = enemy.y + enemy.radius + 40;
+ enemyAttacks.push(atk);
+ game.addChild(atk);
+ enemy.specialCooldown = 120 + Math.floor(Math.random() * 60);
+ LK.getSound('atk_enemy').play();
+ }
+}
+// Main update
+game.update = function () {
+ // Cooldowns
+ if (player.basicCooldown > 0) player.basicCooldown--;
+ if (player.specialCooldown > 0) player.specialCooldown--;
+ if (player.invuln > 0) player.invuln--;
+ if (enemy.basicCooldown > 0) enemy.basicCooldown--;
+ if (enemy.specialCooldown > 0) enemy.specialCooldown--;
+ if (enemy.invuln > 0) enemy.invuln--;
+ // Update attack cooldown overlays
+ atkBtnCd.visible = player.basicCooldown > 0;
+ if (atkBtnCd.visible) {
+ atkBtnCd.width = 260 * (player.basicCooldown / 30);
+ }
+ spcBtnCd.visible = player.specialCooldown > 0;
+ if (spcBtnCd.visible) {
+ spcBtnCd.width = 260 * (player.specialCooldown / 120);
+ }
+ // Update attacks
+ for (var i = attacks.length - 1; i >= 0; i--) {
+ var atk = attacks[i];
+ atk.update();
+ // Remove if off screen
+ if (atk.y < -100) {
+ atk.destroy();
+ attacks.splice(i, 1);
+ continue;
+ }
+ // Hit enemy
+ if (circlesCollide(atk, enemy) && enemy.hp > 0) {
+ enemy.takeDamage(atk.dmg);
+ atk.destroy();
+ attacks.splice(i, 1);
+ continue;
+ }
+ }
+ for (var i = enemyAttacks.length - 1; i >= 0; i--) {
+ var atk = enemyAttacks[i];
+ atk.update();
+ // Remove if off screen
+ if (atk.y > 2732 + 100) {
+ atk.destroy();
+ enemyAttacks.splice(i, 1);
+ continue;
+ }
+ // Hit player
+ if (circlesCollide(atk, player) && player.hp > 0) {
+ player.takeDamage(atk.dmg);
+ atk.destroy();
+ enemyAttacks.splice(i, 1);
+ continue;
+ }
+ }
+ // Enemy AI
+ if (enemy.hp > 0) {
+ enemyAI();
+ }
+ // Update HP bars
+ playerHpFg.width = 400 * (player.hp / player.maxHP);
+ playerHpTxt.setText(player.hp + '/' + player.maxHP);
+ enemyHpFg.width = 400 * (enemy.hp / enemy.maxHP);
+ enemyHpTxt.setText(enemy.hp + '/' + enemy.maxHP);
+ // Win/lose
+ if (player.hp <= 0) {
+ LK.effects.flashScreen(0xe53935, 800);
+ LK.showGameOver();
+ return;
+ }
+ if (enemy.hp <= 0) {
+ LK.effects.flashScreen(0x4caf50, 800);
+ LK.setScore(1);
+ LK.showYouWin();
+ return;
+ }
+};
+// GUI: show player and enemy names
+var playerName = new Text2('You', {
+ size: 60,
+ fill: 0x3B4CCA
+});
+playerName.anchor.set(0, 1);
+playerName.x = 100;
+playerName.y = 2732 - 160;
+game.addChild(playerName);
+var enemyName = new Text2('Enemy', {
+ size: 60,
+ fill: 0xE53935
+});
+enemyName.anchor.set(0, 0);
+enemyName.x = 100;
+enemyName.y = 160;
+game.addChild(enemyName);
+// Center arena (no scrolling, so nothing to do)
\ No newline at end of file
Fullscreen modern App Store landscape banner, 16:9, high definition, for a game titled "Pokémon PvP: Battle Arena" and with the description "A real-time 2D Pokémon battle game where players control a Pokémon, use attacks, dodge, and outlast their opponent in quick PvP matches.". No text on banner!
Darkrai. In-Game asset. 2d. High contrast. No shadows
Lickilicky. In-Game asset. 2d. High contrast. No shadows
Dark ball. In-Game asset. 2d. High contrast. No shadows