MonoGame för nybörjare

Detta är en samlingsartikel för serien ”MonoGame för nybörjare”. I huvudsak bygger den på de Youtube-klipp som listas. Du finner också den grafik/content som används i serien här som nedladdningsbar zip-fil samt lite källkod ifall du missat något.

Grafik och Content

Del 1

Del 2

Del 3

Del 4

Del 5

Källkod

MonoGame för nybörjare - Efter del 5
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace MyGame
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        private Texture2D normalTexture;
        private Texture2D jumpingTexture;
        private Texture2D crouchTexture;
        private Texture2D fireballTexture;
        private Texture2D currentTexture;

        private Texture2D backgroundTexture;
        private Texture2D layer1Texture;
        private Texture2D layer2Texture;
        private Texture2D layer3Texture;
        private ParallaxTexture layer1;
        private ParallaxTexture layer2;
        private ParallaxTexture layer3;

        private SpriteFont font;

        private List<Vector2> fireballs;
        private int fireballTimer = 120;
        private Random rnd;

        private Vector2 position;
        private Vector2 speed;
        private bool isJumping;
        private bool isCrouching;
        private bool hit;
        private bool isPlaying;
        private double score = 0;

        private const int STARTY = 400;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            position = new Vector2(300, STARTY);
            fireballs = new List<Vector2>();
            rnd = new Random();

            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            normalTexture = Content.Load<Texture2D>("normal");
            jumpingTexture = Content.Load<Texture2D>("jump");
            crouchTexture = Content.Load<Texture2D>("crouch");
            fireballTexture = Content.Load<Texture2D>("fireball");

            backgroundTexture = Content.Load<Texture2D>("background");
            layer1Texture = Content.Load<Texture2D>("layer1");
            layer2Texture = Content.Load<Texture2D>("layer2");
            layer3Texture = Content.Load<Texture2D>("layer3");

            layer1 = new ParallaxTexture(layer1Texture, 370);
            layer2 = new ParallaxTexture(layer2Texture, 300);
            layer3 = new ParallaxTexture(layer3Texture, 200);

            font = Content.Load<SpriteFont>("font");
        }

        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed 
                || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();
            var state = Keyboard.GetState();

            if (state.IsKeyDown(Keys.Enter) && !isPlaying)
            {
                Reset();
                isPlaying = true;
            }

            if (!isPlaying)
                return;

            // parallax layers
            layer1.OffsetX += 1.5f;
            layer2.OffsetX += 1.0f;
            layer3.OffsetX += 0.5f;

            score += gameTime.ElapsedGameTime.TotalSeconds;
            position += speed;
            if (position.Y > STARTY)
            {
                position = new Vector2(position.X, STARTY);
                speed = Vector2.Zero;
                isJumping = false;
            }

            speed += new Vector2(0, 0.2f);

            if (state.IsKeyDown(Keys.W) && !isJumping)
            {
                speed = new Vector2(0, -5.0f);
                isJumping = true;
            }

            if (state.IsKeyDown(Keys.S) && !isJumping)
            {
                isCrouching = true;
            }
            else
            {
                isCrouching = false;
            }

            //fireballs!!
            fireballTimer--;
            if (fireballTimer <= 0)
            {
                fireballTimer = 120;

                if (rnd.Next(2) == 0)
                {
                    fireballs.Add(new Vector2(800, STARTY));
                }
                else
                {
                    fireballs.Add(new Vector2(800, STARTY + 40));
                }
            }

            for (int i = 0; i < fireballs.Count; i++)
            {
                fireballs[i] = fireballs[i] + new Vector2(-2, 0);
            }

            //collision

            if (isJumping)
            {
                currentTexture = jumpingTexture;
            }
            else if (isCrouching)
            {
                currentTexture = crouchTexture;
            }
            else
            {
                currentTexture = normalTexture;
            }

            Rectangle playerBox = new Rectangle((int)position.X, (int)position.Y, 
                currentTexture.Width, currentTexture.Height);
            hit = false;

            foreach (var fireball in fireballs)
            {
                Rectangle fireballBox = new Rectangle((int)fireball.X, (int)fireball.Y, 
                    fireballTexture.Width, fireballTexture.Height);

                //Överlappar vi?
                var kollision = Intersection(playerBox, fireballBox);

                if (kollision.Width > 0 && kollision.Height > 0)
                {
                    Rectangle r1 = Normalize(playerBox, kollision);
                    Rectangle r2 = Normalize(fireballBox, kollision);
                    hit = TestCollision(currentTexture, r1, fireballTexture, r2);
                    if (hit)
                    {
                        isPlaying = false;
                    }
                }
            }
                 
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            //GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            spriteBatch.Draw(backgroundTexture, Vector2.Zero, Color.White);
            layer3.Draw(spriteBatch);
            layer2.Draw(spriteBatch);
            layer1.Draw(spriteBatch);

            if (isPlaying)
            {
                spriteBatch.DrawString(font, ((int) score).ToString(),
                    new Vector2(10, 20), Color.White);

                if (hit)
                {
                    spriteBatch.DrawString(font, "HIT!!", new Vector2(10, 40), Color.White);
                }

                spriteBatch.Draw(currentTexture, position, Color.White);

                foreach (var fireball in fireballs)
                {
                    spriteBatch.Draw(fireballTexture, fireball, Color.White);
                }
            }
            else
            {
                spriteBatch.DrawString(font, "Press ENTER to start!", 
                    new Vector2(340, 200), Color.White);
            }

            spriteBatch.End();

            base.Draw(gameTime);
        }

        private void Reset()
        {
            fireballs.Clear();
            fireballTimer = 120;
            score = 0;
        }


        public static Rectangle Normalize(Rectangle reference, Rectangle overlap)
        {
            //Räkna ut en rektangel som kan användas relativt till referensrektangeln
            return new Rectangle(
                overlap.X - reference.X,
                overlap.Y - reference.Y,
                overlap.Width,
                overlap.Height);
        }

        public static bool TestCollision(Texture2D t1, Rectangle r1, Texture2D t2, Rectangle r2)
        {
            //Beräkna hur många pixlar som finns i området som ska undersökas
            int pixelCount = r1.Width * r1.Height;
            uint[] texture1Pixels = new uint[pixelCount];
            uint[] texture2Pixels = new uint[pixelCount];

            //Kopiera ut pixlarna från båda områdena
            t1.GetData(0, r1, texture1Pixels, 0, pixelCount);
            t2.GetData(0, r2, texture2Pixels, 0, pixelCount);

            //Jämför om vi har några pixlar som överlappar varandra i områdena
            for (int i = 0; i < pixelCount; ++i)
            {
                if (((texture1Pixels[i] & 0xff000000) > 0) && ((texture2Pixels[i] & 0xff000000) > 0))
                {
                    return true;
                }
            }
            return false;
        }

        public static Rectangle Intersection(Rectangle r1, Rectangle r2)
        {
            int x1 = Math.Max(r1.Left, r2.Left);
            int y1 = Math.Max(r1.Top, r2.Top);
            int x2 = Math.Min(r1.Right, r2.Right);
            int y2 = Math.Min(r1.Bottom, r2.Bottom);

            if ((x2 >= x1) && (y2 >= y1))
            {
                return new Rectangle(x1, y1, x2 - x1, y2 - y1);
            }
            return Rectangle.Empty;
        }
    }
}
ParallaxTexture.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace MyGame
{
    class ParallaxTexture
    {
        private Texture2D _texture;
        private int _positionY;

        public float OffsetX { get; set; }

        public ParallaxTexture(Texture2D Texture, int PositionY)
        {
            _positionY = PositionY;
            _texture = Texture;
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            int width = spriteBatch.GraphicsDevice.Adapter.CurrentDisplayMode.Width;
            int textureStartX = (int)(OffsetX % _texture.Width);
            int textureWidth = _texture.Width - textureStartX;
            int startX = 0;

            while (startX < width)
            {
                spriteBatch.Draw(_texture, new Vector2(startX, _positionY),
                    new Rectangle(textureStartX, 0, textureWidth, _texture.Height), Color.White);
                startX += textureWidth;
                textureStartX = 0;
                textureWidth = _texture.Width;
            }
        }

    }
}
Scroll to top