Author Topic: BearLibTerminal: a pseudo-terminal window library for roguelike  (Read 283643 times)

Cfyz

  • Rogueliker
  • ***
  • Posts: 194
  • Karma: +0/-0
    • View Profile
    • Email
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #15 on: July 14, 2014, 12:27:17 PM »
Contrary to how it might look, the project is alive. Not very popular though, but oh well.
Version 0.10: http://foo.wyrd.name/en:bearlibterminal#download

I did try to make SDL-based window implementation but somehow it resulted into a mess. SDL is good, robust library when you start from it and build your app around its infrequient quirks. However, integrating it into project (half of which functionality is window management) halfway is not as simple as it seems. I've found myself working more against SDL than with it. Therefore, Mac port is delayed for now.

Instead I've refactored the input subsystem (which was a mess by itself) a bit and implemented a couple of new features. Nothing really breaking, though.

1. Minor adjustments in constants naming like TK_PAGEUP or TK_MOUSE_LEFT instead of WinAPI-legacy TK_PRIOR and TK_LBUTTON. Constants related to mouse or numpad are now grouped together: TK_MOUSE_xxx, TK_KP_xxx.

2. Input event categories are removed. There was an input.events option before which allowed to 'subscribe' on keypresses or keyreleases or mouse with somewhat inconsistent mechanics. For example, TK_CLOSE is better not to be ignored (what category it is?), same with TK_RESIZED. And actually there is no real difference between keypress and keyrelease for application as user always can press a whole lot of random buttons you will have to ignore anyway. So now the read function does read everything (like GetMessage, ha), you just have to handle only those events you're interested in.

3. Next is read_ext. A thing with somewhat obscure logic. It was introduced because it was necessary to read both event scancode and character code produced by that event: terminal_read_ext(TK_READ_CHAR). Ugh, somehow it did not fazed me in the slightest that there was already mouse events where you can read both the event and mouse properties at the same time: via terminal_state(TK_MOUSE_xxx). Therefore, the read_ext is removed and two new states are introduced: TK_CHAR and TK_WCHAR. They simply return the code of a character produced by the latest read input event, or zero if none was produced:
Code: [Select]
int key = terminal_read();
if (key == TK_ESCAPE)
{
   return;
}
else if (terminal_state(TK_WCHAR) > 0)
{
   str += (wchar_t)terminal_state(TK_WCHAR);
}
TK_WCHAR returns an Unicode codepoint of the character and TK_CHAR return an ASCII/ANSI codepoint translated accordingly to the codepage selected with the terminal.encoding option.

There was also non-blocking input via read_ext but it can easly implemented without additional API methods:
Code: [Select]
// Both literally,
int key = terminal_has_input()? terminal_read(): 0;

// ...and logically
while (terminal_has_input()) {
   int key = terminal_read();
   ...
}
Oh, there is also TK_EVENT that will return a scancode of the last dequeued input event.

4. Mouse input has been extended. There are new TK_MOUSE_X1 and TK_MOUSE_X2 buttons which are additional buttons on some mouse models. There is new TK_MOUSE_CLICKS state that return a number of fast consecutive clicks by the time of the last dequeued mouse button event. E. g. terminal_state(TK_MOUSE_CLICKS) == 2 indicated that this TK_MOUSE_LEFT event is the second one in double-click action.

Also, TK_MOUSE_WHEEL now returns scroll delta instead of some global counter.

5. You can press Alt+Enter to switch between windowed and fullscreen mode (with no display resolution change). The window.fullscreen option may be used to force the fullscreen mode programmaticaly.

6. You can press Alt+[plus/minus] to scale the window up and down. This may be useful if some application uses tiny tileset and you want to run it on FullHD+ display. For now it is done via simple OpenGL scene scaling. Later I'll try to take advantage of shaders where they are supported. But you cannot scale resizeable window (window.resizeable option) as it would allow for a number of difficult configuration cases I'm not yet sure how to deal with.

7. There is also a couple of debug key combinations: Alt+G will turn on cell grid and Alt+A will dump the texture atlas on disk.

The up-to-date reference on the input subsystem is located here: http://foo.wyrd.name/en:bearlibterminal:reference:input
« Last Edit: July 15, 2014, 12:51:54 PM by Cfyz »

Cfyz

  • Rogueliker
  • ***
  • Posts: 194
  • Karma: +0/-0
    • View Profile
    • Email
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #16 on: August 14, 2014, 01:57:41 PM »
Another update: v0.11.1: http://foo.wyrd.name/en:bearlibterminal#download

'print' function now allows for text alignment and autowrap. This is done via formatting tags.

Code: [Select]
T.print_(40, 12, "[align=bottom-right]Spike Vixen\nGrease Monk")

Code: [Select]
T.print_(40, 12, "[bbox=30x10]Void Initiate: gain 1 rune. "
                 "You may banish a card in your hand or "
                 "discard pile.")


Dimensions of an autowrapped string may be calculated without printing with the 'measure' function:
Code: [Select]
int height = terminal_measuref(L“[bbox=%d]%ls”, width, ws.c_str());
Using simple in-text iconographics or alternative fonts is a bit easier now:
Code: [Select]
terminal_print(“One [font=0xE000]Two”);

Code: [Select]
T.print_(2, 1, "This spell requires: 2[0xE004] 3[0xE022]")
T.print_(2, 3, "The scroll says \"[font=0xE100]whatewer[/font]\"")


By combining these features it is fairly easy to implement text output with basic formatting, scrolling dynamically adjustable output area. It is demonstrated in SampleOmni showcase. I would add a picture here but it is big and I can't find a spoiler tag =_=.

And there is now a Python wrapper which works with 2.x and 3.x versions:
Code: [Select]
import PyBearLibTerminal as T

T.open()
T.print_(2, 1, “Hello, wordl”)
while True:
    T.refresh()
    key = T.read()
    if key == T.TK_CLOSE or key == T.TK_ESCAPE:
        break
T.close()

#bearlibterminal #nobodycares #everyonereadsthetags
« Last Edit: August 15, 2014, 09:52:33 AM by Cfyz »

Brigand

  • Rogueliker
  • ***
  • Posts: 93
  • Karma: +0/-0
    • View Profile
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #17 on: August 25, 2014, 02:55:59 PM »
Wow, played around with this over the weekend, and it seems to be almost exactly what I am looking for - very nicely done! Makes me want to abandon my current project and start a new one using this. I like libtcod, but I only want that display functions and not all the other stuff it brings along (along with a bit of a learning curve.)


3 quick questions:

1) Do you plan on including any basic drawing functionality? We're just talking simple colored lines, or maybe an ellipse function. (For drawing UI borders and such.)

2) When using composition to stack tiles on the same location on the same layer, is there any way to make a copy of the composed tile and save it off as a temporary (or even permanent) tile that can be reused, or would I always need to rebuild (recompose) the tile each move?

3) Similar to question 2, is there a function to simply copy an area of the screen and paste it somewhere else? (It wouldn't need to retain all the layers; purely just a pixel copy of a designated space, placed into it's own layer in a different spot.)

Sorry if these question are already answered - I have been reading the API reference on your webpage, and I have a feeling they are already answered and I am just not searching for my answers with the right phrase.

Again, very nice library - please continue to develop it :)

Cfyz

  • Rogueliker
  • ***
  • Posts: 194
  • Karma: +0/-0
    • View Profile
    • Email
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #18 on: August 26, 2014, 10:07:24 AM »
Thanks for your feedback =)

Quote from: Brigand
Do you plan on including any basic drawing functionality? We're just talking simple colored lines, or maybe an ellipse function. (For drawing UI borders and such.)
Not sure. Such "classic" drawing primitives do not combine well with cells/characters architecture. The library does not draw tiles the moment you issue 'put' or 'print' command but constructs a 'scene description' for later render. This allows more 'terminal'-way operation where you can replace some of the characters while leaving everything else intact. This also allows library to redraw the scene all by itself if necessary. Lines and circles are rather foreign to characters-based modifiable scene structure, and I do not see a way to make a clear API with those.

I had considered going all the way to the optional 'custom' output via some callbacks hooked into a scene (e. g. to a layer). Inside callback you would have a different drawing context where you can do things differently because it does not buffer drawing commands. And from the API perspective it becomes very clear that mechanics are different because mode change is intentional and obvious. However, it has a whole new lot of problems not completely thought out yet so the priority of this is fairly low.

As for UI, wouldn't it be enough to just prepare a few tiles for borders and corners?

Quote from: Brigand
When using composition to stack tiles on the same location on the same layer, is there any way to make a copy of the composed tile and save it off as a temporary (or even permanent) tile that can be reused, or would I always need to rebuild (recompose) the tile each move?
Right now the only option is to reconstruct them every time. Given the scene architecture it is not as straightforward as copying pixels, but I think its possible to allow to save an output string (which usually goes to 'print' and supports combining via formatting) as a precomputed template, e. g. like this:
Code: [Select]
terminal_set("0xE100: 'a[+][color=red]/'");
terminal_put(2, 1, 0xE100);
Though it will take a decent amount of coding =).

Quote from: Brigand
Similar to question 2, is there a function to simply copy an area of the screen and paste it somewhere else? (It wouldn't need to retain all the layers; purely just a pixel copy of a designated space, placed into it's own layer in a different spot.)
As I mentioned above, pixel copy is almost impossible and layers do make a problem. However, it indeed may be a useful feature, will think about it. What do you intend to use it for exactly?

Brigand

  • Rogueliker
  • ***
  • Posts: 93
  • Karma: +0/-0
    • View Profile
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #19 on: August 26, 2014, 12:09:12 PM »
I had considered going all the way to the optional 'custom' output via some callbacks hooked into a scene (e. g. to a layer). Inside callback you would have a different drawing context where you can do things differently because it does not buffer drawing commands. And from the API perspective it becomes very clear that mechanics are different because mode change is intentional and obvious. However, it has a whole new lot of problems not completely thought out yet so the priority of this is fairly low.

As for UI, wouldn't it be enough to just prepare a few tiles for borders and corners?

Yeah, I could just use tiles to make the border and other effects....especially if I could scale and rotate the tiles  ;)


Quote from: Brigand
Similar to question 2, is there a function to simply copy an area of the screen and paste it somewhere else? (It wouldn't need to retain all the layers; purely just a pixel copy of a designated space, placed into it's own layer in a different spot.)
As I mentioned above, pixel copy is almost impossible and layers do make a problem. However, it indeed may be a useful feature, will think about it. What do you intend to use it for exactly?

I was just thinking in terms of performance, which probably isn't an issue :) If you have 10 enemies and the player, and each is composed of 10 layered tiles (body, armor, boots, cloak, weapon, helmet, effects, etc), along with other layered/composed parts of the scene... If you could save each off beforehand you could just redraw a single tile reducing the number of tile look-ups/copies by a factor of 10.

Again, this was just me thinking through a future problem - the reality is I probably would get to the point I described above and find the performance almost completely identical in both cases.

Either way, still very well done - whatever the ultimate answer is, it won't deter me from checking this out and seeing what I can do with it.

Thank you again for your hard work, and please keep at it - even if people don't seem to respond or give much feedback, there are some of us who still are very grateful for your efforts.

Wattmann

  • Newcomer
  • Posts: 4
  • Karma: +0/-0
    • View Profile
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #20 on: October 30, 2014, 04:29:49 PM »
A newbie's question: any tutorial on using this work of art hehe?

Cfyz

  • Rogueliker
  • ***
  • Posts: 194
  • Karma: +0/-0
    • View Profile
    • Email
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #21 on: October 31, 2014, 01:22:27 PM »
Sorry but there is no such thing yet. For now there are only a function reference and a number of short C++ examples. I'd like to say I'm working on it but sadly I'm a bit busy right now =|. I do plan to make a regular tutorial though. Probably based off one already popular like libtcod's or something =).

However, I'll answer any questions. It would help to at least know what language and platform you are using so I'll be able to take those into account later.

Wattmann

  • Newcomer
  • Posts: 4
  • Karma: +0/-0
    • View Profile
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #22 on: November 01, 2014, 02:06:56 PM »
Ah thanks a lot! So far I'll be playing with the reference and samples to see what I can do. I'm using C++ with MinGW GCC 4.8 (I think) or the latest regular Clang from 27.10.2014. (whichever I feel like I guess) on Win7 Ultimate 64-bit.

Quendus

  • Rogueliker
  • ***
  • Posts: 447
  • Karma: +0/-0
  • $@ \in \{1,W\} \times \{1,H\}$
    • View Profile
    • Klein Roguelikes
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #23 on: November 28, 2014, 05:01:37 AM »
#bearlibterminal #nobodycares #everyonereadsthetags
I care! BLT is my first choice for a roguelike display/input library at the moment. It has much more flexibility as a display system than libtcod, and isn't bloated with mapgen/fov features. Text alignment/wrapping, inline icons, and Python support are great additions.
I haven't written any games since the March 7DRLC (health problems), but when I start again I'll be very pleased to continue using BearLibTerm.

Wattmann

  • Newcomer
  • Posts: 4
  • Karma: +0/-0
    • View Profile
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #24 on: December 05, 2014, 06:40:34 PM »
Been a while hehe but I've gotten round to playing with it again and, well, got this thingy here --- "error: 'terminal_delay' was not declared in this scope". Every other thing I've used works so it's not bad linking, and I copied it off the API reference a couple of times just to make sure I wasn't doing something bad. Oversight?

Cfyz

  • Rogueliker
  • ***
  • Posts: 194
  • Karma: +0/-0
    • View Profile
    • Email
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #25 on: December 09, 2014, 01:26:13 PM »
Sorry for the delay, was somewhat busy =_=.

Quote from: Wattmann
got this thingy here --- "error: 'terminal_delay' was not declared in this scope". <...> I copied it off the API reference a couple of times just to make sure I wasn't doing something bad. Oversight?
Pretty much. I've updated the library but got distracted, messed up the links and did not post about it >_<. Try redownload the 0.11.3 version.

The 0.11.3 update:
* terminal_pick* functions to examine cell contents.
* terminal_peek to preview an input event.
* terminal_delay to pause the execution a bit.
* There is no input.sticky-close option anymore (it has introduced more problems than it solved).
* Input filtering added. By setting the input.filter option one can select which events will be returned by terminal_read (e. g. keyboard keypresses only) and which will be ignored.

Wattmann

  • Newcomer
  • Posts: 4
  • Karma: +0/-0
    • View Profile
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #26 on: December 12, 2014, 02:40:08 AM »
Made a brainfuck interpreter in the library for general practice :D

Might be offtopic, but the library is fast enough to make it viable!

Edit: hey, I'm gettin bits of issues: when I run the .exe normally it sets itself up OK but when I run it with cmd.exe it doesn't set up the font. Any ideas why?
« Last Edit: December 12, 2014, 10:53:12 AM by Wattmann »

notostraca

  • Newcomer
  • Posts: 6
  • Karma: +0/-0
    • View Profile
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #27 on: February 27, 2015, 09:22:00 AM »
This is quite nice. I've got it working with C# already, I have dungeon generation ported in from an earlier game project, and the API of BearLibTerminal seems quite well-thought-out. Kudos! I'm just not sure how to use a custom codepage. If I have an image like https://dl.dropboxusercontent.com/u/11914692/Zodiac-Narrow.png, where the first row corresponds to Unicode U+0000-U+007F, and the second row to U+2500-U+257F , how would I get the codepage to load? I've already tried making a file, custom.txt , with the text "U+0000-U+007F, U+2500-U+257F" like the encodings in BLT's source use, but every glyph displays as a box (the not-found glyph). Does the file have to be an embedded resource? The image isn't...

Cfyz

  • Rogueliker
  • ***
  • Posts: 194
  • Karma: +0/-0
    • View Profile
    • Email
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #28 on: February 27, 2015, 11:26:08 AM »
Quote from: Wattmann
when I run the .exe normally it sets itself up OK but when I run it with cmd.exe it doesn't set up the font. Any ideas why?
Somehow I did not receive any forums notifications and notice this question only now =/. As for the library behaviour, it most likely attributes to possibly different working directories when run in different ways. Try to look for bearlibterminal.log, the library will complain there if it can't find the file.

Quote from: notostraca
I've already tried making a file, custom.txt , with the text "U+0000-U+007F, U+2500-U+257F" like the encodings in BLT's source use, but every glyph displays as a box (the not-found glyph).
Hmm, every glyph? I've tried using your image:

Code: (test.lua) [Select]
T.set("font: ./Zodiac-Narrow.png, size=12x24, codepage=./Zodiac-Narrow.txt")
T.print(2, 1, "Hello, world! [U+256C] [U+2573]")
Code: (Zodiac-Narrow.txt) [Select]
U+0000-U+007F, U+2500-U+257F
And its mostly working. The regular text (U+0000-U+007F, "hello world" part) is output in the correct font. With the U+25xx glyphs there is a bug, though. The library has built-in generator for Box Drawing and Block Elements unicode ranges in case the font doesn't have those -- or if it is a TrueType font which rarely have useful Box Drawing characters. Bitmap fonts should have higher priority but I've made a mistake there. I'll upload a fixed version later today.

Even with this bug you should not be getting glyph-not-found boxes.

notostraca

  • Newcomer
  • Posts: 6
  • Karma: +0/-0
    • View Profile
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #29 on: February 28, 2015, 07:46:55 AM »
My source is here, in case there's something obviously wrong: https://github.com/tommyettinger/DungeonRising.  The code starts in DungeonRising/Entry.cs (here https://github.com/tommyettinger/DungeonRising/blob/master/DungeonRising/Entry.cs#L81); it calls Terminal.Put(int, int, char) each time it wants to render something.