Couple of bugs in a game

I made a minimal version of the game I'm making and there are 2 bugs that keep occuring.
If the player's health is 5 or 0, suddenly maxhealth becomes 200 instead of 20.
If the player's health is 10, a potion heals it up to 20, instead of 15 like it should.

Here's the code (it works, but with the bugs I specified)
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
#include <iostream>
#include <windows.h>

class Hero
{
private:
    unsigned short Health, MaxHealth;
    unsigned short CurrentY, CurrentX, NewY, NewX;

public:

    //Constructor
    Hero()
    {
        MaxHealth = 20;
        Health = 20;
    }

    //Destructor
    ~Hero() { ; }

    //Getters
    const unsigned short getHealth() const { return Health; }
    const unsigned short getMaxHealth() const { return MaxHealth; }
    const unsigned short getCurrentY() const { return CurrentY; }
    const unsigned short getCurrentX() const { return CurrentX; }
    const unsigned short getNewY() const { return NewY; }
    const unsigned short getNewX() const { return NewX; }

    //Setters
    void setHealth(unsigned short _Health) { Health = _Health; }
    void setMaxHealth(unsigned short _MaxHealth) { MaxHealth = _MaxHealth; }
    void setCurrentY(unsigned short _CurrentY) { CurrentY = _CurrentY; }
    void setCurrentX(unsigned short _CurrentX) { CurrentX = _CurrentX; }
    void setNewY(unsigned short _NewY) { NewY = _NewY; }
    void setNewX(unsigned short _NewX) { NewX = _NewX; }

    //Updaters
    void newHealth(short _Health) { Health += _Health; }
    void newMaxHealth(short _MaxHealth) { MaxHealth += _MaxHealth; }
    void newCurrentY(short _CurrentY) { CurrentY += _CurrentY; }
    void newCurrentX(short _CurrentX) { CurrentX += _CurrentX; }
    void newNewY(short _NewY) { NewY += _NewY; }
    void newNewX(short _NewX) { NewX += _NewX; }
};

/********************************
        Global variables
********************************/
char (* Map)[10][20];
Hero Player;

void controls()
{
    (*Map)[Player.getCurrentY()][Player.getCurrentX()] = '@';
    Player.setNewX( Player.getCurrentX() );
    Player.setNewY( Player.getCurrentY() );

    if (GetAsyncKeyState(VK_UP) != 0)    Player.newNewY(-1);
    if (GetAsyncKeyState(VK_DOWN) != 0)  Player.newNewY(+1);
    if (GetAsyncKeyState(VK_LEFT) != 0)  Player.newNewX(-1);
    if (GetAsyncKeyState(VK_RIGHT) != 0) Player.newNewX(+1);

        switch ( (*Map)[Player.getNewY()][Player.getNewX()] )
        {
            case ' ': //Moves the player
            (*Map)[Player.getCurrentY()][Player.getCurrentX()] = ' ';
            Player.setCurrentX( Player.getNewX() );
            Player.setCurrentY( Player.getNewY() );
            (*Map)[Player.getNewY()][Player.getNewX()] = '@';
            break;

            case '*': //Trap - takes away 5 health
            Player.newHealth(-5);
            //if (Player.getHealth() <= 0) gameover(); <- I have it, but it's unrelated to the problem
            (*Map)[Player.getCurrentY()][Player.getCurrentX()] = ' ';
            Player.setCurrentX( Player.getNewX() );
            Player.setCurrentY( Player.getNewY() );
            (*Map)[Player.getNewY()][Player.getNewX()] = '@';
            break;

            case '+': //Potion - adds 5 health
            if (Player.getHealth() < Player.getMaxHealth() -5)  Player.newHealth(+5);
            if (Player.getHealth() >= Player.getMaxHealth() -5) Player.setHealth( Player.getMaxHealth() );
            (*Map)[Player.getCurrentY()][Player.getCurrentX()] = ' ';
            Player.setCurrentX( Player.getNewX() );
            Player.setCurrentY( Player.getNewY() );
            (*Map)[Player.getNewY()][Player.getNewX()] = '@';
            break;
        }
    Sleep(100);
}

void MoveCursorHome()
{
    HANDLE  hStdOut;
    COORD   homeCoords = { 0, 0 };
    hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );

    if (hStdOut == INVALID_HANDLE_VALUE)
        return;

    /* Move the cursor home */
    SetConsoleCursorPosition( hStdOut, homeCoords );
}

int main()
{

bool running = true;

char mymap [10][20] =
{"###################",
 "#      +          #",
 "#           *     #",
 "# +      *        #",
 "#           *     #",
 "#   +             #",
 "#        *   +    #",
 "#                 #",
 "###################" };

    Map = &mymap;
    Player.setCurrentY(1), Player.setCurrentX(1);
    while (running)
    {
        MoveCursorHome();
        for (int i = 0; i < 10; i++)
        {
            std::cout << (*Map)[i] << "\n";
        }
        std::cout << "Health: " << Player.getHealth() << "/" << Player.getMaxHealth();
        controls();
    }

    return 0;
}


Sorry that it's a bit long, but I shrank it as much as I could.
Last edited on
If the player's health is 10, a potion heals it up to 20, instead of 15 like it should.


Line 83 will raise health from 10 to 15. Then line 84 is evaluated. That will raise health from 15 to 20.

You want an "else if" in line 84.

Edit: Actually, you just want an "else"
Last edited on
closed account (zb0S216C)
Vidminas wrote:
 
//if (Player.getHealth() <= 0) 

"Hero::Health" cannot be any lower than zero because it's unsigned.

On line 83, I would write any of the following:

1
2
3
4
5
6
7
// Option A:
if( Player.setHealth( Player.getHealth( ) + 5 ) > Player.getMaxHealth( ) )
  Player.setHealth( Player.getMaxHealth( ) );

// Option B:
if( ( Player.getMaxHealth( ) - Player.getHealth( ) ) >= 5 )
  Player.setHealth( Player.getHealth( ) + 5 );

I personally would add another member function to "Hero" that allows you to add additional health points without resetting the entire health value, like so:

1
2
3
4
5
6
7
class Hero
{
    // ...
  public:
    // ...
    void addHealth( unsigned short _Value ) { Health += _Value; }
};

EDIT: Sorry, I missed the "newHealth( )" member function.

Wazzak
Last edited on
If the player's health is 5 or 0, suddenly maxhealth becomes 200 instead of 20.


From the code you posted here, I don't know how you know this. If it's from line 132, try putting << std::endl at the end of the line to make sure you're not getting some spurious '0' from somewhere else.

I don't see where max health is being set, so it's a mystery to me.
Ok I fixed the potion bug with your suggestions (and I now understand why the bug was there)
I wrote that:
1
2
3
4
5
case '+': //Potion - adds 5 health
            if ( Player.getHealth() +5 < Player.getMaxHealth() )
                Player.newHealth(+5);
            else
                Player.setHealth( Player.getMaxHealth() );


By the way my newHealth() thing uses a signed short as a value, so you can also take away like Player.newHealth(-5)
(in maths value +- 5, is the same as value - 5)

And I changed Health and MaxHealth to short instead of unsigned short (just to handle any possible errors)

... and finally
I wrote:
If the player's health is 5 or 0, suddenly maxhealth becomes 200 instead of 20.
doug4 wrote:
From the code you posted here, I don't know how you know this
Ummm... maybe because I can see that on the screen, when the program is running? (the exact same code I posted, well... with the potion fix)
You have to compile the code for yourself, so you can see (or possibly, it's due to my computer?)

doug4 wrote:
I don't see where max health is being set
It's set to 20 in the constructor.

I know that there's no code that affects maxhealth, so it still confuses me, must be a leak or something somewhere. And I changed the line where the health is displayed to
std::cout << "Health: " << Player.getHealth() << "/" << Player.getMaxHealth() << std::endl;
but that didn't help, maxhealth still becomes 200 when the player's health is 5 or 0.
So there's one more bug to go!
Last edited on
closed account (zb0S216C)
Here's a tip, make "Hero::maxHealth" constant so that any attempt to modify the value of "maxHealth" will produce an error. And when you've found the troublesome line, remove the const-ness (I would keep "maxHealth" constant if it's not meant to change after initialisation).

1
2
3
4
5
6
7
8
9
10
11
class Hero
{
  // ...
  private:
    unsigned int Health;
    unsigned int const maxHealth;
};

Hero::Hero( )
  : maxHealth( 20u ), Health( maxHealth ) // "maxHealth" must be initialised this way when constant.
{ }

If the output still produces the same 200 value, then it's a problem with the output, not "maxHealth".

Wazzak
Last edited on
maxHealth( 20u ) not maxHealth(20) ?
I don't know, I tried it both ways. At first I got a few errors, because I had to remove the setter and the "updater" for maxHealth. Then I got a few warnings that maxHealth is initialized afterwards so I cannot do Health( maxHealth ), because then Health becomes 0.

The warnings I'm getting are:

main.cpp: In constructor 'Hero::Hero()':
main.cpp:7:19: warning: 'Hero::MaxHealth' will be initialized after [-Wreorder]
main.cpp:7:11: warning:   'short int Hero::Health' [-Wreorder]
main.cpp:13:5: warning:   when initialized here [-Wreorder]


maxHealth still becomes 200 when Health is 5 or less... So the problem is not with the code, then?
I have no idea how to troubleshoot something like this... I don't even know what to google :P.

One of the weirdest things is that it becomes 20 again, when Health is above 5

EDIT: To fix the warnings you just have to declare MaxHealth before Health
Last edited on
I am running on a linux machine. I made changes as shown below to get rid of Windows-specific code. It worked like a charm.

To run my version of the code, you have to type "a"<return> to move left, "w"<return> to move up, etc. It was just for debugging purposes, but it showed no problems with your MaxHealth value.

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
#include <iostream>

class Hero
{
private:
    unsigned short Health, MaxHealth;
    unsigned short CurrentY, CurrentX, NewY, NewX;

public:

    //Constructor
    Hero()
    {
        MaxHealth = 20;
        Health = 20;
    }

    //Destructor
    ~Hero() { ; }

    //Getters
    const unsigned short getHealth() const { return Health; }
    const unsigned short getMaxHealth() const { return MaxHealth; }
    const unsigned short getCurrentY() const { return CurrentY; }
    const unsigned short getCurrentX() const { return CurrentX; }
    const unsigned short getNewY() const { return NewY; }
    const unsigned short getNewX() const { return NewX; }

    //Setters
    void setHealth(unsigned short _Health) { Health = _Health; }
    void setMaxHealth(unsigned short _MaxHealth) { MaxHealth = _MaxHealth; }
    void setCurrentY(unsigned short _CurrentY) { CurrentY = _CurrentY; }
    void setCurrentX(unsigned short _CurrentX) { CurrentX = _CurrentX; }
    void setNewY(unsigned short _NewY) { NewY = _NewY; }
    void setNewX(unsigned short _NewX) { NewX = _NewX; }

    //Updaters
    void newHealth(short _Health) { Health += _Health; }
    void newMaxHealth(short _MaxHealth) { MaxHealth += _MaxHealth; }
    void newCurrentY(short _CurrentY) { CurrentY += _CurrentY; }
    void newCurrentX(short _CurrentX) { CurrentX += _CurrentX; }
    void newNewY(short _NewY) { NewY += _NewY; }
    void newNewX(short _NewX) { NewX += _NewX; }
};

/********************************
        Global variables
********************************/
char (* Map)[10][20];
Hero Player;

void controls()
{
    (*Map)[Player.getCurrentY()][Player.getCurrentX()] = '@';
    Player.setNewX( Player.getCurrentX() );
    Player.setNewY( Player.getCurrentY() );

/*
    if (GetAsyncKeyState(VK_UP) != 0)    Player.newNewY(-1);
    if (GetAsyncKeyState(VK_DOWN) != 0)  Player.newNewY(+1);
    if (GetAsyncKeyState(VK_LEFT) != 0)  Player.newNewX(-1);
    if (GetAsyncKeyState(VK_RIGHT) != 0) Player.newNewX(+1);
*/
	char input;
	std::cin >> input;

    if (input == 'w') Player.newNewY(-1);
    else if (input == 'z') Player.newNewY(+1);
    else if (input == 'a') Player.newNewX(-1);
    else if (input == 's') Player.newNewX(+1);

        switch ( (*Map)[Player.getNewY()][Player.getNewX()] )
        {
            case ' ': //Moves the player
            (*Map)[Player.getCurrentY()][Player.getCurrentX()] = ' ';
            Player.setCurrentX( Player.getNewX() );
            Player.setCurrentY( Player.getNewY() );
            (*Map)[Player.getNewY()][Player.getNewX()] = '@';
            break;

            case '*': //Trap - takes away 5 health
            Player.newHealth(-5);
            //if (Player.getHealth() <= 0) gameover(); <- I have it, but it's unrelated to the problem
            (*Map)[Player.getCurrentY()][Player.getCurrentX()] = ' ';
            Player.setCurrentX( Player.getNewX() );
            Player.setCurrentY( Player.getNewY() );
            (*Map)[Player.getNewY()][Player.getNewX()] = '@';
            break;

            case '+': //Potion - adds 5 health
            if (Player.getHealth() < Player.getMaxHealth() -5)
					Player.newHealth(+5);
            else
					Player.setHealth( Player.getMaxHealth() );
            (*Map)[Player.getCurrentY()][Player.getCurrentX()] = ' ';
            Player.setCurrentX( Player.getNewX() );
            Player.setCurrentY( Player.getNewY() );
            (*Map)[Player.getNewY()][Player.getNewX()] = '@';
            break;
        }
    //Sleep(100);
}

void MoveCursorHome()
{
#if 0
    HANDLE  hStdOut;
    COORD   homeCoords = { 0, 0 };
    hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );

    if (hStdOut == INVALID_HANDLE_VALUE)
        return;

    /* Move the cursor home */
    SetConsoleCursorPosition( hStdOut, homeCoords );
#else
	for (int i = 0; i < 80; ++i)
	{
		std::cout << std::endl;
	}
#endif

}

int main()
{

bool running = true;

char mymap [10][20] =
{"###################",
 "#      +          #",
 "#           *     #",
 "# +      *        #",
 "#           *     #",
 "#   +             #",
 "#        *   +    #",
 "#                 #",
 "###################" };

    Map = &mymap;
    Player.setCurrentY(1), Player.setCurrentX(1);
    while (running)
    {
        MoveCursorHome();
        for (int i = 0; i < 10; i++)
        {
            std::cout << (*Map)[i] << "\n";
        }
        std::cout << "Health: " << Player.getHealth() << "/" << Player.getMaxHealth() << std::endl;
        controls();
    }

    return 0;
}
closed account (zb0S216C)
Vidminas wrote:
"maxHealth( 20u ) not maxHealth(20)?"

It's a small detail, but the "u" suffix denotes an unsigned integer literal. You don't have to have it there, but it's better if you do.

Vidminas wrote:
" Then I got a few warnings that maxHealth is initialized afterwards so I cannot do Health( maxHealth ), because then Health becomes 0."

Sorry about that -- long day. Simply change the declaration order of "maxHealth" and "Health".

Can you update your code so that we know what changes you've made.

Wazzak
Ok I'll give the code, but since doug4's version doesn't have that bug (doug4 why didn't you use WASD, I mean it took me a while to understand your WAZS version)
I think that there's either a leak from GetAsyncKeyState or MoveCursorHome(), but I have no idea.
And the debugger doesn't say anything...

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
#include <iostream>
#include <windows.h>

class Hero
{
private:
    const unsigned short MaxHealth;
    short Health;
    unsigned short CurrentY, CurrentX, NewY, NewX;

public:

    //Constructor
    Hero() : MaxHealth(20u), Health(MaxHealth) {}

    //Destructor
    ~Hero() { ; }

    //Getters
    const unsigned short getHealth() const { return Health; }
    const unsigned short getMaxHealth() const { return MaxHealth; }
    const unsigned short getCurrentY() const { return CurrentY; }
    const unsigned short getCurrentX() const { return CurrentX; }
    const unsigned short getNewY() const { return NewY; }
    const unsigned short getNewX() const { return NewX; }

    //Setters
    void setHealth(unsigned short _Health) { Health = _Health; }
    //void setMaxHealth(unsigned short _MaxHealth) { MaxHealth = _MaxHealth; }
    void setCurrentY(unsigned short _CurrentY) { CurrentY = _CurrentY; }
    void setCurrentX(unsigned short _CurrentX) { CurrentX = _CurrentX; }
    void setNewY(unsigned short _NewY) { NewY = _NewY; }
    void setNewX(unsigned short _NewX) { NewX = _NewX; }

    //Updaters
    void newHealth(short _Health) { Health += _Health; }
    //void newMaxHealth(short _MaxHealth) { MaxHealth += _MaxHealth; }
    void newCurrentY(short _CurrentY) { CurrentY += _CurrentY; }
    void newCurrentX(short _CurrentX) { CurrentX += _CurrentX; }
    void newNewY(short _NewY) { NewY += _NewY; }
    void newNewX(short _NewX) { NewX += _NewX; }
};

/********************************
        Global variables
********************************/
char (* Map)[10][20];
Hero Player;
/*******************************/

void controls()
{
    (*Map)[Player.getCurrentY()][Player.getCurrentX()] = '@';
    Player.setNewX( Player.getCurrentX() );
    Player.setNewY( Player.getCurrentY() );

    if (GetAsyncKeyState(VK_UP) != 0)    Player.newNewY(-1);
    if (GetAsyncKeyState(VK_DOWN) != 0)  Player.newNewY(+1);
    if (GetAsyncKeyState(VK_LEFT) != 0)  Player.newNewX(-1);
    if (GetAsyncKeyState(VK_RIGHT) != 0) Player.newNewX(+1);

        switch ( (*Map)[Player.getNewY()][Player.getNewX()] )
        {
            case ' ': //Moves the player
            (*Map)[Player.getCurrentY()][Player.getCurrentX()] = ' ';
            Player.setCurrentX( Player.getNewX() );
            Player.setCurrentY( Player.getNewY() );
            (*Map)[Player.getNewY()][Player.getNewX()] = '@';
            break;

            case '*': //Trap - takes away 5 health
            Player.newHealth(-5);
            //if (Player.getHealth() <= 0) gameover(); <- I have it, but it's unrelated to the problem
            (*Map)[Player.getCurrentY()][Player.getCurrentX()] = ' ';
            Player.setCurrentX( Player.getNewX() );
            Player.setCurrentY( Player.getNewY() );
            (*Map)[Player.getNewY()][Player.getNewX()] = '@';
            break;

            case '+': //Potion - adds 5 health
            if ( Player.getHealth() +5 < Player.getMaxHealth() )
                Player.newHealth(+5);
            else
                Player.setHealth( Player.getMaxHealth() );
            (*Map)[Player.getCurrentY()][Player.getCurrentX()] = ' ';
            Player.setCurrentX( Player.getNewX() );
            Player.setCurrentY( Player.getNewY() );
            (*Map)[Player.getNewY()][Player.getNewX()] = '@';
            break;
        }
    Sleep(100);
}

void MoveCursorHome()
{
    HANDLE  hStdOut;
    COORD   homeCoords = { 0, 0 };
    hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );

    if (hStdOut == INVALID_HANDLE_VALUE)
        return;

    /* Move the cursor home */
    SetConsoleCursorPosition( hStdOut, homeCoords );
}

int main()
{

bool running = true;

char mymap [10][20] =
{"###################",
 "#      +          #",
 "#           *     #",
 "# +      *        #",
 "#           *     #",
 "#   +             #",
 "#        *   +    #",
 "#                 #",
 "###################" };

    Map = &mymap;
    Player.setCurrentY(1), Player.setCurrentX(1);
    while (running)
    {
        MoveCursorHome();
        for (int i = 0; i < 10; i++)
        {
            std::cout << (*Map)[i] << "\n";
        }
        std::cout << "Health: " << Player.getHealth() << "/" << Player.getMaxHealth() << std::endl;
        controls();
    }

    return 0;
}
Last edited on
closed account (zb0S216C)
This line:

 
if ( Player.getHealth() +5 < Player.getMaxHealth() )

...should be:

 
if ( Player.getHealth() +5 <= Player.getMaxHealth() )

Wazzak
@Framework That doesn't make a difference, because both ways it adds 5 to Health. However I did that, just because I can.

And I took the linux-friendly version further (it doesn't have this bug (I don't know why) and there wouldn't be a problem if linux had a way of capturing keys without pressing enter (and without getch() from conio.h) and could get the arrow keys)

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
#include <iostream>
#include <string>

class Hero
{
private:
    unsigned short Health, MaxHealth;
    unsigned short CurrentY, CurrentX, NewY, NewX;

public:

    //Constructor
    Hero()
    {
        MaxHealth = 20;
        Health = 20;
    }

    //Destructor
    ~Hero() { ; }

    //Getters
    const unsigned short getHealth() const { return Health; }
    const unsigned short getMaxHealth() const { return MaxHealth; }
    const unsigned short getCurrentY() const { return CurrentY; }
    const unsigned short getCurrentX() const { return CurrentX; }
    const unsigned short getNewY() const { return NewY; }
    const unsigned short getNewX() const { return NewX; }

    //Setters
    void setHealth(unsigned short _Health) { Health = _Health; }
    void setMaxHealth(unsigned short _MaxHealth) { MaxHealth = _MaxHealth; }
    void setCurrentY(unsigned short _CurrentY) { CurrentY = _CurrentY; }
    void setCurrentX(unsigned short _CurrentX) { CurrentX = _CurrentX; }
    void setNewY(unsigned short _NewY) { NewY = _NewY; }
    void setNewX(unsigned short _NewX) { NewX = _NewX; }

    //Updaters
    void newHealth(short _Health) { Health += _Health; }
    void newMaxHealth(short _MaxHealth) { MaxHealth += _MaxHealth; }
    void newCurrentY(short _CurrentY) { CurrentY += _CurrentY; }
    void newCurrentX(short _CurrentX) { CurrentX += _CurrentX; }
    void newNewY(short _NewY) { NewY += _NewY; }
    void newNewX(short _NewX) { NewX += _NewX; }
};

/********************************
        Global variables
********************************/
char (* Map)[10][20];
Hero Player;

void controls()
{
    (*Map)[Player.getCurrentY()][Player.getCurrentX()] = '@';
    Player.setNewX( Player.getCurrentX() );
    Player.setNewY( Player.getCurrentY() );

    char movement = {0};
    std::string input;
    while (true)
    {
        getline(std::cin, input);

        if (input.length() == 1)
        {
            movement = input[0];
            break;
        }
    }

    if (movement == 'w') Player.newNewY(-1);
    else if (movement == 's') Player.newNewY(+1);
    else if (movement == 'a') Player.newNewX(-1);
    else if (movement == 'd') Player.newNewX(+1);

        switch ( (*Map)[Player.getNewY()][Player.getNewX()] )
        {
            case ' ': //Moves the player
            (*Map)[Player.getCurrentY()][Player.getCurrentX()] = ' ';
            Player.setCurrentX( Player.getNewX() );
            Player.setCurrentY( Player.getNewY() );
            (*Map)[Player.getNewY()][Player.getNewX()] = '@';
            break;

            case '*': //Trap - takes away 5 health
            Player.newHealth(-5);
            //if (Player.getHealth() <= 0) gameover(); <- I have it, but it's unrelated to the problem
            (*Map)[Player.getCurrentY()][Player.getCurrentX()] = ' ';
            Player.setCurrentX( Player.getNewX() );
            Player.setCurrentY( Player.getNewY() );
            (*Map)[Player.getNewY()][Player.getNewX()] = '@';
            break;

            case '+': //Potion - adds 5 health
            if (Player.getHealth() < Player.getMaxHealth() -5)
					Player.newHealth(+5);
            else
					Player.setHealth( Player.getMaxHealth() );
            (*Map)[Player.getCurrentY()][Player.getCurrentX()] = ' ';
            Player.setCurrentX( Player.getNewX() );
            Player.setCurrentY( Player.getNewY() );
            (*Map)[Player.getNewY()][Player.getNewX()] = '@';
            break;
        }
}

void ScrollDown()
{
	for (unsigned short i = 0; i < 20; i++)
	{
		std::cout << std::endl;
	}
}

int main()
{

bool running = true;

char mymap [10][20] =
{"###################",
 "#      +          #",
 "#           *     #",
 "# +      *        #",
 "#           *     #",
 "#   +             #",
 "#        *   +    #",
 "#                 #",
 "###################" };

    Map = &mymap;
    Player.setCurrentY(1), Player.setCurrentX(1);
    while (running)
    {
        for (int i = 0; i < 10; i++)
        {
            std::cout << (*Map)[i] << "\n";
        }
        std::cout << "Health: " << Player.getHealth() << "/" << Player.getMaxHealth() << std::endl;
        controls();
        ScrollDown();
    }

    return 0;
}
Wonderful example of why getters and setters are evil.

> if linux had a way of capturing keys without pressing enter
curses
ne555 wrote:
Wonderful example of why getters and setters are evil.

It's funny, because I recently started a topic asking why getters and setters are bad and what should I do instead.

At first the aim was to not use curses or SDL, or whatever... But I came to see that my program was Windows only and I'd have to make sacrifices for better code and portability.
Last edited on
Well, if the "Linux-friendly" code works for you without problems, try adding stuff back step by step. First replace ScrollDown with your original MoveCursorHome. See if the bug comes back. Then put back the Sleep statement. Finally put back the GetAsyncKeyState calls.

See where it breaks.

I can't help you with those Windows-specific things. Sorry.

p.s. Oh, and the reason I used wasz is because there was a game that I playe 30 years ago (I have no idea what it was any more) that used those keys to move, and I have been using those keys as navigation keys whenever I need them. I don't do much game writing, but I do remember my early attempts.
Last edited on
I figured it out! It was all caused by the MoveCursorHome() function.
You see when there are 2 numbers of 2 digits like: 20/20, there are 4 digits in total. Then if the first number becomes 5 (one digit) it's like 5/20, 3 digits in total.

basically
10/20
and ↓
5/20

The MoveCursorHome() function never clears the screen, so the 0 from when there were 4 digits stays on screen though the value of MaxHealth itself is never modified. :) Behind that smile, I hate Windows

This can be solved by clearing the line where health is and then displaying it
Last edited on
Topic archived. No new replies allowed.