A close friend of mine just released a game! You should probably check it out if you like games.
Ballistic Zen is a first person open world platformer with a unique movement system based on old-school air-strafing, updated for the modern age. Simple to pick up but difficult to master, Ballistic Zen celebrates the joy and meditation of movement in games.
Of course, I decided to play it with the Wii Balance Board.
Controls and controllers have always been a passion of mine, so when a colleague decided to sell his Balance Board, I immediately seized the opportunity. My glee was then almost-as-immediately shattered when I realised that opportunities to actually use the thing would be few and far between. (Playing Wii Fit in 2022, I found it…disappointing.)
Anyway, when Alex finally published Ballistic Zen, I knew that the time had come.
The final control scheme I ended up with uses the Balance Board and Wiimote/Nunchuk in concert. At first, I wanted to use the Balance Board on its own, but the game requires too many fast direction changes, and I couldn’t keep up without falling over. Using multiple sensitivity zones (that is, making the edges of the board more sensitive than the centre) helped – but in the end I had to couple it with the Wiimote.
Watching the video, you’ll notice that you turn much faster using the Wiimote and Nunchuk than you do using the Balance Board, and might reasonably ask if the Balance Board is really necessary. Well, it isn’t. But it isn’t completely useless, either. I did try a control scheme without the Balance Board, and though it worked, it lacked some of the fine control afforded by the full scheme. In short, it was more awkward. Moreover, with any motion control scheme, the more sensors you use, the more stable and reliable the signal, and in this case using the Wiimote, Nunchuk and Balance Board together gave the best result.
The B and Z (trigger) buttons are used for tight turns, inspired by Ballistic Zen’s actual gamepad control scheme.
Here’s the button mapping:
And here’s the FreePIE script:
def armsUp():
return wm.acceleration.y < lift_arms_threshold and wm.nunchuck.acceleration.y < lift_arms_threshold
def shouldClick():
global arms_currently_up
global last_click_time
if (wm.buttons.button_down(WiimoteButtons.DPadDown)):
return True
if armsUp():
if arms_currently_up and time.clock() - last_click_time > click_debounce:
return True
elif not arms_currently_up:
arms_currently_up = True
last_click_time = time.clock()
else:
arms_currently_up = False
return False
def shouldJump():
return wm.buttons.button_down(WiimoteButtons.A)
def maprange(input, imin, imax, omin, omax):
return (omax-omin)*((input-imin)/(imax-imin)) + omin
def deltaX(centre_of_gravity):
turn = 0
if (wm.buttons.button_down(WiimoteButtons.B)):
turn += turn_enhancer_strength
return turn
if (wm.nunchuck.buttons.button_down(NunchuckButtons.Z)):
turn -= turn_enhancer_strength
return turn
turn += maprange(wm.nunchuck.acceleration.y, 0, lift_arms_threshold, 0, arm_steering_sensitivity)
turn -= maprange(wm.acceleration.y, 0, lift_arms_threshold, 0, arm_steering_sensitivity)
if (abs(centre_of_gravity) > bb_deadzone):
turn += centre_of_gravity * bb_sensitivity
if (abs(wm.nunchuck.stick.x) > nunchuck_deadzone):
turn += wm.nunchuck.stick.x * nunchuck_sensitivity
return turn
def deltaY(stick):
if (abs(stick) < nunchuck_deadzone):
return 0
return -(stick * nunchuck_sensitivity)
if starting:
import time
bb = wiimote[1].balanceBoard
wm = wiimote[0]
nunchuck_sensitivity = 0.1
nunchuck_deadzone = 10
bb_deadzone = 2
bb_sensitivity = 0.1
bb_deadzone_2 = 6
bb_sensitivity_2 = 0.4
lift_arms_threshold = -6.5
turn_enhancer_strength = 10
arm_steering_sensitivity = 3
click_debounce = 0.25
last_click_time = 0
arms_currently_up = False
mouse.deltaX = deltaX(bb.centerOfGravity.x)
mouse.deltaY = deltaY(wm.nunchuck.stick.y)
mouse.setButton(0, shouldClick())
mouse.setButton(1, shouldJump())
keyboard.setPressed(Key.E, wm.nunchuck.buttons.button_down(NunchuckButtons.C))
keyboard.setPressed(Key.Escape, wm.buttons.button_down(WiimoteButtons.Plus))
keyboard.setPressed(Key.Tab, wm.buttons.button_down(WiimoteButtons.Minus))
keyboard.setPressed(Key.Q, wm.buttons.button_down(WiimoteButtons.One))
keyboard.setPressed(Key.A, wm.buttons.button_down(WiimoteButtons.Two))
keyboard.setPressed(Key.R, wm.buttons.button_down(WiimoteButtons.Home))
Ballistic Zen is available on Steam and on itch.io.
Oh, and if you like this kind of thing, check out BadRAM’s custom Ballistic Zen controller.