const Phaser = require('phaser'); const { DELAYS, TEXT, POSITIONS: { COMBAT }, COLOURS } = require('./constants'); const calcMargin = () => { const CRYP_MARGIN = COMBAT.height() / 5; const TEXT_MARGIN = COMBAT.height() / 35; const TEAM_MARGIN = COMBAT.width() * 0.7; const X_PADDING = COMBAT.width() / 10; const Y_PADDING = COMBAT.height() / 7; return { CRYP_MARGIN, TEXT_MARGIN, TEAM_MARGIN, X_PADDING, Y_PADDING }; }; const healthBarDimensions = (team, iter) => { const { TEAM_MARGIN, TEXT_MARGIN, CRYP_MARGIN } = calcMargin(); const healthBarX = 1.25 * TEAM_MARGIN * team; const healthBarY = COMBAT.y() + TEXT_MARGIN + CRYP_MARGIN * iter + COMBAT.height() * 0.07; const healthBarWidth = TEAM_MARGIN / 10; const healthBarHeight = TEXT_MARGIN / 1.5; return { healthBarX, healthBarY, healthBarWidth, healthBarHeight }; }; const crypAvatarText = (team, iter) => { const { TEAM_MARGIN, CRYP_MARGIN, TEXT_MARGIN } = calcMargin(); const nameTextX = 1.25 * TEAM_MARGIN * team; const nameTextY = COMBAT.y() + CRYP_MARGIN * iter + COMBAT.height() * 0.07; const healthTextX = 1.25 * TEAM_MARGIN * team; const healthTextY = COMBAT.y() + TEXT_MARGIN * 2 + CRYP_MARGIN * iter + COMBAT.height() * 0.07; return { nameTextX, nameTextY, healthTextX, healthTextY }; }; const skillTextPosition = (crypIter, skillIter) => { const { TEXT_MARGIN } = calcMargin(); const skillTextX = 0.15 * COMBAT.width() * crypIter; const skillTextY = COMBAT.y() + COMBAT.height() * 0.7 + TEXT_MARGIN * skillIter; return [skillTextX, skillTextY]; }; const crypPosition = (team, iter) => { const { CRYP_MARGIN, TEAM_MARGIN, Y_PADDING } = calcMargin(); const crypAvatarX = COMBAT.width() / 8 + TEAM_MARGIN * team; const crypAvatarY = Y_PADDING * 1.25 + CRYP_MARGIN * iter; return { crypAvatarX, crypAvatarY }; }; class CrypImage extends Phaser.GameObjects.Image { constructor(scene, team, iter, skills, avatar, cryp, healthbar) { // Avatar will be a property of cryp const { crypAvatarX, crypAvatarY } = crypPosition(team, iter); super(scene, crypAvatarX, crypAvatarY, avatar); this.scene = scene; this.cryp = cryp; this.skills = skills; this.healthbar = healthbar; } clickHandler() { const activeSkill = this.scene.registry.get('activeSkill'); const game = this.scene.registry.get('game'); if (activeSkill) { if (activeSkill.cryp.account !== this.cryp.account) { const ws = this.scene.registry.get('ws'); if (game.phase === 'Skill') { ws.sendGameSkill(game.id, activeSkill.cryp.id, this.cryp.account, activeSkill.skill.skill); } else if (game.phase === 'Target') { ws.sendGameTarget(game.id, this.cryp.id, activeSkill.skill.id); } } activeSkill.clearTint(); this.scene.registry.set('activeSkill', null); this.scene.registry.set('activeCryp', null); } } takeDamage(damage) { this.setTint(0xff0000); this.healthbar.takeDamage(damage); this.scene.time.delayedCall(DELAYS.DAMAGE_TICK, () => { this.clearTint(); }); } } class CrypSkill extends Phaser.GameObjects.Text { constructor(scene, x, y, team, skill, cryp) { // Avatar will be a property of cryp super(scene, x, y, skill.skill, TEXT.NORMAL); this.cryp = cryp; this.skill = skill; this.setInteractive(); } clickHandler() { const activeSkill = this.scene.registry.get('activeSkill'); if (activeSkill) { activeSkill.clearTint(); } this.scene.registry.set('activeSkill', this); this.setTint(COLOURS.BLUE); } } class HealthBar extends Phaser.GameObjects.Graphics { constructor(scene, cryp, team, iter, crypHpText) { super(scene); this.team = team; this.iter = iter; this.hp = cryp.hp.base; this.stam = cryp.stamina.base; this.hpText = crypHpText; this.drawHealthBar(); } drawHealthBar() { const { healthBarX, healthBarY, healthBarWidth, healthBarHeight } = healthBarDimensions(this.team, this.iter); // Draw Black Border this.fillStyle(COLOURS.BLACK); this.fillRect(healthBarX, healthBarY, healthBarWidth, healthBarHeight); // White fill this.fillStyle(COLOURS.WHITE); this.fillRect(healthBarX + 2, healthBarY + 2, healthBarWidth - 4, healthBarHeight - 4); const healthPercentage = this.hp / this.stam; if (healthPercentage < 0.3) { this.fillStyle(COLOURS.RED); } else if (healthPercentage < 0.65) { this.fillStyle(COLOURS.YELLOW); } else { this.fillStyle(0x00ff00); // str8 up green } const healthWidth = Math.floor(healthBarWidth * healthPercentage); this.fillRect(healthBarX + 2, healthBarY + 2, healthWidth, healthBarHeight - 4); } takeDamage(damage) { this.hp -= damage; this.hpText.text = `${this.hp.toString()} / ${this.stam.toString()} HP`; this.clear(); this.drawHealthBar(); } } function renderCryp(scene, group, cryp, skills, game, team, iter) { // Add Image Avatar Class const avatar = team ? 'magmar' : 'alk'; // Add cryp hp const { nameTextX, nameTextY, healthTextX, healthTextY } = crypAvatarText(team, iter); const crypName = scene.add.text(nameTextX, nameTextY, cryp.name, TEXT.NORMAL); const crypHpText = scene.add.text(healthTextX, healthTextY, `${cryp.hp.base.toString()} / ${cryp.stamina.base.toString()} HP`, TEXT.NORMAL); const healthBar = scene.add.existing(new HealthBar(scene, cryp, team, iter, crypHpText)); // Add cryp name const crypSpawn = scene.add.existing(new CrypImage(scene, team, iter, skills, avatar, cryp, healthBar)) .setScale(0.5) .setInteractive(); group.addMultiple([crypHpText, healthBar, crypSpawn, crypName]); return crypSpawn; } function renderSkills(scene, group, cryp, account, game, team, iter) { const nameTextPosition = skillTextPosition(iter, 0); const skillList = []; if (scene.registry.get('resolve')) return true; if (game.phase === 'Skill' && cryp.account === account.id) { if (cryp.hp.base === 0) return true; const crypName = scene.add.text(nameTextPosition[0], nameTextPosition[1], cryp.name, TEXT.HEADER); crypName.text = cryp.name; cryp.skills.forEach((skill, i) => { const skillText = skillTextPosition(iter, i + 2); const skillObj = new CrypSkill(scene, skillText[0], skillText[1], team, skill, cryp); scene.add.existing(skillObj); skillList.push(skillObj); group.addMultiple([crypName, skillObj]); }); } else if (game.phase === 'Target' && cryp.account !== account.id) { const blockSkill = game.stack.find(skill => skill.source_cryp_id === cryp.id); // cryp not casting this turn if (!blockSkill) return false; const crypName = scene.add.text(nameTextPosition[0], nameTextPosition[1], cryp.name, TEXT.HEADER); const skillText = skillTextPosition(iter, 2); const skillObj = new CrypSkill(scene, skillText[0], skillText[1], team, blockSkill, cryp); scene.add.existing(skillObj); skillList.push(skillObj); group.addMultiple([crypName, skillObj]); } return skillList; } class DrawCrypTeams extends Phaser.GameObjects.Group { constructor(scene, game) { super(scene); this.scene = scene; this.keyboard = scene.input.keyboard; let allyCount = 0; let enemyCount = 0; const account = scene.registry.get('account'); scene.cryps.forEach((cryp) => { const team = cryp.account === account.id ? 0 : 1; const iter = cryp.account === account.id ? allyCount : enemyCount; const skillsObj = renderSkills(scene, this, cryp, account, game, team, iter); const crypObj = renderCryp(scene, this, cryp, skillsObj, game, team, iter); allyCount = cryp.account === account.id ? allyCount += 1 : enemyCount += 1; const addKeys = (game.phase === 'Skill' && !team) || (game.phase === 'Target' && team); if (addKeys) scene.crypKeyHandler(crypObj, iter); }); } } module.exports = { CrypImage, CrypSkill, DrawCrypTeams, renderCryp };