SteelGolem icon

ano sekai - simple warcraft-style unit selection and movemen

SteelGolem | PRO | 10/19/16 01:43:42 PM UTC | 0 ⭐ | 483 👁️ | Never ⏰ | []
C# |

10.64 KB

|

None

|

0 👍

/

0 👎

/*
    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.
    Game1.cs needs major overhauls and a metric ton of commenting still.
*/
 
// ================================ /2d api/Sprite.cs ================================
 
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
 
namespace ano_sekai
{
    /// <summary>
    /// A simple sprite element.
    /// </summary>
    public class Sprite
    {
        /// <summary>
        /// Top left corner of the sprite.
        /// </summary>
        public Vector2 pos;
 
        /// <summary>
        /// Size of the sprite. X is the width, Y is the height.
        /// </summary>
        public Vector2 size;
 
        /// <summary>
        /// Rectangle to copy from the sprite sheet when drawing.
        /// </summary>
        public Rectangle srcRect;
 
        /// <summary>
        /// Texture atlas containing all of the sprite graphics.
        /// </summary>
        public static Texture2D Sheet = null;
 
        /// <summary>
        /// Creates a new sprite.
        /// </summary>
        /// <param name="srcRect">Rectangle to copy from the sprite sheet when drawing.</param>
        /// <param name="pos">Top left corner of the sprite.</param>
        /// <param name="size">Size of the sprite. X is the width, Y is the height.</param>
        public Sprite(Rectangle srcRect, Vector2 pos, Vector2 size)
        {
            this.srcRect = srcRect; this.pos = pos; this.size = size;
        }
 
        public void Update(GameTime gameTime)
        {
            // nothing to update yet, but when animations are put in, we'll need this
        }
 
        public Rectangle GetDestRect()
        {
            return new Rectangle((int)pos.X, (int)pos.Y, (int)size.X, (int)size.Y);
        }
 
        /// <summary>
        /// Draws the sprite using the given SpriteBatch.
        /// </summary>
        /// <param name="spriteBatch">SpriteBatch to draw with.</param>
        public void Draw(SpriteBatch spriteBatch)
        {
            // TODO: throw exception if Sprite.sheet is null
 
            // using destination rectangle in SpriteBatch.Draw to keep things simple
            spriteBatch.Draw(Sheet, GetDestRect(), srcRect, Color.White);
        }
    }
}
 
// ================================ /engine/GameObject.cs ================================
 
using System;
using Microsoft.Xna.Framework;
 
namespace ano_sekai
{
    public class GameObject
    {
        // don't derive game object classes from sprites
        // -> once Sprite gets alot of public functions and variables, it'll clutter
        //      intellisense for game objects too
        /// <summary>
        /// The sprite instance associated with the game object.
        /// </summary>
        public Sprite sprite;
 
        // the sprite position and the game position are seperate, even if they're usually the same
        /// <summary>
        /// The position of the game object.
        /// </summary>
        public Vector2 pos;
 
        /// <summary>
        /// Updates a game object's logic and sprite. Override in child classes.
        /// </summary>
        /// <param name="gameTime"></param>
        public virtual void Update(GameTime gameTime) { sprite.Update(gameTime); }
    }
}
 
// ================================ /engine/Input.cs ================================
 
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
 
namespace ano_sekai
{
    public class Input
    {
        public static KeyboardState keyboard, lastKeyboard;
        public static MouseState mouse, lastMouse;
        public static GamePadState gamepad, lastGamepad;
 
        public static void Update()
        {
            lastKeyboard = keyboard;
            keyboard = Keyboard.GetState();
            lastMouse = mouse;
            mouse = Mouse.GetState();
            lastGamepad = gamepad;
            gamepad = GamePad.GetState(PlayerIndex.One);
        }
    }
}
 
// ================================ /Game1.cs ================================
 
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
 
namespace ano_sekai
{
    public class Maid : GameObject
    {
        public Vector2 destPos;
 
        public Maid(Vector2 startPos)
        {
            pos = startPos;
            destPos = pos; // keeps it in place
 
            sprite =
                new Sprite(
                    new Rectangle(0, 16, 16, 16), // source rectangle
                    startPos, // top left
                    new Vector2(16, 16) // size
                );
        }
 
        public override void Update(GameTime gameTime)
        {
            if (pos != destPos)
            {
                float dist = (destPos - pos).Length();
                Vector2 dir = (destPos - pos) / dist;
                Vector2 moveVec = dir * 32 * (float)gameTime.ElapsedGameTime.TotalSeconds;
                if (moveVec.Length() >= dist) pos = destPos;
                else pos += moveVec;
            }
 
            // why do i have to do this every time?
            sprite.pos = pos;
 
            base.Update(gameTime);
        }
    }
 
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
 
        /// <summary>
        /// The player sprite.
        /// </summary>
        Player player;
 
        /// <summary>
        /// The maid sprites.
        /// </summary>
        Maid[] maids;
 
        // left-click object to select, left-click nothing to deselect
        // right-click will perform actions (maybe hold for a menu?)
        // TODO: multiple selection
        List<GameObject> selectedObjects = new List<GameObject>();
 
        public Game1()
        {
            // some stuff added by default, just leave it here
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
 
            // show the mouse over the window
            IsMouseVisible = true;
 
            // set the window title
            Window.Title = "Ano Sekai";
 
            // set the size of the window's client area
            graphics.PreferredBackBufferWidth = 800;
            graphics.PreferredBackBufferHeight = 600;
        }
 
        protected override void LoadContent()
        {
            // load the sprite sheet from pipeline
            // the .png is located at e:/coding/projects/games/ano sekai/current/
            Sprite.Sheet = Content.Load<Texture2D>("sprite sheet");
 
            // create the sprite batch so it's ready when we need it
            spriteBatch = new SpriteBatch(GraphicsDevice);
 
            // create a temporary player sprite so we can fiddle with stuff
            player = new Player(new Vector2(32, 32));
 
            // create temporary maid sprites.
            // TODO: will soon be selectable and order-giveable
            maids = new Maid[3];
            maids[0] = new Maid(new Vector2(64, 96));
            maids[1] = new Maid(new Vector2(96, 64));
            maids[2] = new Maid(new Vector2(96, 96));
        }
 
        protected override void Update(GameTime gameTime)
        {
            Input.Update();
 
            // press esc to exit
            if (Input.keyboard.IsKeyDown(Keys.Escape)) Exit();
 
            // "command" inputs done seperately from "hero" input
            if (Input.mouse.LeftButton == ButtonState.Pressed && Input.lastMouse.LeftButton == ButtonState.Released)
            {
                bool clickedTheGround = true;
                for (int m = 0; m < maids.Length; m++)
                {
                    // gotta divide by 4 cuz we're scaling shit up
                    // TODO: deal with this better
                    if (maids[m].sprite.GetDestRect().Contains(Input.mouse.X / 4, Input.mouse.Y / 4))
                    {
                        clickedTheGround = false;
                        // control will add or remove them
                        if (!Input.keyboard.IsKeyDown(Keys.LeftControl)) selectedObjects.Clear();
                        if (selectedObjects.Contains(maids[m])) selectedObjects.Remove(maids[m]);
                        else selectedObjects.Add(maids[m]);
                    }
                }
                if (clickedTheGround) selectedObjects.Clear();
            }
            if (Input.mouse.RightButton == ButtonState.Pressed && Input.lastMouse.RightButton == ButtonState.Released)
            {
                // we'd check to see if any enemy units were being selected first, but none yet so just move
                // dividing by 4 because we're scaling again
                // TODO: deal with this smarter
                Vector2 dest = new Vector2(Input.mouse.X / 4, Input.mouse.Y / 4);
                foreach (GameObject obj in selectedObjects)
                {
                    if (obj.GetType() == typeof(Maid)) ((Maid)obj).destPos = dest;
                }
            }
 
            player.Update(gameTime);
 
            for (int m = 0; m < maids.Length; m++) maids[m].Update(gameTime);
 
            base.Update(gameTime);
        }
 
        protected override void Draw(GameTime gameTime)
        {
            // clear the screen
            GraphicsDevice.Clear(Color.CornflowerBlue);
 
            // scale sprites by 4x
            Matrix drawMatrix = Matrix.CreateScale(4.0f);
            // start drawing sprites. using PointClamp to give us sharp pixel edges for that retro look.
            spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null, null, drawMatrix);
            {
                // draw the maid sprites
                for (int m = 0; m < maids.Length; m++)
                {
                    if (selectedObjects.Contains(maids[m])) spriteBatch.Draw(Sprite.Sheet, maids[m].sprite.GetDestRect(), new Rectangle(16, 16, 16, 16), Color.Yellow);
                    maids[m].sprite.Draw(spriteBatch);
                }
 
                // draw the player sprite
                player.sprite.Draw(spriteBatch);
            }
            // done drawing sprites
            spriteBatch.End();
 
            base.Draw(gameTime);
        }
    }
}

Comments