TIC-80 icon indicating copy to clipboard operation
TIC-80 copied to clipboard

Propose `getc()` - slightly higher level character input

Open joshgoebel opened this issue 4 years ago • 5 comments

Related: https://github.com/nesbox/TIC-80/issues/1229

I think #1229 is asking for too much but I'd like to propose a far more minimal solution here. Here is some code I've been using:

  keys = {
    enter = 50,
    backspace = 51,
    shift = 64,
    capslock = 62,
    lbracket = 39,
    rbracket = 40,
    comma = 45,
    period = 46,
    space = 48,
    tab = 49,
    equals = 38,
    ctrl = 63
  }

function getc()

  local letter = nil

  -- loop to handle the easy cases: A to Z, 0 to 9
  for i = 1,36 do
    if(keyp(i)) then
      if i <= 26 then -- letter
        letter = string.char(i+97-1) -- 65 is `a` in ascii
      else -- number
        letter = string.char(i-26+48-1) -- 48 is `0` in ascii
      end
      return letter
    end
  end

  if(keyp(keys.space)) then
    letter = " "
  elseif(keyp(keys.tab)) then
    letter = "	"
  elseif(keyp(keys.comma)) then
    letter = ","
  elseif(keyp(keys.period)) then
    letter = "."
  elseif(keyp(keys.lbracket)) then
    letter = "["
  elseif(keyp(keys.rbracket)) then
    letter = "]"
  elseif(keyp(keys.equals)) then
    letter = "="
  end

  return letter
end

The if/else could probably be collapsed into a loop - making a table of [code, value, string]... I think this is a reasonable minimal way to get this done... but I still think this is HUGELY verbose for something than in any standard C library is a single function dispatch to getc().

I'd like to propose a getc() (non-blocking) that reads a character from input (if available) and returns an ASCII string representation - ie all the mapping from SDL key codes to ASCII is abstracted away. That alone would make writing keyword driven things much easier I think without having to copy and paste all this boilerplate just to get character input.

If no character is available it would immediately return nil.

I realizing this would need some additional discussion since technically there is no sequential "input stream/buffer" per se, but I would welcome such a discussion if others thought this was a good addition.

Thoughts?

joshgoebel avatar Mar 07 '21 17:03 joshgoebel

If it's something that can be achieved through some handler code like you posted above, I think it's something that would live nicely outside of the TIC-80 API, and as a TIC-80 Library. Could make your own library of helper scripts like getc() :wink:

RobLoach avatar Mar 25 '21 17:03 RobLoach

If it's something that can be achieved through some handler code

And lines can be drawn one pixel at a time also yet we still have a line API... so I'll hold my breath until nesbox shuts it down. 😜

Lets remember there is a code size limit... to requiring TONS of code just to do very trivial things limits what is possible on the platform. :)

joshgoebel avatar Mar 25 '21 17:03 joshgoebel

We don't need no circ()!!!! :laughing:

function circle(x, y, r)
  for i = 1, 360 do
    local angle = i * math.pi / 180
    local ptx, pty = x + r * math.cos( angle ), y + r * math.sin( angle )
    drawPoint( ptx, pty )
  end
end

RobLoach avatar Mar 25 '21 21:03 RobLoach

That's going to be slow I think with cos and sin. :) Isn't there faster ways to plot circle? :)

joshgoebel avatar Mar 26 '21 12:03 joshgoebel

Using co-routines and this getc(), I have built a small lib to simulate a terminal.

Features:

  • console.print("...")
  • line=console.read()
  • takes care of positioning text and auto scrolling down

https://github.com/nesbox/TIC-80/wiki/Console-program-example

dcaillia avatar Aug 17 '22 22:08 dcaillia