One of the many problems I solved in my
MMO that I single-handedly developed over 5 months of many 12-hour days, was the Cube Violin.
Violin represented in code
I wanted to get this working on the client before I made it work multi-player. Sometimes you’re better off doing something client-only first, and sometimes you are not.
Data
A few months before I started development, I started playing violin in real life. This gave me a wish list:
- Four strings, each with different character
- Fretless (sliding frequency, unlike a guitar)
- Louder when the bow is near where you hold it, because there is more weight.
- Allow techniques like playing two strings at once, lifting the bow, and stopping a string by not lifting the bow.
As I programmed and designed, I added the code and data that I needed to accomplish this.
Each string is smoothed by lerping via this code:
_rendered_volume = lerp_time(_rendered_volume, volume, 20.0, dt);
Freya Holmer’s video
(See on frame-rate independent lerp; this will not be the only time I used their lerp method for this violin.)
Music is patterny math, so I found a pattern to multiply pitch:
MAJOR_SECOND :: 1.12244;
MINOR_SECOND :: 1.05945;
From observing the following pattern (en is E natural, fs is F sharp):
To give each string character, they are each square, sawtooth, sine, and triangle waves. This fits into the World of Squares aesthetic. Making the violin sing is uneventful; I always play an audio file on loop, and bend its volume and pitch according to the data I laid out, which is affected by your input.
Controls
(In the first half of the above video, watch the bow subtly lift off the strings. That corresponds to my clicks. Clicking raises the bow, because in real life gravity lets the bow rest and it takes effort to raise it.)
As a game designer, I have two things in mind:
a game I made inspired by his work
- How can we give interesting audiovisual feedback? (this results in polish and immersion)
- How can we re-imagine interesting peripherals and inputs? (this results in fun to control games. See Bennet Foddy’s work, for example, and .)
The bow is very important, so I gave that the analog mouse control. Horizontal speed plays the bow, and vertical position on the window chooses the strings. This feels an intuitive model to real life.
The keyboard is almost a perfect fingerboard, except its X position quantized per key rather than analog. This is unfortunate, and when I showed it in a discord call to someone who helped produce music with their friends, they suggested it should be quantized to a musical scale instead of chromatic, so people who can’t make music can have fun too. With only 10 keys per string, this also lets you reach higher notes. I was uncertain, but I’m glad I took this choice in hindsight.
Drawing the violin
I created the violin in code, piece by piece.
Making it rotatable
I wanted it to sit on your cube shoulder and rotate arbitrarily. To do this, I can multiply any coordinate by normalized axes like this
new_position = old.x*x_axis + old.y*y_axis + old.z*z_axis
So I only need to punch in the numbers for what the violin looks like when placed where its longest part is on the X axis of (1,0,0), and Y axis (0,1,0) is up. Then, when drawing, I will give it axes so it looks like it’s on your shoulder.
Each piece may be rotated and have its own arbitrary axes, like the neck and fingerboard:
String deformation
I also deformed the strings so they look like they’re pressed flat against the fingerboard, by drawing it in two parts. It’s accurate to how a real violin works, that each time you halve the string, it is one octave. See the comment on (1/(2^x)) and how “
cut_percentage” is used:
For specifics, check the full code for drawing violin
1
Networking the violin
VOLUME WARNING (10 violins at once)
It would be fun if some players got together and did a Cube Orchestra. Maybe they could play christmas carols! And I’d maybe I’d add cellos and double-basses! That’s one reason I wanted this in my MMO.
I thought that if you send packets in real time to update the playing state of other players’ violins, it will sound bad. But I knew if I would store a backlog before sending it, I can use a tiny delay to outdo the variance.
And I use a server-authoritative timestamp that the clients count on their own and synchronize so that everyone can be on the same page about when something happened.
To save space, instead of saving the whole violin state 1000 times per second, I only store when things change. These are called violin events.
The whole batch of data says when it started and the initial state, then each event stores the milliseconds to add from the last event. Clients add to this buffer each frame, then send it when it’s been 25 milliseconds.
The server receives it, then parrots it to nearbly clients very simply. While I’m at it, because I can serialize violin events now, I might as well add recording functionality on the server, so I can pre-record NPC songs.
(A funny thing you can notice is that NPCs animate all values to 0 when they are done playing to ready for the next song, and so this bends the pitch. That’s a bug, but you can see it too, watch the fat string!)
Maybe they just like sliding their fingers down the fingerboard. Not a bug… a feature?
NPCs playing songs
Just now I pointed out that I can save these packet buffers to a file to replay later. As an admin on the server, I can send an action to begin recording, then save to a file.
And so Riff, the pink violinist NPC, can now play songs passively, and perform demonstrations for their tutorial:
NPCs can play these stored songs by remembering where they were in the buffer, then pushing a new packet just like a player would push.

Server: The API for NPCs is simple, either
npc_stop_playing_violin_song or
npc_start_playing_violin_song. The songs are globals loaded when the server starts:
(…I had said that I used
Freya Holmer’s lerp more than just for strings. It is in the client knowing what offset to use for the violin updates:)
See the full code for the NPC sending violin packets here2.
And see the full code for the clients playing violin packets from the server here3.
Conclusion
In my 35,000 line of code MMO, this system was straightforward to implement. It used the tactile positional nature of keyboard keys, and the analog nature of the mouse, to make a fun playing experience. It had a delta-based data structure to show changes of values to save bandwidth, and it worked even for players with ten living clones.
I made this because I like the violin, and this game was to be full of ideas I liked. (This is common advice among artists, but will not necessarily produce something popular.)
To me, this translation of all the things I love about the violin in real life into a game, to share among people who might not be able to afford a violin (a decent starter violin is $1500? rental is a good option!), or can’t make loud noises in their apartment, or don’t have friends they can share music with. To give them an MMO to play music with their friends, or go to a distant place in the forest and practice by themselves, was my only goal for this.
Though, nobody really used it.
~
~
~
~
~
~
Footnotes