AtomicPair/wolfentext3d

Ruby Curses

Opened this issue · 8 comments

Hi, awesome project!

Have you thought about using http://ruby-doc.org/stdlib-2.0.0/libdoc/curses/rdoc/Curses.html for rendering? It's much better fit for rendering ascii game graphics on console than puts: ). It would require for all output to go through curses, but will probably be worth it, performance and feature wise.

I'm using guake console on rather powerful stationary pc, and any colored mode is completely unusable with 5-8 fps...

I will have a couple of hours in next days, and this is fun enough for me to produce a PR with it if you are not very attached to using puts for rendering : )

Thanks, @killapl!

I explored using Ruby's built-in curses library during the initial stages of the project, but I decided it against it for two reasons:

  1. Since the Ruby curses library is nothing more than a wrapper class for the OS-level library, using curses as the primary renderer would create an additional third-party dependency requirement for anyone who played the game. (Linux and Mac users are more likely to have the required curses libraries installed, but woe to the Windows user who has to install ncurses on their system.) :-)
  2. Even without using curses, I was able to emulate similar cursor handling and rendering functionality by using Ruby's STDIN and STDOUT objects to output customized ANSI/VT100 terminal control codes. Some examples of this can be found here and here.

That said, color rendering still renders noticeably slow on every Windows terminal I've tried, and I've not yet had time to research an appropriate solution. If it can be shown that curses provides a measurable benefit across a large number of users and terminals, then I would certainly be willing to include it as an option within the program and let the user choose their preferred rendering system.

As a test, I installed the latest Guake console from GitHub onto my local machine here -- an HP Pavilion dv7 built in 2010 running Ubuntu 14.04 -- and the best frame rate I could manage was around 11-12 fps. Since I routinely achieve 45-60 fps in the native GNOME Terminal, I suspect something funky may be afoot with Guake's terminal emulation.

Out of curiosity, what distribution are you running? Also, have you tried Wolfentext in any other terminals?

Curses is in stdlib with 2.0.0, only after 2.1.0 it's moved to gem, so it should be there for windows users.
With native terminal, I'm getting 9-11 fps for colored output, and at least it's not cluttering. It is still unplayable, however.
I'm using ubuntu, maybe this is a reason.
I'll try to play with curses, and we'll see where this leads to.

@AtomicPair I thought I'll give you a little status update. I have a proof of concept working and producing 47-48 fps on both coloring modes. I can get it to work as fast as with no coloring, I have at least a couple of ideas for speedup. You can find the code here: https://github.com/KillaPL/wolfentext3d

For now I'm 2 problems away from creating a PR:

  • I'm not sure if I can get more than 8 colors with curses.
  • I'm not sure if I can output utf-8 characters

I wrote on ruby-curses github about the colors, we'll see how it goes.

@AtomicPair I got a respons from curses supporter: ruby/curses#17 (comment). It would seem that newest curses is needed to support more than 8 colors, and that ruby-curses itself will need an update.

I don't suppose anybody will want to fiddle with c libraries, so I suppose the issue is dead.

After a little bit more work, I found a way to use 16 characters, but only for front colors. This allows me to implement fully functional "2" color mode, but not 3.

Thanks for your work on this, @killapl. Fortunately, I don't think we need to abandon this effort just yet.

In testing the current development build across several different terminals on my local Ubuntu installation, I've found at least two items that may partly explain the variations in rendering performance:

  1. On hybrid graphics systems like my laptop, using the integrated Intel graphics can produce lower frame rates in some terminals versus using the discrete ATI graphics. This is a small but obvious option that may help some users.
  2. More importantly, some of the terminal emulators — like tmux — are using their own versions of curses for text rendering.  This may explain why, even when using basic VT100 escape codes for output, I see 45+ fps in tmux but only 10 fps in the standard GNOME Terminal.

In looking deeper into the ncurses sources, it appears that ncurses does little more than wrap the standard terminal output codes to render it's output. The difference is that it uses the termcap/terminfo data provided by the system to help it determine the most optimal type of output codes to use for the current terminal environment. Variations in terminal implementations can affect what features are supported and even how many items are rendered, meaning a proper rendering system will have to take these differences into account if it wishes to be performant.

My current thinking is if we can duplicate the necessary curses functionality ourselves, we can potentially solve our performance problems without relying any third-party dependencies, while also keeping the code lean by only building what we need to support the most popular terminals.

I'm planning to push some big changes to the code this week, but perhaps we can revisit this afterwards. Let me know if you have any further thoughts in the meantime.

@AtomicPair I personally wouldn't want to spend time reimplementing curses, just not my kind of fun, and seems like reinventing the wheel. However, with architecture I have in place, rendering adapters are interchangeable, and I have both stdout adapter working, and curses adapter. If you wish, I can still send you a PR with these, and properly functioning modes 1 and 2, I have that ~90% done.

@killapl I've recently pushed several updates to the project that loosely adopt some of the structural changes reflected in your fork, all of which should make the code a bit more modular and easier to extend with custom rendering adapters, if necessary.

Feel free to have a look at the updated code and graft your curses code into the new structure. When you're ready, you can submit a pull request and we'll look at integrating your code into the main project.