CS111: Game Level - Castle Grounds (GameLevelOutside)
First level with NPC interactions and player customization
Game Level: Castle Grounds (GameLevelOutside)
Overview
Castle Grounds is the first game level introducing player customization, NPC interactions, and narrative progression. This demonstrates full OOP implementation with multiple game systems working together.
File Location
_projects/games/castle-game/levels/GameLevelOutside.js
Quick Concept
localStorage persistence stores small pieces of data in the browser so they survive page reloads. It is commonly used to remember player preferences like chosen skins without a server round-trip. Using localStorage allows simple, persistent customization across sessions.
Level Features
- Player Customization: Choose between 3 knight skins
- Persistent Storage: localStorage saves player preferences
- NPC Interactions:
- Sir Morty: Knowledge base AI providing hints
- DarkKnight: Triggers progression to next level
- Scene Transitions: Elaborate fade-in with starfield parallax
- Typed Dialogue: Animated text reveal for story progression
Configuration
- Canvas Dimensions: Width, height set per difficulty level
- Game Path: Asset paths for sprites and backgrounds
- Background: Castle exterior with parallax scrolling
Game Objects
- Player (customizable)
- Sir Morty (friendly NPC with AI Q&A)
- DarkKnight (progression trigger NPC)
- Environmental elements (coins, barriers)
Key Methods
init()- Initializes level with configurationupdate()- Updates game state each framedraw()- Renders all game objectshandleNPCInteraction()- Manages dialogue with NPCstransitionToMaze()- Level progression
Technical Implementation
- Complex object instantiation with configuration
- Async operations for image loading
- API integration for NPC AI responses
- State management for player progression
- Canvas rendering for parallax effects
Code Example - Level Configuration and Object Instantiation
class GameLevelOutside {
constructor(gameEnv) {
const width = gameEnv.innerWidth;
const height = gameEnv.innerHeight;
const path = gameEnv.path;
// Floor background configuration
const image_src_floor = path + "/images/projects/castle-game/castleOutsideV2.png";
const image_data_floor = {
name: 'floor',
src: image_src_floor,
pixels: { height: 989, width: 1582 }
};
// Player skin selection with localStorage persistence
const playerSpriteOptions = {
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 playerSkinStorageKey = 'castleGame.playerSkin';
const getPlayerSpriteSrc = (skinKey) => playerSpriteOptions[skinKey] || playerSpriteOptions.gray;
const getStoredPlayerSkinKey = () => {
try {
if (typeof window === 'undefined' || !window.localStorage) {
return 'gray';
}
const stored = window.localStorage.getItem(playerSkinStorageKey);
if (stored && playerSpriteOptions[stored]) {
return stored;
}
window.localStorage.setItem(playerSkinStorageKey, 'gray');
return 'gray';
} catch (error) {
return 'gray';
}
};
// Sir Morty NPC with AI knowledge base
const sir_morty = path + "/images/projects/castle-game/mortyKnight.png";
const sir_morty_data = {
id: "Sir Morty",
greeting: "Hello! I'm Sir Morty!",
src: sir_morty,
SCALE_FACTOR: 7,
INIT_POSITION: { x: 1259/1667 * width, y: 430/1137 * height },
expertise: "default",
chatHistory: [],
dialogues: [
"Enter the castle if you dare!",
"The Dark Knight awaits inside."
],
knowledgeBase: {
default: [
{
question: "What is inside the castle?",
answer: "Inside the castle lays a prisoner who has been locked away for years. The Dark Knight guards the castle and challenges anyone who dares to enter with an archery test, a maze, and a showdown inside the fortress."
},
{
question: "How do I win the game?",
answer: "To win the game, you need to successfully navigate through the castle grounds, complete the archery challenge, solve the maze, and defeat the Dark Knight in the fortress."
}
]
},
interact: function () {
AiNpc.showInteraction(this);
}
};
// Level object instantiation
this.classes = [
{ class: GameEnvBackground, data: image_data_floor },
{ class: Player, data: sprite_data_mc },
{ class: StrictNpc, data: sprite_data_darkKnight },
{ class: StrictNpc, data: sir_morty_data },
{ class: StrictNpc, data: sprite_data_closet },
{ class: SpriteSheetCoin, data: gem_data },
{ class: SplineBarrier, data: left_wall },
{ class: SplineBarrier, data: right_wall }
];
}
}
export default GameLevelOutside;
Key Features Demonstrated
- Constructor Parameter:
constructor(gameEnv)receives game environment - Configuration Objects: Multiple configuration objects for different game objects
- localStorage API:
window.localStorage.getItem()andsetItem()for persistence - Error Handling: Try/catch blocks for storage access (lines 27-34)
- Conditional Logic: Fallback values and validation (lines 31-35)
- API Integration:
knowledgeBaseobject provides context for NPC AI responses - Object Instantiation Array:
this.classesarray pairs classes with their configuration data - Multiple Object Types: Background, Player, NPCs, Collectibles, and Barriers all instantiated together