Horscht

How to design world, player, obstacles etc classes so they can communicate, which class does what?

Recommended Posts

2 few years have passed since I last tried to make my own game and like always I had to give up because I encountered an unsolvable problem.

And here I go again, hitting the same brickwall with no solution in sight.

My question is: How exactly do I design all my classes so that coupling is minimal when they need to talk to one another somehow.

Let's look at one prime example:

The player exists inside a "world", an environment, where other entities also reside, enemies, obstacles, chests, whatever.

Now the question is, who is responsible for moving the player? The player class itself in something like Player::Update()?

But then how does it know if it hit an obstacle or walks on an ice-tile or got pushed back by a boulder that hit him? For that it would somehow need to talk to the world class, or the boulder class would need to talk to the player and tell it "hey I hit you please move back 3 tiles"? Last time I tried to create a game I had huuuuuge "pass down" chains where class D was instantiated inside C but class D needed class F so I also needed to pass an instance of that into C, which didn't need it itself and since it was created inside class B, class B also needed that instance of class F. So I passed that instance along like 10 levels deep in each constructor... Not confusing at all, right? ;)

Or maybe should the "world"/level class somehow coordinate everything, move everything, since it knows where everything is, but then how does it know the objects movement logic?

How does separation of concerns fall into this, since optimally, every class should only have 1 responsibility. So what should each one do?

I don't even know how to describe it properly, hopefully you can understand what I mean.

Can someone give me a graph of how everything should be "connected"? Which class should "own"/instantiate what, should the player be instantiated by/inside the world class, or from outside and then passed in? But then in what part of the code should he get instantiated, the main loop?

I tried looking for open source projects so I can see how they did it but all of them are wayyyyy too big and I don't even know in which of the 50000 files I need to start looking.

Does anyone maybe know a very simple open source game with a similar structure that I can study? (Platformer, or something like zelda, something with a world/obstalces/player etc).

Share this post


Link to post
Share on other sites

I read only the first 5 line, but I think to have a possible solution, I'll post before finish reading the rest xD

So I am a begginner and never done this, but from what I think to have understood, to do what you want to do it is needed Composition so you are not constrained by problem that can arise with inheritance.

This video below shows how, I yet have to finish watching it and probably will need to go through it multiple times before I can do that, but I think it has the answers we need. 

Another interesting video could be this, from one of the developers of Caves of Cud, he explains how the inheritance system didn't worked at all for a roguelike and how he solved with components. 

 

Share this post


Link to post
Share on other sites

First: don't "design all [your] classes" at once. Pick individual problems, fix them, repeat until you're done. It's less overwhelming that way.

"But then how does it know if it hit an obstacle or walks on an ice-tile or got pushed back by a boulder that hit him?" - Depends on your game. There's no "one-size-fits-all" for character movement. You could have the player set a velocity value, and the world could handle all the movement. You could have the player ask the world, "can I move like this?" and get back a yes/no answer. You could have the player ask the world, "what happens if I try moving in this direction" and get back vector answering where the player actually ended up. Either way, let the world track where everything is, and adjudicate how the movement works.

"How does separation of concerns fall into this, since optimally, every class should only have 1 responsibility" - Don't get obsessed with 'optimal'. Make the object do whatever you need it to. You can clean it up later. And don't try and pre-plan this all in advance in the abstract sense. When you have 2 explicit responsibilities to talk about, then you can consider how to separate them.

"Can someone give me a graph of how everything should be "connected"?" - No, because there's no One True Way to structure a game. You just have to keep at it. You might get further by showing us a graph of what you have already, but unless there is a concrete problem with it, you need to not get 'analysis paralysis' over it. Just keep working.

Share this post


Link to post
Share on other sites

Without getting into too much detail, your game should have a game loop that handles input, logic, and drawing. When you have a class for player, in your input function you would update the player's position based on key strokes. (if keyboard.up()) { player.setPositionY(-5); }

When dealing with collision, every object should have some way of checking. When you create your player class or any object you can set up bounding box collision as an example, so you would run this check when moving the player. (if player.checkCollision(object1) == true) { player.setPosition(player.prevPosition); } Now, how you go about checking collision depends on you. I personally only check objects that are within the view of the player. When dealing with tile collision, you can simply pass the player y, x divided by tile size to check index values for possible collisions, as you never want to cycle through arrays to do this.

You need to think of classes in the real sense, don't over engineer anything. If you have a human class, and a car class, the car knows if it's moving, but the human knows what car he or she is driving. I would strongly suggest you learn more about OOP before moving forward, this question really isn't a game programming related problem, but more of a general programming question in terms of how class objects interact with one another. Then you should study Game Loops, once you understand how the game loop works, you'll know how these objects interact to input and logic checks.

Share this post


Link to post
Share on other sites

I tried making something with Unity to get an understanding of how an entity component system works, but to me it looks a lot like spaghetti-wiring everything together ;) "Oh how will this object talk to the environment? Whatever just put a reference to it in there, done!" It's so much easier when you can just drag + drop one object from the editor onto a script to give it a reference to it.

What would be the equivalent of this in code? Instantiating everything in the "main scope" and then passing it along like "objA->child->child->childThatNeedsObjB->referenceToObjB = &objB"?

Well thanks for the videos I'm going to watch them now :) Somehow I always have a feeling I'm missing something completely obvious/fundamental.

Share this post


Link to post
Share on other sites
3 minutes ago, Horscht said:

Well thanks for the videos I'm going to watch them now  Somehow I always have a feeling I'm missing something completely obvious/fundamental.

Watch the second video I linked first. It's important xD I gave it to you in the wrong order ;)

Edited by MarcusAseth

Share this post


Link to post
Share on other sites
1 minute ago, Kylotan said:

Personally I'd recommend steering well clear of component-based systems until you are more confident with traditional systems.

I would like to know the reasons for this :)

 

Share this post


Link to post
Share on other sites

The Caves of Qud video was informative but the other one waaaaay too complicated, especially since it involves template metaprogramming which is super hardcore hard and I have no experience at all with that.

Share this post


Link to post
Share on other sites
1 minute ago, Horscht said:

The Caves of Qud video was informative but the other one waaaaay too complicated, especially since it involves template metaprogramming which is super hardcore hard and I have no experience at all with that.

He made a "slower" explanation of it which is actually part of a playlist, the video is this one below.

 

You got to learn sooner or later anyway, right?! The video above will probably be still too complicated, so I might as well drop you some more links to watch before it, so that you get to know what you need to know. Watch them when you're ready xD

First one, you need this below. It is a gentle introduction to template, it starts explaining std::abs() and why it works, but be sure you follow along, write the example and compile. It gets interesting when he show the print function with variadic template arguments, and  it gets insane when he shows an implementation of tuple, I had to watch the whole thing twice to start getting my head around it xD

Then next is the series below. You can skip the first video and go to the second, it is about template argument deduction, you need to understand it if you want to get more confortable with what templates are doing. The third is about overload resolution so maybe you can skip that too, the laters one are again about template.

Also, if you are more of a book guy, today actually C++ Templates: The Complete Guide (2nd Edition) was released, should be 600 pages or something, you'll be an expert on it by the time you finish reading I bet. And then, you can go back to the first video of this reply and probably it will look easy :D 

The rest I guess is just practice :)

 

Share this post


Link to post
Share on other sites

Thanks for all that learning material, I'll look into it over the next few days, but I think before I'll try to make my own ECS from scratch I'll start by just using an existing, well designed and tested one to get a feel for how it all fits together.

Share this post


Link to post
Share on other sites
15 minutes ago, Horscht said:

Thanks for all that learning material, I'll look into it over the next few days, but I think before I'll try to make my own ECS from scratch I'll start by just using an existing, well designed and tested one to get a feel for how it all fits together.

I'm going to throw this out there because I really believe new game programmers need to keep it simple, and spend more time creating their games with a more straight forward approach. Game programming alone is cluster of problems waiting to happen for new coders, and you don't need more webs to tangle you up during the process.

Unless you have a good reason, why don't you just create standard classes and make due until you're more experienced. Here is an example:

Enemy Class - has name, type, hp, attk, def, gold, alive, ect... You will have functions that will manage those attributes, along with collision checking, attack status, and alive status. You will also have a setup function that will match the enemy with the desired monster name, stats, ect... as defined by type id. Then when you create the enemy you can just do Enemy Orc1(1); - 1 being the orc function so in your constructor it sets up the enemy attributes based on the assigned enemy id, or Enemy Dragon1(2); In your constructor you would have something like a switch statement that sets the attributes depending on which value is being fed.

Then make your player class to handle everything you need and make those functions as well.

When you're playing the game you can just pass one object through another to make changes as needed.

player.attack(Orc1) as an example. Then in your attack function for player you will  take the values from Orc to decide your health, gold on kill, ect... and during this process you will either die or kill off the Orc, and update the Orc object directly, and so forth. Make sure you're not passing copies, so your functions need to be created with that in mind under attack(Enemy& a), then pass Orc1 into player.attack().

Don't over complicate or over do anything at this stage. Even if you have to make a ton of different classes to represent objects in the game, you'll still be better off in the starting stage so you can at least make a basic 2D game without worrying about templates, inheritance, components, ect... The more you program the better you will become, and overloading yourself isn't the way to go regardless of what people consider the "best way", it's not the "only way".

Share this post


Link to post
Share on other sites

I want to point out that, from what I've understood the OP is facing the same problem he faced 2 years ago, without progress... So if the more obvious suggestion to keep it simple and avoid composition didn't "cut it" for him  in the past 2 yers (here I am assuming the OP asked for help at the time and also practiced programming since then), maybe a different strategy is required... maybe what works well for one might not work so well for another, imho :P

 

Share this post


Link to post
Share on other sites

Well my cycle is something like this:

Get the desire to make a game, start a new project and program for a few weeks, hit a brickwall, get a feeling that I'm doing it all wrong, ask on some forum, still can't figure it out, give up, pause for 2 years and then it starts all over ;P

I've mostly programmed small stuff, where I don't need a big complex system working together. (Chrome extensions, an addon for world of warcraft, a level editor (in C# .Net) for my last attempt at making a game).

The only thing I never understood is how to seperate everything out logically to not have one monolithic class and then wire it back together.

A level class that loads a level from file, player class that takes care of moving, shooting etc, enemy class with some AI... Somehow I always end up with the same structure everytime where everything needs a reference to everything else where I might as well put EVERYTHING in Singleton classes...

Share this post


Link to post
Share on other sites
17 minutes ago, Horscht said:

Well my cycle is something like this:

Get the desire to make a game, start a new project and program for a few weeks, hit a brickwall, get a feeling that I'm doing it all wrong, ask on some forum, still can't figure it out, give up, pause for 2 years and then it starts all over ;P

I've mostly programmed small stuff, where I don't need a big complex system working together. (Chrome extensions, an addon for world of warcraft, a level editor (in C# .Net) for my last attempt at making a game).

The only thing I never understood is how to seperate everything out logically to not have one monolithic class and then wire it back together.

A level class that loads a level from file, player class that takes care of moving, shooting etc, enemy class with some AI... Somehow I always end up with the same structure everytime where everything needs a reference to everything else where I might as well put EVERYTHING in Singleton classes...

If you've made a level editor with C#, you should be able to make a basic PacMan game. Didn't you create classes that handle save, load, tile selection, tile loading, painting, object attributes, ect...? You just create a class for PacMan, the Ghosts, Items, and Dots, and use Tile Collision with a 2D array for the map.

Then your game loop

Game Loop {

Input() -> Keyboard commands move PacMan (Keyboard.Up) { pacman.moveUp(); }

Logic() -> Move Ghosts - Check Collisions - Item Pickup Check - Dots - Game Over? - Next Level?

Draw() -> Render sprites based on Tile Map + Object locations + PacMan and Ghosts

}

"A level class that loads a level from file, player class that takes care of moving, shooting etc, enemy class with some AI... Somehow I always end up with the same structure everytime where everything needs a reference to everything else where I might as well put EVERYTHING in Singleton classes..."

I don't see this as a problem. You need to interact objects. How else does the player know if they've been hit by the enemy with a sword? You're going to be doing a lot of comparing in programming, this isn't a new or unordinary process. I've programmed a lot of editors and 2D games by using classes to handle level loading, enemies, items, ect... I can just re-use and slightly modify the code to make my next project even quicker.

Yes you can use spaghetti code even, but I don't recommend this.

Well I wish you the best in moving forward. I really cannot help you if you've been stuck for that long as I don't know how to change your thought process. If you post code I can assist more, but the rest has to come from you. If you're new to game programming then stick to the basics, don't skip ahead unless you want to cause more confusion. Maybe look into using GameMaker as opposed to programming games if you're already at the last straw.

Share this post


Link to post
Share on other sites
3 minutes ago, Rutin said:

If you've made a level editor with C#, you should be able to make a basic PacMan game. Didn't you create classes that handle save, load, tile selection, tile loading, painting, object attributes, ect...?

I think for that I misused my MainForm as a giant "Service Locator" ;D With tons of properties for getting a reference to anything and a static "GetInstance" so from anywhere I could just type MainForm.GetInstance().ActiveTool to, for instance, get or change the active tool from anywhere... It kind of worked but there was basically almost no encapsulation whatsoever.

Share this post


Link to post
Share on other sites

I'm far from an expert, but the most useful bit of advice that I've ever gotten was to know exactly what you want. If a problem seems huge and intractable, then it is only because you don't fully understand what you're trying to do. In reality any challenge can be overcome with enough work; true problems only arise when we start working in circles because we don't really know what we're trying to achieve.

Therefore, for any large or difficult project the most important thing is to have a design document. Decide exactly what you want and write it down in full detail. Imagine that you're going to pay someone else to make the game, and they'll only do the absolute minimum to get their check, so anything you don't put in the design document won't end up in the game. The process of making that document will clarify countless issues that you never even realized were issues. All the relationships and interactions between entities will be laid out explicitly,  and all the mysteries and confusion will be gone, and all that's left will be to straight-forwardly implement the plan.

The abstractions and names that you create for things while explaining what you're trying to achieve will serve you well during implementation because they will become the data structures and classes, and so it will be obvious which classes must naturally talk to which classes based on their role in the design.

In other words, it's easier to tell Visual Studio what your game should be if you first tell it to Word.

Share this post


Link to post
Share on other sites
1 hour ago, Horscht said:

Somehow I always end up with the same structure everytime where everything needs a reference to everything else where I might as well put EVERYTHING in Singleton classes

You can just make one singleton, a main class that holds shared_ptr pointers to the other class: Input, logic, rendering, etc. Then logic can be in control of managing the actors.

 

1 hour ago, Rutin said:

I don't see this as a problem. You need to interact objects. How else does the player know if they've been hit by the enemy with a sword?

Also, use an event system. This makes it so that the other classes don't need to know much or anything about the other classes. Here's a link to a c++ version of it.

https://stackoverflow.com/questions/7464025/designing-an-event-mechanism-in-c

Also, check out my post below. I don't want to retype the same thing as before. Its about c++ instead of c#, but it might help.

 

Edited by Yxjmir
typo

Share this post


Link to post
Share on other sites
15 hours ago, MarcusAseth said:

I would like to know the reasons for this

 

Because they're a mess. Because it adds complexity, rather than removes it. Because nobody on these forums or elsewhere has any sort of consensus on how best to approach them. Because the only people who are productive with them are people who don't need to ask questions on forums like these.

If you're struggling with program organisation, components ADD problems. Now, instead of just working out how your Entity relates to things, you also have to decide how to decompose your Entity. Don't do it.

 

Horscht, my initial advice applies - stop worrying about how to structure the whole app. Just make what works and refactor as you go, asking specific questions about your code if necessary. People here are happy to help on your journey, but they can't give you a full roadmap.

Share this post


Link to post
Share on other sites
16 hours ago, MarcusAseth said:

I would like to know the reasons for this

 

There are a lot of reasons:

 

- ECS is not a generic solution to solve all game programming problems!

- It overcomplicates everything - especially for beginners because there are so many indirections it requires. Making it debug and follow a nightmare when you dont have the proper tools

- It has runtime performance penalitities, some can be minimized some cannot: You need to be at least aware of that

- Doing it right is hard. Doing it poorly/wrong is really easy.

 

See @Kylotan answer.

Edited by Finalspace

Share this post


Link to post
Share on other sites

And yet, I totally don't like the idea of wasting time doing something like an rpg with classes where my skeleton swordman inherit from baseSkeleton and also the Skeleton Axeman inherit from the baseSkeleton, and now I want to add skeleton BladeMaster which require stuff from swordman and axeman and there is that diamon inheritance problem I often hear about.

As difficult as composition might be, I would rather learn the difficult thing once and be setup for success, rather than following a path knowing it will eventually lead me to a dead end :/

Also I realize it doesn't apply to all scenarios, but I always have in mind that sooner or later I'll attempt doing something roguelike, so I plan for that.

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

This is a totally false dichotomy. There is no reason why you have to have a massive inheritance tree just because you don't use components. I've worked on many games with no components and they never went down to levels like 'baseSkeleton' or 'skeletonAxeman'. More common might be PlayerCharacter and NonplayerCharacter, derived from Character. That's very manageable.

If you don't see how it's possible to make multiple enemy types from a single NonplayerCharacter class without needing extra inheritance, then you're not ready to recommend components as the solution. Most games in history did not and do not use component-based entities. Choosing not to use component-based entities is not a dead-end.

Share this post


Link to post
Share on other sites

I shouldn't have used the word "dead end", poor choice of expression, but I meant that inheritance complicate things as well. At least with components (from my understanding) you simply move all the complications upfront so that for the rest of the project you are more free to put your ideas into practice without having to worry as much about coupling, which seems to be exactly the OP problem (he even said he was passing objects down 10 layers of inheritance or something like that...)

Share this post


Link to post
Share on other sites

Components create extra coupling problems, because now you have to do it within a class as well as between them. There's a pipe-dream of having a useful set of components that are loosely coupled, but the threads on this forum prove that it's incredibly hard to achieve that. It's much easier just to start with an Entity class and work from there.

The original post said nothing about chains of inheritance, just chains of construction. That's composition. You were the first poster to mention inheritance.

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