Faster Output

The game Ive been working on recently im having trouble with. It prints out a 45 x 80 map, and everytime you move it reprints the whole map. However, cout doesnt seem to do it fast enough, and the character blinks each time you move, and it delays the movement from the button press. Is there a way I can get this to go faster?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include "header.h"
#include "mapdata.h"
#include "playerdatabase.h"
#include "commandcentral.h"

using namespace std;

void printmap()
{
 HANDLE hPrint, hBuffer;
 hPrint = GetStdHandle(STD_OUTPUT_HANDLE);
 COORD pos;
 pos.X = 0;
 pos.Y = 0;
 SetConsoleCursorPosition(hPrint, pos);
 for(int Y = 0; Y < 45; Y++)
 {
  for(int X = 0; X < 80; X++)
  {
   SetConsoleTextAttribute(hPrint, cGameMap[0][Y][X]);
   printf("%c", tGameMap[0][Y][X]);
  }
 }
 pos.X = mapx;
 pos.Y = mapy;
 SetConsoleCursorPosition(hPrint, pos);
 SetConsoleTextAttribute(hPrint, clr);
 printf("%c", symbl);
 pos.X = 2;
 pos.Y = 46;
 SetConsoleCursorPosition(hPrint, pos);
 SetConsoleTextAttribute(hPrint, 7);
 cout << gamemsg << "                                                           ";
 gamemsg = "";
 cmdcent();
}
http://www.cplusplus.com/forum/articles/28558/

And if that doesn't change your mind, I suggest that instead of redrawing the whole map you should redraw only the parts that change (using SetConsoleCursorPosition).
I may look into that, but Id rather just do this game first. I heard about WriteConsoleOutput, but im not sure how to use that. I think its mainly for reading the screen and re-outputting it. The microsoft site is too confusing to understand.
That's one of the problems with using the console as a medium for games. I recommend looking into SFML: http://www.sfml-dev.org/download.php
Oh, right. I didn't notice you were printfing. Yes WriteConsoleOutput is the thing you need.
Is there any example of using WriteConsoleOutput() to use an array? The one on the microsoft site doesnt help, it just copies the screen. And I have trouble understanding it.
1
2
3
4
CHAR_INFO buffer[45*80]; //fill this
COORD null = {0, 0}, size = {80, 45};
SMALL_RECT rect = {0, 0, 80, 45};
WriteConsoleOutput( GetStdHangle( STD_OUTPUT_HANDLE ), buffer, null, size, &rect );
something like that..
I cant figure this out. Here is the chunk of code I tried:

1
2
3
4
5
6
7
8
9
10
11
12
CHAR_INFO buffer[45*80];
 for(int filly = 0; filly < 45; filly++)
 {
  for(int fillx = 0; fillx < 80; fillx++)
  {
   buffer[filly*fillx].Char.AsciiChar = tGameMap[0][filly][fillx];
   buffer[filly*fillx].Attributes = cGameMap[0][filly][fillx];
  }
 }
 COORD null = {0, 0}, size = {80, 45};
 SMALL_RECT rect = {0, 0, 80, 45};
 WriteConsoleOutput( GetStdHandle( STD_OUTPUT_HANDLE ), buffer, null, size, &rect );


I dont get errors, but it doesnt do anything.

EDIT: Forgot {} for the second for, but it still doesnt do anything.
Last edited on
filly*fillx isn't right. You won't change all elements like that. It should be fillx+filly*80.
I don't know what's in your arrays. Try AsciiChar = ' ' and Attributes = 0xFF for simplicity.
edit: whoops. I switched null with size in my code. sorry. http://msdn.microsoft.com/en-us/library/ms687404(v=vs.85).aspx
Last edited on
It worked now. The null and size switched was the problem. Thanks, it works much smoother now.

EDIT:
New problem, I'm having trouble with movement. For some reason if I try moving around the map too fast by holding the movement keys, the game gets a runtime error and shuts down. I tried using debug, and it says:

An access violation (Segmentation Fault) raised in your program.
Last edited on
that means you have a problem in your code...
I added something to see how many times it prints the map, and I can do exactly 140 moves everything time before it does this. What could be the problem? After clicking any button 140 times, the game pauses and shuts down. It breaks on this line:
WriteConsoleOutput( GetStdHandle( STD_OUTPUT_HANDLE ), buffer, size, null, &rect );
Last edited on
Do you only call WriteConsoleOutput when a key is pressed?
It would be weird if writeconsoleoutput was the problem. Many times I've used where it was called several times every second. What else do you do when a key is pressed?
When you start the game, it goes into a function with an infinite loop, until you exit the game. It keeps asking for you to press a key, with getch(). And then it sends the info to a function movechar(), which decides if the character can move and/or do another action, and then it sends the map coordinates to the player file, and then goes to the printscreen file and prints out the whole map. It does all this everytime you press a key, and later it will have to process all the monster movements and stuff too. Heres the code in order of what it does:

(commandcentral.cpp)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void cmdcent()
{
 bool gameLoop = true;
 char cmd;
 while(gameLoop == true)
 {
  cmd = getch();
  int dir[9][2] = {
   {-1, 1}, {0, 1}, {1, 1},
   {-1, 0}, {0, 0}, {1, 0},
   {-1,-1}, {0,-1}, {1,-1}
  };
if( cmd <= '9' && cmd >= '1' )
   movechar( dir[cmd-'1'][0], dir[cmd-'1'][1], '0' );
else if( cmd == ';' || cmd == '<' || cmd == '>' )
   movechar(0, 0, cmd);
 }
} ^ Thanks to you hamsterman


(movechar.cpp)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
int movechar(int toX, int toY, char key)
{
 steps++;
 /*Game Obstacles: -1 = Empty
                   0 = Wall
                   1 = Floor
                   2 = Closed Door
                   3 = Open Door
                   4 = Tree
                   5 = Water
                   6 = Up Stairs
                   7 = Down stairs
                   18 = Pile of Sand
                   200 = Lever 1
                   201 = Bridge 1
                   202 = Door 1
                   203 = Monster Release 1
                   220 = Lever 2
                   240 = Lever 3
                   260 = Lever 4
                   280 = Lever 5
                   300 = Lever 6
 */
 if(key == '0')
 {
  if(mapy+toY > 0 && mapy+toY < 44 && mapx+toX > 0 && mapx+toX < 79)
  {
   if(tGameObstaclePositions[mapz][mapy+toY][mapx+toX] == -1)
   {
    mapy += toY;
    mapx += toX;
   }
   else if(tGameObstaclePositions[mapz][mapy+toY][mapx+toX] == 0)
   {
    gamemsg += "You smack into a wall! ";
   }
   else if(tGameObstaclePositions[mapz][mapy+toY][mapx+toX] == 1 || tGameObstaclePositions[mapz][mapy+toY][mapx+toX] == 18 || tGameObstaclePositions[mapz][mapy+toY][mapx+toX] == 6 || tGameObstaclePositions[mapz][mapy+toY][mapx+toX] == 7)
   {
    mapy += toY;
    mapx += toX;
   }
   else if(tGameObstaclePositions[mapz][mapy+toY][mapx+toX] == 4)
   {
    gamemsg += "There is a tree standing here. ";
   }
   else if(tGameObstaclePositions[mapz][mapy+toY][mapx+toX] == 5)
   {
    gamemsg += "There is water here. ";
   }
  }
  else
  {
   gamemsg += "No.";
  }
 }
 else if(key == '>')
 {
  if(tGameObstaclePositions[mapz][mapy][mapx] == 7)
  {
   mapz--;
  }
  else
  {
   gamemsg += "There is no downward stairway here. ";
  }
 }
 else if(key == '<')
 {
  if(tGameObstaclePositions[mapz][mapy][mapx] == 6)
  {
   mapz++;
  }
  else
  {
   gamemsg += "There is no upward stairway here. ";
  }
 }
 else if(key == ';')
 {
  if(tGameObstaclePositions[mapz][mapy][mapx] == 18)
  {
   gamemsg += "You scoop up a handful of soft sand. ";
  }
 }
 if(tGameObstaclePositions[mapz][mapy][mapx] == -1)
  {
   gamemsg += "You feel yourself floating. ";
  }
 printmap();
}


(printmap.cpp)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using namespace std;

void printmap()
{
 HANDLE hPrint;
 hPrint = GetStdHandle(STD_OUTPUT_HANDLE);
 COORD pos;
 pos.X = 0;
 pos.Y = 0;
 SetConsoleCursorPosition(hPrint, pos);
 CHAR_INFO buffer[45*80];
 for(int filly = 0; filly < 45; filly++)
 {
  for(int fillx = 0; fillx < 80; fillx++)
  {
   buffer[fillx+filly*80].Char.AsciiChar = tGameMap[0][filly][fillx];
   buffer[fillx+filly*80].Attributes = cGameMap[0][filly][fillx];
  }
 }
 COORD null = {0, 0}, size = {80, 45};
 SMALL_RECT rect = {0, 0, 80, 45};
 WriteConsoleOutput( GetStdHandle( STD_OUTPUT_HANDLE ), buffer, size, null, &rect ); pos.X = mapx;
 pos.Y = mapy;
 SetConsoleCursorPosition(hPrint, pos);
 SetConsoleTextAttribute(hPrint, clr);
//And here
 cout << symbl;
 pos.X = 2;
 pos.Y = 46;
 SetConsoleCursorPosition(hPrint, pos);
 SetConsoleTextAttribute(hPrint, 7);
 cout << gamemsg << "                                                           ";
 cout << steps; <-- steps is what I used to count the number of times it runs through this       before the game shuts down. It does it exactly 140 times.
 gamemsg = "";
 cmdcent();
}
Last edited on
Why does printmap() call cmdcent() ?
I think that's the problem. Every printmap needs 45*80*4 and then some bytes of stack, so after 140 recursive calls you run out of it.
Last edited on
Actually now that I think of it, thats probably it. I put that there for the first time because it calls that function at the begininng of the game once, but then it just opens the function another time. Ill have to fix my code and just make it print the map at the beginning.

EDIT: It works now. My program is fixed, I can move on now. Although it took me 15 minutes to wonder why my character wouldnt move, and I realized num lock wasnt on, since I use the numpad to move...
Last edited on
Topic archived. No new replies allowed.