Skip to main content
GameDev.net gamedev.net
🔒 Locked

The chunks the game is made of

Started by Calin Oct 12, 2023 at 5:10 PM 13 replies 11.7k views
Original Post
Calin
Calin

These are the WIP main sections of my game what do you think?

A GameEntity base class with an Update function. I will have a loop in which every frame I will iterate through all GameEntities and run the Update function.

Collision detection and range check. Range check against buildings with four “collision” bodies at the corner of each building and also against enemy units.

A routine to run the build orders for AI players

Is there something missing?

My project`s facebook page is “DreamLand Page”
MarkS
MarkS

Is there something missing?

Yes. Code.

No, I am not a professional programmer. I'm just a hobbyist having fun...
Calin
Calin

MarkS said:

Is there something missing?

Yes. Code.

I posted my code once here in the blogs section. Maybe I’ll post code again in the future.
For now I’m just presenting how things should be in theory

My project`s facebook page is “DreamLand Page”
JoeJ
JoeJ

Calin said:
Is there something missing?

You forgot the most important: Handling player input.
You always only worry about NPC and world simulation it seems, which is our technical challenge.
But we do this only for one reason: It should be fun to interact with, which is our design challenge and what makes the game good or bad for most.

Calin said:
A GameEntity base class with an Update function. I will have a loop in which every frame I will iterate through all GameEntities and run the Update function.

Sounds you want to adopt some generic software design concepts without knowing exactly why you should, or what's the advantage / disadvantage of said concept over others.
Personally i prefer to figure out what's needed and care just about that. It does not matter if we call it entities and components, OOP class hierarchies, or whatever else. The specific problem dictates the good solution, but we can't expect some generic concept to be the best solution for our problem. Nor can we expect such concept feels convenient and natural to use. It depends on personal favors and habits. In other words: Do what you want, in the way you like. Follow belly feeling, and if it turns out bad, change it - now that you know what's the problem with it.

A question: What is supposed to happen in your Update() function?

Update usually means to change state due to the advancement of time.
So what you need to think of is how to manage this state and the dependency graph so all information affecting this change of state is available when you do the update.
Assuming you still work on RTS, you have units. And a unit can have a lot of state. Position and velocity, health and armor, ammo, maybe a current target, maybe a path to the goal, etc.
You may also have different types of units, some of them way more complex than others. A unit may even produce smaller units and release them to the battlefield while moving to some goal. Eventually such unit keeps commanding its sub units, so it needs to keep track of them.

At this point, likely we can no longer use just one simple struct or class to represent every potential unit. Our class will have too much state which by most of them is never used, and out memory access patterns become random and inefficient.
To address this, intially OOP class hierarchies were often used. We have a NPC base class, then a knight and a pawn to derive from that, and also sword or bow fighters deriving from the knight. Etc.
But this has many problems, mainly because class hierarchies form a tree, not a graph. So we are not flexible. We may want that both sword and bow fighters can now also have some magic skills. But we can not derive our magican class from both the knight and the bow fighter. So we are forced to derive them from a magican instead, which my not work for other reasons.

The Entity component model addressed this problem. It replaces class hierarchies with components. We have a magican component, a knight component, and a bow fighter component.
And somehow we can couple them loosely, so a certain NPC can have all of those components. Great. Now we can form graphs and have no more tree limitations.
We also have multiple classes now to make some NPC. That's good for systems. E.g., a physics system just cares about rigid body components. It loops only over relevant data, so our memory patterns are much better. The physics system now also is modular, and we can use it and its rigid body class in other games. Great too.

However, the catch is that it is now no longer easy to find all components belonging to a certain NPC. There are many ways to do this, all with their pros and cons.
We could have a list of components per NPC, but this list has variable size.
We could use some ID per component, and find all components which have this ID. But then we need to do a lot of searching, which is slow.
We could form a linked list, so NPC points to rigid body, rigid body points to health stats, health stats point to weapon, etc. But now we need to traverse and chase pointers, hopping around in memory constantly still.

It's hopeless. We will never have a ‘right’ way to do it. So just do what you think should work, but be prepared to regret your decision later and improve.

Calin said:
A routine to run the build orders for AI players

Build orders, just like walking along a path, are actions which last over a duration of time. That's usually a challenge.

For example, you may start with just one NPC, successfully calculate a path to a goal, and than make the NPC walk along the path. Nice.
But then, when you move on to multiple units, each having it's own path and eventually changing goals at any moments, you may find it difficult to apply what you have already solved before.
That's a good example of why state management is important. You now no longer can just follow the path from start to finish in a single function. Instead your NPC must be able to do just one step (per Update), then eventually find a new path to a new objective, or eventually continue to follow the given path.
This means either your NPC or your pathfinding system needs to store this path, and on which segment on the path we currently are, and that the NPC is currently walking along a path, or it may do a break because some combat. We also need to delete the path and free memory once it's no longer needed, etc.

I would care about this first.
Make a map with multiple units, let the player select them and have them move to a goal they click on.
Even if the units are walking to their goals, the player must still be able to select them again and give them another goal.

That's what you need to do i think. And only after problems show up eventually, you have a good question to ask.

Calin
Calin

Hi JoeJ


>handling player input

there is no player input in my program. AI player vs AI player is still a functional thing. I don’t find the player interface ( not the type where you make abstraction of who is playing the game but rather user interface) and buttons etc. challenging. I’ve done that before, I’m tired of it.

>Sounds you want to adopt some generic

I think keeping everything in the same container is the easiest thing to do. Keeping a patch of crystals (resource) in one place and a unit in another and then trying to run them against each other if there is a relation between them seems like a lot of trouble.

My project`s facebook page is “DreamLand Page”
JoeJ
JoeJ

Calin said:
there is no player input in my program. AI player vs AI player is still a functional thing. I don’t find the player interface ( not the type where you make abstraction of who is playing the game but rather user interface) and buttons etc. challenging. I’ve done that before, I’m tired of it.

Oh, so you work only on things you find challenging, interesting, or fun to do?
Well, sadly this won't work. If you want to make a game you have to work on everything that's needed, including input and user interface.

Sooner or later. But better sooner, because:
You can use it to test your application. It helps to find things which do not always work. It reveals issues you did not think of, and will not spot if nobody does unexpected things to your game.
GUI and input is needed for debugging reasons, not just to make your game playable.

Calin said:
I think keeping everything in the same container is the easiest thing to do. Keeping a patch of crystals (resource) in one place and a unit in another and then trying to run them against each other if there is a relation between them seems like a lot of trouble.

You mean you will have a single god class, and it will handle everything? All kinds of units, all resources, all buildings?
The RTS games i have in mind are way too complex to make this work. The class would be huge, a waste of memory and spaghetti code hard to maintain.
But i think it's fine to try it and see how far you get. At some point you may feel a desire to split the class into multiple classes, but that's always possible.

Assuming the day will come, here are some options regarding your worries of processing multiple kinds of objects.

You can use OOP. Declare a common interface you need in the base class, and have derived classes each having specific implementations of said interface. Then you can call e.g. Update() on any derived class object. C++ cares about all the details under the hood. But you need to design your interface with foresight.

You can do the details yourself. E.g. using switch statements, processing different code depending on the kind of object. Because i do not like OOP so much, i still do this often. But often i regret it. It's more work and more error prone. If you add a new kind of object, you have to go through all your code manually to add it everywhere.

After bad experience with either, you may start to look up what other people do, and it will bring you to ECS and similar advanced topics. That's not something i would describe as 'interesting'.

If you want to postpone this as much as possible, i understand this. I also think it's better to do some mistakes first, like using the god class, then learning from those mistakes and ideally coming up with improvements.


Calin
Calin

>build orders just like walking along a path

there’s two types of build orders. One is training units ”inside“ a building. That’s easy. The other type is telling a worker to build a building. That one is a bit of a challenge, there’s a lot more things that need to be done.

>build orders, ,are actions which last over a duration of time.

a build order to produce a unit is made of an one-time event and working time for the building.

>you mean you will have a single god class

A base class from which I’ll derive things.

>oh, so you work only on things

)))

In all seriousness skipping over doesn’t break anything, but you know that

>What is supposed to happen in your Update() function

When the Update is called combat units move a tiny bit along the path and the walk animation gets looped a little ( if I’ll have a walk animation at all, for now a unit is just a cube. I’m not including a lot of flashy things, there’s too many things that need to get done ) or the fight animation is looped, depends. If it’s a building the training animation is run etc.

My project`s facebook page is “DreamLand Page”
JoeJ
JoeJ

Calin said:
In all seriousness skipping over doesn’t break anything

Umm, ‘skipping’ means ‘not doing at all’. So you mean you will NEVER make your game playable?
It remains a self running RTS demo?
No ‘adding playability' at least with day one patch on release?

Well, that's interesting. It's not a game then, and you may be on the wrong forum. But i admit it is something new.

Or, in case you have expressed yourself badly and i've got some things wrong…

Calin said:
Is there something missing?

Yes. Make it interactive from the start, and playable as soon as possible.

Calin
Calin

JoeJ said:

Calin said:
In all seriousness skipping over doesn’t break anything

Umm, ‘skipping’ means ‘not doing at all’. So you mean you will NEVER make your game playable?
It remains a self running RTS demo?
No ‘adding playability' at least with day one patch on release?

Well, that's interesting. It's not a game then, and you may be on the wrong forum. But i admit it is something new.

Or, in case you have expressed yourself badly and i've got some things wrong…

Calin said:
Is there something missing?

Yes. Make it interactive from the start, and playable as soon as possible.

My goal was to build a game on my own, and then move on to a better RTS, I know there are guys that can do the work of building a RTS way better then me. I would like to work on verson 2 which is better ai.

My project`s facebook page is “DreamLand Page”
JoeJ
JoeJ

Calin said:
My goal was to build a game on my own, and then move on to a better RTS, I know there are guys that can do the work of building a RTS way better then me. I would like to work on verson 2 which is better ai.

So your argument is something like ‘I do not work on a game - i work on an AI system. Thus i do not need things like processing player input or a GUI.’ If i get you right.

But imo, that's still the wrong way of thinking, and you think this way because you do not know what you miss. You are unaware how much harder you make it for yourself, and how much you could increase your rate of progress, if you had a ‘proper dev environment’.

What do i mean with proper dev environment?
Let's think of game engines like Unity or Unreal. They have an editor, lots of GUI stuff, and the same things 3D modelling tools have. Gizmos to transform objects, users can move their camera anywhere to look up things in detail. They can enable debug visualizations e.g. to show control points of a spline, etc. Devs can and will also implement their own code just to visualize some thing currently giving them problems. They can output text in the 3D viewport, e.g. an error message, showing something went wrong. And due the visualization, the user sees where things went wrong, and how they look like. This might tell them more in an instant moment than using the debugger to step through the code, but lacking any spatial context.

That's not a luxury. It is a requirement. If i have to guess, here's how much i use various ways of debugging:
Visual / interactive debugging, requiring to write a lot of specific code: 90 %
Logging text to a file, e.g. error messages or warnings. Requires to write very little of code: 5%
Using the debugger, not requiring any code at all: 5%

As a beginner, i did not use anything of this. Not even the debugger. It took me some time to figure out why this is so useful, actually years. I assume you are at a similar level right now.
But now, knowing better and looking back, i do know how much time i have wasted by not investing into debugging skills. I was working blind folded and inefficiently, so even simple things took me a lot of time.

Different devs use different ways to debug their code. For example, i had never used the way to log text to a file, until i've worked with a web dev on a webpage. He could not use the debugger for technical reasons, so he had to use just logging. Working on webpages, options on visual / interactive debugging are pretty limited too, so logging was the only real option for him. So, being new to web dev, i have adopted the same method. And only then i realized it gives a lot of options that using the debugger do not give. For example, i can see the order of things happening. I can see which error appeared first, and i can speculate that maybe this error causes all the others after that. Using the debugger, you do not get such kind of information.
I'm pretty happy now to know this, and i still use it a lot in my own projects.

The kind of visual / interactive debugging i want to talk about is used rarely. Because it's almost exclusive to realtime / graphics application development. But for us, working on game related stuff, it's always available.
Here's what i currently have on my screen:

Basically all i have on my screen is debugging stuff. All those dots, lines, text, and all of the GUI is debugging stuff. I work this way 90% of the time.
That's because what i do is very difficult. Working with geometry is hard, because it's so easy to introduce degenerate cases. Often i need to work a whole day just to understand why exactly such a bad case happens, to see how it looks like, and what would be the proper way to fix it. I need those visualizations, and i need interaction so i can observe what a unique iteration of a loop is doing, for example. It's some work to make all those visuals and GUI stuff, but it is the only way. It would be much too hard otherwise.

Now you may think you don't need this, because you do not work on geometry.
But no. I do the exact same thing for everything else too. No matter if it's robot ragdolls, setting up a character skeleton, or a little game. It's always useful. For almost everything, all the time.

If i would work on an RTS AI system, i would use this heavily. I would click on a unit, and then i would see it's current path to follow, and the enemies it currently sees. An window would pop up, showing the current queue of orders it is processing. And i could click buttons on this window to add new orders to test how that works.
I would make a whole RPG game to test my AI. I would use boxes for the units, like you do. But my GUI and interaction would be much more than what later remains in the final game. 10 times more, maybe. So i can test all the things and see how they work.
I would spend more work on debugging, visualization and GUI than you do, but i would have a playable RTS in 3 months, i claim.

How long do you already work on your RTS? How many years? And it's still not playable.
Why could i do this so much quicker than you can? Because i'm a better programmer? Because i know all about C++, OOP or ECS, and because know ‘how RTS is made’?
No. I actually know very little about all those things.
But i do know what's needed to develop a graphical realtime application:
You need ability to draw stuff.
You need GUI.
You need a linear math library for vectors and matrices.

You need all that first. And only after you have all of this, you can start work on your application, whatever it is.
Using DirectX, you have a check on point 1 and 3. But you have no GUI, so you are extremely limited on what you can do.
I propose you add imGui to your project. Almost everybody uses this library. It's great. It's made for debugging reasons, and not really useful for a final GUI of a completed game.
Like character boxes, you can postpone work on a final GUI, and you should even. It's not yet important.
But for anything more complex than PacMan, you need some basic GUI to interact with your application, and to print information to your screen, not just to some file.

Integrating ImGui is some work, but it's worth the time. You'll work much more efficiently after that investment.
If you don't do it, every script kid using Unity will achieve more in less time. Your choice is to do everything yourself. Respect and congrats. But this means you have to care about some things which are not really interesting, but still absolutely required.

That's just my personal opinion and experience, ofc. But i'm sure many would agree.

Calin
Calin

>I work on an AI system

Call it that if you like. Thinking what is needed to get a RTS ai player working is enough to build the whole game. The only other thing that’s needed is playing a RTS game and paying attention at what an ai player does.
> you need the ability to draw stuff

You mean graphical artist skills? What are lame programmer art placeholders for?

>Let’s think of game engines like Unity or Unreal

Everything these commercial engines have, debugging tools included is oriented towards producing a commercial game that is up to date with the requirements of the year. It’s all about next gen, I have no such worries.

offtopic, I‘m lost when it comes to what I’m going to use to draw stuff. Graphical engines and API’s in c++ are so tough to use. Currently I’m using DirectX 10. I heard DirectX 10 and 11 are deprecated in the new version of Windows. I will try Ogre maybe I’ll manage to bind it to my current engine.

I like your screenshot btw.

My project`s facebook page is “DreamLand Page”
JoeJ
JoeJ

Calin said:
You mean graphical artist skills? What are lame programmer art placeholders for?

No, i don't mean art, or anything visible in the final game.
I mean temporary debug visualizations. Temporary code we write only to visualize a certain problem which we can't understand using the traditional debugging methods.
A typical example is intersection or closest distance calculation between two geometric primitives. Box - box, sphere - box, sphere - triangle, etc. You may need this e.g. to plan obstacle avoidance for your units.
Such tests often have many special cases. It's a difference if the sphere is closest to vertex, an edge, or a face of our box. Each case requires its own code to handle it.
Thus, if you develop such test within your game, it's likely some special cases just do not happen at the moment. But it seems working, so you move on.
Three weeks later, when you have already forgotten everything about how your test works, bugs show up. So you have to work on it again, building up the forgotten knowledge again, taking a lot of time, to finally fix it.
A month later, another problem shows up, which went undetected before. Again you have to work on that damn intersection function…

Equipped with visual / interactive debugging superpowers, we can do much better:
We develop our function in isolation, independent of the game.
We make a GUI so we can move the box and sphere with sliders, editing numbers, or ideally transforming them with a gizmo. This allows us to test all special cases in seconds. It's even likely we stumble over failure cases we did not think of, while moving those sliders.
We also visualize the results in real time. A point on the sphere, a point on the box, and a line connecting them. We also have ability to rotate camera around our test model. And observing it from many perspectives, we quickly feel sure about our result to be the correct closest distance, and no shorter line should be possible.
Then we use our function in the game, and much more likely we never need to go back to it.

I hope this example makes sense.
Another one would be to visualize all the paths your path finder explores, not just the path which makes the final result. This way you can just ‘see’ how efficient or inefficient your algorithm is and how much work it does.
If we observe this visualization for each iteration of the path finder, we can also just ‘see’ HOW our algorithm works. We may have never heard about Dijkstra or A-Star, but we may understand how it works just by looking at our visualization of said algorithm. I grant you, this really is a low effort but powerful way to grasp some concepts quickly.

Also, application is not limited to geometrical problems. I often visualize data structures, e.g. graphs or trees. I may visualize pointers with an arrow. It can help to spot data errors visually very quickly, which would be impossible to find from looking just at raw numbers of the data itself, or stepping through the code with the debugger. There are many ways to make programming easier, but this one maybe is the most important. To me at least.

To visualize stuff, i can draw only 3 things: Points, lines, and triangles. I can color them, but i have no texturing or lighting. I do however have helper functions to draw arrows, circles, spheres, boxes.

Calin said:
>Let’s think of game engines like Unity or Unreal

offtopic, I have no idea what I’m going to use to draw stuff. Graphical engines in c++ are so tough to use.

Like you, i don't care about final assets or advanced rendering either. It's fine to use placeholders and boxes.

Again - i do not talk about graphics or even games. I talk about making programming easier and more efficient using visualizations and GUI to interact with the application.
Even if we have written this application ourselves, at some point we no longer know how it will behave in any situation. It may be much too complex to know all about it.
So all we can do is observing the application, to verify it behaves as intended. And to observe it, we need an interface of interaction.

Ofc. we could also write specific testing code, which verifies our app. We could create random test cases, run them 1000 times, and then we might be sure it works.
But both those options have their pros and cons, and they are not mutually exclusive. Work spend on one often enables to use the other as well.

It's offtopic, agreed. But imo it makes little sense to talk about higher level game dev concepts at this point, and i'm not the right one to talk about ‘Entities’ anyway.
Remembering your code you've showed me years ago, the code was pretty fine.
But you need to work an ability to manage a larger, growing project.
You need to split your single source file into multiple files, so you learn how to compile code from multiple files. (Maybe you already know.)
After that you're ready to include 3rd party code as well, e.g, the GUI i have proposed. There really is no reason to write this yourself - it's only for debugging.
There are many free and good open source libraries. You may use a rendering library one day. Or a physics engine, audio, network, etc.

In other words: No matter if you aim for an amateur or professional level, you need to care about some other things too, beside the actual programming problem you may currently work on.
This includes managing larger projects with many code files and eventual 3rd party libraries, and this includes general properties an application or game has, like processing input and having some GUI.
You should not postpone this, because not doing it holds you back in many ways.

Calin
Calin

>I mean temporary debug visualizations

I never thought you could debug using other methods than just plain text. You are creating visual models of various problems, how interesting.

Speaking of the case when you build a GUI of your own, one of the problems I’ve had is that I wasn’t even sure if the numbers the GUI was showing were real numbers or a bug in the interface. It’s like you’re building something but you have no idea what you’re doing.

>ofc. we could also write specific testing code

Is that what a test unit is? People were talking about it on code project forums and I kept asking my self what that is.

My project`s facebook page is “DreamLand Page”
JoeJ
JoeJ

Calin said:

I never thought you could debug using other methods than just plain text. You are creating visual models of various problems, how interesting.

Other programmers are often surprised about this. So i spread the word, because i think it's really powerful.

Calin said:
Speaking of the case when you build a GUI of your own, one of the problems I’ve had is that I wasn’t even sure if the numbers the GUI was showing were real numbers or a bug in the interface. It’s like you’re building something but you have no idea what you’re doing.

GUI is something annoying and frustrating to me. I remember, for very early tools i did i have used Win32 GUI. But this really sucked. It feels like Windows is not designed for realtime applications.

Then i did my own GUI in OpenGL. With menus, drop downs and all the stuff. 3 weeks of work. I've used it for 10 years and was pretty happy with it. But it still was cumbersome to use. I had to setup the controls of a window in advance in some Create() function. My GUI took pointers to my variables and changed them directly, so i did not have the problem of invalidated duplicates, as you describe. But this was risky. If a pointer becomes invalid, the GUI could crash my app.

Then imGui came up, and i was switching over to Vulkan, so i gave it a try instead porting my old stuff.
imGui is an ‘immideate mode’ gui, which means there is no more need to setup things in advance. That's a game changer, making it totally effortless to use. It works like this:

void RenderMyFrame()
{
static float sharpness = 0.7f; // Some variable i want to tweak at runtime
ImGui::DragFloat("sharpness", &sharpness); // Now i can. A gui element is created in the current window. But i do not need to care about windows if i don't want to.
RenderImage(myImage, sharpness); // doing stuff using the tweaked variable
}

It is that simple, and works for any gui elements. They just appear in the order you created them during processing one frame. It stores a pointer to my variable, but because the gui is recreated each frame, some object which has been deleted simply won't no longer create it's gui elements. You don't need to manage anything, and all you need is to include ‘imGui.h’ in your code file.

But it is some work to set it up. You need to give it a rendering backend, but it comes with examples for any gfx API. Basically callbacks to render triangles.
And you need to give it info about kb+mouse input, usually at the place where you process input for the game as well.
However, after spending some hour to make this work, you can interact with anything in your application. No more need to express all and everything with source code.

Calin said:
Is that what a test unit is? People were talking about it on code project forums and I kept asking my self what that is.

Hehe, i'm thinking the exact same. I wonder too what ‘unit test’ really means.
I assume it is like keeping and maintaining all the various tests we implement during development, and then running them every day so you get a warning if something breaks again.

If so, that's a debugging superpower i'm personally not capable of, til yet…

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.