← projects

2D-EMG-GAME

Solo (building on Hugo Devoille's framework) · 2023–24

PythonsEMGBITalino (r)evolutionOpenSignalsNumPy / SciPyTCP socketsC#Steam InputUnityPygame

GitHub

Overview

Surface electromyography measures the electrical activity a muscle produces when it contracts. Prosthetics use it. So do rehabilitation and control interfaces. Entertainment barely does, and the little research that exists rarely leaves the forearm.

So I asked a blunter question. Can a muscle, any muscle you pick, be a game controller? A real one, mapped to real inputs, playing games that were never designed for it.

Live demo: muscle activation driving on-screen actions.

The control logic: four bands of effort

Treat the muscle as a dial rather than a button. Contraction strength is normalized against the player’s own maximum, then split into four bands, and each band triggers a different input.

Effort (% of your max)Input
0 – 25 %input 1
25 – 50 %input 2
50 – 75 %input 3
75 – 100 %input 4

One muscle, four controls. Add a second channel and the vocabulary multiplies.

Calibration therefore happens per muscle and per player, never as a fixed voltage. Percent of your own maximum is the only unit that survives moving the electrodes to another arm, another muscle, or another person.

Raw sEMG waveform
What arrives from the sensor: raw sEMG, before rectification and smoothing.
BITalino board wired to the EMG sensor and three electrodes
The acquisition chain: BITalino board, EMG module, three electrodes.

The chain

  1. Acquisition. A BITalino (r)evolution Plugged board with the BioSignals sensor kit, one EMG module per muscle, three electrodes each: IN+ and IN− straddle the muscle belly, REF sits on bone. The full assembly is documented on the Body Shape Control Suit page, since both projects use the same hardware.
  2. Recording. OpenSignals, for streaming and visual inspection. It is how you find out that a channel is picking up mains hum instead of a biceps.
  3. Processing. Python with NumPy and SciPy: band-pass, rectify, smooth, then compare against the calibrated maximum to land in one of the four bands.
  4. Output. The bands are emitted as controller inputs and routed through Steam Input. That last step is what takes the prototype out of the lab and into games nobody wrote for it.
Garments with EMG electrodes, cabling, BITalino board and battery
The multi-muscle setup. Electrodes carried by the garment rather than taped to skin, so a session takes minutes.

The bridge: Python on one side, Unity on the other

Steam Input covers commercial games. My own Unity game needed something more direct, so the two halves talk over a plain TCP socket.

On the Python side, BitalinoAcquisition.py opens a server on localhost:12345 and streams comma-separated values, one per reading, as soon as a client connects. On the Unity side, EMGData.cs opens a TcpClient, reads the stream inside a coroutine so the game loop never blocks, splits on the comma and parses each value with CultureInfo.InvariantCulture, because a decimal separator that changes with the machine’s locale will silently break a controller.

That seam keeps showing up in my work. The same shape drives Thoughts in Motion, where a Python classifier feeds a 3D scene, and it is the same problem I solved again in TRON and Chat-Room-API. One process owns the signal, another owns the display, and a socket carries the agreement between them.

The games

Three tiers, deliberately, because each one tests something different.

  • Python prototypes. A custom Flappy Bird as the training game. One muscle, one action, instant feedback. It is where a player learns what 40 % of their own strength actually feels like.
  • A 2D platformer in Unity. Several scenes, movement and jumping on muscle input. Continuous control, so the band boundaries have to hold steady or the character jitters.
  • Real Steam titles. The actual test. No cooperation from the game, no special build.
The custom 2D platformer running in the Unity editor
The Unity platformer: Level1, Level2, StartMenu, played entirely by contracting a muscle.
Presenting the EMG controller at the Festival of Learning
Handing the controller to strangers at the Festival of Learning.

Evaluation protocol

The test session was structured rather than improvised.

  1. Setup. Fit the electrodes, calibrate, explain the four bands.
  2. Training. Free play on the custom Flappy Bird until the mapping stops feeling arbitrary.
  3. Testing. Play Steam games with the EMG controller, watching for ease of use, accuracy and responsiveness.

Running that protocol in public at the Festival of Learning was its harshest version. Strangers, different body types, no time to fiddle. Anything that only worked on my own forearm failed within seconds.

What was hard

  • Signal, not data. Filtering, noise rejection and real-time interpretation all have to be right at the same time. Get one wrong and the controller feels haunted rather than simply broken.
  • Mapping is a design problem. Turning EMG features into controls that feel fair took more iterations than the signal processing did. Band edges that look clean on a plot can be exhausting to hold.
  • Calibration drifts. Muscle activity changes with fatigue, electrode placement changes with the person, and the room adds its own noise. The per-user maximum absorbs a lot of that. Not all of it, though, and sometimes a mid-session recalibration is the honest answer.

Why it matters

The research this builds on points the same way. MyoGuide uses sEMG to gamify wrist-extension training for stroke patients, and detects movement intention even in a paretic limb. Pedro Lopes’ work on proprioceptive interaction and muscle-propelled force feedback goes further, treating the body as input and output at once. The common thread: a muscle-driven interface can work in situations where a hand on a gamepad cannot.

That is the ambition here. Four bands of effort make a game controller. One that needs no fingers.

Documented in full in From Muscle to Screen: A Comprehensive Tutorial on Integrating surface EMG Detection in game and using it like a game-controller (2023–24). Built on top of Hugo Devoille’s acquisition framework.