• 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
AldenB

How should important data be passed around a program?

11 posts in this topic

Posted (edited)

In my particular case I have a "________App" class which is basically a wrapper for all the logic in the program. This is the class which calls the run(), update(), draw(), etc, functions. I'm also using a StateMachine class which is used to handle the different "states" of the program (e.g. the "main" state or the "pause" state). The update() and draw() methods are really just wrapper functions for the state machine's update() and draw(). It look a little bit like this...

class MyApp
{
private:
    //...
    Graphics gfx;
    StateMachine<MyApp> state_machine;
    //...
public:
    //...
    void update() {state_machine.draw();}
    void draw() {state_machine.draw();}
    //...
}

However, in order for my state_machine to properly update() and draw(), it needs access to some of MyApp's private members, such as gfx. What I'm really looking for here is a way that the StateMachine can modify the members of the MyApp class that owns it. Making the StateMachine a friend class is tempting, although I believe that it's a poor design decision. Can someone give me some advice or point me in a direction where I could read up on this?

 

Here's a look at my actual code:

//Sol::Application is the class I made which implements run() as well as other lower level operations.
class LogicGatesApp : public Sol::Application
{
public:
    using WireGraph = SparseGraph<GraphNode, Wire>;

private:
    StateMachine<LogicGatesApp> m_state_machine;
    //This is the graphical component of the grid that the user will
    //be interacting with
    Grid m_grid;

    //this is used to represent the wire circuitry logic of the program.
    //each cell in the grid corresponds to a node in the wire graph.
    //see the file description at the top for a visual.
    WireGraph m_wire_graph;

public:
    LogicGatesApp();

    void update();
    void draw();

    //...
};

In this case, the StateMachine needs to be able to access and modify Grid and WireGraph. Particularly, in one of the states, it needs to highlight the block in the grid that the mouse is hovering over (hence the need to modify the Graphics object, and access to the Mouse object both found in Sol::Application)

Edited by AldenB
1

Share this post


Link to post
Share on other sites

If gfx is the only instance ever, I'd just make a global pointer called GFX or GRAPHICS. When the app is created, the GFX point is set to &this->gfx. Upon destruction, GFX is set to 0.

-1

Share this post


Link to post
Share on other sites

If gfx is the only instance ever, I'd just make a global pointer called GFX or GRAPHICS. When the app is created, the GFX point is set to &this->gfx. Upon destruction, GFX is set to 0.

At that point we may as well make Graphics a singleton class don't you think--since I was the creator of it.

0

Share this post


Link to post
Share on other sites

@Josh Petrie I would agree with what you said about passing around Graphics; I've done that often before. However, my StateMachine needs access to MyApps private members in order to perform its logical operations as well. My code is not that complicated nor are my requirements for the program, so if you would like to see it I can supply it.

0

Share this post


Link to post
Share on other sites

However, my StateMachine needs access to MyApps private members in order to perform its logical operations as well.
Maybe the state machine should own that data instead?
1

Share this post


Link to post
Share on other sites

 

If gfx is the only instance ever, I'd just make a global pointer called GFX or GRAPHICS. When the app is created, the GFX point is set to &this->gfx. Upon destruction, GFX is set to 0.

At that point we may as well make Graphics a singleton class don't you think--since I was the creator of it.

 

Sure if you want to. Personally I don't find value in singletons though, but to each their own.

0

Share this post


Link to post
Share on other sites

I usually collect the things that states need shared access to into a struct and have the "app" class hold an instance of that struct. When a state is created it gets passed a pointer to the struct, which it stores and thereby has access to the stuff it may need.

This is a moderately hamfisted approach in some ways (it allows all states to access all the shared stuff instead of only what they actually need), but the alternatives are equally manky and I've sort of gravitated more and more to this for the sake of its simplicity. In practice I've never had any trouble with it.

The shared object package tends to easy to work with as long as I keep it conceptually organized (which is not hard to do). At the root level it contains the modular parts like the "graphics" object, then it also includes a utility struct for holding things like a randomizer instance, the game timer, the message dispatcher, etc. Finally it can include a struct containing the persistent game state. For example, in an RPG you may have a map scene where you're running around exploring, and a menu scene where you sort out your inventory and check your stats. The persistent state data can hold the stats and inventory as well as your current location on the map. Both states (and probably others) want access to that information for different reasons.

The end result is something like:

shared->gameData.inventory["bacon"] += 4;

or

shared->util.timer.getDT();

I know a lot of people aren't fans of this approach (Demeter slaps my face once a day.), but honestly after having experimented with a lot of ways of working this issue out this is the one that has presented the least problems to me. Compile times can be an issue if gameData gets complicated (there are ways to deal with this), and sometimes I wonder about passing 'system', 'util', and 'gameData' instead of just 'shared', but that's about the extent of my difficulty with this pattern for now.

 

At that point we may as well make Graphics a singleton class don't you think--since I was the creator of it.

That's a terrible habit to be in, and I'd advise you to steer clear of it.

1

Share this post


Link to post
Share on other sites

Posted (edited)

@Khatharr

 

At that point we may as well make Graphics a singleton class don't you think--since I was the creator of it.

That's a terrible habit to be in, and I'd advise you to steer clear of it.

Good thing it's not a habit then. The only thing that I have used singletons for thus far are the various program State classes (the "main" state or "pause" state; going off my previous example).

Edited by AldenB
0

Share this post


Link to post
Share on other sites
The only thing that I have used singletons for thus far are the various program State classes

I don't think that's really worthwhile either, though I suppose the idea of states that are never discarded could be made to work, I don't typically keep them around when they're not a part of the active stack. Either way there's no reason to impose the single instance rule on them.

I came back to clarify something about the use of the gameData object in my approach. I only use it to hold "things that belong in a save file" and make everything else the responsibility of the individual states. This creates a problem for transient state (such as AI state) in some games, but that's neatly solved by using a state stack. When I load a game it involves deserializing the save file into gameData and then switching from the load state to one of the gameplay states, and the instantiation of said state generates all the transient data based on the contents of gameData.

The idea of the state stack - if you're not familiar - is that the state base class contains a pointer to a state, which is nullptr by default. If the pointer is null then nothing special happens. Otherwise the state logic and drawing delegate to the sub-state indicated there. This means that the map scene of aforementioned RPG can create the menu state as a sub-state rather than switching the primary state machine to it. For each logical frame you can update the parts of the state that you want, skip the parts you don't want, and then delegate to the sub-state's logic. This allows you to painlessly retain the transient data of the map state, including AI state, physics state, etc.

Likewise for drawing, you can draw the primary state normally and then let the sub-state draw "on top" of it, easily allowing for effects like transparent menu backgrounds.

1

Share this post


Link to post
Share on other sites

Posted (edited)

The idea of the state stack - if you're not familiar - is that the state base class contains a pointer to a state, which is nullptr by default. If the pointer is null then nothing special happens. Otherwise the state logic and drawing delegate to the sub-state indicated there. 

I'm familiar with the state stack. However, I'm not using it for my StateMachine in this program. Although this state stack is a little different then what I'm used to. Are you saying that a State would look something like this?

template <typename T>
class State
{
private:
    State<T>* sub_state;

public:
    State() : sub_state{nullptr} {}
    State(State<T>* sub) : sub_state{sub} {}

    void update()=0;
    //...
}
Edited by AldenB
0

Share this post


Link to post
Share on other sites

Just a linked list, really. (And please use std::unique_ptr.) The simplest form would be to only process the state at the "tail" of the list, but the structure - as mentioned - allows for elective processing/drawing of the enclosing states.

I'm not sure why you'd have a constructor that takes an existing state object and assigns it to the sub-state.

Why is your state class templated?

1

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