It sounds like 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. When objects render themselves, every object (in this case a paddle, a ball, et cetera) has a draw
method and some corresponding data. In your case you just appear to be moving that method and state into its own class, so you'd still have a PaddleRenderer
and a BallRenderer
and so on. I would argue this is inferior, as it doesn't really solve many of the problems associated with the "objects render themselves" approach.
Instead, I would encourage you to think more broadly: generally you can visually represent things in one of two broad classes: sprites or 3D meshes. Your renderer should know how to render sprites, and it should know how to render meshes. Let's say for simplicity everything in your game is represented and rendered as sprites. So you create a Sprite
class that contains all the needed properties: references to textures, animation sequence information and current state, position, current sequence index, current frame index, et cetera.
Then you give your Paddle
a Sprite*
, and you give you Ball
a Sprite*
, and you configure the data on each sprite to be appropriate for the ball, or the paddle, or whatever else you want to put in the game. But the renderer just has this big homogeneous list of Sprite
objects to render and that's all it concerns itself with.
Every tick of the game logic, you update the ball's position and the paddle positions and all of that. Once the logic tick completes, before you actually render, you can simply copy that position information into the appropriate sprite member before rendering. Likewise with any other state (for example maybe you update the sprite's tint color randomly every time the ball hits a paddle, for a psychedelic effect).
This approaches makes the "renderer" subordinate to the game logic, but that's reasonable. Generally in a game you'll have user input which directs the game logic, and then game logic which directs the rendering. Information (and responsibility) flows along those paths, but it generally does not flow in the other direction (the renderer usually does not influence the state of the game logic).