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.
Registered users can post here. Sign in or register to post.
Pages: 12