Advertisement
SteelGolem

ano sekai - simple warcraft-style unit selection and movemen

Oct 19th, 2016
172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.64 KB | None | 0 0
  1. /*
  2.     You can move the player sprite with WASD and use the mouse to click on the maids to select them. Ctrl-clicking selects multiple maids (it acts as a toggle, so you can deselect the same way). Clicking the ground (nothing) clears what you had selected. Right clicking will send selected maids to that position.
  3.     Game1.cs needs major overhauls and a metric ton of commenting still.
  4. */
  5.  
  6. // ================================ /2d api/Sprite.cs ================================
  7.  
  8. using System;
  9. using Microsoft.Xna.Framework;
  10. using Microsoft.Xna.Framework.Graphics;
  11.  
  12. namespace ano_sekai
  13. {
  14.     /// <summary>
  15.     /// A simple sprite element.
  16.     /// </summary>
  17.     public class Sprite
  18.     {
  19.         /// <summary>
  20.         /// Top left corner of the sprite.
  21.         /// </summary>
  22.         public Vector2 pos;
  23.  
  24.         /// <summary>
  25.         /// Size of the sprite. X is the width, Y is the height.
  26.         /// </summary>
  27.         public Vector2 size;
  28.  
  29.         /// <summary>
  30.         /// Rectangle to copy from the sprite sheet when drawing.
  31.         /// </summary>
  32.         public Rectangle srcRect;
  33.  
  34.         /// <summary>
  35.         /// Texture atlas containing all of the sprite graphics.
  36.         /// </summary>
  37.         public static Texture2D Sheet = null;
  38.  
  39.         /// <summary>
  40.         /// Creates a new sprite.
  41.         /// </summary>
  42.         /// <param name="srcRect">Rectangle to copy from the sprite sheet when drawing.</param>
  43.         /// <param name="pos">Top left corner of the sprite.</param>
  44.         /// <param name="size">Size of the sprite. X is the width, Y is the height.</param>
  45.         public Sprite(Rectangle srcRect, Vector2 pos, Vector2 size)
  46.         {
  47.             this.srcRect = srcRect; this.pos = pos; this.size = size;
  48.         }
  49.  
  50.         public void Update(GameTime gameTime)
  51.         {
  52.             // nothing to update yet, but when animations are put in, we'll need this
  53.         }
  54.  
  55.         public Rectangle GetDestRect()
  56.         {
  57.             return new Rectangle((int)pos.X, (int)pos.Y, (int)size.X, (int)size.Y);
  58.         }
  59.  
  60.         /// <summary>
  61.         /// Draws the sprite using the given SpriteBatch.
  62.         /// </summary>
  63.         /// <param name="spriteBatch">SpriteBatch to draw with.</param>
  64.         public void Draw(SpriteBatch spriteBatch)
  65.         {
  66.             // TODO: throw exception if Sprite.sheet is null
  67.  
  68.             // using destination rectangle in SpriteBatch.Draw to keep things simple
  69.             spriteBatch.Draw(Sheet, GetDestRect(), srcRect, Color.White);
  70.         }
  71.     }
  72. }
  73.  
  74. // ================================ /engine/GameObject.cs ================================
  75.  
  76. using System;
  77. using Microsoft.Xna.Framework;
  78.  
  79. namespace ano_sekai
  80. {
  81.     public class GameObject
  82.     {
  83.         // don't derive game object classes from sprites
  84.         // -> once Sprite gets alot of public functions and variables, it'll clutter
  85.         //      intellisense for game objects too
  86.         /// <summary>
  87.         /// The sprite instance associated with the game object.
  88.         /// </summary>
  89.         public Sprite sprite;
  90.  
  91.         // the sprite position and the game position are seperate, even if they're usually the same
  92.         /// <summary>
  93.         /// The position of the game object.
  94.         /// </summary>
  95.         public Vector2 pos;
  96.  
  97.         /// <summary>
  98.         /// Updates a game object's logic and sprite. Override in child classes.
  99.         /// </summary>
  100.         /// <param name="gameTime"></param>
  101.         public virtual void Update(GameTime gameTime) { sprite.Update(gameTime); }
  102.     }
  103. }
  104.  
  105. // ================================ /engine/Input.cs ================================
  106.  
  107. using System;
  108. using Microsoft.Xna.Framework;
  109. using Microsoft.Xna.Framework.Content;
  110. using Microsoft.Xna.Framework.Graphics;
  111. using Microsoft.Xna.Framework.Input;
  112.  
  113. namespace ano_sekai
  114. {
  115.     public class Input
  116.     {
  117.         public static KeyboardState keyboard, lastKeyboard;
  118.         public static MouseState mouse, lastMouse;
  119.         public static GamePadState gamepad, lastGamepad;
  120.  
  121.         public static void Update()
  122.         {
  123.             lastKeyboard = keyboard;
  124.             keyboard = Keyboard.GetState();
  125.             lastMouse = mouse;
  126.             mouse = Mouse.GetState();
  127.             lastGamepad = gamepad;
  128.             gamepad = GamePad.GetState(PlayerIndex.One);
  129.         }
  130.     }
  131. }
  132.  
  133. // ================================ /Game1.cs ================================
  134.  
  135. using System;
  136. using System.Collections.Generic;
  137. using Microsoft.Xna.Framework;
  138. using Microsoft.Xna.Framework.Content;
  139. using Microsoft.Xna.Framework.Graphics;
  140. using Microsoft.Xna.Framework.Input;
  141.  
  142. namespace ano_sekai
  143. {
  144.     public class Maid : GameObject
  145.     {
  146.         public Vector2 destPos;
  147.  
  148.         public Maid(Vector2 startPos)
  149.         {
  150.             pos = startPos;
  151.             destPos = pos; // keeps it in place
  152.  
  153.             sprite =
  154.                 new Sprite(
  155.                     new Rectangle(0, 16, 16, 16), // source rectangle
  156.                     startPos, // top left
  157.                     new Vector2(16, 16) // size
  158.                 );
  159.         }
  160.  
  161.         public override void Update(GameTime gameTime)
  162.         {
  163.             if (pos != destPos)
  164.             {
  165.                 float dist = (destPos - pos).Length();
  166.                 Vector2 dir = (destPos - pos) / dist;
  167.                 Vector2 moveVec = dir * 32 * (float)gameTime.ElapsedGameTime.TotalSeconds;
  168.                 if (moveVec.Length() >= dist) pos = destPos;
  169.                 else pos += moveVec;
  170.             }
  171.  
  172.             // why do i have to do this every time?
  173.             sprite.pos = pos;
  174.  
  175.             base.Update(gameTime);
  176.         }
  177.     }
  178.  
  179.     public class Game1 : Game
  180.     {
  181.         GraphicsDeviceManager graphics;
  182.         SpriteBatch spriteBatch;
  183.  
  184.         /// <summary>
  185.         /// The player sprite.
  186.         /// </summary>
  187.         Player player;
  188.  
  189.         /// <summary>
  190.         /// The maid sprites.
  191.         /// </summary>
  192.         Maid[] maids;
  193.  
  194.         // left-click object to select, left-click nothing to deselect
  195.         // right-click will perform actions (maybe hold for a menu?)
  196.         // TODO: multiple selection
  197.         List<GameObject> selectedObjects = new List<GameObject>();
  198.  
  199.         public Game1()
  200.         {
  201.             // some stuff added by default, just leave it here
  202.             graphics = new GraphicsDeviceManager(this);
  203.             Content.RootDirectory = "Content";
  204.  
  205.             // show the mouse over the window
  206.             IsMouseVisible = true;
  207.  
  208.             // set the window title
  209.             Window.Title = "Ano Sekai";
  210.  
  211.             // set the size of the window's client area
  212.             graphics.PreferredBackBufferWidth = 800;
  213.             graphics.PreferredBackBufferHeight = 600;
  214.         }
  215.  
  216.         protected override void LoadContent()
  217.         {
  218.             // load the sprite sheet from pipeline
  219.             // the .png is located at e:/coding/projects/games/ano sekai/current/
  220.             Sprite.Sheet = Content.Load<Texture2D>("sprite sheet");
  221.  
  222.             // create the sprite batch so it's ready when we need it
  223.             spriteBatch = new SpriteBatch(GraphicsDevice);
  224.  
  225.             // create a temporary player sprite so we can fiddle with stuff
  226.             player = new Player(new Vector2(32, 32));
  227.  
  228.             // create temporary maid sprites.
  229.             // TODO: will soon be selectable and order-giveable
  230.             maids = new Maid[3];
  231.             maids[0] = new Maid(new Vector2(64, 96));
  232.             maids[1] = new Maid(new Vector2(96, 64));
  233.             maids[2] = new Maid(new Vector2(96, 96));
  234.         }
  235.  
  236.         protected override void Update(GameTime gameTime)
  237.         {
  238.             Input.Update();
  239.  
  240.             // press esc to exit
  241.             if (Input.keyboard.IsKeyDown(Keys.Escape)) Exit();
  242.  
  243.             // "command" inputs done seperately from "hero" input
  244.             if (Input.mouse.LeftButton == ButtonState.Pressed && Input.lastMouse.LeftButton == ButtonState.Released)
  245.             {
  246.                 bool clickedTheGround = true;
  247.                 for (int m = 0; m < maids.Length; m++)
  248.                 {
  249.                     // gotta divide by 4 cuz we're scaling shit up
  250.                     // TODO: deal with this better
  251.                     if (maids[m].sprite.GetDestRect().Contains(Input.mouse.X / 4, Input.mouse.Y / 4))
  252.                     {
  253.                         clickedTheGround = false;
  254.                         // control will add or remove them
  255.                         if (!Input.keyboard.IsKeyDown(Keys.LeftControl)) selectedObjects.Clear();
  256.                         if (selectedObjects.Contains(maids[m])) selectedObjects.Remove(maids[m]);
  257.                         else selectedObjects.Add(maids[m]);
  258.                     }
  259.                 }
  260.                 if (clickedTheGround) selectedObjects.Clear();
  261.             }
  262.             if (Input.mouse.RightButton == ButtonState.Pressed && Input.lastMouse.RightButton == ButtonState.Released)
  263.             {
  264.                 // we'd check to see if any enemy units were being selected first, but none yet so just move
  265.                 // dividing by 4 because we're scaling again
  266.                 // TODO: deal with this smarter
  267.                 Vector2 dest = new Vector2(Input.mouse.X / 4, Input.mouse.Y / 4);
  268.                 foreach (GameObject obj in selectedObjects)
  269.                 {
  270.                     if (obj.GetType() == typeof(Maid)) ((Maid)obj).destPos = dest;
  271.                 }
  272.             }
  273.  
  274.             player.Update(gameTime);
  275.  
  276.             for (int m = 0; m < maids.Length; m++) maids[m].Update(gameTime);
  277.  
  278.             base.Update(gameTime);
  279.         }
  280.  
  281.         protected override void Draw(GameTime gameTime)
  282.         {
  283.             // clear the screen
  284.             GraphicsDevice.Clear(Color.CornflowerBlue);
  285.  
  286.             // scale sprites by 4x
  287.             Matrix drawMatrix = Matrix.CreateScale(4.0f);
  288.             // start drawing sprites. using PointClamp to give us sharp pixel edges for that retro look.
  289.             spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null, null, drawMatrix);
  290.             {
  291.                 // draw the maid sprites
  292.                 for (int m = 0; m < maids.Length; m++)
  293.                 {
  294.                     if (selectedObjects.Contains(maids[m])) spriteBatch.Draw(Sprite.Sheet, maids[m].sprite.GetDestRect(), new Rectangle(16, 16, 16, 16), Color.Yellow);
  295.                     maids[m].sprite.Draw(spriteBatch);
  296.                 }
  297.  
  298.                 // draw the player sprite
  299.                 player.sprite.Draw(spriteBatch);
  300.             }
  301.             // done drawing sprites
  302.             spriteBatch.End();
  303.  
  304.             base.Draw(gameTime);
  305.         }
  306.     }
  307. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement