Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [SOLVED]class variables reset value after function loop  (Read 1219 times)

0 Members and 1 Guest are viewing this topic.

Mooks

  • Newbie
  • *
  • Posts: 7
    • View Profile
[SOLVED]class variables reset value after function loop
« on: June 26, 2017, 12:01:40 am »
SOLUTION: It seems I was being really rigid in my idea of how to declare and define the objects I was working with. I was declaring and defining the objects generally in the same scope. The solution I found was to declare the objects outside the scope of the function that I wanted to change the objects' value and then make calls to that objects member functions (thus defining them, I think) inside the function in question. I hope that explains it.

What it looks like:
overworldTime() previously looked like this:

 

class gameTime {

void overworldTime() {
        overworldLocations cityA;   //objects are declared //
        overworldLocations cityB;
        cityB.overworldCity({(float)windowSizeX/8, (float)windowSizeY/8}, "My Second City");
        cityA.overworldCity({(float)windowSizeX/3, (float)windowSizeY/3}, "My First City");
        // ..and objects are defined right away //
// do stuff //

}; // end gameTime
 

now is looks like this:


overworldLocations cityA;   //objects are declared outside of gameTime //
overworldLocations cityB;

class gameTime {

void overworldTime() {
       
        cityB.overworldCity({(float)windowSizeX/8, (float)windowSizeY/8}, "My Second City");
        cityA.overworldCity({(float)windowSizeX/3, (float)windowSizeY/3}, "My First City");
        // ..and they are still defined in the same place //

// do stuff //

}; // end gameTime
 

/edit


This is more of a general C++ question I believe, but because I'm using SFML to work on this project I figured I'd ask around for help here before going elsewhere.

I have a set of classes and I'd like for their variables to be shared. Easy enough, however I have a function within one of the classes that is meant to incriment the value of the shared variable. In my logger I note that the incriment occurs once and then reverts to the initial value, and this process just repeats itself.

The goal is to get cityFood which is defined in class overworldLocations to be incrimented in the loop in overworldTime() which is a function of class gameTime.

Here are the two classes ( I'm sure there are errors everywhere, but everthing works aside from this one problem) overworldLocations:

#include "text_function.hpp"
#include <memory>

unsigned int cityPosX{(unsigned int)windowSizeX/3}, cityPosY{(unsigned int)windowSizeY/3};
sf::Font font, cityFont;

class overworldLocations {
       
       

public:
        static int cityFood, cityIndustry, cityPopulation;
        friend class gameTime;
       
int resourceSetter(int a, int b, int c) {

        cityFood = a;
        cityIndustry = b;
        cityPopulation = c;
       
}

int resourceGetter() {

        return cityFood, cityIndustry, cityPopulation;
}

void overworldCity(sf::Vector2f cityPos, std::string cityName) {

        float citySizeX{100}, citySizeY{100};

        sf::RectangleShape cityShape(sf::Vector2f(citySizeX, citySizeY));
        cityShape.setPosition(cityPos);
        window.draw(cityShape);
       
        sf::Vector2f cityPosition{cityShape.getPosition()};

        float x = cityPosition.x;
        float y = cityPosition.y;

        sf::Vector2f cityPosVector{cityPosition.x + 25, cityPosition.y + 80};
        // *foodPointer = cityFood;

       
       
        std::string foodString = std::to_string(cityFood), industryString = std::to_string(cityIndustry), populationString = std::to_string(cityPopulation);

        text_function textObject(cityName, cityFont, cityPosVector, sf::Color::Black, 10);

        text_function cityTextObject1("F", cityFont, {cityPosition.x, cityPosition.y - 15}, sf::Color::Green, 12);
        text_function cityResourceText1(foodString, cityFont, {cityPosition.x + 7, cityPosition.y - 15}, sf::Color::Green, 12);

        text_function cityTextObject2("I", cityFont, {cityPosition.x + 40, cityPosition.y - 15}, sf::Color::Red, 12);
        text_function cityResourceText2(industryString, cityFont, {cityPosition.x + 47, cityPosition.y - 15}, sf::Color::Red, 12);

        text_function cityTextObject3("P", cityFont, {cityPosition.x + 80, cityPosition.y - 15}, sf::Color::Yellow, 12);
        text_function cityResourceText3(populationString, cityFont, {cityPosition.x + 87, cityPosition.y - 15}, sf::Color::Yellow, 12);
       
};
};

 int overworldLocations::cityFood{10}, overworldLocations::cityIndustry{10}, overworldLocations::cityPopulation{10};

 

 and gameTime:
#include "overworldLocations.hpp"
#include "drawable_objects.hpp"

sf::Font overworldFont;
bool timePaused = true;


sf::Clock overworldClock;
sf::Text overworldText, overworldCurrentDay;
float overworldObjectPosX{(float)windowSizeX/windowSizeX}, overworldObjectPosY{(float)windowSizeY - 30};
sf::Vector2f overworldCurrentDayObjectPos{(float)windowSizeX/windowSizeX + 50, (float)windowSizeY - 30};

class gameTime : public overworldLocations {

public:

static int currentDay;

friend class overworldLocations;

void overworldTime(int& reference) {

        sf::Time wholeDay = sf::seconds(1.0f);
        sf::Time timePassed = overworldClock.getElapsedTime();
       
        if(timePassed > wholeDay) {

                std::cout
                        << "OVERWORLD TIME "
                        << timePassed.asSeconds()
                        << std::endl;

                overworldClock.restart();

                if(!timePaused) {

                        if(currentDay >= 7) {
                                currentDay = 0;
                                overworldLocations::cityFood += 1;
                        std::cout
                                << "OL CF is "
                                << overworldLocations::cityFood
                                << std::endl;
                        std::cout
                                << "GT CF is "
                                << cityFood
                                << std::endl;
                        std::cout
                                << "reference to cityFood is "
                                << reference
                                << std::endl;
                        }


                        // std::cout
                        //      << "shared_ptr & is "
                        //      << &sharedfoodPointer
                        //      << std::endl;
                        // std::cout
                        //      << "shared_ptr * is "
                        //      << *sharedfoodPointer
                        //      << std::endl;
                        // std::cout
                        //      << "shared_ptr is "
                        //      << sharedfoodPointer
                        //      << std::endl;

                        }

                         
                        currentDay ++;
                        std::cout
                                << "Day "
                                << currentDay
                                << std::endl;

        }
       
overworldLocations::cityFood += 1;
        std::string currentDayString = std::to_string(currentDay);

        text_function overworldTextObject("Day:", overworldFont, {overworldObjectPosX, overworldObjectPosY}, sf::Color::Red, 24);
        text_function overworldTextCurrentDay(currentDayString, overworldFont, overworldCurrentDayObjectPos, sf::Color::Red, 24);

};


};

int gameTime::currentDay{1};

 

and the main.cpp:
#include <SFML/System.hpp>
#include <SFML/WIndow.hpp>
#include <SFML/Graphics.hpp>
#include "include/window.hpp"
#include <iostream>
#include <thread>
#include <string>
#include "include/eventPoll.hpp"


int main() {

if (!cityFont.loadFromFile("impact.ttf")) {

                std::cout
                        << "error loading font";

                }
if (!overworldFont.loadFromFile("impact.ttf")) {

                std::cout
                        << "error loading font";

                }
if (!font.loadFromFile("impact.ttf")) {

                std::cout
                        << "error loading font";

                }
 
   
        while(true) {

                window.clear(black);

                gameTime gameClock;
                gameClock.overworldTime(overworldLocations::cityFood);

                character();

                drawable_objects();

               

                eventPoll();

                window.display();
               
                if(isClosed == true) {

                        break;
                }
       
        }

        return 0;

} //main()  

 

There is more I can put here if its neccesary but I believe my problem lies within these bits of code.

I can achieve the desired effect by making cityFood global - but alot of information suggests that is bad practice, and theres obviously something fundemental I'm missing so I'd like to learn how to get the results I want without using globals. The last thing I tried was passing by reference, as you can see in the overworldTime() function but I did not notice any change.

Any help would be appreciated, I hope I provided enough information.

EDIT: I forgot to add the code where I make instances of the overworldLocations class. I have those objects in a function called drawable_objects which is called in main :
void drawable_objects() {

        overworldLocations cityA, cityB;
        cityA.resourceSetter(10,10,10);
        cityB.resourceSetter(10,10,10);
    cityB.overworldCity({(float)windowSizeX/8, (float)windowSizeY/8}, "My Second City");
        cityA.overworldCity({(float)windowSizeX/3, (float)windowSizeY/3}, "My First City");

}

 
« Last Edit: June 27, 2017, 12:53:01 am by Mooks »

Arcade

  • Full Member
  • ***
  • Posts: 230
    • View Profile
Re: class variables reset value after function loop
« Reply #1 on: June 26, 2017, 05:21:59 pm »
It seems to me that your edit is pointing out what the problem is. Every loop you call drawable_objects(). drawable_objects() calls cityA.resourceSetter(10,10,10). resourceSetter will set cityFood to 10. You are therefore resetting cityFood to 10 every loop.

If you don't mind me making a few other suggestions:
  • The way you are using static variables isn't really any better than just using globals. Why not just construct those variables in main() or some class and pass them in as a function parameter where needed?
  • Why does gameTime inherit from overworldLocations?
  • You may want to look up the use of commas in C++. I'm not sure what you are expecting this function to return:
int resourceGetter() {

        return cityFood, cityIndustry, cityPopulation;
}

Mooks

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: class variables reset value after function loop
« Reply #2 on: June 27, 2017, 12:22:15 am »
Thanks for your response!

Testing the code without the resourcesSetter() in drawable_objects works! Seems I made a really basic error there. Now that cityFood isnt being reset I can incrimentin the loop. Overnight I made a few edits to the code and (hopefully) eliminated some of the errors you pointed out.

I entirely removed the drawable_objects functions (perhaps just for now) and moved the object declarations and definitions to overworldTime(), so I could test out incrimenting the cityFood of each object respectively.

I'm thinking that in order to get the behaviour I want out of my objects I need to have the objects properly scoped, and as it is putting them inside overworldTime() works great for changing the data inside the loop but the objects are destructed once the scope ends and then reconstructed when it begins again ( I think thats whats happening). Thus I am still essentially having the same issue, although it is clearer now what the problem is. If I could prevent the destructor from occuring OR chose a better place to declare and define my objects I believe I can get the results I want however all the methods I've tested dont seem to work; one way or another at some point the objects are destroyed and recreated and they loose they modified values.

This is what overworldTime() looks like now:

void overworldTime() {
   
        overworldLocations cityA;
        overworldLocations cityB;
        cityB.overworldCity({(float)windowSizeX/8, (float)windowSizeY/8}, "My Second City");
        cityA.overworldCity({(float)windowSizeX/3, (float)windowSizeY/3}, "My First City");
 
    sf::Time wholeDay = sf::seconds(1.0f);
    sf::Time timePassed = overworldClock.getElapsedTime();
   
    if(timePassed > wholeDay) {
        std::cout
                << "OVERWORLD TIME "
                << timePassed.asSeconds()
                << std::endl;

        overworldClock.restart();

        if(!timePaused) {

            if(currentDay >= 7) {
                    currentDay = 0;
                    cityA.cityFood +=1;
                    cityB.cityFood += 5;

             std::cout
                << "CFA is "
                << cityA.cityFood
                << std::endl;
             std::cout
                << "CFB is "
                << cityB.cityFood
                << std::endl;
            }

            currentDay ++;
                std::cout
                    << "Day "
                    << currentDay
                    << std::endl;
        }

    }
       
        std::string currentDayString = std::to_string(currentDay);

        text_function overworldTextObject("Day:", overworldFont, {overworldObjectPosX, overworldObjectPosY}, sf::Color::Red, 24);
        text_function overworldTextCurrentDay(currentDayString, overworldFont, overworldCurrentDayObjectPos, sf::Color::Red, 24);

};
 

As I mentioned, its pretty clear what the problem is but I do not really have ideas for solutions. I've tried declaring and defining the objects in different  places in the code, ultimately that doesnt get the results I want because declaring them outside of the scope of overworldTime() means that overworldTime() cant interact with the member variables.

Here are the full changes I've made to overworldLocations and gameTime they are mostly the same other than changing some of the global variables and chaing overworldTIme to no longer take a reference to overworldLocations::cityFood and some other suggestions you had:

#include "text_function.hpp"

class overworldLocations {

    private:

int cityFood, cityIndustry, cityPopulation;

    public:

void overworldCity(sf::Vector2f v, std::string s);        
friend class gameTime;

};

void overworldLocations::overworldCity(sf::Vector2f cityPos, std::string cityName) {

        float citySizeX{100}, citySizeY{100};
       
        sf::RectangleShape cityShape(sf::Vector2f(citySizeX, citySizeY));
        cityShape.setPosition(cityPos);
        window.draw(cityShape);
       
        sf::Vector2f cityPosition{cityShape.getPosition()};
        float x = cityPosition.x;
        float y = cityPosition.y;
        sf::Vector2f cityPosVector{cityPosition.x + 25, cityPosition.y + 80};

        std::string foodString = std::to_string(this->cityFood), industryString = std::to_string(this->cityIndustry), populationString = std::to_string(this->cityPopulation);

        text_function textObject(cityName, cityFont, cityPosVector, sf::Color::Black, 10);

        text_function cityTextObject1("F", cityFont, {cityPosition.x, cityPosition.y - 15}, sf::Color::Green, 12);
        text_function cityResourceText1(foodString, cityFont, {cityPosition.x + 7, cityPosition.y - 15}, sf::Color::Green, 12);

        text_function cityTextObject2("I", cityFont, {cityPosition.x + 40, cityPosition.y - 15}, sf::Color::Red, 12);
        text_function cityResourceText2(industryString, cityFont, {cityPosition.x + 47, cityPosition.y - 15}, sf::Color::Red, 12);

        text_function cityTextObject3("P", cityFont, {cityPosition.x + 80, cityPosition.y - 15}, sf::Color::Yellow, 12);
        text_function cityResourceText3(populationString, cityFont, {cityPosition.x + 87, cityPosition.y - 15}, sf::Color::Yellow, 12);
       
};
 

#include "overworldLocations.hpp"
#include "drawable_objects.hpp"

class gameTime {

        private:

static int currentDay;

sf::Text overworldText, overworldCurrentDay;
float overworldObjectPosX{(float)windowSizeX/windowSizeX}, overworldObjectPosY{(float)windowSizeY - 30};
sf::Vector2f overworldCurrentDayObjectPos{(float)windowSizeX/windowSizeX + 50, (float)windowSizeY - 30};

        public:

static  bool timePaused;
int gtfoodCount;
friend class overworldLocations;


void overworldTime() {

        overworldLocations cityA;
        overworldLocations cityB;
        cityB.overworldCity({(float)windowSizeX/8, (float)windowSizeY/8}, "My Second City");
        cityA.overworldCity({(float)windowSizeX/3, (float)windowSizeY/3}, "My First City");
 
    sf::Time wholeDay = sf::seconds(1.0f);
    sf::Time timePassed = overworldClock.getElapsedTime();
   
    if(timePassed > wholeDay) {
        std::cout
                << "OVERWORLD TIME "
                << timePassed.asSeconds()
                << std::endl;

        overworldClock.restart();

        if(!timePaused) {

            if(currentDay >= 7) {
                    currentDay = 0;
                    cityA.cityFood +=1;
                cityB.cityFood += 5;

             std::cout
                << "CFA is "
                << cityA.cityFood
                << std::endl;
             std::cout
                << "CFB is "
                << cityB.cityFood
                << std::endl;
            }

            currentDay ++;
                std::cout
                    << "Day "
                    << currentDay
                    << std::endl;
        }

    }
       
        std::string currentDayString = std::to_string(currentDay);

        text_function overworldTextObject("Day:", overworldFont, {overworldObjectPosX, overworldObjectPosY}, sf::Color::Red, 24);
        text_function overworldTextCurrentDay(currentDayString, overworldFont, overworldCurrentDayObjectPos, sf::Color::Red, 24);

};

};

bool gameTime::timePaused = true;
int gameTime::currentDay{1};
 

Your advice is greatly appreciated! I'm sure I'm still doing things wrong all over the place so any corrections you have for my project are definitely taken to heart.

Mooks

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: class variables reset value after function loop
« Reply #3 on: June 27, 2017, 12:40:49 am »
I've figured out a method to get the results I was after! I'll edit the original post.

Thanks again  :)