Skip to main content

Overview

The essence system in Elemental Battlecards tracks which elemental types have been activated through direct attacks. Each player has an essence Set that stores activated essence types. Filling all 6 essences is one of the victory conditions.
Implementation Note: While the codebase includes an EssenceManager class in /game_objects/essences.js, the actual game implementation uses a native JavaScript Set for essence tracking, as seen in GameScene.js.

Actual Implementation (GameScene)

Essences are implemented as a JavaScript Set in the game:
// From Frontend/src/scenes/GameScene.js:199-200

this.player.essences = new Set();
this.opponent.essences = new Set();
Initial State: The Set starts empty. Essence types are added via the add() method when direct attacks are performed. The six essence types:
  • Fire (fuego)
  • Water (agua)
  • Plant (planta)
  • Light (luz)
  • Shadow (sombra)
  • Spirit (espiritu)

Properties

essences
Set<string>
A JavaScript Set containing activated essence types. Empty at game start, populated through direct attacks.Type: Set<string>Possible values:
  • 'fuego' (Fire)
  • 'agua' (Water)
  • 'planta' (Plant)
  • 'luz' (Light)
  • 'sombra' (Shadow)
  • 'espiritu' (Spirit)

Key Operations

fillEssence(essenceType)

Adds an essence type to the player’s Set. This method is dynamically added to Player instances in GameScene.
essenceType
string
required
The type of essence to activate (using CARD_TYPES values)
// From Frontend/src/scenes/GameScene.js:203-214

playerInstance.fillEssence = function(essenceType) {
  // Only add if not already present
  if (!this.essences.has(essenceType)) {
    this.essences.add(essenceType);
    console.log('[GameScene] Essence activated', { 
      playerId: this.id, 
      essenceType, 
      total: this.essences.size 
    });
    // Emit event for UI update
    this.scene.events.emit('essence-activated', this.id, essenceType);
  } else {
    console.log('[GameScene] Essence already activated', { 
      playerId: this.id, 
      essenceType 
    });
  }
};
Usage:
// Perform direct attack and fill essence
this.player.fillEssence('fuego');  // Adds fire essence
this.player.fillEssence('agua');   // Adds water essence
this.player.fillEssence('fuego');  // No effect - already added

has(essenceType)

Checks if a specific essence type is in the Set.
essenceType
string
required
The essence type to check
return
boolean
Returns true if the essence is active, false otherwise
// Check if player has fire essence
if (player.essences.has('fuego')) {
  console.log('Fire essence is active!');
}

// Check before adding
if (!player.essences.has('agua')) {
  player.essences.add('agua');
}

size

Returns the number of activated essences.
size
number
The count of unique essence types in the Set (0-6)
// From Frontend/src/scenes/GameScene.js:1336-1343

// Check for victory condition
if (this.player.essences.size === 6) {
  console.log('[GameScene] VICTORY: PLAYER (filled all 6 essences)');
  return 'player';
}

// Display count
console.log(`Player has ${this.player.essences.size} essences`);

Complete Example

// From Frontend/src/scenes/GameScene.js

class GameScene extends Phaser.Scene {
  create() {
    // Initialize essence Sets for both players
    this.player.essences = new Set();
    this.opponent.essences = new Set();
    
    // Add fillEssence method to players
    const addFillEssence = (playerInstance) => {
      playerInstance.fillEssence = function(essenceType) {
        if (!this.essences.has(essenceType)) {
          this.essences.add(essenceType);
          console.log('[GameScene] Essence activated', { 
            playerId: this.id, 
            essenceType, 
            total: this.essences.size 
          });
          this.scene.events.emit('essence-activated', this.id, essenceType);
        }
      };
    };
    
    addFillEssence(this.player);
    addFillEssence(this.opponent);
  }
  
  handleDirectAttack(attackingCard) {
    // Get card type
    const attackerData = attackingCard.getData('cardData');
    
    // Fill essence matching the attacking card's type
    this.player.fillEssence(attackerData.type);
    
    // Check for victory
    if (this.player.essences.size === 6) {
      this.endGame('player');
    }
  }
  
  checkVictoryConditions() {
    // Check essence victory condition
    if (this.player.essences.size === 6) {
      console.log('[GameScene] VICTORY: PLAYER (filled all 6 essences)');
      return 'player';
    }
    if (this.opponent.essences.size === 6) {
      console.log('[GameScene] VICTORY: OPPONENT (filled all 6 essences)');
      return 'opponent';
    }
    
    return null;
  }
}

How Essences Are Earned

Essences are filled through direct attacks only - when a player attacks while the opponent has no cards on the field:
// From Frontend/src/scenes/GameScene.js:1237-1241

// Direct attack handling
console.log('[GameScene] Player performs direct attack', { 
  attackerType: attackerData.type, 
  attackerIndex: attackingCardObject.getData('fieldIndex') 
});

this.player.fillEssence(attackerData.type);
Key points:
  • Direct attacks only occur when opponent’s field is empty
  • Each direct attack fills the essence matching the attacking card’s type
  • Each essence can only be filled once (Set prevents duplicates)
  • Need to perform direct attacks with all 6 different card types to win

UI Integration

Essences are visually displayed in the UIScene:
// From Frontend/src/scenes/uiScene.js

// Listen for essence activation events
this.gameScene.events.on('essence-activated', (playerId, essenceType) => {
  // Update orb visual for the essence type
  this.updateEssenceOrb(playerId, essenceType, true);
});

function updateEssenceOrb(playerId, essenceType, isActive) {
  const orb = this.essenceOrbs[playerId][essenceType];
  // Light up the orb or dim it
  orb.setAlpha(isActive ? 1.0 : 0.3);
}
Visual Layout:
  • 12 total orbs (6 per player)
  • Arranged in two triangular patterns per player
  • Gray when inactive, lit when active
  • Arrows show type advantage relationships

Card Types Reference

Use the CARD_TYPES constant for type-safe essence operations:
import { CARD_TYPES as CardTypes } from '../helpers/constants.js';

// Available card types:
CardTypes.FUEGO      // 'fuego' - Fire
CardTypes.AGUA       // 'agua' - Water
CardTypes.PLANTA     // 'planta' - Plant
CardTypes.LUZ        // 'luz' - Light
CardTypes.SOMBRA     // 'sombra' - Shadow
CardTypes.ESPIRITU   // 'espiritu' - Spirit

The EssenceManager Class (Unused)

While the codebase includes an EssenceManager class in /Frontend/src/game_objects/essences.js, it is not used in the actual game. The class provides an object-based approach to essence tracking with methods like activate(), has(), and getAll(), but GameScene implements essence tracking using native JavaScript Sets instead. If you’re extending the game, you can choose to:
  1. Use the current implementation: Continue with Set<string> (simpler, native)
  2. Migrate to EssenceManager: Refactor to use the class (more structured, extensible)
The EssenceManager class source can be found in /Frontend/src/game_objects/essences.js if needed for future development.

Build docs developers (and LLMs) love