/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = 0;
self.speedY = 0;
self.damage = 10;
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
};
return self;
});
var Button = Container.expand(function () {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
self.text = '';
self.action = null;
self.down = function (x, y, obj) {
if (self.action) {
self.action();
}
LK.effects.flashObject(self, 0xffffff, 200);
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.maxHP = 80;
self.currentHP = 80;
self.attackTimer = 0;
self.attackCooldown = 120;
self.canBeSpared = false;
self.actProgress = 0;
self.takeDamage = function (damage) {
self.currentHP -= damage;
if (self.currentHP <= 0) {
self.currentHP = 0;
}
LK.effects.flashObject(self, 0xff0000, 300);
};
self.update = function () {
self.attackTimer++;
if (self.attackTimer >= self.attackCooldown && currentPhase === 'enemyTurn') {
self.performAttack();
self.attackTimer = 0;
}
};
self.performAttack = function () {
for (var i = 0; i < 3; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x + (Math.random() - 0.5) * 100;
bullet.y = self.y;
bullet.speedX = (Math.random() - 0.5) * 4;
bullet.speedY = 3 + Math.random() * 2;
enemyBullets.push(bullet);
game.addChild(bullet);
}
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = 0;
self.speedY = 0;
self.damage = 15;
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
};
return self;
});
var Heart = Container.expand(function () {
var self = Container.call(this);
var heartGraphics = self.attachAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.maxHP = 100;
self.currentHP = 100;
self.soulPower = 0;
self.takeDamage = function (damage) {
self.currentHP -= damage;
if (self.currentHP <= 0) {
self.currentHP = 0;
}
LK.effects.flashObject(self, 0xff0000, 500);
LK.getSound('hit').play();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game state variables
var currentPhase = 'playerTurn'; // 'playerTurn', 'enemyTurn', 'fightPhase', 'gameOver'
var phaseTimer = 0;
var maxPhaseTime = 300; // 5 seconds at 60fps
// Game objects
var heart = null;
var battleBox = null;
var enemies = [];
var bullets = [];
var enemyBullets = [];
var buttons = [];
// UI elements
var hpText = null;
var phaseText = null;
var turnText = null;
// Input handling
var keys = {
left: false,
right: false,
up: false,
down: false
};
// Initialize battle box
battleBox = game.addChild(LK.getAsset('battleBox', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 100
}));
// Initialize heart
heart = game.addChild(new Heart());
heart.x = battleBox.x;
heart.y = battleBox.y;
// Initialize enemy
var enemy = game.addChild(new Enemy());
enemy.x = 2048 / 2;
enemy.y = 2732 / 2 - 200;
enemies.push(enemy);
// Initialize UI
hpText = new Text2('HP: 100/100', {
size: 60,
fill: 0xFFFFFF
});
hpText.anchor.set(0, 0);
LK.gui.topLeft.addChild(hpText);
hpText.x = 120;
hpText.y = 20;
phaseText = new Text2('Your Turn', {
size: 80,
fill: 0xFFFF00
});
phaseText.anchor.set(0.5, 0);
LK.gui.top.addChild(phaseText);
phaseText.y = 100;
turnText = new Text2('Choose your action', {
size: 50,
fill: 0xFFFFFF
});
turnText.anchor.set(0.5, 0);
LK.gui.center.addChild(turnText);
turnText.y = -100;
// Initialize buttons
var fightButton = game.addChild(new Button());
fightButton.x = 2048 / 2 - 150;
fightButton.y = 2732 - 300;
fightButton.text = 'FIGHT';
fightButton.action = function () {
if (currentPhase === 'playerTurn') {
startFightPhase();
}
};
buttons.push(fightButton);
var actButton = game.addChild(new Button());
actButton.x = 2048 / 2 + 150;
actButton.y = 2732 - 300;
actButton.text = 'ACT';
actButton.action = function () {
if (currentPhase === 'playerTurn') {
performAct();
}
};
buttons.push(actButton);
// Add button labels
var fightLabel = new Text2('FIGHT', {
size: 40,
fill: 0xFFFFFF
});
fightLabel.anchor.set(0.5, 0.5);
fightButton.addChild(fightLabel);
var actLabel = new Text2('ACT', {
size: 40,
fill: 0xFFFFFF
});
actLabel.anchor.set(0.5, 0.5);
actButton.addChild(actLabel);
function startFightPhase() {
currentPhase = 'fightPhase';
phaseTimer = 0;
phaseText.setText('Time your attack!');
turnText.setText('Press when the line is in the center!');
// Create timing indicator
var indicator = game.addChild(LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 - 200,
y: 2732 / 2 - 100
}));
tween(indicator, {
x: 2048 / 2 + 200
}, {
duration: 2000,
onFinish: function onFinish() {
indicator.destroy();
endFightPhase(false);
}
});
// Listen for fight timing
var fightHandler = function fightHandler() {
var distance = Math.abs(indicator.x - 2048 / 2);
var accuracy = Math.max(0, 1 - distance / 100);
var damage = Math.floor(20 + accuracy * 30);
enemy.takeDamage(damage);
heart.soulPower += Math.floor(accuracy * 10);
indicator.destroy();
tween.stop(indicator);
endFightPhase(true);
};
game.down = fightHandler;
}
function endFightPhase(attacked) {
game.down = null;
if (attacked) {
turnText.setText('Attack dealt damage!');
} else {
turnText.setText('Missed the timing!');
}
LK.setTimeout(function () {
if (checkWinCondition()) return;
switchToEnemyTurn();
}, 1000);
}
function performAct() {
enemy.actProgress += 25;
heart.soulPower += 5;
if (enemy.actProgress >= 100) {
enemy.canBeSpared = true;
turnText.setText('Enemy can now be spared!');
LK.setTimeout(function () {
LK.showYouWin();
}, 1500);
} else {
turnText.setText('You tried to reason with the enemy');
LK.setTimeout(function () {
if (checkWinCondition()) return;
switchToEnemyTurn();
}, 1000);
}
}
function switchToEnemyTurn() {
currentPhase = 'enemyTurn';
phaseTimer = 0;
phaseText.setText('Enemy Turn');
turnText.setText('Dodge the bullets!');
// Hide buttons during enemy turn
for (var i = 0; i < buttons.length; i++) {
buttons[i].alpha = 0.3;
}
}
function switchToPlayerTurn() {
currentPhase = 'playerTurn';
phaseTimer = 0;
phaseText.setText('Your Turn');
turnText.setText('Choose your action');
// Show buttons during player turn
for (var i = 0; i < buttons.length; i++) {
buttons[i].alpha = 1.0;
}
}
function checkWinCondition() {
var allEnemiesDefeated = true;
for (var i = 0; i < enemies.length; i++) {
if (enemies[i].currentHP > 0) {
allEnemiesDefeated = false;
break;
}
}
if (allEnemiesDefeated) {
LK.getSound('victory').play();
LK.showYouWin();
return true;
}
if (heart.currentHP <= 0) {
LK.showGameOver();
return true;
}
return false;
}
function updateHeartMovement() {
var moveX = 0;
var moveY = 0;
if (keys.left) moveX -= heart.speed;
if (keys.right) moveX += heart.speed;
if (keys.up) moveY -= heart.speed;
if (keys.down) moveY += heart.speed;
// Apply movement
heart.x += moveX;
heart.y += moveY;
// Keep heart within battle box bounds
var boxLeft = battleBox.x - battleBox.width / 2 + 20;
var boxRight = battleBox.x + battleBox.width / 2 - 20;
var boxTop = battleBox.y - battleBox.height / 2 + 20;
var boxBottom = battleBox.y + battleBox.height / 2 - 20;
heart.x = Math.max(boxLeft, Math.min(boxRight, heart.x));
heart.y = Math.max(boxTop, Math.min(boxBottom, heart.y));
}
// Touch controls for heart movement
var touchStartX = 0;
var touchStartY = 0;
var isTouching = false;
game.down = function (x, y, obj) {
// Check if touching heart area for movement
var heartDistance = Math.sqrt(Math.pow(x - heart.x, 2) + Math.pow(y - heart.y, 2));
if (heartDistance < 100) {
isTouching = true;
touchStartX = x;
touchStartY = y;
return;
}
// Check button presses
for (var i = 0; i < buttons.length; i++) {
var button = buttons[i];
if (Math.abs(x - button.x) < 100 && Math.abs(y - button.y) < 30) {
if (button.action) {
button.action();
}
break;
}
}
};
game.move = function (x, y, obj) {
if (isTouching && currentPhase === 'enemyTurn') {
var deltaX = x - touchStartX;
var deltaY = y - touchStartY;
heart.x += deltaX * 0.1;
heart.y += deltaY * 0.1;
// Keep heart within battle box bounds
var boxLeft = battleBox.x - battleBox.width / 2 + 20;
var boxRight = battleBox.x + battleBox.width / 2 - 20;
var boxTop = battleBox.y - battleBox.height / 2 + 20;
var boxBottom = battleBox.y + battleBox.height / 2 - 20;
heart.x = Math.max(boxLeft, Math.min(boxRight, heart.x));
heart.y = Math.max(boxTop, Math.min(boxBottom, heart.y));
touchStartX = x;
touchStartY = y;
}
};
game.up = function (x, y, obj) {
isTouching = false;
};
game.update = function () {
phaseTimer++;
// Update HP display
hpText.setText('HP: ' + heart.currentHP + '/' + heart.maxHP);
// Phase management
if (currentPhase === 'enemyTurn') {
if (phaseTimer >= maxPhaseTime) {
// Clear enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
enemyBullets[i].destroy();
enemyBullets.splice(i, 1);
}
switchToPlayerTurn();
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
// Check if bullet is out of battle box
if (bullet.y > battleBox.y + battleBox.height / 2 + 50 || bullet.x < battleBox.x - battleBox.width / 2 - 50 || bullet.x > battleBox.x + battleBox.width / 2 + 50 || bullet.y < battleBox.y - battleBox.height / 2 - 50) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with heart
if (bullet.intersects(heart)) {
heart.takeDamage(bullet.damage);
bullet.destroy();
enemyBullets.splice(i, 1);
if (checkWinCondition()) return;
continue;
}
}
// Check win/lose conditions
checkWinCondition();
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = 0;
self.speedY = 0;
self.damage = 10;
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
};
return self;
});
var Button = Container.expand(function () {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
self.text = '';
self.action = null;
self.down = function (x, y, obj) {
if (self.action) {
self.action();
}
LK.effects.flashObject(self, 0xffffff, 200);
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.maxHP = 80;
self.currentHP = 80;
self.attackTimer = 0;
self.attackCooldown = 120;
self.canBeSpared = false;
self.actProgress = 0;
self.takeDamage = function (damage) {
self.currentHP -= damage;
if (self.currentHP <= 0) {
self.currentHP = 0;
}
LK.effects.flashObject(self, 0xff0000, 300);
};
self.update = function () {
self.attackTimer++;
if (self.attackTimer >= self.attackCooldown && currentPhase === 'enemyTurn') {
self.performAttack();
self.attackTimer = 0;
}
};
self.performAttack = function () {
for (var i = 0; i < 3; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x + (Math.random() - 0.5) * 100;
bullet.y = self.y;
bullet.speedX = (Math.random() - 0.5) * 4;
bullet.speedY = 3 + Math.random() * 2;
enemyBullets.push(bullet);
game.addChild(bullet);
}
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = 0;
self.speedY = 0;
self.damage = 15;
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
};
return self;
});
var Heart = Container.expand(function () {
var self = Container.call(this);
var heartGraphics = self.attachAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.maxHP = 100;
self.currentHP = 100;
self.soulPower = 0;
self.takeDamage = function (damage) {
self.currentHP -= damage;
if (self.currentHP <= 0) {
self.currentHP = 0;
}
LK.effects.flashObject(self, 0xff0000, 500);
LK.getSound('hit').play();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game state variables
var currentPhase = 'playerTurn'; // 'playerTurn', 'enemyTurn', 'fightPhase', 'gameOver'
var phaseTimer = 0;
var maxPhaseTime = 300; // 5 seconds at 60fps
// Game objects
var heart = null;
var battleBox = null;
var enemies = [];
var bullets = [];
var enemyBullets = [];
var buttons = [];
// UI elements
var hpText = null;
var phaseText = null;
var turnText = null;
// Input handling
var keys = {
left: false,
right: false,
up: false,
down: false
};
// Initialize battle box
battleBox = game.addChild(LK.getAsset('battleBox', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 100
}));
// Initialize heart
heart = game.addChild(new Heart());
heart.x = battleBox.x;
heart.y = battleBox.y;
// Initialize enemy
var enemy = game.addChild(new Enemy());
enemy.x = 2048 / 2;
enemy.y = 2732 / 2 - 200;
enemies.push(enemy);
// Initialize UI
hpText = new Text2('HP: 100/100', {
size: 60,
fill: 0xFFFFFF
});
hpText.anchor.set(0, 0);
LK.gui.topLeft.addChild(hpText);
hpText.x = 120;
hpText.y = 20;
phaseText = new Text2('Your Turn', {
size: 80,
fill: 0xFFFF00
});
phaseText.anchor.set(0.5, 0);
LK.gui.top.addChild(phaseText);
phaseText.y = 100;
turnText = new Text2('Choose your action', {
size: 50,
fill: 0xFFFFFF
});
turnText.anchor.set(0.5, 0);
LK.gui.center.addChild(turnText);
turnText.y = -100;
// Initialize buttons
var fightButton = game.addChild(new Button());
fightButton.x = 2048 / 2 - 150;
fightButton.y = 2732 - 300;
fightButton.text = 'FIGHT';
fightButton.action = function () {
if (currentPhase === 'playerTurn') {
startFightPhase();
}
};
buttons.push(fightButton);
var actButton = game.addChild(new Button());
actButton.x = 2048 / 2 + 150;
actButton.y = 2732 - 300;
actButton.text = 'ACT';
actButton.action = function () {
if (currentPhase === 'playerTurn') {
performAct();
}
};
buttons.push(actButton);
// Add button labels
var fightLabel = new Text2('FIGHT', {
size: 40,
fill: 0xFFFFFF
});
fightLabel.anchor.set(0.5, 0.5);
fightButton.addChild(fightLabel);
var actLabel = new Text2('ACT', {
size: 40,
fill: 0xFFFFFF
});
actLabel.anchor.set(0.5, 0.5);
actButton.addChild(actLabel);
function startFightPhase() {
currentPhase = 'fightPhase';
phaseTimer = 0;
phaseText.setText('Time your attack!');
turnText.setText('Press when the line is in the center!');
// Create timing indicator
var indicator = game.addChild(LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 - 200,
y: 2732 / 2 - 100
}));
tween(indicator, {
x: 2048 / 2 + 200
}, {
duration: 2000,
onFinish: function onFinish() {
indicator.destroy();
endFightPhase(false);
}
});
// Listen for fight timing
var fightHandler = function fightHandler() {
var distance = Math.abs(indicator.x - 2048 / 2);
var accuracy = Math.max(0, 1 - distance / 100);
var damage = Math.floor(20 + accuracy * 30);
enemy.takeDamage(damage);
heart.soulPower += Math.floor(accuracy * 10);
indicator.destroy();
tween.stop(indicator);
endFightPhase(true);
};
game.down = fightHandler;
}
function endFightPhase(attacked) {
game.down = null;
if (attacked) {
turnText.setText('Attack dealt damage!');
} else {
turnText.setText('Missed the timing!');
}
LK.setTimeout(function () {
if (checkWinCondition()) return;
switchToEnemyTurn();
}, 1000);
}
function performAct() {
enemy.actProgress += 25;
heart.soulPower += 5;
if (enemy.actProgress >= 100) {
enemy.canBeSpared = true;
turnText.setText('Enemy can now be spared!');
LK.setTimeout(function () {
LK.showYouWin();
}, 1500);
} else {
turnText.setText('You tried to reason with the enemy');
LK.setTimeout(function () {
if (checkWinCondition()) return;
switchToEnemyTurn();
}, 1000);
}
}
function switchToEnemyTurn() {
currentPhase = 'enemyTurn';
phaseTimer = 0;
phaseText.setText('Enemy Turn');
turnText.setText('Dodge the bullets!');
// Hide buttons during enemy turn
for (var i = 0; i < buttons.length; i++) {
buttons[i].alpha = 0.3;
}
}
function switchToPlayerTurn() {
currentPhase = 'playerTurn';
phaseTimer = 0;
phaseText.setText('Your Turn');
turnText.setText('Choose your action');
// Show buttons during player turn
for (var i = 0; i < buttons.length; i++) {
buttons[i].alpha = 1.0;
}
}
function checkWinCondition() {
var allEnemiesDefeated = true;
for (var i = 0; i < enemies.length; i++) {
if (enemies[i].currentHP > 0) {
allEnemiesDefeated = false;
break;
}
}
if (allEnemiesDefeated) {
LK.getSound('victory').play();
LK.showYouWin();
return true;
}
if (heart.currentHP <= 0) {
LK.showGameOver();
return true;
}
return false;
}
function updateHeartMovement() {
var moveX = 0;
var moveY = 0;
if (keys.left) moveX -= heart.speed;
if (keys.right) moveX += heart.speed;
if (keys.up) moveY -= heart.speed;
if (keys.down) moveY += heart.speed;
// Apply movement
heart.x += moveX;
heart.y += moveY;
// Keep heart within battle box bounds
var boxLeft = battleBox.x - battleBox.width / 2 + 20;
var boxRight = battleBox.x + battleBox.width / 2 - 20;
var boxTop = battleBox.y - battleBox.height / 2 + 20;
var boxBottom = battleBox.y + battleBox.height / 2 - 20;
heart.x = Math.max(boxLeft, Math.min(boxRight, heart.x));
heart.y = Math.max(boxTop, Math.min(boxBottom, heart.y));
}
// Touch controls for heart movement
var touchStartX = 0;
var touchStartY = 0;
var isTouching = false;
game.down = function (x, y, obj) {
// Check if touching heart area for movement
var heartDistance = Math.sqrt(Math.pow(x - heart.x, 2) + Math.pow(y - heart.y, 2));
if (heartDistance < 100) {
isTouching = true;
touchStartX = x;
touchStartY = y;
return;
}
// Check button presses
for (var i = 0; i < buttons.length; i++) {
var button = buttons[i];
if (Math.abs(x - button.x) < 100 && Math.abs(y - button.y) < 30) {
if (button.action) {
button.action();
}
break;
}
}
};
game.move = function (x, y, obj) {
if (isTouching && currentPhase === 'enemyTurn') {
var deltaX = x - touchStartX;
var deltaY = y - touchStartY;
heart.x += deltaX * 0.1;
heart.y += deltaY * 0.1;
// Keep heart within battle box bounds
var boxLeft = battleBox.x - battleBox.width / 2 + 20;
var boxRight = battleBox.x + battleBox.width / 2 - 20;
var boxTop = battleBox.y - battleBox.height / 2 + 20;
var boxBottom = battleBox.y + battleBox.height / 2 - 20;
heart.x = Math.max(boxLeft, Math.min(boxRight, heart.x));
heart.y = Math.max(boxTop, Math.min(boxBottom, heart.y));
touchStartX = x;
touchStartY = y;
}
};
game.up = function (x, y, obj) {
isTouching = false;
};
game.update = function () {
phaseTimer++;
// Update HP display
hpText.setText('HP: ' + heart.currentHP + '/' + heart.maxHP);
// Phase management
if (currentPhase === 'enemyTurn') {
if (phaseTimer >= maxPhaseTime) {
// Clear enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
enemyBullets[i].destroy();
enemyBullets.splice(i, 1);
}
switchToPlayerTurn();
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
// Check if bullet is out of battle box
if (bullet.y > battleBox.y + battleBox.height / 2 + 50 || bullet.x < battleBox.x - battleBox.width / 2 - 50 || bullet.x > battleBox.x + battleBox.width / 2 + 50 || bullet.y < battleBox.y - battleBox.height / 2 - 50) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with heart
if (bullet.intersects(heart)) {
heart.takeDamage(bullet.damage);
bullet.destroy();
enemyBullets.splice(i, 1);
if (checkWinCondition()) return;
continue;
}
}
// Check win/lose conditions
checkWinCondition();
};
Battle Box for a Deltarune game. In-Game asset. 2d. High contrast. No shadows
Make me a Deltarune enemy. In-Game asset. 2d. High contrast. No shadows
Make me a Bullet for Deltarune game. In-Game asset. 2d. High contrast. No shadows
Make me a heart for Deltarune. In-Game asset. 2d. High contrast. No shadows