Add Movable Player to Map

Pages: 12
Anyway, If it is feasible, I would like to stick with using a console application for now.


It's certainly feasible, it's just more difficult. The console is not really designed for this kind of use.

Libs like SFML actually make this kind of thing easier, not harder. The tradeoff is you'll have to learn something new... so it might seem more difficult at first because it's new... but once you get familiar with it, you won't regret it.
If you're using Visual Studio on Windows, this might work:
http://www.cplusplus.com/forum/general/51271/

one change to make it easier and more efficient would be to not redraw the whole map each time the player moves, just redraw the character the player moved from with the original map character, then draw the player in the space they moved to.

Esslercuffi, I don't suppose you could show me some example code as to how to redraw the character to different coordinates?
well here's a breakdown of what needs to be done.

after you get the input for which way to move, call a function which takes the map array, the player's current coordinates, and the movement direction.
that function would do the following:

-draw the map character for the character's current location (mapArray[playerX][playerY])
-update the player's coordinates based on direction. (make sure they don't move off edge of map)
-draw the player character at the new location.
Just thought of a problem I overlooked before. The displayMap() function would need to be reworked to display the map at known coordinates, otherwise you won't know which cursor position to move to. Also, since windows consoles can be resized, this can get really flaky. This is another reason 2D graphics can be easier to deal with. you can set up fixed windows so you always know exactly what you're dealing with. Back in the days of DOS, you could directly access the video card memory buffer and that made doing this kind of thing really simple. These days, the windows console is really set up for streaming I/O.

As others have said, doing this kind of thing in text mode is doable, but it gets sloppy and annoying. If you're doing this as an exercise to learn c++ language features, there's probably better exercises to tackle that won't distract you with system specific minutia like this. If you're doing this as an exercise in game programming, then I'd recommend diving in with a graphics library.
I appreciate that using the console is not the most intuitive way to get player movement on a map to work. However, I would really like to do this, just so that I know I can. Then I can move on.

I'm looking at your instructions and I'm sorry but I can't make sense of how to implement them. I would love it if you would demonstrate with some example code.
I suppose I could take a stab at it. Not much goin' on today anyway :)
well, here's what I came up with:
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <iostream>
#include <Windows.h>
#define MAP_ROWS 15
#define MAP_COLS 20

using namespace std;

void displayMap( char mapArray[MAP_ROWS][MAP_COLS] );
void MovePlayer( char mapArray[MAP_ROWS][MAP_COLS], int& plrX, int& plrY, char Dir );


int main()
{
	int playerX = 5;
	int playerY = 5;
	char playerMove = ' ';

	char mapArray[MAP_ROWS][MAP_COLS] =
	{
		{'_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','|'}
	};


	displayMap( mapArray );

	HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD CurPos;

	CurPos.X = 5;
	CurPos.Y = MAP_ROWS + 3 ;
	SetConsoleCursorPosition( console, CurPos );

	cout << "Choose a direction to move (U, D, L, R): ";

	while( true )
	{
		CurPos.X = 46; // at end of prompt string
		CurPos.Y = MAP_ROWS + 3 ;
		SetConsoleCursorPosition( console, CurPos );

		cin >> playerMove;

		if( playerMove == 'q' ) // Quit
			break;
		else
			MovePlayer( mapArray, playerX, playerY, playerMove );
	}

	return 0;
}


void displayMap( char mapArray[MAP_ROWS][MAP_COLS] )
{
	HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD CurPos;

	for( int row = 0; row < MAP_ROWS; row++ )
	{
		// moves the map in 5 chars from left and leave an empty row at top
		CurPos.X = 5;
		CurPos.Y = row + 1 ;
		SetConsoleCursorPosition( console, CurPos );

		for( int col = 0; col < MAP_COLS; col++ )
		{
			cout << mapArray[row][col];
		}
	}
}



void MovePlayer( char mapArray[MAP_ROWS][MAP_COLS], int& plrX, int& plrY, char Dir )
{
	HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD CurPos;

	// restore map tile at player's current location
	CurPos.X = plrX + 5; 
	CurPos.Y = plrY + 1 ;
	SetConsoleCursorPosition( console, CurPos );
	cout << mapArray[plrY][plrX];

	// Move the player
	switch( Dir )
	{
		case 'U':
		case 'u':
			if( plrY > 1 )
				plrY--;
			break;
		case 'D':
		case 'd':
			if( plrY < (MAP_ROWS - 2) )
				plrY++;
			break;
		case 'L':
		case 'l':
			if( plrX > 1 )
				plrX--;
			break;
		case 'R':
		case 'r':
			if( plrX < (MAP_COLS - 2) )
				plrX++;
			break;
		default:
			// ignore bad input
			break;
	}


	// Draw character at new location
	CurPos.X = plrX + 5; 
	CurPos.Y = plrY + 1 ;
	SetConsoleCursorPosition( console, CurPos );
	cout << '@';

	return;
}


There's a bug in there somewhere. while moving around, I sometimes get a strange character left behind.

Forgot to draw the player at initial location. Should be easy enough to figure out how from here.
Last edited on
I don't understand some of that, but I've got to say, you the man!

Thank you very much for taking the time to do that for me. Now I just need to spend the next week trying to figure it out... :)
which parts don't you understand?
Things like:
1
2
3
4
5
int& plrX
HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE); 
COORD CurPos; 
CurPos.X
SetConsoleCursorPosition( console, CurPos );
ok, in no particular order....

HANDLE console = ....
This is a Windows thing that you really shouldn't concern yourself with too much at this point. Similar to the way you use a variable name to access a certain chunk of memory, like mapArray points to the block of memory which holds your character data, a HANDLE just creates a variable which points to the console window. Seems odd at this point, but when you realize that it is possible for a single program to spawn multiple individual console windows, you'll understand why they're needed. For our purposes here, GetStdHandle( STD_OUTPUT_HANDLE ); just returns a handle to the current console window.

SetConsoleCursorPosition() is a function which (as you may have guessed) moves the cursor to the position specified by CurPos within the console pointed to by our previously created colsole HANDLE. The only reason the HANDLE is even created is so that we can pass it to this function.

COORD CurPos is just a structure very similar to the one I showed you back at the beginning of the thread. Again, we only use it here because the SetConsoleCursorPosition() function expects to get one as a parameter. We set CurPos.X, and CurPos.Y to the position we want the cursor to be at, then pass the CurPos structure and the console HANDLE to SetConsoleCursorPosition() which does the actual cursor movement. Now any output from cout will start at those coordinates.


All of the above stuff isn't anything that you should twist yourself into knots worrying about exactly what's going on until you get into Windows programming. While still learning the basics of C++, just trust that it'll get the job done and move on.


The part that you should pay attention to is the
int& plrX

This is a nifty little thing we call 'passing by reference'.

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
#include <iostream>
using namespace std;

void junkFunc1( int a );
void junkFunc2( int& a );


int main()
{
	int x = 1;
	int y = 1;

	cout << "x = " << x << endl;
	cout << "y = " << y << endl;

	junkFunc1( x );
	junkFunc2( y );

	cout << "x = " << x << endl;
	cout << "y = " << y << endl;
}

void junkFunc1( int a )
{
	a += 2;
	return;
}

void junkFunc2( int& a )
{
	a += 2;
	return;
}


junkFunc1 passes its parameter by value.
junkFunc2 passes its parameter by reference.

Passing by value gives a copy of the variable to the function. the function therefore cannot change the value of the variable in main()

Passing by reference gives the called function direct access to the same variable in main(). in junkFunc2() 'a' is just another name for 'y' in main(). both names refer to the same memory address.

the output of the above program is:
x = 1
y = 1
x = 1
y = 3
Last edited on
Funkist posted:
Here's a nice and explicit tutorial:

http://www.youtube.com/watch?v=kfRjvvgjTNQ

It helped me out back when i wanted to do the same thing.


I'm not gonna comment on the code in that 'tutorial', because I'm not even gonna look at it. What the hell is the point of making a video of someone typing? Is delivering your code in tidy small text files just too convenient? Is he just concerned that I might not reach my ISPs bandwidth cap for the month and is trying to make sure I get full value for the money I pay them?

If you're going to make a video tutorial, at least speak and explain what you're doing rather than blasting metal tunes to show how hard-core your mad coding skillz are. This is ridiculous.
I'm underestimating the difficulty of implementing my ideas. Anyway, If it is feasible, I would like to stick with using a console application for now.
I think you are. You should probably just avoid the console altogether, because it usually involves hacking and ugly code (You've already gotten a taste of it.)

would you recommend SFML 2.1 or SDL 2.0?
I personally prefer SDL 2.0, but beginners often like to use SFML 2.1. I gave some reasons why I prefer SDL 2.0 in my original post I believe. If it means anything, people find SDL 2.0 is a lot quicker to set up than SFML, but it takes a few more lines of code to get something on the screen.

Esslercuffi wrote:
I think trying to set up and use a graphics library could be a bit overwhelming, and distracting if you're just doing this as a learning exercise.

As to your question, are you trying to figure out how to move your character around the map without redrawing the map each frame and scrolling the last frame off the top of the console?
I'll have to disagree with you. You often spend most of your time making interactive games in the console hacking around crap that's irrelevant to actual development.

It's fairly straightforward to set up a graphical library.
Last edited on
Avilius, I don't think the OP was really interested in actually making a full game. just toying around with this as a programming exercise. Yes, setting up a graphics library is easy, if you are comfortable with your language and IDE. The OP struck me as someone who was just starting out and wanted to fairly quickly toy around with a simple idea (although the implementation may not have turned out as simple as he initially thought it might be).

Some people learn programming by just following their course requirements, or reading straight through a book while perhaps actually doing a few of the exercises at the end of each chapter. Others, especially those who are genuinely interested in programming and not just doing it to complete degree requirements, like to experiment. As they learn something new, they toy around with new concepts as they learn them. This is what this appeared to be to me.

To say to someone doing something as an exercise in the features of the language they're exploring, that they should just scrap it all and do something entirely different kinda misses the point.
I don't know if anyone mentioned this and it won't actually help you solve the problem but..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
	char mapArray[MAP_ROWS][MAP_COLS] =
	{
		{'_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','|'},
		{'|','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','|'}
	};
would be something like

1
2
std::string row = "|__________________|";
std::vector<std::string> gameMap(rows, row);

Though for the very first row you would change index 0 and columns -1 to _ instead of |
Last edited on
Actually, my code OCD kicked in and I changed that bit in my working version, I just didn't post this bit to avoid adding to confusion of the OP.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
	char mapArray[MAP_ROWS][MAP_COLS];
	for( int x = 0; x < MAP_ROWS; x++ )
	{
		for( int y = 0; y < MAP_COLS; y++ )
		{
			if( x == 0 ) // top row
				mapArray[x][y] = '_';
			else if( y == 0 || y == MAP_COLS-1 ) // left or right column
				mapArray[x][y] = '|';
			else if( x == MAP_ROWS-1 ) // Bottom row
				mapArray[x][y] = '_';
			else
				mapArray[x][y] = ' ';
		}
	}
I try to make everything as generic as I can.
Last edited on
Avilius, I don't think the OP was really interested in actually making a full game. just toying around with this as a programming exercise. Yes, setting up a graphics library is easy, if you are comfortable with your language and IDE. The OP struck me as someone who was just starting out and wanted to fairly quickly toy around with a simple idea (although the implementation may not have turned out as simple as he initially thought it might be).
The wealth of tutorials for setting up these libraries for virtually every modern IDE greatly reduces the difficulty in setting up a library.

I am simply suggesting that the OP shouldn't waste their time trying to figure out how to make the console do something it wasn't meant to do, and just learn something that's much simpler. Although I strongly suggest it, I cannot force the OP to do this, it's entirely up to him/her.

Some people learn programming by just following their course requirements, or reading straight through a book while perhaps actually doing a few of the exercises at the end of each chapter. Others, especially those who are genuinely interested in programming and not just doing it to complete degree requirements, like to experiment. As they learn something new, they toy around with new concepts as they learn them. This is what this appeared to be to me.
This is exactly how it struck me as well. I actually did exactly what the OP did, and looking back at it I feel that this was a massive waste of time. I haven't really learned much during that experience that I'll use today. Prototyping with something that's made for that task is much better than hacking something that's inflexible and simplistic.

To say to someone doing something as an exercise in the features of the language they're exploring, that they should just scrap it all and do something entirely different kinda misses the point.
Except it's really ugly and painstaking to do anything even remotely interactive in the console. You're either fiddling with the system libraries (not really cross-platform), or you're struggling to get a beast like ncurses to actually work.

This article sums it up nicely:
http://www.cplusplus.com/forum/articles/28558/

I have to admit that it is quite childish of me to actually draw this out, so I'll try to make this my last reply debating with you. Sorry for any inconvenience.
Last edited on
It's not childish. It's not like we're calling each other Nazis and child molesters. We just have a different take on whether it's useful to spend one's time trying to train a venerable crippled cat to do acrobatics. :)

You make solid points about why it isn't useful to do so in any practical sense. But there is something I admire about someone who will persist in finding a solution to a problem, even when they know that the solution and/or the problem itself isn't in any way valuable. That kind of persistence will go a long way for the OP. In a professional environment, one has to be willing to drop a bad idea like a hot rock. But that kind of thing can leave you with an annoying itch where you constantly wonder why you couldn't figure out how to do it before it had to be abandoned.
Apologies for not posting sooner but I've been very busy with coursework. Who knew getting a degree was so difficult, eh?

Anyway, I feel that the points which have been made have been pertinent on both sides and I appreciate the sentiments behind the cases put forward.

I only wanted to do this out of curiosity. I thought it would be interesting to be able to make a grid with movable objects. Unfortunately it is more complicated than I anticipated and I simply don't have the time to invest in it at the moment.

For now, I'll continue to learn through my coursework. I'll probably come back to this when I feel more comfortable with the relevant aspects of the language.

Thank you all for your efforts and contributions.
Topic archived. No new replies allowed.
Pages: 12