Skip to content

Instantly share code, notes, and snippets.

@robbiewoods05
Created February 9, 2016 14:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robbiewoods05/4661196fd2396db230d3 to your computer and use it in GitHub Desktop.
Save robbiewoods05/4661196fd2396db230d3 to your computer and use it in GitHub Desktop.
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;
namespace Shooter
{
public class Bullet : GameEntity
{
// List of bullets
private static List<Bullet> bullets = new List<Bullet>();
public static List<Bullet> Bullets { get { return bullets; } }
new public static Texture2D sprite;
static Bullet managerInstance;
new static int speed;
/// <summary>
/// Create a new bullet object
/// </summary>
/// <param name="x">X position</param>
/// <param name="y">Y position </param>
public Bullet(int x, int y, int speed)
{
position.X = x;
position.Y = y;
Enemy.speed = speed;
}
/// <summary>
/// Returns a single instance of Bullet to allow function usage
/// </summary>
/// <returns>Returns a single bullet object</returns>
public static Bullet GetManagerInstance()
{
if (managerInstance == null)
managerInstance = new Bullet();
return managerInstance;
}
private Bullet()
{
}
/// <summary>
/// Adds a bullet to the list of bullets
/// </summary>
/// <param name="b">Bullet object</param>
public static void Add(Bullet b)
{
bullets.Add(b);
}
/// <summary>
/// Draws bullets to screen
/// </summary>
/// <param name="sb">Spritebatch object</param>
public override void Draw(SpriteBatch sb)
{
for (int i = 0; i < bullets.Count; i++)
{
sb.Draw(sprite, bullets[i].position, Color.White);
}
}
/// <summary>
/// Updates the bullets' positions
/// </summary>
/// <param name="gTime">Game timing object</param>
public override void Update(GameTime gTime)
{
for (int i = 0; i < bullets.Count; i++)
{
bullets[i].position.Y -= (float)(Enemy.speed * 0.016);
if (bullets[i].position.Y < 0)
bullets.RemoveAt(i);
}
}
/// <summary>
/// Remove bullet
/// </summary>
/// <param name="b">Index of bullet to remove</param>
public static void Remove(int b)
{
// TODO: Use remove not remove at
bullets.RemoveAt(b);
}
}
}
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
namespace Shooter
{
public class Enemy : GameEntity
{
// Time left to next spawn, total respawn timer
new static float timer = 0.9f, maxTimer = 0.9f;
// Enemy image
new public static Texture2D sprite;
// Random number generator for X position
static readonly Random randomX = new Random();
new static int speed = 140;
// List of enemies
private static List<Enemy> enemies = new List<Enemy>();
public static List<Enemy> Enemies
{
get { return enemies; }
}
static Enemy enemyManager;
public static Enemy GetManagerInstance()
{
if (enemyManager == null)
enemyManager = new Enemy();
return enemyManager;
}
/// <summary>
/// Creates a new enemy object
/// </summary>
/// <param name="x">X position</param>
/// <param name="y">Y position</param>
private Enemy(int x, int y)
{
position.X = x;
position.Y = y;
}
private Enemy()
{ }
/// <summary>
/// Create and add an enemy to the list of enemies
/// </summary>
/// <param name="gt">Game timing object</param>
public static void CreateEnemy(GameTime gt)
{
// Subtracts time between frames from respawn timer
timer -= (float)gt.ElapsedGameTime.TotalSeconds;
// Respawn timer is less than or equal to 0 and less than 5 enemies
if (timer <= 0 && enemies.Count < 5)
{
// Reset respawn timer
timer = maxTimer;
// Get random number between (0, 0+ScreenWidth)=
int xPos = randomX.Next(0, 696);
// Add a new enemy at random X, 60px before 0 so enemies appear to fly in
enemies.Add(new Enemy(xPos, -60));
}
}
/// <summary>
/// Moves the enemies
/// </summary>
/// <param name="gt">Game timing object</param>
public override void Update(GameTime gt)
{
// Iterate through list of enemies
for (int i = 0; i < enemies.Count; i++)
{
// Add enemy speed to Y position after multiplying speed by delta time in order to find distance travelled per frame
enemies[i].position.Y += (int)(speed * (float)gt.ElapsedGameTime.TotalSeconds);
// If enemy is off screen, remove it
if (enemies[i].position.Y > 660)
enemies.RemoveAt(i);
}
}
/// <summary>
/// Draws enemies to the screen
/// </summary>
/// <param name="sb">Spritebatch object</param>
public override void Draw (SpriteBatch sb)
{
// Loop through enemies to draw them
for (int i = 0; i < enemies.Count; i++)
sb.Draw(sprite, enemies[i].position, Color.White);
}
/// <summary>
/// Removes a given enemy from the list of enemies
/// </summary>
/// <param name="en">Enemy to remove</param>
public static void Remove(Enemy en)
{
enemies.Remove(en);
}
}
}
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace Shooter
{
/// <summary>
/// This is the main type for your game.
/// </summary>
public class Shooter : Game
{
private GraphicsDeviceManager graphics;
private SpriteBatch spriteBatch;
private Player player;
private KeyboardState keyState;
private SoundEffect firesound;
#region Object Managers
private GameStateManager gameState;
private Bullet bulletManager;
private PlayerStateManager playerState;
private Enemy enemyManager;
#endregion
public Shooter()
{
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()
{
// TODO: Add your initialization logic here
player = new Player(0, 0);
gameState = new GameStateManager("Menu");
bulletManager = Bullet.GetManagerInstance();
enemyManager = Enemy.GetManagerInstance();
playerState = new PlayerStateManager("idle");
base.Initialize();
}
/// <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);
#region Menu Assets
Menu.BGMusic = Content.Load<Song>("bgmusic");
Menu.MenuSound = Content.Load<SoundEffect>("menuChange");
Menu.MSound = Menu.MenuSound.CreateInstance();
Menu.Button = Content.Load<Texture2D>("button");
Menu.MenuPanel = Content.Load<Texture2D>("menuPanel");
Menu.MenuFont = Content.Load<SpriteFont>("menuFont");
Menu.TitleFont = Content.Load<SpriteFont>("titleFont");
Menu.Cursor = Content.Load<Texture2D>("mouse_cursor");
Menu.CreateButton("Play");
Menu.CreateButton("Options");
Menu.CreateButton("Credits");
Menu.CreateButton("Exit");
#endregion
Bullet.sprite = Content.Load<Texture2D>("laserRed");
#region Player Assets
player.PlayerSprite = Content.Load<Texture2D>("player");
firesound = Content.Load<SoundEffect>("laser");
player.FireSound = firesound.CreateInstance();
// Debug stuff, probably should remove this
player.sFont = Content.Load<SpriteFont>("sFont");
#endregion
Enemy.sprite = Content.Load<Texture2D>("enemyShip");
Menu.PlayMusic(0.15f);
// TODO: use this.Content to load your game content here
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// game-specific content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <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)
{
keyState = Keyboard.GetState();
// If we are not in credits or otions and the player presses escape
if ((gameState.CurrentState != "Options" || gameState.CurrentState != "Credits") && (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)))
Exit();
// Do menu stuff
if (gameState.CurrentState == "Menu")
Menu.HandleInput(ref gameState, this);
// Do play stuff
if (gameState.CurrentState == "Play")
{
player.HandleInput(keyState, gameTime, ref playerState);
bulletManager.Update(gameTime);
Enemy.CreateEnemy(gameTime);
enemyManager.Update(gameTime);
// Iterate through bullets, if bullet ccollides with enemy, remove both
for (int i = 0; i < Bullet.Bullets.Count; i++)
{
for (int j = 0; j < Enemy.Enemies.Count; j++)
{
if (Collisions.IsColliding((int)Bullet.Bullets[i].position.X, (int)Bullet.Bullets[i].position.Y, Bullet.sprite.Width, Bullet.sprite.Height,
(int)Enemy.Enemies[j].position.X, (int)Enemy.Enemies[j].position.Y, Enemy.sprite.Width, Enemy.sprite.Height))
{
Enemy.Remove(Enemy.Enemies[j]);
Bullet.Remove(i);
}
}
}
// Iterate through enemies, if enemy hits player remove enemy
for (int i = 0; i < Enemy.Enemies.Count; i++)
{
if (Collisions.IsColliding((int)player.Position.X, (int)player.Position.Y, player.PlayerSprite.Width, player.PlayerSprite.Height,
(int)Enemy.Enemies[i].position.X, (int)Enemy.Enemies[i].position.Y, Enemy.sprite.Width, Enemy.sprite.Height))
Enemy.Remove(Enemy.Enemies[i]);
}
}
if (gameState.CurrentState == "Credits")
Credits.HandleInput(ref gameState);
// TODO: Add your update logic here
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)
{
spriteBatch.Begin();
GraphicsDevice.Clear(new Color(99, 63, 132));
// Menu drawing stuff
if (gameState.CurrentState == gameState.States[0])
Menu.Draw(spriteBatch);
// Game drawing stuff
if (gameState.CurrentState == gameState.States[2])
{
bulletManager.Draw(spriteBatch);
player.Draw(spriteBatch);
enemyManager.Draw(spriteBatch);
}
// Credits drawing stuff
if (gameState.CurrentState == "Credits")
Credits.Draw(spriteBatch);
// TODO: Add your drawing code here
spriteBatch.End();
base.Draw(gameTime);
}
}
}
using System.Collections.Generic;
namespace Shooter
{
public class GameStateManager : StateManager
{
private List<string> states = new List<string> { "Menu", "Options", "Play", "Credits" };
public List<string> States { get { return states; } }
public GameStateManager(string state) : base(state)
{
}
}
}
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Collections.Generic;
using System.Linq;
namespace Shooter
{
public static class Menu
{
// Holds old state to facilitate checking for button releases so menu doesn't change too quickly
private static KeyboardState oldState = Keyboard.GetState();
// Store allthe sounds for the menu
#region Sounds
private static Song bgMusic;
public static Song BGMusic { get { return bgMusic; } set { bgMusic = value; } }
private static SoundEffect menuSound;
public static SoundEffect MenuSound { get { return menuSound; } set { menuSound = value; } }
public static SoundEffectInstance MSound { get; set; }
#endregion
// Stores everything needed for buttons - Images, the currently selected button, the text on the buttons, the current button being drawn, total buttons, the menu panel as well as the font
#region Menu Buttons
private static Texture2D button;
public static Texture2D Button
{
get { return button; }
set { button = value; }
}
private static string _selected;
private static string[] buttonText = new string[4];
private static int drawIndex = 0, buttonCount = 0;
private static Texture2D menuPanel;
public static Texture2D MenuPanel;
private static SpriteFont menuFont;
public static SpriteFont MenuFont
{
get { return menuFont; }
set { menuFont = value; }
}
#endregion
// Stores the image for the mouse cursor
private static Texture2D cursor;
public static Texture2D Cursor
{
get { return cursor; }
set { cursor = value; }
}
// Stores the font for the title
private static SpriteFont titleFont;
public static SpriteFont TitleFont
{
get { return titleFont; }
set { titleFont = value; }
}
/// <summary>
/// Creates a button on the menu
/// </summary>
/// <param name="buttonName">Name and text of the button</param>
public static void CreateButton(string buttonName)
{
// If this is the first button, it will be selected by default
if (buttonText.Length == 0)
_selected = buttonName;
buttonText[buttonCount] = buttonName;
buttonCount++;
}
/// <summary>
/// Handles the intput for the menu
/// </summary>
/// <param name="state">State of the game</param>
/// <param name="game"></param>
public static void HandleInput(ref GameStateManager state, Game game)
{
// The state of the keyboard after it last got state
KeyboardState newState = Keyboard.GetState();
// Gets the state of the mouse
MouseState ms = Mouse.GetState();
// If key is pressed and released
if (newState.IsKeyDown(Keys.Down))
{
if (!oldState.IsKeyDown(Keys.Down))
{
// If the index of the button to draw as selected is not the last, go to next button, if it is the last go to the first button
if (drawIndex != buttonText.Length - 1)
drawIndex++;
else
drawIndex = 0;
// Play the button switching sound
MSound.Play();
_selected = buttonText[drawIndex];
}
}
else if (newState.IsKeyDown(Keys.Up))
{
if (!oldState.IsKeyDown(Keys.Up))
{
// If not first button, go up, else go to last button
if (drawIndex != 0)
drawIndex--;
else
drawIndex = buttonText.Length - 1;
MSound.Play();
_selected = buttonText[drawIndex];
}
}
else if (newState.IsKeyDown(Keys.Enter))
{
// Perform the selected buttons action
if (_selected == "Play")
state.Set(_selected);
else if (_selected == "Exit")
game.Exit();
else
state.Push(_selected);
MSound.Play();
}
// If the mouse is inside the button, it will be colliding. If LMB is clicked, perform button's action
if (Collisions.IsColliding(ms.X, ms.Y, 0, 0, 305, 205, button.Width, button.Height))
{
_selected = "Play";
if (ms.LeftButton == ButtonState.Pressed)
state.Set("Play");
}
else if (Collisions.IsColliding(ms.X, ms.Y, 0, 0, 365, 258, button.Width, button.Height))
{
_selected = "Options";
if (ms.LeftButton == ButtonState.Pressed)
state.Push("Options");
}
else if (Collisions.IsColliding(ms.X, ms.Y, 0, 0, 425, 311, button.Width, button.Height))
{
_selected = "Credits";
if (ms.LeftButton == ButtonState.Pressed)
state.Push("Credits");
}
else if (Collisions.IsColliding(ms.X, ms.Y, 0, 0, 485, 364, button.Width, button.Height))
{
if (ms.LeftButton == ButtonState.Pressed)
game.Exit();
}
// Set old state to the latest state when done
oldState = newState;
}
/// <summary>
/// Draw the menu to the screen
/// </summary>
/// <param name="spriteBatch">Spritebatch object</param>
public static void Draw(SpriteBatch spriteBatch)
{
// Draw the title to screen
spriteBatch.DrawString(titleFont, "Star Shooter", new Vector2(20, 20), Color.White);
// Start X & Y positons of buttons, move word left if it's long
int x = 365, y = 220, xOffset;
// Colour to draw the button text in
Color colour;
// TODO: Get rid of this
//spriteBatch.Draw(menuPanel, new Vector2(80, 0), null, Color.White, 2f, Vector2.Zero, 0f, SpriteEffects.None, 0f);
// Loop through all buttons
foreach (string b in buttonText)
{
// If the button is selected, draw its text in black
colour = (_selected == b) ? Color.Black : Color.Gray;
// If it's a longer word, distance to move left by
xOffset = (b == "Options" || b == "Credits") ? 5 : -10;
// Draw button image and button text
spriteBatch.Draw(button, new Vector2(x - 60, y - 15), null, Color.White, 0f, Vector2.Zero, 1f, SpriteEffects.None, 0f);
spriteBatch.DrawString(menuFont, b, new Vector2(x - xOffset, y), colour);
// Move to Y position of next button
y += 53;
}
// Draw mouse cursor image to location of cursor
MouseState ms = Mouse.GetState();
spriteBatch.Draw(cursor, new Vector2(ms.X, ms.Y), Color.White);
}
/// <summary>
/// Play the menu music
/// </summary>
/// <param name="vol">Volume</param>
public static void PlayMusic(float vol)
{
MediaPlayer.IsRepeating = true;
MediaPlayer.Volume = vol;
MediaPlayer.Play(bgMusic);
}
}
}
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Collections.Generic;
using System.Linq;
namespace Shooter
{
public static class Menu
{
// Holds old state to facilitate checking for button releases so menu doesn't change too quickly
private static KeyboardState oldState = Keyboard.GetState();
// Store allthe sounds for the menu
#region Sounds
private static Song bgMusic;
public static Song BGMusic { get { return bgMusic; } set { bgMusic = value; } }
private static SoundEffect menuSound;
public static SoundEffect MenuSound { get { return menuSound; } set { menuSound = value; } }
public static SoundEffectInstance MSound { get; set; }
#endregion
// Stores everything needed for buttons - Images, the currently selected button, the text on the buttons, the current button being drawn, total buttons, the menu panel as well as the font
#region Menu Buttons
private static Texture2D button;
public static Texture2D Button
{
get { return button; }
set { button = value; }
}
private static string _selected;
private static string[] buttonText = new string[4];
private static int drawIndex = 0, buttonCount = 0;
private static Texture2D menuPanel;
public static Texture2D MenuPanel;
private static SpriteFont menuFont;
public static SpriteFont MenuFont
{
get { return menuFont; }
set { menuFont = value; }
}
#endregion
// Stores the image for the mouse cursor
private static Texture2D cursor;
public static Texture2D Cursor
{
get { return cursor; }
set { cursor = value; }
}
// Stores the font for the title
private static SpriteFont titleFont;
public static SpriteFont TitleFont
{
get { return titleFont; }
set { titleFont = value; }
}
/// <summary>
/// Creates a button on the menu
/// </summary>
/// <param name="buttonName">Name and text of the button</param>
public static void CreateButton(string buttonName)
{
// If this is the first button, it will be selected by default
if (buttonText.Length == 0)
_selected = buttonName;
buttonText[buttonCount] = buttonName;
buttonCount++;
}
/// <summary>
/// Handles the intput for the menu
/// </summary>
/// <param name="state">State of the game</param>
/// <param name="game"></param>
public static void HandleInput(ref GameStateManager state, Game game)
{
// The state of the keyboard after it last got state
KeyboardState newState = Keyboard.GetState();
// Gets the state of the mouse
MouseState ms = Mouse.GetState();
// If key is pressed and released
if (newState.IsKeyDown(Keys.Down))
{
if (!oldState.IsKeyDown(Keys.Down))
{
// If the index of the button to draw as selected is not the last, go to next button, if it is the last go to the first button
if (drawIndex != buttonText.Length - 1)
drawIndex++;
else
drawIndex = 0;
// Play the button switching sound
MSound.Play();
_selected = buttonText[drawIndex];
}
}
else if (newState.IsKeyDown(Keys.Up))
{
if (!oldState.IsKeyDown(Keys.Up))
{
// If not first button, go up, else go to last button
if (drawIndex != 0)
drawIndex--;
else
drawIndex = buttonText.Length - 1;
MSound.Play();
_selected = buttonText[drawIndex];
}
}
else if (newState.IsKeyDown(Keys.Enter))
{
// Perform the selected buttons action
if (_selected == "Play")
state.Set(_selected);
else if (_selected == "Exit")
game.Exit();
else
state.Push(_selected);
MSound.Play();
}
// If the mouse is inside the button, it will be colliding. If LMB is clicked, perform button's action
if (Collisions.IsColliding(ms.X, ms.Y, 0, 0, 305, 205, button.Width, button.Height))
{
_selected = "Play";
if (ms.LeftButton == ButtonState.Pressed)
state.Set("Play");
}
else if (Collisions.IsColliding(ms.X, ms.Y, 0, 0, 365, 258, button.Width, button.Height))
{
_selected = "Options";
if (ms.LeftButton == ButtonState.Pressed)
state.Push("Options");
}
else if (Collisions.IsColliding(ms.X, ms.Y, 0, 0, 425, 311, button.Width, button.Height))
{
_selected = "Credits";
if (ms.LeftButton == ButtonState.Pressed)
state.Push("Credits");
}
else if (Collisions.IsColliding(ms.X, ms.Y, 0, 0, 485, 364, button.Width, button.Height))
{
if (ms.LeftButton == ButtonState.Pressed)
game.Exit();
}
// Set old state to the latest state when done
oldState = newState;
}
/// <summary>
/// Draw the menu to the screen
/// </summary>
/// <param name="spriteBatch">Spritebatch object</param>
public static void Draw(SpriteBatch spriteBatch)
{
// Draw the title to screen
spriteBatch.DrawString(titleFont, "Star Shooter", new Vector2(20, 20), Color.White);
// Start X & Y positons of buttons, move word left if it's long
int x = 365, y = 220, xOffset;
// Colour to draw the button text in
Color colour;
// TODO: Get rid of this
//spriteBatch.Draw(menuPanel, new Vector2(80, 0), null, Color.White, 2f, Vector2.Zero, 0f, SpriteEffects.None, 0f);
// Loop through all buttons
foreach (string b in buttonText)
{
// If the button is selected, draw its text in black
colour = (_selected == b) ? Color.Black : Color.Gray;
// If it's a longer word, distance to move left by
xOffset = (b == "Options" || b == "Credits") ? 5 : -10;
// Draw button image and button text
spriteBatch.Draw(button, new Vector2(x - 60, y - 15), null, Color.White, 0f, Vector2.Zero, 1f, SpriteEffects.None, 0f);
spriteBatch.DrawString(menuFont, b, new Vector2(x - xOffset, y), colour);
// Move to Y position of next button
y += 53;
}
// Draw mouse cursor image to location of cursor
MouseState ms = Mouse.GetState();
spriteBatch.Draw(cursor, new Vector2(ms.X, ms.Y), Color.White);
}
/// <summary>
/// Play the menu music
/// </summary>
/// <param name="vol">Volume</param>
public static void PlayMusic(float vol)
{
MediaPlayer.IsRepeating = true;
MediaPlayer.Volume = vol;
MediaPlayer.Play(bgMusic);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Shooter
{
public class PlayerStateManager : StateManager
{
public string[] states = { "firing", "idle" };
public PlayerStateManager(string state):base(state)
{
}
}
}
using System.Collections.Generic;
namespace Shooter
{
public class StateManager
{
Stack<string> states = new Stack<string>();
public string CurrentState { get { return states.Peek(); } }
/// <summary>
/// Create a new state manager
/// </summary>
/// <param name="state">Default state</param>
public StateManager(string state)
{
states.Push(state);
}
/// <summary>
/// Return to last state
/// </summary>
public virtual void Pop()
{
states.Pop();
}
/// <summary>
/// Push the given state onto the top of the state stack.
/// </summary>
/// <param name="state">State to push on</param>
public virtual void Push(string state)
{
states.Push(state);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment