Fast Console Rendering

Just starting out? Need help? Post your questions and find answers here.
quickie
New User
New User
Posts: 9
Joined: Fri Feb 23, 2007 8:03 am

Fast Console Rendering

Post 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!
quickie
New User
New User
Posts: 9
Joined: Fri Feb 23, 2007 8:03 am

Post 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()
Derek
Addict
Addict
Posts: 2354
Joined: Wed Apr 07, 2004 12:51 am
Location: England

Post by Derek »

Have you considered using a graphics screen and printing to that instead of using a console window?
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post 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.
oh... and have a nice day.
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post 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
quickie
New User
New User
Posts: 9
Joined: Fri Feb 23, 2007 8:03 am

Post 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
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post 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
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post 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.
oh... and have a nice day.
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post 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.
quickie
New User
New User
Posts: 9
Joined: Fri Feb 23, 2007 8:03 am

Post 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.
Derek
Addict
Addict
Posts: 2354
Joined: Wed Apr 07, 2004 12:51 am
Location: England

Post by Derek »

Looks quite good, keep us posted. :)
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post 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.
oh... and have a nice day.
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post by dracflamloc »

Quickie, looks cool. I can't wait to try it when its done =)

I love console games
quickie
New User
New User
Posts: 9
Joined: Fri Feb 23, 2007 8:03 am

Post 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.
JCV
Enthusiast
Enthusiast
Posts: 580
Joined: Fri Jun 30, 2006 4:30 pm
Location: Philippines

Post 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/
Post Reply