User prompt
when the faint courage song plays, stop all sound effects and other songs,and make the battlebox invisible until the player chooses an option
User prompt
when the player dies,play the song Faint Courage.when the player chooses any option.stop playing the song faint_courage
User prompt
Please fix the bug: 'Timeout.tick error: t.setStageReference is not a function' in or related to this line: 'game.addChild(deathDialogueBox);' Line Number: 1250
User prompt
when the player dies.make everything black,stop any sound or song and make anything except the the hearth that got ripped in half and the dialogue black and invisible,and make the dialogbox asset invisible. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
when the player dies.make the whole screen black except the hearth that got ripped in half and the dialogue ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
when the player starts the game,play the sound: battlestart,and then when the audio ''battlestart''ends,play the song THE WORLD REVOLVING
User prompt
dont overuse the random enemy attack sounds (enemyrandom1,enemyrandom2,enemyrandom3)
User prompt
randomly whenever the enemy attacks us,play one of the audio assets (enemyrandom1,enemyrandom2,enemyrandom3)
User prompt
make an audio asset for the enemys attack sound.and name it enemyattack
User prompt
make an audio asset for when the enemy is attacking us
User prompt
randomly select one of the audio assets for the enemy dialogue
User prompt
make couple of audio assets for when a random enemy dialogue plays,randomly selected one of those audio assets will play
User prompt
put the enemytalking sprite onto the enemy sprite
User prompt
when the enemys dialogue appears.change the enemys sprite to enemytalking,and when the dialogue disappears,change it back to the normal sprite(enemy)
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Bullet = Container.expand(function (speed, direction) { var self = Container.call(this); var bulletSprite = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = speed || 3; self.direction = direction || 0; // radians self.lastX = self.x; self.lastY = self.y; self.update = function () { self.lastX = self.x; self.lastY = self.y; self.x += Math.cos(self.direction) * self.speed; self.y += Math.sin(self.direction) * self.speed; // Remove bullet if off screen if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) { self.destroy(); } }; return self; }); var Character = Container.expand(function (name, assetId) { var self = Container.call(this); // Character graphics var characterSprite = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); // Character stats self.name = name; self.hp = 100; self.maxHp = 100; self.atk = 10; self.def = 5; self.mag = 8; self.speed = 5; self.tp = 0; self.maxTp = 100; // Battle state self.isDefending = false; self.lastX = self.x; self.lastY = self.y; self.takeDamage = function (amount) { if (self.isDefending) { amount = Math.floor(amount * 0.5); } self.hp = Math.max(0, self.hp - amount); // Flash red when taking damage tween(characterSprite, { tint: 0xFF0000 }, { duration: 200, onFinish: function onFinish() { tween(characterSprite, { tint: 0xFFFFFF }, { duration: 200 }); } }); }; self.heal = function (amount) { self.hp = Math.min(self.maxHp, self.hp + amount); // Flash green when healing tween(characterSprite, { tint: 0x00FF00 }, { duration: 300, onFinish: function onFinish() { tween(characterSprite, { tint: 0xFFFFFF }, { duration: 200 }); } }); }; self.gainTp = function (amount) { self.tp = Math.min(self.maxTp, self.tp + amount); }; return self; }); var Enemy = Container.expand(function (name, assetId, hp, atk) { var self = Container.call(this); var enemySprite = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); self.name = name; self.hp = hp || 50; self.maxHp = self.hp; self.atk = atk || 15; self.isSpared = false; self.mercyLevel = 0; self.takeDamage = function (amount) { self.hp = Math.max(0, self.hp - amount); // Flash white when taking damage tween(enemySprite, { tint: 0xFFFFFF }, { duration: 100, onFinish: function onFinish() { tween(enemySprite, { tint: 0xFFFFFF }, { duration: 100 }); } }); if (self.hp <= 0) { self.destroy(); } }; self.increaseMercy = function (amount) { self.mercyLevel = Math.min(100, self.mercyLevel + (amount || 20)); if (self.mercyLevel >= 100) { enemySprite.tint = 0xFFFF00; // Yellow tint when spareable } }; return self; }); var Heart = Container.expand(function () { var self = Container.call(this); var heartSprite = self.attachAsset('heart', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.lastX = self.x; self.lastY = self.y; self.graceTime = 0; self.update = function () { self.lastX = self.x; self.lastY = self.y; if (self.graceTime > 0) { self.graceTime--; heartSprite.alpha = 0.5 + 0.5 * Math.sin(LK.ticks * 0.3); } else { heartSprite.alpha = 1; } }; self.takeHit = function () { if (self.graceTime <= 0) { self.graceTime = 120; // 2 seconds of invincibility return true; } return false; }; return self; }); var ItemMenu = Container.expand(function () { var self = Container.call(this); self.isVisible = false; self.selectedItemIndex = 0; self.items = [{ name: 'Dark Candy', description: 'Restores 10 HP', effect: 'heal', value: 10, quantity: 3 }, { name: 'Revive Mint', description: 'Restores 30 HP', effect: 'heal', value: 30, quantity: 2 }, { name: 'Tension Bit', description: 'Restores 20 TP', effect: 'tp', value: 20, quantity: 1 }]; // Create menu background var menuBg = self.attachAsset('dialogBox', { anchorX: 0.5, anchorY: 0.5 }); menuBg.width = 1200; menuBg.height = 800; menuBg.tint = 0x222222; // Create title text var titleText = new Text2('ITEMS', { size: 48, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0); titleText.x = 0; titleText.y = -350; self.addChild(titleText); // Create item buttons and text self.itemButtons = []; self.itemTexts = []; for (var i = 0; i < self.items.length; i++) { var itemButton = LK.getAsset('menuButton', { anchorX: 0, anchorY: 0.5 }); itemButton.x = -550; itemButton.y = -200 + i * 100; itemButton.width = 1000; itemButton.height = 80; itemButton.tint = 0x444444; itemButton.itemIndex = i; self.addChild(itemButton); self.itemButtons.push(itemButton); var itemText = new Text2(self.items[i].name + ' x' + self.items[i].quantity, { size: 32, fill: 0xFFFFFF }); itemText.x = -500; itemText.y = -200 + i * 100; itemText.anchor.set(0, 0.5); self.addChild(itemText); self.itemTexts.push(itemText); var descText = new Text2(self.items[i].description, { size: 24, fill: 0xCCCCCC }); descText.x = -200; descText.y = -200 + i * 100; descText.anchor.set(0, 0.5); self.addChild(descText); } // Create back button var backButton = LK.getAsset('menuButton', { anchorX: 0.5, anchorY: 0.5 }); backButton.x = 0; backButton.y = 300; backButton.width = 200; backButton.height = 60; backButton.tint = 0x666666; self.addChild(backButton); var backText = new Text2('BACK', { size: 32, fill: 0xFFFFFF }); backText.anchor.set(0.5, 0.5); backButton.addChild(backText); self.show = function () { self.isVisible = true; self.alpha = 1; self.updateSelection(); }; self.hide = function () { self.isVisible = false; self.alpha = 0; }; self.updateSelection = function () { for (var i = 0; i < self.itemButtons.length; i++) { if (i === self.selectedItemIndex) { self.itemButtons[i].tint = 0x666666; } else { self.itemButtons[i].tint = 0x444444; } } }; self.useSelectedItem = function () { var item = self.items[self.selectedItemIndex]; if (item.quantity <= 0) return false; item.quantity--; self.itemTexts[self.selectedItemIndex].setText(item.name + ' x' + item.quantity); if (item.effect === 'heal') { kris.heal(item.value); } else if (item.effect === 'tp') { kris.gainTp(item.value); } return true; }; // Handle button clicks for (var i = 0; i < self.itemButtons.length; i++) { self.itemButtons[i].down = function (x, y, obj) { if (self.isVisible && self.items[obj.itemIndex].quantity > 0) { self.selectedItemIndex = obj.itemIndex; if (self.useSelectedItem()) { LK.getSound('heal').play(); self.hide(); if (gameState === 'battle') { selectedAction = 'ITEM'; executePlayerAction(); } } } }; } backButton.down = function (x, y, obj) { if (self.isVisible) { LK.getSound('select').play(); self.hide(); if (gameState === 'battle') { battlePhase = 'menu'; for (var j = 0; j < menuButtons.length; j++) { tween(menuButtons[j], { alpha: 1 }, { duration: 200 }); } } } }; return self; }); var LaserBullet = Container.expand(function (speed, direction) { var self = Container.call(this); var laserSprite = self.attachAsset('laserBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = speed || 6; self.direction = direction || 0; self.lastX = self.x; self.lastY = self.y; // Set rotation to match direction laserSprite.rotation = self.direction; // Pulsing effect self.pulseTime = 0; self.update = function () { self.lastX = self.x; self.lastY = self.y; // Track heart position if in bullet hell phase if (gameState === 'battle' && battlePhase === 'bullet_hell' && heart && heart.alpha > 0) { // Calculate angle to heart var deltaX = heart.x - self.x; var deltaY = heart.y - self.y; var targetAngle = Math.atan2(deltaY, deltaX); // Smoothly rotate towards heart var angleDiff = targetAngle - self.direction; // Normalize angle difference to -PI to PI while (angleDiff > Math.PI) angleDiff -= Math.PI * 2; while (angleDiff < -Math.PI) angleDiff += Math.PI * 2; // Rotate at a maximum rate for smooth turning var rotationSpeed = 0.08; self.direction += Math.sign(angleDiff) * Math.min(Math.abs(angleDiff), rotationSpeed); // Update sprite rotation to match direction laserSprite.rotation = self.direction; } self.x += Math.cos(self.direction) * self.speed; self.y += Math.sin(self.direction) * self.speed; // Pulsing scale effect self.pulseTime += 0.2; laserSprite.scaleY = 1 + 0.3 * Math.sin(self.pulseTime); // Remove bullet if off screen if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) { self.destroy(); } }; return self; }); /**** * Initialize Game ****/ // Game state variables var game = new LK.Game({ backgroundColor: 0x1a1a2e }); /**** * Game Code ****/ // Create background sprite // Sounds // World elements // UI elements // Battle elements // Enemy sprites // Character sprites // Game state variables var backgroundSprite = LK.getAsset('background', { anchorX: 0, anchorY: 0, scaleX: 1, scaleY: 1 }); backgroundSprite.x = 0; backgroundSprite.y = 0; game.addChild(backgroundSprite); // Move background to the bottom layer game.setChildIndex(backgroundSprite, 0); var gameState = 'overworld'; // 'overworld', 'battle', 'dialogue' var currentChapter = 1; var partyMembers = []; var currentEnemies = []; var selectedAction = null; var selectedTarget = null; var turnOrder = []; var currentTurnIndex = 0; var battlePhase = 'menu'; // 'menu', 'action', 'enemy_turn', 'bullet_hell' var bullets = []; var dialogueText = ''; var dialogueIndex = 0; // Enemy dialogue options var enemyDialogues = ["UEE HEE HEE! VISITORS, VISITORS! NOW WE CAN PLAY, PLAY!", "THEN, AFTER YOU, I CAN PLAY WITH EVERYONE ELSE, TOO!", "So what are we playing, exactly...?", "OH, IT'S JUST A SIMPLE NUMBERS GAME.", "WHEN YOUR HP DROPS TO 0, YOU LOSE!", "So that's the kinda game you wanna play, huh...?", "Then, I gotta warn you...", "You're dealing with a couple of sharks.", "UEE HEE HEE! SHARK-TO-SHARK! I WOULDN'T HAVE IT ANY OTHER WAY!", "NOW, NOW!! LET THE GAMES BEGIN!!"]; // UI elements var hpText, tpText, menuButtons = [], dialogueBox, battleBox, itemMenu, enemyDialogBox, enemyDialogText; var heart; // Create party members var kris = new Character('Kris', 'kris'); kris.x = 300; kris.y = 1366; partyMembers.push(kris); game.addChild(kris); var susie = new Character('Susie', 'susie'); susie.x = 300; susie.y = 1000; susie.atk = 15; susie.hp = 120; susie.maxHp = 120; partyMembers.push(susie); game.addChild(susie); var ralsei = new Character('Ralsei', 'ralsei'); ralsei.x = 300; ralsei.y = 1732; ralsei.mag = 15; ralsei.hp = 80; ralsei.maxHp = 80; partyMembers.push(ralsei); game.addChild(ralsei); // Create TP bars for party members (behind characters) var tpBars = []; for (var i = 0; i < partyMembers.length; i++) { var tpBarBg = LK.getAsset('menuButton', { anchorX: 0, anchorY: 0.5 }); tpBarBg.x = 50; tpBarBg.y = partyMembers[i].y; tpBarBg.width = 400; tpBarBg.height = 30; tpBarBg.tint = 0x333333; game.addChild(tpBarBg); var tpBarFill = LK.getAsset('menuButton', { anchorX: 0, anchorY: 0.5 }); tpBarFill.x = 50; tpBarFill.y = partyMembers[i].y; tpBarFill.width = 0; tpBarFill.height = 30; tpBarFill.tint = 0xFFFF00; game.addChild(tpBarFill); tpBars.push({ bg: tpBarBg, fill: tpBarFill, character: partyMembers[i] }); } // Create UI hpText = new Text2('HP: 100/100', { size: 40, fill: 0xFFFFFF }); hpText.anchor.set(1, 1); hpText.x = -50; hpText.y = -50; LK.gui.bottomRight.addChild(hpText); tpText = new Text2('TP: 0/100', { size: 40, fill: 0xFFFF00 }); tpText.anchor.set(1, 1); tpText.x = -50; tpText.y = -100; LK.gui.bottomRight.addChild(tpText); // Create battle menu buttons var actionNames = ['FIGHT', 'ACT', 'ITEM', 'DEFEND', 'SPARE']; for (var i = 0; i < actionNames.length; i++) { var button = LK.getAsset('menuButton', { anchorX: 0.5, anchorY: 0.5 }); button.x = 200 + i * 220; button.y = 2600; button.actionType = actionNames[i]; button.alpha = 0; var buttonText = new Text2(actionNames[i], { size: 32, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); button.addChild(buttonText); button.down = function (x, y, obj) { if (gameState === 'battle' && battlePhase === 'menu') { selectedAction = obj.actionType; LK.getSound('select').play(); if (obj.actionType === 'ITEM') { // Show item menu for (var j = 0; j < menuButtons.length; j++) { tween(menuButtons[j], { alpha: 0 }, { duration: 200 }); } itemMenu.show(); } else { // Hide menu and start action for (var j = 0; j < menuButtons.length; j++) { tween(menuButtons[j], { alpha: 0 }, { duration: 200 }); } battlePhase = 'action'; executePlayerAction(); } } }; menuButtons.push(button); game.addChild(button); } // Create dialogue box dialogueBox = LK.getAsset('dialogBox', { anchorX: 0.5, anchorY: 0 }); dialogueBox.x = 1024; dialogueBox.y = 2532; dialogueBox.alpha = 0; game.addChild(dialogueBox); var dialogueTextObj = new Text2('', { size: 36, fill: 0xFFFFFF }); dialogueTextObj.x = 100; dialogueTextObj.y = 50; dialogueBox.addChild(dialogueTextObj); // Create battle box battleBox = LK.getAsset('battleBox', { anchorX: 0.5, anchorY: 0.5 }); battleBox.x = 1024; battleBox.y = 1366; battleBox.alpha = 0; game.addChild(battleBox); // Create heart for bullet hell heart = new Heart(); heart.x = 1024; heart.y = 1366; heart.alpha = 0; game.addChild(heart); // Create item menu itemMenu = new ItemMenu(); itemMenu.x = 1024; itemMenu.y = 1366; itemMenu.alpha = 0; game.addChild(itemMenu); // Create enemy dialog box enemyDialogBox = LK.getAsset('enemyDialogBox', { anchorX: 0.5, anchorY: 0.5 }); enemyDialogBox.x = 1024; enemyDialogBox.y = 800; enemyDialogBox.alpha = 0; game.addChild(enemyDialogBox); // Create enemy dialog text enemyDialogText = new Text2('', { size: 32, fill: 0xFFFFFF }); enemyDialogText.anchor.set(0.5, 0.5); enemyDialogText.x = 0; enemyDialogText.y = 0; enemyDialogBox.addChild(enemyDialogText); // Functions function startBattle() { gameState = 'battle'; battlePhase = 'menu'; // Create enemy var enemy = new Enemy('Dark Creature', 'enemy', 60, 12); enemy.x = 1700; enemy.y = 1366; currentEnemies.push(enemy); game.addChild(enemy); // Show battle UI for (var i = 0; i < menuButtons.length; i++) { tween(menuButtons[i], { alpha: 1 }, { duration: 500 }); } tween(battleBox, { alpha: 0.3 }, { duration: 500 }); } function executePlayerAction() { var target = currentEnemies[0]; if (!target) return; switch (selectedAction) { case 'FIGHT': var damage = Math.floor(kris.atk + Math.random() * 10); target.takeDamage(damage); LK.getSound('attack').play(); showDialogue(kris.name + ' deals ' + damage + ' damage!'); break; case 'ACT': target.increaseMercy(25); showDialogue(kris.name + ' tries to reason with ' + target.name); break; case 'ITEM': // Item action is now handled by the ItemMenu class showDialogue(kris.name + ' used an item!'); break; case 'DEFEND': kris.isDefending = true; kris.gainTp(15); showDialogue(kris.name + ' guards and gains TP!'); break; case 'SPARE': if (target.mercyLevel >= 100) { target.isSpared = true; showDialogue(target.name + ' was spared!'); currentEnemies = []; target.destroy(); endBattle(); return; } else { showDialogue(target.name + ' is not ready to be spared.'); } break; } LK.setTimeout(function () { if (currentEnemies.length > 0 && !currentEnemies[0].isSpared) { startEnemyTurn(); } else { endBattle(); } }, 2000); } function startEnemyTurn() { battlePhase = 'bullet_hell'; // Show random enemy dialogue first var randomDialogue = enemyDialogues[Math.floor(Math.random() * enemyDialogues.length)]; showEnemyDialogue(randomDialogue); // Delay bullet hell start to show dialogue LK.setTimeout(function () { hideEnemyDialogue(); // Show heart and battle box tween(heart, { alpha: 1 }, { duration: 300 }); tween(battleBox, { alpha: 0.8 }, { duration: 300 }); // Start bullet pattern var bulletTimer = LK.setInterval(function () { createBulletPattern(); }, 600); // End bullet hell after 8 seconds (doubled duration) LK.setTimeout(function () { LK.clearInterval(bulletTimer); endEnemyTurn(); }, 8000); }, 2000); // Show dialogue for 2 seconds } var maxAttackPhases = 10; function createBulletPattern() { var centerX = battleBox.x; var centerY = battleBox.y; // Random attack phase selection var attackPhase = Math.floor(Math.random() * maxAttackPhases); switch (attackPhase) { case 0: // Original circular pattern for (var i = 0; i < 8; i++) { var angle = i / 8 * Math.PI * 2; var bullet = new Bullet(4, angle); bullet.x = centerX; bullet.y = centerY; bullets.push(bullet); game.addChild(bullet); } break; case 1: // Spiral pattern with tween animation for (var i = 0; i < 12; i++) { var angle = i / 12 * Math.PI * 2; var bullet = new Bullet(2, angle); bullet.x = centerX; bullet.y = centerY; bullets.push(bullet); game.addChild(bullet); // Animate bullet in a spiral tween(bullet, { speed: 6 }, { duration: 1000, easing: tween.easeOut }); } break; case 2: // Wave pattern from sides for (var i = 0; i < 6; i++) { // Left side bullets var leftBullet = new Bullet(3, 0); // Moving right leftBullet.x = centerX - 280; leftBullet.y = centerY - 150 + i * 60; bullets.push(leftBullet); game.addChild(leftBullet); // Animate with sine wave motion tween(leftBullet, { direction: Math.PI / 4 }, { duration: 800, easing: tween.sinceOut }); // Right side bullets var rightBullet = new Bullet(3, Math.PI); // Moving left rightBullet.x = centerX + 280; rightBullet.y = centerY - 150 + i * 60; bullets.push(rightBullet); game.addChild(rightBullet); // Animate with sine wave motion tween(rightBullet, { direction: Math.PI * 3 / 4 }, { duration: 800, easing: tween.sinceOut }); } break; case 3: // Expanding ring pattern for (var ring = 0; ring < 3; ring++) { for (var i = 0; i < 6; i++) { var angle = i / 6 * Math.PI * 2; var bullet = new Bullet(1, angle); bullet.x = centerX; bullet.y = centerY; bullets.push(bullet); game.addChild(bullet); // Animate expanding rings with delay tween(bullet, { speed: 4 + ring * 2 }, { duration: 500, easing: tween.easeInOut, onFinish: function () { // Change direction slightly for unpredictability this.direction += (Math.random() - 0.5) * 0.5; }.bind(bullet) }); } // Delay between rings LK.setTimeout(function (ringIndex) { return function () { // Ring animation complete }; }(ring), ring * 200); } break; case 4: // Cross pattern with rotating bullets for (var i = 0; i < 4; i++) { var angle = i * Math.PI / 2; var bullet = new Bullet(3, angle); bullet.x = centerX; bullet.y = centerY; bullets.push(bullet); game.addChild(bullet); // Rotate direction while moving tween(bullet, { direction: angle + Math.PI * 2 }, { duration: 1500, easing: tween.linear }); } // Add diagonal bullets for (var i = 0; i < 4; i++) { var angle = i * Math.PI / 2 + Math.PI / 4; var bullet = new Bullet(2, angle); bullet.x = centerX; bullet.y = centerY; bullets.push(bullet); game.addChild(bullet); tween(bullet, { speed: 5 }, { duration: 800, easing: tween.easeInOut }); } break; case 5: // Zigzag pattern from corners for (var corner = 0; corner < 4; corner++) { var startX = centerX + (corner < 2 ? -250 : 250); var startY = centerY + (corner % 2 === 0 ? -150 : 150); var bullet = new Bullet(4, corner * Math.PI / 2); bullet.x = startX; bullet.y = startY; bullets.push(bullet); game.addChild(bullet); // Create zigzag motion tween(bullet, { direction: bullet.direction + Math.PI / 3 }, { duration: 400, easing: tween.easeInOut, onFinish: function () { tween(this, { direction: this.direction - Math.PI / 1.5 }, { duration: 400, easing: tween.easeInOut }); }.bind(bullet) }); } break; case 6: // Bouncing bullets from walls for (var i = 0; i < 8; i++) { var side = i % 4; // 0=top, 1=right, 2=bottom, 3=left var bullet = new Bullet(5, 0); switch (side) { case 0: // Top bullet.x = centerX - 200 + i / 4 * 400; bullet.y = centerY - 180; bullet.direction = Math.PI / 2; break; case 1: // Right bullet.x = centerX + 280; bullet.y = centerY - 100 + i / 4 * 200; bullet.direction = Math.PI; break; case 2: // Bottom bullet.x = centerX - 200 + i / 4 * 400; bullet.y = centerY + 180; bullet.direction = -Math.PI / 2; break; case 3: // Left bullet.x = centerX - 280; bullet.y = centerY - 100 + i / 4 * 200; bullet.direction = 0; break; } bullets.push(bullet); game.addChild(bullet); // Add bouncing behavior tween(bullet, { speed: 3 }, { duration: 1200, easing: tween.bounceOut }); } break; case 7: // Converging then diverging pattern for (var i = 0; i < 16; i++) { var angle = i / 16 * Math.PI * 2; var distance = 300; var bullet = new Bullet(1, angle + Math.PI); bullet.x = centerX + Math.cos(angle) * distance; bullet.y = centerY + Math.sin(angle) * distance; bullets.push(bullet); game.addChild(bullet); // First converge to center tween(bullet, { speed: 4 }, { duration: 800, easing: tween.easeIn, onFinish: function () { // Then diverge outward tween(this, { direction: this.direction + Math.PI, speed: 6 }, { duration: 600, easing: tween.easeOut }); }.bind(bullet) }); } break; case 8: // Horizontal laser sweeps for (var i = 0; i < 2; i++) { var laser = new LaserBullet(4, 0); // Moving right laser.x = centerX - 300; laser.y = centerY - 80 + i * 160; bullets.push(laser); game.addChild(laser); // Animate speed increase tween(laser, { speed: 8 }, { duration: 1000, easing: tween.easeInOut }); } // Vertical laser sweeps for (var i = 0; i < 2; i++) { var laser = new LaserBullet(3, Math.PI / 2); // Moving down laser.x = centerX - 50 + i * 100; laser.y = centerY - 200; bullets.push(laser); game.addChild(laser); // Animate with slight direction change tween(laser, { direction: Math.PI / 2 + 0.3 }, { duration: 800, easing: tween.easeInOut }); } break; case 9: // Rotating laser beams from center for (var i = 0; i < 4; i++) { var angle = i / 4 * Math.PI * 2; var laser = new LaserBullet(2, angle); laser.x = centerX; laser.y = centerY; bullets.push(laser); game.addChild(laser); // Rotate continuously while moving tween(laser, { direction: angle + Math.PI * 1.5, speed: 5 }, { duration: 1200, easing: tween.linear }); } break; } } function endEnemyTurn() { battlePhase = 'menu'; // Hide heart and dim battle box tween(heart, { alpha: 0 }, { duration: 300 }); tween(battleBox, { alpha: 0.3 }, { duration: 300 }); // Show menu buttons again for (var i = 0; i < menuButtons.length; i++) { tween(menuButtons[i], { alpha: 1 }, { duration: 500 }); } kris.isDefending = false; } function endBattle() { gameState = 'overworld'; // Hide battle UI for (var i = 0; i < menuButtons.length; i++) { tween(menuButtons[i], { alpha: 0 }, { duration: 500 }); } tween(battleBox, { alpha: 0 }, { duration: 500 }); tween(heart, { alpha: 0 }, { duration: 500 }); hideDialogue(); // Clear bullets for (var i = bullets.length - 1; i >= 0; i--) { bullets[i].destroy(); bullets.splice(i, 1); } } function showDialogue(text) { dialogueText = text; dialogueTextObj.setText(text); tween(dialogueBox, { alpha: 1 }, { duration: 300 }); } function showEnemyDialogue(text) { enemyDialogText.setText(text); // Change enemy sprite to talking version if (currentEnemies.length > 0) { var enemy = currentEnemies[0]; // Hide original sprite and show talking sprite enemy.originalSprite = enemy.children[0]; enemy.originalSprite.alpha = 0; var enemyTalkingSprite = LK.getAsset('enemyTalking', { anchorX: 0.5, anchorY: 0.5 }); enemyTalkingSprite.x = enemy.x; enemyTalkingSprite.y = enemy.y; enemy.addChild(enemyTalkingSprite); enemy.talkingSprite = enemyTalkingSprite; } tween(enemyDialogBox, { alpha: 1 }, { duration: 300 }); } function hideEnemyDialogue() { // Restore original enemy sprite if (currentEnemies.length > 0) { var enemy = currentEnemies[0]; if (enemy.talkingSprite) { enemy.talkingSprite.destroy(); enemy.talkingSprite = null; } if (enemy.originalSprite) { enemy.originalSprite.alpha = 1; } } tween(enemyDialogBox, { alpha: 0 }, { duration: 300 }); } function hideDialogue() { tween(dialogueBox, { alpha: 0 }, { duration: 300 }); } function showDeathScreen() { // Fade background to black tween(game, { backgroundColor: 0x000000 }, { duration: 1000 }); // Make everything invisible except the heart for (var i = 0; i < partyMembers.length; i++) { tween(partyMembers[i], { alpha: 0 }, { duration: 1000 }); } for (var i = 0; i < currentEnemies.length; i++) { tween(currentEnemies[i], { alpha: 0 }, { duration: 1000 }); } tween(battleBox, { alpha: 0 }, { duration: 1000 }); for (var i = 0; i < menuButtons.length; i++) { tween(menuButtons[i], { alpha: 0 }, { duration: 1000 }); } tween(dialogueBox, { alpha: 0 }, { duration: 1000 }); // Create two heart pieces var heartLeft = LK.getAsset('heart', { anchorX: 1, anchorY: 0.5 }); heartLeft.x = heart.x; heartLeft.y = heart.y; heartLeft.width = heart.width / 2; game.addChild(heartLeft); var heartRight = LK.getAsset('heart', { anchorX: 0, anchorY: 0.5 }); heartRight.x = heart.x; heartRight.y = heart.y; heartRight.width = heart.width / 2; game.addChild(heartRight); // Hide original heart heart.alpha = 0; // Animate heart pieces splitting apart tween(heartLeft, { x: heart.x - 100, rotation: -0.5 }, { duration: 1500, easing: tween.easeOut }); tween(heartRight, { x: heart.x + 100, rotation: 0.5 }, { duration: 1500, easing: tween.easeOut, onFinish: function onFinish() { // Show death dialogue and choices after heart split animation LK.setTimeout(function () { showDeathDialogue(); }, 500); } }); } function showDeathDialogue() { // Create death dialogue background var deathDialogueBox = LK.getAsset('dialogBox', { anchorX: 0.5, anchorY: 0.5 }); deathDialogueBox.x = 1024; deathDialogueBox.y = 1366; deathDialogueBox.width = 1600; deathDialogueBox.height = 600; deathDialogueBox.tint = 0x000000; game.addChild(deathDialogueBox); // Create death dialogue text var deathText = new Text2('Is this the end? You can keep going no matter what happens..', { size: 48, fill: 0xFFFFFF }); deathText.anchor.set(0.5, 0.5); deathText.x = 0; deathText.y = -150; deathDialogueBox.addChild(deathText); // Create "..." button var dotsButton = LK.getAsset('menuButton', { anchorX: 0.5, anchorY: 0.5 }); dotsButton.x = -200; dotsButton.y = 100; dotsButton.width = 300; dotsButton.height = 80; dotsButton.tint = 0x444444; deathDialogueBox.addChild(dotsButton); var dotsText = new Text2('...', { size: 36, fill: 0xFFFFFF }); dotsText.anchor.set(0.5, 0.5); dotsButton.addChild(dotsText); // Create "Proceed" button var proceedButton = LK.getAsset('menuButton', { anchorX: 0.5, anchorY: 0.5 }); proceedButton.x = 200; proceedButton.y = 100; proceedButton.width = 300; proceedButton.height = 80; proceedButton.tint = 0x444444; deathDialogueBox.addChild(proceedButton); var proceedText = new Text2('Proceed', { size: 36, fill: 0xFFFFFF }); proceedText.anchor.set(0.5, 0.5); proceedButton.addChild(proceedText); // Handle "..." button click (death) dotsButton.down = function (x, y, obj) { // Hide dialogue and options immediately deathDialogueBox.alpha = 0; LK.setTimeout(function () { LK.showGameOver(); }, 500); }; // Handle "Proceed" button click (restart with flash) proceedButton.down = function (x, y, obj) { // Hide dialogue and options immediately deathDialogueBox.alpha = 0; // White flash effect LK.effects.flashScreen(0xFFFFFF, 1000); LK.setTimeout(function () { // Restart the game by recreating the game state restartGame(); }, 1000); }; // Fade in the death dialogue tween(deathDialogueBox, { alpha: 1 }, { duration: 1000 }); } function restartGame() { // Destroy current game elements for (var i = 0; i < partyMembers.length; i++) { partyMembers[i].destroy(); } for (var i = 0; i < currentEnemies.length; i++) { currentEnemies[i].destroy(); } for (var i = bullets.length - 1; i >= 0; i--) { bullets[i].destroy(); bullets.splice(i, 1); } // Reset game state gameState = 'overworld'; currentEnemies = []; partyMembers = []; bullets = []; selectedAction = null; selectedTarget = null; battlePhase = 'menu'; // Reset background color game.setBackgroundColor(0x1a1a2e); // Recreate party members kris = new Character('Kris', 'kris'); kris.x = 300; kris.y = 1366; kris.hp = 100; kris.tp = 0; partyMembers.push(kris); game.addChild(kris); susie = new Character('Susie', 'susie'); susie.x = 300; susie.y = 1000; susie.atk = 15; susie.hp = 120; susie.maxHp = 120; susie.tp = 0; partyMembers.push(susie); game.addChild(susie); ralsei = new Character('Ralsei', 'ralsei'); ralsei.x = 300; ralsei.y = 1732; ralsei.mag = 15; ralsei.hp = 80; ralsei.maxHp = 80; ralsei.tp = 0; partyMembers.push(ralsei); game.addChild(ralsei); // Reset heart heart.x = 1024; heart.y = 1366; heart.alpha = 0; heart.graceTime = 0; // Reset UI visibility for (var i = 0; i < menuButtons.length; i++) { menuButtons[i].alpha = 0; } battleBox.alpha = 0; dialogueBox.alpha = 0; enemyDialogBox.alpha = 0; itemMenu.alpha = 0; itemMenu.hide(); // Update TP bars for (var i = 0; i < tpBars.length; i++) { tpBars[i].fill.width = 0; } } // Dragging variables var dragTarget = null; var dragOffset = { x: 0, y: 0 }; // Input handlers game.down = function (x, y, obj) { if (gameState === 'overworld') { // Check if clicking on Kris for dragging var distToKris = Math.sqrt(Math.pow(x - kris.x, 2) + Math.pow(y - kris.y, 2)); if (distToKris < 100) { // Within dragging range dragTarget = kris; dragOffset.x = x - kris.x; dragOffset.y = y - kris.y; } else { // Start battle when touching screen elsewhere startBattle(); } } else if (gameState === 'battle' && battlePhase === 'bullet_hell') { // Move heart to touch position var localPos = battleBox.toLocal({ x: x, y: y }); var boundedX = Math.max(-280, Math.min(280, localPos.x)); var boundedY = Math.max(-180, Math.min(180, localPos.y)); tween(heart, { x: battleBox.x + boundedX, y: battleBox.y + boundedY }, { duration: 100 }); } }; game.up = function (x, y, obj) { // Stop dragging when mouse/touch is released dragTarget = null; }; game.move = function (x, y, obj) { if (gameState === 'overworld' && dragTarget) { // Drag Kris around the screen dragTarget.x = x - dragOffset.x; dragTarget.y = y - dragOffset.y; // Keep Kris within screen bounds dragTarget.x = Math.max(50, Math.min(1998, dragTarget.x)); dragTarget.y = Math.max(50, Math.min(2682, dragTarget.y)); } else if (gameState === 'battle' && battlePhase === 'bullet_hell') { // Move heart to cursor position within battle box bounds var localPos = battleBox.toLocal({ x: x, y: y }); var boundedX = Math.max(-280, Math.min(280, localPos.x)); var boundedY = Math.max(-180, Math.min(180, localPos.y)); heart.x = battleBox.x + boundedX; heart.y = battleBox.y + boundedY; } }; // Start music when game begins LK.playMusic('World_Revolving'); // Main game update loop game.update = function () { // Update UI hpText.setText('HP: ' + kris.hp + '/' + kris.maxHp); tpText.setText('TP: ' + kris.tp + '/' + kris.maxTp); // Update TP bars for (var i = 0; i < tpBars.length; i++) { var tpBar = tpBars[i]; var tpPercent = tpBar.character.tp / tpBar.character.maxTp; tpBar.fill.width = 400 * tpPercent; } // Update bullets and check collisions for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; if (bullet.lastX === undefined) bullet.lastX = bullet.x; if (bullet.lastY === undefined) bullet.lastY = bullet.y; // Check if bullet is outside battle box var distFromCenter = Math.sqrt(Math.pow(bullet.x - battleBox.x, 2) + Math.pow(bullet.y - battleBox.y, 2)); if (distFromCenter > 320) { bullet.destroy(); bullets.splice(i, 1); continue; } // Check collision with heart during bullet hell if (gameState === 'battle' && battlePhase === 'bullet_hell' && heart.alpha > 0) { if (bullet.intersects(heart)) { var distance = Math.sqrt(Math.pow(bullet.x - heart.x, 2) + Math.pow(bullet.y - heart.y, 2)); if (distance < 40 && distance > 20) { // Graze - gain TP kris.gainTp(5); LK.effects.flashObject(heart, 0x00FF00, 200); } else if (distance <= 20) { // Hit - take damage if (heart.takeHit()) { kris.takeDamage(10); LK.getSound('damage').play(); LK.effects.flashScreen(0xFF0000, 300); if (kris.hp <= 0) { showDeathScreen(); } } } } } bullet.lastX = bullet.x; bullet.lastY = bullet.y; } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bullet = Container.expand(function (speed, direction) {
var self = Container.call(this);
var bulletSprite = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = speed || 3;
self.direction = direction || 0; // radians
self.lastX = self.x;
self.lastY = self.y;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
// Remove bullet if off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
self.destroy();
}
};
return self;
});
var Character = Container.expand(function (name, assetId) {
var self = Container.call(this);
// Character graphics
var characterSprite = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// Character stats
self.name = name;
self.hp = 100;
self.maxHp = 100;
self.atk = 10;
self.def = 5;
self.mag = 8;
self.speed = 5;
self.tp = 0;
self.maxTp = 100;
// Battle state
self.isDefending = false;
self.lastX = self.x;
self.lastY = self.y;
self.takeDamage = function (amount) {
if (self.isDefending) {
amount = Math.floor(amount * 0.5);
}
self.hp = Math.max(0, self.hp - amount);
// Flash red when taking damage
tween(characterSprite, {
tint: 0xFF0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(characterSprite, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
};
self.heal = function (amount) {
self.hp = Math.min(self.maxHp, self.hp + amount);
// Flash green when healing
tween(characterSprite, {
tint: 0x00FF00
}, {
duration: 300,
onFinish: function onFinish() {
tween(characterSprite, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
};
self.gainTp = function (amount) {
self.tp = Math.min(self.maxTp, self.tp + amount);
};
return self;
});
var Enemy = Container.expand(function (name, assetId, hp, atk) {
var self = Container.call(this);
var enemySprite = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.name = name;
self.hp = hp || 50;
self.maxHp = self.hp;
self.atk = atk || 15;
self.isSpared = false;
self.mercyLevel = 0;
self.takeDamage = function (amount) {
self.hp = Math.max(0, self.hp - amount);
// Flash white when taking damage
tween(enemySprite, {
tint: 0xFFFFFF
}, {
duration: 100,
onFinish: function onFinish() {
tween(enemySprite, {
tint: 0xFFFFFF
}, {
duration: 100
});
}
});
if (self.hp <= 0) {
self.destroy();
}
};
self.increaseMercy = function (amount) {
self.mercyLevel = Math.min(100, self.mercyLevel + (amount || 20));
if (self.mercyLevel >= 100) {
enemySprite.tint = 0xFFFF00; // Yellow tint when spareable
}
};
return self;
});
var Heart = Container.expand(function () {
var self = Container.call(this);
var heartSprite = self.attachAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.lastX = self.x;
self.lastY = self.y;
self.graceTime = 0;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
if (self.graceTime > 0) {
self.graceTime--;
heartSprite.alpha = 0.5 + 0.5 * Math.sin(LK.ticks * 0.3);
} else {
heartSprite.alpha = 1;
}
};
self.takeHit = function () {
if (self.graceTime <= 0) {
self.graceTime = 120; // 2 seconds of invincibility
return true;
}
return false;
};
return self;
});
var ItemMenu = Container.expand(function () {
var self = Container.call(this);
self.isVisible = false;
self.selectedItemIndex = 0;
self.items = [{
name: 'Dark Candy',
description: 'Restores 10 HP',
effect: 'heal',
value: 10,
quantity: 3
}, {
name: 'Revive Mint',
description: 'Restores 30 HP',
effect: 'heal',
value: 30,
quantity: 2
}, {
name: 'Tension Bit',
description: 'Restores 20 TP',
effect: 'tp',
value: 20,
quantity: 1
}];
// Create menu background
var menuBg = self.attachAsset('dialogBox', {
anchorX: 0.5,
anchorY: 0.5
});
menuBg.width = 1200;
menuBg.height = 800;
menuBg.tint = 0x222222;
// Create title text
var titleText = new Text2('ITEMS', {
size: 48,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
titleText.x = 0;
titleText.y = -350;
self.addChild(titleText);
// Create item buttons and text
self.itemButtons = [];
self.itemTexts = [];
for (var i = 0; i < self.items.length; i++) {
var itemButton = LK.getAsset('menuButton', {
anchorX: 0,
anchorY: 0.5
});
itemButton.x = -550;
itemButton.y = -200 + i * 100;
itemButton.width = 1000;
itemButton.height = 80;
itemButton.tint = 0x444444;
itemButton.itemIndex = i;
self.addChild(itemButton);
self.itemButtons.push(itemButton);
var itemText = new Text2(self.items[i].name + ' x' + self.items[i].quantity, {
size: 32,
fill: 0xFFFFFF
});
itemText.x = -500;
itemText.y = -200 + i * 100;
itemText.anchor.set(0, 0.5);
self.addChild(itemText);
self.itemTexts.push(itemText);
var descText = new Text2(self.items[i].description, {
size: 24,
fill: 0xCCCCCC
});
descText.x = -200;
descText.y = -200 + i * 100;
descText.anchor.set(0, 0.5);
self.addChild(descText);
}
// Create back button
var backButton = LK.getAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5
});
backButton.x = 0;
backButton.y = 300;
backButton.width = 200;
backButton.height = 60;
backButton.tint = 0x666666;
self.addChild(backButton);
var backText = new Text2('BACK', {
size: 32,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backButton.addChild(backText);
self.show = function () {
self.isVisible = true;
self.alpha = 1;
self.updateSelection();
};
self.hide = function () {
self.isVisible = false;
self.alpha = 0;
};
self.updateSelection = function () {
for (var i = 0; i < self.itemButtons.length; i++) {
if (i === self.selectedItemIndex) {
self.itemButtons[i].tint = 0x666666;
} else {
self.itemButtons[i].tint = 0x444444;
}
}
};
self.useSelectedItem = function () {
var item = self.items[self.selectedItemIndex];
if (item.quantity <= 0) return false;
item.quantity--;
self.itemTexts[self.selectedItemIndex].setText(item.name + ' x' + item.quantity);
if (item.effect === 'heal') {
kris.heal(item.value);
} else if (item.effect === 'tp') {
kris.gainTp(item.value);
}
return true;
};
// Handle button clicks
for (var i = 0; i < self.itemButtons.length; i++) {
self.itemButtons[i].down = function (x, y, obj) {
if (self.isVisible && self.items[obj.itemIndex].quantity > 0) {
self.selectedItemIndex = obj.itemIndex;
if (self.useSelectedItem()) {
LK.getSound('heal').play();
self.hide();
if (gameState === 'battle') {
selectedAction = 'ITEM';
executePlayerAction();
}
}
}
};
}
backButton.down = function (x, y, obj) {
if (self.isVisible) {
LK.getSound('select').play();
self.hide();
if (gameState === 'battle') {
battlePhase = 'menu';
for (var j = 0; j < menuButtons.length; j++) {
tween(menuButtons[j], {
alpha: 1
}, {
duration: 200
});
}
}
}
};
return self;
});
var LaserBullet = Container.expand(function (speed, direction) {
var self = Container.call(this);
var laserSprite = self.attachAsset('laserBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = speed || 6;
self.direction = direction || 0;
self.lastX = self.x;
self.lastY = self.y;
// Set rotation to match direction
laserSprite.rotation = self.direction;
// Pulsing effect
self.pulseTime = 0;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
// Track heart position if in bullet hell phase
if (gameState === 'battle' && battlePhase === 'bullet_hell' && heart && heart.alpha > 0) {
// Calculate angle to heart
var deltaX = heart.x - self.x;
var deltaY = heart.y - self.y;
var targetAngle = Math.atan2(deltaY, deltaX);
// Smoothly rotate towards heart
var angleDiff = targetAngle - self.direction;
// Normalize angle difference to -PI to PI
while (angleDiff > Math.PI) angleDiff -= Math.PI * 2;
while (angleDiff < -Math.PI) angleDiff += Math.PI * 2;
// Rotate at a maximum rate for smooth turning
var rotationSpeed = 0.08;
self.direction += Math.sign(angleDiff) * Math.min(Math.abs(angleDiff), rotationSpeed);
// Update sprite rotation to match direction
laserSprite.rotation = self.direction;
}
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
// Pulsing scale effect
self.pulseTime += 0.2;
laserSprite.scaleY = 1 + 0.3 * Math.sin(self.pulseTime);
// Remove bullet if off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
// Game state variables
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Create background sprite
// Sounds
// World elements
// UI elements
// Battle elements
// Enemy sprites
// Character sprites
// Game state variables
var backgroundSprite = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
scaleX: 1,
scaleY: 1
});
backgroundSprite.x = 0;
backgroundSprite.y = 0;
game.addChild(backgroundSprite);
// Move background to the bottom layer
game.setChildIndex(backgroundSprite, 0);
var gameState = 'overworld'; // 'overworld', 'battle', 'dialogue'
var currentChapter = 1;
var partyMembers = [];
var currentEnemies = [];
var selectedAction = null;
var selectedTarget = null;
var turnOrder = [];
var currentTurnIndex = 0;
var battlePhase = 'menu'; // 'menu', 'action', 'enemy_turn', 'bullet_hell'
var bullets = [];
var dialogueText = '';
var dialogueIndex = 0;
// Enemy dialogue options
var enemyDialogues = ["UEE HEE HEE! VISITORS, VISITORS! NOW WE CAN PLAY, PLAY!", "THEN, AFTER YOU, I CAN PLAY WITH EVERYONE ELSE, TOO!", "So what are we playing, exactly...?", "OH, IT'S JUST A SIMPLE NUMBERS GAME.", "WHEN YOUR HP DROPS TO 0, YOU LOSE!", "So that's the kinda game you wanna play, huh...?", "Then, I gotta warn you...", "You're dealing with a couple of sharks.", "UEE HEE HEE! SHARK-TO-SHARK! I WOULDN'T HAVE IT ANY OTHER WAY!", "NOW, NOW!! LET THE GAMES BEGIN!!"];
// UI elements
var hpText,
tpText,
menuButtons = [],
dialogueBox,
battleBox,
itemMenu,
enemyDialogBox,
enemyDialogText;
var heart;
// Create party members
var kris = new Character('Kris', 'kris');
kris.x = 300;
kris.y = 1366;
partyMembers.push(kris);
game.addChild(kris);
var susie = new Character('Susie', 'susie');
susie.x = 300;
susie.y = 1000;
susie.atk = 15;
susie.hp = 120;
susie.maxHp = 120;
partyMembers.push(susie);
game.addChild(susie);
var ralsei = new Character('Ralsei', 'ralsei');
ralsei.x = 300;
ralsei.y = 1732;
ralsei.mag = 15;
ralsei.hp = 80;
ralsei.maxHp = 80;
partyMembers.push(ralsei);
game.addChild(ralsei);
// Create TP bars for party members (behind characters)
var tpBars = [];
for (var i = 0; i < partyMembers.length; i++) {
var tpBarBg = LK.getAsset('menuButton', {
anchorX: 0,
anchorY: 0.5
});
tpBarBg.x = 50;
tpBarBg.y = partyMembers[i].y;
tpBarBg.width = 400;
tpBarBg.height = 30;
tpBarBg.tint = 0x333333;
game.addChild(tpBarBg);
var tpBarFill = LK.getAsset('menuButton', {
anchorX: 0,
anchorY: 0.5
});
tpBarFill.x = 50;
tpBarFill.y = partyMembers[i].y;
tpBarFill.width = 0;
tpBarFill.height = 30;
tpBarFill.tint = 0xFFFF00;
game.addChild(tpBarFill);
tpBars.push({
bg: tpBarBg,
fill: tpBarFill,
character: partyMembers[i]
});
}
// Create UI
hpText = new Text2('HP: 100/100', {
size: 40,
fill: 0xFFFFFF
});
hpText.anchor.set(1, 1);
hpText.x = -50;
hpText.y = -50;
LK.gui.bottomRight.addChild(hpText);
tpText = new Text2('TP: 0/100', {
size: 40,
fill: 0xFFFF00
});
tpText.anchor.set(1, 1);
tpText.x = -50;
tpText.y = -100;
LK.gui.bottomRight.addChild(tpText);
// Create battle menu buttons
var actionNames = ['FIGHT', 'ACT', 'ITEM', 'DEFEND', 'SPARE'];
for (var i = 0; i < actionNames.length; i++) {
var button = LK.getAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5
});
button.x = 200 + i * 220;
button.y = 2600;
button.actionType = actionNames[i];
button.alpha = 0;
var buttonText = new Text2(actionNames[i], {
size: 32,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
button.addChild(buttonText);
button.down = function (x, y, obj) {
if (gameState === 'battle' && battlePhase === 'menu') {
selectedAction = obj.actionType;
LK.getSound('select').play();
if (obj.actionType === 'ITEM') {
// Show item menu
for (var j = 0; j < menuButtons.length; j++) {
tween(menuButtons[j], {
alpha: 0
}, {
duration: 200
});
}
itemMenu.show();
} else {
// Hide menu and start action
for (var j = 0; j < menuButtons.length; j++) {
tween(menuButtons[j], {
alpha: 0
}, {
duration: 200
});
}
battlePhase = 'action';
executePlayerAction();
}
}
};
menuButtons.push(button);
game.addChild(button);
}
// Create dialogue box
dialogueBox = LK.getAsset('dialogBox', {
anchorX: 0.5,
anchorY: 0
});
dialogueBox.x = 1024;
dialogueBox.y = 2532;
dialogueBox.alpha = 0;
game.addChild(dialogueBox);
var dialogueTextObj = new Text2('', {
size: 36,
fill: 0xFFFFFF
});
dialogueTextObj.x = 100;
dialogueTextObj.y = 50;
dialogueBox.addChild(dialogueTextObj);
// Create battle box
battleBox = LK.getAsset('battleBox', {
anchorX: 0.5,
anchorY: 0.5
});
battleBox.x = 1024;
battleBox.y = 1366;
battleBox.alpha = 0;
game.addChild(battleBox);
// Create heart for bullet hell
heart = new Heart();
heart.x = 1024;
heart.y = 1366;
heart.alpha = 0;
game.addChild(heart);
// Create item menu
itemMenu = new ItemMenu();
itemMenu.x = 1024;
itemMenu.y = 1366;
itemMenu.alpha = 0;
game.addChild(itemMenu);
// Create enemy dialog box
enemyDialogBox = LK.getAsset('enemyDialogBox', {
anchorX: 0.5,
anchorY: 0.5
});
enemyDialogBox.x = 1024;
enemyDialogBox.y = 800;
enemyDialogBox.alpha = 0;
game.addChild(enemyDialogBox);
// Create enemy dialog text
enemyDialogText = new Text2('', {
size: 32,
fill: 0xFFFFFF
});
enemyDialogText.anchor.set(0.5, 0.5);
enemyDialogText.x = 0;
enemyDialogText.y = 0;
enemyDialogBox.addChild(enemyDialogText);
// Functions
function startBattle() {
gameState = 'battle';
battlePhase = 'menu';
// Create enemy
var enemy = new Enemy('Dark Creature', 'enemy', 60, 12);
enemy.x = 1700;
enemy.y = 1366;
currentEnemies.push(enemy);
game.addChild(enemy);
// Show battle UI
for (var i = 0; i < menuButtons.length; i++) {
tween(menuButtons[i], {
alpha: 1
}, {
duration: 500
});
}
tween(battleBox, {
alpha: 0.3
}, {
duration: 500
});
}
function executePlayerAction() {
var target = currentEnemies[0];
if (!target) return;
switch (selectedAction) {
case 'FIGHT':
var damage = Math.floor(kris.atk + Math.random() * 10);
target.takeDamage(damage);
LK.getSound('attack').play();
showDialogue(kris.name + ' deals ' + damage + ' damage!');
break;
case 'ACT':
target.increaseMercy(25);
showDialogue(kris.name + ' tries to reason with ' + target.name);
break;
case 'ITEM':
// Item action is now handled by the ItemMenu class
showDialogue(kris.name + ' used an item!');
break;
case 'DEFEND':
kris.isDefending = true;
kris.gainTp(15);
showDialogue(kris.name + ' guards and gains TP!');
break;
case 'SPARE':
if (target.mercyLevel >= 100) {
target.isSpared = true;
showDialogue(target.name + ' was spared!');
currentEnemies = [];
target.destroy();
endBattle();
return;
} else {
showDialogue(target.name + ' is not ready to be spared.');
}
break;
}
LK.setTimeout(function () {
if (currentEnemies.length > 0 && !currentEnemies[0].isSpared) {
startEnemyTurn();
} else {
endBattle();
}
}, 2000);
}
function startEnemyTurn() {
battlePhase = 'bullet_hell';
// Show random enemy dialogue first
var randomDialogue = enemyDialogues[Math.floor(Math.random() * enemyDialogues.length)];
showEnemyDialogue(randomDialogue);
// Delay bullet hell start to show dialogue
LK.setTimeout(function () {
hideEnemyDialogue();
// Show heart and battle box
tween(heart, {
alpha: 1
}, {
duration: 300
});
tween(battleBox, {
alpha: 0.8
}, {
duration: 300
});
// Start bullet pattern
var bulletTimer = LK.setInterval(function () {
createBulletPattern();
}, 600);
// End bullet hell after 8 seconds (doubled duration)
LK.setTimeout(function () {
LK.clearInterval(bulletTimer);
endEnemyTurn();
}, 8000);
}, 2000); // Show dialogue for 2 seconds
}
var maxAttackPhases = 10;
function createBulletPattern() {
var centerX = battleBox.x;
var centerY = battleBox.y;
// Random attack phase selection
var attackPhase = Math.floor(Math.random() * maxAttackPhases);
switch (attackPhase) {
case 0:
// Original circular pattern
for (var i = 0; i < 8; i++) {
var angle = i / 8 * Math.PI * 2;
var bullet = new Bullet(4, angle);
bullet.x = centerX;
bullet.y = centerY;
bullets.push(bullet);
game.addChild(bullet);
}
break;
case 1:
// Spiral pattern with tween animation
for (var i = 0; i < 12; i++) {
var angle = i / 12 * Math.PI * 2;
var bullet = new Bullet(2, angle);
bullet.x = centerX;
bullet.y = centerY;
bullets.push(bullet);
game.addChild(bullet);
// Animate bullet in a spiral
tween(bullet, {
speed: 6
}, {
duration: 1000,
easing: tween.easeOut
});
}
break;
case 2:
// Wave pattern from sides
for (var i = 0; i < 6; i++) {
// Left side bullets
var leftBullet = new Bullet(3, 0); // Moving right
leftBullet.x = centerX - 280;
leftBullet.y = centerY - 150 + i * 60;
bullets.push(leftBullet);
game.addChild(leftBullet);
// Animate with sine wave motion
tween(leftBullet, {
direction: Math.PI / 4
}, {
duration: 800,
easing: tween.sinceOut
});
// Right side bullets
var rightBullet = new Bullet(3, Math.PI); // Moving left
rightBullet.x = centerX + 280;
rightBullet.y = centerY - 150 + i * 60;
bullets.push(rightBullet);
game.addChild(rightBullet);
// Animate with sine wave motion
tween(rightBullet, {
direction: Math.PI * 3 / 4
}, {
duration: 800,
easing: tween.sinceOut
});
}
break;
case 3:
// Expanding ring pattern
for (var ring = 0; ring < 3; ring++) {
for (var i = 0; i < 6; i++) {
var angle = i / 6 * Math.PI * 2;
var bullet = new Bullet(1, angle);
bullet.x = centerX;
bullet.y = centerY;
bullets.push(bullet);
game.addChild(bullet);
// Animate expanding rings with delay
tween(bullet, {
speed: 4 + ring * 2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function () {
// Change direction slightly for unpredictability
this.direction += (Math.random() - 0.5) * 0.5;
}.bind(bullet)
});
}
// Delay between rings
LK.setTimeout(function (ringIndex) {
return function () {
// Ring animation complete
};
}(ring), ring * 200);
}
break;
case 4:
// Cross pattern with rotating bullets
for (var i = 0; i < 4; i++) {
var angle = i * Math.PI / 2;
var bullet = new Bullet(3, angle);
bullet.x = centerX;
bullet.y = centerY;
bullets.push(bullet);
game.addChild(bullet);
// Rotate direction while moving
tween(bullet, {
direction: angle + Math.PI * 2
}, {
duration: 1500,
easing: tween.linear
});
}
// Add diagonal bullets
for (var i = 0; i < 4; i++) {
var angle = i * Math.PI / 2 + Math.PI / 4;
var bullet = new Bullet(2, angle);
bullet.x = centerX;
bullet.y = centerY;
bullets.push(bullet);
game.addChild(bullet);
tween(bullet, {
speed: 5
}, {
duration: 800,
easing: tween.easeInOut
});
}
break;
case 5:
// Zigzag pattern from corners
for (var corner = 0; corner < 4; corner++) {
var startX = centerX + (corner < 2 ? -250 : 250);
var startY = centerY + (corner % 2 === 0 ? -150 : 150);
var bullet = new Bullet(4, corner * Math.PI / 2);
bullet.x = startX;
bullet.y = startY;
bullets.push(bullet);
game.addChild(bullet);
// Create zigzag motion
tween(bullet, {
direction: bullet.direction + Math.PI / 3
}, {
duration: 400,
easing: tween.easeInOut,
onFinish: function () {
tween(this, {
direction: this.direction - Math.PI / 1.5
}, {
duration: 400,
easing: tween.easeInOut
});
}.bind(bullet)
});
}
break;
case 6:
// Bouncing bullets from walls
for (var i = 0; i < 8; i++) {
var side = i % 4; // 0=top, 1=right, 2=bottom, 3=left
var bullet = new Bullet(5, 0);
switch (side) {
case 0:
// Top
bullet.x = centerX - 200 + i / 4 * 400;
bullet.y = centerY - 180;
bullet.direction = Math.PI / 2;
break;
case 1:
// Right
bullet.x = centerX + 280;
bullet.y = centerY - 100 + i / 4 * 200;
bullet.direction = Math.PI;
break;
case 2:
// Bottom
bullet.x = centerX - 200 + i / 4 * 400;
bullet.y = centerY + 180;
bullet.direction = -Math.PI / 2;
break;
case 3:
// Left
bullet.x = centerX - 280;
bullet.y = centerY - 100 + i / 4 * 200;
bullet.direction = 0;
break;
}
bullets.push(bullet);
game.addChild(bullet);
// Add bouncing behavior
tween(bullet, {
speed: 3
}, {
duration: 1200,
easing: tween.bounceOut
});
}
break;
case 7:
// Converging then diverging pattern
for (var i = 0; i < 16; i++) {
var angle = i / 16 * Math.PI * 2;
var distance = 300;
var bullet = new Bullet(1, angle + Math.PI);
bullet.x = centerX + Math.cos(angle) * distance;
bullet.y = centerY + Math.sin(angle) * distance;
bullets.push(bullet);
game.addChild(bullet);
// First converge to center
tween(bullet, {
speed: 4
}, {
duration: 800,
easing: tween.easeIn,
onFinish: function () {
// Then diverge outward
tween(this, {
direction: this.direction + Math.PI,
speed: 6
}, {
duration: 600,
easing: tween.easeOut
});
}.bind(bullet)
});
}
break;
case 8:
// Horizontal laser sweeps
for (var i = 0; i < 2; i++) {
var laser = new LaserBullet(4, 0); // Moving right
laser.x = centerX - 300;
laser.y = centerY - 80 + i * 160;
bullets.push(laser);
game.addChild(laser);
// Animate speed increase
tween(laser, {
speed: 8
}, {
duration: 1000,
easing: tween.easeInOut
});
}
// Vertical laser sweeps
for (var i = 0; i < 2; i++) {
var laser = new LaserBullet(3, Math.PI / 2); // Moving down
laser.x = centerX - 50 + i * 100;
laser.y = centerY - 200;
bullets.push(laser);
game.addChild(laser);
// Animate with slight direction change
tween(laser, {
direction: Math.PI / 2 + 0.3
}, {
duration: 800,
easing: tween.easeInOut
});
}
break;
case 9:
// Rotating laser beams from center
for (var i = 0; i < 4; i++) {
var angle = i / 4 * Math.PI * 2;
var laser = new LaserBullet(2, angle);
laser.x = centerX;
laser.y = centerY;
bullets.push(laser);
game.addChild(laser);
// Rotate continuously while moving
tween(laser, {
direction: angle + Math.PI * 1.5,
speed: 5
}, {
duration: 1200,
easing: tween.linear
});
}
break;
}
}
function endEnemyTurn() {
battlePhase = 'menu';
// Hide heart and dim battle box
tween(heart, {
alpha: 0
}, {
duration: 300
});
tween(battleBox, {
alpha: 0.3
}, {
duration: 300
});
// Show menu buttons again
for (var i = 0; i < menuButtons.length; i++) {
tween(menuButtons[i], {
alpha: 1
}, {
duration: 500
});
}
kris.isDefending = false;
}
function endBattle() {
gameState = 'overworld';
// Hide battle UI
for (var i = 0; i < menuButtons.length; i++) {
tween(menuButtons[i], {
alpha: 0
}, {
duration: 500
});
}
tween(battleBox, {
alpha: 0
}, {
duration: 500
});
tween(heart, {
alpha: 0
}, {
duration: 500
});
hideDialogue();
// Clear bullets
for (var i = bullets.length - 1; i >= 0; i--) {
bullets[i].destroy();
bullets.splice(i, 1);
}
}
function showDialogue(text) {
dialogueText = text;
dialogueTextObj.setText(text);
tween(dialogueBox, {
alpha: 1
}, {
duration: 300
});
}
function showEnemyDialogue(text) {
enemyDialogText.setText(text);
// Change enemy sprite to talking version
if (currentEnemies.length > 0) {
var enemy = currentEnemies[0];
// Hide original sprite and show talking sprite
enemy.originalSprite = enemy.children[0];
enemy.originalSprite.alpha = 0;
var enemyTalkingSprite = LK.getAsset('enemyTalking', {
anchorX: 0.5,
anchorY: 0.5
});
enemyTalkingSprite.x = enemy.x;
enemyTalkingSprite.y = enemy.y;
enemy.addChild(enemyTalkingSprite);
enemy.talkingSprite = enemyTalkingSprite;
}
tween(enemyDialogBox, {
alpha: 1
}, {
duration: 300
});
}
function hideEnemyDialogue() {
// Restore original enemy sprite
if (currentEnemies.length > 0) {
var enemy = currentEnemies[0];
if (enemy.talkingSprite) {
enemy.talkingSprite.destroy();
enemy.talkingSprite = null;
}
if (enemy.originalSprite) {
enemy.originalSprite.alpha = 1;
}
}
tween(enemyDialogBox, {
alpha: 0
}, {
duration: 300
});
}
function hideDialogue() {
tween(dialogueBox, {
alpha: 0
}, {
duration: 300
});
}
function showDeathScreen() {
// Fade background to black
tween(game, {
backgroundColor: 0x000000
}, {
duration: 1000
});
// Make everything invisible except the heart
for (var i = 0; i < partyMembers.length; i++) {
tween(partyMembers[i], {
alpha: 0
}, {
duration: 1000
});
}
for (var i = 0; i < currentEnemies.length; i++) {
tween(currentEnemies[i], {
alpha: 0
}, {
duration: 1000
});
}
tween(battleBox, {
alpha: 0
}, {
duration: 1000
});
for (var i = 0; i < menuButtons.length; i++) {
tween(menuButtons[i], {
alpha: 0
}, {
duration: 1000
});
}
tween(dialogueBox, {
alpha: 0
}, {
duration: 1000
});
// Create two heart pieces
var heartLeft = LK.getAsset('heart', {
anchorX: 1,
anchorY: 0.5
});
heartLeft.x = heart.x;
heartLeft.y = heart.y;
heartLeft.width = heart.width / 2;
game.addChild(heartLeft);
var heartRight = LK.getAsset('heart', {
anchorX: 0,
anchorY: 0.5
});
heartRight.x = heart.x;
heartRight.y = heart.y;
heartRight.width = heart.width / 2;
game.addChild(heartRight);
// Hide original heart
heart.alpha = 0;
// Animate heart pieces splitting apart
tween(heartLeft, {
x: heart.x - 100,
rotation: -0.5
}, {
duration: 1500,
easing: tween.easeOut
});
tween(heartRight, {
x: heart.x + 100,
rotation: 0.5
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Show death dialogue and choices after heart split animation
LK.setTimeout(function () {
showDeathDialogue();
}, 500);
}
});
}
function showDeathDialogue() {
// Create death dialogue background
var deathDialogueBox = LK.getAsset('dialogBox', {
anchorX: 0.5,
anchorY: 0.5
});
deathDialogueBox.x = 1024;
deathDialogueBox.y = 1366;
deathDialogueBox.width = 1600;
deathDialogueBox.height = 600;
deathDialogueBox.tint = 0x000000;
game.addChild(deathDialogueBox);
// Create death dialogue text
var deathText = new Text2('Is this the end? You can keep going no matter what happens..', {
size: 48,
fill: 0xFFFFFF
});
deathText.anchor.set(0.5, 0.5);
deathText.x = 0;
deathText.y = -150;
deathDialogueBox.addChild(deathText);
// Create "..." button
var dotsButton = LK.getAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5
});
dotsButton.x = -200;
dotsButton.y = 100;
dotsButton.width = 300;
dotsButton.height = 80;
dotsButton.tint = 0x444444;
deathDialogueBox.addChild(dotsButton);
var dotsText = new Text2('...', {
size: 36,
fill: 0xFFFFFF
});
dotsText.anchor.set(0.5, 0.5);
dotsButton.addChild(dotsText);
// Create "Proceed" button
var proceedButton = LK.getAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5
});
proceedButton.x = 200;
proceedButton.y = 100;
proceedButton.width = 300;
proceedButton.height = 80;
proceedButton.tint = 0x444444;
deathDialogueBox.addChild(proceedButton);
var proceedText = new Text2('Proceed', {
size: 36,
fill: 0xFFFFFF
});
proceedText.anchor.set(0.5, 0.5);
proceedButton.addChild(proceedText);
// Handle "..." button click (death)
dotsButton.down = function (x, y, obj) {
// Hide dialogue and options immediately
deathDialogueBox.alpha = 0;
LK.setTimeout(function () {
LK.showGameOver();
}, 500);
};
// Handle "Proceed" button click (restart with flash)
proceedButton.down = function (x, y, obj) {
// Hide dialogue and options immediately
deathDialogueBox.alpha = 0;
// White flash effect
LK.effects.flashScreen(0xFFFFFF, 1000);
LK.setTimeout(function () {
// Restart the game by recreating the game state
restartGame();
}, 1000);
};
// Fade in the death dialogue
tween(deathDialogueBox, {
alpha: 1
}, {
duration: 1000
});
}
function restartGame() {
// Destroy current game elements
for (var i = 0; i < partyMembers.length; i++) {
partyMembers[i].destroy();
}
for (var i = 0; i < currentEnemies.length; i++) {
currentEnemies[i].destroy();
}
for (var i = bullets.length - 1; i >= 0; i--) {
bullets[i].destroy();
bullets.splice(i, 1);
}
// Reset game state
gameState = 'overworld';
currentEnemies = [];
partyMembers = [];
bullets = [];
selectedAction = null;
selectedTarget = null;
battlePhase = 'menu';
// Reset background color
game.setBackgroundColor(0x1a1a2e);
// Recreate party members
kris = new Character('Kris', 'kris');
kris.x = 300;
kris.y = 1366;
kris.hp = 100;
kris.tp = 0;
partyMembers.push(kris);
game.addChild(kris);
susie = new Character('Susie', 'susie');
susie.x = 300;
susie.y = 1000;
susie.atk = 15;
susie.hp = 120;
susie.maxHp = 120;
susie.tp = 0;
partyMembers.push(susie);
game.addChild(susie);
ralsei = new Character('Ralsei', 'ralsei');
ralsei.x = 300;
ralsei.y = 1732;
ralsei.mag = 15;
ralsei.hp = 80;
ralsei.maxHp = 80;
ralsei.tp = 0;
partyMembers.push(ralsei);
game.addChild(ralsei);
// Reset heart
heart.x = 1024;
heart.y = 1366;
heart.alpha = 0;
heart.graceTime = 0;
// Reset UI visibility
for (var i = 0; i < menuButtons.length; i++) {
menuButtons[i].alpha = 0;
}
battleBox.alpha = 0;
dialogueBox.alpha = 0;
enemyDialogBox.alpha = 0;
itemMenu.alpha = 0;
itemMenu.hide();
// Update TP bars
for (var i = 0; i < tpBars.length; i++) {
tpBars[i].fill.width = 0;
}
}
// Dragging variables
var dragTarget = null;
var dragOffset = {
x: 0,
y: 0
};
// Input handlers
game.down = function (x, y, obj) {
if (gameState === 'overworld') {
// Check if clicking on Kris for dragging
var distToKris = Math.sqrt(Math.pow(x - kris.x, 2) + Math.pow(y - kris.y, 2));
if (distToKris < 100) {
// Within dragging range
dragTarget = kris;
dragOffset.x = x - kris.x;
dragOffset.y = y - kris.y;
} else {
// Start battle when touching screen elsewhere
startBattle();
}
} else if (gameState === 'battle' && battlePhase === 'bullet_hell') {
// Move heart to touch position
var localPos = battleBox.toLocal({
x: x,
y: y
});
var boundedX = Math.max(-280, Math.min(280, localPos.x));
var boundedY = Math.max(-180, Math.min(180, localPos.y));
tween(heart, {
x: battleBox.x + boundedX,
y: battleBox.y + boundedY
}, {
duration: 100
});
}
};
game.up = function (x, y, obj) {
// Stop dragging when mouse/touch is released
dragTarget = null;
};
game.move = function (x, y, obj) {
if (gameState === 'overworld' && dragTarget) {
// Drag Kris around the screen
dragTarget.x = x - dragOffset.x;
dragTarget.y = y - dragOffset.y;
// Keep Kris within screen bounds
dragTarget.x = Math.max(50, Math.min(1998, dragTarget.x));
dragTarget.y = Math.max(50, Math.min(2682, dragTarget.y));
} else if (gameState === 'battle' && battlePhase === 'bullet_hell') {
// Move heart to cursor position within battle box bounds
var localPos = battleBox.toLocal({
x: x,
y: y
});
var boundedX = Math.max(-280, Math.min(280, localPos.x));
var boundedY = Math.max(-180, Math.min(180, localPos.y));
heart.x = battleBox.x + boundedX;
heart.y = battleBox.y + boundedY;
}
};
// Start music when game begins
LK.playMusic('World_Revolving');
// Main game update loop
game.update = function () {
// Update UI
hpText.setText('HP: ' + kris.hp + '/' + kris.maxHp);
tpText.setText('TP: ' + kris.tp + '/' + kris.maxTp);
// Update TP bars
for (var i = 0; i < tpBars.length; i++) {
var tpBar = tpBars[i];
var tpPercent = tpBar.character.tp / tpBar.character.maxTp;
tpBar.fill.width = 400 * tpPercent;
}
// Update bullets and check collisions
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
if (bullet.lastX === undefined) bullet.lastX = bullet.x;
if (bullet.lastY === undefined) bullet.lastY = bullet.y;
// Check if bullet is outside battle box
var distFromCenter = Math.sqrt(Math.pow(bullet.x - battleBox.x, 2) + Math.pow(bullet.y - battleBox.y, 2));
if (distFromCenter > 320) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
// Check collision with heart during bullet hell
if (gameState === 'battle' && battlePhase === 'bullet_hell' && heart.alpha > 0) {
if (bullet.intersects(heart)) {
var distance = Math.sqrt(Math.pow(bullet.x - heart.x, 2) + Math.pow(bullet.y - heart.y, 2));
if (distance < 40 && distance > 20) {
// Graze - gain TP
kris.gainTp(5);
LK.effects.flashObject(heart, 0x00FF00, 200);
} else if (distance <= 20) {
// Hit - take damage
if (heart.takeHit()) {
kris.takeDamage(10);
LK.getSound('damage').play();
LK.effects.flashScreen(0xFF0000, 300);
if (kris.hp <= 0) {
showDeathScreen();
}
}
}
}
}
bullet.lastX = bullet.x;
bullet.lastY = bullet.y;
}
};