| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434 | //-----------------------------------------------------------------------------// DemoGame.cs//// Microsoft XNA Community Game Platform// Copyright (C) Microsoft Corporation. All rights reserved.//-----------------------------------------------------------------------------using System;using System.Collections.Generic;using System.Linq;using Microsoft.Xna.Framework;using Microsoft.Xna.Framework.Audio;using Microsoft.Xna.Framework.Content;using Microsoft.Xna.Framework.Graphics;using Microsoft.Xna.Framework.Input;using Microsoft.Xna.Framework.Input.Touch;using Microsoft.Xna.Framework.Media;namespace XnaGraphicsDemo{    /// <summary>    /// The main game class.    /// </summary>    public class DemoGame : Game    {        // Constants.        const float TransitionSpeed = 1.5f;        const float ZoomyTextLifespan = 0.75f;        // Properties.        public GraphicsDeviceManager Graphics { get; private set; }        public SpriteBatch SpriteBatch { get; private set; }        public SpriteFont Font { get; private set; }        public SpriteFont BigFont { get; private set; }        public Texture2D BlankTexture { get; private set; }        public Matrix ScaleMatrix { get; private set; }        // Fields.        List<MenuComponent> menuComponents = new List<MenuComponent>();        GameTime currentGameTime;        // Transition effects provide swooshy crossfades when moving from one screen to another.        float transitionTimer = float.MaxValue;        int transitionMode;        RenderTarget2D transitionRenderTarget;        // Zoomy text provides visual feedback when selecting menu items.        // This is implemented by the main game, rather than any individual menu        // screen, because the zoomy effect from selecting a menu item needs to        // display across the transition while that menu makes way for a new one.        class ZoomyText        {            public string Text;            public Vector2 Position;            public float Age;        }        static List<ZoomyText> zoomyTexts = new List<ZoomyText>();        const int BACK_BUFFER_WIDTH = 480;        const int BACK_BUFFER_HEIGHT = 640;        /// <summary>        /// Constructor.        /// </summary>        public DemoGame()        {            Content.RootDirectory = "Content";            Graphics = new GraphicsDeviceManager(this);            Graphics.PreferredBackBufferWidth = BACK_BUFFER_WIDTH;            Graphics.PreferredBackBufferHeight = BACK_BUFFER_HEIGHT;#if MOBILE            Graphics.IsFullScreen = true;#endif            IsMouseVisible = true;            TargetElapsedTime = TimeSpan.FromSeconds(1 / 30.0);            // Create all the different menu screens.            menuComponents.Add(new TitleMenu(this));            menuComponents.Add(new BasicDemo(this));            menuComponents.Add(new DualDemo(this));            menuComponents.Add(new AlphaDemo(this));            menuComponents.Add(new SkinnedDemo(this));            menuComponents.Add(new EnvmapDemo(this));            menuComponents.Add(new ParticleDemo(this));            // Set all the menu screens except the first to hidden and inactive.             foreach (MenuComponent component in menuComponents)            {                component.Enabled = component.Visible = false;                Components.Add(component);            }            // Make the title menu active and visible.            menuComponents[0].Enabled = menuComponents[0].Visible = true;        }        /// <summary>        /// Changes which menu screen is currently active.        /// </summary>        public void SetActiveMenu(int index)        {            // Trigger the transition effect.            for (int i = 0; i < menuComponents.Count; i++)            {                if (menuComponents[i].Visible)                {                    BeginTransition(i, index);                    break;                }            }            // Mark the previous menu as inactive, and the new one as active.            for (int i = 0; i < menuComponents.Count; i++)            {                menuComponents[i].Enabled = menuComponents[i].Visible = (i == index);                menuComponents[i].Reset();            }        }        /// <summary>        /// Loads content and creates graphics resources.        /// </summary>        protected override void LoadContent()        {            SpriteBatch = new SpriteBatch(GraphicsDevice);            Font = Content.Load<SpriteFont>("font");            BigFont = Content.Load<SpriteFont>("BigFont");            BlankTexture = new Texture2D(GraphicsDevice, 1, 1);            BlankTexture.SetData(new Color[] { Color.White });            transitionRenderTarget = new RenderTarget2D(GraphicsDevice, BACK_BUFFER_WIDTH, BACK_BUFFER_HEIGHT, false, SurfaceFormat.Color, DepthFormat.Depth24, 0, 0);        }        /// <summary>        /// Updates the transition effect and zoomy text animations.        /// </summary>        protected override void Update(GameTime gameTime)        {            currentGameTime = gameTime;            UpdateZoomyText(gameTime);            if (transitionTimer < float.MaxValue)                transitionTimer += (float)gameTime.ElapsedGameTime.TotalSeconds;            // This updates game components, including the currently active menu screen.            base.Update(gameTime);        }        /// <summary>        /// Draws the game.        /// </summary>        protected override void Draw(GameTime gameTime)        {            ScaleMatrix = Matrix.CreateScale(Graphics.PreferredBackBufferWidth / BACK_BUFFER_WIDTH, Graphics.PreferredBackBufferHeight / BACK_BUFFER_HEIGHT, 1);            // This draws game components, including the currently active menu screen.            base.Draw(gameTime);            DrawTransitionEffect();            DrawZoomyText();        }        /// <summary>        /// Begins a transition effect, capturing a copy of the current screen into the transitionRenderTarget.        /// </summary>        void BeginTransition(int oldMenuIndex, int newMenuIndex)        {            ScaleMatrix = Matrix.Identity;            GraphicsDevice.SetRenderTarget(transitionRenderTarget);            // Draw the old menu screen into the rendertarget.            menuComponents[oldMenuIndex].Draw(currentGameTime);            // Force the rendertarget alpha channel to fully opaque.            SpriteBatch.Begin(0, BlendState.Additive);            SpriteBatch.Draw(BlankTexture, new Rectangle(0, 0, BACK_BUFFER_WIDTH, BACK_BUFFER_HEIGHT), new Color(0, 0, 0, 255));            SpriteBatch.End();            GraphicsDevice.SetRenderTarget(null);            // Initialize the transition state.            transitionTimer = (float)TargetElapsedTime.TotalSeconds;            transitionMode = newMenuIndex;        }        /// <summary>        /// Draws the transition effect, displaying various animating pieces of the rendertarget        /// which contains the previous scene image over the top of the new scene. There are        /// various different effects which animate these pieces in different ways.        /// </summary>        void DrawTransitionEffect()        {            if (transitionTimer >= TransitionSpeed)                return;            SpriteBatch.Begin();            float mu = transitionTimer / TransitionSpeed;            float alpha = 1 - mu;            switch (transitionMode)            {                case 1:                    // BasicEffect                    DrawOpenCurtainsTransition(alpha);                    break;                case 2:                case 5:                    // DualTexture                    // EnvironmentMap                    DrawSpinningSquaresTransition(mu, alpha);                    break;                case 3:                case 4:                    // AlphaTest and Skinning                    DrawChequeredAppearTransition(mu);                    break;                case 6:                    // Particles                    DrawFallingLinesTransition(mu);                    break;                default:                    // Returning to menu.                    DrawShrinkAndSpinTransition(mu, alpha);                    break;            }            SpriteBatch.End();        }        /// <summary>        /// Transition effect where the screen splits in half, opening down the middle.        /// </summary>        void DrawOpenCurtainsTransition(float alpha)        {            int w = (int)(BACK_BUFFER_WIDTH / 2 * alpha * alpha);            SpriteBatch.Draw(transitionRenderTarget, new Rectangle(0, 0, w, BACK_BUFFER_HEIGHT), new Rectangle(0, 0, BACK_BUFFER_WIDTH / 2, BACK_BUFFER_HEIGHT), Color.White * alpha);            SpriteBatch.Draw(transitionRenderTarget, new Rectangle(BACK_BUFFER_WIDTH - w, 0, w, BACK_BUFFER_HEIGHT), new Rectangle(BACK_BUFFER_WIDTH / 2, 0, BACK_BUFFER_WIDTH / 2, BACK_BUFFER_HEIGHT), Color.White * alpha);        }        /// <summary>        /// Transition effect where the screen splits into pieces, each spinning off in a different direction.        /// </summary>        void DrawSpinningSquaresTransition(float mu, float alpha)        {            Random random = new Random(23);            for (int x = 0; x < 4; x++)            {                for (int y = 0; y < 8; y++)                {                    Rectangle rect = new Rectangle(BACK_BUFFER_WIDTH * x / 4, BACK_BUFFER_HEIGHT * y / 8, BACK_BUFFER_WIDTH / 4, BACK_BUFFER_HEIGHT / 8);                    Vector2 origin = new Vector2(rect.Width, rect.Height) / 2;                    float rotation = (float)(random.NextDouble() - 0.5) * mu * mu * 2;                    float scale = 1 + (float)(random.NextDouble() - 0.5f) * mu * mu;                    Vector2 pos = new Vector2(rect.Center.X, rect.Center.Y);                    pos.X += (float)(random.NextDouble() - 0.5) * mu * mu * BACK_BUFFER_HEIGHT / 2;                    pos.Y += (float)(random.NextDouble() - 0.5) * mu * mu * BACK_BUFFER_HEIGHT / 2;                    SpriteBatch.Draw(transitionRenderTarget, pos, rect, Color.White * alpha, rotation, origin, scale, 0, 0);                }            }        }        /// <summary>        /// Transition effect where each square of the image appears at a different time.        /// </summary>        void DrawChequeredAppearTransition(float mu)        {            Random random = new Random(23);            for (int x = 0; x < 8; x++)            {                for (int y = 0; y < 16; y++)                {                    Rectangle rect = new Rectangle(BACK_BUFFER_WIDTH * x / 8, BACK_BUFFER_HEIGHT * y / 16, BACK_BUFFER_WIDTH / 8, BACK_BUFFER_HEIGHT / 16);                    if (random.NextDouble() > mu * mu)                        SpriteBatch.Draw(transitionRenderTarget, rect, rect, Color.White);                }            }            // The zoomy text effect doesn't look so good with this            // particular transition effect, so we temporarily disable it.            zoomyTexts.Clear();        }        /// <summary>        /// Transition effect where the image dissolves into a sequence of vertically falling lines.        /// </summary>        void DrawFallingLinesTransition(float mu)        {            Random random = new Random(23);            const int segments = 60;            for (int x = 0; x < segments; x++)            {                Rectangle rect = new Rectangle(BACK_BUFFER_WIDTH * x / segments, 0, BACK_BUFFER_WIDTH / segments, BACK_BUFFER_HEIGHT);                Vector2 pos = new Vector2(rect.X, 0);                pos.Y += BACK_BUFFER_HEIGHT * (float)Math.Pow(mu, random.NextDouble() * 10);                SpriteBatch.Draw(transitionRenderTarget, pos, rect, Color.White);            }        }        /// <summary>        /// Transition effect where the image spins off toward the bottom left of the screen.        /// </summary>        void DrawShrinkAndSpinTransition(float mu, float alpha)        {            Vector2 origin = new Vector2(BACK_BUFFER_WIDTH / 2, BACK_BUFFER_HEIGHT / 2);            Vector2 translate = (new Vector2(32, BACK_BUFFER_HEIGHT - 32) - origin) * mu * mu;            float rotation = mu * mu * -4;            float scale = alpha * alpha;            Color tint = Color.White * (float)Math.Sqrt(alpha);            SpriteBatch.Draw(transitionRenderTarget, origin + translate, null, tint, rotation, origin, scale, 0, 0);        }        /// <summary>        /// Creates a new zoomy text menu item selection effect.        /// </summary>        public static void SpawnZoomyText(string text, Vector2 position)        {            zoomyTexts.Add(new ZoomyText { Text = text, Position = position });        }        /// <summary>        /// Updates the zoomy text animations.        /// </summary>        static void UpdateZoomyText(GameTime gameTime)        {            int i = 0;            while (i < zoomyTexts.Count)            {                zoomyTexts[i].Age += (float)gameTime.ElapsedGameTime.TotalSeconds;                if (zoomyTexts[i].Age >= ZoomyTextLifespan)                    zoomyTexts.RemoveAt(i);                else                    i++;            }        }        /// <summary>        /// Draws the zoomy text animations.        /// </summary>        void DrawZoomyText()        {            if (zoomyTexts.Count <= 0)                return;            SpriteBatch.Begin(0, null, null, null, null, null, ScaleMatrix);            foreach (ZoomyText zoomyText in zoomyTexts)            {                Vector2 pos = zoomyText.Position + Font.MeasureString(zoomyText.Text) / 2;                float age = zoomyText.Age / ZoomyTextLifespan;                float sqrtAge = (float)Math.Sqrt(age);                float scale = 0.333f + sqrtAge * 2f;                float alpha = 1 - age;                SpriteFont font = BigFont;                // Our BigFont only contains characters a-z, so if the text                // contains any numbers, we have to use the other font instead.                foreach (char ch in zoomyText.Text)                {                    if (char.IsDigit(ch))                    {                        font = Font;                        scale *= 2;                        break;                    }                }                Vector2 origin = font.MeasureString(zoomyText.Text) / 2;                SpriteBatch.DrawString(font, zoomyText.Text, pos, Color.Lerp(new Color(64, 64, 255), Color.White, sqrtAge) * alpha, 0, origin, scale, 0, 0);            }            SpriteBatch.End();        }    }}
 |