using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace FallingBlocksFINAL
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
// The color data for the images; used for per-pixel collision
Color[] personTextureData;
Color[] blockTextureData;
GraphicsDeviceManager graphics;
// Audio objects
AudioEngine engine;
SoundBank soundBank;
WaveBank waveBank;
AudioCategory musicCategory;
// Music volume.
float musicVolume = 1.0f;
// For when a collision is detected
bool personHit = false;
// The images to draw
Texture2D personTexture;
Texture2D blockTexture;
// The images will be drawn with this SpriteBatch
SpriteBatch spriteBatch;
// Person
Vector2 personPosition;
const int PersonMoveSpeed = 5;
// Blocks
List<Vector2> blockPositions = new List<Vector2>();
float BlockSpawnOdds = 0.035f;
const int BlockFallSpeed = 3;
Random random = new Random();
public Game1()
{
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()
{
base.Initialize();
// Initialize audio objects.
engine = new AudioEngine("Content\\onemoretest.xgs");
soundBank = new SoundBank(engine, "Content\\Sound Bank.xsb");
waveBank = new WaveBank(engine, "Content\\Wave Bank.xwb");
// Get the category.
musicCategory = engine.GetCategory("Music");
// Play the sound.
soundBank.PlayCue("agroome_wondering.wav");
// Start the player in the center along the bottom of the screen
personPosition.X = (Window.ClientBounds.Width - personTexture.Width) / 2;
personPosition.Y = Window.ClientBounds.Height - personTexture.Height;
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Load textures
blockTexture = Content.Load<Texture2D>("Block");
personTexture = Content.Load<Texture2D>("Person");
// Extract collision data
blockTextureData =
new Color[blockTexture.Width * blockTexture.Height];
blockTexture.GetData(blockTextureData);
personTextureData =
new Color[personTexture.Width * personTexture.Height];
personTexture.GetData(personTextureData);
// Create a sprite batch to draw those textures
spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
//HERE
protected void UpdateInput()
{
// Get the current gamepad state.
KeyboardState keyboard = Keyboard.GetState();
if (keyboard.IsKeyDown(Keys.W))
{
musicVolume = MathHelper.Clamp(musicVolume + 0.01f, 0.0f, 4.0f);
}
if (keyboard.IsKeyDown(Keys.S))
{
musicVolume = MathHelper.Clamp(musicVolume - 0.01f, 0.0f, 4.0f);
}
// Set the category volume.
musicCategory.SetVolume(musicVolume);
}
/// <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)
{
// Get the current gamepad state.
// Get input
KeyboardState keyboard = Keyboard.GetState();
GamePadState gamePad = GamePad.GetState(PlayerIndex.One);
// Allows the game to exit
if (gamePad.Buttons.Back == ButtonState.Pressed)
this.Exit();
// Check input.
UpdateInput();
// Update the audio engine.
engine.Update();
// Move the player left and right with arrow keys or d-pad
if (keyboard.IsKeyDown(Keys.Left) ||
gamePad.DPad.Left == ButtonState.Pressed)
{
personPosition.X -= PersonMoveSpeed;
}
if (keyboard.IsKeyDown(Keys.Right) ||
gamePad.DPad.Right == ButtonState.Pressed)
{
personPosition.X += PersonMoveSpeed;
}
// Prevent the person from moving off of the screen
personPosition.X = MathHelper.Clamp(personPosition.X,
0, Window.ClientBounds.Width - personTexture.Width);
// Spawn new falling blocks
if (random.NextDouble() < BlockSpawnOdds)
{
float x = (float)random.NextDouble() *
(Window.ClientBounds.Width - blockTexture.Width);
blockPositions.Add(new Vector2(x, -blockTexture.Height));
}
// Get the bounding rectangle of the person
Rectangle personRectangle =
new Rectangle((int)personPosition.X, (int)personPosition.Y,
personTexture.Width, personTexture.Height);
// Update each block
personHit = false;
for (int i = 0; i < blockPositions.Count; i++)
{
// Animate this block falling
blockPositions[i] =
new Vector2(blockPositions[i].X,
blockPositions[i].Y + BlockFallSpeed);
// Get the bounding rectangle of this block
Rectangle blockRectangle =
new Rectangle((int)blockPositions[i].X, (int)blockPositions[i].Y,
blockTexture.Width, blockTexture.Height);
// Check collision with person
if (IntersectPixels(personRectangle, personTextureData,
blockRectangle, blockTextureData))
{
personHit = true;
}
// Remove this block if it have fallen off the screen
if (blockPositions[i].Y > Window.ClientBounds.Height)
{
blockPositions.RemoveAt(i);
// When removing a block, the next block will have the same index
// as the current block. Decrement i to prevent skipping a block.
i--;
}
}
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)
{
GraphicsDevice device = graphics.GraphicsDevice;
// Change the background to red when the person was hit by a block
if (personHit)
device.Clear(Color.Red);
else
device.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
// Draw person
spriteBatch.Draw(personTexture, personPosition, Color.White);
// Draw blocks
foreach (Vector2 blockPosition in blockPositions)
spriteBatch.Draw(blockTexture, blockPosition, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
static bool IntersectPixels(Rectangle rectangleA, Color[] dataA,
Rectangle rectangleB, Color[] dataB)
{
// Find the bounds of the rectangle intersection
int top = Math.Max(rectangleA.Top, rectangleB.Top);
int bottom = Math.Min(rectangleA.Bottom, rectangleB.Bottom);
int left = Math.Max(rectangleA.Left, rectangleB.Left);
int right = Math.Min(rectangleA.Right, rectangleB.Right);
// Check every point within the intersection bounds
for (int y = top; y < bottom; y++)
{
for (int x = left; x < right; x++)
{
// Get the color of both pixels at this point
Color colorA = dataA[(x - rectangleA.Left) +
(y - rectangleA.Top) * rectangleA.Width];
Color colorB = dataB[(x - rectangleB.Left) +
(y - rectangleB.Top) * rectangleB.Width];
// If both pixels are not completely transparent,
if (colorA.A != 0 && colorB.A != 0)
{
// then an intersection has been found
return true;
}
}
}
// No intersection found
return false;
}
}
}