🚀 SOMARIO – Web Development End Term Project
A custom 2D game engine and platformer game built from scratch using vanilla JavaScript, HTML5 Canvas, and CSS3. This project demonstrates a modular Entity-Component-System (ECS) architecture, custom physics, and state management without relying on external game libraries.
Technical Highlight: Since Object-Oriented Programming (OOP) is important for JavaScript, this project has used OOP along with DOM manipulation and Asynchronous JavaScript.
- Project Type: Web Development End Term Project
- Engine Name: Somario
- Game Title: Run Mario Run
- Tech Stack: HTML5, CSS3, JavaScript (ES6 Modules)
- Custom ECS Engine: Built on a modular Entity-Component-System architecture for scalable game logic.
- Physics & Collision: Custom AABB (Axis-Aligned Bounding Box) collision detection and resolution.
- Game Loop: Optimized
requestAnimationFrameloop handling logic updates and rendering separately. - Audio System: Web Audio API integration for synthesized SFX and background music.
- Dynamic UI: Responsive menus, HUD, and game-over screens using HTML/CSS overlays interacting with the Canvas. 30-40% usage of DOM.
- Level Generation: Procedural-style placement of platforms, lava, and enemies.
The project is structured to separate the core engine logic from the specific game implementation using ES6 Modules.
These files constitute the reusable game engine logic, decoupled from specific game content.
-
engine/ecs/Entity.js:- The fundamental base class for all objects in the game (Player, Enemy, Platforms).
- Manages core properties:
x,ycoordinates,width,height, and state flags likealiveandsolid. - Provides empty
update(dt)andrender(ctx)methods to be overridden by subclasses.
-
engine/ecs/systems/:MovementSystem.js: Handles the physics simulation. It applies gravity, velocity, and resolves collisions between dynamic entities (like the Player) and static environment blocks (Bricks).CollisionSystem.js: Optimization layer that detects overlaps. It provides helper methods to find all colliding pairs in the current frame.CombatSystem.js: Encapsulates game rules for combat.- Checks collisions between Bullets and Enemies.
- Handles Player melee attacks using hitboxes (
attackBox). - Manages damage application, entity death states, and triggers score/SFX events.
-
engine/physics/Collision.js:- Contains pure mathematical functions for collision detection.
- Exports
aabb(a, b): Performs Axis-Aligned Bounding Box checks to determine if two rectangles intersect.
-
engine/input/Keyboard.js:- A static class managing user input.
- Listens for
keydownandkeyupevents globally. - Stores the state of keys in a dictionary (
keys) for efficient polling viaKeyboard.isDown(code).
These files utilize the engine to build "Run Mario Run".
-
game/main.js:- Entry Point: Bootstraps the application.
- UI Management: Handles DOM overlays for the Start Screen, HUD (Score, Lives), Pause Menu, and Game Over screens.
- Audio: Initializes the Web Audio API context and manages background music/SFX.
- Game Loop: Runs the
requestAnimationFrameloop, calculating delta time (dt) and delegating updates to the active Scene.
-
game/TestScene.js:- Represents the main level of the game.
- World Generation: Procedurally places
Brickplatforms,Lavapits, and decorative elements (Cloud,Grass,Bird). - Entity Spawning: Instantiates the
Playerand placesEnemyunits based on selected difficulty. - Camera Logic: Implements a side-scrolling camera that follows the player's X position.
- Game Logic: Checks for win/loss conditions (lives < 0, falling in lava, killing all enemies).
-
game/entities/:Player.js: The hero character. Contains logic for movement physics (jump, run), animation state switching, and input handling.Enemy.js: AI-controlled opponents. Implements simple patrolling behavior and interaction logic.Bullet.js: Projectiles fired by the player.
index.html: The main container. It loads the modules and provides the DOM structure for the Canvas and UI overlays.style.css: Handles the visual styling of the menus, HUD, and responsive layout adjustments.
Because this project uses ES6 Modules (import/export), browsers will block execution if you simply open the index.html file directly due to CORS (Cross-Origin Resource Sharing) policies. You must serve the files via a local web server.
- Open the project folder in Visual Studio Code.
- Install the Live Server extension .
- Right-click on
index.htmlin the file explorer. - Select "Open with Live Server".
If you have Python installed, you can run a simple HTTP server from the terminal:
- Open a terminal/command prompt in the project root folder.
- Run the following command:
# For Python 3 python -m http.server 8000 - Open your browser and go to
http://localhost:8000.
If you have Node.js installed:
- Run
npx http-server .in the terminal. - Open the URL shown in the terminal.
- Arrow Keys / WASD: Move Left/Right
- Up Arrow / W: Jump
- Space: Attack / Shoot Projectile
- P: Pause Game
- Esc: Exit to Main Menu
- Objective: The goal is to defeat all enemies on the map to win the level.
- Combat: You must use your attack (Spacebar) to defeat enemies. Simply touching them will cause you to lose a life.
- Hazards: Avoid falling into the lava pits.
- Lives: You start with 3 lives. If you lose all of them, it's Game Over.
Contributions are welcome! If you'd like to improve the engine or add new features:
- Fork the repository.
- Create a new branch for your feature (
git checkout -b feature/AmazingFeature). - Commit your changes (
git commit -m 'Add some AmazingFeature'). - Push to the branch (
git push origin feature/AmazingFeature). - Open a Pull Request.