Bemuse is a free and open source, web-based online rhythm action game.
Started in 2015, it is built on modern HTML5 technology and libraries such as React and Pixi.js.
Play the gamehttps://bemuse.ninja
Name
The original name of the game was “beat☆music☆sequence”. This name was derived from the file format that it uses, .bms (Be-Music Source). Later, I shortened the name to Bemuse, which happens to be a valid English word, meaning “to make confused”.
Origin
I built this game as a playground in applying software engineering principles and practices. It is also my graduation project. The project is open source, and has automated tests as well as a CI/CD pipeline around it.
Source code on GitHubhttps://github.com/bemusic/bemuse
Features
The gameplay is heavily inspired and influenced by Lunatic Rave 2, beatmaniaIIDX, and O2Jam. It is key sounded, meaning that each individual note gets its own sound. The song will sound off if you did not hit the notes correctly.
I created this project because most PC rhythm games only work on Windows, and I use a Mac. I originally designed this project for desktops and iPads, but being web based, the game could be made to work on more devices as mobile devices become more powerful over time, bringing a truly cross platform experience.
In 2018, a 3D mode is added, and the game can be enjoyed in mobile phones.
Party mode lets multiple people play Bemuse together.
As of 2019, Bemuse has over 15,000 monthly active players.

Development
Software engineering
The first few weeks of development consists solely of setting up the project: webpack with loaders for Jade, SCSS, and 6to5 (now Babel). webpack-dev-server, JSHint, JSCS, Jasmine, Istanbul, Code Climate, Travis CI, among others.
Developing software in an Agile way entails taking to heart that “Working software is the primary measure of progress.” Within a month, I deployed a teaser page with a technical demo, which proves that a rhythm game can indeed be built with current browser technology.
Software engineering for me is about striking a healthy balance between building the right thing and building it right. Although I want to ship things fast, I want to do it on top of a sound foundation.
Here are some technical choices that I felt very happy about when I look back:
Setting up linting tools from the start with pre-commit hooks and an automated code review bot.
Using test-driven development for the game logic. As far as I remember, it never broke. Without the tests I wouldn’t dare replacing Ramda with Lodash in one go. You can even run the unit tests online. A Japanese player once reviewed the game and said that “beta 版だが結構安定している。” (although the game is in beta, it is quite stable).
Setting up the app to allow multiple entry points. This lets me create pages to test components in isolation before Storybook existed, and also keep the teaser page and as well as our unit tests online.
Not using too many webpack plugins. This made upgrading to newer versions of webpack relatively painless.
Not using ES features lower than stage 2 or custom Babel plugins. This gave a lot of interoperability with tools that were not based on Babel, and also eased the transition to TypeScript compiler later on.
Using clean architecture and separating the core logic away from UI frameworks and libraries. This allowed me to replace Vue.js (v0.11) with Ractive (v0.7) and subsequently replace Ractive with React (v0.13).
Experiment with confidence and explore with safety
Clean architecture and tests enable me to experiment with new things. It lets me make many two-way door decisions. I can try out new (and perhaps not-so-mainstream) libraries and tools (such as webpack (at the time), Ramda, Ractive, and Bacon.js).
If they worked out well, then I could keep them (webpack being one example). Otherwise, if situation calls, I could switch to more boring, stable, tried-and-true solutions (such as Lodash, React, and Redux) at a relatively low cost.
It allowed me to update the project to use new tools and follow the general direction of JavaScript community:
For UI library I initially used Vue (v0.11), then migrated to Ractive (v0.7), then migrated again to React.
The project documentation used to reside directly on GitHub, then moved to Viewdocs, then to Read the Docs, and then with help from Resi Respati, to Docusaurus.
For testing framework I initially used Jasmine, then moved to Mocha due to Jasmine’s lack of support for Promises at the time despite Promises becoming mainstream already.
For testing library I initially used expectations (because Jasmine), and then later on migrated to Chai.
For test runner I started with plain Mocha running in the browser. I created my own test runner script that fires up a browser, navigates to the test page, and then collects the test result. It then gets replaced with Karma once it has a perfect webpack support. I did not migrate to Jest because our tests required access to browser’s APIs such as canvas.
For continuous integration I initially used Travis CI. But since there are many CI services in the market, I commenced a CI war and also added CircleCI, AppVeyor and Codeship. In the end CircleCI wins.
For Promise utilities, I initially tried out prfun and later replaced it with Bluebird which was more popular.
For code quality management I initially used Code Climate, then stopped using it due to subpar support for JavaScript, replacing it with Coveralls, and then with Codecov, before coming back to Code Climate after it improved support for JavaScript and TypeScript. I also threw in SonarCloud after SonarQube gets a nice TypeScript support.
For source code transpilation I initially used 6to5 which is later renamed to Babel. Getting tired of having to configure the plugins and presets and setting up regenerator, I replaced Babel with TypeScript compiler. One
tsconfig.jsonfile to rule ’em all!For code coverage instrumentation I initially used Istanbul but its lack of ES6 support at the time made me switch to Isparta, which has some issues and that led me to create
babel-plugin-__coverage__for use in Bemuse. That Babel plugin later got incorporated into a new major version of Istanbul to which I migrated the project to once again.For linting I initially used JSHint then later replaced with ESLint. Extra linting is done with TypeScript Compiler’s
strictmode, SonarCloud and Code Climate.For code formatting I initially used JSCS then later replaced with ESLint, and subsequently with Prettier.
Having a system for automated tests in place also allowed me to implement support for new file format in a single night.
@wosderge Thanks to unit tests. It saved a lot of manual testing time. https://t.co/Gkqf3mMfql pic.twitter.com/WUUw1eWjl4
— Bemuse · flicknote は JSConf.jp に行きます (@bemusegame) August 20, 2015
Music
Bemuse plays song files in Be-Music Source .bms file format. It is the same format used in Lunatic Rave 2 and others, and has a thriving community around it where ‘BMS artists’ collectively publish hundreds of original songs every year.
Most playable songs in the game, I reached out to BMS artists and asked for permission to use them in the game. Most artists are happy to allow me to use their songs for free, given that Bemuse is also a free game.
The background music for the game screens, as well as some playable songs, I composed myself.
- Tutorial song: BY☆MY☆SIDE
- Music selection song: BY☆MY☆SIDE (Ambient House Mix)
- Delay calibration song: AUTO±SYNCHRO
— Bemuse · flicknote は JSConf.jp に行きます (@bemusegame)