Which method to use for drawing?

Started by
5 comments, last by Xanather 11 years, 6 months ago
Quick question, which method should I use to draw the game scenes? This is the only part of my game design/code structure which I am lost on.

Some idea's I have are:
A: Create a Drawing class and dump all the drawing code in there (which will make for a extremely large class eventually)?
B: Write drawing code in their respective classes (i.e. for player write player only drawing code there), and then have a Drawer class that calls all the methods of other classes that need to be drawn (such as the player class).

Some Info:
- Using OOP (C#)
- Using XNA
- 2D game
- I am using RenderTarget(s)

All replies are appreciated.
Thanks,
Xanather.
Advertisement
The one wich is the most obvious to me would be spriteBatch.Draw()..?

Pass spritebatch the the respective classes of the items and draw it directly from the class.
The concept of letting an object draw itself is quite outdated and pretty inefficient when looking at modern graphics hardware. Unless you do some really weird things with your 'drawable' objects you will always be able to dilute these to a common format. If you're working on a 2D game your common drawable format for a single frame will probably be a structure containing at least a sprite, a transformation and maybe some fancy effect to apply to your sprite.

All you have to do then is design a class which can draw these structures correctly. The benefit of this approach is that you're working with completely uniform data which can be properly sorted or modified for very efficient rendering (eg. overdraw reduction, reducing state switches, etc.)

I gets all your texture budgets!

OK, well, that sounds about right :P. Looks like I will be designing a class that will draw everything then (other than the game menu, just the primary game).

Thanks :)

OK, well, that sounds about right tongue.png. Looks like I will be designing a class that will draw everything then (other than the game menu, just the primary game).

Thanks smile.png


Your game menu could very well be drawn by the same system, as GUI elements also essentialy boil down to (collections of) sprites.

I want to be clear about the fact that I'm not talking about a god-class here which knows everything about every drawable object in your game. It's all about finding a single simple format which can store all the essential information for drawing a single object in its most basic form.

I gets all your texture budgets!

You should have renderable object types (by how theyre rendered) draw themselves using an abstract renderer interface (so you can implement it using opengl then change to directx. or perhaps you dont need a renderer with other functionality than render() if you use lets say SFML?)

Then each of your game objects can obtain one of those object types, register it somewhere, and then upload new data to it (like change the texture). However i dont think you should do GameObject.Draw(), but rather make the "somewhere" where the renderable objects are registered draw them all at once when requested.

Thats how i would do it at least.

class GameObject //Moves data between a LogicalGameObject and GraphicalGameObject, eg. if its a player, the LGO has the position, which the GameObject updates to the GGO so it will render at the correct position.
{
LogicalGameObject lgo; //handles the modeling side. physics etc. can work independently.
GraphicalGameObject ggo; //makes a visual representation of lgo, using the data from lgo passed to it by GameObject in some way.
}

(is this MVC by the way? looks like it...)

The benefits of this would be that you can run the game logic without any of the graphics stuff and it works just as it would work if you turn your monitor off, and all the code linking the logical representation and the graphics etc. (sound? network replication?) are done by the GameObject, so if you want to change how the logical object is rendered, all you need to do is change how the GameObject class is implemented.

Lets say if you have the network replication object (replicates the object based on data from the network) so you sometimes get the current outdated state of that object on the server.

What you could do, is have 2 LogicalGameObjects, the other existing in a local World, and the network replicated one in the ServerWorld. The GameObject would thus contain what the server saw some time ago and what you see. What the gameobject could do, is tell something (another class, ClientServerWorldsSmoothUnifier? xD) to try and make the local world smoothly match the server world, with prediction and all. (eg. SmoothlyUnifyWorldATowardsB(A,B) or SmoothlyUnifyATowardsBSoIfIShootItTheServerWontTryToTellMeHeWas2MetersAway(A,B))

So the GameObject would observe the "physics" (Logical version) and all and pass the relevant information between them so they all react correctly to each other, and allow you to remove such a component by just stopping passing data to it. (A bad way to do it would be to lets say play a sound directly in hit detection and draw it when the physics move it. Instead you want to tell the owner of the physical representation when those events happen so it can tell rendering and sound to do their thing.)

Controls (eg wasd for a character) also are a representation of the object, but a very shallow one. Pressing w for example tells that "The object tries to move forward", like the graphical representation is "The area occupied by the objects surface looks like this from this position in the world.", which is also shallow. Or the network tells "The objects position was this an unspecified amount of time ago, and heres some data that might help you figure out what happened during that time."

tl;dr:
{
MVC
*daydreaming mumble*
Separate logical (physics etc.), rendering, audio, network etc. representations of an object and have a higher class contain thouse components and pass relevant data from relevant components to components that use that data.
*daydreaming mumble*
*daydreaming mumble*
tl;dr section
}

o3o


You should have renderable object types (by how theyre rendered) draw themselves using an abstract renderer interface (so you can implement it using opengl then change to directx. or perhaps you dont need a renderer with other functionality than render() if you use lets say SFML?)

Then each of your game objects can obtain one of those object types, register it somewhere, and then upload new data to it (like change the texture). However i dont think you should do GameObject.Draw(), but rather make the "somewhere" where the renderable objects are registered draw them all at once when requested.

Thats how i would do it at least.

class GameObject //Moves data between a LogicalGameObject and GraphicalGameObject, eg. if its a player, the LGO has the position, which the GameObject updates to the GGO so it will render at the correct position.
{
LogicalGameObject lgo; //handles the modeling side. physics etc. can work independently.
GraphicalGameObject ggo; //makes a visual representation of lgo, using the data from lgo passed to it by GameObject in some way.
}

(is this MVC by the way? looks like it...)

The benefits of this would be that you can run the game logic without any of the graphics stuff and it works just as it would work if you turn your monitor off, and all the code linking the logical representation and the graphics etc. (sound? network replication?) are done by the GameObject, so if you want to change how the logical object is rendered, all you need to do is change how the GameObject class is implemented.

Lets say if you have the network replication object (replicates the object based on data from the network) so you sometimes get the current outdated state of that object on the server.

What you could do, is have 2 LogicalGameObjects, the other existing in a local World, and the network replicated one in the ServerWorld. The GameObject would thus contain what the server saw some time ago and what you see. What the gameobject could do, is tell something (another class, ClientServerWorldsSmoothUnifier? xD) to try and make the local world smoothly match the server world, with prediction and all. (eg. SmoothlyUnifyWorldATowardsB(A,B) or SmoothlyUnifyATowardsBSoIfIShootItTheServerWontTryToTellMeHeWas2MetersAway(A,B))

So the GameObject would observe the "physics" (Logical version) and all and pass the relevant information between them so they all react correctly to each other, and allow you to remove such a component by just stopping passing data to it. (A bad way to do it would be to lets say play a sound directly in hit detection and draw it when the physics move it. Instead you want to tell the owner of the physical representation when those events happen so it can tell rendering and sound to do their thing.)

Controls (eg wasd for a character) also are a representation of the object, but a very shallow one. Pressing w for example tells that "The object tries to move forward", like the graphical representation is "The area occupied by the objects surface looks like this from this position in the world.", which is also shallow. Or the network tells "The objects position was this an unspecified amount of time ago, and heres some data that might help you figure out what happened during that time."

tl;dr:
{
MVC
*daydreaming mumble*
Separate logical (physics etc.), rendering, audio, network etc. representations of an object and have a higher class contain thouse components and pass relevant data from relevant components to components that use that data.
*daydreaming mumble*
*daydreaming mumble*
tl;dr section
}


Thanks for the reply, I have already setup a networking system and its probably much more simple as well as I am not dealing with a 3 dimensional environment. Basically the whole game is server-based except for the player/user itself (ive also handled so that clients can just fly everywhere with this system).

@Radikalizm I have not made a Drawer class for the menu state. I thought it was not really neccessary as I am not dealing with render targets and additional complexity there? What do you think about that?

Thanks, Xanather.

This topic is closed to new replies.

Advertisement