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 { /// /// This is the main type for your game /// 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 blockPositions = new List(); float BlockSpawnOdds = 0.035f; const int BlockFallSpeed = 3; Random random = new Random(); public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } /// /// 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. /// 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; } /// /// LoadContent will be called once per game and is the place to load /// all of your content. /// protected override void LoadContent() { // Load textures blockTexture = Content.Load("Block"); personTexture = Content.Load("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); } /// /// UnloadContent will be called once per game and is the place to unload /// all content. /// 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); } /// /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// /// Provides a snapshot of timing values. 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); } /// /// This is called when the game should draw itself. /// /// Provides a snapshot of timing values. 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; } } }