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

Cfyz

  • Rogueliker
  • ***
  • Posts: 194
  • Karma: +0/-0
    • View Profile
    • Email
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #150 on: November 30, 2016, 09:46:09 PM »
Quote from: Aukustus
there's a fairly interesting effect when using bitmap font without specifying size. It opens a white full screen sized window and nothing else.
Oh >_<. When the 'size' of bitmap font/tileset is omitted, image is treated as a single sprite. And then library uses this sprite as a character tile and adjust the size of a cell and a window accordingly. Well, tries to. With 256x256 image library will try to resize the window to 80x25 * 256x256 = 20480x6400 pixels which is probably beyond reason and breaks a few things.

Since not specifying a size for a font makes no sense, I'll just make it fail (and roll back) in this case.

Quote from: Aukustus
Also, are TCOD layouted fonts supported?
About two thirds? ASCII_INROW is codepage '437', TCOD is, well, 'tcod' and ASCII_INCOL is just too weird.
Code: [Select]
Terminal.Set("font: consolas12x12_gs_tc.png, size=12x12, codepage=tcod");Nuances are:
1. Most of tcod font images are non-transparent (fully opaque background) and their tiles will not overlay nicely. Might not be a problem. I have an idea how to fix that on-the-fly.
2. I've just noticed that CP437 does actually contain various icons and arrows at 0x01-0x1F in contrast with other ANSI codepages. I'll fix that in the next release.
3. Looks like there is a bug in handling box drawing characters. Working on it.

Technically, BearLibTerminal supports any layout. Instead of a predefined built-in name, you can specify a filename in the 'codepage' parameter:
Code: [Select]
Terminal.Set("font: image.png, size=16x16, codepage=my_codepage.txt");With file containing a list of Unicode codepoints for each tile consecutively, left-to-right, top-to-bottom:
Code: [Select]
U+0020-U+003F, U+0040, U+005B-U+0060, U+007B-U+007E, U+2591-U+2593,
U+2502, U+2500, U+253C, U+2524, U+2534, U+251C, U+252C, U+2514, U+250C, U+2510, U+2518,
...

Quote from: tapeworm711
The use case was for ranged combat: <...>
Why do you need to move the mouse though? Not sure I understood your note, but placing/cycling the reticle over the targets via keyboard and then moving it under the mouse on the mouse movement looks more natural. Mouse does not move when you use keyboard to navigate the text in an editor or file icons in an explorer, yet you can always 'override' the cursor (selection) position by moving/clicking the mouse.

Quote from: tapeworm711
NOTE: in the python bindings i'm using: TK_MOUSE_MOVE state is ALWAYS 0.
TK_MOUSE_MOVE is an event, not a state (and listed so in the docs, so my conscience is clear here =)), so it will be read zero as any other invalid state code. There are no separate lists of constants because almost every other event is also a state.

Quote from: tapeworm711
Additionally i'm not sure how to get bearlib to read the "box drawing acsii" from my PNG file instead of the default. Even using your yoshi_island font the boxes draw standard when addressing them via unicode (ex: 0x2502 prints a |, regardless of the glyph in the .PNG)
Yup, that's looks like a bug. Bitmap fonts should override box drawing characters. Will look into it shortly. Not sure what yoshi_island is, though =/.

-----
Edit: well, most of issues are minor code-wise, expect an update in about a day.
« Last Edit: November 30, 2016, 11:12:16 PM by Cfyz »

tapeworm711

  • Newcomer
  • Posts: 12
  • Karma: +0/-0
    • View Profile
    • Email
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #151 on: December 01, 2016, 04:07:37 PM »
More mouse questions:

I'm having trouble with differentiating between mouse clicks.

Example:
1) User presses key to open a Pop-Up window with a 'close' button.
2) User clicks on 'close' button with mouse.
3) Game closes Pop-Up, but also attempts to Pathfind to X, Y location (also activated by clicking)

Since I don't see a "TK_MOUSE_LEFT_UP" or "TK_MOUSE_LEFT_RELEASED". I tried using TK_MOUSE_CLICKS but that still shows 'True' while its being held. which is being seen by my other event handlers.

In addition to this issue it appears there is no state difference between HOLDING down a button and CLICKING IT rapidly (well you would get an occasional False from MOUSE_LEFT, but not sure if thats useful in this case).

Cfyz

  • Rogueliker
  • ***
  • Posts: 194
  • Karma: +0/-0
    • View Profile
    • Email
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #152 on: December 01, 2016, 04:47:43 PM »
Quote from: tapeworm711
I'm having trouble with differentiating between mouse clicks. Example: <...>
Erm, are you using terminal_read or terminal_state? Runtime state is not the right tool for this task. There should not be any problems with basic mouse handling when reading its events. The first TK_MOUSE_LEFT closes popup and the next TK_MOUSE_LEFT (which would trigger pathfinding) won't come until another actual mouse click.

To use mouse (read any mouse-related events from terminal_read) you need to explicitly enable it by setting input.filter option, see docs.
Also, take a look at "Input 2: mouse" in SampleOmni (event counter, states and behavior) and it's source code.
« Last Edit: December 01, 2016, 06:05:03 PM by Cfyz »

tapeworm711

  • Newcomer
  • Posts: 12
  • Karma: +0/-0
    • View Profile
    • Email
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #153 on: December 01, 2016, 06:38:06 PM »
Figured it out.

I had two different functions polling for inputs. So each mouse event was registering in each one. Fixed that and VOILA!.


Cfyz

  • Rogueliker
  • ***
  • Posts: 194
  • Karma: +0/-0
    • View Profile
    • Email
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #154 on: December 01, 2016, 10:22:45 PM »
Okay, here is an update: 0.14.12 (Windows / Linux / OS X / PyPi)

* First ~32 symbols of CP437 (xxx_ro.png from tcod are this) are properly mapped onto the Unicode now (kind of missed that before).
* Grayscale fonts (.png w/o transparency) are properly supported.
* Box Drawing elements from bitmap fonts are not overrided by auto-generated tiles anymore.
This also means libtcod fonts (except ASCII_INCOL layout) are fully useable now.

* The library will not accept a font tileset without a 'size' parameter.
It's now a bit harder to break things accidentally.

* C# wrapper: added some Point/Rectangle function overloads.
* C# wrapper: Set() and Get() support formatting and parsing System.Drawing.Size type (I mean, in library-recognizable format):
Code: [Select]
Size custom_size = Terminal.Get<Size>("ini.settings.custom-size", new Size(80, 25));
Terminal.Set("window.size={0}", custom_size);

* Python wrapper: added atexit cleanup handler that closes the library if Python exits due to exception.
« Last Edit: December 02, 2016, 09:30:16 AM by Cfyz »

Aukustus

  • Rogueliker
  • ***
  • Posts: 440
  • Karma: +0/-0
    • View Profile
    • The Temple of Torment
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #155 on: December 02, 2016, 08:45:41 PM »
Is it possible to have a single font (ttf or bitmap) but print chars from it different sizes? I've been planning an ascii system that has double sized chars in the game screen but regular in the text.

Cfyz

  • Rogueliker
  • ***
  • Posts: 194
  • Karma: +0/-0
    • View Profile
    • Email
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #156 on: December 03, 2016, 12:33:09 AM »
It is possible. But technically it is not the same font with different sizes, they are different tilesets loaded from the same source with different parameters. Which may be done in a few ways.

Let me provide an example of various font configurations:


There are two groups, blue is UbuntuMono-R.ttf, green is terminal10x18_gs_ro.png.
1. First line is the basic font loaded with a bare minimum of options.
2. Second line is the same font but spaced to make it fit [almost] square map cells. The 'spacing' parameter controls how a character is centered relative to its origin cell and how much cells Print() function should advance.
3. Third line illustrates what will happen if characters are resized to some arbitrary size irrelevant to the base cell size.
4. Fourth line is pretty much the same as the second one.
For truetype tilesets 'size' directly specifies the target size. For bitmap tilesets 'size' is a size of a tile in source image and target size is overriden by 'resize' parameter. Spacing is the same for both.

You may have several different fonts at once. In the example above there are eight different fonts loaded like this:
Code: [Select]
Terminal.Set("twice font: UbuntuMono-R.ttf, size=20x36, spacing=4x2");Such extra fonts are used like this:
Code: [Select]
Terminal.Print(2, 1, "[font=twice]Abc 123");But there is a limitation: you cannot address individual tiles from extra font with Put() since it does not have a font name argument. You have to use Print() with 'font' formatting tag.

Instead of loading alternative character configurations as fonts you can also load them as generic tilesets:
Code: [Select]
Terminal.Set("0xE000: terminal10x18_gs_ro.png, size=10x18, resize=20x36, resize-filter=nearest, spacing=4x2");This will place twice-size character tiles into codepoints 0xE000..0xE0FF. You won't be able to Print() with them since those are not character codes anymore but you'll be able to Put() them:
Code: [Select]
Terminal.Put(2, 1, 0xE040); // @But there is a gotcha, 'codepage' has a very different meaning when loading tilesets vs. loading fonts. Most of the time you do not need one though because usually you want a whole tileset loaded straight consecutively.

I probably need to write a nice long article about how all of this works. The system is flexible enough to become confusing.

P. S. And I've immediately found a new thing to fix. When a truetype font is loaded with size that is not the same aspect ratio as the base cell size (e. g. 18x18 vs 10x18), its characters are not aligned correctly within tiles. Aargh!
« Last Edit: December 03, 2016, 01:34:17 AM by Cfyz »

Elronnd

  • Newcomer
  • Posts: 16
  • Karma: +0/-0
    • View Profile
    • NetHack and Slash'EM EU server
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #157 on: December 25, 2016, 11:27:53 PM »
Would anyone be interested in D bindings?  I'm learning D right now, and had been going to write an RL in it with bearlib.  If anyone wanted, I could probably formalize it all into a library.
Wishes, wishes.  Wish in one hand and do something else in the other, and squeeze them both and see which comes true

 —Roger Zelazny, Nine Princes in Amber

Looks like a fish, moves like a fish, steers like a cow.

 —Douglas Adams, Hitchhiker's Guide to the Galaxy Fit the Fifth

Elronnd

  • Newcomer
  • Posts: 16
  • Karma: +0/-0
    • View Profile
    • NetHack and Slash'EM EU server
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #158 on: December 25, 2016, 11:45:55 PM »
It seems that bearlibterm leaks memory?  Just running the example C program, valgrind reports:

definitely lost: 520 bytes in 2 blocks
indirectly lost: 1,661 bytes in 14 blocks

Full valgrind log: http://lpaste.net/350473
Wishes, wishes.  Wish in one hand and do something else in the other, and squeeze them both and see which comes true

 —Roger Zelazny, Nine Princes in Amber

Looks like a fish, moves like a fish, steers like a cow.

 —Douglas Adams, Hitchhiker's Guide to the Galaxy Fit the Fifth

Cfyz

  • Rogueliker
  • ***
  • Posts: 194
  • Karma: +0/-0
    • View Profile
    • Email
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #159 on: December 26, 2016, 10:43:55 AM »
Quote from: Elrond
It seems that bearlibterm leaks memory?
Oh, thanks for pointing that out. There is also a small leak in TrueType tileset. Overall it is just a few bytes once a process, so I will not re-upload right away and incorporate the fixes into the next update.

Incidentally, how do you name a size structure (usual width, height) using lowercase when the 'size_t' name is underhandedly taken by the standard library?

Elronnd

  • Newcomer
  • Posts: 16
  • Karma: +0/-0
    • View Profile
    • NetHack and Slash'EM EU server
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #160 on: December 26, 2016, 09:11:57 PM »
Some unicode doesn't seem to be supported.  The ╱ character, for example, which is supported by the font I'm using (I've verified this with SDL-TTF) just shows up as a black box in bearlibterminal.  Any fix?
Wishes, wishes.  Wish in one hand and do something else in the other, and squeeze them both and see which comes true

 —Roger Zelazny, Nine Princes in Amber

Looks like a fish, moves like a fish, steers like a cow.

 —Douglas Adams, Hitchhiker's Guide to the Galaxy Fit the Fifth

Cfyz

  • Rogueliker
  • ***
  • Posts: 194
  • Karma: +0/-0
    • View Profile
    • Email
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #161 on: December 26, 2016, 10:28:30 PM »
Actually, no symbol out of Box Drawing (0x2500-0x257F) range is being taken from any TrueType font, these characters are automatically generated by the library. This is how it happened:

* Most TrueType fonts provide only a small subset of Box Drawing character range. Using half native, half auto-generated produces a shabby image.
* Those characters that actually provided are often do not align well even within the font itself.
* Even if the font is good, it is hard to align there characters when rasterized which produce unseemly patterns of various visibility (e. g. a pixel missing every tile in a wall).
* More so if the cell size is not native to the font, e. g. manually set to be 10x20 for design purposes when the font is more like 10x18.5 at that specific size.

So in the end I just went with auto generating these instead of using ones from the font. Also, same goes for Block Elements (0x2580-0x259F) range. Note that bitmap fonts is a very different case and theirs version of characters are used normally.

But seven characters (0x256D-0x2573, and ╱ is there) turned out to be not so easy to generate nicely and ended up as no-characters to this day.

Looking at this again, I probably should just allow the user to use font's characters if he wants to, e. g. by an additional 'use-box-drawing=true' font parameter. I'll include that into the next update. And I need to support those seven characters, but this is not as easy.

Meanwhile there is a rather ugly hack to still use these font's characters right now by loading a subset of a font to some other unused code points, e. g. 0xE000-0xE07F, so that 0x2571 (╱) would be availables as 0xE071. Tell me if you really want to see this =/.
« Last Edit: December 27, 2016, 09:32:20 AM by Cfyz »

tapeworm711

  • Newcomer
  • Posts: 12
  • Karma: +0/-0
    • View Profile
    • Email
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #162 on: January 03, 2017, 02:25:34 PM »
When terminal.read_str() accepting input from the keyboard, is there a way to allow the use of the NUMPAD numbers? Cannot seem to enable this.

Thanks, as always.

Serin Delaunay

  • Newcomer
  • Posts: 13
  • Karma: +0/-0
  • they/them/their
    • View Profile
    • itch.io
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #163 on: January 08, 2017, 04:13:08 AM »
Thanks for continuing to develop this library :)

More than once when working with bearlibterminal I've needed to implement maps that scroll smoothly. The included demo application also has a smooth-scrolling sample. The problem with implementing this in BLT is that when the display is offset by a fraction of a tile, there are more tiles to be drawn than there are slots in the terminal. There are two ways around this:
  • Use composition, put all the tiles at (0,0), use the pixel offset to control where they appear.
  • Use composition, put most of the tiles in the correct slots with uniform pixel offsets, put one row and one column in the wrong slots with different pixel offsets.
Both methods "work" and don't seem to have any performance implications, but from the perspective of code readability I would prefer to be able to put each tile in its own slot. That's not currently possible because characters can only be put inside the terminal's boundaries.

Would it be possible to extend the terminal storage, writing, and drawing outside the bounds imposed by TK_WIDTH and TK_HEIGHT? Just one row and one column would be enough for this purpose, but another option would be to have a configurable number of extra rows and columns on each side. This could be helpful when drawing 2.5D terrain where tiles could be N rows off the bottom of the terminal but still be high enough that they should appear on the display.

Here's a discrete dimetric heightmap drawn with BLT. It probably would have been easier with a configurable number of extra rows on the top and bottom.

Cfyz

  • Rogueliker
  • ***
  • Posts: 194
  • Karma: +0/-0
    • View Profile
    • Email
Re: BearLibTerminal: a pseudo-terminal window library for roguelike
« Reply #164 on: January 09, 2017, 12:32:24 AM »
Update time: 0.15.0 (Windows / Linux / OS X / PyPi)

The main (but still minor) version bump comes from a slight change in printing function. Not sure what had I been under while first implementing that, but until now text wrapping/aligning was done via in-text formatting tags:
Code: [Select]
terminal_printf(2, 1, "[bbox=%dx%d][align=center]%s", w, h, str);To make things even messier, print() was returning either width or height of a string depending on the presence of bbox. While there is some logic, the overall it is just... ugh.

Now print() (or a variant of it if no overloading available for the language) accepts width, height and alignment parameters explicitly and always returns both dimensions:
Code: [Select]
y += terminal_print_ext(x, y, width, 0, TK_ALIGN_DEFAULT, message).height;And same goes for measure().

By the way, it was quite a quest to update all seven (sic!) wrappers for various languages. I've initially tried a naive approach with simply returning a struct, but quickly discovered that doesn't work across multiple languages -- apparently there is no standard to how cdecl handles return values larger than a scalar.

Another change I need to illustrate is 'dead-center' alignment mode for tiles. It essentially ignores any typographic values for the tileset:

This might be useful for map/level elements since that will align the good old ASCII in the map cells rather neatly.

Other than that, changes include:
* New 'use-box-drawing=true' and 'use-block-elements=true' truetype font parameters to force the library to use in-font glyphs if you really want. It still will auto-generate the missing ones.
* Keypad keys update TK_CHAR/WCHAR states now so they can be used for text input (e. g. read_str() function).
* Querying library version via terminal_get("version"), it will return a string like "0.15.0".
* A few fixes here and there.

Also, I've changed the Python wrapper structure a tiny bit. Instead of a lone .py file there is a Python package/module skeleton now. See the README.md in the corresponding directory for some notes about it. Having a 'bearlibterminal' module directory instead of a single PyBearLibTerminal.py in the project allows easier switching between an installed package and a local copy (import statement is identical, no changes to source needed).

Quote from: tapeworm711
When terminal.read_str() accepting input from the keyboard, is there a way to allow the use of the NUMPAD numbers? Cannot seem to enable this.
That should be fixed in this update, see above.

Quote from: Serin Delaunay
Would it be possible to extend the terminal storage, writing, and drawing outside the bounds imposed by TK_WIDTH and TK_HEIGHT?
Well, I'll probably implement that one way or another. This would help tiles which are bigger than a cell like square map tiles, it is currently hard to place them above or to the left of the viewport even if you do not need any pixel offsets.

That said, personally I do not think that putting tiles into (0, 0) makes things messier. It could be easily wrapped into something like
Code: [Select]
def put_freely(x, y, dx, dy, c):
    terminal.put(0, 0, x*cell_width + dx, y*cell_height + dy, c)
to make intent clear in the source code.

The most messy part is that offsets themselves are a hack to the pseudo-terminal ideology. It is fine for a tile or two but for the whole scene there is almost no support, you have to recalculate and readd every tile. It would be nice to have scrolling viewport and cells with different geometry but devising a sane API for that seems close to impossible.
« Last Edit: January 09, 2017, 11:11:38 AM by Cfyz »