Recently I decided to start optimizing code in the game development field.
I found this pacman project on github a good starting point: https://github.com/LucaFeggi/PacMan_SDL/tree/main
I found a lot of things that deserve an optimization. One of the most things that caught my attention is that a lot of classes have their Draw
(render) method inside them, such as Pac
, Ghost
, Fruit
classes...
So I decided to make a Renderer
class, and move to it the Draw
method and the appropriate fields that the latter works on.
Let us take the Pac
class inside the PacRenderer.hpp
as an example, to clarify things:
class Pac : public Entity{
public:
Pac();
~Pac();
void UpdatePos(std::vector<unsigned char> &mover, unsigned char ActualMap[]);
unsigned char FoodCollision(unsigned char ActualMap[]);
bool IsEnergized();
void ChangeEnergyStatus(bool NewEnergyStatus);
void SetFacing(unsigned char mover);
bool IsDeadAnimationEnded();
void ModDeadAnimationStatement(bool NewDeadAnimationStatement);
void UpdateCurrentLivingPacFrame();
void ResetCurrentLivingFrame();
void WallCollisionFrame();
void Draw();
private:
LTexture LivingPac;
LTexture DeathPac;
SDL_Rect LivingPacSpriteClips[LivingPacFrames];
SDL_Rect DeathPacSpriteClips[DeathPacFrames];
unsigned char CurrLivingPacFrame;
unsigned char CurrDeathPacFrame;
bool EnergyStatus;
bool DeadAnimationStatement;
};
So according to what I described above, the PacRenderer
class will be:
class PacRenderer {
public:
PacRenderer(std::shared_ptr<Pac> pac);
void Draw();
private:
LTexture LivingPac;
LTexture DeathPac;
SDL_Rect LivingPacSpriteClips[LivingPacFrames];
SDL_Rect DeathPacSpriteClips[DeathPacFrames];
}
PacRenderer::PacRenderer(std::shared_ptr<Pac> pac)
{
this->pac = pac;
//loading textures here instead of in the Fruit class
LivingPac.loadFromFile("Textures/PacMan32.png");
DeathPac.loadFromFile("Textures/GameOver32.png");
InitFrames(LivingPacFrames, LivingPacSpriteClips);
InitFrames(DeathPacFrames, DeathPacSpriteClips);
}
After moving Draw()
and 4 fields from the Pac
class.
At the beginning, I thought that it is a very good optimization, and separation between game logic and graphics rendering.
Until I read this question and its right answer: How should renderer class relate to the class it renders?
I found that what the right answer describes as
you're just taking a baby step away from "objects render themselves" rather than moving all the way to an approach where something else renders the objects
applies exactly to my solution.
So I want to verify if this description really apply to my solution.
Is my solution good, did I actually separate game logic from graphics rendering?
If not, what is the best thing to do in this case?