Operators
Table of Contents
Operators are symbols that perform actions on values. In a game, they power the physics engine, build sprite file paths, and decide whether a collision should deal damage.
Mathematical Operators
Mathematical operators handle all the physics in the game. Every frame, gravity is added to velocity, velocity is added to position, and collision overlap is calculated
Code Runner Challenge
gravity
View IPYNB Source
%%js
//CODE_RUNNER: gravity
const GRAVITY = 0.4;
const JUMP_FORCE = -8;
let x = 100;
let y = 300;
let velocityY = JUMP_FORCE; // player just jumped, moving upward
let score = 0;
const basePoints = 10;
const comboMultiplier = 3;
console.log("--- Simulating 10 frames of physics ---");
for (let frame = 1; frame <= 10; frame++) {
// + adds gravity to velocity each frame
velocityY = velocityY + GRAVITY;
// + moves the player by its velocity
y = y + velocityY;
// * scales score by combo
score = score + (basePoints * comboMultiplier);
console.log(`Frame ${frame}: velocityY = ${velocityY.toFixed(2)}, y = ${y.toFixed(2)}, score = ${score}`);
}
// - calculates collision overlap
const playerX = 200;
const playerWidth = 48;
const enemyX = 230;
const overlapX = (playerX + playerWidth) - enemyX;
console.log(`\nCollision overlap: (${playerX} + ${playerWidth}) - ${enemyX} = ${overlapX}px`);
// * Pythagorean theorem for total speed
const vx = 3;
const vy = 4;
const speed = Math.sqrt(vx * vx + vy * vy);
console.log(`Total speed: sqrt(${vx}^2 + ${vy}^2) = ${speed}`);
Lines: 1
Characters: 0
Output
Click "Run" in code control panel to see output ...
Explanation — Running this shows velocityY starting at -8 (moving up) and climbing toward 0 then going positive as gravity adds 0.4 every frame — that is exactly how a jump arc works. The y position falls once velocity turns positive. The overlap line shows - measuring how far two hitboxes intersect. The speed line shows * squaring each velocity component before + sums them for the Pythagorean theorem.
String Operations
String operators build the file paths that load sprite images and construct the text displayed on the HUD. Template literals are the cleaner modern approach.
Code Runner Challenge
string operations
View IPYNB Source
%%js
//CODE_RUNNER: string operations
const name = "mario";
const state = "run";
const health = 80;
const score = 450;
const level = 3;
// Template literal — slots variables directly into a string
const spriteSrc = `./images/sprites/${name}/${state}.png`;
console.log("Sprite path (template literal):", spriteSrc);
// + concatenation — classic string joining
const hudLabel = "Character: " + name;
const healthBar = "HP: " + health + " / 100";
console.log("HUD label (concatenation):", hudLabel);
console.log("Health bar (concatenation):", healthBar);
// Template literal with a method call inside ${}
const statusLine = `${name.toUpperCase()} — Level ${level} — State: ${state}`;
console.log("Status line (template literal):", statusLine);
// Changing state updates the path automatically — no manual rebuilding
const states = ["idle", "run", "jump", "hurt"];
console.log("\n--- All sprite paths for mario ---");
states.forEach(s => {
console.log(`./images/sprites/${name}/${s}.png`);
});
Lines: 1
Characters: 0
Output
Click "Run" in code control panel to see output ...
Explanation — Running this prints the exact strings a game would use. The sprite path changes automatically when you swap state — no manual rebuilding needed. The forEach at the bottom shows how one template literal generates every animation path for a character by looping through the states array.
Boolean Expressions
| Boolean expressions combine true/false values using && (AND), |
|
(OR), and ! (NOT) to build compound conditions. Game logic is full of multi-part checks — a player should only take damage if they are vulnerable AND the attacker is an enemy AND no shield is active. |
Code Runner Challenge
Boolean logic
View IPYNB Source
%%js
//CODE_RUNNER: Boolean logic
function handleCollision(isVulnerable, isShielded, isEnemy) {
console.log(`isVulnerable: ${isVulnerable}, isShielded: ${isShielded}, isEnemy: ${isEnemy}`);
// && means ALL must be true to deal damage
if (isEnemy && isVulnerable && !isShielded) {
console.log("Result: Player takes damage!");
} else {
console.log("Result: No damage.");
}
}
// Test 1 — player is vulnerable, no shield, hits an enemy
console.log("=== Test 1: No shield ===");
handleCollision(true, false, true);
// Test 2 — same but shield is now on
console.log("\n=== Test 2: Shield active ===");
handleCollision(true, true, true);
Lines: 1
Characters: 0
Output
Click "Run" in code control panel to see output ...
Explanation — Running this prints exactly which branch fires for each scenario. Test 1 shows && requiring all three conditions before damage is dealt. Test 2 shows !isShielded blocking damage even though the player is vulnerable — flipping one boolean changes the whole outcome. Test 3 shows !isPaused shutting everything down when the game is paused.