• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
GrimV5

cleaning up a state

13 posts in this topic

that's pretty cool. I actually have a question about states.  I've read that states should have a clean up method of some sort that should be called when the game is closed or the currently running state is changed to a new state.  My question what exactly is supposed to happen in this clean up method? Its not like i can delete the variables or objects in a state , otherwise when i try to run the code I'll get a debug assertion error.

0

Share this post


Link to post
Share on other sites

I'm a little rusty on the whole patterns thing, but I think it depends entirely on what you're using it for. The question is a little broad.  But, why can't you clean up resource demanding objects?  They can always be reloaded/recreated on initialization.  If you have a very elaborate menu/configuration state which uses lots of graphics, animations, music and so on, it'd be wasteful to leave all that taking up resources while your game is executing.

0

Share this post


Link to post
Share on other sites

It seems the best I would be able to do is set them all to null. Because when I try to use delete on anything it would give me a debug assertion error when I run the program. Plus I would assume that the garbage collector would handle it after the state is popped off the vector. 

Edited by GrimV5
0

Share this post


Link to post
Share on other sites

What happens during the activation of a state? Is anything allocated into the memory? Are entities created with "new"? Are the textures of those entities' sprites loaded? Are sound effects or music loaded? As a general rule, whatever you allocate during the activation of a state should be deallocated during its deactivation.

0

Share this post


Link to post
Share on other sites

What's the context for this question? You're not really giving us much to go on.

 

 

 


Because when I try to use delete on anything it would give me a debug assertion error when I run the program.

 

Huh? Did you allocate something with new? If so, then you need to delete it when you're done using it. If you're getting a "debug assertion", you're probably deleting something you never allocated, or your heap is corrupted.

 

 

 


Plus I would assume that the garbage collector would handle it after the state is popped off the vector. 

 

C++ doesn't have a garbage collector, what are you talking about?

Edited by phil_t
2

Share this post


Link to post
Share on other sites


I've read that states should have a clean up method of some sort that should be called when the game is closed or the currently running state is changed to a new state.  My question what exactly is supposed to happen in this clean up method?

A state is a concept.  Exactly what it means is entirely up to you.

 

A state might be a single number or enumeration.  Your code may have something like "int state = 0; ... state = 1; ... state = 2..." or more likely it would be named: "int state = ThingState_PreInit; ... state = ThingState_Initialized; ... state = ThingState_Active".

 

A state might be an index to a data table. "StateEntry* currentState = AllPossibleStates[0]; ... currentState = currentState->Next.AfterSuccess;"

 

A state might be an object on a stack. A state might be an item in a queue. A state might be some other object or structure.

 


It seems the best I would be able to do is set them all to null. Because when I try to use delete on anything it would give me a debug assertion error when I run the program.

 

That has nothing to do with states and everything to do with memory management. In order to use the C++ language effectively you must understand memory management and object lifetimes.  If you create or allocate something it is your responsibility as the developer to ensure it is properly cleaned up. This is true on all languages; even those with automatic garbage collection require you to properly manage object lifetimes.

 

If you created objects and simply point them to null you are probably creating memory and resource leaks. Sometimes you can get away with those bugs for a short time, but they are bugs that can result in very nasty problems. 

2

Share this post


Link to post
Share on other sites

that's pretty cool. I actually have a question about states.  I've read that states should have a clean up method of some sort that should be called when the game is closed or the currently running state is changed to a new state.  My question what exactly is supposed to happen in this clean up method? Its not like i can delete the variables or objects in a state , otherwise when i try to run the code I'll get a debug assertion error.

 

In my states, I have Activated() and Deactivated(), and the gamestates also have constructors and destructors (destructors are mostly unused, since most dynamic memory uses smart pointers).

Activation is when gamestates get switched. Since my gamestates are hierarchical, the entire parent-child hierarchy is activated. 

 

Not every state needs to do something when activated or deactivated. If you're managing some heavy resources, you might want to allocate and free the resources there, but in general, I wouldn't do that unless you find (through actual use, not premature optimization) that you actually need the memory.

 

One non-memory related use for activation is this:

Imagine you had one or more timers associated with a state. The states get switched, the pause menu gets displayed, and the old state with the timers is no longer active. Depending on what those timers are doing, some of them you'll want to pause() and resume() when the state gets deactivated() and activated(), and others you'll want to continue to let running even when the state isn't active.

 

Any directly time-based changes to a state you can manipulate through the Update(deltaTime) function calls (which in my code doesn't get called when the state is deactivated), but if you want to do something like "Do X every five minutes", or "Y was triggered, so in 30 seconds trigger function Z one time", I'd use a timer for that.

Edited by Servant of the Lord
0

Share this post


Link to post
Share on other sites
This sounds so familiar I can’t help but wonder if this stems from something on my site or something I posted some time ago.

Breaking your game into states is a good idea.
If you have managed your memory properly, when a state starts and ends, the amount of memory allocated should be the same.
This is a good way to detect leaks and pinpoint where they are. If you detect a leak when you change from the main menu to the game-start screen, you know you have a leak in your main menu state class and it should be easy to track down.


But there is nothing really tricky about how to implement this.
All classes have a constructor and destructor, but I recommend requiring them to implement a Create() and Destroy() instead, because some resources require a pointer to a higher-level object, such as CGame, and you won’t necessarily have the option to release those resources inside a destructor (which can’t accept parameters). You could implement only Destroy() and use the constructor to replace Create(), but it’s just cleaner to let the constructor and destructor be its own pair and let Create() and Destroy() be their own pair.


Otherwise there is nothing about it.
If the state has released everything it has allocated, the state manager can check how much memory has been allocated before and after a state and if there are any discrepancies it should print a warning.


L. Spiro Edited by L. Spiro
2

Share this post


Link to post
Share on other sites

sorry for taking so long to reply here is one of states I made:

 

#include "MainMenuState.h"
#include "State.h"
#include "SEngine.h"
#include <SFML/Graphics.hpp>
 
MainMenuState MainMenuState::mainMenuStart; // static MainMenuState variable
 
/* Load() method for MainMenuState, initializes all variables in MainMenuState.
 */
void MainMenuState::Load(){
backGround = sf::RectangleShape(sf::Vector2f(640.0f,480.0f));
menu = backGround.getLocalBounds();
backGround.setOrigin(menu.left,menu.top);
button1 = sf::RectangleShape(sf::Vector2f(100.0f,50.0f));
button2 = sf::RectangleShape(sf::Vector2f(100.0f,50.0f));
button1.setPosition(menu.left + 270.0f, menu.top + 300.0f);
button2.setPosition(menu.left + 270.0f, menu.top + 390.0f);
backGround.setFillColor(sf::Color::Blue);
button1.setFillColor(sf::Color::Red);
button2.setFillColor(sf::Color::Red);
};//Load()
 
/* Handling method for MainMenuState, handles events that may occur in the
   MainMenuState. The only parameter it takes is a reference to the state
   machine, SEngine.*/
void MainMenuState::Handling(SEngine* gameEng){
 
};//Handling()
 
/* Paint method for MainMenuState, draws the components of this state onto the screen.
   The only parameter it takes is a reference to the state machine, SEngine.*/
void MainMenuState::Paint(SEngine* gameEng){
gameEng->getWindow()->clear();
gameEng->getWindow()->draw(backGround);
gameEng->getWindow()->draw(button1);
gameEng->getWindow()->draw(button2);
gameEng->getWindow()->display();
};//Paint()
 
/* Update method for MainMenuState, updates certain values or components that may
   have been affected by events in Handling method. The only parameter it takes
   is a reference to the state machine, SEngine.*/
void MainMenuState::Update(SEngine* gameEng){
 
};//Update()
 
void MainMenuState::TidyUp(){
};//TidyUp()
 
void MainMenuState::Halt(){
};//Halt()
 
void MainMenuState::Continue(){
};//Continue()
 
button1 and button2 are both RectangleShape objects from the SFML library.  I tried putting the following lines in TidyUp():
delete button1;
delete button2;
 
The compiler doesn't have an issue with this but if I try to run the program then I get the debug assertion error.
0

Share this post


Link to post
Share on other sites

 

 

C++ doesn't have a garbage collector, what are you talking about?

 

This only proves to me that my C++ teacher wasn't that great, he never clarified certain things so I was left to assume.

-2

Share this post


Link to post
Share on other sites

button1 and button2 are both RectangleShape objects from the SFML library. I tried putting the following lines in TidyUp():
delete button1;
delete button2;


[tt]button1[/tt] and [tt]button2[/tt] are [tt]RectangleShape[/tt] objects from the SFML library, but they weren't allocated on the heap with [tt]new[/tt]. Therefore, no delete is necessary:

int main() {
    sf::RectangleShape a = sf::RectangleShape(sf::Vector2f(640.0f,480.0f));
    sf::RectangleShape* b = new sf::RectangleShape(sf::Vector2f(640.0f,480.0f));

    // Do stuff with a, b

    delete b;
} // a is destroyed automatically

0

Share this post


Link to post
Share on other sites

 

 

It's the student's job to ask questions if they don't understand. 
It's the teacher's job to answer questions - that's what they are there for (otherwise, you might as well just read a book).
The teacher can't answer questions that the students don't ask. wink.png

 

This is not the issue and I don't assume he's ignorant. It's just that english is not his first language and while he can speak it pretty well, he still has an issue understanding what other people ask or say to him.  I've physically walked up to the board to write (even draw) out my problem and barely half the time does he understand. And while his TA CAN speak english, he is near impossible to get a hold of. So I resort to an C Reference handbook and C++ forums to get my answers.

-1

Share this post


Link to post
Share on other sites

As fastcall22 mentioned, only delete what you new - and if you're a beginner, don't new or delete at all. And if you're a professional, and using modern C++ techniques, you'd use smart pointers 95% of the time anyway so you'd still mostly ignore new and delete.
 

 

C++ doesn't have a garbage collector, what are you talking about?

This only proves to me that my C++ teacher wasn't that great, he never clarified certain things so I was left to assume.

 

It's the student's job to ask questions if they don't understand. 
It's the teacher's job to answer questions - that's what they are there for (otherwise, you might as well just read a book).
The teacher can't answer questions that the students don't ask. wink.png
 
Plus, C++ does automatically collect some memory. It doesn't have a "garbage collector", but it still frees memory automatically in certain circumstances. Maybe your teacher was trying to explain how C++ memory was collected, and having heard the phrase "garbage collector" sometime in the past, you might've automatically assumed that the teacher was talking about garbage collection?
 
I'm guessing this is the case, because this is exactly the problem you are having with your code: You think certain memory isn't getting freed that C++ is already freeing for you, and you're trying the manually free memory that has already been freed (or that will automatically be freed later). smile.png
 
As popular as it is to do so, don't assume your teacher is ignorant. Just ask questions if you don't understand. If, after asking questions, something still doesn't make sense, then ask on these forums and we can clarify.
 
Here's how basic C++ variables work: (Don't roll your eyes, this is important to understand!)
int x = 0;
That line of code creates an integer named 'x', that is initialized to '0'. It will automatically be freed when the execution of the code reaches the end of its scope.
 
Example:
void func()
{
     int a = 20;
 
     if(true)
     {
          int b = 70;
          
     } //The variable 'b' gets freed after this point.
    
     int c = 0;
     
} //The variables 'a' and 'c' get freed after this point.
 
If you do this:
void func()
{
     int a = 20;
 
     delete &a; //Programmer  manually frees 'a' (not good).
     
} //Compiler automatically frees 'a'. But since was *already* freed, the program will either
  //crash (if you're lucky) or do unexpected crazy stuff that's really hard to track down and debug.
For every variable in your code, either you're managing its memory, or the compiler is. But not both. Every variable should have an owner: Who owns it? The function? The class? Or are you manually managing it?
 
Now let's look at the lifetime of variables in structs: (classes behave the same way)
struct MyStruct
{
     int x;
};
'x' is owned by 'MyStruct'. When 'MyStruct' has its memory freed, 'x' will also be freed.
 
Observe:
void func()
{
     MyStruct myStruct;
     myStruct.x = 20;
     
} //'myStruct' is freed here. Because 'myStruct' is freed, 'myStruct.x' is also freed at the same time.
 
Now classes also have constructors and destructors, which is important to use. All your 'Load()' code should go in the class's constructor. That's what it's for.
All your 'TidyUp()' code should go in the class's destructor. That's why destructors exist.
//This is a constructor. It's a function called when a class gets created.
MainMenuState::MainMenuState()
{
    
}
 
//This is a destructor. It's a function called when a class gets destroyed.
MainMenuState::~MainMenuState()
{
    
}
Unless you're manually doing something that needs to be manually undone, you don't really need to use a destructor in this MainMenuState class.

 

Well, I don't actually use a constructor for my states anyway, here is my initialstate header:

 

#ifndef InitializeState_h
#define InitializeState_h
#include "State.h"
#include "SFML/Graphics.hpp"


class InitializeState : public State{
public:

void Load();
void Handling(SEngine* gameEng);
void Paint(SEngine* gameEng);
void Update(SEngine* gameEng);
void TidyUp();
void Halt();
void Continue();
static InitializeState* Initialize(){
return &gameStart;
}


protected:
InitializeState() {}

private:
static InitializeState gameStart;
int ready;
sf::RectangleShape shape;
};


#endif
 
Here is my main that calls the Initialize function:
 
#include "SEngine.h"
#include "InitializeState.h"


using namespace std;

int main(){
  char word[] = {'T','e','s','t','i','n','g'}; //ignore, just for testing purposes
  SEngine engine;
  engine.Load(word);
  engine.changeState(InitializeState::Initialize());

  while(engine.isRunning()){
   while(engine.getWindow()->isOpen()){
    engine.Handling();
    engine.Update();
    engine.Paint();
   }
  }

  return 0;
};

And here is my state engine class:

#include "SEngine.h"
#include <SFML/Graphics.hpp>
#include "State.h"


void SEngine::Load(const char* title, int xsize, int ysize){
  running = true;
  width = xsize;
  height = ysize;
  window.create(sf::VideoMode(width,height), "Game Engine");
};

void SEngine::changeState(State* state){
  if(!states.empty()){
   states.back()->TidyUp();
   states.pop_back();
  }

  states.push_back(state);
  states.back()->Load();
};

void SEngine::Handling(){
  states.back()->Handling(this);
};

void SEngine::Update(){
states.back()->Update(this);
};

void SEngine::Paint(){
  states.back()->Paint(this);
};

bool SEngine::isRunning(){
  return running;
};

void SEngine::endGame(){
  running = false;
};

void SEngine::PushIt(State* gstate){
  if(!states.empty()){
   states.back()->Halt();
  }

  states.push_back(gstate);
  states.back()->Load();
};

void SEngine::PopIt(){
  if(!states.empty()){
   states.back()->TidyUp();
   states.pop_back();
  }

  if(!states.empty()){
   states.back()->Continue();
  }
};

void SEngine::TidyUp(){

  while(!states.empty()){
   states.back()->TidyUp();
   states.pop_back();
}


};
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0