简体   繁体   中英

C++ - Class private variables not changing

Ive been programming in C++ for a while and am using the SDL2 library to make a game. Unfortunately, the class for the player has variables that only change in the method and then don't update for later use.

Header:

class playerChar {
public:
     void move();
     void handleInput(SDL_Event& lEvent);
     void render();
     int getValX();
     int getValY();
     playerChar();
private:
     int pPosX, pPosY;             //Pos and Direction arent changing
     int pDirectionX, pDirectionY;
     //Posion and Direction (direction. Has value -1, 0 or 1)
     static const int pVel = 10;
     static const int pHeight = 10, pWidth = 10;
     eTexture playerTex;
};

cpp file:

playerChar::playerChar(){
     pPosX = 0;
     pPosY = 0;
     pDirectionX = 0;
     pDirectionY = 0;
     playerTex.loadFile("playerIMG.png");
}

void playerChar::handleInput(SDL_Event& lEvent){
     //Key Pressed
     if(lEvent.type == SDL_KEYDOWN && lEvent.key.repeat == 0){
          switch(lEvent.key.keysym.sym){
               case SDLK_UP:
               pDirectionY = -1;
               break;
               case SDLK_s:
               pDirectionY = 1;
               printf("%i\n", pDirectionY);
               break;
               case SDLK_d:
               pDirectionX = 1;
               break;
               case SDLK_a:
               pDirectionX = -1;
               break;
               default:
               break;
          }
     }
     //Key Released
     else if(lEvent.type == SDL_KEYUP && lEvent.key.repeat == 0){
          switch(lEvent.key.keysym.sym){
               case SDLK_w:
               pDirectionY = 0;
               break;
               case SDLK_s:
               pDirectionY = 0;
               break;
               case SDLK_d:
               pDirectionX = 0;
               break;
               case SDLK_a:
               pDirectionX = 0;
               break;
               default:
               break;
          }
     }
}

void playerChar::move(){
     //printf("pos:%i, vel:%i, dir:%i\n", pPosY, pVel, pDirectionY);
     pPosX += pVel*pDirectionX;
     pPosY += pVel*pDirectionY;
     //If Direction is + then it adds velocity
     //If Direction is - then it subtracts
     //If Direction is 0 then adds nothing
     //printf("%i, %i\n", pDirectionX, pDirectionY);
}

void playerChar::render(){
     playerTex.render(pPosX, pPosY);
}

int playerChar::getValX(){
     return pDirectionX;
}

int playerChar::getValY(){
     return pDirectionY;
}

Ive been checking the values of them with printf()s every frame (it is just a printf() in the main() that uses the getValX/Y() methods). The one inside of the handleInput() shows that it has changed in the method but then the one that runs every frame says that it is still 0. I mainly tested pressing s.

Ive tried making the handleInput() method return the value and then making a set method but that didnt fix it.

Ive looked over many websites and forums and an experienced friend who was also stumped and couldn't work out the problem. Any help is greatly appreciated.

Edit:
Sorry if I am too vague, Im trying to keep it concise. The cpp above ONLY contains the methods for the playerChar class.
The actual implementation in Main() is

int main(int argc, char* args[]) {
//irrevelvant to question

playerChar player;
while(!quit) {
          fpsTimer.start();
          quit = eInputCheck(event, player);

          if(fpsTimer.getTicks() < ticksPerFrame) {
               SDL_Delay(ticksPerFrame - fpsTimer.getTicks());
          }
          SDL_RenderClear(gRenderer);

          //Render new frame here
          player.move();
          player.render();
          printf("%ix, %iy\n", player.getValX(), player.getValY());
          SDL_RenderPresent(gRenderer);
     }
     eClose();
     return 0;
}  

Where eInputCheck() is from controls.cpp

bool eInputCheck(SDL_Event event, playerChar player){
     while(SDL_PollEvent(&event) != 0){
          player.handleInput(event);
          if(event.type == SDL_QUIT){
               return true;
          }
     return false;
}

I am trying to make it so that pDirectionX/Y change to 1 / -1 for direction and making 0 a standstill. The problem is that, even while holding the button down, it doesnt appear to change when I call the getValX/Y method in main.

Terminal appears like so while running and I press s:

0x, 0y
0x, 0y
0x, 0y
0x, 0y
0x, 0y
0x, 0y
0x, 0y
1        //The printf() from inside the handleInput() method
0x, 0y
0x, 0y
0x, 0y
0x, 0y

it even gives this while holding the button down. (I press ESC to end the program)

You pass a COPY to eInputCheck , this copy is constructed when enters the function. You pass playerChar by value.

It is like this

playerChar otherOne = player; // Copies the player to the variable otherOne using a "copy constructor"

There is a lot of cases in C++, it is a very rich language.

playerChar otherOne = player;   // Copies the player (said before).

playerChar &reference = player; // Reference is now refers to otherOne,
                                // a change on reference is reflected
                                // on player.

otherOne = player;              // otherOne was initialized before,
                                // so copy constructor is not called
                                // But a copy assignment is called instead

reference = otherOne;           // Reference was set before to refer to
                                // player, so, a "copy assignment" is
                                // called. Because references always
                                // refers to the same object
                                // initialized with. So, C++ solves this
                                // by copying the otherOne to the object
                                // refered by reference, using a copy 
                                // assignment operator

This is one of the most confusing and difficult part in C++.

You have two solutions,

  1. The modern solution (which is I think not good for C++ in performance), immutability, try to return a new instance of player from eInputCheck .

  2. Second solution is to pass a REFERENCE to eInputCheck

Please redefine eInputCheck like this:

bool eInputCheck(SDL_Event &event, playerChar &player){
    while(SDL_PollEvent(&event) != 0){
        player.handleInput(event);
        if(event.type == SDL_QUIT){
            return true;
        }
    return false;
}

This makes a reference passed to your function. Read this please:

Reference concept in C++

Passing arguments by reference

Copy constructor

Copy assignment

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM