浏览代码

PerPixelCollition updated to SDK and MG 3.8.*

CartBlanche 1 周之前
父节点
当前提交
de75699f4b
共有 28 个文件被更改,包括 973 次插入539 次删除
  1. 49 0
      PerPixelCollisionSample/.vscode/launch.json
  2. 181 0
      PerPixelCollisionSample/.vscode/tasks.json
  3. 0 0
      PerPixelCollisionSample/Core/Content/Block.bmp
  4. 0 0
      PerPixelCollisionSample/Core/Content/Block.xnb
  5. 0 0
      PerPixelCollisionSample/Core/Content/Game.ico
  6. 0 0
      PerPixelCollisionSample/Core/Content/Person.bmp
  7. 0 0
      PerPixelCollisionSample/Core/Content/Person.xnb
  8. 265 270
      PerPixelCollisionSample/Core/Game1.cs
  9. 0 0
      PerPixelCollisionSample/Core/GameThumbnail.png
  10. 13 0
      PerPixelCollisionSample/Core/PerPixelCollisionSample.Core.csproj
  11. 0 94
      PerPixelCollisionSample/PerPixelCollision.iOS.csproj
  12. 0 82
      PerPixelCollisionSample/PerPixelCollisionSample.MacOS.csproj
  13. 28 18
      PerPixelCollisionSample/PerPixelCollisionSample.sln
  14. 25 0
      PerPixelCollisionSample/Platforms/Android/AndroidManifest.xml
  15. 32 0
      PerPixelCollisionSample/Platforms/Android/MainActivity.cs
  16. 31 0
      PerPixelCollisionSample/Platforms/Android/PerPixelCollisionSample.Android.csproj
  17. 4 0
      PerPixelCollisionSample/Platforms/Android/Resources/values/strings.xml
  18. 29 0
      PerPixelCollisionSample/Platforms/Desktop/PerPixelCollisionSample.DesktopGL.csproj
  19. 14 0
      PerPixelCollisionSample/Platforms/Desktop/Program.cs
  20. 31 0
      PerPixelCollisionSample/Platforms/Windows/PerPixelCollisionSample.Windows.csproj
  21. 27 0
      PerPixelCollisionSample/Platforms/Windows/Program.cs
  22. 41 0
      PerPixelCollisionSample/Platforms/Windows/app.manifest
  23. 16 0
      PerPixelCollisionSample/Platforms/iOS/AppDelegate.cs
  24. 0 0
      PerPixelCollisionSample/Platforms/iOS/Info.plist
  25. 27 0
      PerPixelCollisionSample/Platforms/iOS/PerPixelCollisionSample.iOS.csproj
  26. 13 0
      PerPixelCollisionSample/Platforms/iOS/Program.cs
  27. 0 75
      PerPixelCollisionSample/Program.cs
  28. 147 0
      PerPixelCollisionSample/README.md

+ 49 - 0
PerPixelCollisionSample/.vscode/launch.json

@@ -0,0 +1,49 @@
+{
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "name": "Launch Windows",
+            "type": "coreclr",
+            "request": "launch",
+            "preLaunchTask": "build-windows",
+            "program": "${workspaceFolder}/bin/Debug/net8.0-windows/PerPixelCollisionSample.Windows.exe",
+            "args": [],
+            "cwd": "${workspaceFolder}",
+            "console": "internalConsole",
+            "stopAtEntry": false
+        },
+        {
+            "name": "Launch DesktopGL",
+            "type": "coreclr",
+            "request": "launch",
+            "preLaunchTask": "build-desktopgl",
+            "program": "${workspaceFolder}/bin/Debug/net8.0/PerPixelCollisionSample.DesktopGL.exe",
+            "args": [],
+            "cwd": "${workspaceFolder}",
+            "console": "internalConsole",
+            "stopAtEntry": false
+        },
+        {
+            "name": "Launch Android",
+            "type": "coreclr",
+            "request": "launch",
+            "preLaunchTask": "build-android",
+            "program": "${workspaceFolder}/bin/Debug/net8.0-android/PerPixelCollisionSample.Android.dll",
+            "args": [],
+            "cwd": "${workspaceFolder}",
+            "console": "internalConsole",
+            "stopAtEntry": false
+        },
+        {
+            "name": "Launch iOS",
+            "type": "coreclr",
+            "request": "launch",
+            "preLaunchTask": "build-ios",
+            "program": "${workspaceFolder}/bin/Debug/net8.0-ios/PerPixelCollisionSample.iOS.dll",
+            "args": [],
+            "cwd": "${workspaceFolder}",
+            "console": "internalConsole",
+            "stopAtEntry": false
+        }
+    ]
+}

+ 181 - 0
PerPixelCollisionSample/.vscode/tasks.json

@@ -0,0 +1,181 @@
+{
+    "version": "2.0.0",
+    "tasks": [
+        {
+            "label": "build-windows",
+            "command": "dotnet",
+            "type": "process",
+            "args": [
+                "build",
+                "${workspaceFolder}/Platforms/Windows/PerPixelCollisionSample.Windows.csproj",
+                "/property:GenerateFullPaths=true",
+                "/consoleloggerparameters:NoSummary"
+            ],
+            "group": "build",
+            "presentation": {
+                "reveal": "silent"
+            },
+            "problemMatcher": "$msCompile"
+        },
+        {
+            "label": "build-desktopgl",
+            "command": "dotnet",
+            "type": "process",
+            "args": [
+                "build",
+                "${workspaceFolder}/Platforms/Desktop/PerPixelCollisionSample.DesktopGL.csproj",
+                "/property:GenerateFullPaths=true",
+                "/consoleloggerparameters:NoSummary"
+            ],
+            "group": "build",
+            "presentation": {
+                "reveal": "silent"
+            },
+            "problemMatcher": "$msCompile"
+        },
+        {
+            "label": "build-android",
+            "command": "dotnet",
+            "type": "process",
+            "args": [
+                "build",
+                "${workspaceFolder}/Platforms/Android/PerPixelCollisionSample.Android.csproj",
+                "/property:GenerateFullPaths=true",
+                "/consoleloggerparameters:NoSummary"
+            ],
+            "group": "build",
+            "presentation": {
+                "reveal": "silent"
+            },
+            "problemMatcher": "$msCompile"
+        },
+        {
+            "label": "run-windows",
+            "command": "dotnet",
+            "type": "process",
+            "args": [
+                "run",
+                "--project",
+                "${workspaceFolder}/Platforms/Windows/PerPixelCollisionSample.Windows.csproj"
+            ],
+            "group": "test",
+            "presentation": {
+                "reveal": "always",
+                "panel": "new"
+            },
+            "dependsOn": "build-windows"
+        },
+        {
+            "label": "run-desktopgl",
+            "command": "dotnet",
+            "type": "process",
+            "args": [
+                "run",
+                "--project",
+                "${workspaceFolder}/Platforms/Desktop/PerPixelCollisionSample.DesktopGL.csproj"
+            ],
+            "group": "test",
+            "presentation": {
+                "reveal": "always",
+                "panel": "new"
+            },
+            "dependsOn": "build-desktopgl"
+        },
+        {
+            "label": "build-ios",
+            "command": "dotnet",
+            "type": "process",
+            "args": [
+                "build",
+                "${workspaceFolder}/Platforms/iOS/PerPixelCollisionSample.iOS.csproj",
+                "/property:GenerateFullPaths=true",
+                "/consoleloggerparameters:NoSummary"
+            ],
+            "group": "build",
+            "presentation": {
+                "reveal": "silent"
+            },
+            "problemMatcher": "$msCompile"
+        },
+        {
+            "label": "build-android",
+            "command": "dotnet",
+            "type": "process",
+            "args": [
+                "build",
+                "${workspaceFolder}/Platforms/Android/PerPixelCollisionSample.Android.csproj",
+                "/property:GenerateFullPaths=true",
+                "/consoleloggerparameters:NoSummary"
+            ],
+            "group": "build",
+            "presentation": {
+                "reveal": "silent"
+            },
+            "problemMatcher": "$msCompile"
+        },
+        {
+            "label": "run-android",
+            "command": "dotnet",
+            "type": "process",
+            "args": [
+                "run",
+                "--project",
+                "${workspaceFolder}/Platforms/Android/PerPixelCollisionSample.Android.csproj"
+            ],
+            "group": "test",
+            "presentation": {
+                "reveal": "always",
+                "panel": "new"
+            },
+            "dependsOn": "build-android"
+        },
+        {
+            "label": "run-ios",
+            "command": "dotnet",
+            "type": "process",
+            "args": [
+                "run",
+                "--project",
+                "${workspaceFolder}/Platforms/iOS/PerPixelCollisionSample.iOS.csproj"
+            ],
+            "group": "test",
+            "presentation": {
+                "reveal": "always",
+                "panel": "new"
+            },
+            "dependsOn": "build-ios"
+        },
+        {
+            "label": "clean-windows",
+            "command": "dotnet",
+            "type": "process",
+            "args": [
+                "clean",
+                "${workspaceFolder}/PerPixelCollisionSample.Windows.csproj",
+                "/property:GenerateFullPaths=true",
+                "/consoleloggerparameters:NoSummary"
+            ],
+            "group": "build",
+            "presentation": {
+                "reveal": "silent"
+            },
+            "problemMatcher": "$msCompile"
+        },
+        {
+            "label": "clean-desktopgl",
+            "command": "dotnet",
+            "type": "process",
+            "args": [
+                "clean",
+                "${workspaceFolder}/PerPixelCollisionSample.DesktopGL.csproj",
+                "/property:GenerateFullPaths=true",
+                "/consoleloggerparameters:NoSummary"
+            ],
+            "group": "build",
+            "presentation": {
+                "reveal": "silent"
+            },
+            "problemMatcher": "$msCompile"
+        }
+    ]
+}

+ 0 - 0
PerPixelCollisionSample/Content/Block.bmp → PerPixelCollisionSample/Core/Content/Block.bmp


+ 0 - 0
PerPixelCollisionSample/Content/Block.xnb → PerPixelCollisionSample/Core/Content/Block.xnb


+ 0 - 0
PerPixelCollisionSample/Game.ico → PerPixelCollisionSample/Core/Content/Game.ico


+ 0 - 0
PerPixelCollisionSample/Content/Person.bmp → PerPixelCollisionSample/Core/Content/Person.bmp


+ 0 - 0
PerPixelCollisionSample/Content/Person.xnb → PerPixelCollisionSample/Core/Content/Person.xnb


+ 265 - 270
PerPixelCollisionSample/Game1.cs → PerPixelCollisionSample/Core/Game1.cs

@@ -1,270 +1,265 @@
-#region File Description
-//-----------------------------------------------------------------------------
-// Game.cs
-//
-// Microsoft XNA Community Game Platform
-// Copyright (C) Microsoft Corporation. All rights reserved.
-//-----------------------------------------------------------------------------
-#endregion
-
-#region Using Statements
-using System;
-using System.Collections.Generic;
-using Microsoft.Xna.Framework;
-using Microsoft.Xna.Framework.Audio;
-using Microsoft.Xna.Framework.Content;
-using Microsoft.Xna.Framework.Graphics;
-using Microsoft.Xna.Framework.Input;
-using Microsoft.Xna.Framework.Storage;
-#endregion
-
-namespace PerPixelCollision
-{
-    /// <summary>
-    /// This is the main type for your game
-    /// </summary>
-    public class PerPixelCollisionGame : Microsoft.Xna.Framework.Game
-    {
-        GraphicsDeviceManager graphics;
-
-        // The images we will draw
-        Texture2D personTexture;
-        Texture2D blockTexture;
-
-        // The color data for the images; used for per pixel collision
-        Color[] personTextureData;
-        Color[] blockTextureData;
-
-        // 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 BlockSpawnProbability = 0.01f;
-        const int BlockFallSpeed = 2;
-
-        Random random = new Random();
-
-        // For when a collision is detected
-        bool personHit = false;
-
-        // The sub-rectangle of the drawable area which should be visible on all TVs
-        Rectangle safeBounds;
-        // Percentage of the screen on every side is the safe area
-        const float SafeAreaPortion = 0.05f;
-
-
-        public PerPixelCollisionGame()
-        {
-            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();
-
-            // Calculate safe bounds based on current resolution
-            Viewport viewport = graphics.GraphicsDevice.Viewport;
-            safeBounds = new Rectangle(
-                (int)(viewport.Width * SafeAreaPortion),
-                (int)(viewport.Height * SafeAreaPortion),
-                (int)(viewport.Width * (1 - 2 * SafeAreaPortion)),
-                (int)(viewport.Height * (1 - 2 * SafeAreaPortion)));
-            // Start the player in the center along the bottom of the screen
-            personPosition.X = (safeBounds.Width - personTexture.Width) / 2;
-            personPosition.Y = safeBounds.Height - personTexture.Height;
-        }
-
-
-        /// <summary>
-        /// Load your graphics 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>
-        /// 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 input
-            KeyboardState keyboard = Keyboard.GetState();
-            GamePadState gamePad = GamePad.GetState(PlayerIndex.One);
-
-            // Allows the game to exit
-            if (gamePad.Buttons.Back == ButtonState.Pressed ||
-                keyboard.IsKeyDown(Keys.Escape))
-            {
-                this.Exit();
-            }
-
-            // 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,
-                safeBounds.Left, safeBounds.Right - personTexture.Width);
-
-            // Spawn new falling blocks
-            if (random.NextDouble() < BlockSpawnProbability)
-            {
-                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);
-        }
-
-
-        /// <summary>
-        /// Determines if there is overlap of the non-transparent pixels
-        /// between two sprites.
-        /// </summary>
-        /// <param name="rectangleA">Bounding rectangle of the first sprite</param>
-        /// <param name="dataA">Pixel data of the first sprite</param>
-        /// <param name="rectangleB">Bouding rectangle of the second sprite</param>
-        /// <param name="dataB">Pixel data of the second sprite</param>
-        /// <returns>True if non-transparent pixels overlap; false otherwise</returns>
-        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;
-        }
-    }
-}
+//-----------------------------------------------------------------------------
+// Game.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Audio;
+using Microsoft.Xna.Framework.Content;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+
+namespace PerPixelCollision
+{
+    /// <summary>
+    /// This is the main type for your game
+    /// </summary>
+    public class PerPixelCollisionGame : Microsoft.Xna.Framework.Game
+    {
+        GraphicsDeviceManager graphics;
+
+        // The images we will draw
+        Texture2D personTexture;
+        Texture2D blockTexture;
+
+        // The color data for the images; used for per pixel collision
+        Color[] personTextureData;
+        Color[] blockTextureData;
+
+        // 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 BlockSpawnProbability = 0.01f;
+        const int BlockFallSpeed = 2;
+
+        Random random = new Random();
+
+        // For when a collision is detected
+        bool personHit = false;
+
+        // The sub-rectangle of the drawable area which should be visible on all TVs
+        Rectangle safeBounds;
+        // Percentage of the screen on every side is the safe area
+        const float SafeAreaPortion = 0.05f;
+
+
+        public PerPixelCollisionGame()
+        {
+            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();
+
+            // Calculate safe bounds based on current resolution
+            Viewport viewport = graphics.GraphicsDevice.Viewport;
+            safeBounds = new Rectangle(
+                (int)(viewport.Width * SafeAreaPortion),
+                (int)(viewport.Height * SafeAreaPortion),
+                (int)(viewport.Width * (1 - 2 * SafeAreaPortion)),
+                (int)(viewport.Height * (1 - 2 * SafeAreaPortion)));
+            // Start the player in the center along the bottom of the screen
+            personPosition.X = (safeBounds.Width - personTexture.Width) / 2;
+            personPosition.Y = safeBounds.Height - personTexture.Height;
+        }
+
+
+        /// <summary>
+        /// Load your graphics 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>
+        /// 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 input
+            KeyboardState keyboard = Keyboard.GetState();
+            GamePadState gamePad = GamePad.GetState(PlayerIndex.One);
+
+            // Allows the game to exit
+            if (gamePad.Buttons.Back == ButtonState.Pressed ||
+                keyboard.IsKeyDown(Keys.Escape))
+            {
+                this.Exit();
+            }
+
+            // 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,
+                safeBounds.Left, safeBounds.Right - personTexture.Width);
+
+            // Spawn new falling blocks
+            if (random.NextDouble() < BlockSpawnProbability)
+            {
+                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);
+        }
+
+
+        /// <summary>
+        /// Determines if there is overlap of the non-transparent pixels
+        /// between two sprites.
+        /// </summary>
+        /// <param name="rectangleA">Bounding rectangle of the first sprite</param>
+        /// <param name="dataA">Pixel data of the first sprite</param>
+        /// <param name="rectangleB">Bouding rectangle of the second sprite</param>
+        /// <param name="dataB">Pixel data of the second sprite</param>
+        /// <returns>True if non-transparent pixels overlap; false otherwise</returns>
+        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;
+        }
+    }
+}

+ 0 - 0
PerPixelCollisionSample/GameThumbnail.png → PerPixelCollisionSample/Core/GameThumbnail.png


+ 13 - 0
PerPixelCollisionSample/Core/PerPixelCollisionSample.Core.csproj

@@ -0,0 +1,13 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>net8.0</TargetFramework>
+    <AssemblyName>PerPixelCollisionSample.Core</AssemblyName>
+    <RootNamespace>PerPixelCollision</RootNamespace>
+    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.*" />
+  </ItemGroup>
+
+</Project>

+ 0 - 94
PerPixelCollisionSample/PerPixelCollision.iOS.csproj

@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
-    <ProductVersion>10.0.0</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
-    <ProjectGuid>{CE342066-BCCD-4989-A401-0D36287276EF}</ProjectGuid>
-    <ProjectTypeGuids>{6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
-    <OutputType>Exe</OutputType>
-    <RootNamespace>MonoGame.Samples.PerPixelCollision</RootNamespace>
-    <AssemblyName>MonoGameSamplesPerPixelCollision</AssemblyName>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
-    <DebugSymbols>True</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>False</Optimize>
-    <OutputPath>bin\iPhoneSimulator\Debug</OutputPath>
-    <DefineConstants>DEBUG;IPHONE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <MtouchLink>None</MtouchLink>
-    <MtouchDebug>True</MtouchDebug>
-    <ConsolePause>False</ConsolePause>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
-    <DebugType>none</DebugType>
-    <Optimize>False</Optimize>
-    <OutputPath>bin\iPhoneSimulator\Release</OutputPath>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <MtouchLink>None</MtouchLink>
-    <ConsolePause>False</ConsolePause>
-    <DefineConstants>IPHONE</DefineConstants>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
-    <DebugSymbols>True</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>False</Optimize>
-    <OutputPath>bin\iPhone\Debug</OutputPath>
-    <DefineConstants>DEBUG;IPHONE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <MtouchDebug>True</MtouchDebug>
-    <CodesignKey>iPhone Developer</CodesignKey>
-    <ConsolePause>False</ConsolePause>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
-    <DebugType>none</DebugType>
-    <Optimize>False</Optimize>
-    <OutputPath>bin\iPhone\Release</OutputPath>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <ConsolePause>False</ConsolePause>
-    <CodesignKey>iPhone Developer</CodesignKey>
-    <DefineConstants>IPHONE</DefineConstants>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="System" />
-    <Reference Include="System.Xml" />
-    <Reference Include="System.Core" />
-    <Reference Include="monotouch" />
-    <Reference Include="OpenTK" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="Info.iOS.plist">
-      <Link>Info.plist</Link>
-    </None>
-    <None Include="GameThumbnail.png">
-      <Link>GameThumbnail.png</Link>
-    </None>
-    <None Include="Content\Block.bmp">
-      <Link>Content\Block.bmp</Link>
-    </None>
-    <None Include="Content\Person.bmp">
-      <Link>Content\Person.bmp</Link>
-    </None>
-  </ItemGroup>
-  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
-  <ItemGroup>
-    <Compile Include="Game1.cs">
-      <Link>Game1.cs</Link>
-    </Compile>
-    <Compile Include="Program.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <Content Include="Content\Block.xnb">
-      <Link>Content\Block.xnb</Link>
-    </Content>
-    <Content Include="Content\Person.xnb">
-      <Link>Content\Person.xnb</Link>
-    </Content>
-  </ItemGroup>
-</Project>

+ 0 - 82
PerPixelCollisionSample/PerPixelCollisionSample.MacOS.csproj

@@ -1,82 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProductVersion>10.0.0</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
-    <ProjectGuid>{56C67234-2829-4AB0-8FEE-C8D01617CDCE}</ProjectGuid>
-    <ProjectTypeGuids>{948B3504-5B70-4649-8FE4-BDE1FB46EC69};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
-    <OutputType>Exe</OutputType>
-    <RootNamespace>PerPixelCollisionSample</RootNamespace>
-    <AssemblyName>PerPixelCollisionSample</AssemblyName>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>True</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>False</Optimize>
-    <OutputPath>bin\Debug</OutputPath>
-    <DefineConstants>DEBUG;MONOMAC</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <ConsolePause>False</ConsolePause>
-    <EnableCodeSigning>False</EnableCodeSigning>
-    <CreatePackage>False</CreatePackage>
-    <EnablePackageSigning>False</EnablePackageSigning>
-    <IncludeMonoRuntime>False</IncludeMonoRuntime>
-    <UseSGen>False</UseSGen>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>none</DebugType>
-    <Optimize>False</Optimize>
-    <OutputPath>bin\Release</OutputPath>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <ConsolePause>False</ConsolePause>
-    <DefineConstants>MONOMAC</DefineConstants>
-    <EnableCodeSigning>False</EnableCodeSigning>
-    <CreatePackage>False</CreatePackage>
-    <EnablePackageSigning>False</EnablePackageSigning>
-    <IncludeMonoRuntime>False</IncludeMonoRuntime>
-    <UseSGen>False</UseSGen>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="System" />
-    <Reference Include="System.Xml" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Xml.Linq" />
-    <Reference Include="System.Drawing" />
-    <Reference Include="MonoMac" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="Info.plist">
-    </None>
-    <None Include="Game.ico" />
-    <None Include="GameThumbnail.png" />
-  </ItemGroup>
-  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
-  <Import Project="$(MSBuildExtensionsPath)\Mono\MonoMac\v0.0\Mono.MonoMac.targets" />
-  <ItemGroup>
-    <Folder Include="Content\" />
-  </ItemGroup>
-  <ItemGroup>
-    <Content Include="Content\Block.bmp" />
-    <Content Include="Content\Person.bmp" />
-    <Content Include="Content\Block.xnb" />
-    <Content Include="Content\Person.xnb" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="Game1.cs" />
-    <Compile Include="Program.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="..\..\MonoGame.Framework\MonoGame.Framework.MacOS.csproj">
-      <Project>{36C538E6-C32A-4A8D-A39C-566173D7118E}</Project>
-      <Name>MonoGame.Framework.MacOS</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\ThirdParty\Lidgren.Network\Lidgren.Network.MacOS.csproj">
-      <Project>{AE483C29-042E-4226-BA52-D247CE7676DA}</Project>
-      <Name>Lidgren.Network.MacOS</Name>
-    </ProjectReference>
-  </ItemGroup>
-</Project>

+ 28 - 18
PerPixelCollisionSample/PerPixelCollisionSample.sln

@@ -1,35 +1,45 @@
 
 
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual Studio 2010
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PerPixelCollisionSample", "PerPixelCollisionSample.csproj", "{56C67234-2829-4AB0-8FEE-C8D01617CDCE}"
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PerPixelCollisionSample.Core", "Core\PerPixelCollisionSample.Core.csproj", "{E1E2E3E4-E5E6-4E7E-8E9E-EAE1E2E3E4E5}"
 EndProject
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lidgren.Network.MacOS", "..\..\..\..\..\..\..\Users\Jimmy\Public\Share\MonoMacSource\kjpgit\MonoGame\ThirdParty\Lidgren.Network\Lidgren.Network.MacOS.csproj", "{AE483C29-042E-4226-BA52-D247CE7676DA}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PerPixelCollisionSample.Windows", "Platforms\Windows\PerPixelCollisionSample.Windows.csproj", "{56C67234-2829-4AB0-8FEE-C8D01617CDCE}"
 EndProject
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoGame.Framework.MacOS", "..\..\..\..\..\..\..\Users\Jimmy\Public\Share\MonoMacSource\kjpgit\MonoGame\MonoGame.Framework\MonoGame.Framework.MacOS.csproj", "{36C538E6-C32A-4A8D-A39C-566173D7118E}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PerPixelCollisionSample.DesktopGL", "Platforms\Desktop\PerPixelCollisionSample.DesktopGL.csproj", "{B8E4D2A1-4F54-4832-8C9E-DA2E8C5B9F72}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PerPixelCollisionSample.iOS", "Platforms\iOS\PerPixelCollisionSample.iOS.csproj", "{CE342066-BCCD-4989-A401-0D36287276EF}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PerPixelCollisionSample.Android", "Platforms\Android\PerPixelCollisionSample.Android.csproj", "{A1B2C3D4-E5F6-7890-1234-567890ABCDEF}"
 EndProject
 EndProject
 Global
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
 		Debug|Any CPU = Debug|Any CPU
 		Release|Any CPU = Release|Any CPU
 		Release|Any CPU = Release|Any CPU
-		Distribution|Any CPU = Distribution|Any CPU
 	EndGlobalSection
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{36C538E6-C32A-4A8D-A39C-566173D7118E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{36C538E6-C32A-4A8D-A39C-566173D7118E}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{36C538E6-C32A-4A8D-A39C-566173D7118E}.Distribution|Any CPU.ActiveCfg = Distribution|Any CPU
-		{36C538E6-C32A-4A8D-A39C-566173D7118E}.Distribution|Any CPU.Build.0 = Distribution|Any CPU
-		{36C538E6-C32A-4A8D-A39C-566173D7118E}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{36C538E6-C32A-4A8D-A39C-566173D7118E}.Release|Any CPU.Build.0 = Release|Any CPU
 		{56C67234-2829-4AB0-8FEE-C8D01617CDCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{56C67234-2829-4AB0-8FEE-C8D01617CDCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{56C67234-2829-4AB0-8FEE-C8D01617CDCE}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{56C67234-2829-4AB0-8FEE-C8D01617CDCE}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{56C67234-2829-4AB0-8FEE-C8D01617CDCE}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{56C67234-2829-4AB0-8FEE-C8D01617CDCE}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{56C67234-2829-4AB0-8FEE-C8D01617CDCE}.Release|Any CPU.Build.0 = Release|Any CPU
 		{56C67234-2829-4AB0-8FEE-C8D01617CDCE}.Release|Any CPU.Build.0 = Release|Any CPU
-		{AE483C29-042E-4226-BA52-D247CE7676DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{AE483C29-042E-4226-BA52-D247CE7676DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{AE483C29-042E-4226-BA52-D247CE7676DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{AE483C29-042E-4226-BA52-D247CE7676DA}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B8E4D2A1-4F54-4832-8C9E-DA2E8C5B9F72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B8E4D2A1-4F54-4832-8C9E-DA2E8C5B9F72}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B8E4D2A1-4F54-4832-8C9E-DA2E8C5B9F72}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B8E4D2A1-4F54-4832-8C9E-DA2E8C5B9F72}.Release|Any CPU.Build.0 = Release|Any CPU
+		{CE342066-BCCD-4989-A401-0D36287276EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CE342066-BCCD-4989-A401-0D36287276EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CE342066-BCCD-4989-A401-0D36287276EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CE342066-BCCD-4989-A401-0D36287276EF}.Release|Any CPU.Build.0 = Release|Any CPU
+		{A1B2C3D4-E5F6-7890-1234-567890ABCDEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A1B2C3D4-E5F6-7890-1234-567890ABCDEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A1B2C3D4-E5F6-7890-1234-567890ABCDEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A1B2C3D4-E5F6-7890-1234-567890ABCDEF}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
 	EndGlobalSection
 	EndGlobalSection
-	GlobalSection(MonoDevelopProperties) = preSolution
-		StartupItem = PerPixelCollisionSample.csproj
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {12345678-1234-5678-9012-123456789ABC}
 	EndGlobalSection
 	EndGlobalSection
 EndGlobal
 EndGlobal

+ 25 - 0
PerPixelCollisionSample/Platforms/Android/AndroidManifest.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+  <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />
+  
+  <uses-permission android:name="android.permission.INTERNET" />
+  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+  
+  <uses-feature android:glEsVersion="0x00020000" android:required="true" />
+  
+  <application android:allowBackup="true" android:label="Per Pixel Collision Sample">
+    <activity 
+      android:name=".MainActivity"
+      android:exported="true"
+      android:label="Per Pixel Collision Sample"
+      android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
+      android:screenOrientation="userLandscape"
+      android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
+      <intent-filter>
+        <action android:name="android.intent.action.MAIN" />
+        <category android:name="android.intent.category.LAUNCHER" />
+      </intent-filter>
+    </activity>
+  </application>
+</manifest>

+ 32 - 0
PerPixelCollisionSample/Platforms/Android/MainActivity.cs

@@ -0,0 +1,32 @@
+using Android.App;
+using Android.Content.PM;
+using Android.OS;
+using Android.Views;
+using Microsoft.Xna.Framework;
+
+namespace PerPixelCollision.Android
+{
+    [Activity(
+        Label = "Per Pixel Collision Sample", 
+        MainLauncher = true,
+        AlwaysRetainTaskState = true,
+        LaunchMode = LaunchMode.SingleInstance,
+        ScreenOrientation = ScreenOrientation.UserLandscape,
+        ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden | ConfigChanges.ScreenSize
+    )]
+    public class MainActivity : AndroidGameActivity
+    {
+        private PerPixelCollisionGame _game;
+        private View _view;
+
+        protected override void OnCreate(Bundle bundle)
+        {
+            base.OnCreate(bundle);
+
+            _game = new PerPixelCollisionGame();
+            _view = _game.Services.GetService(typeof(View)) as View;
+            SetContentView(_view);
+            _game.Run();
+        }
+    }
+}

+ 31 - 0
PerPixelCollisionSample/Platforms/Android/PerPixelCollisionSample.Android.csproj

@@ -0,0 +1,31 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net8.0-android</TargetFramework>
+    <OutputType>Exe</OutputType>
+    <RollForward>Major</RollForward>
+    <SupportedOSPlatformVersion>21</SupportedOSPlatformVersion>
+    <UseInterpreter>false</UseInterpreter>
+    <AssemblyName>PerPixelCollisionSample.Android</AssemblyName>
+    <RootNamespace>PerPixelCollision</RootNamespace>
+    <ApplicationId>com.monogame.perpixelcollisionsample</ApplicationId>
+    <ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
+    <ApplicationVersion>1</ApplicationVersion>
+    <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="MonoGame.Framework.Android" Version="3.8.*" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\PerPixelCollisionSample.Core.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Content Include="..\..\Core\Content\**\*.xnb" Link="Content\%(RecursiveDir)%(Filename)%(Extension)">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+
+</Project>

+ 4 - 0
PerPixelCollisionSample/Platforms/Android/Resources/values/strings.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">Per Pixel Collision Sample</string>
+</resources>

+ 29 - 0
PerPixelCollisionSample/Platforms/Desktop/PerPixelCollisionSample.DesktopGL.csproj

@@ -0,0 +1,29 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net8.0</TargetFramework>
+    <RollForward>Major</RollForward>
+    <PublishReadyToRun>false</PublishReadyToRun>
+    <TieredCompilation>false</TieredCompilation>
+    <AssemblyName>PerPixelCollisionSample.DesktopGL</AssemblyName>
+    <RootNamespace>PerPixelCollision</RootNamespace>
+    <ApplicationIcon>..\..\Core\Content\Game.ico</ApplicationIcon>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.*" />
+    <PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.*" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\PerPixelCollisionSample.Core.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Content Include="..\..\Core\Content\**\*.xnb" Link="Content\%(RecursiveDir)%(Filename)%(Extension)">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+
+</Project>

+ 14 - 0
PerPixelCollisionSample/Platforms/Desktop/Program.cs

@@ -0,0 +1,14 @@
+using System;
+
+namespace PerPixelCollision.Desktop
+{
+    public static class Program
+    {
+        [STAThread]
+        static void Main()
+        {
+            using (var game = new PerPixelCollisionGame())
+                game.Run();
+        }
+    }
+}

+ 31 - 0
PerPixelCollisionSample/Platforms/Windows/PerPixelCollisionSample.Windows.csproj

@@ -0,0 +1,31 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>WinExe</OutputType>
+    <TargetFramework>net8.0-windows</TargetFramework>
+    <RollForward>Major</RollForward>
+    <PublishReadyToRun>false</PublishReadyToRun>
+    <TieredCompilation>false</TieredCompilation>
+    <UseWindowsForms>true</UseWindowsForms>
+    <AssemblyName>PerPixelCollisionSample.Windows</AssemblyName>
+    <RootNamespace>PerPixelCollision</RootNamespace>
+    <ApplicationIcon>..\..\Core\Content\Game.ico</ApplicationIcon>
+    <ApplicationManifest>app.manifest</ApplicationManifest>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="MonoGame.Framework.WindowsDX" Version="3.8.*" />
+    <PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.*" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\PerPixelCollisionSample.Core.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Content Include="..\..\Core\Content\**\*.xnb" Link="Content\%(RecursiveDir)%(Filename)%(Extension)">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+
+</Project>

+ 27 - 0
PerPixelCollisionSample/Platforms/Windows/Program.cs

@@ -0,0 +1,27 @@
+//-----------------------------------------------------------------------------
+// Program.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+
+using System;
+
+namespace PerPixelCollision.Windows
+{
+    /// <summary>
+    /// The main class.
+    /// </summary>
+    public static class Program
+    {
+        /// <summary>
+        /// The main entry point for the application.
+        /// </summary>
+        [STAThread]
+        static void Main()
+        {
+            using (var game = new PerPixelCollisionGame())
+                game.Run();
+        }
+    }
+}

+ 41 - 0
PerPixelCollisionSample/Platforms/Windows/app.manifest

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
+  <assemblyIdentity version="1.0.0.0" name="PerPixelCollisionSample.Windows"/>
+  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+    <security>
+      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
+        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
+      </requestedPrivileges>
+    </security>
+  </trustInfo>
+
+  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+    <application>
+      <!-- A list of the Windows versions that this application has been tested on and is
+           is designed to work with. Uncomment the appropriate elements and Windows will 
+           automatically selected the most compatible environment. -->
+
+      <!-- Windows Vista -->
+      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
+
+      <!-- Windows 7 -->
+      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
+
+      <!-- Windows 8 -->
+      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
+
+      <!-- Windows 8.1 -->
+      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
+
+      <!-- Windows 10 -->
+      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
+
+    </application>
+  </compatibility>
+
+  <application xmlns="urn:schemas-microsoft-com:asm.v3">
+    <windowsSettings>
+    </windowsSettings>
+  </application>
+
+</assembly>

+ 16 - 0
PerPixelCollisionSample/Platforms/iOS/AppDelegate.cs

@@ -0,0 +1,16 @@
+using Foundation;
+using UIKit;
+
+namespace PerPixelCollision.iOS
+{
+    [Register("AppDelegate")]
+    public class AppDelegate : UIApplicationDelegate
+    {
+        private PerPixelCollisionGame game;
+        public override void FinishedLaunching(UIApplication app)
+        {
+            game = new PerPixelCollisionGame();
+            game.Run();
+        }
+    }
+}

+ 0 - 0
PerPixelCollisionSample/Info.plist → PerPixelCollisionSample/Platforms/iOS/Info.plist


+ 27 - 0
PerPixelCollisionSample/Platforms/iOS/PerPixelCollisionSample.iOS.csproj

@@ -0,0 +1,27 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net8.0-ios</TargetFramework>
+    <OutputType>Exe</OutputType>
+    <RollForward>Major</RollForward>
+    <IsPackable>false</IsPackable>
+    <SupportedOSPlatformVersion>11.0</SupportedOSPlatformVersion>
+    <AssemblyName>PerPixelCollisionSample.iOS</AssemblyName>
+    <RootNamespace>PerPixelCollision</RootNamespace>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="MonoGame.Framework.iOS" Version="3.8.*" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\PerPixelCollisionSample.Core.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Content Include="..\..\Core\Content\**\*.xnb" Link="Content\%(RecursiveDir)%(Filename)%(Extension)">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+
+</Project>

+ 13 - 0
PerPixelCollisionSample/Platforms/iOS/Program.cs

@@ -0,0 +1,13 @@
+using System;
+using UIKit;
+
+namespace PerPixelCollision.iOS
+{
+    public static class Program
+    {
+        public static void Main(string[] args)
+        {
+            UIApplication.Main(args, null, typeof(AppDelegate));
+        }
+    }
+}

+ 0 - 75
PerPixelCollisionSample/Program.cs

@@ -1,75 +0,0 @@
-#region File Description
-//-----------------------------------------------------------------------------
-// Program.cs
-//
-// Microsoft XNA Community Game Platform
-// Copyright (C) Microsoft Corporation. All rights reserved.
-//-----------------------------------------------------------------------------
-#endregion
-
-#region Using Statements
-using System;
-
-#if MONOMAC
-using MonoMac.Foundation;
-using MonoMac.AppKit;
-using MonoMac.ObjCRuntime;
-#elif IPHONE
-using MonoTouch.Foundation;
-using MonoTouch.UIKit;
-#endif
-#endregion
-
-namespace PerPixelCollision
-{
-#if MONOMAC
-	static class Program
-	{
-		/// <summary>
-		/// The main entry point for the application.
-		/// </summary>
-		static void Main (string[] args)
-		{
-			NSApplication.Init ();
-			
-			using (var p = new NSAutoreleasePool ()) {
-				NSApplication.SharedApplication.Delegate = new AppDelegate();
-				NSApplication.Main(args);
-			}
-		}
-	}
-	
-	class AppDelegate : NSApplicationDelegate
-	{
-		PerPixelCollisionGame game;
-		public override void FinishedLaunching (MonoMac.Foundation.NSObject notification)
-		{
-			game = new PerPixelCollisionGame();
-			game.Run ();
-
-		}
-		
-		public override bool ApplicationShouldTerminateAfterLastWindowClosed (NSApplication sender)
-		{
-			return true;
-		}
-	}
-#elif IPHONE
-	[Register ("AppDelegate")]
-	class Program : UIApplicationDelegate 
-	{
-        PerPixelCollisionGame game;
-		public override void FinishedLaunching (UIApplication app)
-		{
-			// Fun begins..
-			game = new PerPixelCollisionGame();
-			game.Run ();
-		}
-
-		static void Main (string [] args)
-		{
-			UIApplication.Main (args,null,"AppDelegate");
-		}
-	}
-#endif
-}

+ 147 - 0
PerPixelCollisionSample/README.md

@@ -0,0 +1,147 @@
+# Per Pixel Collision Sample
+
+This is a MonoGame sample that demonstrates per-pixel collision detection between sprites. The game features a person character that can be moved around the screen while blocks fall from the top. When the person touches a block, a collision is detected using per-pixel accuracy rather than simple bounding box collision.
+
+
+## Project Structure
+
+```
+PerPixelCollisionSample/
+│
+├── Core/
+│   ├── Game1.cs
+│   ├── Content/
+│   ├── GameThumbnail.png
+│   └── PerPixelCollisionSample.Core.csproj
+│
+├── Platforms/
+│   ├── Windows/
+│   │   ├── PerPixelCollisionSample.Windows.csproj
+│   │   └── app.manifest
+│   ├── Desktop/
+│   │   └── PerPixelCollisionSample.DesktopGL.csproj
+│   ├── Android/
+│   │   ├── PerPixelCollisionSample.Android.csproj
+│   │   ├── Program.cs
+│   │   ├── AndroidManifest.xml
+│   │   └── Resources/
+│   └── iOS/
+│       ├── PerPixelCollisionSample.iOS.csproj
+│       ├── Program.cs
+│       └── Info.plist
+│
+├── PerPixelCollisionSample.sln
+├── README.md
+└── .vscode/
+```
+
+**Platforms:**
+- **Windows** (`Platforms/Windows/PerPixelCollisionSample.Windows.csproj`) - Uses MonoGame.Framework.WindowsDX
+- **DesktopGL** (`Platforms/Desktop/PerPixelCollisionSample.DesktopGL.csproj`) - Cross-platform OpenGL version
+- **iOS** (`Platforms/iOS/PerPixelCollisionSample.iOS.csproj`) - iOS version targeting net8.0-ios
+- **Android** (`Platforms/Android/PerPixelCollisionSample.Android.csproj`) - Android version targeting net8.0-android
+
+## Building and Running
+
+### Prerequisites
+
+- .NET 8.0 SDK or later
+- For iOS development: Xcode and iOS development tools
+- For Android development: Android SDK and development tools
+
+### Building from Command Line
+
+
+#### Windows
+```bash
+dotnet build Platforms/Windows/PerPixelCollisionSample.Windows.csproj
+dotnet run --project Platforms/Windows/PerPixelCollisionSample.Windows.csproj
+```
+
+#### DesktopGL (Cross-platform)
+```bash
+dotnet build Platforms/Desktop/PerPixelCollisionSample.DesktopGL.csproj
+dotnet run --project Platforms/Desktop/PerPixelCollisionSample.DesktopGL.csproj
+```
+
+#### Android
+```bash
+dotnet build Platforms/Android/PerPixelCollisionSample.Android.csproj
+```
+
+#### iOS
+```bash
+dotnet build Platforms/iOS/PerPixelCollisionSample.iOS.csproj
+```
+
+### Building with Visual Studio
+
+Open `PerPixelCollisionSample.sln` in Visual Studio and build/run the desired platform target.
+
+### Building with VS Code
+
+This project includes VS Code configuration files:
+
+1. **Build Tasks**: Use Ctrl+Shift+P → "Tasks: Run Task" and select:
+   - `build-windows` - Build Windows version
+   - `build-desktopgl` - Build DesktopGL version
+   - `build-android` - Build Android version
+   - `build-ios` - Build iOS version
+
+2. **Run/Debug**: Use F5 or the Debug panel to run:
+   - "Launch Windows" - Run Windows version
+   - "Launch DesktopGL" - Run DesktopGL version
+   - "Launch Android" - Run Android version
+   - "Launch iOS" - Run iOS version
+
+## Game Controls
+
+- **Arrow Keys** or **WASD** - Move the person character around the screen
+- **Escape** - Exit the game
+
+## Technical Details
+
+### Per-Pixel Collision
+
+The sample demonstrates how to implement per-pixel collision detection by:
+
+1. Loading texture color data into arrays
+2. Transforming sprite rectangles based on position
+3. Checking overlapping pixels for transparency
+4. Only registering a collision when non-transparent pixels overlap
+
+### Content Pipeline
+
+The project uses pre-built `.xnb` content files located in the `Content/` folder:
+- `Block.xnb` - The falling block texture
+- `Person.xnb` - The player character texture
+
+These files are automatically copied to the output directory and loaded at runtime.
+
+## Platform-Specific Notes
+
+### Windows
+- Uses DirectX graphics backend
+- Includes application manifest for DPI awareness
+
+### DesktopGL
+- Uses OpenGL graphics backend
+- Runs on Windows, macOS, and Linux
+
+### iOS
+- Requires iOS 11.0 or later
+- Configured for landscape orientation
+- Uses the iOS-specific Program.cs in `Platforms/iOS/`
+
+### Android
+- Requires Android API level 21 or later
+- Uses Android-specific Activity in `Platforms/Android/`
+- Includes AndroidManifest.xml configuration
+
+## Dependencies
+
+All platforms use MonoGame 3.8.* NuGet packages:
+- Windows: `MonoGame.Framework.WindowsDX`
+- DesktopGL: `MonoGame.Framework.DesktopGL`
+- iOS: `MonoGame.Framework.iOS`
+- Android: `MonoGame.Framework.Android`