Tactile - a nice, straightforward input library!

Showcase your libraries, tools and other projects that help your fellow love users.
User avatar
Tesselode
Party member
Posts: 555
Joined: Fri Jul 23, 2010 7:55 pm

Tactile - a nice, straightforward input library!

Post by Tesselode » Thu Jul 02, 2015 5:56 am

Yo! I've been working on this input library called Tactile. It lets you assign multiple buttons to a control, just like any other input library, but what makes it unique is it makes it easy to have an axis (like an analog stick) control binary controls or to have buttons control an axis. This is because it has a pretty flexible system of controls and detectors.

Have an example!

Code: Select all

function love.load()
  tactile = require 'tactile'

  --button detectors
  keyboardLeft  = tactile.key('left')
  keyboardRight = tactile.key('right')
  keyboardX     = tactile.key('x')
  gamepadA      = tactile.gamepadButton('a', 1) --the second argument is controller number, in case you're wondering

  --axis detectors
  keyboardXAxis = tactile.binaryAxis(keyboardLeft, keyboardRight)
  gamepadXAxis  = tactile.analogStick('leftx', 1)

  --controls
  horizontal    = tactile.newAxis(keyboardXAxis, gamepadXAxis)
  shoot         = tactile.newButton(keyboardX, gamepadA)
end

function love.update(dt)
  --you have to update buttons, sorry for the extra step :(
  shoot:update()

  --movement
  player.x = player.x + player.speed * horizontal:getValue() * dt

  --shooting
  if shoot:pressed() then
    player:shoot()
  end
end
Code and documentation on GitHub

This is my first library (that useless highscore table library I made a couple years ago doesn't count), so please let me know anything I could be doing better.
Last edited by Tesselode on Mon Jul 27, 2015 4:54 am, edited 2 times in total.

Muzz
Citizen
Posts: 54
Joined: Sun Jun 28, 2015 1:24 pm

Re: Tactile - a nice, straightforward input library!

Post by Muzz » Thu Jul 02, 2015 6:59 am

Seems useful.

I'll give it a shot and give you some feedback :)!

User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: Tactile - a nice, straightforward input library!

Post by airstruck » Thu Jul 02, 2015 7:24 pm

I haven't tried it yet, but I have some questions/concerns from looking at your example.

In general the API sems to follow this form:

Code: Select all

input.foo('name', ...)
And then subsequent calls need to refer to "name." Is it necessary to rely on strings like this, or could the API use a form more like this:

Code: Select all

local name = input.foo(...)
So instead of binding the result of input.foo() to a string, it returns a value representing the detector/axis/button/whatever, and that value can be stored in a variable, and then the variable is passed to subsequent API calls. That approach might feel more intuitive and be less error-prone since you don't have to deal with string literals as much.

Here's your example rewritten as I'd imagine the API working:

Code: Select all

local input = require 'tactile'
local primary, horizontal

function love.load ()

  --button detectors
  local keyboardX = input.addKeyboardButtonDetector('x')
  local keyboardLeft = input.addKeyboardButtonDetector('left')
  local keyboardRight = input.addKeyboardButtonDetector('right')
  local gamepadA = input.addGamepadButtonDetector('a', 1)

  --axis detectors
  local keyboardXAxis = input.addBinaryAxisDetector(keyboardLeft, keyboardRight)
  local gamepadXAxis = input.addAnalogAxisDetector('leftx', 1)

  --controls
  primary = input.addButton({ keyboardX, gamepadA })
  horizontal = input.addAxis({ keyboardXAxis, gamepadXAxis })
end

function love.update (dt)
  input.update()

  --movement
  player.x += input.getAxis(horizontal) * player.speed * dt

  --shooting
  if input.pressed(primary) then
    player:shoot()
  end
end
Also maybe input.getAxis(horizontal) could be something like horizontal:getValue() instead.

This relies much less on string literals; when you see string literals you know they represent an "internal" name of a key/button/whatever, rather than a name you are assigning to something you just created. I don't know how difficult this change would be; I haven't looked at the source.

Also I didn't understand this line; where did 'leftx' come from?
input.addAnalogAxisDetector('gamepadXAxis', 'leftx', 1)

User avatar
Tesselode
Party member
Posts: 555
Joined: Fri Jul 23, 2010 7:55 pm

Re: Tactile - a nice, straightforward input library!

Post by Tesselode » Thu Jul 02, 2015 10:29 pm

time thief wrote:I haven't tried it yet, but I have some questions/concerns from looking at your example.

In general the API sems to follow this form:

Code: Select all

input.foo('name', ...)
And then subsequent calls need to refer to "name." Is it necessary to rely on strings like this, or could the API use a form more like this:

Code: Select all

local name = input.foo(...)
So instead of binding the result of input.foo() to a string, it returns a value representing the detector/axis/button/whatever, and that value can be stored in a variable, and then the variable is passed to subsequent API calls. That approach might feel more intuitive and be less error-prone since you don't have to deal with string literals as much.
I know what you mean, but the way the syntax is now reflects the fact that the library stores things internally. The example you provided could certainly be done, but it wouldn't really be meaningful since the library would still be keeping track of things internally. Why would you need to return a detector or control if you're not controlling its behavior yourself?

I could design the library so it has no internal state and it returns objects that contain all of their behavior, but then you'd have to update every detector and control individually, which would be a pain. Or you could have the input library return an input handler instance that holds all the detectors and controls, which I'm open to doing, but I haven't found a need for it.
time thief wrote: Also I didn't understand this line; where did 'leftx' come from?
input.addAnalogAxisDetector('gamepadXAxis', 'leftx', 1)
'leftx' is the name of a GamepadAxis.

Edit: on second thought, I think you're right. Pretty much every other library I've seen returns a handle to an object, even if it's mainly managed internally. I think I'll go ahead and switch over to that.

User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: Tactile - a nice, straightforward input library!

Post by airstruck » Fri Jul 03, 2015 2:27 am

If you don't want to return an object, you could even do things exactly the same way, except have a counter to make new ids for things. Then you'd only need to add a counter and a function to increment it and return the next value, and remove the first parameter from some functions and have them return new ids.

But it might be nice if it did return objects and the objects had a somewhat unified interface like getValue(), then if you swapped an axis out with a button or whatever you wouldn't need to change as much code.

User avatar
Tesselode
Party member
Posts: 555
Joined: Fri Jul 23, 2010 7:55 pm

Re: Tactile - a nice, straightforward input library!

Post by Tesselode » Fri Jul 03, 2015 3:33 am

time thief wrote:If you don't want to return an object, you could even do things exactly the same way, except have a counter to make new ids for things. Then you'd only need to add a counter and a function to increment it and return the next value, and remove the first parameter from some functions and have them return new ids.
I have no idea what you mean by this.

User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: Tactile - a nice, straightforward input library!

Post by airstruck » Fri Jul 03, 2015 5:08 am

I mean right now you identify the things you're creating with a primitive value, right, a string that you pass in. You could still identify them with a primitive value, just use a number that you generate with a simple counter. Instead of passing that id in to functions like getFooDetector, assign ids internally and return them, and let the user pass them in to other functions that need to reference the detector (addAxis, addButton and so on). The point is you don't need to manage any state in the returned values, they don't even need to be objects. They could just be primitive values, or at least can be treated like totally opaque values.

User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: Tactile - a nice, straightforward input library!

Post by airstruck » Fri Jul 03, 2015 9:47 pm

I've just had a look at the code, it looks pretty good but attaching properties to return objects seems strange when the functions that mostly deal with those values are defined inside closures where they already have access to those values.

I've made a pull request so you can see what I mean, but it's completely untested. This library looks like it could be very useful, I hope you consider adding some automated tests so it's possible to contribute. I may add some myself if I have time and if you'd be inclined to pull them over.

Here's the PR for anyone else who's interested.

User avatar
Tesselode
Party member
Posts: 555
Joined: Fri Jul 23, 2010 7:55 pm

Re: Tactile - a nice, straightforward input library!

Post by Tesselode » Fri Jul 03, 2015 10:13 pm

time thief wrote:I've just had a look at the code, it looks pretty good but attaching properties to return objects seems strange when the functions that mostly deal with those values are defined inside closures where they already have access to those values.

I've made a pull request so you can see what I mean, but it's completely untested. This library looks like it could be very useful, I hope you consider adding some automated tests so it's possible to contribute. I may add some myself if I have time and if you'd be inclined to pull them over.

Here's the PR for anyone else who's interested.
As far as automated tests go, I started one, but it was turning out to be a real pain. Writing a unit test is easily more work than writing the library itself, and considering the lengths I would have to go through to fake love.keyboard, love.joystick, and love.mouse, it didn't seem worth it. That being said, I'm planning on making an interactive example thing that can also be used to make sure nothing's horribly broken. I'll probably do that later tonight.

User avatar
Tesselode
Party member
Posts: 555
Joined: Fri Jul 23, 2010 7:55 pm

Re: Tactile - a nice, straightforward input library!

Post by Tesselode » Sat Jul 04, 2015 3:04 am

For anyone who cares, I just pushed a pretty major update. Constructors now return handles to the objects, and there's a new AxisPair class. I updated the example in the OP, and there's more info on GitHub.

Post Reply

Who is online

Users browsing this forum: girng and 10 guests