MariOCaml runs a Mario platformer in the browser from OCaml source
HTML 5 canvas implementation of Mario written in Ocaml
At a glance
- What is it?
- MariOCaml is an HTML5 canvas implementation of Super Mario Bros written entirely in OCaml and transpiled to JavaScript with js_of_ocaml, with procedurally generated levels and a director-driven game loop. It started as a Cornell CS3110 course project and is MIT licensed.
- Who is it for?
- Adopt MariOCaml if you are learning OCaml or js_of_ocaml and want a small, readable game that runs in a browser, since the whole project is eight modules and a Makefile. Skip it if you want a polished platformer, because the procedural generator is described as producing playable but not necessarily attractive maps, and there is no gamepad or level editor story to tell.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly OCaml, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What MariOCaml is and what it is not
MariOCaml is described as an HTML5 canvas web-browser implementation of the Super Mario Bros platformer written exclusively in OCaml. The key features list names three things: a 2D Mario platformer that emulates the platformer mechanics of Super Mario Bros, a web-based playable implementation with graphics and OCaml transpiled to JavaScript, and a procedural level generator that randomly generates levels. The game itself is described as including several basic enemies, blocks and items, with particle support, and it covers game-over and game-win states along with score and coin counts. There is a playable build online at the project homepage. The repository is not archived, the licence is MIT, the last push was on 2026-04-05, and there are no GitHub releases, so the commit history is the only version record. It was originally conceived for Cornell University's Fall 2015 CS3110 final project, by Matthew Hsu, Ashley Xue and Liam Bui, which explains both the scope and the educational framing.
The director model that holds the game state
The architecture is described as a director model, with the director maintaining state based on game objects and tiles, including Mario, items and obstacles. The Director module is the heart of the game: it executes the main game loop and performs updates on the map, the canvas and the objects, and it also executes the side-effectful collision detection. The Viewport module represents the slice of the game map currently in view and rendered on the canvas, which is how the game gets a camera without the map ever needing to fit on screen. Actors represents the characters, items and obstacles in the game world. Sprite is the visual representation of an object drawn on the canvas and holds the ability to create sprites from a template configuration based on the type of actor. Object is the abstract representation of a specific actor on the map, with the same template-based construction. Particle represents a non-collidable, visually oriented object on the map, covering destruction and creation effects. Draw contains the methods which update the canvas. The README notes that the implementation of enemies and items is designed to be easily extensible, which is the practical payoff of splitting rendering from state.
The procedural generator and its honest limitation
Levels are procedurally generated, pseudo-randomly, algorithmically creating an environment of textures and objects that are interactable. The underlying generation uses a grid system to generate objects, taking account of parameters such as proximity and location, and during play the director maintains the game state including the location and status of items, enemies and the character. The README is unusually candid about the result: the procedural generation generally generates a playable map, but due to the nature of random generation, maps may not be the most aesthetically pleasing. That is the trade-off of shipping a generator instead of hand-authored levels, and the phrasing is worth reading twice because it means the game is a demonstration of generation rather than a demonstration of level design. A player who opens the game expecting the first level of the NES original will not get it. A player who opens it expecting a different level every attempt, with the same physics and rules each time, will.
Why js_of_ocaml is the load-bearing decision
The game is interactive and graphical using js_of_ocaml, which enables cross-compilation of OCaml to JavaScript and allows MariOCaml to run in any modern web browser. This is the technical choice that makes the rest of the project possible, and it is also the one that constrains it. A game loop that drives an HTML5 canvas at frame rate, with a mutable director holding state, is an imperative program, and OCaml's expression-oriented style is an awkward fit for that. The director model is what makes it work, since keeping the mutable game state in one module and pushing everything else towards pure data keeps the imperative core small and explicit. The alternative approach, writing the game in JavaScript and calling it from OCaml, would have produced a smaller codebase but would have given up the point of the exercise. The project also carries a dune build configuration, a dune-project file, an .ocamlformat file and a mariocaml.opam file, so it is a conventional OCaml package rather than a loose set of scripts.
Building it: opam switch, make, and a local server
The build steps are short. The first is to make sure opam is installed, pointing at the official installation instructions if it is not. The second is to create a local opam switch in the project root and reload the environment, which prompts installation of the project dependencies.
opam switch create .
eval $(opam env)The third step is to run make all, which the README says compiles the binaries to the _build folder and runs the js_of_ocaml cross-compiler. The Makefile shows the three things that target chains together.
all:
make clean; make build; make webThe build step is dune build, the clean step is dune clean, and the web step serves the page locally.
web:
python3 -m http.server 8000Once that is running, the README says to open http://localhost:8000 in a web browser to run the game. There is also a build-release target that runs dune build with the release profile, and a comment in the Makefile noting that the resulting working website is found in _build/default/. One small friction point is worth flagging: the README numbers the steps 1, 2, 3 and then 5, so if you are following it literally you will notice the gap.
Where this project stops being useful
Three limits. The first is the generator, already mentioned, since maps are generated rather than designed and the README does not claim otherwise. The second is that the repository layout shows no test directory, no CI configuration beyond the usual gitignore and editor files, and no packaging of a release artefact, so the project is a piece of coursework that happens to be playable rather than a maintained game. There is a fonts directory, a sprites directory, a css directory and a screenshots directory alongside the OCaml sources and index.html, which is the shape of a web app with static assets served by the local server rather than a bundled single file. The third is the practical one for anyone planning to extend it. The Makefile serves the page with python3 -m http.server 8000, which is fine for a single developer but is not a deployment story, and there is no mention of how the game is hosted, cached or versioned for users beyond the static demo on the project homepage. And because the whole thing is written in OCaml with js_of_ocaml, any contributor needs to be comfortable with the OCaml toolchain and the cross-compilation step, which narrows the pool of people who can help.
What it is genuinely good for
Read as what it is, a course project that was released publicly, MariOCaml is a compact reference implementation of a browser game in a functional language, and the eight modules are small enough to read in an afternoon. The Director and Viewport split is the clearest lesson, since it separates mutable frame-by-frame state from the map data and makes the game loop readable. The Sprite and Object template-configuration approach is the second, showing how to separate visual representation from the abstract actor so a new enemy type does not require touching the drawing code. The procedural generator on a grid with proximity and location parameters is the third. For an instructor, the project has direct value, and the README says pull requests fixing bugs, adding functionality or improving organisation are welcome. For a learner, the online build at the project homepage means you can play it before deciding whether to read the code, which is a better way to decide than a screenshot in a README.
Editorial conclusion
Adopt MariOCaml if you are learning OCaml or js_of_ocaml and want a small, readable game that runs in a browser, since the whole project is eight modules and a Makefile. Skip it if you want a polished platformer, because the procedural generator is described as producing playable but not necessarily attractive maps, and there is no gamepad or level editor story to tell. Before you build, check that opam is installed, create the local switch with the documented command, and expect to serve the site at http://localhost:8000 to play it.
Frequently asked questions
What is MariOCaml?
It is an HTML5 canvas web-browser implementation of the Super Mario Bros platformer written exclusively in OCaml, with graphics produced by transpiling OCaml to JavaScript, a procedural level generator, basic enemies, blocks, items and particle support.
How do I build and run MariOCaml?
Create a local opam switch with `opam switch create .` and `eval $(opam env)`, then run `make all`, which cleans, builds with dune and serves the site. Then open http://localhost:8000 in a web browser to play.
What modules make up MariOCaml?
Director for the main loop and collision detection, Viewport for the visible slice of the map, Procedural Generator for level creation, Actors for characters, items and obstacles, Sprite and Object for the visual and abstract representations of actors, Particle for non-collidable effects, and Draw for updating the canvas.
Are the levels in MariOCaml hand-designed?
No. The README states that levels are procedurally generated pseudo-randomly on a grid using parameters such as proximity and location, and that the generation generally produces a playable map, though random generation means maps may not be the most aesthetically appealing.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/mahsu-mariocaml)Was this useful?