Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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.GamerServices;
- using Microsoft.Xna.Framework.Graphics;
- using Microsoft.Xna.Framework.Input;
- using Microsoft.Xna.Framework.Media;
- namespace GeneratorTest
- {
- public class Entity
- {
- public Vector2 Position;
- }
- /// <summary>
- /// This is the main type for your game
- /// </summary>
- public class Game1 : Microsoft.Xna.Framework.Game
- {
- GraphicsDeviceManager graphics;
- SpriteBatch spriteBatch;
- float currentDelta;
- List<Entity> entities = new List<Entity>();
- Texture2D tex;
- Stack<IEnumerator<object>> stack = new Stack<IEnumerator<object>>();
- public Game1()
- {
- graphics = new GraphicsDeviceManager(this);
- Content.RootDirectory = "Content";
- }
- /// <summary>
- /// Allows the game to perform any initialization it needs to before starting to run.
- /// This is where it can query for any required services and load any non-graphic
- /// related content. Calling base.Initialize will enumerate through any components
- /// and initialize them as well.
- /// </summary>
- protected override void Initialize()
- {
- base.Initialize();
- entities.Add(new Entity() { Position = new Vector2(100,100) });
- entities.Add(new Entity() { Position = new Vector2(300,100) });
- // Begin the cinematic.
- stack.Push(Cinematic().GetEnumerator());
- }
- /// <summary>
- /// LoadContent will be called once per game and is the place to load
- /// all of your content.
- /// </summary>
- protected override void LoadContent()
- {
- // Create a new SpriteBatch, which can be used to draw textures.
- spriteBatch = new SpriteBatch(GraphicsDevice);
- tex = Content.Load<Texture2D>("Sprite");
- }
- /// <summary>
- /// Allows the game to run logic such as updating the world,
- /// checking for collisions, gathering input, and playing audio.
- /// </summary>
- /// <param name="gameTime">Provides a snapshot of timing values.</param>
- protected override void Update(GameTime gameTime)
- {
- // Allows the game to exit
- if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
- this.Exit();
- currentDelta = (float)gameTime.ElapsedGameTime.Ticks / (float)TimeSpan.TicksPerSecond;
- // This is the complicated part.
- // When you run a generator you get an IEnumerable<>, then you have to call GetEnumerator()
- // to get an enumerator, then for an enumerator you can do the following to step through it:
- //
- // while(enumerator.MoveNext())
- // {
- // do something with enumerator.Current
- // }
- //
- // In our case, we actually wait a frame before calling MoveNext again.
- // Also, as a nicety, if the generator returns another IEnumerable<>, treat it like a "subroutine"
- // and begin stepping it until it's over, and then return to stepping the caller.
- // This is why this resembles a programming language stack behavior so much.
- if (stack.Count > 0)
- {
- IEnumerator<object> e = stack.Peek();
- if (e.MoveNext())
- {
- if (e.Current is IEnumerable<object>)
- {
- var newFrame = (IEnumerable<object>)e.Current;
- stack.Push(newFrame.GetEnumerator());
- }
- // otherwise it's probably null, ignore it
- }
- else
- {
- stack.Pop();
- }
- }
- base.Update(gameTime);
- }
- /// <summary>
- /// This is called when the game should draw itself.
- /// </summary>
- /// <param name="gameTime">Provides a snapshot of timing values.</param>
- protected override void Draw(GameTime gameTime)
- {
- GraphicsDevice.Clear(Color.CornflowerBlue);
- // Draw stuff
- spriteBatch.Begin();
- foreach (Entity ent in entities)
- {
- spriteBatch.Draw(tex, new Rectangle((int)ent.Position.X, (int)ent.Position.Y, 50, 50), Color.White);
- }
- spriteBatch.End();
- base.Draw(gameTime);
- }
- // Function that lets you wait for N seconds
- public IEnumerable<object> Wait(float seconds)
- {
- float t = 0;
- while (t < seconds)
- {
- t += currentDelta;
- yield return null;
- }
- }
- // Lerps an entity to the target position over N seconds
- public IEnumerable<object> MoveEntity(Entity ent, Vector2 targetPosition, float seconds)
- {
- Vector2 startPos = ent.Position;
- float t = 0;
- while (t < seconds)
- {
- ent.Position = Vector2.Lerp(startPos, targetPosition, t / seconds);
- t += currentDelta;
- yield return null;
- }
- ent.Position = targetPosition;
- }
- // This is the "cinematic" script
- // Notice how it almost looks like it just blocks, but it actually runs over several frames
- // Easier than dealing with an FSM
- public IEnumerable<object> Cinematic()
- {
- Entity a = entities[0];
- Entity b = entities[1];
- while (true)
- {
- yield return MoveEntity(a, new Vector2(100, 200), 1.0f);
- yield return Wait(0.25f);
- yield return MoveEntity(b, new Vector2(200, 200), 1.0f);
- yield return Wait(0.5f);
- yield return MoveEntity(b, new Vector2(100, 100), 0.5f);
- yield return MoveEntity(a, new Vector2(400, 200), 0.5f);
- yield return Wait(1.0f);
- yield return MoveEntity(a, new Vector2(100, 100), 0.2f);
- yield return MoveEntity(b, new Vector2(300, 100), 0.2f);
- }
- }
- }
- }
Add Comment
Please, Sign In to add comment