Page 1 of 2

Fast Console Rendering

Posted: Fri Feb 23, 2007 2:09 pm
by quickie
Hello, this is my first post.

I have a question:
Is there any faster way to render the Console window compared to Printing each character by to Fors and ConsoleLocations.

This is how it is done now.

Code: Select all

Protected X.c, Y.c
For Y.c = 0 To #Console_Height
	For X.c = 0 To #Console_Width
		ConsoleLocate(X.c, Y.c)
		ConsoleColor(Console(X.c, Y.c)\Color.c, 0)
		Print(Chr(Console(X.c, Y.c)\Char.c))
	Next
Next
It works fine but is very slow.

Any ideas?

Thanks!

Posted: Tue Feb 27, 2007 2:23 pm
by quickie
Hi,

please let me bump up this post.

I found out that I can use WriteConsoleData() like the code below to achive the effect I want, but only in "Non-graphical" mode.

Would there be a similar way to do this? Because the current method above(First post) is way too slow for a Roguelike.

Thanks.

Code: Select all

OpenConsole()

#Console_Size = 2000
Global *Buffer = AllocateMemory(#Console_Size)

Repeat
	For i = 0 To #Console_Size
		PokeB(*Buffer + i, Random(93) + 33)
	Next
	ClearConsole()
	WriteConsoleData(*Buffer, #Console_Size)
Until Input() <>""

CloseConsole()

Posted: Tue Feb 27, 2007 2:41 pm
by Derek
Have you considered using a graphics screen and printing to that instead of using a console window?

Posted: Tue Feb 27, 2007 2:49 pm
by Kaeru Gaman
- afaik the "non-graphical" mode of the console has only additional shell-functions,
there is no difference in the display.
I wonder, why the buffer-access shouldn't work in graphical mode.

- your first code could be speeded up by two changes:
- - locate only in the outer loop, also concides not to locate but to print a newline at the end of the inner loop.
- - only call ConsoleColor, if the color really changed.

- think about Derek's suggestion.
with only a little effort you can develop a similar look of the surface,
with every conveniences of a 2D-Grafix-surface.

Posted: Tue Feb 27, 2007 3:46 pm
by dracflamloc
You're approaching this from the wrong angle anyway.

What you need to do with a console and plotting characters is different than the way you're used to with graphical screens.

For instance your 2d-gfx rendering loop would be like so:

Code: Select all

Repeat
 flipbuffers()
 clearscreen()

 ;loop through and draw everything 
 drawtext(....
 drawsprite(...

 delay(5)
Forever
But with a console thats very inefficient and pointless. What you do is if you need a change, track those changes and immediately draw that change. You have no 'rendering loop' persay.

You just clear the character you need to update by locating, then printing a space. Or you just print the character that it needs to be changed to if its not being cleared.

Example:

Code: Select all

Repeat
 if inkey()="J" ;move left
   consolelocate(playerx,playery)
   print(" ") ;clear old position
   playerx - 1
   consolelocate(playerx,playery)
   print("P") ;draw new pos
 elseif inkey()="L" ;move right
   consolelocate(playerx,playery)
   print(" ") ;clear old position
   playerx + 1
   consolelocate(playerx,playery)
   print("P") ;draw new pos
 endif
 delay(5)
Forever

[edit]
Also, if you really need to draw the way you are thinking then you should buffer the drawing. For example:

Code: Select all

Protected X.c, Y.c
For Y.c = 0 To #Console_Height
   buf.s=""
   For X.c = 0 To #Console_Width
      if X = #Console_Width
        buf + Console(X.c, Y.c)\Char
        ConsoleLocate(0, Y.c)
        Print(Chr(Console(X.c, Y.c)\Char.c))
      else
        buf + Console(X.c, Y.c)\Char
      endif
   Next
Next 
This would need more consideration to handle colors but should be a similar piece of code. You should not run this code in a 'rendering loop' either. You still will want to track changes.

Also consider making a macro to handle color changes and location and printing all in one step. You may want to add code to see if the color needs changing and only call ConsoleColor if the color is different:

Code: Select all

Macro PrintChar(string,x,y,color)
  ConsoleColor(color)
  ConsoleLocate(x,y)
  Print(string)
EndMacro

Macro PrintCharAndClear(string,x,y,color,oldx,oldy)
  ConsoleColor(color)
  Consolelocate(oldx,oldy)
  print(" ")
  ConsoleLocate(x,y)
  Print(string)
EndMacro

Posted: Tue Feb 27, 2007 5:51 pm
by quickie
Thanks everybody for all the advice!

Derek:
I was thinking of that as a last resort, since I wanted the atmosphere of an "authentic" console :P !

Kaeru Gaman:
I don't know why either but the manual says it can't, and so does the compiler :(

Thanks, I'll try a bit more before considering a 2D solution.

dracflamloc:
Thanks for the examples!

About the approach thing, I was thinking of having the whole map scroll if needed, which is why I wanted to redraw the whole console screen. I've seen some games that do this, so figured that it should be possible.

Oh and about the buffer idea, I thought of that as well but wouldn't that be a problem with color? The reason I think so is because each "print" prints out a whole string of letters, there isn't any way to specify the color of each character.

Ohhh, the irony of having to speed up text mode drawing to get decent game play! heheh

Posted: Tue Feb 27, 2007 6:43 pm
by dracflamloc
You probably can use the buffering thing with colors, the loop will just be a bit more complex and will have to compare the previous character's color with the current one. If they aren't the same, print the buffer,clear it and set the new color, and continue with the loop.

Even with a scrolling map you won't need to reprint everything. I'd have a 'current' and 'changed' array. Loop through the changed array when you print everything to screen, but only actually call print if current(x,y)\char is not equal to changed(x,y)\char

Posted: Tue Feb 27, 2007 7:47 pm
by Kaeru Gaman
fine so far.
just one more remark:
quickie wrote:I wanted the atmosphere of an "authentic" console :P !
it is absolutely possible with a 2D screen, pixel by pixel identically,
and it is not that much work as it sounds,
but you have really more convenience in displaying and calculating.
it will no longer be the output, that slows your program down.

Posted: Tue Feb 27, 2007 8:57 pm
by dracflamloc
Well if hes in graphical mode coloring the reasons for using the traditional console window kind of go out the window anyway.

The benefits of using a normal console window are basically limited to its simplicity and piping output through other programs and interfaces.

Posted: Wed Feb 28, 2007 6:15 am
by quickie
Thanks again for all the advice.

When I was coding in QBasic, I *think* I was able to POKE in the characters as well as the colors.

For example:

Code: Select all

DEF SEG where ever the console vram is
POKE 0, 14
POKE 1, 65
something like the above displaying a bright yellow A on the left top corner of the screen.

Fiddling around with ConsoleWriteMem, it seems as if the console video memory isn't constructed in that way(Color, Char, Color, Char and so on)...

dracflamloc:
Ah, I see, yeah that could speed it up alot, especially with Roguelikes :)
Thanks!

Kaeru Gaman:
Yeah, I know it's possible to make it pixel perfectly the same, but I want to start off with a completely console mode, and then work up to graphics if the project goes well, and be able to switch between the 2, or have 2 separate versions.

For example:
http://www.santiagoz.com/web/news.php
this Roguelike has 2 modes, console mode and graphical mode, which works surprisingly well(I think it uses a generic RL engine though).

I've uploaded what I've done so far, in case anyone is interested :)
http://wing2.jp/~upploader/cgi-bin/up/src/up3670.zip

Thanks again.

Posted: Wed Feb 28, 2007 10:59 am
by Derek
Looks quite good, keep us posted. :)

Posted: Wed Feb 28, 2007 1:39 pm
by Kaeru Gaman
> When I was coding in QBasic, I *think* I was able to POKE in the characters as well as the colors.

in those times the "console" was a real video ram in the graphics card that ran in textmode.
means, you wrote chars and colors into the mem on the GraCa,
like you write color-values into one of the two buffers today.

today a console is some allocated mem of an application that is translated
into bitmap information wich is passed to the GraCa to display.

It's a totally different hardware-approach.

Posted: Wed Feb 28, 2007 2:46 pm
by dracflamloc
Quickie, looks cool. I can't wait to try it when its done =)

I love console games

Posted: Wed Feb 28, 2007 5:17 pm
by quickie
Derek:
Thanks :D

Kaeru Gaman:
Hmm, I see, yeah I understand that but if I ran the QB program on modern hardware, it'd probably work. I still think that copying a whole gob of info into the console is possible given the right knowledge.

Just tried, and the following QB code works in WinXP:

Code: Select all

DEF SEG = &HA000
POKE 0, 1
POKE 0, 14
So yeah, I think with the console "screen mode", it's still possible to fast update it.

dracflamloc:
Thanks :)
Can't wait to work on the map generator.

Posted: Wed Feb 28, 2007 6:30 pm
by JCV
phew I remember the game I played when I was in highschool. Its really a good game. 8)

Adom - Ancient Domains of Mystery
http://www.adom.de/