Should subjects be able to draw themselves?

A bit of a simple question, but I'm not sure about that. This is mainly in the context of the development of the game. Say you had an entity, like a ship or character. Should (and I know this is a matter of opinion) this object contain a Draw method? (maybe implement the IDrawable interface)

When looking at the source code in some game projects, I see that this is done in so many ways. Sometimes there is a separate class that can take a basic Entity object and draw it, given its properties (texture, location, etc.). In other cases, the subject is assigned his own drawing method, and they can do it themselves.

I hope this question is not too subjective. Sometimes I hear people say that things like painting should be completely separate from objects, and they shouldn't know how to draw themselves or be able to. Some of them are more pragmatic and feel such a design where objects have this ability.

I am not too confident. I did not find such questions for this, because it may be a little subjective or any method is in order, but I would like to hear what I have to say about it, because such design decisions daily reflect my development. These small decisions, such as the question of whether object A should be able to perform function B or whether it violates some design principles.

Iā€™m sure that some will say that, if necessary, go with my gut and refactor later, but this is what I did, and now I would like to hear a real solution theory when certain objects should support certain capabilities.

I assume that I am looking for some heuristics to determine how much authority a given object should have.

+6
source share
4 answers

You have to go with what makes your implementation the easiest. Even if it turns out that you made the wrong choice, you will first find out why one method is better than another and can apply this knowledge in the future. This is valuable knowledge to help you make decisions later. I find that one of the best ways to learn something in something is to do it wrong several times (not specifically for you) so that you can understand the pitfalls of the approach well.

The way I process this is as follows: the entity has all the information about it that is required to draw it. for example the episodes that make it up, where they are located relative to the center of the entity. Essence itself does very little, if anything. This is just a place to store information on which other systems work.

The visualization code in the world processes both the world and all entities. He looks at this entity and draws each of his sprites in the right place, applying any necessary camera transforms or effects or something-you.

This is how most of my game works. Essence has no idea about physics. All this is a dataset that other systems work with. He does not know about physics, but he has some Box2D structures that hang from him, which Box2D works during the physics update phase. Same thing with AI or Input and everything else.

+3
source

Each method has pros and cons.

The advantage of providing facilities:

It is more convenient for both sides. the person writing the engine just needs to call the function, and the person using it, writing these IDrawable classes, has low-level access to everything they need. If you want to create a system in which each object must determine what it looks like, what shaders and textures it will use, and how to apply any special effects. You will have either a rather complicated system or a very limited one.

The advantage of managing rendering and drawing objects

All modern 3D gaming engines do this for a very good reason. If the renderer has full control over which textures are connected, which models to use, and which shaders are active, it can optimize. Let's say you had a lot of objects with the same shader. The renderer can install the shader once and display everything in one batch! You cannot do this if each object itself is drawn.

Conclusion

For small projects, it's fine for each object to draw on its own. This is actually more convenient. If you really need performance and you want to squeeze everything out of your video card, you need a renderer that has strict control over what is visualized and how, so that it can optimize.

+3
source

I assume that I am looking for some heuristics to determine how many powers a given object should have.

I would replace authority with responsibility, and then the answer was ONE. The responsibility for both the behavior and the drawing of the ship seems to me too much.

+1
source

It depends on what you mean by "draw yourself." If you mean, if it contains low-level routines involving pixels or triangles, then probably not.

My suggestion:

  • One class to represent the behavior of an object (motion, AI, whatever)
  • One class to represent the appearance of an object
  • One class for defining an object as a combination of appearance and behavior

If the "appearance" includes some kind of custom drawing procedure, which may be in this class. In general, although the drawing could be abstracted from the core API, perhaps using a strategy, a visitor, or some IoC template, the object would be drawn by some rendering manager. This is especially true in game design, where things such as sharing textures to / from video memory and drawing things in the correct order are important; something should be able to optimize things above the level of the object.

To try to be more specific, one part of your object graph (the object itself or the object break) implements IRenderable , has a Draw(IRenderEngine) method, and that IRenderEngine provides IRenderable access to methods such as IRenderable t24>, CreateParticleEffect or whatever. Optimizing or measuring your engine and algorithms will be much easier, and if you need to swap engines or rewrite them in an uncontrolled, high-performance way (or port to another platform), just create a new implementation of IRenderEngine .

Hint: if you do this, you can have many things that look the same / similar, but act differently, replacing the behavior, or many things that look different, but act the same. You can also have the behavior of things on the server, and the look is happening on the client.

I did something very similar to this before. Each object class had a base class that contained the properties used on the client, but on the server it was a derived instance of this class that was created and included behavior (movement, simulation, etc.). The class also had a factory method for providing its associated IRenderable interface (appearance). In fact, in the end there was a fairly effective multiplayer game engine.

+1
source

Source: https://habr.com/ru/post/899253/


All Articles