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.
Myo Scripting Orientation and Gestures Part Six: Beyond Scripting

Part Six: Beyond Scripting
Hello again. This is the last part of our advanced Myo Script tutorial on orientation and gestures. You can find parts one, two, three, four and five here. Today, I’ll leave you with the final Race The Sun script as well as some thoughts on when you might want to use something other than Myo Script to Myo-enable a game or app.
But first, the final script:
scriptId = 'com.thalmic.examples.racethesun'
scriptTitle = "Race The Sun"
scriptDetailsUrl = "https://market.myo.com/app/5478fb74e4b05772f1d76920"
description = [[
Race the Sun
From the Steam description: You are a solar craft. The sun is your death timer. Hurtle towards the sunset at breakneck speed in a futile race against time. Delay the inevitable by catching energy boosts which reverse the setting sun - if only for a moment.
Problems? Talk to us (@thalmicdev)
Demo here: http://www.kongregate.com/games/flippfly/race-the-sun ]]
link = [[http://store.steampowered.com/app/253030/]]
controls = [[
Controls:
- Hold wave out enable/disable mouse control
- Wave in to click
- Fist to center your yaw/roll, and then yaw left/right to fly left/right
- Fist also hits "enter" on menus
- Wave up/down to jump if you get a jump pickup
- Fingers spread to hit escape and pause or back up in the menus
]]
knownIssues = [[
- None
]]
centreYaw = 0
centreRoll = 0
deltaRoll = 0
YAW_DEADZONE = .1
ROLL_DEADZONE = .2
MOUSE_CONTROL_TOGGLE_DURATION = 1000
PI = 3.1416
TWOPI = PI * 2
flyingLeft = false
flyingRight = false
togglingMouseControl = 0
mouseEnabled = true
printCount = 0
function onForegroundWindowChange(app, title)
--myo.debug("onForegroundWindowChange: " .. app .. ", " .. title)
local titleMatch = string.match(title, "Play Race The Sun, a free online game on Kongregate") ~= nil or platform == "MacOS" and app == "unity.Flippfly.RaceTheSun" or platform == "Windows" and app == "RaceTheSun.exe"
myo.controlMouse(titleMatch and mouseEnabled);
if (titleMatch) then
myo.setLockingPolicy("none")
end
return titleMatch;
end
function onPoseEdge(pose, edge)
--myo.debug("onPoseEdge: " .. pose .. ", " .. edge)
if (edge == "on") then
if (pose == "fist") then
centre()
if (mouseEnabled) then
toggleMouseControl()
end
elseif (pose == "fingersSpread") then
escape();
elseif (pose == "waveIn" or pose == "waveOut") then
if (math.abs(deltaRoll) > ROLL_DEADZONE) then
jump()
elseif (pose == "waveIn") then
leftClick()
else
if (mouseEnabled) then
toggleMouseControl();
else
togglingMouseControl = myo.getTimeMilliseconds();
end
end
end
else
togglingMouseControl = 0
end
end
function activeAppName()
return "Race The Sun"
end
function centre()
--myo.debug("Centred")
centreYaw = myo.getYaw()
centreRoll = myo.getRoll()
myo.controlMouse(false);
myo.vibrate("short")
myo.keyboard("return", "press")
end
function onPeriodic()
if (togglingMouseControl > 0 and myo.getTimeMilliseconds() > (togglingMouseControl + MOUSE_CONTROL_TOGGLE_DURATION)) then
togglingMouseControl = 0
toggleMouseControl()
end
if (centreYaw == 0) then
return
end
local currentYaw = myo.getYaw()
local currentRoll = myo.getRoll()
local deltaYaw = calculateDeltaRadians(currentYaw, centreYaw)
deltaRoll = calculateDeltaRadians(currentRoll, centreRoll);
printCount = printCount + 1
if printCount >= 200 then
--myo.debug("deltaYaw = " .. deltaYaw .. ", centreYaw = " .. centreYaw .. ", currentYaw = " .. currentYaw)
--myo.debug("deltaRoll = " .. deltaRoll .. " currentRoll = " .. currentRoll)
printCount = 0
end
if (deltaYaw < -YAW_DEADZONE) then
flyLeft()
elseif (deltaYaw > YAW_DEADZONE) then
flyRight()
else
flyNeutral()
end
end
function flyLeft()
if (flyingRight) then
--myo.debug("Not flying right");
myo.keyboard("right_arrow","up")
flyingRight = false
end
if (not flyingLeft) then
--myo.debug("Flying left");
myo.keyboard("left_arrow","down")
flyingLeft = true;
end
end
function flyRight()
if (flyingLeft) then
--myo.debug("Not flying left");
myo.keyboard("left_arrow","up")
flyingLeft = false
end
if (not flyingRight) then
--myo.debug("Flying right");
myo.keyboard("right_arrow","down")
flyingRight = true
end
end
function jump()
--myo.debug("Jump!")
myo.keyboard("space","press")
end
function flyNeutral()
if (flyingLeft) then
--myo.debug("Not flying left");
myo.keyboard("left_arrow","up")
flyingLeft = false
end
if (flyingRight) then
--myo.debug("Not flying right");
myo.keyboard("right_arrow","up")
flyingRight = false
end
end
function calculateDeltaRadians(currentYaw, centreYaw)
local deltaYaw = currentYaw - centreYaw
if (deltaYaw > PI) then
deltaYaw = deltaYaw - TWOPI
elseif(deltaYaw < -PI) then
deltaYaw = deltaYaw + TWOPI
end
return deltaYaw
end
function toggleMouseControl()
mouseEnabled = not mouseEnabled
myo.vibrate("medium")
if (mouseEnabled) then
--myo.debug("Mouse control enabled")
centreYaw = 0
flyNeutral()
else
--myo.debug("Mouse control disabled")
end
myo.controlMouse(mouseEnabled);
end
function leftClick()
--myo.debug("Left click!")
myo.mouse("left", "click")
end
function escape()
--myo.debug("Escape!")
centreYaw = 0
myo.keyboard("escape","press")
end
Note that it has a scriptDetailsUrl link now. That’s because you can actually go and download this script in the Myo Market. Make sure you remember to update that property as you are submitting your script!
Beyond Scripting
That’s all for Myo Script! Quite easy and powerful, no? We haven’t talked about the gyroscope and accelerometer support, or the MIDI support, but that’s basically it. We’ll have to leave those for another tutorial.
You may be wondering at this point why you would ever use any of the actual SDKs. First, if you want to target a mobile platform, scripting is not available. You’ll have to use the full Android or iOS SDK.
Second, if you actually control the application’s source, asking the user to install a script may be a needless extra hassle.
Third, there may be other easy integrations available using some of the third party bindings our developer community has built. For example, there is a Javascript package that lets you integrate Myo controls directly into a webpage.
But finally, there is a whole suite of problems you can run into by not knowing the state of the app you are targeting. We almost hit this in Race The Sun. How do we know if the user is in the menu or not? We solved that with a gesture to let the user enable/disable the mouse, but wouldn’t it be better if mouse control just automatically turned on and off at the right time? What if we wanted to have several sets of totally different controls for different stages or minigames? Myo enabled quicktime events?
What if the window title is not a useful identifier?
Clearly, though Myo Scripts are a great way to Myo-enable existing apps, rapidly prototype experiments, and give users the power to use their Myo armband to control the things they want, there are still times when a full SDK is the way to go.
If you're hungry for more, check out #MyoCraft, an ongoing series full of Myo developer tips, including a bunch of more sophisticated Myo Script techniques. If you ever get stuck or have any questions, don’t forget you can always jump on Developer Forums! Follow the official @ThalmicDev Twitter account and sign up for our newsletter to stay up to date with all the latest Myo development news. And of course, stay tuned to this blog (RSS).
Good luck, and happy coding!