Game Structure Question

Started by
5 comments, last by Mekuri 11 years ago

I am about to start making an event system for my game.

All the way through this game I've had a hard time determining how to structure things, but this event system will have a huge impact on the game, so I figured it was a good idea to get it "right" from the beginning.

The event system will handle all kinds of random events in my game- In this example, let's assume it controls when the weather will change.

My problem is what class get to do what.

I have my TileWorld class, which currently contains the World Array (2D tile based game), it contains methods that handles mining and building (I have a static WorldBuilder class that assists here, but not relevant atm). It also has a particle engine object that handles all particle generation- which in turn is used to create the weather effects like snow and rain.

Now I also have this EventSystem class, that decides when to change the weather. The TileWorld will have an instance of the EventSystem.

My questions are:

- Should the EventSystem handle everything related to weather, or only change the weather and let the TileWorld class handle the rest?

- Which of the classes should contain the variable(s) related to the weather? (For Instance the weather variable is in the TileWorld, but is changed from the EventSystem)

- If I decide to let the TileWorld hold the variables, and the EventSystem only handles the logic to change events(weather), I will have to give the EventSystem a reference to the TileWorld- I've done this quite a lot in my game, is this good practice, or should I use a different approach?

I hope I've expressed myself clearly enough- Thanks for reading :-)

Check out the game I am making here - http://www.youtube.com/user/NasarethMekuri

Advertisement
I think you should break up the event system to different systems.
This will save a lot of headaches. Headaches should only be caused by bugs.
Joking aside, here is an example how I would structure it using inheritance and interfaces in Java
I guess you can use polymorphism if you decide to mix weather together
Day Class
Night Class
Weather Class
Rain Class - interface
Sunny Class -interface
Snow Class -interface
TileWorldHandler Class - handles loading tiles into the game
Tile Class -interface
Rock Class
Grass Class
Always prevent your class from becoming a god class. The class name should give you a clue and also other programmers what your class is suppose to do. You want the class to be straightforward and intuitive without the programmer looking at the implementation of your code. It should be reusable for your other projects.

Hey there- Thanks for your input smile.png - Sorry for the late reply, got struck by a flu a few days ago.- Better now though smile.png

I am already having a few classes that could be described as "god classes".

he way I do things is probably not the "best" way to do it. My entire game is a "learning by doing" project. I do occasionally go back and change things, but some of my code is just too tied in that it would take tremendous amounts of time to do so- I started this project almost 11 months ago, so there's a lot of work in it already smile.png

When you start playing the game I have a gamestate enumerator that I set to "PlayField. I then have a Playfield class, (my play screen) which is loaded. It then loads the TileWorld class and a player Class. At the same time, my PlayGUI (user interface class) reacts to the gamestate and draws on top. Here I'm thinking the correct way to do things would be to have the Playfield class load the PlayGUI instead. Anyways I'm going a bit off topic.

Day/Night cycles are handled through the TileWorld class. It has a background class that handles everything on the background (cloud movement, sun/moon cycle, background objects) and it at also handles the ingame time. I can then use the timer here to determine whether it is night or day, and handle things accordingly.

The way I currently handle weather is quite simple- I have an enumerator with 3 values- Normal, Rain and Snow. When the value is changed, the UpdateWeather method in my TileWorld class (the class that handles most logic related to a game world) simply acts differently (if, else if, else). The idea was to have the EventSystem class to change it, based on the current season, and some random modifiers that the EventSystem handles.

The size of my world can easly be several million tiles (currently max world size is aprox 31.5 million tiles), so the way I handle tiles are different from what you suggest.

My Tile class contains an enumerator that holds the value of the TileType, and another that holds the value of the BackgroundTileType, the orientation of the tile, and the amount of water in the tile (if any).

Then I have my WorldItemClass that inherrits from the Tileclass. This is basically used for items that are made of more than one tile, and may be usable, like crafting tables, furnaces, etc. I also have a container class that inherrits from it, and a few other types.

The reason I made those tiles inherrit from Tile, is that they require more data. For instance, the chest item, which is a containertype item, is required to have an inventory "inside of it"- This way, I don't need to have all the tiles to be able to have an inventory, which saves loads of memory, and hdd space when saving.

Anyways, just wanted to explain how I do things and my logic (or lack thereof) behind it.

Thanks for your input. I always look for ways to improve my code and learn new things. I really appreciate it. If anyone has some thoughts on the structure I've explained, don't hesitate to share them- Thanks smile.png

Check out the game I am making here - http://www.youtube.com/user/NasarethMekuri

Sounds fine to me. The godclass you said you have should have their functionality isolated into a particular class.

Since you mention XNA. Before I ditched XNA handled Day/Night cycle by create a game component that only job is to calculate things related to the atmosphere.

The update method did the following in this order:

1) Increment the time (stored in julian date format).

2) Calculate the position of the sun and moon (google it, so awesome).

3) Update the sun and moon's directional lights based on their position.

4) Attenuate the moon's light based on two factors: how far the current time is away from lunar noon (another julian date based equation) and the dot product of the sun and moon light direction.

5) Calculate fog factor based on how close the sun is from sunrise (another julian date based equation).

A lot of other things too. Storing the date and time in julian date format turned out to have a lot of really cool side-effects thanks to astonomer's work with the format.

My questions are:

- Should the EventSystem handle everything related to weather, or only change the weather and let the TileWorld class handle the rest?

- Which of the classes should contain the variable(s) related to the weather? (For Instance the weather variable is in the TileWorld, but is changed from the EventSystem)

- If I decide to let the TileWorld hold the variables, and the EventSystem only handles the logic to change events(weather), I will have to give the EventSystem a reference to the TileWorld- I've done this quite a lot in my game, is this good practice, or should I use a different approach?

I hope I've expressed myself clearly enough- Thanks for reading :-)

Why would the EventSystem handle any logic related to the weather or TileWorld? I think you need to rethink what the responsibility of your classes are. When you say you have an EventSystem, I invision a class that only works with "event" logic. The way I think about an event deals with timing logic. An "event" is something that happens at a specific time. I would create some sort of callback mecahnism so that a class can "register" events, and the EventClass would call upon a callback when it is time to trigger the event.

For example:

class EventRegister

{

public:

virtual void OnEvent(time, eventType) = 0;

};

class EventSystem

{

public

void RegisterEvent(EventRegister*, time, eventType);

void Update();

};

The idea is pretty simple. A class that needs an event would derive from EventRegister and implement the OnEvent() function. So, say your weather class needs to have an event that will switch from sun to rain. You would include that logic in the OnEvent() function for a "sun to rain" eventType. You would then register that event to the EventSystem by calling on its RegisterEvent(...) function and providing it with the specific time at which the event should happen and the event type. The EventSystem should be updated periodically. In its Update() function, it would update the time, check to see if any registered EventRegister class have a pending event, and if it is time for that event, it would call upon the OnEvent(...) function.

This would completely leave any logic not related to events out of the EventSystem. You need to modularize your classes so that you can reduce the dependency between them. I don't think it is ideal for TileWorld to have anything related to weather as well.

Also to touch on your last point, the EventSystem should never have references to specific realization of objects. This is why a base class is used to keep things generic as demonstrated above with the EventRegister class.

hy would the EventSystem handle any logic related to the weather or TileWorld? I think you need to rethink what the responsibility of your classes are. When you say you have an EventSystem, I invision a class that only works with "event" logic. The way I think about an event deals with timing logic. An "event" is something that happens at a specific time. I would create some sort of callback mecahnism so that a class can "register" events, and the EventClass would call upon a callback when it is time to trigger the event.

For example:

class EventRegister

{

public:

virtual void OnEvent(time, eventType) = 0;

};

class EventSystem

{

public

void RegisterEvent(EventRegister*, time, eventType);

void Update();

};

The idea is pretty simple. A class that needs an event would derive from EventRegister and implement the OnEvent() function. So, say your weather class needs to have an event that will switch from sun to rain. You would include that logic in the OnEvent() function for a "sun to rain" eventType. You would then register that event to the EventSystem by calling on its RegisterEvent(...) function and providing it with the specific time at which the event should happen and the event type. The EventSystem should be updated periodically. In its Update() function, it would update the time, check to see if any registered EventRegister class have a pending event, and if it is time for that event, it would call upon the OnEvent(...) function.

This would completely leave any logic not related to events out of the EventSystem. You need to modularize your classes so that you can reduce the dependency between them. I don't think it is ideal for TileWorld to have anything related to weather as well.

Also to touch on your last point, the EventSystem should never have references to specific realization of objects. This is why a base class is used to keep things generic as demonstrated above with the EventRegister class.

One of the bigger mistakes I did back when I started, was to have a lot of classes depend on each other. In hindsight I can see why you would avoid that. It is at times like these I tend to get discouraged, since I realize that I still have a lot to learn smile.png - I did end up making parts of my event system, but it's nothing similar to this. I did keep it fairly clean, so that it mostly handles timing and changing of some event related variables.

Thank you for your detailed input, and sorry for not replying sooner ;-)

Check out the game I am making here - http://www.youtube.com/user/NasarethMekuri

This topic is closed to new replies.

Advertisement