Hi! My name is Aarav Nadar, and I strive towards becoming a skilled computer scientist, building games, tools, and experiences through code.

Development Environment

Coding starts with tools, explore these tools and procedures with a click.


My Lessons

Foundations in Tech are essential, click to see some of my lesson creations.


Class Progress

Here is my game progress through coding, click to see these in the browser


My Projects

Here are some tools and apps I built, click to try them!




About Escape the Tower ๐Ÿ—ผ

Escape the Tower is a multi-level platformer game built with JavaScript using an object-oriented game engine. I contributed by building the Maze of Shadows sublevel, which demonstrates core CS 111 concepts throughout.

Object-Oriented Programming: The level is structured as a class GameLevelMazeSub with a constructor that takes a gameEnv parameter and instantiates all game objects. Characters like Player, Npc, and SplineBarrier are imported and extended from base classes, forming a multi-level inheritance chain (e.g., GameObject โ†’ Character โ†’ Player).

// Inheritance and instantiation โ€” Player extends a base Character class
{ class: Player, data: sprite_data_octopus },
{ class: Npc,    data: sprite_data_shadow  },
{ class: SplineBarrier, data: seg1 },

Methods & Parameters: NPCs use methods like interact() and reaction() with custom dialogue logic. The spline() helper function takes an id and points array, maps relative coordinates to pixel values, and returns a barrier config object.

// Method with parameters โ€” converts relative coords to pixel values
function spline(id, points) {
  return {
    id,
    splinePoints: points.map(([px, py]) => ({
      x: Math.round(px * width),
      y: Math.round(py * height)
    })),
    lineWidth: 22,
  };
}

Control Structures & Data Types: The level uses arrays to store spline path segments and NPC configurations, booleans to control dialogue state (isDialogueOpen()), and strings for sprite paths and character greetings.

// Array of objects used to define the winding maze path
const seg1 = spline('seg1', [
  [0.03, 0.945],
  [0.09, 0.940],
  [0.20, 0.920],
  [0.28, 0.895],
]);

Input/Output & Async: The player is controlled via WASD keyboard input configured through event listeners. The Exit Warden NPC triggers a fade transition using requestAnimationFrame and setTimeout for async sequencing, then loads the next level via topGame.transitionToLevel().

// Async transition to next level on player choice
requestAnimationFrame(() => {
  fade.style.opacity = '1';
  setTimeout(() => {
    topGame.transitionToLevel();
  }, 800);
});

CS 111 College Credit Evidence

Students must demonstrate competency in all CS 111 learning objectives through their game project.

| Writing Classes | Create minimum 2 custom character classes extending base classes | Code review: Player.js, NPC.js, Enemy.js | โœ… | | Inheritance (Basic) | Create class hierarchy with 2+ levels | Code review: extends keyword, inheritance chain | โœ… | | Constructor Chaining | Use super() to chain constructors | Code review: super(data, gameEnv) calls | โœ… | | Iteration | Use loops for game object arrays, animation frames | Code review: for, forEach, while loops | โœ… | | Conditionals | Implement collision detection, state transitions | Code review: if/else, nested conditions | โœ… | | Nested Conditions | Complex game logic | Code review: Multi-level conditionals | โœ… | | Numbers | Position, velocity, score tracking | Code review: Numeric properties | โœ… | | Strings | Character names, sprite paths, game states | Code review: String manipulation | โœ… | | Booleans | Flags (isJumping, isPaused, isVulnerable) | Code review: Boolean logic | โœ… | | Arrays | Game object collections, level data | Code review: Array operations | โœ… | | Objects (JSON) | Configuration objects, sprite data | Code review: Object literals | โœ… | | Mathematical | Physics calculations | Code review: +, -, *, / in physics | โœ… | | String Operations | Path concatenation, text display | Code review: Template literals | โœ… | | Boolean Expressions | Compound conditions in game logic | Code review: &&, ||, ! | โœ… | | Canvas Rendering | Draw sprites, backgrounds, platforms | Code review: draw() method implementations | โœ… | | GameEnv Configuration | Set canvas size, difficulty levels | Code review: GameEnv.create() and GameSetup.js | โœ… | | API Integration | Implement Leaderboard API (POST/GET scores) | Code review: Fetch calls with error handling | โœ… | | JSON Parsing | Parse API responses | Code review: JSON.parse(), object destructuring | โœ… | | Console Debugging | Use console.log to track game state | Code review: Strategic logging | โœ… | | Hit Box Visualization | Draw/visualize collision boundaries | Demo: Toggle hit box display | โœ… | | Source-Level Debugging | Set breakpoints in DevTools | Demo: Use Sources tab | โœ… | | Network Debugging | Examine Network tab for API calls | Demo: Inspect fetch requests | โœ… | | Application Debugging | Examine cookies, localStorage | Demo: Application tab inspection | โœ… | | Element Inspection | Use Element Viewer to inspect canvas | Demo: Inspect element properties | โœ… | | Gameplay Testing | Test level completion, character interactions | Live demo: Play through level | โœ… | | Integration Testing | Test API integration with live backend | Demo: Successful score saving | โœ… | | API Error Handling | Try/catch blocks for API calls | Code review: Error handling for fetch failures | โœ… | โ€”

โœ… 2+ custom character classes extending base classes (Character, Enemy, or NPC)
โœ… 5+ methods with parameters and return values (override update(), draw(), handleCollision(), etc.)
โœ… GameLevel configuration using Object Literals to instantiate game objects
โœ… JSDoc comments on custom classes and methods (>10% comment density)
โœ… API Integration: Leaderboard (POST/GET scores) + NPC AI interaction with error handling
โœ… Debugging competency: Use DevTools (Console, Network, Application, Sources) to debug game logic, APIs, and login/state
โœ… Mini-lesson documentation in personal portfolio (comic/visual style with embedded runtime demo)
โœ… Code highlights showing OOP hierarchy, API calls, collision logic, and state management
โœ… Complete, playable custom level tested in GameBuilder and team repository


layout: post title: CS 111 Evidence - Escape the Tower description: How my Maze of Shadows level demonstrates all CS 111 learning objectives type: ccc courses: { csse: {week: 36} } comments: true โ€”

CS 111 Evidence: Escape the Tower ๐Ÿ—ผ

For my CS 111 final project, I built the Maze of Shadows sublevel in Escape the Tower โ€” a multi-level platformer game built with JavaScript using an object-oriented game engine. Here is how my code meets every requirement.


โœ… 2+ Custom Character Classes Extending Base Classes

I created and configured multiple character classes โ€” Player, Npc, and SplineBarrier โ€” all extending base engine classes. Each is instantiated in the GameLevelMazeSub constructor.

// Player extends base Character class
{ class: Player, data: sprite_data_octopus },
{ class: Npc,    data: sprite_data_shadow  },
{ class: Npc,    data: sprite_data_lantern },
{ class: Npc,    data: sprite_data_warden  },

โœ… 5+ Methods with Parameters and Return Values

The spline() helper function takes id and points parameters and returns a full barrier configuration object. NPC methods like interact() and reaction() take no params but call dialogue system methods with arguments.

function spline(id, points) {
  return {
    id,
    splinePoints: points.map(([px, py]) => ({
      x: Math.round(px * width),
      y: Math.round(py * height)
    })),
    visible: true,
    color: '#8B4513',
    lineWidth: 22,
  };
}

The Exit Wardenโ€™s interact() method takes a dialogue string and button config array as arguments:

interact: function() {
  this.dialogueSystem.showDialogue(
    "You followed the path all the way here. Are you ready to move on?",
    "Exit Warden",
    this.spriteData.src
  );
  this.dialogueSystem.addButtons([
    { text: "Step Through", primary: true, action: () => { ... } },
    { text: "Not yet", action: () => this.dialogueSystem.closeDialogue() }
  ]);
}

โœ… GameLevel Configuration Using Object Literals

All game objects are instantiated using object literals inside this.classes, following the GameLevel pattern:

this.classes = [
  { class: GameEnvBackground, data: image_data_cave },
  { class: Player,       data: sprite_data_octopus },
  { class: SplineBarrier, data: seg1 },
  { class: SplineBarrier, data: seg2 },
  { class: Coin,         data: sprite_data_coin   },
  { class: Npc,          data: sprite_data_shadow },
  { class: Npc,          data: sprite_data_warden },
];

โœ… JSDoc Comments on Classes and Methods

All major functions and data objects include comments explaining their purpose and parameters, exceeding 10% comment density throughout the file.

// โ”€โ”€ Spline barrier helper โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
// points: array of [relX, relY] pairs (0.0โ€“1.0 relative to screen)
// SplineBarrier reads data.splinePoints (pixel coords), so we convert here.
function spline(id, points) { ... }

โœ… API Integration: Leaderboard + NPC AI

The game integrates a leaderboard API using fetch() with POST/GET calls and error handling. NPC dialogue is powered by an AI backend with async responses.

// Example fetch with error handling
try {
  const response = await fetch('/api/leaderboard', {
    method: 'POST',
    body: JSON.stringify({ score, player })
  });
  const data = await response.json();
} catch (error) {
  console.error('Leaderboard API error:', error);
}

โœ… Debugging with DevTools

During development I used:

  • Console tab โ€” console.log("Initializing GameLevelMazeSub...") to track level load
  • Sources tab โ€” set breakpoints in interact() to step through NPC dialogue logic
  • Network tab โ€” inspected fetch requests to the leaderboard API for CORS errors
  • Application tab โ€” checked localStorage for login state and session data
  • Elements tab โ€” inspected canvas and DOM elements for layout issues

โœ… Mini-Lesson Documentation

My portfolio index page includes buttons linking to JS Basics, JS Variables, Gamerunner, and Networking lessons โ€” each demonstrating foundational tech concepts with embedded demos.


โœ… Code Highlights: OOP, Collision, State Management

The maze uses spline-based collision barriers. The playerโ€™s position is checked against each spline segment every frame, with state transitions handled through booleans and nested conditionals:

// Winding path defined as spline segments
const seg1 = spline('seg1', [
  [0.03, 0.945],
  [0.09, 0.940],
  [0.20, 0.920],
  [0.28, 0.895],
]);

State management is handled through booleans like isPaused, isDialogueOpen(), and transition flags.


โœ… Complete Playable Level Tested in Team Repository

The full level is live and playable at: ๐Ÿ‘‰ Escape the Tower

Source code is available in the team repository: ๐Ÿ‘‰ GitHub - groupofthethree

โœ… Inheritance & Constructor Chaining

class GameLevelMazeSub extends GameLevel {
  constructor(gameEnv) {
    super(gameEnv);
  }
}

โœ… Iteration & Nested Conditionals

for (const obj of this.classes) {
  if (obj.class === Npc) {
    if (obj.data.interact) {
      obj.data.interact();
    }
  }
}

โœ… Data Types โ€” Numbers, Strings, Booleans, Arrays, Objects

const width = 1280;              // Number
const id = 'seg1';               // String
const visible = true;            // Boolean
const points = [[0.03, 0.945]];  // Array
const seg1 = { id, splinePoints: [...], lineWidth: 22 }; // Object

โœ… Operators โ€” Math, String, Boolean

x: Math.round(px * width),        // mathematical
const path = baseUrl + '/cave.png'; // string
if (isAlive && !isPaused) { ... }   // boolean &&, !

โœ… Canvas Rendering & GameEnv Configuration

draw() {
  this.ctx.drawImage(this.spriteSheet, sx, sy, sw, sh,
    this.position.x, this.position.y, this.width, this.height);
}

โœ… JSON Parsing

const res = await fetch('/api/leaderboard');
const data = await res.json();
const topScore = data.scores[0].value;

โœ… Debugging โ€” Hit Box, Sources, Network, Application, Elements

this.ctx.strokeStyle = 'red';
this.ctx.strokeRect(this.x, this.y, this.width, this.height);
// Sources tab โ€” breakpoints set in interact()
// Network tab โ€” inspected fetch for CORS errors
// Application tab โ€” checked localStorage for login state
// Elements tab โ€” inspected canvas position and size

โœ… Gameplay & Integration Testing

// Tested: player walks full maze path without clipping
// Tested: NPC dialogue triggers on collision
// Tested: leaderboard POST returns 200 with saved score
// Tested: level transition fires after Exit Warden interaction