public override void Draw(GameTime gameTime, Frame frame)
{
ClearBatch.AddNew(frame, 4, Materials.Clear, clearColor: new Color(16, 32, 48));
var alphaGeometry = Materials.Get(Materials.ScreenSpaceGeometry, blendState: BlendState.AlphaBlend);
using (var gb = GeometryBatch.New(frame, 5, alphaGeometry)) {
gb.AddGradientFilledQuad(
Vector2.Zero, new Vector2(Graphics.PreferredBackBufferWidth, Graphics.PreferredBackBufferHeight),
Color.DarkSlateGray, Color.DarkSlateGray,
Color.SlateBlue, Color.SlateBlue
);
}
using (var gb = GeometryBatch.New(frame, 6, alphaGeometry)) {
var alphaBlack = new Color(0, 0, 0, 192);
var alphaBlack2 = new Color(0, 0, 0, 64);
gb.AddQuadBorder(
Playfield.Bounds.TopLeft + new Vector2(32 + 24, 0),
Playfield.Bounds.BottomRight + new Vector2(-32 - 24, 0),
alphaBlack2, alphaBlack, 24
);
}
// Render the contents of the trail buffer to the screen using additive blending
using (var bb = BitmapBatch.New(frame, 7, Materials.Trail)) {
bb.Add(new BitmapDrawCall(
TrailBuffer, Vector2.Zero, (float)TrailScale
));
}
// Render the paddles and ball to both the framebuffer and the trail buffer (note the different layer values)
using (var gb = GeometryBatch.New(frame, 8, alphaGeometry))
using (var gb2 = GeometryBatch.New(frame, 9, alphaGeometry))
using (var trailBatch = GeometryBatch.New(frame, 2, alphaGeometry)) {
foreach (var paddle in Paddles) {
gb.AddFilledQuad(
paddle.Bounds.TopLeft, paddle.Bounds.BottomRight, Color.White
);
gb2.AddQuadBorder(
paddle.Bounds.TopLeft, paddle.Bounds.BottomRight, Color.Black, Color.Black, 2.25f
);
trailBatch.AddFilledQuad(
paddle.Bounds.TopLeft, paddle.Bounds.BottomRight, Color.White
);
}
gb.AddFilledRing(Ball.Position, 0.0f, Ball.Radius, Color.White, Color.White);
gb2.AddFilledRing(Ball.Position, Ball.Radius, Ball.Radius + 2.0f, Color.Black, Color.Black);
trailBatch.AddFilledRing(Ball.Position, 0.0f, Ball.Radius, Color.White, Color.White);
}
// Render the score values using a stringbatch (unfortunately this uses spritebatch to render spritefonts :( )
{
var ir = new ImperativeRenderer(frame, Materials, 10, blendState: BlendState.AlphaBlend);
ir.DrawString(
Font, String.Format("Player 1: {0:00}", Scores[0]),
new Vector2(16, 16)
);
var player2Text = String.Format("Player 2: {0:00}", Scores[1]);
ir.DrawString(
Font, player2Text,
new Vector2(Graphics.PreferredBackBufferWidth - 16 - Font.MeasureString(player2Text).X, 16)
);
}
// The first stage of our frame involves selecting the trail buffer as our render target (note that it's layer 0)
SetRenderTargetBatch.AddNew(frame, 0, TrailBuffer);
if (FirstFrame) {
// If it's the first time we've rendered, we erase the trail buffer since it could contain anything
ClearBatch.AddNew(frame, 1, Materials.Clear, clearColor: Color.Black);
FirstFrame = false;
} else {
// Otherwise, we fade out the contents of the trail buffer
using (var gb = GeometryBatch.New(frame, 1, Materials.SubtractiveGeometry)) {
gb.AddFilledQuad(
new Bounds(Vector2.Zero, new Vector2(Graphics.PreferredBackBufferWidth, Graphics.PreferredBackBufferHeight)),
new Color(12, 12, 12, 0)
);
}
}
// After the trail buffer has been updated, we turn it off and begin rendering to the framebuffer. Note layer 3.
SetRenderTargetBatch.AddNew(frame, 3, null);
}