Created
November 11, 2025 23:50
-
-
Save StringManolo/7a12afdf19d74b318284a720ed1e3dd5 to your computer and use it in GitHub Desktop.
Kimi K2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| export class BattleScene extends Phaser.Scene { | |
| constructor() { | |
| super({ key: 'BattleScene' }); | |
| } | |
| init(data) { | |
| this.playerData = data.playerData; | |
| this.onBattleEnd = data.onBattleEnd; | |
| this.terrain = data.terrain; | |
| // Initialize battle system | |
| this.battleSystem = null; | |
| this.battleMenu = null; | |
| this.isProcessingTurn = false; | |
| } | |
| preload() { | |
| // Load battle backgrounds | |
| this.load.image('battle_grass', 'assets/images/battles/battle_grass.png'); | |
| this.load.image('battle_forest', 'assets/images/battles/battle_forest.png'); | |
| this.load.image('battle_mountain', 'assets/images/battles/battle_mountain.png'); | |
| this.load.image('battle_dirt', 'assets/images/battles/battle_dirt.png'); | |
| // Load basic enemies | |
| this.load.image('goat', 'assets/images/enemies/goat.png'); | |
| this.load.image('war_dwarf', 'assets/images/enemies/war_dwarf.png'); | |
| this.load.image('snake', 'assets/images/enemies/snake.png'); | |
| this.load.image('wolf', 'assets/images/enemies/wolf.png'); | |
| this.load.image('fly', 'assets/images/enemies/fly.png'); | |
| this.load.image('war_blob', 'assets/images/enemies/war_blob.png'); | |
| this.load.image('war_orc', 'assets/images/enemies/war_orc.png'); | |
| this.load.image('magic_demon', 'assets/images/enemies/magic_demon.png'); | |
| // Warrior attack animation frames | |
| this.load.image("warrior_basic_attack", "assets/images/battleAnimations/warrior_basic_1.png"); | |
| this.load.image("warrior_basic_attack_2", "assets/images/battleAnimations/warrior_basic_2.png"); | |
| this.load.image("warrior_basic_attack_3", "assets/images/battleAnimations/warrior_basic_3.png"); | |
| this.load.image("warrior_basic_attack_4", "assets/images/battleAnimations/warrior_basic_4.png"); | |
| // Sound effect for attack | |
| this.load.audio("warrior_slash", "assets/audio/warrior_slash.wav"); | |
| // Battle music | |
| this.load.audio("battle_music", "assets/audio/battle.mp3"); | |
| } | |
| create() { | |
| let backgroundKey = "battle_grass"; | |
| const terrainMap = { | |
| 'grass': 'battle_grass', | |
| 'forest': 'battle_forest', | |
| 'mountain': 'battle_mountain', | |
| 'path': 'battle_dirt', | |
| 'water': 'battle_grass' | |
| }; | |
| if (this.terrain && terrainMap[this.terrain]) { | |
| backgroundKey = terrainMap[this.terrain]; | |
| } | |
| // Background | |
| const background = this.add.image(400, 300, backgroundKey); | |
| background.setDisplaySize(800, 600); | |
| // Setup battle units | |
| this.setupBattleUnits(); | |
| // Create UI elements | |
| this.createBattleUI(); | |
| // Initialize battle system | |
| this.battleSystem = new BattleSystem(this); | |
| // Remove old click handler | |
| this.input.off('pointerdown'); | |
| // Play battle music | |
| this.sound.play('battle_music', { loop: true }); | |
| } | |
| setupBattleUnits() { | |
| // Get enemy configuration | |
| this.enemyConfig = this.getEnemyForTerrain(this.terrain); | |
| // Create enemy unit with stats | |
| this.enemyUnit = new BattleUnit({ | |
| name: this.enemyConfig.name, | |
| key: this.enemyConfig.key, | |
| maxHp: this.getEnemyStats(this.enemyConfig.key).hp, | |
| attack: this.getEnemyStats(this.enemyConfig.key).attack, | |
| defense: this.getEnemyStats(this.enemyConfig.key).defense, | |
| speed: this.getEnemyStats(this.enemyConfig.key).speed, | |
| isPlayer: false | |
| }); | |
| // Create player unit with stats from data or defaults | |
| const playerStats = this.getPlayerStats(); | |
| this.playerUnit = new BattleUnit({ | |
| name: playerStats.name || 'Warrior', | |
| key: 'warrior_basic_attack', | |
| maxHp: playerStats.maxHp, | |
| maxMp: playerStats.maxMp || 50, | |
| attack: playerStats.attack, | |
| defense: playerStats.defense, | |
| magic: playerStats.magic || 15, | |
| speed: playerStats.speed, | |
| isPlayer: true | |
| }); | |
| // Add enemy sprite | |
| this.enemy = this.add.image(400, 330, this.enemyConfig.key); | |
| this.enemy.setDisplaySize(175, 175); | |
| // Add player sprite | |
| this.warrior = this.add.sprite(400, 650, 'warrior_basic_attack'); | |
| this.warrior.setOrigin(0.5, 1); | |
| this.warrior.setDisplaySize(175, 175); | |
| this.warrior.setDepth(2); | |
| this.isAttacking = false; | |
| } | |
| getPlayerStats() { | |
| const defaults = { | |
| name: 'Warrior', | |
| maxHp: 500, | |
| maxMp: 50, | |
| attack: 75, | |
| defense: 45, | |
| magic: 15, | |
| speed: 25 | |
| }; | |
| if (!this.playerData) return defaults; | |
| return { | |
| name: this.playerData.name || defaults.name, | |
| maxHp: this.playerData.maxHp || defaults.maxHp, | |
| maxMp: this.playerData.maxMp || defaults.maxMp, | |
| attack: this.playerData.attack || defaults.attack, | |
| defense: this.playerData.defense || defaults.defense, | |
| magic: this.playerData.magic || defaults.magic, | |
| speed: this.playerData.speed || defaults.speed, | |
| currentHp: this.playerData.currentHp || this.playerData.maxHp || defaults.maxHp, | |
| currentMp: this.playerData.currentMp || this.playerData.maxMp || defaults.maxMp | |
| }; | |
| } | |
| getEnemyStats(enemyKey) { | |
| const enemyStats = { | |
| 'goat': { hp: 200, attack: 40, defense: 20, speed: 35 }, | |
| 'war_dwarf': { hp: 350, attack: 60, defense: 50, speed: 15 }, | |
| 'snake': { hp: 150, attack: 35, defense: 15, speed: 40 }, | |
| 'wolf': { hp: 250, attack: 50, defense: 25, speed: 30 }, | |
| 'fly': { hp: 100, attack: 25, defense: 10, speed: 45 }, | |
| 'war_blob': { hp: 400, attack: 45, defense: 40, speed: 10 }, | |
| 'war_orc': { hp: 450, attack: 70, defense: 45, speed: 20 }, | |
| 'magic_demon': { hp: 600, attack: 80, defense: 60, speed: 25 } | |
| }; | |
| return enemyStats[enemyKey] || enemyStats['goat']; | |
| } | |
| createBattleUI() { | |
| // Create menu background with Graphics | |
| const menuGraphics = this.add.graphics(); | |
| menuGraphics.fillStyle(0x000000, 0.85); | |
| menuGraphics.fillRoundedRect(10, 440, 780, 150, 8); | |
| menuGraphics.lineStyle(2, 0xffffff, 1); | |
| menuGraphics.strokeRoundedRect(10, 440, 780, 150, 8); | |
| this.menuBg = menuGraphics; | |
| this.menuBg.setDepth(10); | |
| this.menuBg.setVisible(false); | |
| // Create HP Bars | |
| this.createHPBars(); | |
| // Create ATB Bars | |
| this.createATBBars(); | |
| // Create Battle Menu | |
| this.createBattleMenu(); | |
| // Battle log | |
| this.battleLog = this.add.text(10, 10, '', { | |
| fontSize: '16px', | |
| fill: '#ffffff', | |
| backgroundColor: '#000000', | |
| padding: { x: 10, y: 5 } | |
| }); | |
| this.battleLog.setDepth(10); | |
| } | |
| createHPBars() { | |
| const playerHpX = 100; | |
| const playerHpY = 450; | |
| const hpBarWidth = 150; | |
| const hpBarHeight = 20; | |
| // Player HP Bar Background | |
| this.playerHpBarBg = this.add.rectangle(playerHpX, playerHpY, hpBarWidth, hpBarHeight, 0x333333); | |
| this.playerHpBarBg.setOrigin(0.5); | |
| this.playerHpBarBg.setDepth(10); | |
| // Player HP Bar | |
| this.playerHpBar = this.add.rectangle(playerHpX - hpBarWidth / 2, playerHpY, hpBarWidth, hpBarHeight, 0x00ff00); | |
| this.playerHpBar.setOrigin(0, 0.5); | |
| this.playerHpBar.setDepth(11); | |
| this.playerHpText = this.add.text(playerHpX, playerHpY - 20, '', { | |
| fontSize: '14px', | |
| fill: '#ffffff' | |
| }).setOrigin(0.5).setDepth(12); | |
| // Enemy HP Bar | |
| const enemyHpX = 400; | |
| const enemyHpY = 250; | |
| const enemyHpBarWidth = 150; | |
| const enemyHpBarHeight = 15; | |
| this.enemyHpBarBg = this.add.rectangle(enemyHpX, enemyHpY, enemyHpBarWidth, enemyHpBarHeight, 0x333333); | |
| this.enemyHpBarBg.setOrigin(0.5); | |
| this.enemyHpBarBg.setDepth(10); | |
| this.enemyHpBar = this.add.rectangle(enemyHpX - enemyHpBarWidth / 2, enemyHpY, enemyHpBarWidth, enemyHpBarHeight, 0xff0000); | |
| this.enemyHpBar.setOrigin(0, 0.5); | |
| this.enemyHpBar.setDepth(11); | |
| this.enemyHpText = this.add.text(enemyHpX, enemyHpY - 15, '', { | |
| fontSize: '12px', | |
| fill: '#ffffff' | |
| }).setOrigin(0.5).setDepth(12); | |
| this.updateHPBars(); | |
| } | |
| createATBBars() { | |
| const playerAtbX = 100; | |
| const playerAtbY = 480; | |
| const atbBarWidth = 150; | |
| const atbBarHeight = 10; | |
| // Player ATB Bar Background | |
| this.playerAtbBarBg = this.add.rectangle(playerAtbX, playerAtbY, atbBarWidth, atbBarHeight, 0x222222); | |
| this.playerAtbBarBg.setOrigin(0.5); | |
| this.playerAtbBarBg.setDepth(10); | |
| // Player ATB Bar | |
| this.playerAtbBar = this.add.rectangle(playerAtbX - atbBarWidth / 2, playerAtbY, atbBarWidth, atbBarHeight, 0x00ff00); | |
| this.playerAtbBar.setOrigin(0, 0.5); | |
| this.playerAtbBar.setDepth(11); | |
| // Enemy ATB Bar | |
| const enemyAtbX = 400; | |
| const enemyAtbY = 270; | |
| const enemyAtbBarWidth = 150; | |
| const enemyAtbBarHeight = 10; | |
| this.enemyAtbBarBg = this.add.rectangle(enemyAtbX, enemyAtbY, enemyAtbBarWidth, enemyAtbBarHeight, 0x222222); | |
| this.enemyAtbBarBg.setOrigin(0.5); | |
| this.enemyAtbBarBg.setDepth(10); | |
| this.enemyAtbBar = this.add.rectangle(enemyAtbX - enemyAtbBarWidth / 2, enemyAtbY, enemyAtbBarWidth, enemyAtbBarHeight, 0xff0000); | |
| this.enemyAtbBar.setOrigin(0, 0.5); | |
| this.enemyAtbBar.setDepth(11); | |
| } | |
| createBattleMenu() { | |
| this.menuOptions = ['Attack', 'Magic', 'Ability', 'Defend', 'Items', 'Flee']; | |
| this.menuIndex = 0; | |
| this.menuTexts = []; | |
| this.menuVisible = false; | |
| for (let i = 0; i < this.menuOptions.length; i++) { | |
| const text = this.add.text(200 + (i % 3) * 150, 470 + Math.floor(i / 3) * 30, | |
| this.menuOptions[i], { | |
| fontSize: '18px', | |
| fill: '#ffffff', | |
| backgroundColor: '#333333', | |
| padding: { x: 10, y: 5 } | |
| }); | |
| text.setInteractive(); | |
| text.setDepth(12); | |
| text.setVisible(false); | |
| text.on('pointerover', () => { | |
| if (this.menuVisible) text.setBackgroundColor('#666666'); | |
| }); | |
| text.on('pointerout', () => { | |
| if (this.menuVisible) text.setBackgroundColor('#333333'); | |
| }); | |
| text.on('pointerdown', () => { | |
| if (this.menuVisible) this.selectMenuOption(i); | |
| }); | |
| this.menuTexts.push(text); | |
| } | |
| } | |
| showBattleMenu() { | |
| this.menuVisible = true; | |
| this.menuBg.setVisible(true); | |
| this.menuTexts.forEach(text => text.setVisible(true)); | |
| this.updateMenuSelection(); | |
| } | |
| hideBattleMenu() { | |
| this.menuVisible = false; | |
| this.menuBg.setVisible(false); | |
| this.menuTexts.forEach(text => text.setVisible(false)); | |
| } | |
| updateMenuSelection() { | |
| this.menuTexts.forEach((text, index) => { | |
| if (index === this.menuIndex) { | |
| text.setBackgroundColor('#888888'); | |
| } else { | |
| text.setBackgroundColor('#333333'); | |
| } | |
| }); | |
| } | |
| selectMenuOption(index) { | |
| if (this.isProcessingTurn) return; | |
| const option = this.menuOptions[index]; | |
| this.hideBattleMenu(); | |
| this.isProcessingTurn = true; | |
| switch (option) { | |
| case 'Attack': | |
| this.executeAttack(); | |
| break; | |
| case 'Magic': | |
| this.executeMagic(); | |
| break; | |
| case 'Ability': | |
| this.executeAbility(); | |
| break; | |
| case 'Defend': | |
| this.executeDefend(); | |
| break; | |
| case 'Items': | |
| this.executeItems(); | |
| break; | |
| case 'Flee': | |
| this.executeFlee(); | |
| break; | |
| } | |
| } | |
| executeAttack() { | |
| this.isAttacking = true; | |
| const originalX = this.warrior.x; | |
| const originalY = this.warrior.y; | |
| this.tweens.add({ | |
| targets: this.warrior, | |
| x: 400, | |
| y: 400, | |
| displayWidth: 175 * 0.7, | |
| displayHeight: 175 * 0.7, | |
| duration: 200, | |
| onComplete: () => { | |
| this.warrior.setTexture('warrior_basic_attack_2'); | |
| this.time.delayedCall(25, () => { | |
| this.warrior.setTexture('warrior_basic_attack_3'); | |
| this.sound.play('warrior_slash', { volume: 0.8 }); | |
| // Calculate damage | |
| const damage = this.calculateDamage(this.playerUnit, this.enemyUnit, 'physical'); | |
| this.enemyUnit.currentHp = Math.max(0, this.enemyUnit.currentHp - damage); | |
| this.updateHPBars(); | |
| this.showDamageNumber(damage, 400, 330, false); | |
| this.time.delayedCall(20, () => { | |
| this.warrior.setTexture('warrior_basic_attack_4'); | |
| this.time.delayedCall(60, () => { | |
| this.warrior.setTexture('warrior_basic_attack'); | |
| this.tweens.add({ | |
| targets: this.warrior, | |
| x: originalX, | |
| y: originalY, | |
| displayWidth: 175, | |
| displayHeight: 175, | |
| duration: 200, | |
| onComplete: () => { | |
| this.isAttacking = false; | |
| this.endTurn(); | |
| } | |
| }); | |
| }); | |
| }); | |
| }); | |
| } | |
| }); | |
| } | |
| executeMagic() { | |
| this.logMessage(`${this.playerUnit.name} casts a spell!`); | |
| this.time.delayedCall(1000, () => this.endTurn()); | |
| } | |
| executeAbility() { | |
| this.logMessage(`${this.playerUnit.name} uses a special ability!`); | |
| this.time.delayedCall(1000, () => this.endTurn()); | |
| } | |
| executeDefend() { | |
| this.logMessage(`${this.playerUnit.name} is defending!`); | |
| this.playerUnit.isDefending = true; | |
| this.time.delayedCall(500, () => this.endTurn()); | |
| } | |
| executeItems() { | |
| this.logMessage(`${this.playerUnit.name} uses an item!`); | |
| this.time.delayedCall(1000, () => this.endTurn()); | |
| } | |
| executeFlee() { | |
| this.logMessage(`${this.playerUnit.name} attempts to flee!`); | |
| const fleeChance = 0.6; | |
| const success = Math.random() < fleeChance; | |
| if (success) { | |
| this.logMessage('Fled successfully!'); | |
| this.time.delayedCall(1000, () => this.endBattle(false, true)); | |
| } else { | |
| this.logMessage("Couldn't escape!"); | |
| this.time.delayedCall(1000, () => this.endTurn()); | |
| } | |
| } | |
| enemyTurn() { | |
| this.logMessage(`${this.enemyUnit.name} attacks!`); | |
| this.time.delayedCall(500, () => { | |
| const damage = this.calculateDamage(this.enemyUnit, this.playerUnit, 'physical'); | |
| this.playerUnit.currentHp = Math.max(0, this.playerUnit.currentHp - damage); | |
| this.updateHPBars(); | |
| this.showDamageNumber(damage, 400, 650, true); | |
| this.time.delayedCall(1000, () => this.endTurn()); | |
| }); | |
| } | |
| calculateDamage(attacker, defender, type) { | |
| const baseDamage = attacker.attack; | |
| const defense = defender.defense * (defender.isDefending ? 1.5 : 1); | |
| const variance = 0.85 + Math.random() * 0.3; | |
| let damage = Math.floor((baseDamage * variance) - defense); | |
| damage = Math.max(1, damage); | |
| return damage; | |
| } | |
| showDamageNumber(damage, x, y, isPlayerDamage) { | |
| const damageText = this.add.text(x, y - 50, `-${damage}`, { | |
| fontSize: '24px', | |
| fill: isPlayerDamage ? '#ff0000' : '#ffff00', | |
| stroke: '#000000', | |
| strokeThickness: 4 | |
| }).setOrigin(0.5); | |
| this.tweens.add({ | |
| targets: damageText, | |
| y: y - 100, | |
| alpha: 0, | |
| duration: 1000, | |
| onComplete: () => damageText.destroy() | |
| }); | |
| } | |
| updateHPBars() { | |
| // Player HP | |
| const playerHpPercent = this.playerUnit.currentHp / this.playerUnit.maxHp; | |
| this.playerHpBar.width = 150 * playerHpPercent; | |
| this.playerHpText.setText(`${this.playerUnit.currentHp}/${this.playerUnit.maxHp}`); | |
| // Enemy HP | |
| const enemyHpPercent = this.enemyUnit.currentHp / this.enemyUnit.maxHp; | |
| this.enemyHpBar.width = 150 * enemyHpPercent; | |
| this.enemyHpText.setText(`${this.enemyUnit.currentHp}/${this.enemyUnit.maxHp}`); | |
| } | |
| updateATBBars() { | |
| if (!this.battleSystem || this.isProcessingTurn) return; | |
| // Player ATB | |
| const playerAtbPercent = this.battleSystem.getATBPercent(this.playerUnit); | |
| this.playerAtbBar.width = 150 * playerAtbPercent; | |
| // Enemy ATB | |
| const enemyAtbPercent = this.battleSystem.getATBPercent(this.enemyUnit); | |
| this.enemyAtbBar.width = 150 * enemyAtbPercent; | |
| } | |
| logMessage(message) { | |
| this.battleLog.setText(message); | |
| this.time.delayedCall(2000, () => { | |
| if (this.battleLog.text === message) { | |
| this.battleLog.setText(''); | |
| } | |
| }); | |
| } | |
| endTurn() { | |
| // Reset defending status | |
| this.playerUnit.isDefending = false; | |
| this.enemyUnit.isDefending = false; | |
| // Reset ATB | |
| if (this.battleSystem) { | |
| this.battleSystem.resetATB(this.playerUnit); | |
| this.battleSystem.resetATB(this.enemyUnit); | |
| } | |
| this.isProcessingTurn = false; | |
| // Check for battle end | |
| if (this.playerUnit.currentHp <= 0) { | |
| this.endBattle(false, false); | |
| } else if (this.enemyUnit.currentHp <= 0) { | |
| this.endBattle(true, false); | |
| } | |
| } | |
| endBattle(victory, fled) { | |
| this.sound.stopAll(); | |
| this.scene.stop(); | |
| if (this.onBattleEnd) { | |
| const result = { | |
| victory: victory, | |
| fled: fled, | |
| experience: victory ? this.enemyUnit.maxHp : 0, | |
| gold: victory ? Math.floor(this.enemyUnit.maxHp / 5) : 0, | |
| enemy: this.enemyUnit.name, | |
| playerStats: { | |
| currentHp: this.playerUnit.currentHp, | |
| currentMp: this.playerUnit.currentMp | |
| } | |
| }; | |
| this.onBattleEnd(result); | |
| } | |
| } | |
| update() { | |
| if (this.battleSystem && !this.isProcessingTurn) { | |
| this.battleSystem.update(); | |
| this.updateATBBars(); | |
| // Check if player ATB is full and menu is not shown | |
| if (this.battleSystem.isATBFull(this.playerUnit) && !this.menuVisible) { | |
| this.showBattleMenu(); | |
| } | |
| // Check if enemy ATB is full | |
| if (this.battleSystem.isATBFull(this.enemyUnit) && !this.isProcessingTurn) { | |
| this.isProcessingTurn = true; | |
| this.hideBattleMenu(); | |
| this.enemyTurn(); | |
| } | |
| } | |
| } | |
| getEnemyForTerrain(terrain) { | |
| const enemyPools = { | |
| 'mountain': [ | |
| { key: 'goat', name: 'Mountain Goat', weight: 35 }, | |
| { key: 'war_dwarf', name: 'War Dwarf', weight: 30 }, | |
| { key: 'war_blob', name: 'War Blob', weight: 20 }, | |
| { key: 'magic_demon', name: 'Magic Demon', weight: 5 }, | |
| { key: 'wolf', name: 'Wolf', weight: 10 } | |
| ], | |
| 'forest': [ | |
| { key: 'snake', name: 'Forest Snake', weight: 40 }, | |
| { key: 'wolf', name: 'Wolf', weight: 35 }, | |
| { key: 'fly', name: 'Giant Fly', weight: 15 }, | |
| { key: 'magic_demon', name: 'Magic Demon', weight: 5 }, | |
| { key: 'war_orc', name: 'Forest Orc', weight: 5 } | |
| ], | |
| 'grass': [ | |
| { key: 'fly', name: 'Giant Fly', weight: 40 }, | |
| { key: 'wolf', name: 'Wolf', weight: 30 }, | |
| { key: 'snake', name: 'Snake', weight: 15 }, | |
| { key: 'magic_demon', name: 'Magic Demon', weight: 5 }, | |
| { key: 'goat', name: 'Goat', weight: 10 } | |
| ], | |
| 'path': [ | |
| { key: 'war_orc', name: 'Orc Warrior', weight: 40 }, | |
| { key: 'fly', name: 'Giant Fly', weight: 25 }, | |
| { key: 'wolf', name: 'Wolf', weight: 20 }, | |
| { key: 'magic_demon', name: 'Magic Demon', weight: 5 }, | |
| { key: 'snake', name: 'Snake', weight: 10 } | |
| ], | |
| 'water': [ | |
| { key: 'fly', name: 'Giant Fly', weight: 40 }, | |
| { key: 'snake', name: 'Water Snake', weight: 30 }, | |
| { key: 'magic_demon', name: 'Magic Demon', weight: 10 }, | |
| { key: 'wolf', name: 'Wolf', weight: 20 } | |
| ] | |
| }; | |
| const pool = enemyPools[terrain] || enemyPools['grass']; | |
| return this.selectRandomEnemy(pool); | |
| } | |
| selectRandomEnemy(enemyPool) { | |
| const totalWeight = enemyPool.reduce((sum, enemy) => sum + enemy.weight, 0); | |
| let random = Math.random() * totalWeight; | |
| let weightSum = 0; | |
| for (const enemy of enemyPool) { | |
| weightSum += enemy.weight; | |
| if (random <= weightSum) { | |
| return enemy; | |
| } | |
| } | |
| return enemyPool[0]; | |
| } | |
| } | |
| // Battle Unit Class | |
| class BattleUnit { | |
| constructor(config) { | |
| this.name = config.name; | |
| this.key = config.key; | |
| this.maxHp = config.maxHp; | |
| this.currentHp = config.currentHp || config.maxHp; | |
| this.maxMp = config.maxMp || 0; | |
| this.currentMp = config.currentMp || config.maxMp || 0; | |
| this.attack = config.attack; | |
| this.defense = config.defense; | |
| this.magic = config.magic || 0; | |
| this.speed = config.speed; | |
| this.isPlayer = config.isPlayer; | |
| this.isDefending = false; | |
| this.atbValue = 0; | |
| } | |
| } | |
| // Battle System Class | |
| class BattleSystem { | |
| constructor(scene) { | |
| this.scene = scene; | |
| this.maxATB = 1000; | |
| this.isPaused = false; | |
| } | |
| update() { | |
| if (this.isPaused) return; | |
| // Update player ATB | |
| if (this.scene.playerUnit.currentHp > 0 && !this.isATBFull(this.scene.playerUnit)) { | |
| this.scene.playerUnit.atbValue += this.scene.playerUnit.speed; | |
| } | |
| // Update enemy ATB | |
| if (this.scene.enemyUnit.currentHp > 0 && !this.isATBFull(this.scene.enemyUnit)) { | |
| this.scene.enemyUnit.atbValue += this.scene.enemyUnit.speed; | |
| } | |
| } | |
| isATBFull(unit) { | |
| return unit.atbValue >= this.maxATB; | |
| } | |
| getATBPercent(unit) { | |
| return Math.min(1, unit.atbValue / this.maxATB); | |
| } | |
| resetATB(unit) { | |
| unit.atbValue = 0; | |
| } | |
| pause() { | |
| this.isPaused = true; | |
| } | |
| resume() { | |
| this.isPaused = false; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment