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

Gameplay programming design question.

Started by jakemry Sep 13, 2023 at 10:42 AM 10 replies 10.2k views
Original Post
jakemry
jakemry

I'm a beginner to game development and am having frequent trouble with designing my classes and structuring my code. I feel I don't know when to separate logic from a class into a new class.

For example, I'm making a game with a grid. I made a grid class that has properties like number of rows, cols, etc. There is a function to be able to visualize the grid, where it generates the cells, edges, and corners. There is also a handful of functions for manipulating grid data for each [row][col] location.

My questions are: Should the visualization code be a part of the grid class? Should the manipulation of data be a part of the grid class? I just don't know when the right time is to separate things or when I am creating too many layers. Are visualization and data unique enough to warrant separating them from the main class?

SuperVGA
SuperVGA

That is a very common challenge. It makes sense to let a class that knows details about the Grid class draw the Grid. Whether the Grid class itself should do it, and know some graphics interface, or some other dedicated drawing class (friend of Grid) should, is a design choice.

If the project is small enough, I'd also say that one can benefit from letting some general rendering class draw the grid, but with the likelihood of bloat or an eventual refactor.

Don't feel bad about this sort of challenge - with enough experience you'll make better design choices early. Eventually. Perhaps. Sometimes. Nobody is perfect.

scott8
scott8

@jakemry I vote for separate class. I've done that recently with a grid I used for generating a maze, pathfinding, and spacial partitioning. My visualization class (a friend of the grid) is really just for debugging.

alvaro
alvaro

You should prefer to separate logic and representation. The grid should probably not know how to render itself or how to modify itself. A common software pattern that might help you here is called model-view-controller. I would start by reading about this pattern (I'm sure there are many descriptions on the web) and see if you can map what you learn to your situation.

LorenzoGatti
LorenzoGatti

There are likely to be cases where you use the grid without rendering it (e.g. simulating offscreen places) and more importantly different ways to render the same game state from the grid (e.g. realtime main view in third person 3D, realtime minimap from an overhead perspective, exported high quality video).

Even without such slightly advanced usages, defining and respecting a boundary between game data and rendering will produce a simpler and cleaner design.

Omae Wa Mou Shindeiru
skinmarquee
skinmarquee

It depends what you're trying to accomplish. If you're trying to make the next Unreal Engine 5, then stick to the books. If you're trying to make a game, though, do what works and refine it on the next game.

None
LorenzoGatti
LorenzoGatti

troutsneeze said:

If you're trying to make a game, though, do what works and refine it on the next game.

I'm afraid this sounds like advice to ignore traffic lights because one is in a hurry, but slow down at the next intersection: if a game project is abandoned because it has become too complicated to make progress, the next project might not exist at all.

Omae Wa Mou Shindeiru
skinmarquee
skinmarquee

Afraid I couldn't disagree more, but there's no sense in arguing. I do have over a dozen (probably 2 dozen) published games since the 1990s to back me up.

None
LorenzoGatti
LorenzoGatti

troutsneeze said:

I do have over a dozen (probably 2 dozen) published games since the 1990s to back me up.

This is the “For Beginners” forum. You know how to “do what works” with small and rare mistakes and you probably don't even see organizing data structures and rendering as a challenge; but someone “having frequent trouble with designing my classes and structuring my code” needs more actionable and specific advice than spending years to reach your level of experience.

Splitting a complex design (here a self-rendering grid) into two simpler and therefore easier designs (here a grid and a renderer) is a safe general principle to follow for a beginner because minimizing difficulty is more important than minimizing effort or code size.

An expert who can predict and avoid mistakes could be confident enough to combine the two systems in order to write less code, but (another useful general principle for beginners) cutting corners is something that should be attempted prudently after you “stick to the books” and succeed.

Omae Wa Mou Shindeiru
JoeJ
JoeJ

jakemry said:
My questions are: Should the visualization code be a part of the grid class?

Usually no, especially if it involves gfx API calls, but you might replece the gfx API later.
But tbh, personally i do add debug visualization and GUI stuff to the class. This often even helps to figure out how the class works and what it's doing. So in some sense such debug code serves as documentation.
I do however make such code optional using preprocessor defines, to remove it from final release builds.

jakemry said:
Should the manipulation of data be a part of the grid class?

Usually yes. That's functionality tightly coupled to the data of the class, basically like those getters and setters we use for abstraction.

jakemry said:
I just don't know when the right time is to separate things or when I am creating too many layers. Are visualization and data unique enough to warrant separating them from the main class?

Usually you want to split a class if it starts to serve multiple purposes instead just one.
Notice visualization is a bad example. Because it should not affect the state of the data, it won't do any harm, and thus there shows no real need to separate it.
But let's say we have some GameObject class, and it has member functions like those:
DetectCollisions(), CalculateForces(), IntegratePhysics(), Animate, Render(), PlaySound().
That's surely too much. We quickly loose track of who might have affected state and when in unexpected ways.
So i would remove all those functions but put them into Physics, Animation, Rendering and Audio systems, which then may all depend on GameObject but the GameObject knows nothing about those systems.

But that's just personal opinion and habits. You can look up ‘SOLID’ for generally accepted guidelines.

John_Stones
John_Stones

In game development, it's beneficial to follow the Single Responsibility Principle (SRP) and separate concerns. Your grid class should primarily handle data and logic related to the grid structure and manipulation. Visualization code, such as rendering cells and edges, is best placed in a separate class, often referred to as a "renderer" or "view" class. This separation helps maintain clean, organized code and makes it easier to modify or extend either the grid or visualization independently in the future. Keep the classes focused on their specific responsibilities to avoid creating unnecessary layers and improve code maintainability.

Topic Locked

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

Sign in to reply to this topic.