TLbind

About

TLbind is a system which turns a mass of keyboard/joystick input into easy-to-use game-oriented controls. Making this divide also makes it easy to rebind controls, enable or disable keyboard or joystick input at will, and make digital and analogue input work easily together. It's goal is to make it easy to add professional-style configurable "2 sets of keys + optional joystick" controls to Love2D games.

It's under the ZLIB license.

Download

Direct from Dropbox

Contact


Setup

Procedural style

  1. Add TLbind.lua to your game's folder
  2. In love.load, add the code TLbind,control = love.filesystem.load("TLbind.lua")()
  3. In love.update(), add the code TLbind:update()

Object-oriented style

  1. Add TLbind.lua to your game's folder
  2. Assuming your player object is called "player", and you want its controls to be listed in player.control, use the code player.controlOptions, player.control = love.filesystem.load("TLbind.lua")()
  3. In your player object's update function (or otherwise once per frame), call TLbind:update()
  4. TLbind itself acts like an object, so you can give each player their own separate TLbind, if you so desire (could be handy for splitscreen)


FAQ

Q) How do I know when a control is pressed?
A) Whenever a control is pressed or held, control[control name] will be true. You could use it with a statement like if control.up then...
Q) How do I change a control?
A) To bind a "fire" control to the third button of joystick 0, for example, you would say TLbind.joyBtns[0][3]="fire". From then on, control.fire would be true whenever Joy0 button 3 is pressed.
Q) How do I know if the player has simply pressed the button, instead of holding it? What if I want to know when it's released?
A) When any control is first pressed, control.tap[control name] will be true for one frame. Likewise, when it's released, control.released[control name] will be true for one frame. These would be used the same way you'd use a normal control - if control.tap.jump then. You can also use the control.controlPressed and control.controlReleased callbacks (see below).
Q) What functionality does TLbind have?
A) It separates controls (things your game cares about "jump", "left", etc.) and input (spacebar, joystick coordinates, etc.). This allows a game's controls to be easily configured at any time; lets a game have multiple inputs per control (or controls per input); and makes coding simpler. It makes it easy to bridge analogue and digital control; disable keyboard or joystick input easily; detection of taps instead of holding (no more "hold jump to bounce over and over the second you touch the ground"); and can optionally restrain analogue input (and associated digital input) to a circle (preventing the all-too-common "you run faster diagonally" bug)
Q) Is it hard to use?
A) I tried to make it as simple as possible, and the default bindings are an example of every feature: They demonstrate jump and attack controls bound to both keyboard and joystick buttons, and joint digital/analogue movement controls taking input from WASD, arrowkeys, joystick axes, and joystick hat at the same time. And configuring all that only takes six lines of code!
Q) What's the difference between digital and analogue controls, and how do you make them work together?
A) In TLbind, digital controls are keys or buttons, and are represented as either true or false. Analogue controls take input from joystick axes or balls, and are represented as a decimal between -1 and 1, with 0 being centered. TLbind lets you map an analogue control to two digital controls, which makes the analogue input trigger the digital controls and the digital input push the analogue control to -1 or 1. As an example: In the default bindings, pressing the joystick a little to the left would make control.horiz == -0.22191, control.left == true, and control.right==false.


Functions

TLbind:update

TLbind:update()

This updates the controls, and thus should be called once each frame. Please note that it has a colon, not a period.

control.controlPressed

control.controlPressed(c)

This callback works just like love.keypressed, except for controls (meaning it'll work properly with binding changes and joystick input). It gets called exactly once when a control is activated.

string c
The name of the control that was pressed.

control.controlReleased

control.controlReleased(c)

This callback works just like love.keyreleased, except for controls.

string c
The name of the control that was released.


Input types and configuration

Bindings are managed under TLbind (procedural example) or player.controlOptions (OOP example). A list of bindings is a table, grouped together by input, joystick number, etc.. For clarity, please refer to the following terminology:

  • Control - an abstract, game-centric variable which will either equal true/false (for digital controls) or a number between -1 and 1 (analogue controls). Controls can have any name you want to give them, but each name must be unique.
  • Input - the signal a keyboard or joystick gives off when manipulated. Love2D defines these as KeyConstants, JoystickConstants, joystick numbers, and joystick button, axis, hat, and ball numbers. Please note that Love2D currently starts joystick enumeration from 0, not 1!
  • Bind - the link between input and controls. "When this input is triggered, set that control". Each input can be bound to only one control, but a control may be bound to many inputs.
  • Map - links an analogue control to two digital controls (example: By default, horiz is mapped to left and right). Mapping makes it simpler to work with analogue controls since you don't have to worry about whether or not the player is using analogue or digital input.

TLbind.keys

This is for keyboard keys. It's a table where the keys are KeyConstants and the values are the names of controls. In other words, you make bindings in the format TLbind.keys.KeyConstant = "control".

TLbind.keys = {
	w="up", a="left", s="down", d="right", [" "]="jump", lctrl="attack", escape="menu",
	up="up", left="left", down="down", right="right", z="jump", rctrl="attack",
}

TLbind.joyAxes

This is the list of joystick axes (the stick itself or gamepad thumbstick(s), but may also include rudders, etc.). It's in the form of TLbind.joyAxes[joystick#][axis#] = "control".

TLbind.joyaxes = { [0]={[0]="horiz", [1]="vert"} }

TLbind.joyBtns

This lists joystick buttons, in the form of TLbind.joyBtns[joystick#][button#] = "control"

TLbind.joyBtns = { [0]={[0]="jump", [1]="attack", [7]="menu"} }

TLbind.joyBalls

This is for any ball device a joystick may be sporting. Since these are rare, it's advisable to not make your game depend on using one. Their binds are in form of TLbind.joyBalls[joystick#][ball#] = {"x control", "y control"}

TLbind.joyBalls = { [0]={ [0]={"horiz","vert"}, [1]={"yaw","pitch"} } }

TLbind.joyHats

This table is for joystick hats (those mini-thumbstick things seen on some joysticks). Please note that they're digital, not analogue. They're bound in the form of TLbind.joyHats[joystick#][hat#] = {"l control", "r control", "u control", "d control"}

TLbind.joyHats = { [0]={[0]={"left","right","up","down"}} }

TLbind.maps

This table lists the analogue controls that should be mapped to and from digital controls. Using this, you can easily code for one type of input without having to worry about coding for the other type. They're created in the form of TLbind.maps[analogue] = {"negative digital", "positive digital"}

TLbind.maps = { horiz={"left","right"}, vert={"up","down"} }

TLbind.circleAnalogue

This feature restricts the movement of a pair of analogue controls to the inside of a circle, rather than the default square. Using this, you can avoid the classic "you move faster diagonally" bug very easily. A circle-analogue will reach about 0.7 when at a perfect 45-degree angle (but still reach a full 1 when straight). It's made in the form of TLbind.circleAnalogue[entry#] = {"analogue 1", "analogue 2"}

TLbind.circleAnalogue = { {"horiz", "vert"} }


A note about Xbox controllers

Microsoft has decided that Xbox controllers are the official gamepad for Windows, and as such, are the most common controller a player may have. Therefore, it's advisable to tailor your game's controls to work with them.

One important caveat about Xbox controllers: Both of their triggers (L2 and R2 for those of you more familiar with Playstations) are treated as one axis, rather than two buttons!