Planetary Gravity

Hello. Today i will be showing you how to create planetary gravity in MonoGame with C#. I used Newton’s law of universal gravitation with some tweaking to make it ‘feel’ good.  If you have any questions ask in the comments or email me in the contact section. (sweeney1995@live.co.uk)

The Universal Gravitation Class

using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

/*
 * The following code is created by Darren Sweeney.
 * Twitter: @NerdyNinja95
*/

namespace PlanetaryGravityExample
{
 static class UniversalGravitation
 {
 /* Newton's law of universal gravitation states that every point mass in
 // the universe attracts every other point mass with a force that is directly
 // proportional to the product of their masses and inversely proportional
 to the square of the distance between them. */

 // E.g Force = GravitationalConstant * MoonMass * PlanetMass / distance^2
 // or
 //
 // Force = GravitationalConstant X MoonMass X PlanetMass
 // _____________________________________________________
 // distance X distance

 public static float force; //The force changes as the moon comes closer to the planet , so therfore it accelerates.
 public const float gravitationalConstant = 1f; //In our universe its 6.67300 × 10-11 m3 kg-1 s-2
 public static float distance; //The distance is meassured from the center of each sprite
 public static Vector2 direction; //Gravity is always an attracitve force.
 }
}

The Object Class

#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
#endregion

/*
 * The following code is created by Darren Sweeney.
 * Twitter: @NerdyNinja95
*/

namespace PlanetaryGravityExample
{
    abstract class Object
    {
        public Texture2D texture;
        public Vector2 position;
        public Vector2 center;
        public float radius;
        public float mass;
        public float scale;
        public Vector2 velocity;

        public Object(ContentManager content, String fileName, float objectScale)
        {
            texture = content.Load<Texture2D>(fileName);

            center = new Vector2(texture.Width / 2, texture.Height / 2);
            position = position + center; // Position is measured from the center of texture
            radius = texture.Width / 2;
            scale = objectScale;
        }

        public void UpdateGravity(Vector2 p2, float m2)
        {
            position += velocity * UniversalGravitation.force;
            UniversalGravitation.distance = Vector2.Distance(p2, position);
            UniversalGravitation.force =     (UniversalGravitation.gravitationalConstant * mass * m2)
            //                             ____________________________________________________________
                                                     / (UniversalGravitation.distance * 10);

            UniversalGravitation.direction = (p2) - (position);
            UniversalGravitation.direction.Normalize();
            velocity += UniversalGravitation.direction * UniversalGravitation.force;
        }

        public virtual void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Begin();
            spriteBatch.Draw(texture, position, null, Color.White, 0, Vector2.Zero, scale, SpriteEffects.None, 0);
            spriteBatch.End();
        }
    }
}

The Input Class

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

/*
 * The following code is created by Darren Sweeney.
 * Twitter: @NerdyNinja95
*/

namespace PlanetaryGravityExample
{
    static class Input
    {
        private static KeyboardState keyboardState;

        public static void Update()
        {
            keyboardState = Keyboard.GetState();
        }

        public static Vector2 GetMovementDirection()
        {
            Vector2 direction = Vector2.Zero; 

            if (keyboardState.IsKeyDown(Keys.A))
                direction.X -= 1;
            if (keyboardState.IsKeyDown(Keys.D))
                direction.X += 1;
            if (keyboardState.IsKeyDown(Keys.W))
                direction.Y -= 1;
            if (keyboardState.IsKeyDown(Keys.S))
                direction.Y += 1;

            // Clamp the length of the vector to a maximum of 1.
            if (direction.Length() > 1)
                direction.Normalize();

            return direction;
        }
    }
}

The Player Class

using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

/*
 * The following code is created by Darren Sweeney.
 * Twitter: @NerdyNinja95
*/

namespace PlanetaryGravityExample
{
    class Player : Object
    {
        public Player(ContentManager content, float objectMass, Vector2 objectPos, float objectScale)
            : base (content, "Player", objectScale)
        {
            mass = objectMass;
            position = objectPos;
        }

        public void Update()
        {
            Input.Update();
            velocity += Input.GetMovementDirection();
        }
    }
}

The Planet Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;

/*
 * The following code is created by Darren Sweeney.
 * Twitter: @NerdyNinja95
*/

namespace PlanetaryGravityExample
{
    class Planet : Object
    {
        public Planet(ContentManager content, float objectMass, Vector2 objectPos, float objectScale)
            : base(content, "Planet", objectScale)
        {
            mass = objectMass;
            position = objectPos;
        }
    }
}

The Solar System Class

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

/*
 * The following code is created by Darren Sweeney.
 * Twitter: @NerdyNinja95
*/

namespace PlanetaryGravityExample
{
    class SolarSystem
    {
        Player player;
        List<Planet> planets = new List<Planet>();

        public SolarSystem(ContentManager content)
        {
            player = new Player(content, 10, new Vector2(200, 100), 0.2f);

            planets.Add(new Planet(content, 20, new Vector2(750, 200), 0.45f));
        }

        public void Update()
        {
            player.Update();

            foreach(Planet p in planets)
            {
                player.UpdateGravity(p.position, p.mass);
                p.UpdateGravity(player.position, player.mass);

                // Planets pull of each other.
                foreach (Planet op in planets)
                {
                    if (p.Equals(op))
                        break;

                    p.UpdateGravity(op.position, op.mass);
                    op.UpdateGravity(p.position, p.mass);
                }
            }
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            player.Draw(spriteBatch);

            for (int i = 0; i < planets.Count(); i++)
                planets[i].Draw(spriteBatch);
        }
    }
}

The Game1 Class

#region Using Statements
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;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.GamerServices;
#endregion

/*
 * The following code is created by Darren Sweeney.
 * Twitter: @NerdyNinja95
*/

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

        SolarSystem solarSystem;

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

            Window.AllowUserResizing = true;
        }

        protected override void Initialize()
        {
            solarSystem = new SolarSystem(Content);

            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
        }

        protected override void UnloadContent()
        {

        }

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

            solarSystem.Update();

            base.Update(gameTime);
        }

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

            solarSystem.Draw(spriteBatch);

            base.Draw(gameTime);
        }
    }
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s