代码之家  ›  专栏  ›  技术社区  ›  ImAProgrammer

C++-类私有变量未更改

  •  -1
  • ImAProgrammer  · 技术社区  · 7 年前

    我用C++编程已经有一段时间了,我正在使用SDL2库制作一个游戏。不幸的是,player的类中有一些变量,这些变量只会在方法中更改,然后不会更新以供以后使用。

    标题:

    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文件:

    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;
    }
    

    我一直在每帧用printf()检查它们的值(它只是main()中使用getValX/Y()方法的printf()。handleInput()中的一个表示它在方法中已更改,但运行每帧的一个表示它仍然为0。我主要测试了冲压s。

    我尝试让handleInput()方法返回值,然后创建一个set方法,但没有解决这个问题。

    我浏览了许多网站和论坛,还有一位经验丰富的朋友也被难住了,无法解决问题。非常感谢您的帮助。

    编辑:
    对不起,如果我太含糊了,我会尽量保持简洁。上面的cpp只包含playerChar类的方法。
    Main()中的实际实现是

    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;
    }  
    

    其中eInputCheck()来自控件。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;
    }
    

    我试图使PDDirectionX/Y变为1/-1表示方向,并使0表示静止。问题是,即使按住按钮,当我在main中调用getValX/Y方法时,它似乎也没有改变。

    终端在运行时显示为这样,我按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
    

    它甚至会在按下按钮时发出这种声音。(我按ESC结束程序)

    1 回复  |  直到 7 年前
        1
  •  1
  •   user9335240    7 年前

    您将副本传递给 eInputCheck ,则在进入函数时构造此副本。你通过了 playerChar 按值。

    是这样的

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

    C++中有很多例子,它是一种非常丰富的语言。

    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
    

    这是C++中最令人困惑和困难的部分之一。

    有两种解决方案,

    1. 现代解决方案(我认为这对C++的性能不好)、不变性,尝试从 eInputCheck .

    2. 第二种解决方案是将引用传递给 eInputCheck

    请如下重新定义eInputCheck:

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

    这会将引用传递给函数。 请阅读以下内容:

    Reference concept in C++

    Passing arguments by reference

    Copy constructor

    Copy assignment