DEV Community

Cover image for TCJSGame State Utilities: Complete Reference Guide
Kehinde Owolabi
Kehinde Owolabi

Posted on

TCJSGame State Utilities: Complete Reference Guide

TCJSGame State Utilities: Complete Reference Guide

Game State Management

Introduction to State Utilities

TCJSGame provides powerful state utilities through the state object that allow you to query and monitor game object properties in real-time. These utilities are essential for game logic, collision detection, and dynamic behavior.

📊 State Query Functions

Distance Calculation

// Calculate distance between two components
const distance = state.distance(player, enemy);

// Get distance between component and point
const pointDistance = state.distance(player, {x: 300, y: 200});

// Example: Enemy aggro range
function update() {
    const dist = state.distance(player, enemy);
    if (dist < 200) { // 200 pixel aggro range
        // Enemy detects player and starts chasing
        move.pointTo(enemy, player.x, player.y);
        move.accelerate(enemy, 0.1, 0, 3);
    }
}

// Example: Proximity trigger
const trigger = new Component(50, 50, "transparent", 400, 300, "rect");
function checkProximity() {
    if (state.distance(player, trigger) < 75) {
        // Player entered trigger area
        console.log("Secret area discovered!");
    }
}
Enter fullscreen mode Exit fullscreen mode

Rectangle Properties

// Get component's bounding rectangle [x, y, width, height]
const rect = state.rect(player); // Returns [100, 100, 30, 30]

// Example: UI alignment
function alignToComponent(source, target, padding = 10) {
    const targetRect = state.rect(target);
    source.x = targetRect[0] + targetRect[2] + padding;
    source.y = targetRect[1];
}

// Example: Screen bounds checking
function isOnScreen(component) {
    const [x, y, width, height] = state.rect(component);
    return x >= 0 && x <= display.canvas.width && 
           y >= 0 && y <= display.canvas.height;
}
Enter fullscreen mode Exit fullscreen mode

⚙️ Physics State Monitoring

Physics Status

// Check if physics is enabled on a component
const hasPhysics = state.physics(player); // Returns true or false

// Example: Conditional physics application
function applyGravity(component) {
    if (!state.physics(component)) {
        component.physics = true;
        component.gravity = 0.5;
    }
}

// Example: Physics-based puzzles
function togglePhysicsPlatform() {
    const physicsEnabled = state.physics(movingPlatform);
    if (physicsEnabled) {
        movingPlatform.physics = false;
        movingPlatform.speedX = 0;
        movingPlatform.speedY = 0;
    }
}
Enter fullscreen mode Exit fullscreen mode

Rotation State

// Check if rotation is enabled
const canRotate = state.changeAngle(player); // Returns boolean

// Get current rotation angle in radians
const angle = state.Angle(player);

// Example: Turret rotation limits
function updateTurret() {
    if (state.changeAngle(turret)) {
        const currentAngle = state.Angle(turret);
        // Limit rotation to 180 degrees
        if (currentAngle > Math.PI || currentAngle < -Math.PI) {
            turret.angle = 0;
        }
    }
}

// Example: Convert angle to degrees
function getAngleDegrees(component) {
    return state.Angle(component) * (180 / Math.PI);
}
Enter fullscreen mode Exit fullscreen mode

Position Information

// Get position as formatted string "x,y"
const posString = state.pos(player); // Returns "100,200"

// Example: Save game state
function saveGame() {
    const saveData = {
        playerPosition: state.pos(player),
        enemyPosition: state.pos(enemy),
        timestamp: Date.now()
    };
    localStorage.setItem('gameSave', JSON.stringify(saveData));
}

// Example: Load game state
function loadGame() {
    const saveData = JSON.parse(localStorage.getItem('gameSave'));
    if (saveData) {
        const [x, y] = saveData.playerPosition.split(',').map(Number);
        move.teleport(player, x, y);
    }
}
Enter fullscreen mode Exit fullscreen mode

🎯 Advanced State Combinations

Collision Detection System

// Enhanced collision with state utilities
function advancedCollision(obj1, obj2) {
    const dist = state.distance(obj1, obj2);
    const rect1 = state.rect(obj1);
    const rect2 = state.rect(obj2);

    // Fast distance check first
    if (dist > 100) return false;

    // Precise rectangle collision
    return (rect1[0] < rect2[0] + rect2[2] &&
            rect1[0] + rect1[2] > rect2[0] &&
            rect1[1] < rect2[1] + rect2[3] &&
            rect1[1] + rect1[3] > rect2[1]);
}

// Example: Smart enemy AI
function updateEnemyAI() {
    const playerRect = state.rect(player);
    const enemyRect = state.rect(enemy);
    const dist = state.distance(player, enemy);

    if (dist < 150) {
        // Chase player
        move.pointTo(enemy, player.x, player.y);
        move.accelerate(enemy, 0.2, 0, 4);
    } else if (dist > 400) {
        // Return to patrol
        patrolBehavior();
    }
}
Enter fullscreen mode Exit fullscreen mode

State-Based Animation System

// Animation states based on component properties
const animationStates = {
    IDLE: 0,
    WALKING: 1,
    JUMPING: 2,
    FALLING: 3
};

function getAnimationState(character) {
    const isGrounded = character.y >= display.canvas.height - character.height;
    const isMoving = Math.abs(character.speedX) > 0.1;

    if (!isGrounded) {
        return character.speedY < 0 ? animationStates.JUMPING : animationStates.FALLING;
    } else if (isMoving) {
        return animationStates.WALKING;
    } else {
        return animationStates.IDLE;
    }
}

// Example: Apply appropriate animation
function updateCharacterAnimation() {
    const animState = getAnimationState(player);

    switch(animState) {
        case animationStates.IDLE:
            player.color = "blue"; // Idle color
            break;
        case animationStates.WALKING:
            player.color = "green"; // Walking color
            break;
        case animationStates.JUMPING:
            player.color = "yellow"; // Jumping color
            break;
        case animationStates.FALLING:
            player.color = "orange"; // Falling color
            break;
    }
}
Enter fullscreen mode Exit fullscreen mode

🎮 Game Logic Implementation

Health and Damage System

// Health management with state monitoring
class GameCharacter {
    constructor(component, maxHealth = 100) {
        this.component = component;
        this.maxHealth = maxHealth;
        this.health = maxHealth;
        this.invulnerable = false;
    }

    takeDamage(amount) {
        if (this.invulnerable) return;

        this.health -= amount;
        this.invulnerable = true;

        // Flash effect
        const originalColor = this.component.color;
        this.component.color = "red";

        setTimeout(() => {
            this.component.color = originalColor;
            this.invulnerable = false;
        }, 500);

        return this.health <= 0;
    }

    getHealthPercent() {
        return (this.health / this.maxHealth) * 100;
    }
}

// Usage
const playerCharacter = new GameCharacter(player, 100);
Enter fullscreen mode Exit fullscreen mode

Score and Progress Tracking

// Game state manager
class GameState {
    constructor() {
        this.score = 0;
        this.level = 1;
        this.collectibles = [];
        this.startTime = Date.now();
    }

    addCollectible(component) {
        const pos = state.pos(component);
        this.collectibles.push({
            component: component,
            position: pos,
            collected: false
        });
    }

    checkCollectionProgress() {
        const collected = this.collectibles.filter(c => c.collected).length;
        return (collected / this.collectibles.length) * 100;
    }

    getPlayTime() {
        return Math.floor((Date.now() - this.startTime) / 1000);
    }
}

// Example usage
const gameState = new GameState();
Enter fullscreen mode Exit fullscreen mode

🔧 Advanced State Patterns

State Machine Implementation

// Finite State Machine for game objects
class StateMachine {
    constructor(component) {
        this.component = component;
        this.states = {};
        this.currentState = null;
    }

    addState(name, onEnter, onUpdate, onExit) {
        this.states[name] = { onEnter, onUpdate, onExit };
    }

    changeState(newState) {
        if (this.currentState && this.states[this.currentState].onExit) {
            this.states[this.currentState].onExit();
        }

        this.currentState = newState;

        if (this.states[newState].onEnter) {
            this.states[newState].onEnter();
        }
    }

    update() {
        if (this.currentState && this.states[this.currentState].onUpdate) {
            this.states[this.currentState].onUpdate();
        }
    }
}

// Example: Enemy AI states
const enemyAI = new StateMachine(enemy);

enemyAI.addState('patrol', 
    () => console.log("Enemy started patrolling"),
    () => {
        // Patrol behavior using state utilities
        const playerDist = state.distance(enemy, player);
        if (playerDist < 200) {
            enemyAI.changeState('chase');
        }
    },
    () => console.log("Enemy stopped patrolling")
);

enemyAI.addState('chase',
    () => console.log("Enemy started chasing"),
    () => {
        move.pointTo(enemy, player.x, player.y);
        move.accelerate(enemy, 0.3, 0, 5);

        const playerDist = state.distance(enemy, player);
        if (playerDist > 300) {
            enemyAI.changeState('patrol');
        }
    },
    () => console.log("Enemy stopped chasing")
);
Enter fullscreen mode Exit fullscreen mode

Event System with State Checks

// Event system based on state conditions
class GameEvent {
    constructor(condition, action, oneTime = false) {
        this.condition = condition;
        this.action = action;
        this.oneTime = oneTime;
        this.triggered = false;
    }

    check() {
        if (this.oneTime && this.triggered) return;

        if (this.condition()) {
            this.action();
            this.triggered = true;
        }
    }
}

// Example events
const events = [
    // Player reaches specific position
    new GameEvent(
        () => state.distance(player, {x: 500, y: 300}) < 50,
        () => console.log("Player reached the checkpoint!"),
        true
    ),

    // Player collects all coins
    new GameEvent(
        () => coins.every(coin => !coin.visible),
        () => console.log("All coins collected! Level complete!"),
        true
    ),

    // Continuous event - low health warning
    new GameEvent(
        () => playerHealth < 30,
        () => showLowHealthWarning(),
        false
    )
];

function checkEvents() {
    events.forEach(event => event.check());
}
Enter fullscreen mode Exit fullscreen mode

🎯 Practical Game Examples

Platformer Game State Manager

class PlatformerGame {
    constructor() {
        this.player = new Component(30, 30, "blue", 100, 100, "rect");
        this.player.physics = true;
        this.player.gravity = 0.5;

        this.enemies = [];
        this.platforms = [];
        this.coins = [];
        this.score = 0;
        this.lives = 3;
    }

    checkGameState() {
        // Check if player fell off screen
        if (state.rect(this.player)[1] > display.canvas.height) {
            this.respawnPlayer();
        }

        // Check coin collection
        this.coins.forEach((coin, index) => {
            if (this.player.crashWith(coin)) {
                this.score += 10;
                coin.hide();
                this.coins.splice(index, 1);
            }
        });

        // Check enemy collisions
        this.enemies.forEach(enemy => {
            if (this.player.crashWith(enemy)) {
                this.lives--;
                this.respawnPlayer();
            }
        });

        return this.lives > 0;
    }

    respawnPlayer() {
        move.teleport(this.player, 100, 100);
        this.player.speedX = 0;
        this.player.speedY = 0;
    }

    getGameStats() {
        return {
            score: this.score,
            lives: this.lives,
            coinsRemaining: this.coins.length,
            playerPosition: state.pos(this.player),
            playTime: Math.floor(display.frameNo / 50) // Approximate seconds
        };
    }
}
Enter fullscreen mode Exit fullscreen mode

Real-time Debug Information

// Debug overlay showing state information
const debugInfo = new Component(20, 20, "white", 10, 10, "text");

function updateDebugOverlay() {
    const info = [
        `Position: ${state.pos(player)}`,
        `Physics: ${state.physics(player)}`,
        `Rotation: ${state.changeAngle(player)}`,
        `Angle: ${state.Angle(player).toFixed(2)}rad`,
        `Speed: (${player.speedX.toFixed(1)}, ${player.speedY.toFixed(1)})`,
        `Frame: ${display.frameNo}`,
        `Scene: ${display.scene}`
    ];

    debugInfo.text = info.join('\n');
}
Enter fullscreen mode Exit fullscreen mode

⚡ Performance Optimization

Efficient State Checking

// Optimize frequent state checks
class OptimizedStateChecker {
    constructor() {
        this.lastCheck = 0;
        this.checkInterval = 10; // Check every 10 frames
        this.cachedStates = new Map();
    }

    getCachedDistance(obj1, obj2) {
        const key = `distance_${obj1.id}_${obj2.id}`;

        if (display.frameNo - this.lastCheck >= this.checkInterval) {
            const distance = state.distance(obj1, obj2);
            this.cachedStates.set(key, distance);
            this.lastCheck = display.frameNo;
            return distance;
        }

        return this.cachedStates.get(key) || 0;
    }
}

// Usage
const stateChecker = new OptimizedStateChecker();

function update() {
    // Only calculates distance every 10 frames
    const dist = stateChecker.getCachedDistance(player, enemy);
    if (dist < 100) {
        // Chase logic
    }
}
Enter fullscreen mode Exit fullscreen mode

📚 Conclusion

TCJSGame's state utilities provide:

  • Real-time object monitoring with simple function calls
  • Distance calculation for AI and triggers
  • Property checking for dynamic behavior
  • Position tracking for save systems and debugging
  • Physics state management for complex interactions

These utilities work seamlessly with TCJSGame's movement system to create sophisticated game logic with minimal code. By combining state queries with movement functions, you can build complex behaviors, AI systems, and game mechanics efficiently.

The state utilities are particularly powerful for:

  • AI behavior trees
  • Game progress tracking
  • Collision detection systems
  • Debug information displays
  • Save game functionality
  • Dynamic difficulty adjustment

Master these utilities to create responsive, intelligent game objects that react to their environment and player actions!

Top comments (0)