my player@ slide right and down

@ player
i don't want its slide please help

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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253


#include <Windows.h>
#include <iostream>

void MoveUp(int x, int y);
void MoveDown(int x, int y);
void MoveRight(int x, int y);
void MoveLeft(int x, int y);

using namespace std;
	
	




char Map[20][20] =
{
	"###################",
	"#        *      ^^#",
	"#  #####  #########",
	"#  # Y #  #  ^    #",
	"# *# E #  # ##### #",
	"#  # A #* # # ! # #",
	"#* # H #  #     # #",
	"#  # ! #  ####### #",
	"#@ # ! #          #",
	"###################"
};

int Gamespeed = 100;
int Level = 1;
bool stopgame = false;
int Hp = 100;
int MaxHp = 100;
int Score = 0;

int main()
{
	while(stopgame == false && Level == 1)
	{	
	
		system("cls");
		for (int y = 0; y < 10; y++)
		{
			cout << Map[y] << endl; 
		}

		cout << "Hp: " << Hp << "/" << MaxHp << endl;
		cout << "Score: " << Score << endl;
		cout << "@=You" << endl;
		cout << "*=Enemy" << endl;
		cout << "!=Goal" << endl;
		for (int y = 0; y<20; y++)
		{
			for (int x = 0; x<20; x++)
			{
				switch(Map[y][x])
				{
				case '#':	
					{
						Map[y][x] = 219;
					}
					break;

				case '@':
					{
						if (GetAsyncKeyState(VK_UP) != 0 )
						{
							MoveUp(x, y);
						}
						else if (GetAsyncKeyState (VK_DOWN) != 0)
						{
							MoveDown(x, y);
						}
						else if (GetAsyncKeyState(VK_RIGHT) != 0)
						{
							MoveRight(x, y);
						}
						else if (GetAsyncKeyState(VK_LEFT)!= 0)
						{
							MoveLeft(x, y);
						}
					}
					break;
				}
			}
		}

		Sleep(Gamespeed);
	}

	while (stopgame == false && Level == 2)
	{
		system("cls");
		cout << "You Win!!!\n\n";
		cout << "Your score: " << Score << "\n\n";
		cout << "©supermies games 2014 \n\n";
		system("pause");
		return EXIT_SUCCESS;
	}

	return 0;
}

void MoveUp(int x, int y)
{
	int y2 = (y-1);

	switch(Map[y2][x])
	{
	case ' ':
		{
			Map[y][x] = ' ';
			y -= 1;
			Map[y2][x] = '@';
		}
		break;
	case '!':
		{
			Level = 2;
		}
		break;
	case '*':
		{
			Hp -= 20;
			Map[y][x] = ' ';
			y -= 1;
			Map[y2][x] = '@';	
		}
		break;
	case '^':
		{
			Score += 20;
			Map[y][x] = ' ';
			y -= 1;
			Map[y2][x] = '@';
		}	
		break;
	}
}

void MoveDown(int x, int y)
{
	int y2 = (y+ 1 );

	switch (Map [y2][x])
	{
	case ' ':
		{
			Map[y][x] = ' ';
			y += 1;
			Map[y2][x] = '@';
		}
		break;
	case '!':
		{
			Level = 2;
		}
		break;
	case '*':
		{
			Hp -= 20;
			Map[y][x] = ' ';
			y += 1;
			Map[y2][x] = '@';
		}
		break;
	case '^':
		{
			Score += 20;
			Map[y][x] = ' ';
			y += 1;
			Map[y2][x] = '@';
		}
		break;	
	}
}

void MoveRight(int x, int y)
{
	int x2 = (x + 1);

	switch(Map[y][x2])
	{
	case ' ':
		{
			Map[y][x] = ' ';
			x += 1;
			Map[y][x2] = '@';
		}
		break;
	case '!':
		{
			Level = 2;
		}
		break;
	case '*':
		{
			Hp -= 20;
			Map[y][x] = ' ';
			x += 1;
			Map[y][x2] = '@';
		}
		break;
	case '^':
		{
			Score += 20;
			Map[y][x] = ' ';
			x += 1;
			Map[y][x2] = '@';
		}break;
	} 
}

void MoveLeft(int x, int y)
{
	int x2 = (x - 1);

	switch(Map[y][x2])
	{
	case ' ':
		{
			Map[y][x] = ' ';
			x -= 1;
			Map[y][x2] = '@';
		}
		break;
	case '!':
		{
			Level = 2;
		}
		break;
	case '*':
		{
			Hp -= 20;
			Map[y][x] = ' ';
			x -= 1;
			Map[y][x2] = '@';	
		}
		break;
	case '^':
		{
			Score += 20;
			Map[y][x] = ' ';
			x -= 1;
			Map[y][x2] = '@';
		}	
	}
}

Your problem seems to be conceptual/organizational.

Take a look at lines 55 through 58:

1
2
3
4
        for (int y = 0; y<20; y++)
        {
            for (int x = 0; x<20; x++)
            {


You are looping through the entire map. In this loop, you are checking the user's keypresses and moving the user.

So.. for example.. let's say the player is at x=1... and they press the right key. This is what happens:

- x=0. You check to see if the map character is '@'. It isn't.
- x=1. You check to see if the map character is '@'. It is, so you move the character to the right
- x=2. You check to see if it's '@'. It is (because you just moved it), so you move it again
- x=3. You check for '@'. It is, so you move it again
and again
and again
until you hit a wall or until the loop ends.


Same thing happens when you press down.

The solution is to move that logic out of the loop (it's wasteful to have it in a loop anyway... you shouldn't check the buttons 400 times... you should only have to do it once).


The problem is.... you do not keep track of the player's position in dependently. You only know where the player is because he's a '@' symbol on the map.


<side rant>This is one reason why I really dislike console as a medium for games, as it kind of hints at these types of tricks. I strongly consider leaving the console and using an actual graphics lib like SFML. It really is much easier that you'd think.</side rant>


So you need to do a few things.

1) You need to keep track of player position in a better way. I'd create 2 vars named 'playerx' and 'playery' or something... and keep them updated as the player moves.

2) You need to change how the player is drawn. The player and the map are 2 different things and should be drawn separately. This is slightly harder to do on the console that it would be with traditional graphics, but is not impossible.

3) Your move function(s) would need to update the player position, rather than update the map.


I also recommend the following changes:

4) Combine MoveLeft/MoveRight/etc functions into one 'Move' function. Notice how they're largely copy/pastes of each other.

5) Convert your '#' symbols to blocks once at startup (or really, when the map is loaded), rather than every frame.

6) Possibly even make some defines rather than use magic numbers/symbols.

7) The correct way to use GetAsyncKeyState is to check the high bit of the return value... not to check for nonzero.

8) Only redraw if you need to (to minimize flickering) -- ie, only redraw if the player moved.

9) Eventually you'll probably want to get rid of those globals and put things in a class... but it's fine for now.



I made those changes (except for #9) here. I also added comments so you can follow what I did. Let me know if you have questions.
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#include <Windows.h>
#include <iostream>

/*
void MoveUp(int x, int y);
void MoveDown(int x, int y);
void MoveRight(int x, int y);
void MoveLeft(int x, int y);*/
bool Move(int xadj, int yadj);  // <- combining all 4 move functions into a single thing.
                                //  ie:  Move(-1,  0) would move left
                                //       Move( 0, -1) would move up
                                //       Move( 1,  0) would move right, etc
                                //  returns a boolean.  'true' if the move was successful (map needs to be redrawn)
                                //    false otherwise.

void LoadMap();                 // <- adding a function to load the map
void DrawScreen();              // <- and one to draw it

using namespace std;
    
    




char Map[10][20] =      // <- only have 10 rows, so I changed this to 10
{
    "###################",
    "#        *      ^^#",
    "#  #####  #########",
    "#  # Y #  #  ^    #",
    "# *# E #  # ##### #",
    "#  # A #* # # ! # #",
    "#* # H #  #     # #",
    "#  # ! #  ####### #",
    "#@ # ! #          #",
    "###################"
};

int Gamespeed = 100;
int Level = 1;
bool stopgame = false;
int Hp = 100;
int MaxHp = 100;
int Score = 0;
int PlayerX = 0;
int PlayerY = 0;

// some constants so it's easier to follow than magic symbols
const char Tile_Wall  = (char)219;
const char Tile_Floor = ' ';
const char Tile_Goal  = '!';
const char Tile_Enemy = '*';    // note, enemy and bonuses probably should be in-game objects and not part
const char Tile_Bonus = '^';    //  of the map.  But again, since this is the console, that's harder to do... so
                                //  for this example, I'm going to leave them as part of the map.  Please consider
                                //  leaving the console... it is a terrible medium for games.

int main()
{
    LoadMap();      // load the map
    DrawScreen();   // and immediatley draw it

    while(stopgame == false && Level == 1)      // then go into your game loop
    {
        // see if the player moves
        //   note the change to GetAsyncKeyState here... I'm checking & 0x8000... I'm not looking for nonzero
        bool playermoved = false;

             if(GetAsyncKeyState(VK_UP   ) & 0x8000)  playermoved = Move( 0,-1);
        else if(GetAsyncKeyState(VK_DOWN ) & 0x8000)  playermoved = Move( 0, 1);
        else if(GetAsyncKeyState(VK_LEFT ) & 0x8000)  playermoved = Move(-1, 0);
        else if(GetAsyncKeyState(VK_RIGHT) & 0x8000)  playermoved = Move( 1, 0);

        // if the player moved, redraw the screen
        if(playermoved)
            DrawScreen();

        // then wait for next frame
        Sleep(Gamespeed);
    }

    while (stopgame == false && Level == 2)
    {
        system("cls");
        cout << "You Win!!!\n\n";
        cout << "Your score: " << Score << "\n\n";
        cout << "©supermies games 2014 \n\n";
        system("pause");
        return EXIT_SUCCESS;
    }

    return 0;
}

bool Move(int xadj, int yadj)
{
    // find the new position the player is trying to move to
    int x = PlayerX + xadj;
    int y = PlayerY + yadj;

    // see if they can move there
    bool canmove = true;      // assume they can move to this tile

    switch(Map[y][x])
    {
    case Tile_Wall:     canmove = false;        break;  // can't move onto a wall
    case Tile_Floor:                            break;  // no special action needed for the floor
    case Tile_Goal:     ++Level;                break;  // move to the next level
    case Tile_Enemy:    Hp -= 20;               break;  // hurt the player
    case Tile_Bonus:    Score += 20;            break;  // give them a bonus
    }

    // if they can move... move them
    if(canmove)
    {
        // update their position
        PlayerX = x;
        PlayerY = y;

        // and since enemyes/bonuses are part of the map, remove them here so the user can't
        //  step on them again
        Map[y][x] = Tile_Floor;
    }

    // finally, return whether or not they moved
    return canmove;
}

void LoadMap()
{
    // Loading the map does 2 things.
    //  1)  It replaces the '#' characters with wall tiles
    //  2)  It find the '@' character, removes it, and puts our player there

    for(int y = 0; y < 10; ++y)
    {
        for(int x = 0; x < 20; ++x)
        {
            switch(Map[y][x])
            {
            case '#':                       // is it a '#'?
                Map[y][x] = Tile_Wall;      // if so, replace it with a wall.
                break;

            case '@':                       // is the the player?
                Map[y][x] = Tile_Floor;     // if so, replace it with a floor.
                PlayerX = x;                // and put our player here
                PlayerY = y;
                break;
            }
        }
    }
}


void DrawScreen()
{
    // clear the screen (clunky to do in the console... but whatev)
    system("cls");
    
    // drawing the map is clunky in the console.  Ordinarily you would draw the map, then just
    //  draw the player and other objects on top of it... but with the console, you kind of have
    //  to draw everything at once, so we have to 'combine' the player and the map before
    //  drawing.  There are ways around this... but whatever

    // put the player back in the map
    Map[PlayerY][PlayerX] = '@';

    // draw each row
    for (int y = 0; y < 10; y++)
    {
        cout << Map[y] << '\n';     // <- note I don't use endl because I don't want to
                                    //    flush the buffer yet (reduce flicker).  It's a weird console thing.
                                    //    .. this is a nonissue with graphic libs.
    }

    // now that it's drawn, take the player out of the map again
    Map[PlayerY][PlayerX] = Tile_Floor;     // assume they were standing on a floor tile.

    // now draw the rest:
    cout << "Hp: " << Hp << "/" << MaxHp << '\n';       // <- again note not using endl
    cout << "Score: " << Score << '\n';
    cout << "@=You" << '\n';
    cout << "*=Enemy" << '\n';
    cout << "!=Goal" << endl;       // <- until I'm done drawing.. then I want it to flush.  So use endl here.
}
Thank you very much! :D
i'm noob
Topic archived. No new replies allowed.