Move most of the drawing code into a Scene class

GitOrigin-RevId: 4515493a3bbf99b9513f2f1e66acadae1df53a5a
This commit is contained in:
Colin McMillen 2020-02-17 21:08:01 -05:00
parent 43f6bded70
commit 7e7b0f7715
3 changed files with 120 additions and 81 deletions

110
Shared/Scene.cs Normal file
View File

@ -0,0 +1,110 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace SemiColinGames {
class Scene {
Color backgroundColor = Color.CornflowerBlue;
readonly GraphicsDevice graphics;
readonly Camera camera;
readonly RenderTarget2D sceneTarget;
readonly RenderTarget2D lightingTarget;
readonly BasicEffect lightingEffect;
readonly SpriteBatch spriteBatch;
readonly SpriteFont font;
readonly Texture2D grasslandBg1;
readonly Texture2D grasslandBg2;
public Scene(GraphicsDevice graphics, Camera camera, ContentManager content) {
Enabled = false;
this.graphics = graphics;
this.camera = camera;
sceneTarget = new RenderTarget2D(
graphics, camera.Width, camera.Height, false /* mipmap */,
graphics.PresentationParameters.BackBufferFormat, DepthFormat.Depth24);
lightingTarget = new RenderTarget2D(
graphics, camera.Width, camera.Height, false /* mipmap */,
graphics.PresentationParameters.BackBufferFormat, DepthFormat.Depth24);
lightingEffect = new BasicEffect(graphics);
lightingEffect.World = Matrix.CreateTranslation(0, 0, 0);
lightingEffect.View = Matrix.CreateLookAt(Vector3.Backward, Vector3.Zero, Vector3.Up);
lightingEffect.VertexColorEnabled = true;
// TODO: handle unloading of resources when the level is done.
spriteBatch = new SpriteBatch(graphics);
font = content.Load<SpriteFont>("font");
grasslandBg1 = content.Load<Texture2D>("grassland_bg1");
grasslandBg2 = content.Load<Texture2D>("grassland_bg2");
}
public bool Enabled { get; set; }
public void Draw(World world, Player player, LinesOfSight linesOfSight) {
graphics.SetRenderTarget(null);
graphics.Clear(backgroundColor);
if (!Enabled) {
return;
}
graphics.SetRenderTarget(sceneTarget);
graphics.Clear(backgroundColor);
// Draw scene to sceneTarget.
spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.LinearWrap, null, null);
// Draw background.
Color bgBlend = Color.FromNonPremultiplied(new Vector4(1, 1, 1, 0.5f));
Rectangle bgSource = new Rectangle(
(int) (camera.Left * 0.25), 0, camera.Width, camera.Height);
Rectangle bgTarget = new Rectangle(0, 0, camera.Width, camera.Height);
spriteBatch.Draw(grasslandBg2, bgTarget, bgSource, bgBlend);
bgSource = new Rectangle(
(int) (camera.Left * 0.5), 0, camera.Width, camera.Height);
spriteBatch.Draw(grasslandBg1, bgTarget, bgSource, bgBlend);
spriteBatch.End();
// Set up transformation matrix for drawing world objects.
Matrix transform = Matrix.CreateTranslation(-camera.Left, -camera.Top, 0);
spriteBatch.Begin(
SpriteSortMode.Deferred, null, SamplerState.LinearWrap, null, null, null, transform);
// Draw foreground tiles.
world.Draw(spriteBatch);
// Draw player.
player.Draw(spriteBatch);
// Aaaaand we're done.
spriteBatch.End();
// Draw lighting to lightingTarget.
graphics.SetRenderTarget(lightingTarget);
graphics.Clear(new Color(0, 0, 0, 0f));
lightingEffect.Projection = camera.Projection;
linesOfSight.Draw(player, world.CollisionTargets, graphics, lightingEffect);
// Draw debug rects & lines on top.
Debug.Draw(graphics, lightingEffect);
// Draw sceneTarget to screen.
graphics.SetRenderTarget(null);
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend,
SamplerState.PointClamp, DepthStencilState.Default,
RasterizerState.CullNone);
Rectangle drawRect = new Rectangle(
0, 0, graphics.Viewport.Width, graphics.Viewport.Height);
spriteBatch.Draw(sceneTarget, drawRect, Color.White);
spriteBatch.Draw(lightingTarget, drawRect, Color.White);
// Draw debug toasts.
Debug.DrawToasts(spriteBatch, font);
spriteBatch.End();
}
}
}

View File

@ -21,6 +21,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Line.cs" />
<Compile Include="$(MSBuildThisFileDirectory)LinesOfSight.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Player.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Scene.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SneakGame.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Timer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)World.cs" />

View File

@ -11,13 +11,7 @@ namespace SemiColinGames {
const double TARGET_FRAME_TIME = 1.0 / TARGET_FPS;
readonly GraphicsDeviceManager graphics;
RenderTarget2D sceneTarget;
RenderTarget2D lightingTarget;
BasicEffect lightingEffect;
SpriteBatch spriteBatch;
SpriteFont font;
bool fullScreen = false;
bool paused = false;
IDisplay display;
@ -30,10 +24,9 @@ namespace SemiColinGames {
// Draw() needs to be called without IsRunningSlowly this many times before we actually
// attempt to draw the scene. This is a workaround for the fact that otherwise the first few
// frames can be really slow to draw.
int framesToSuppress = 2;
Texture2D grasslandBg1;
Texture2D grasslandBg2;
int framesToSuppress;
Scene scene;
Player player;
World world;
LinesOfSight linesOfSight;
@ -58,18 +51,6 @@ namespace SemiColinGames {
Debug.Initialize(GraphicsDevice);
sceneTarget = new RenderTarget2D(
GraphicsDevice, camera.Width, camera.Height, false /* mipmap */,
GraphicsDevice.PresentationParameters.BackBufferFormat, DepthFormat.Depth24);
lightingTarget = new RenderTarget2D(
GraphicsDevice, camera.Width, camera.Height, false /* mipmap */,
GraphicsDevice.PresentationParameters.BackBufferFormat, DepthFormat.Depth24);
lightingEffect = new BasicEffect(GraphicsDevice);
lightingEffect.World = Matrix.CreateTranslation(0, 0, 0);
lightingEffect.View = Matrix.CreateLookAt(Vector3.Backward, Vector3.Zero, Vector3.Up);
lightingEffect.VertexColorEnabled = true;
RasterizerState rasterizerState = new RasterizerState() {
CullMode = CullMode.None
};
@ -81,18 +62,16 @@ namespace SemiColinGames {
// Called once per game. Loads all game content.
protected override void LoadContent() {
base.LoadContent();
spriteBatch = new SpriteBatch(GraphicsDevice);
font = Content.Load<SpriteFont>("font");
linesOfSight = new LinesOfSight(GraphicsDevice);
grasslandBg1 = Content.Load<Texture2D>("grassland_bg1");
grasslandBg2 = Content.Load<Texture2D>("grassland_bg2");
LoadLevel();
}
private void LoadLevel() {
framesToSuppress = 2;
camera = new Camera();
player = new Player(Content.Load<Texture2D>("Ninja_Female"));
world = new World(Content.Load<Texture2D>("grassland"), Levels.ONE_ONE);
scene = new Scene(GraphicsDevice, camera, Content);
}
// Called once per game. Unloads all game content.
@ -145,8 +124,12 @@ namespace SemiColinGames {
protected override void Draw(GameTime gameTime) {
drawTimer.Start();
// Enable the scene after we've gotten enough non-slow frames.
if (framesToSuppress > 0 && !gameTime.IsRunningSlowly) {
framesToSuppress--;
if (framesToSuppress == 0) {
scene.Enabled = true;
}
}
// We need to update the FPS counter in Draw() since Update() might get called more
@ -160,62 +143,7 @@ namespace SemiColinGames {
Debug.SetFpsText(fpsText);
// Draw scene to sceneTarget.
GraphicsDevice.SetRenderTarget(sceneTarget);
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.LinearWrap, null, null);
// Draw background.
Color bgBlend = Color.FromNonPremultiplied(new Vector4(1, 1, 1, 0.5f));
Rectangle bgSource = new Rectangle(
(int) (camera.Left * 0.25), 0, camera.Width, camera.Height);
Rectangle bgTarget = new Rectangle(0, 0, camera.Width, camera.Height);
spriteBatch.Draw(grasslandBg2, bgTarget, bgSource, bgBlend);
bgSource = new Rectangle(
(int) (camera.Left * 0.5), 0, camera.Width, camera.Height);
spriteBatch.Draw(grasslandBg1, bgTarget, bgSource, bgBlend);
spriteBatch.End();
// Set up transformation matrix for drawing world objects.
Matrix transform = Matrix.CreateTranslation(-camera.Left, -camera.Top, 0);
spriteBatch.Begin(
SpriteSortMode.Deferred, null, SamplerState.LinearWrap, null, null, null, transform);
// Draw foreground tiles.
world.Draw(spriteBatch);
// Draw player.
player.Draw(spriteBatch);
// Aaaaand we're done.
spriteBatch.End();
// Draw lighting to lightingTarget.
GraphicsDevice.SetRenderTarget(lightingTarget);
GraphicsDevice.Clear(new Color(0, 0, 0, 0f));
lightingEffect.Projection = camera.Projection;
linesOfSight.Draw(player, world.CollisionTargets, GraphicsDevice, lightingEffect);
// Draw debug rects & lines on top.
Debug.Draw(GraphicsDevice, lightingEffect);
// Draw sceneTarget to screen.
GraphicsDevice.SetRenderTarget(null);
GraphicsDevice.Clear(Color.CornflowerBlue);
if (framesToSuppress == 0) {
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend,
SamplerState.PointClamp, DepthStencilState.Default,
RasterizerState.CullNone);
Rectangle drawRect = new Rectangle(
0, 0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);
spriteBatch.Draw(sceneTarget, drawRect, Color.White);
spriteBatch.Draw(lightingTarget, drawRect, Color.White);
// Draw debug toasts.
Debug.DrawToasts(spriteBatch, font);
spriteBatch.End();
}
scene.Draw(world, player, linesOfSight);
base.Draw(gameTime);
drawTimer.Stop();