简体   繁体   English

C ++-无法获得if语句使用状态工作

[英]C++ - Can't get if statement to work using states

I'm currently creating a project which involves switching between different game states such as main menu to play state and play state to battle state etc. I'm currently struggling with getting my battle state to only draw the enemy the player collides with inside the play state. 我目前正在创建一个项目,该项目涉及在不同的游戏状态之间进行切换,例如在主菜单中切换为播放状态,在游戏状态中切换为战斗状态等。我目前正在努力使战斗状态仅吸引玩家与之碰撞的敌人。播放状态。 I tried doing this using a very simply "enemyNo =;" 我尝试使用非常简单的“ enemyNo =;”来执行此操作 where the first enemy was 1, second was 2, and so on. 第一个敌人是1,第二个敌人是2,依此类推。 then in battle state, tell it "if(enemyNo =1) then draw enemy 1 and it's corresponding stats. Can't for the life of me figure it out, pretty sure im not inheriting the enemyNo value across states properly. Any and all help would be appreciated. 然后在战斗状态下,告诉它“ if(enemyNo = 1)然后画出敌人1及其对应的统计数据。我一生都无法弄清楚它,我敢肯定我不会在各个州之间正确继承敌人No的值。任何和所有帮助将不胜感激。

StatePlay.cpp StatePlay.cpp

#include "StatePlay.h"
#include <iostream>
// stringstream and string
#include <sstream>
#include <string>


#include "Game.h"


StatePlay::StatePlay(void)
{
}


StatePlay::~StatePlay(void)
{
}

void StatePlay::init(Game &context)
{

std::cout << "Initialising play state." << std::endl;
player = new Rect(0.0f, 0.0f, 0.15f, 0.15f);
//player stats
health = 10;
maxHealth = 10;
strength = 10;
speed = 10;
dollars = 0;

noTargets = false;
targetCount = 5;
bruteCount = 3;
raiderCount = 1;

//target
for(int i = 1; i <=5; i++)
{
target[i] = new Rect();
target[i]->setX((float)rand()/RAND_MAX - 0.75f);
target[i]->setY((float)rand()/RAND_MAX - 0.75f);    
targetAlive[i] = true;
}

//brute
for(int i = 1; i <=3; i++)
{
brute[i] = new Rect();
brute[i]->setX((float)rand()/RAND_MAX - 0.75f);
brute[i]->setY((float)rand()/RAND_MAX - 0.75f); 
bruteAlive[i] = true;
}

//raider
for(int i = 1; i <=1; i++)
{
raider[i] = new Rect();
raider[i]->setX((float)rand()/RAND_MAX - 0.75f);
raider[i]->setY((float)rand()/RAND_MAX - 0.75f);    
raiderAlive[i] = true;
}


score = 0; 

}


void StatePlay::enter()
{
std::cout << "Entering play state. Press ESCAPE to return to menu" << std::endl;
}

void StatePlay::exit()
{
}


void StatePlay::draw(SDL_Window * window)
{
// Replace this with OpenGL draw calls to draw the main menu screen

TTF_Font *textFont = TTF_OpenFont("MavenPro-Regular.ttf", 24);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0,1.0,1.0);
player->draw();
std::stringstream strStream2;
std::stringstream strStream3;
strStream2 << "Player" << std::endl;
strStream3 << "Target" << std::endl;
Label :: displayString(player->x() + player->w()/2.0,player->y() + player->h(),     strStream2.str().c_str(), textFont);

//enemy
for(int i = 1; i <=5; i++)
{
    if(targetAlive[i] == true)
    {
Label :: displayString(target[i]->x() + target[i]->w()/2.0,target[i]->y() + target[i]->h(), strStream3.str().c_str(), textFont);

glColor3f(1.0,0.0,0.0);
targetAlive[i] = target[i];
target[i]->draw();
}
}



std::stringstream strStream4;
strStream4 << "Brute" << std::endl;

//brute
for(int i = 1; i <=3; i++)
{
    if(bruteAlive[i] == true)
    {
Label :: displayString(brute[i]->x() + brute[i]->w()/2.0,brute[i]->y() + brute[i]->h(), strStream4.str().c_str(), textFont);

glColor3f(0.6,0.3,0.1);
bruteAlive[i] = brute[i];
brute[i]->draw();

}
}

std::stringstream strStream6;
strStream6 << "Raider" << std::endl;

//raider
for(int i = 1; i <=1; i++)
{
    if(raiderAlive[i] == true)
    {
        Label :: displayString(raider[i]->x() + raider[i]->w()/2.0,raider[i]->y() + raider[i]->h(), strStream6.str().c_str(), textFont);

        glColor3f(0.2,0.9,0.4);
        raiderAlive[i] = raider[i];
        raider[i]->draw();
    }
}

//information
std::stringstream strStream;
std::stringstream strStream1;
strStream << "Score:" << score;
strStream1 << "Health:" << health;
Label :: displayString(-0.9,-0.9, strStream.str().c_str(), textFont);
Label :: displayString(-0.4,-0.9, strStream1.str().c_str(), textFont);
SDL_GL_SwapWindow(window); // swap buffers
}



void StatePlay::handleSDLEvent(SDL_Event const &sdlEvent, Game &context)
{
if (sdlEvent.type == SDL_KEYDOWN)
{
    //std::cout << "Scancode: " << sdlEvent.key.keysym.scancode ;
    //std::cout << ", Name: " << SDL_GetKeyName( sdlEvent.key.keysym.sym ) << std::endl;
    switch( sdlEvent.key.keysym.sym )
    {
        case SDLK_UP:
        case 'w': case 'W':
            player->setY(player->y() + 0.05f);
            break;
        case SDLK_DOWN:
        case 's': case 'S':
            player->setY(player->y() - 0.05f);
            break;
        case SDLK_LEFT:
        case 'a': case 'A':
            player->setX(player->x() - 0.05f);
            break;
        case SDLK_RIGHT:
        case 'd': case 'D':
            player->setX(player->x() + 0.05f);
            break;
        default:
            break;
    }
}


if (sdlEvent.type == SDL_KEYDOWN)
{
    //std::cout << "Scancode: " << sdlEvent.key.keysym.scancode ;
    //std::cout << ", Name: " << SDL_GetKeyName( sdlEvent.key.keysym.sym ) << std::endl;
    switch( sdlEvent.key.keysym.sym )
    {
        case SDLK_ESCAPE:
            context.setState(context.getMainMenuState());
        default:
            break;
    }
}

//target
for(int i = 1; i <=5; i++)
{
if ( (target[i]->x() >= player->x()) && (target[i]->x()+target[i]->w() <= player->x()+player->w())  // cursor surrounds target in x
&& (target[i]->y() >= player->y()) && (target[i]->y()+target[i]->h() <= player->y()+player->h() ) && targetAlive[i] == true ) // cursor surrounds target in y
{   
    score += 100;
    enemyNo = 1;
    context.setState(context.getBattleState());

    delete target[i];
    targetAlive[i] = false;

    targetCount -= 1;

}
}

//brute
    for(int i = 1; i <=3; i++)
{
if ( (brute[i]->x() >= player->x()) && (brute[i]->x()+brute[i]->w() <= player->x()+player->w())     // cursor surrounds target in x
&& (brute[i]->y() >= player->y()) && (brute[i]->y()+brute[i]->h() <= player->y()+player->h() ) && bruteAlive[i] == true ) // cursor surrounds target in y
{   

    score += 100;
    enemyNo = 2;
    context.setState(context.getBattleState());
    delete brute[i];
    bruteAlive[i] = false;

    bruteCount -= 1;

}
}

//raider
for(int i = 1; i <=1; i++)
{
if ( (raider[i]->x() >= player->x()) && (raider[i]->x()+raider[i]->w() <= player->x()+player->w())  // cursor surrounds target in x
&& (raider[i]->y() >= player->y()) && (raider[i]->y()+raider[i]->h() <= player->y()+player->h() ) && raiderAlive[i] == true ) // cursor surrounds target in y
{   
    score += 100;
    enemyNo = 3;
    context.setState(context.getBattleState()); 
    delete raider[i];
    raiderAlive[i] = false;

    raiderCount -= 1;

}
}





}

StatePlay.h StatePlay.h

#ifndef STATE_PLAY
#define STATE_PLAY

#include "gameState.h"
#include "Label.h"
// C stdlib and C time libraries for rand and time functions
#include <cstdlib>
#include <ctime>
#include "rect.h"

class StatePlay : public GameState
{
public:
StatePlay(void);
~StatePlay(void);
void init(Game &context);
void draw(SDL_Window * window);
void handleSDLEvent(SDL_Event const &sdlEvent, Game &context);
void enter();
void exit();
int enemyNo;



int targetCount;
private:
//player Stats
int score;
int health;
int maxHealth;
int strength;
int speed;
int dollars;



int getHealth() {return health;}
int getMaxHealth() { return maxHealth;}
int getStrength() { return strength;}
int getSpeed() { return speed;}
int getDollars() { return dollars; }

void setHealth(int newHealth) { health = newHealth; }
void damageTaken(int damage) { health = health - damage; }
void setMaxHealth(int newHealth) { maxHealth = maxHealth + newHealth; }
void setStrength(int newStrength) { strength = strength+newStrength; }
void setSpeed(int newSpeed) { speed = speed+newSpeed; }
void setDollars(int newDollars) { dollars = dollars+newDollars; }

// Another *strong* candidate for creating a new class type
// is character/agent, to encapsulate player and target data,
// potentially to include an Agent::draw() function and
// perhaps also generalise collision detection
// This is left as a further exercise
float xpos;
float ypos;
float xsize;
float ysize;


//target
float targetXPos;
float targetYPos;
float targetXSize;
float targetYSize;


bool targetAlive[5];
bool noTargets;

//brute
float bruteXPos;
float bruteYPos;
float bruteXSize;
float bruteYSize;

int bruteCount;
bool bruteAlive[5];
bool noBrutes;

//raider
float raiderXPos;
float raiderYPos;
float raiderXSize;
float raiderYSize;

int raiderCount;
bool raiderAlive[1];
bool noRaider;

clock_t lastTime; // clock_t is an integer type
clock_t currentTime; // use this to track time between frames

Label * playerLabel;
Label * targetLabel;
Label * bruteLabel;
Label * raiderLabel;

TTF_Font * textFont;    // SDL type for True-Type font rendering
Rect * player;
Rect * target[5];
Rect * brute[3];
Rect * raider[1];

};

#endif

StateBattle.cpp StateBattle.cpp

#include "StateBattle.h"

#include <iostream>
#include "Game.h"
#include "StatePlay.h"
#include "rect.h"


StateBattle::StateBattle(void)
{
}


StateBattle::~StateBattle(void)
{
}

void StateBattle::init(Game &context)
{
fighting = false;   
}

void StateBattle::enter()
{
std::cout << "Entering main menu state: Press RETURN to play or ESCAPE to quit " <<  std::endl;
}

void StateBattle::exit()
{
}


void StateBattle::draw(SDL_Window * window)
{
glClearColor(0.0f,0.0f,0.0f,0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0,1.0,1.0);
TTF_Font *textFont = TTF_OpenFont("MavenPro-Regular.ttf", 24);
std::stringstream strStream;
strStream << "FIGHT!" <<std::endl;
Label :: displayString(-0.8 ,0.8, strStream.str().c_str(),textFont);

//player
Rect * player;
player = new Rect(-0.4f, 0.0f, 0.15f, 0.15f);
player ->draw();

std::stringstream playerStrStream1;
playerStrStream1 << "Health:" << std::endl;
Label :: displayString(-0.4 ,0.5, playerStrStream1.str().c_str(),textFont);

std::stringstream playerStrStream2;
playerStrStream2 << "Strength:" << std::endl;
Label :: displayString(-0.4 , -0.2, playerStrStream2.str().c_str(),textFont);

std::stringstream playerStrStream3;
playerStrStream3 << "Speed:" << std::endl;
Label :: displayString(-0.4 , -0.3, playerStrStream3.str().c_str(),textFont);

std::stringstream playerStrStream4;
playerStrStream4 << "Dollars:" << std::endl;
Label :: displayString(-0.4 , -0.4, playerStrStream4.str().c_str(),textFont);


//Enemy
if(enemyNo = 1)
{
Rect * target;
glColor3f(1.0,0.0,0.0);
target = new Rect(0.4f, 0.0f, 0.15f, 0.15f);
target->draw();

std::stringstream targetStrStream1;
targetStrStream1 << "Health:" << std::endl;
Label :: displayString(0.4f,0.5f, targetStrStream1.str().c_str(),textFont);

std::stringstream targetStrStream2;
targetStrStream2 << "Strength:" << std::endl;
Label :: displayString(0.4, -0.2, targetStrStream2.str().c_str(),textFont);

std::stringstream targetStrStream3;
targetStrStream3 << "Speed:" << std::endl;
Label :: displayString(0.4, -0.3, targetStrStream3.str().c_str(),textFont);

std::stringstream targetStrStream4;
targetStrStream4 << "Dollars:" << std::endl;
Label :: displayString(0.4, -0.4, playerStrStream4.str().c_str(),textFont);
}

//brute 
if(enemyNo = 2)
{
Rect * brute;
glColor3f(0.6,0.3,0.1);
brute = new Rect(0.6f, 0.0f, 0.15f, 0.15f);
brute->draw();

std::stringstream bruteStrStream1;
bruteStrStream1 << "Health:" << std::endl;
Label :: displayString(0.4, 0.5, bruteStrStream1.str().c_str(),textFont);

std::stringstream bruteStrStream2;
bruteStrStream2 << "Strength:" << std::endl;
Label :: displayString(0.4, -0.2, bruteStrStream2.str().c_str(),textFont);

std::stringstream bruteStrStream3;
bruteStrStream3 << "Speed:" << std::endl;
Label :: displayString(0.4, -0.3, bruteStrStream3.str().c_str(),textFont);

std::stringstream bruteStrStream4;
bruteStrStream4 << "Dollars:" << std::endl;
Label :: displayString(0.4, -0.4, bruteStrStream4.str().c_str(),textFont);
}

//raider
if(enemyNo = 3)
{
Rect * raider;
glColor3f(0.2,0.9,0.4);
raider = new Rect(0.8f, 0.0f, 0.15f, 0.15f);
raider->draw();

std::stringstream raiderStrStream1;
raiderStrStream1 << "Health:" << std::endl;
Label :: displayString(0.4, 0.5, raiderStrStream1.str().c_str(),textFont);

std::stringstream raiderStrStream2;
raiderStrStream2 << "Strength:" << std::endl;
Label :: displayString(0.4, -0.2, raiderStrStream2.str().c_str(),textFont);

std::stringstream raiderStrStream3;
raiderStrStream3 << "Speed:" << std::endl;
Label :: displayString(0.4, -0.3, raiderStrStream3.str().c_str(),textFont);

std::stringstream raiderStrStream4;
raiderStrStream4 << "Dollars:" << std::endl;
Label :: displayString(0.4, -0.4, raiderStrStream4.str().c_str(),textFont);

}

SDL_GL_SwapWindow(window); // swap buffers
}


void StateBattle::handleSDLEvent(SDL_Event const &sdlEvent, Game &context)
{
// Add additional input checks for any other actions carried out in this state
std::cout << "Event handling in main menu state." << std::endl;
if (sdlEvent.type == SDL_KEYDOWN)
{
    //std::cout << "Scancode: " << sdlEvent.key.keysym.scancode ;
    //std::cout << ", Name: " << SDL_GetKeyName( sdlEvent.key.keysym.sym ) << std::endl;
    switch( sdlEvent.key.keysym.sym )
    {
        case SDLK_RETURN:
            context.setState(context.getPlayState());
            break;
        case SDLK_ESCAPE:
            // Create a SDL quit event and push into the event queue
            SDL_Event quitEvent;
            quitEvent.type = SDL_QUIT;
            SDL_PushEvent(&quitEvent);
        default:
            break;
    }
}
}

StateBattle.h 状态战

#ifndef STATE_BATTLE
#define STATE_BATTLE

#include "GameState.h"
#include "Label.h"
#include "StatePlay.h"

class StateBattle : public GameState, public StatePlay
{
public:
StateBattle(void);
~StateBattle(void);
void init(Game &context);
void draw(SDL_Window * window);
void handleSDLEvent(SDL_Event const &sdlEvent, Game &context);
void enter();
void exit();
bool fighting;
};

#endif

I've included all the .cpp and .h files involved, hopefully this is enough. 我已经包含了所有涉及的.cpp和.h文件,希望这足够了。 If not i can upload more. 如果没有,我可以上传更多。 Thanks again 再次感谢

You are missing a = , you should write 您缺少= ,您应该写

if(enemyNo == 1)

instead of 代替

if(enemyNo = 1)

But for the next time, please provide a smaller example (as already suggested) with the exact error message. 但是对于下一次,请提供一个较小的示例(如已经建议的),并提供确切的错误消息。

You should declare the dstor in StatePlay virtual, because it acts as a base class for the StateBattle class. 您应该在StatePlay虚拟环境中声明dstor,因为它充当StateBattle类的基类。 And in the StateBattle implementation file your are initializing enemyNo to 1 instead of comparing it to 1: 在StateBattle实施文件中,您正在将敌人编号初始化为1,而不是将其与1进行比较:

    //Enemy
    if(enemyNo == 1) // <-- missing == 

Inside your states you should only hold state variables: variables that are bound to only this specific state. 在状态内部,您应该只保存状态变量:仅绑定到此特定状态的变量。 Enemies could be a state variable if you have just one game state and all other states are complelty independent (ie menu state, setting state...). 如果您只有一个游戏状态而所有其他状态都是完全独立的(例如,菜单状态,设置状态...),则敌人可能是状态变量。 But your states kind of having cross dependencies. 但是您的州有点交叉依赖。

To solve this problem you should extract first everything that doesn't belong to one specific state into another class. 要解决此问题,您应该首先将不属于一个特定状态的所有内容提取到另一个类中。 Ie You could have a 'World' class, which manages the list of enemies, terrain, ... Or a class for a List of your Entities. 也就是说,您可以拥有一个“世界”类,该类可以管理敌人,地形等等的列表,或者您的实体列表的类。 It's a design decision you have to take yourself. 这是您必须自己做的设计决定。

However, your StatePlay shouldn't handle the enemies - and get it inherited by the StateBattle. 但是,您的StatePlay不应处理敌人-由StateBattle继承。 StateBattle overrides the init(Game &context) function from StatePlay - so it get's never called if you don't call it yourself. StateBattle覆盖了StatePlay中的init(Game&context)函数-因此,如果您自己不调用它,则永远不会调用它。 The enemyNo in StateBattle is never initalized this way (in fact it is, but just because of another mistake)! StateBattle中的敌人号从未以这种方式被初始化(实际上是这样,只是因为另一个错误)! You could write: 您可以这样写:

void StateBattle::init(Game &context)
{
  StatePlay::init(context);
  fighting = false;   
}

to do so. 这样做。 But like I pointed out, there are some things in your class design, that makes handling these things hard and redundant. 但是,正如我指出的那样,您的类设计中有些事情使处理这些事情变得困难而多余。

Also you are not checking the enemyNo - you're setting it. 另外,您没有检查敌人编号-您正在设置它。 = is the assignment Operator - you want to use the compare Operator == So better use: =是赋值运算符-您要使用compare运算符==所以更好地使用:

if(enemyNo == 1)

instead of 代替

if(enemyNo = 1)

Otherwise it will set your variable enemyNo to 1 instead of compare it against 1. 否则会将您的变量敌人编号设置为1,而不是与1进行比较。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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