diff --git a/Shared/SpiderScene.cs b/Shared/SpiderScene.cs new file mode 100644 index 0000000..2ba14e8 --- /dev/null +++ b/Shared/SpiderScene.cs @@ -0,0 +1,96 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System; +using System.Collections.Generic; + +namespace SemiColinGames { + public sealed class SpiderScene : IScene { + + const float DESIRED_ASPECT_RATIO = 1920.0f / 1080.0f; + + private readonly Color letterboxColor = Color.Blue; + private readonly Color backgroundColor = Color.Black; + + private readonly GraphicsDevice graphics; + private readonly RenderTarget2D sceneTarget; + private readonly SpriteBatch spriteBatch; + private readonly BasicEffect basicEffect; + + public SpiderScene(GraphicsDevice graphics, Point worldSize) { + this.graphics = graphics; + + sceneTarget = new RenderTarget2D( + graphics, worldSize.X, worldSize.Y, false /* mipmap */, + graphics.PresentationParameters.BackBufferFormat, DepthFormat.Depth24); + spriteBatch = new SpriteBatch(graphics); + + basicEffect = new BasicEffect(graphics) { + World = Matrix.CreateTranslation(0, 0, 0), + View = Matrix.CreateLookAt(Vector3.Backward, Vector3.Zero, Vector3.Up), + VertexColorEnabled = true + }; + } + + ~SpiderScene() { + Dispose(); + } + + public void Dispose() { + sceneTarget.Dispose(); + spriteBatch.Dispose(); + basicEffect.Dispose(); + GC.SuppressFinalize(this); + } + + public void Draw(bool isRunningSlowly, IWorld iworld, bool paused) { + SpiderWorld world = (SpiderWorld) iworld; + + // Draw scene to sceneTarget. + graphics.SetRenderTarget(sceneTarget); + graphics.Clear(backgroundColor); + + spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, + SamplerState.PointClamp, DepthStencilState.Default, + RasterizerState.CullNone); + + foreach (SpiderWorld.Anchor anchor in world.Anchors) { + anchor.Draw(spriteBatch); + } + + world.Player.Draw(spriteBatch); + + // Finish drawing sprites. + spriteBatch.End(); + + // Get ready to draw sceneTarget to screen. + graphics.SetRenderTarget(null); + graphics.Clear(letterboxColor); + + // Letterbox the scene if needed. + float aspectRatio = 1.0f * graphics.Viewport.Width / graphics.Viewport.Height; + Rectangle drawRect; + if (aspectRatio > DESIRED_ASPECT_RATIO) { + // Need to letterbox the sides. + int desiredWidth = (int) (graphics.Viewport.Height * DESIRED_ASPECT_RATIO); + int padding = (graphics.Viewport.Width - desiredWidth) / 2; + drawRect = new Rectangle(padding, 0, desiredWidth, graphics.Viewport.Height); + } else { + // Need to letterbox the top / bottom. + int desiredHeight = (int) (graphics.Viewport.Width / DESIRED_ASPECT_RATIO); + int padding = (graphics.Viewport.Height - desiredHeight) / 2; + drawRect = new Rectangle(0, padding, graphics.Viewport.Width, desiredHeight); + } + + // Actually draw to screen. + spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, + SamplerState.PointClamp, DepthStencilState.Default, + RasterizerState.CullNone); + spriteBatch.Draw(sceneTarget, drawRect, Color.White); + + // Draw debug toasts. + Debug.DrawToasts(spriteBatch); + + spriteBatch.End(); + } + } +} diff --git a/Shared/SpiderWorld.cs b/Shared/SpiderWorld.cs new file mode 100644 index 0000000..b43e88c --- /dev/null +++ b/Shared/SpiderWorld.cs @@ -0,0 +1,83 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System; +using System.Collections.Generic; + +namespace SemiColinGames { + public sealed class SpiderWorld : IWorld { + + public class Spider { + public TextureRef Texture = Textures.Yellow2; + public Vector2 Position; + private Vector2 anchor; + private float radius; + private float angle; + private float momentum = -400; // radians / second * pixels + + public Spider(float x, float y, float radius, float angle) { + Position = new Vector2(); + anchor = new Vector2(x, y); + this.angle = angle; + this.radius = radius; + } + + public void Update(float modelTime, History input) { + radius += 100 * modelTime * input[0].Motion.Y; + radius = Math.Clamp(radius, 10, 300); + float angleChange = modelTime * momentum / radius; + angle += angleChange; + float x = anchor.X + radius * (float) Math.Sin(angle); + float y = anchor.Y + radius * (float) Math.Cos(angle); + Position.X = x; + Position.Y = y; + } + + public void Draw(SpriteBatch spriteBatch) { + Texture2D texture = Texture.Get; + Vector2 spriteCenter = new Vector2(texture.Width / 2, texture.Height / 2); + Vector2 drawPos = Vector2.Floor(Vector2.Subtract(Position, spriteCenter)); + spriteBatch.Draw(texture, drawPos, Color.White); + } + } + + public class Anchor { + public TextureRef Texture = Textures.Blue1; + public Vector2 Position; + + public Anchor(float x, float y) { + Position = new Vector2(x, y); + } + + public void Draw(SpriteBatch spriteBatch) { + Texture2D texture = Texture.Get; + Vector2 spriteCenter = new Vector2(texture.Width / 2, texture.Height / 2); + Vector2 drawPos = Vector2.Floor(Vector2.Subtract(Position, spriteCenter)); + spriteBatch.Draw(texture, drawPos, Color.White); + } + } + + public readonly Rectangle Bounds; + public Spider Player; + public ProfilingList Anchors; + + public SpiderWorld() { + Bounds = new Rectangle(0, 0, 1280, 720); + Player = new Spider(1280 / 2, 720 / 2, 200, 0); + + Anchors = new ProfilingList(100, "anchors"); + Anchors.Add(new Anchor(1280 / 2, 720 / 2)); + } + + ~SpiderWorld() { + Dispose(); + } + + public void Dispose() { + GC.SuppressFinalize(this); + } + + public void Update(float modelTime, History input) { + Player.Update(modelTime, input); + } + } +}