CS111 College Ready

This notebook explains the code in Aquatic For Reference.js using CSSE topics like functions, arrays, booleans, conditionals, classes, constructors, methods, strings, data abstraction, math expressions, variables, and iteration. Each section below connects one CSSE topic to a real code pattern from the Aquatic level file. Before the topic-by-topic breakdown, the notebook now includes a small playable aquatic runner and a preview of the assets currently wired into the published site.

Interactive Rubric Dashboard

Interactive Rubric Dashboard

Search + filter Objective jump links Progress memory
Review completion
0 / 7 checked

CS 111 Course Alignment Rubric

Required Evidence for College Credit

Students must demonstrate competency in all CS 111 learning objectives through their game project. Below is the alignment between CS 111 requirements and project deliverables, with evidence pulled from the Aquatic game level implementation.

Learning Objective Project Evidence Required Assessment Method
Object-Oriented Programming    
Writing Classes Create minimum 2 custom character classes extending base classes. Evidence: class Player extends Character, class Npc extends Character, class Shark extends Enemy in assets/js/GameEnginev1/essentials/Player.js, assets/js/GameEnginev1/essentials/Npc.js, assets/js/GameEnginev1/Shark.js. Code review: class declarations and extends usage
Methods & Parameters Implement methods with parameters. Evidence: applyPlayerDamage(damage, x, y, source) and applyMermaidBossDamage(damage, hitX, hitY) in assets/js/GameEnginev1/GameLevelAquaticGameLevel.js. Code review: method signatures with 2+ parameters
Instantiation & Objects Instantiate game objects in level configuration/runtime. Evidence: const guardian = new Npc(guardianData, this.gameEnv); and this.gameEnv.gameObjects.push(guardian); in assets/js/GameEnginev1/GameLevelAquaticGameLevel.js. Code review: GameLevel setup and runtime object registration
Inheritance (Basic) Create class hierarchy with 2+ levels. Evidence: GameObject -> Character -> Player and Character -> Npc -> Shark. Code review: inheritance chain and shared behavior
Method Overriding Override parent methods (update(), interaction handling, behavior methods). Evidence: child entity update and interaction methods in player/NPC/enemy classes. Code review: polymorphic implementations
Constructor Chaining Use super() to chain constructors. Evidence: super(data, gameEnv) patterns in entity constructors. Code review: super(data, gameEnv) calls
Control Structures    
Iteration Use loops for game object arrays and attack phases. Evidence: thresholds.forEach((threshold) => { ... }), update loops, projectile iteration. Code review: for, forEach, while
Conditionals Implement collision checks and state transitions. Evidence: quest/boss transitions such as if (q1.completed && !q2.accepted) { ... }. Code review: if/else branches
Nested Conditions Multi-stage combat logic. Evidence: if (state.phaseTwoUnlocked && now >= state.nextLaserAt && state.phaseThreeUnlocked) { ... }. Code review: multi-level conditional logic
Data Types    
Numbers Position, HP, cooldown, and timing tracking. Evidence: const hpRatio = this.bossState.hp / this.bossState.maxHp;. Code review: numeric properties and math usage
Strings Character IDs, paths, and labels. Evidence: const aquaticSpriteStorageKey = 'aquatic_selected_sprite_v1';. Code review: string literals and concatenation/template usage
Booleans Flags for active/completed states. Evidence: this.levelCompleted = false;, this.bossState.active = true;. Code review: boolean state transitions
Arrays Game object collections and threshold lists. Evidence: const thresholds = [0.75, 0.5, 0.25];. Code review: array operations
Objects (JSON) Config/state object literals. Evidence: const guardianData = { orientation: { ... }, attack: { ... } };. Code review: object literal structure
Operators    
Mathematical Physics/combat calculations. Evidence: this.bossState.maxHp * threshold, vector and distance calculations in attacks. Code review: +, -, *, / usage
String Operations Path assembly and identifiers. Evidence: const backgroundAssetPath = path + '/images/gamebuilder/bg';. Code review: concatenation/template literals
Boolean Expressions Compound game-state checks. Evidence: &&, ||, ! in phase gates and quest flow. Code review: compound conditions
Input/Output    
Keyboard Input WASD/keyboard mapping and handlers. Evidence: this.keypress = data?.keypress || { up: 87, left: 65, down: 83, right: 68 }; and keydown listeners. Testing: key event handlers respond correctly
Canvas Rendering Draw/update lifecycle for entities. Evidence: update() { this.draw(); } and sprite rendering in character classes. Code review: render lifecycle methods
GameEnv Configuration Canvas/runtime setup and class registration. Evidence: this.gameEnv.create(); and level constructor wiring. Code review: GameEnv setup + GameLevel init
API Integration Fetch-based external communication. Evidence: await fetch(${this.game.javaURI}/bank/${personId}/npcProgress, this.fetchOptions);. Code review: fetch calls with error handling
Asynchronous I/O Non-blocking runtime functions. Evidence: async handleMoodClick(mood) { const response = await fetch(...); }. Code review: async/await flow
JSON Parsing Parse API payloads. Evidence: const result = await response.json();. Code review: response parsing and property access
Documentation    
Code Comments Intent comments in complex logic. Evidence: // Initialize touch controls for mobile devices. Code review: meaningful comment usage
Mini-Lesson Documentation Notebook sections and rubric mapping for instruction. Evidence: this notebook’s rubric + objective sections. Portfolio review: published mini-lesson
Code Highlights Annotated snippets under each rubric objective. Evidence: objective-specific code blocks in this notebook. Portfolio review: highlighted explanations
Debugging    
Console Debugging Runtime diagnostics. Evidence: console.warn('Unable to play aquatic boss theme', err);. Code review: strategic logging/warnings
Hit Box Visualization Collision-distance validation. Evidence: if (hitDistance < 30) { applyPlayerDamage(...); }. Demo: collision boundary verification
Source-Level Debugging Breakpoint-friendly state guards. Evidence: if (this.bossState.active || this.bossState.introPlayed) return;. Demo: stepping through flow in Sources
Network Debugging Request status checks. Evidence: if (!response.ok) throw new Error('Failed to send mood');. Demo: inspect requests and responses
Application Debugging Local/session state verification. Evidence: localStorage.setItem(...), sessionStorage.setItem(...). Demo: inspect storage state
Element Inspection DOM/canvas inspection logic. Evidence: if (this.canvas?.parentNode) { this.canvas.parentNode.removeChild(this.canvas); }. Demo: inspect DOM/canvas lifecycle
Testing & Verification    
Gameplay Testing Validate quest/combat flow. Evidence: dialogue progression and boss-state transitions in Aquatic level scripts. Live demo: complete flow without blockers
Integration Testing Verify backend-connected paths. Evidence: await fetch(${this.game.javaURI}/createStats, { method: 'POST', body: JSON.stringify({ stats, gname, uid }) });. Demo: successful integrated requests
API Error Handling Graceful failure handling. Evidence: try/catch around fetch with fallback status UI (this.showStatus('Network error', true);). Code review: explicit error handling

1 — Object-Oriented Programming

1.1 Writing Classes

A class is a blueprint for creating objects. extends builds an inheritance chain so classes can reuse behavior. this.classes tells the engine what to create at startup.

Code Runner Challenge

OOP coverage for 1.1 to 1.6

View IPYNB Source
// Player class extends Character, so Player inherits movement/collision/sprite behavior.
class Player extends Character {
  // Constructor runs when a new Player is created in the level class list.
  constructor(data = null, gameEnv = null) {
    // super(...) calls Character constructor first; required before using this.
    super(data, gameEnv);

    // Player identity in Aquatic (fallback if data.id is missing).
    this.id = data?.id ?? 'player';

    // Default WASD key mapping used by movement listeners.
    this.keypress = data?.keypress || { up: 87, left: 65, down: 83, right: 68 };

    // Tracks currently pressed keys for continuous movement.
    this.pressedKeys = {};
  }
}

// NPC class extends Character so it can share sprite and interaction lifecycle.
class Npc extends Character {
  constructor(data = null, gameEnv = null) {
    super(data, gameEnv);
  }
}

// Shark class extends Enemy (Enemy extends Character), forming a multi-level chain.
class Shark extends Enemy {
  constructor(data = null, gameEnv = null) {
    super(data, gameEnv);
    // Enemy-state flag used in collision/combat logic.
    this.playerDestroyed = false;
  }
}

// Aquatic level class: this.classes tells the engine exactly what objects to instantiate.
class GameLevelAquaticGameLevel {
  constructor(gameEnv) {
    this.gameEnv = gameEnv;
    this.classes = [
      { class: GameEnvBackground, data: bgData },
      { class: Player, data: playerData },
      { class: Npc, data: mermaidNpc },
      { class: Npc, data: slimeNpc },
      { class: Npc, data: kirbyNpc },
      { class: Npc, data: sharkNpc }
    ];
  }
}
Lines: 1 Characters: 0
Output
Click "Run" in code control panel to see output ...

1.2 Methods & Parameters

A method is a class function that uses this instance state. Parameters let one method handle many callers.

applyPlayerDamage(damage, x, y, source) {
  if (!this.bossState.active) return;
  // damage and hit position are parameter-driven
}

applyMermaidBossDamage(damage, hitX, hitY) {
  if (!this.mermaidBossState.active) return;
  // same logic shape, different target state
}

collisionChecks() {
  for (const gameObj of this.gameEnv.gameObjects) {
    if (gameObj instanceof Player) {
      this.isCollision(gameObj);
      if (this.collisionData.hit) return true;
    }
  }
  return false;
}

1.3 Instantiation & Objects

Instantiation uses new ClassName(...) to create independent runtime objects. Aquatic level setup uses both class instances and object-literal configuration.

const guardianData = {
  orientation: { rows: 6, columns: 6 },
  attack: { row: 4, start: 0, columns: 5 }
};

const guardian = new Npc(guardianData, this.gameEnv);
this.gameEnv.gameObjects.push(guardian);

this.classes = [
  { class: GameEnvBackground, data: image_data_aquatic }
];

1.4 Inheritance

Inheritance lets child classes automatically use parent fields/methods without rewriting everything.

class GameObject {
  constructor(gameEnv) {
    this.gameEnv = gameEnv;
    gameEnv.gameObjects.push(this);
  }
}

class Character extends GameObject {
  constructor(data = null, gameEnv = null) {
    super(gameEnv);
    this.velocity = { x: 0, y: 0 };
  }
}

class Player extends Character {
  constructor(data = null, gameEnv = null) {
    super(data, gameEnv);
    this.keypress = data?.keypress || { up: 87, left: 65, down: 83, right: 68 };
  }
}

1.5 Method Overriding

Overriding happens when a child defines the same method name as a parent. super.methodName() keeps parent behavior and extends it.

update() {
  super.update();
  if (!this.playerDestroyed && this.collisionChecks()) {
    this.handleCollisionEvent();
  }
  this.stayWithinCanvas();
}

handleCollisionReaction(other) {
  const touchPoints = this.collisionData?.touchPoints?.this;
  if (touchPoints?.top) this.velocity.y = Math.min(0, this.velocity.y);
  if (touchPoints?.bottom) this.velocity.y = Math.max(0, this.velocity.y);
  if (touchPoints?.left) this.velocity.x = Math.min(0, this.velocity.x);
  if (touchPoints?.right) this.velocity.x = Math.max(0, this.velocity.x);
}

1.6 Constructor Chaining

super() in child constructors calls parent setup first. JavaScript requires this before using this.

constructor(data = null, gameEnv = null) {
  super(data, gameEnv);
  this.pressedKeys = {};
}

constructor(data = null, gameEnv = null) {
  super(gameEnv);
  this.canvas = document.createElement('canvas');
  this.velocity = { x: 0, y: 0 };
}

constructor(gameEnv) {
  this.gameEnv = gameEnv;
  this.canvas = document.createElement('canvas');
  gameEnv.gameObjects.push(this);
}

Use this section as the OOP evidence reference, then continue with the existing sections for Control Structures, Data Types, Operators, Input/Output, Documentation, Debugging, and Testing.

OOP Code Runners (1.1-1.6)

Run this cell to execute concrete mini-examples for all Object-Oriented Programming sub-lessons.

Code Runner Challenge

Practice #1 - Conditionals and Loops

View IPYNB Source
%%js

// CODE_RUNNER: OOP coverage for 1.1 to 1.6

// 1.4 Inheritance root
class GameObject {
  constructor(gameEnv) {
    this.gameEnv = gameEnv;
  }
  update() {
    return 'base-update';
  }
}

// 1.4 Inheritance middle + 1.6 constructor chaining
class Character extends GameObject {
  constructor(data = null, gameEnv = null) {
    super(gameEnv);
    this.data = data || {};
    this.velocity = { x: 0, y: 0 };
  }
}

// 1.1 Writing classes + 1.6 constructor chaining
class Player extends Character {
  constructor(data = null, gameEnv = null) {
    super(data, gameEnv);
    this.id = data?.id ?? 'player';
    this.keypress = data?.keypress || { up: 87, left: 65, down: 83, right: 68 };
    this.pressedKeys = {};
  }

  // 1.2 Methods and parameters
  applyPlayerDamage(damage, source) {
    this.hp = Math.max(0, (this.hp ?? 100) - damage);
    return `Took ${damage} from ${source}. HP=${this.hp}`;
  }

  // 1.5 Method overriding
  update() {
    const parentResult = super.update();
    return `${parentResult} -> player-update`;
  }
}

// 1.3 Instantiation and objects
const gameEnv = { level: 'Aquatic Demo' };
const p1 = new Player({ id: 'aqua_hero' }, gameEnv);

console.log('1.1 class + extends:', p1 instanceof Player, p1 instanceof Character);
console.log('1.2 method params:', p1.applyPlayerDamage(25, 'rocket'));
console.log('1.3 instantiation:', p1.id, p1.keypress.left);
console.log('1.5 overriding:', p1.update());
console.log('1.6 constructor chaining gameEnv:', p1.gameEnv.level);

Lines: 1 Characters: 0
Output
Click "Run" in code control panel to see output ...

Runner: Category 6 (Documentation)

Use comments and clear section labels to document intent.

Code Runner Challenge

Practice #2 - Arrays, Objects, and Iteration

View IPYNB Source
%%js

// Category 6: Documentation runner
// This function demonstrates concise comments and explicit naming.
function formatRubricStatus(categoryName, completed, total) {
  // Convert progress into percent for display.
  const percent = Math.round((completed / total) * 100);
  // Return a readable status string for lesson dashboards.
  return `${categoryName}: ${completed}/${total} (${percent}%)`;
}

console.log(formatRubricStatus('Documentation', 3, 3));
Lines: 1 Characters: 0
Output
Click "Run" in code control panel to see output ...

Runner: Category 5 (Input/Output)

Simulate keyboard-style input and API-style async flow.

Code Runner Challenge

Practice #3 - Classes and Methods

View IPYNB Source
%%js

// Category 5: Input/Output runner
const keypress = { up: 87, left: 65, down: 83, right: 68 };
const pressed = [87, 68];
const direction = pressed.includes(keypress.up) && pressed.includes(keypress.right) ? 'upRight' : 'idle';

async function fakeApiSave(payload) {
  // Simulate async request/response round trip.
  return Promise.resolve({ ok: true, json: async () => ({ saved: true, payload }) });
}

const response = await fakeApiSave({ direction });
const result = await response.json();
console.log('Direction:', direction, '| API saved:', result.saved);
Lines: 1 Characters: 0
Output
Click "Run" in code control panel to see output ...

Runner: Category 4 (Operators)

Practice math, string, and boolean operators in one snippet.

%%js

// Category 4: Operators runner
const hp = 84;
const maxHp = 120;
const ratio = hp / maxHp;           // mathematical operator
const label = `HP ratio: ${ratio}`; // string operation
const canCast = ratio <= 0.75 && hp > 0; // boolean expression

console.log(label);
console.log('Can cast ability:', canCast);

Runner: Category 3 (Data Types)

Use numbers, strings, booleans, arrays, and objects together.

%%js

// Category 3: Data types runner
const hp = 95;                            // number
const playerName = 'Aqua Hero';           // string
const isBossActive = true;                // boolean
const thresholds = [0.75, 0.5, 0.25];     // array
const state = { hp, maxHp: 120, name: playerName }; // object

console.log(playerName, 'active?', isBossActive);
console.log('Threshold count:', thresholds.length);
console.log('HP ratio:', state.hp / state.maxHp);

Runner: Category 2 (Control Structures)

Practice iteration and nested conditions with boss phases.

%%js

// Category 2: Control structures runner
const thresholds = [0.75, 0.5, 0.25];
const state = { hp: 48, maxHp: 100, phaseTwoUnlocked: true, phaseThreeUnlocked: true, nextLaserAt: 10 };
const now = 20;

thresholds.forEach((threshold) => {
  if (state.hp <= state.maxHp * threshold) {
    console.log('Triggered threshold:', threshold);
  }
});

if (state.phaseTwoUnlocked && now >= state.nextLaserAt && state.phaseThreeUnlocked) {
  console.log('Nested condition passed: laser can start');
}

2 — Control Structures

2.1 Iteration

Code evidence (Aquatic):

// Each threshold represents a boss HP phase trigger (75%, 50%, 25%).
thresholds.forEach((threshold) => {
  // Compare current HP to a percentage of max HP.
  if (this.bossState.hp <= this.bossState.maxHp * threshold) {
    // Spawn reinforcements when that phase is reached.
    summonRushingSharks();
  }
});

How this works in my Aquatic game:

  • The loop checks each HP threshold (75%, 50%, 25%).
  • When Megalodon HP drops below a threshold, shark reinforcements are spawned.
  • This creates phase-based combat escalation.

2.2 Conditionals

Code evidence (Aquatic):

// Only show Quest 2 prompt after Quest 1 is complete.
if (q1.completed && !q2.accepted) {
  // Dialogue branch advances story progression.
  this.dialogueSystem.showDialogue('Will you take Aquatic Quest #2?', 'Slime', null);
}

How this works in my Aquatic game:

  • The game only offers Quest 2 after Quest 1 is complete.
  • It prevents showing wrong dialogue at the wrong time.
  • This keeps quest progression logic consistent.

2.3 Nested Conditions

Code evidence (Aquatic):

// Laser requires: phase unlocked + cooldown reached + late-phase flag.
if (state.phaseTwoUnlocked && now >= state.nextLaserAt && state.phaseThreeUnlocked) {
  // Start laser with configured charge duration.
  startMermaidBossAbility('laser', state.laserChargeMs);
}

How this works in my Aquatic game:

  • Mermaid laser requires multiple conditions at once: phase unlock + cooldown time.
  • This prevents ability spam and preserves intended boss pacing.

3 — Data Types

3.1 Numbers

Code evidence (Aquatic):

// Convert absolute HP into a ratio so behavior can scale by percent.
// Example: 50/100 = 0.5, which can unlock mid-fight phase logic.
const hpRatio = this.bossState.hp / this.bossState.maxHp;

How this works in my Aquatic game:

  • Converts boss health into a ratio for phase checks and UI decisions.
  • Allows behavior to scale by percent, not hardcoded HP only.

3.2 Strings

Code evidence (Aquatic):

// Storage key name used for persisting selected player sprite.
// This exact key is reused when writing and reading localStorage values.
const aquaticSpriteStorageKey = 'aquatic_selected_sprite_v1';

How this works in my Aquatic game:

  • This string is the storage key used to remember selected player sprite.
  • Keeps player customization persistent across sessions.

3.3 Booleans

Code evidence (Aquatic):

// Menu starts hidden when gameplay begins.
this.frontMenuActive = false;

// Boss logic gates open once encounter is activated.
// Many attack/update branches check this flag before running.
this.bossState.active = true;

How this works in my Aquatic game:

  • frontMenuActive toggles menu state.
  • bossState.active enables boss combat logic only when encounter starts.

3.4 Arrays

Code evidence (Aquatic):

// Array of selectable character presets for the Aquatic level.
// Each object stores a stable key (used by logic) and a label (used by UI text).
const aquaticSpriteOptions = [
  { key: 'scuba-diver', label: 'Scuba Diver' },
  { key: 'boy', label: 'Boy' }
];

How this works in my Aquatic game:

  • Stores available character choices in one data structure.
  • UI can render options and switch sprites from this list.

3.5 Objects (JSON)

Code evidence (Aquatic):

// Object literal groups guardian animation configuration.
// Nested fields let renderer/animation code read structured data by action name.
const guardianData = {
  orientation: { rows: 6, columns: 6 },
  attack: { row: 4, start: 0, columns: 5 }
};

How this works in my Aquatic game:

  • Groups sprite/animation config for a guardian NPC.
  • Makes NPC setup data-driven rather than hardcoding values across methods.

4 — Operators

4.1 Mathematical Operators

Code evidence (Aquatic):

// Multiply max HP by threshold to compute phase breakpoint.
// If max HP is 200 and threshold is 0.5, trigger point becomes 100 HP.
if (this.bossState.hp <= this.bossState.maxHp * threshold) {
  summonRushingSharks();
}

How this works in my Aquatic game:

  • Multiplies max HP by threshold to compute trigger points.
  • Uses <= to activate phase actions when HP reaches that level.

4.2 String Operations

Code evidence (Aquatic):

// Build sprite path using string concatenation.
// This keeps file paths dynamic across local and deployed environments.
const spriteAssetPath = path + '/images/gamebuilder/sprites';

// Build unique collectible id using template literal.
// i changes each loop, so IDs become starfish_0, starfish_1, etc.
const itemId = `starfish_${i}`;

How this works in my Aquatic game:

  • Concatenation builds asset folder paths.
  • Template literals generate unique collectible IDs.

4.3 Boolean Expressions

Code evidence (Aquatic):

// Compound condition ensures laser can run only in valid phase/timing state.
// All three checks must be true for this branch to execute.
if (state.phaseTwoUnlocked && now >= state.nextLaserAt && state.phaseThreeUnlocked) {
  startMermaidBossAbility('laser', state.laserChargeMs);
}

How this works in my Aquatic game:

  • Compound boolean logic ensures ability fires only in valid game state.
  • Reduces bugs from partial or premature phase triggers.

5 — Input/Output

5.1 Keyboard Input

Code evidence (Aquatic):

// Default WASD controls used when custom key data is absent.
// 87=W (up), 65=A (left), 83=S (down), 68=D (right).
this.keypress = data?.keypress || { up: 87, left: 65, down: 83, right: 68 };

// Keydown listener routes keyboard input into movement logic.
// bind(this) preserves class context inside handleKeyDown.
addEventListener('keydown', this.handleKeyDown.bind(this));

How this works in my Aquatic game:

  • Maps WASD keycodes to movement directions.
  • Listener captures real-time key presses for player control.

5.2 Canvas Rendering

Code evidence (Aquatic):

update() {
  // Draw is called each frame through the update lifecycle.
  // This keeps sprite position/animation synced with current state.
  this.draw();
}

How this works in my Aquatic game:

  • Every frame calls draw through update lifecycle.
  • Keeps character and boss visuals synced with game state.

5.3 GameEnv Configuration

Code evidence (Aquatic):

// Create initializes game canvas/context and runtime object systems.
// This is the startup handoff that makes the scene render and update.
this.gameEnv.create();

How this works in my Aquatic game:

  • Initializes runtime environment, canvas, and object loop.
  • Without this call, gameplay rendering and updates cannot start.

5.4 API Integration

Code evidence (Aquatic):

// Fetch backend NPC progress tied to current person/player id.
// fetchOptions usually includes method, headers, and auth/session context.
const response = await fetch(`${this.game.javaURI}/bank/${personId}/npcProgress`, this.fetchOptions);

How this works in my Aquatic game:

  • Sends/reads backend progress data tied to player profile.
  • Connects in-game actions with persistent external systems.

5.5 Asynchronous I/O

Code evidence (Aquatic):

// Async handler keeps UI responsive while POST request completes.
// await pauses this function only, not the entire render/game loop.
async handleMoodClick(mood) {
  const response = await fetch(this.endpoint, { method: 'POST' });
}

How this works in my Aquatic game:

  • Prevents UI/game loop blocking during network requests.
  • Allows responses to be handled after request completion.

5.6 JSON Parsing

Code evidence (Aquatic):

// Parse JSON payload into JavaScript object for game logic use.
// After parsing, fields like result.success or result.stats can be read safely.
const result = await response.json();

How this works in my Aquatic game:

  • Converts backend response payload into usable JS object data.
  • Enables quest/mood/progress logic to read structured fields.

6 — Documentation

6.1 Code Comments

Code evidence (Aquatic):

// Initialize touch controls for mobile devices.
// This gives phone/tablet players on-screen movement and interaction inputs.
this.touchControls = new TouchControls(gameEnv, this.touchOptions);

How this works in my Aquatic game:

  • Comment explains why touch controls are created here.
  • Helps reviewers quickly understand mobile input design.

6.2 Mini-Lesson Documentation

Code evidence (Aquatic notebook):

## CS 111 Course Alignment Rubric
### Required Evidence for College Credit

How this works in my Aquatic game portfolio:

  • Organizes evidence in rubric order for grading.
  • Connects gameplay code to CS111 objectives clearly.

6.3 Code Highlights

Code evidence (Aquatic):

// Create boss NPC instance from configured boss data.
// This line proves class-based object creation in a real combat flow.
const boss = new Npc(bossData, this.gameEnv);

// Register boss in game object list so update/draw loop processes it.
// Without push, boss would exist but never be updated or rendered by engine loop.
this.gameEnv.gameObjects.push(boss);

How this works in my Aquatic game:

  • Highlighted snippet proves instantiation + runtime registration.
  • Shows exactly where boss entities enter the update/draw pipeline.

Each topic is now separated with one focused code evidence block, inline comments, and one direct Aquatic-specific explanation.

Topic Index

Use this plain index instead of teleport buttons.

Project Checklist

Learning Objective Related Notes Project Evidence Required Assessment Method    
Writing Classes Classes Create minimum 2 custom character classes extending base classes Code review: Player.js, Npc.js, Enemy.js    
Methods & Parameters Methods Implement methods with parameters Code review: methods with 2+ parameters    
Instantiation & Objects Data Abstraction Instantiate game objects in level config Code review: GameLevel setup objects    
Inheritance (Basic) Classes Use class hierarchy (GameObject -> Character -> Player) Code review: extends chain    
Method Overriding Methods Override parent methods like update and draw Code review: polymorphic implementations    
Constructor Chaining Constructors Use super() in subclass constructors Code review: super(data, gameEnv) calls    
Iteration Iteration Use loops for arrays and animation Code review: for, forEach, while    
Conditionals Conditionals Use if else logic for state transitions Code review: nested conditions    
Numbers Mathematical Expressions Track position, velocity, score Code review: numeric properties    
Strings Strings Use names, paths, and dialogue strings Code review: string operations    
Booleans Booleans Use flags for game state Code review: boolean logic    
Arrays Arrays Use arrays for objects and level data Code review: array operations    
Objects (JSON) Data Abstraction Use object literals for config/state Code review: object structures    
Mathematical Operators Mathematical Expressions Use + - * / for gameplay math Code review: arithmetic in logic    
Boolean Expressions Booleans Use &&,   , ! in logic Code review: compound conditions
Keyboard Input Functions Implement WASD or arrow controls Testing: key handlers work    
Canvas Rendering Classes Draw sprites/backgrounds with canvas Code review: draw methods    
GameEnv Configuration Variables Configure canvas and game settings Code review: GameEnv.create    
Async I/O Methods Use async and await for runtime flows Code review: async methods    
JSON Parsing Data Abstraction Parse structured data payloads Code review: JSON.parse and object access    
Debugging Code Breakdown Use console logs, inspect state, tune hitboxes Demo: stable gameplay loop    
Jump to Code Breakdown Jump to Megalodon Boss Section Jump to Checklist Integration Layer Jump to Full Evidence Rubric

Code Practice Runners

Use the runnable examples below to practice core CS111 patterns.

Practice 1: Conditionals and Thresholds

Test phase checks with loops and if-statements.

%%js

// CODE_RUNNER: Practice #1 - Conditionals and Loops
const bossHp = 46;
const maxHp = 100;
const thresholds = [0.75, 0.5, 0.25];

thresholds.forEach((t) => {
  if (bossHp <= maxHp * t) {
    console.log(`Threshold triggered at ${t * 100}%`);
  }
});

Practice 2: Arrays and Objects

Loop through item data and compute score totals.

%%js

// CODE_RUNNER: Practice #2 - Arrays, Objects, and Iteration
const starfish = [
  { id: 'starfish_0', points: 5 },
  { id: 'starfish_1', points: 10 },
  { id: 'starfish_2', points: 15 }
];

let total = 0;
starfish.forEach((item) => {
  total += item.points;
});

console.log('Collected:', starfish.map((s) => s.id).join(', '));
console.log('Total points:', total);

Practice 3: Classes and Methods

Create an object, call methods, and watch state updates.

%%js

// CODE_RUNNER: Practice #3 - Classes and Methods
class MiniPlayer {
  constructor(name, hp = 100) {
    this.name = name;
    this.hp = hp;
  }

  takeDamage(amount) {
    this.hp = Math.max(0, this.hp - amount);
    return this.hp;
  }
}

const diver = new MiniPlayer('Aqua Hero', 120);
console.log('Start HP:', diver.hp);
console.log('After 25 damage:', diver.takeDamage(25));
console.log('After 200 damage:', diver.takeDamage(200));