Obviously, if we want to draw a Pong paddle, we will need a Texture2D that represents the paddle. A Pong paddle is just a white rectangle. One approach we could take is open up an image editor, draw a white rectangle, save it to a PNG file, and then tell our game to load it. That sounds annoying though - what if we want to tweak the dimensions slightly? We have to repeat the entire process. That's a lot of work just to draw a silly rectangle.
We haven't seen `RenderTarget2D` yet. Basically, a render target is a special kind of texture that we can draw to *instead* of drawing directly to the screen. These can come in extremely handy for many use cases, like generating textures at runtime and creating fullscreen post-processing effects.
*GraphicsDevice* is an instance attached to the Game class. It basically represents the handle that our program has to the device on our computer that will be handling the draw calls. All draw-related operations will be going through the GraphicsDevice. GraphicsDevice is guaranteed to be initialized by the time LoadContent is called, so we will be doing our graphics-related initialization work in there.
First, we create a SpriteBatch instance. We can re-use the same SpriteBatch instance for each batch we need, so we'll just create one of these and re-use it throughout our game.
First, we instantiate our PaddleTexture render target. Then, we set the current render target to PaddleTexture. This means that all draw calls will now draw to this texture instead of to the screen. Next, we begin the SpriteBatch, draw our white pixel to a rectangle of size 20x80, and end the SpriteBatch. Finally, setting the current render target back to `null` means that draw calls will go to the screen.
Finally, we create a new Texture2DComponent using our PaddleTexture, and put it on layer 0. This is attached to the paddle entity with SetComponent as well.
We set up our Renderers before we create any entities and components. We give our SpriteBatch instance to the new Texture2DRenderer. WorldBuilder.AddOrderedRenderer tells the World to use this Renderer. That's it!
We have one little bit of housekeeping to take care of before we can run the game. SpriteBatch can only draw after Begin has been called, and it must call End before anything will draw to the screen. Recall that our Texture2DRenderer does not call Begin or End, because that would only batch one Texture2D at a time, which is very inefficient.
SpriteSortMode.Deferred is the most efficient SpriteBatch drawing mode. It waits as long as possible to send data to the GPU. BlendState.NonPremultiplied is a "blend mode". We will talk more about these later on, but feel free to read about them on your own. There are better ways we might need to structure our SpriteBatch Begins and Ends, but this will do just fine for now.