North (formerly Thalmic Labs), the creator of the Myo armband, was acquired by Google in June 2020. Myo sales ended in October 2018 and Myo software, hardware and SDKs are no longer available or supported. Learn more.
#MyoCraft: Point-and-click adventures at your fingertips!

I’m a big PC gamer. I have a recumbent bike set up in front of an old computer in my basement. It’s a great excuse both to get some exercise and to play some classic or indy games I may not get around to when I’m on my main gaming rig. Unfortunately, you can’t really use a mouse and keyboard on a bike, so that basically cut out a big section of otherwise ideal games. At least, it used to.
One of my favourite genres is the point and click adventure, and I’m glad it’s been making a comeback in recent years. Since Myo Script has built in mouse control, I use it to make a whole bunch of connectors to control a whole bunch of awesome adventure games with my Myo. I’m talking classics like Monkey Island and modern takes like Broken Age, the Blackwell series, and To the Moon. Now they’re playable with a single arm, which is ideal for when I’m biking.
These scripts are also ideal for showing off a neat extension to the function binding concept we discussed a few weeks ago. Let’s dive in!
Here’s the script:
scriptId = 'com.thalmic.adventuregames.Wadjeteye Published Adventures'
scriptTitle = "Wadjeteye Published Adventures"
scriptDetailsUrl = "https://market.myo.com/app/54790c55e4b05772f1d7693a/"
description = [[
Adventure Game Script
Play adventure games with your Myo armband! Play from your couch or excersize bike, or anywhere away from easy reach of a mouse.
Find an adventure game that isn't supported? Talk to us (@thalmicdev)
]]
link = [[ ]]
controls = [[
Controls:
- Move arm to control mouse
- Fist to left click
- Fingers spread to right click
- Wave in to hit spacebar
- Wave out to hit escape
- Double tap to recenter mouse
]]
knownIssues = [[
- Currently only detects Windows games
]]
function mouseClutch(clutch)
myo.controlMouse(clutch)
end
function leftClick(edge)
--myo.vibrate("short")
myo.mouse("left",edge)
end
function rightClick(edge)
myo.mouse("right",edge)
end
function escape(edge)
myo.keyboard("escape",edge)
end
function space(edge)
myo.keyboard("space",edge)
end
function centerMouse(edge)
if (edge == "down") then
myo.centerMousePosition()
end
end
mouseClutched = false
function clutchMouse(edge)
if (edge == "up") then
mouseClutched = not mouseClutched
end
myo.vibrate("short")
myo.controlMouse(not mouseClutched)
end
STANDARD_BINDINGS = {
fist = leftClick,
fingersSpread = rightClick,
waveOut = escape,
wavein = space,
doubleTap = clutchMouse
}
--STANDARD_BINDINGS = true
bindings = STANDARD_BINDINGS
supportedApps = {}
supportedApps["Primordia.exe"] = STANDARD_BINDINGS
supportedApps["Gemini Rue.exe"] = STANDARD_BINDINGS
supportedApps["a-golden-wake.exe"] = STANDARD_BINDINGS
supportedApps["Resonance.exe"] = STANDARD_BINDINGS
function onForegroundWindowChange(app, title)
myo.debug("onForegroundWindowChange: " .. app .. ", " .. title)
appFound = supportedApps[app] ~= nil
if (appFound) then
bindings = supportedApps[app]
myo.debug("Adventure Games active")
myo.setLockingPolicy("none")
end
myo.controlMouse(appFound)
return appFound
end
function activeAppName()
return scriptTitle
end
function onPoseEdge(pose, edge)
--pose = conditionallySwapWave(pose)
myo.debug("onPoseEdge: " .. pose .. ": " .. edge)
fn = bindings[pose]
if fn then
keyEdge = edge == "off" and "up" or "down"
fn(keyEdge)
end
end
function conditionallySwapWave(pose)
if myo.getArm() == "left" then
if pose == "waveIn" then
pose = "waveOut"
elseif pose == "waveOut" then
pose = "waveIn"
end
end
return pose
end`
This script lets you control a bunch of awesome adventure games published by Wadjeteye Games, like Resonance, A Golden Wake, Gemini Rue, and my favourite, Primordia. It’s set up to let you control a bunch of similar games while having slightly different bindings for each. That turned out not to be necessary. We’ll probably cover that approach in more detail another time, but for now I want to focus in on the onPoseEdge
definition:
function onPoseEdge(pose, edge)
--pose = conditionallySwapWave(pose)
myo.debug("onPoseEdge: " .. pose .. ": " .. edge)
fn = bindings[pose]
if fn then
keyEdge = edge == "off" and "up" or "down"
fn(keyEdge)
end
end
This is pretty close to the Saint’s Row approach, with one key difference. We use keyEdge
to let us have a single function for each pose, with either “down”
or “up”
getting passed in depending on if the pose is starting or ending (ie, edge
is “on”
or “off”
). The upside is that in your function you can just pass keyEdge
in as the edge value for your myo.keyboard()
or myo.mouse()
call, and thus the user can hold a key down as long as needed. You could still do this with the Saint’s Row approach, but you’d need two functions, and if you changed the key you’d have to make sure you did it twice. Messy.
Anyway, the downside is, of course, that weird looking keyEdge
definition:
keyEdge = edge == "off" and "up" or "down"
What.
What’s going on there?
Well, in many other language there exists a concept of an “in-line if statement” (or “ternary if”), which is basically designed to let you set a variable based on a condition, all in one line instead of like, five. For instance, in Java this
opacity = connected ? 1 : 0.25
is the same as this
if (connected) {
opacity = 1;
} else {
opacity = .25
}
Clearly the first is much more concise. Lua doesn’t exactly have this facility, unfortunately. What it does have is a specific way of evaluating logical operators. In Lua, x and y
actually evaluates to either false
(if x
or y
is false) or y
(if they are both true
). Similarly, y or z
evaluates to y
if y
is true, z
if y
is false
and z
is true
, and false
if neither are true
.
Confused? I made some tables:
Of course, "up"
and “down”
(x
and y
) don’t change, and are always true
(In fact, this will not work correctly if y
is false
. So our expression of x and y or z
actually looks like this:
Not so scary, I hope. Basically, it’s just
value = test_condition and value_if_true or value_if_false
With that onPoseEdge
, and a function like this bound to a pose:
function escape(edge)
myo.keyboard("escape",edge)
end
The user can hold easily any button as long as they like. This great for things like click and drag as well.
Anyway, that’s it for #MyoCraft this week! Send me ideas for future posts at MyoCraft@thalmic.com. And if you haven’t played any adventure games since the classic days of Lucas Arts and Sierra, well, check out the Blackwell Series, Primordia, and To the Moon. Playable with your Myo armband thanks to those connectors!
See you next week!