Operators: Mathematical, String, Boolean

Requirement

Use mathematical operators (+, -, *, /), string operations, and boolean expressions for game logic.


1. Mathematical Operators - Physics Calculations

Ghost.js - Distance Calculation with Math Operators

followPlayer(player) {
    const ghostCenter = this.getCenter();
    const playerCenter = player.getCenter();

    // ← SUBTRACTION operators: calculate deltas
    const dx = playerCenter.x - ghostCenter.x;  
    const dy = playerCenter.y - ghostCenter.y;  
    
    // ← MULTIPLICATION in Math.hypot: distance = sqrt(dx² + dy²)
    const distance = Math.hypot(dx, dy);        

    // ← Conditional check with number comparison
    if (distance <= this.followStopDistance) {
        this.velocity.x = 0;  // ← ASSIGNMENT
        this.velocity.y = 0;
        return;
    }

    // ← DIVISION: normalize velocity
    const baseSpeed = player?.xVelocity || (this.gameEnv?.innerWidth || 800) / 2000;
    const speed = Math.max(0.3, baseSpeed * this.followSpeedFactor);  // ← MULTIPLICATION
    
    // ← DIVISION: normalize direction vector
    const nx = dx / distance;  
    const ny = dy / distance;  

    // ← MULTIPLICATION and ADDITION: update position
    this.position.x += nx * speed;  // ← MULTIPLICATION + ADDITION
    this.position.y += ny * speed;  
}

How it meets the requirement:

  • Subtraction: dx = playerCenter.x - ghostCenter.x (delta calculation)
  • Division: dx / distance (vector normalization)
  • Multiplication: nx * speed (velocity application)
  • Addition: position.x += nx * speed (position update)

GameLevelOutside.js - Speed Calculation

const baseSpeed = player?.xVelocity || (this.gameEnv?.innerWidth || 800) / 2000;
                                        // ← DIVISION: scale width to speed

const speed = Math.max(0.3, baseSpeed * this.followSpeedFactor);
                          // ← MULTIPLICATION: adjust speed with factor

How it meets the requirement:

  • Division: innerWidth / 2000 converts pixel distance to speed
  • Multiplication: baseSpeed * followSpeedFactor scales the velocity

2. String Operations - Path Concatenation and Text

GameLevelOutside.js - String Concatenation

const path = gameEnv.path;  // Path from game environment

const playerSpriteOptions = {
    // ← STRING CONCATENATION with + operator
    gray: path + "/images/projects/castle-game/grayKnight.png",
    green: path + "/images/projects/castle-game/greenKnight.png",
    dark: path + "/images/projects/castle-game/darkKnight.png"
};

const sir_morty = path + "/images/projects/castle-game/mortyKnight.png";
               // ← Concatenate base path with sprite filename

const getPlayerSpriteSrc = (skinKey) => playerSpriteOptions[skinKey] || playerSpriteOptions.gray;
                                         // ← Ternary with string values

How it meets the requirement:

  • Concatenation: path + "/images/..." builds file paths
  • Logical OR: playerSpriteOptions[skinKey] || playerSpriteOptions.gray fallback

GameLevelOutside.js - Template Literals and String Operations

const transitionText = document.createElement('div');
const transitionDialogues = [
    'Welcome to the castle.',
    'Your job is to break in and free the prisoner.',
    'Use your bow to pass the archery challenge.',
    'Good luck, brave knight.'
];

// ← TEMPLATE LITERAL with string interpolation
const typeLine = (line) => new Promise((resolve) => {
    let i = 0;
    transitionText.innerHTML = '';  // Clear previous text
    const interval = setInterval(() => {
        const span = document.createElement('span');
        // ← charAt() string method: get single character
        span.textContent = line.charAt(i);  
        // ...
        i++;
        if (i >= line.length) {  // ← String length property
            clearInterval(interval);
            resolve();
        }
    }, typingSpeed);
});

const starContext = starCtx;
const gradient = starCtx.createRadialGradient(...);
gradient.addColorStop(0, 'rgba(40, 70, 120, 0.35)');  // ← STRING color value
gradient.addColorStop(1, 'rgba(0, 0, 10, 0.95)');

How it meets the requirement:

  • String Methods: line.charAt(i), line.length
  • String Values: Color strings, dialogue text

3. Boolean Operators - AND, OR, NOT Logic

Ghost.js - Boolean Operators

update() {
    const player = this.getPlayer();
    // ← AND (&&) operator: both conditions must be true
    if (player && !player.isDead) {  
        this.followPlayer(player);
    }
    super.update();
}

getPlayer() {
    // ← OR (||) operator: return first truthy value
    return this.gameEnv?.gameObjects?.find(obj => obj instanceof Player) || null;
}

handleCollisionEvent() {
    // ← OR (||) operator: trigger death if either flag is set
    if (this._hasTriggeredDeath || this.playerDestroyed) return;

    const player = this.getPlayer();
    // ← AND (&&) with NOT (!): both conditions must be false
    if (!player || player.isDead) return;  

    this._hasTriggeredDeath = true;  // ← Set flag
    this.playerDestroyed = true;
    player.isDead = true;
}

How it meets the requirement:

  • AND (&&): player && !player.isDead - both must be true
  • **OR (   )**: ||null - fallback value
  • NOT (!): !player.isDead - negation of condition

DeathBarrier.js - Complex Boolean Logic

update() {
    super.update();

    // ← NOT (!) operator: if NOT already triggered
    if (this._hasTriggeredDeath) return;  

    const player = this.gameEnv?.gameObjects?.find(obj => obj.constructor?.name === 'Player');
    // ← AND (&&) multiple conditions: all must be true
    if (!player || !player.canvas || !this.canvas) return;  

    this.isCollision(player);

    if (this.collisionData?.hit) {  // ← Check if collision occurred
        const timeSinceLevelStart = new Date() - DeathBarrier.levelStartTime;
        // ← LESS THAN operator: numeric comparison
        if (timeSinceLevelStart < 500) {  
            console.log('[MazeDebug] Grace period active:', timeSinceLevelStart, 'ms');
            return;  // Exit if grace period active
        }

        // ← Complex conditional with AND (&&) operators
        this._hasTriggeredDeath = true;  
        player.isDead = true;

        try {
            showDeathScreen(player, 'You got lost in the maze.');
        } catch (error) {  // ← Error handling with try/catch
            console.error('DeathBarrier failed to show death screen:', error);
            this._hasTriggeredDeath = false;
            player.isDead = false;
        }
    }
}

How it meets the requirement:

  • AND (&&): !player || !player.canvas || !this.canvas
  • NOT (!): !this._hasTriggeredDeath
  • Comparison: timeSinceLevelStart < 500

Summary

Mathematical Operators

  • Addition (+): position.x += nx * speed
  • Subtraction (-): dx = playerCenter.x - ghostCenter.x
  • Multiplication (*): baseSpeed * followSpeedFactor
  • Division (/): nx = dx / distance

String Operations

  • Concatenation (+): path + "/images/..."
  • String methods: line.charAt(i), line.length
  • Template literals and string values

Boolean Operators

  • AND (&&): player && !player.isDead
  • OR (   ): value || fallback
  • NOT (!): !player.isDead
  • Comparisons: <, >, ===, !==