Few problems :)

Anything related in any way to game development as a whole is welcome here. Tell us about your game, grace us with your project, show us your new YouTube video, etc.

Moderator: PC Supremacists

User avatar
Tetriarch
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 36
Joined: Thu May 03, 2012 3:55 pm
Current Project: Brotherhood of the Raven
Favorite Gaming Platforms: PC
Programming Language of Choice: C++
Location: Czech Republic

Few problems :)

Post by Tetriarch »

Hi folks, I have a question, HOW whould you solve game states(intro, game, credits,etc) using C,C++/SDL?

Well I figured out the way using switch.
I mean.
loop()
{
switch(state)
{
case MAINMENU:
{
//do something
}
// another cases
}
}

But if I use this for all functions (loop(),events(),draw()etc) it is really huge and I dont see it right.
All classes for states are using static member in classes.

Any idea how to do that better?

Another problem :) I am looking for some game dev beginner :) and teacher if possible. I am looking for this kind of guys because I am pretty alone in this. I haven't anyone in reallife to disccuss with.

Sorry for my bad english :)

- Tetriarch
What if I am 1 and my shadow is 0? Does it still mean that we are 2?

Fractal art - DA Gallery
User avatar
bbguimaraes
Chaos Rift Junior
Chaos Rift Junior
Posts: 294
Joined: Wed Apr 11, 2012 4:34 pm
Programming Language of Choice: c++
Location: Brazil
Contact:

Re: Few problems :)

Post by bbguimaraes »

There are some alternatives. The first thing I suggest is using enums, or at least int constants (which you may already be using). Then, you can (should) use functions:

Code: Select all

switch(state) {
    case Game::MAIN_MENU:
        mainMenu();
        break;

    case Game::SPLASH_SCREEN:
        splashScreen();
        break;

    // ...
}
In this case, I personaly prefer if's instead of a swtich. There are some sophisticated alternatives, like (an array of) function pointers, the state pattern, etc., but switch is the best for most of the cases.
User avatar
Tetriarch
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 36
Joined: Thu May 03, 2012 3:55 pm
Current Project: Brotherhood of the Raven
Favorite Gaming Platforms: PC
Programming Language of Choice: C++
Location: Czech Republic

Re: Few problems :)

Post by Tetriarch »

That code you just posted is exactly the thing I am already using in Brotherhood of the Raven ... my own project. and in my opinion it isn't so good but still... thanks for post.
What if I am 1 and my shadow is 0? Does it still mean that we are 2?

Fractal art - DA Gallery
User avatar
bbguimaraes
Chaos Rift Junior
Chaos Rift Junior
Posts: 294
Joined: Wed Apr 11, 2012 4:34 pm
Programming Language of Choice: c++
Location: Brazil
Contact:

Re: Few problems :)

Post by bbguimaraes »

As I said, this is the most straightforward solution. If you want something more modularized, maintanable and dynamic, the state pattern is the direction I'd follow. You just have to weight the pros and (many) cons. By the way: http://en.wikipedia.org/wiki/Design_Patterns.
User avatar
Tetriarch
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 36
Joined: Thu May 03, 2012 3:55 pm
Current Project: Brotherhood of the Raven
Favorite Gaming Platforms: PC
Programming Language of Choice: C++
Location: Czech Republic

Re: Few problems :)

Post by Tetriarch »

So you think that as fast approach is that good?
What if I am 1 and my shadow is 0? Does it still mean that we are 2?

Fractal art - DA Gallery
DatamancerStudios
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 30
Joined: Sun Sep 11, 2011 4:27 am

Re: Few problems :)

Post by DatamancerStudios »

I personally prefer to use a state class, that way it's more manageable.
The Engine class holds a pointer to the current state, and I just inherit from State to make the states I need.
For example, I might have a state called Menu, and a state called Game.
Each state has an Init(), HandleInput(), Think(), and Draw() function.
So, I just have the Engine call the current states functions.

I do this so it's easy to manage how drastically different certain parts of the game could be,
without getting a tangled web of code.

It makes it very easy to program mini games and stuff that's really different from what normal gameplay is like.

After I got the hang of that for a while, I started making it a queue, where you can pop the Game state off to get back into the Menu etc.
User avatar
Tetriarch
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 36
Joined: Thu May 03, 2012 3:55 pm
Current Project: Brotherhood of the Raven
Favorite Gaming Platforms: PC
Programming Language of Choice: C++
Location: Czech Republic

Re: Few problems :)

Post by Tetriarch »

Okay, and could you show some piece of code? PLEASE? ok.. and could you imagine to work this idea for example in RPG? or RTS?

and btw... it looks really awesome!
What if I am 1 and my shadow is 0? Does it still mean that we are 2?

Fractal art - DA Gallery
User avatar
Nokurn
Chaos Rift Regular
Chaos Rift Regular
Posts: 164
Joined: Mon Jan 31, 2011 12:08 pm
Favorite Gaming Platforms: PC, SNES, Dreamcast, PS2, N64
Programming Language of Choice: Proper C++
Location: Southern California
Contact:

Re: Few problems :)

Post by Nokurn »

I've spent a lot of time thinking about how to do state management in a flexible, generalized way. My current state system is (obviously) the best solution I've come up with so far, and I am fairly pleased with it.

Each State is separated out into its own class (MainMenuState, PlayState, PauseMenuState, etc.), which inherits from the State virtual class. The State virtual class defines a common interface for a State--handling events, updating, and rendering. A State also has an associated StateType, which can be one of: Primary, Overlay, and Popup. More on these later.

Code: Select all

enum StateType {
    kStateTypePrimary, // Blocks everything
    kStateTypeOverlay, // Blocks events and updates
    kStateTypePopup // Blocks nothing
};

class State {
public:
    State(StateType type) : type_(type) {}
    virtual ~State() {}

    virtual void handleEvent(ALLEGRO_EVENT& /*ev*/) {}
    virtual void update(float /*ft*/) {}
    virtual void render() {}

    StateType type() const { return type_; }

private:
    StateType type_;
};
States can stand on their own, or they can be inserted into a StateManager. The StateManager maintains a two-dimensional collection of States, arranged into Layers. The first dimension of the StateManager acts like a stack: only the top Layer can be accessed, and it can only be changed via push or pop. Layers act like weakly-ordered lists, but they cannot be mutated directly. There are two operations defined for a Layer: insert and remove. The insert operation checks the State's StateType. If the StateType is Primary, the insert ensures that the first State in the Layer is non-Primary and acts as a prepend; otherwise, it acts as an append.

The StateManager defines the same methods as declared in the State interface (handle event, update, and render). These methods call the corresponding method on each State in the topmost Layer. The handle event and update methods start at the first Primary or Overlay State (or simply the first State if the Layer doesn't have a Primary or Overlay) and continue to the end. The render method starts at the first State.

Code: Select all

class StateManager {
public:
    void push();
    void push(State* state);
    void pop();

    void insert(State* state);
    void remove(State* state);

    void handleEvent(ALLEGRO_EVENT& ev);
    void update(float ft);
    void render();

private:
    std::stack<std::vector<std::unique_ptr<State>>> layers_;
};
Be careful in how the StateManager is implemented; if you mutate the Layer in any way during a State method call (including popping it), you may invalidate the current State iterator and cause shit to go crazy. I avoid this by also maintaining an ordered list of Jobs; the push, pop, insert, and remove methods are dummies that simply add a Job for the corresponding operation. The Jobs are then carried out by another method, process, that is called at the beginning of each game tick, before handleEvent, update, and render.

The benefit of using a State system like this is that you can use it for many things, including (to some degree) window management--you could have an InventoryState, a JournalState, and an AbilitiesState all open at once as Popups on top of a Primary PlayState. Then if the player pauses, you could insert a PauseMenuState as an Overlay that blocks events from the lower States until it is dismissed, while still rendering them.

I haven't found it to be much slower than conventional enum-based State "management" (the overhead is mostly noticeable during State changes, but it's still negligible), but I do think it's significantly more powerful and usable.

If anyone has any suggestions for my design, I'd be very interested in hearing them. Hope this helps!
User avatar
Tetriarch
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 36
Joined: Thu May 03, 2012 3:55 pm
Current Project: Brotherhood of the Raven
Favorite Gaming Platforms: PC
Programming Language of Choice: C++
Location: Czech Republic

Re: Few problems :)

Post by Tetriarch »

Wow, this looks good :) Well because of my bad english it will take a time to read and understand properly, but I will get it in my head :) Thank you very much.

Now :D I have to find someone who's beginner and someone who could be teacher :)
What if I am 1 and my shadow is 0? Does it still mean that we are 2?

Fractal art - DA Gallery
User avatar
Tetriarch
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 36
Joined: Thu May 03, 2012 3:55 pm
Current Project: Brotherhood of the Raven
Favorite Gaming Platforms: PC
Programming Language of Choice: C++
Location: Czech Republic

Re: Few problems :)

Post by Tetriarch »

Found another problem. When I am drawing some moving SDL_Surface it is tearing.
Well part of that surface stays and another part goes on.

I use SDL_image to load pictures. SDL_Init(SDL_INIT_EVERYTHING); SDL_SetVideoMode(w,h,bpp,SDL_HWSURFACE|SDL_DOUBLEBUF);

and in draw fuction i use SDL_Flip(screen); why is that happening?
What if I am 1 and my shadow is 0? Does it still mean that we are 2?

Fractal art - DA Gallery
User avatar
Nokurn
Chaos Rift Regular
Chaos Rift Regular
Posts: 164
Joined: Mon Jan 31, 2011 12:08 pm
Favorite Gaming Platforms: PC, SNES, Dreamcast, PS2, N64
Programming Language of Choice: Proper C++
Location: Southern California
Contact:

Re: Few problems :)

Post by Nokurn »

Tetriarch wrote:Found another problem. When I am drawing some moving SDL_Surface it is tearing.
Well part of that surface stays and another part goes on.

I use SDL_image to load pictures. SDL_Init(SDL_INIT_EVERYTHING); SDL_SetVideoMode(w,h,bpp,SDL_HWSURFACE|SDL_DOUBLEBUF);

and in draw fuction i use SDL_Flip(screen); why is that happening?
Are you clearing the screen before redrawing? Something like this should do:

Code: Select all

SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0)); // Clear to black
// Draw everything
SDL_Flip(screen);
User avatar
Tetriarch
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 36
Joined: Thu May 03, 2012 3:55 pm
Current Project: Brotherhood of the Raven
Favorite Gaming Platforms: PC
Programming Language of Choice: C++
Location: Czech Republic

Re: Few problems :)

Post by Tetriarch »

Yes I have that.... It is tearing really little but it's still able to be seen.
What if I am 1 and my shadow is 0? Does it still mean that we are 2?

Fractal art - DA Gallery
User avatar
Tetriarch
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 36
Joined: Thu May 03, 2012 3:55 pm
Current Project: Brotherhood of the Raven
Favorite Gaming Platforms: PC
Programming Language of Choice: C++
Location: Czech Republic

Re: Few problems :)

Post by Tetriarch »

Well :) true is, I actually haven't any FPS reduction. And all states are using one event structure in App.h wich is main part of the game. in this part are functions loop() render() events() and other and in these functions I use switch mathod of state management.
What if I am 1 and my shadow is 0? Does it still mean that we are 2?

Fractal art - DA Gallery
User avatar
Tetriarch
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 36
Joined: Thu May 03, 2012 3:55 pm
Current Project: Brotherhood of the Raven
Favorite Gaming Platforms: PC
Programming Language of Choice: C++
Location: Czech Republic

Re: Few problems :)

Post by Tetriarch »

So I finally had enough time to read your post Nokurn. I've tried to understand everything you wrote.

My State "management" will be designed this way.
1st think, I will have to do is writing state with virtual fuctions init() events() loop() draw() clean_up().
Than I will create states for splash, mainmenu, intro, game, outro, credits - all these will iherit functions from parent AppState. Every state will then overload these functions. The only problem I have to solve then is how to implement, quests, inventory, skills, map, etc.. Will see :) but for sure, I don't wanna give up that game.

Well, I didn't understand that "layer" stuff - but I think I can move on without that. ;)

Thank you for help very much. :)
What if I am 1 and my shadow is 0? Does it still mean that we are 2?

Fractal art - DA Gallery
CC Ricers
Chaos Rift Regular
Chaos Rift Regular
Posts: 120
Joined: Sat Jan 24, 2009 1:36 am
Location: Chicago, IL

Re: Few problems :)

Post by CC Ricers »

I went beyond merely using stacks/vectors for game states, for the very reasons you said about wanting to use different kinds of game states. I started using lists where game "screens" can be removed or added to at any position. With this system, it's easier to understand them as layers, or screens to understand the flexibility.

It's possible to have a Background screen that is just that, a background. It does nothing more than draw a background picture where something else can go over it, and on top of it I can load one or more Menu screens, with their own behavior inside their classes.

I can choose to remove menu 1 first, or menu 2 first depending on what I need the game to do. Background stays the same. I can even pull the background underneath the menus clean off and replace it with something different, to give different menus different backgrounds. Or have a Gameplay screen active and put a small background + menu on top to open an inventory. You can also make all the game screens enter and exit with a transition for a bit of visual flash.

The inventory menu does not need to know about everything going on in the gameplay, it would just be passed the player's stats and inventory info. If you have a shield in the inventory you want to equip, click on the shield in the menu, the menu knows what's clicked, it passes it to the Stats, also tell the Player "my inventory changed. Re-check in the next update loop to draw the new equipment". Then you can make some cool results like seeing your player carrying the new shield. If you want to make it a grand RPG experience you can have other menus open at the same time, like a Skill menu and the Quests menu you mentioned.

As you can see this can get complicated fast if you don't keep track of your active screens. Using a list that has no LIFO behavior is more flexible so if you go this route, organize your code well. I would recommend it if you find the stack still too limiting and and more complex interactions in your games. I keep track of the screens by debugging text output showing me what game screens are on at any moment.
Post Reply