Преглед на файлове

MultiTouch updated to SDK project and MG 3.8.*

CartBlanche преди 1 месец
родител
ревизия
e141d6707c

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

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

+ 69 - 0
MultiTouch/.vscode/tasks.json

@@ -0,0 +1,69 @@
+{
+    "version": "2.0.0",
+    "tasks": [
+        {
+            "label": "build-windows",
+            "command": "dotnet",
+            "type": "process",
+            "args": [
+                "build",
+                "Platforms/Windows/MultiTouch.Windows.csproj",
+                "/property:GenerateFullPaths=true",
+                "/consoleloggerparameters:NoSummary"
+            ],
+            "group": "build",
+            "presentation": {
+                "reveal": "silent"
+            },
+            "problemMatcher": "$msCompile"
+        },
+        {
+            "label": "build-desktopgl",
+            "command": "dotnet",
+            "type": "process",
+            "args": [
+                "build",
+                "Platforms/Desktop/MultiTouch.DesktopGL.csproj",
+                "/property:GenerateFullPaths=true",
+                "/consoleloggerparameters:NoSummary"
+            ],
+            "group": "build",
+            "presentation": {
+                "reveal": "silent"
+            },
+            "problemMatcher": "$msCompile"
+        },
+        {
+            "label": "build-android",
+            "command": "dotnet",
+            "type": "process",
+            "args": [
+                "build",
+                "Platforms/Android/MultiTouch.Android.csproj",
+                "/property:GenerateFullPaths=true",
+                "/consoleloggerparameters:NoSummary"
+            ],
+            "group": "build",
+            "presentation": {
+                "reveal": "silent"
+            },
+            "problemMatcher": "$msCompile"
+        },
+        {
+            "label": "build-ios",
+            "command": "dotnet",
+            "type": "process",
+            "args": [
+                "build",
+                "Platforms/iOS/MultiTouch.iOS.csproj",
+                "/property:GenerateFullPaths=true",
+                "/consoleloggerparameters:NoSummary"
+            ],
+            "group": "build",
+            "presentation": {
+                "reveal": "silent"
+            },
+            "problemMatcher": "$msCompile"
+        }
+    ]
+}

+ 0 - 0
MultiTouch/Default.png → MultiTouch/Core/Content/Default.png


+ 0 - 0
MultiTouch/GameThumbnail.png → MultiTouch/Core/Content/GameThumbnail.png


BIN
MultiTouch/Core/Content/Icon.ico


+ 0 - 0
MultiTouch/Content/circle.png → MultiTouch/Core/Content/circle.png


+ 0 - 0
MultiTouch/Content/sqbrush.png → MultiTouch/Core/Content/sqbrush.png


+ 177 - 144
MultiTouch/MultiTouch.cs → MultiTouch/Core/Game1.cs

@@ -1,144 +1,177 @@
-using System;
-using System.Collections.Generic;
-
-using Microsoft.Xna.Framework;
-using Microsoft.Xna.Framework.Graphics;
-using Microsoft.Xna.Framework.Input;
-using Microsoft.Xna.Framework.Input.Touch;
-
-namespace Microsoft.Xna.Samples.MultiTouch
-{
-    /// <summary>
-    /// This is the main type for your game
-    /// </summary>
-    public class Game1 : Microsoft.Xna.Framework.Game
-    {
-        GraphicsDeviceManager graphics;
-        SpriteBatch spriteBatch;
-
-        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()
-        {
-            // TODO: Add your initialization logic here
-            acellerometer.Start();
-
-            base.Initialize();
-        }
-
-        /// <summary>
-        /// LoadContent will be called once per game and is the place to load
-        /// all of your content.
-        /// </summary>
-
-        Texture2D Brush;
-
-        TouchCollection touchStateCollection;
-        bool Cls = true;
-        List<Color> drawColors = new List<Color>();
-        Dictionary<int, Color> LineColors = new Dictionary<int, Color>();
-
-        int ShakeTime = 0;
-        Accelerometer acellerometer = new Accelerometer();
-        float LastAccelX = 0f;
-
-        protected override void LoadContent()
-        {
-            // Create a new SpriteBatch, which can be used to draw textures.
-            spriteBatch = new SpriteBatch(GraphicsDevice);
-
-            // Load in a single pixel to use as the brush
-            Brush = Content.Load<Texture2D>("sqbrush");
-
-            // Set the random colors for multi touch painting
-            drawColors.Add(Color.Orange);
-            drawColors.Add(Color.Yellow);
-            drawColors.Add(Color.Green);
-            drawColors.Add(Color.Cyan);
-            drawColors.Add(Color.HotPink);
-        }
-
-        /// <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)
-        {
-            // Allows the game to exit
-            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
-                this.Exit();
-
-            // Check if the x force on the Zune has changed by more than 0.4g in the past half second - if so, it's shaking
-            ShakeTime += gameTime.TotalGameTime.Milliseconds;
-            if (ShakeTime >= 500)
-            {
-                Vector3 acceleration = acellerometer.CurrentValue.Acceleration;
-                if (Math.Abs(acceleration.X - LastAccelX) > 0.4)
-                {
-                    Cls = true;
-                }
-                LastAccelX = acceleration.X;
-                ShakeTime = 0;
-            }
-
-            // Update touch panel state
-            touchStateCollection = TouchPanel.GetState();
-			
-            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)
-        {
-            if (Cls)
-            {
-                Cls = false;
-                graphics.GraphicsDevice.Clear(Color.Black);
-            }
-
-            spriteBatch.Begin(SpriteSortMode.Deferred,BlendState.AlphaBlend);
-
-			foreach (TouchLocation t in touchStateCollection)
-            {
-				TouchLocation PrevLocation = new TouchLocation();
-                if (t.TryGetPreviousLocation(out PrevLocation))
-                {
-                    if (!LineColors.ContainsKey(t.Id))
-                    {
-                        if (touchStateCollection.Count > 1)
-                        {
-                            Random randomizer = new Random();
-                            LineColors[t.Id] = drawColors[randomizer.Next(0, 4)];
-                        }
-                        else
-                        {
-                            LineColors[t.Id] = Color.White;
-                        }
-                    }
-
-                    spriteBatch.Draw(Brush, PrevLocation.Position, null, 
-					                 LineColors[t.Id], (float)Math.Atan2((double)(t.Position.Y - PrevLocation.Position.Y), (double)(t.Position.X - PrevLocation.Position.X)), Vector2.Zero, 
-					                 new Vector2(Vector2.Distance(PrevLocation.Position, t.Position), 1f), SpriteEffects.None, 0f);
-                }
-            }
-
-            spriteBatch.End();
-            
-            base.Draw(gameTime);
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+using Microsoft.Xna.Framework.Input.Touch;
+
+namespace Microsoft.Xna.Samples.MultiTouch
+{
+    /// <summary>
+    /// This is the main type for your game
+    /// </summary>
+    public class Game1 : Game
+    {
+        private GraphicsDeviceManager graphics;
+        private SpriteBatch spriteBatch;
+
+        public Game1()
+        {
+            graphics = new GraphicsDeviceManager(this);
+            IsMouseVisible = true;
+            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()
+        {
+            // Enable multi-touch
+            TouchPanel.EnabledGestures = GestureType.None;
+            
+            base.Initialize();
+        }
+
+        /// <summary>
+        /// LoadContent will be called once per game and is the place to load
+        /// all of your content.
+        /// </summary>
+
+        private Texture2D Brush;
+
+        private TouchCollection touchStateCollection;
+        private bool Cls = true;
+        private List<Color> drawColors = new List<Color>();
+        private Dictionary<int, Color> LineColors = new Dictionary<int, Color>();
+
+        private int ShakeTime = 0;
+
+        protected override void LoadContent()
+        {
+            // Create a new SpriteBatch, which can be used to draw textures.
+            spriteBatch = new SpriteBatch(GraphicsDevice);
+
+            // Load in a single pixel to use as the brush
+            Brush = Content.Load<Texture2D>("sqbrush");
+
+            // Set the random colors for multi touch painting
+            drawColors.Add(Color.Orange);
+            drawColors.Add(Color.Yellow);
+            drawColors.Add(Color.Green);
+            drawColors.Add(Color.Cyan);
+            drawColors.Add(Color.HotPink);
+        }
+
+        /// <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>
+        private Vector2? prevMousePos = null;
+        private bool prevMouseDown = false;
+
+        protected override void Update(GameTime gameTime)
+        {
+            // Allows the game to exit
+            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed
+            || Keyboard.GetState().IsKeyDown(Keys.Escape))
+                this.Exit();
+
+            // Simple shake detection using gamepad or keyboard
+            ShakeTime += (int)gameTime.ElapsedGameTime.TotalMilliseconds;
+            if (ShakeTime >= 500)
+            {
+                // Clear screen on Space key press or gamepad button press
+                if (Keyboard.GetState().IsKeyDown(Keys.Space) ||
+                    GamePad.GetState(PlayerIndex.One).Buttons.A == ButtonState.Pressed)
+                {
+                    Cls = true;
+                }
+                ShakeTime = 0;
+            }
+
+            // Update touch panel state
+            touchStateCollection = TouchPanel.GetState();
+
+            // Mouse input tracking
+            var mouseState = Mouse.GetState();
+            bool mouseDown = mouseState.LeftButton == ButtonState.Pressed;
+            if (!mouseDown)
+            {
+                prevMousePos = null;
+            }
+            prevMouseDown = mouseDown;
+
+            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)
+        {
+            if (Cls)
+            {
+                Cls = false;
+                graphics.GraphicsDevice.Clear(Color.Black);
+            }
+
+            spriteBatch.Begin(SpriteSortMode.Deferred,BlendState.AlphaBlend);
+            // Touch drawing
+            foreach (TouchLocation t in touchStateCollection)
+            {
+                TouchLocation PrevLocation = new TouchLocation();
+                if (t.TryGetPreviousLocation(out PrevLocation))
+                {
+                    if (!LineColors.ContainsKey(t.Id))
+                    {
+                        if (touchStateCollection.Count > 1)
+                        {
+                            Random randomizer = new Random();
+                            LineColors[t.Id] = drawColors[randomizer.Next(0, 4)];
+                        }
+                        else
+                        {
+                            LineColors[t.Id] = Color.White;
+                        }
+                    }
+                    spriteBatch.Draw(Brush, PrevLocation.Position, null, 
+                        LineColors[t.Id], (float)Math.Atan2((double)(t.Position.Y - PrevLocation.Position.Y), (double)(t.Position.X - PrevLocation.Position.X)), Vector2.Zero, 
+                        new Vector2(Vector2.Distance(PrevLocation.Position, t.Position), 1f), SpriteEffects.None, 0f);
+                }
+            }
+            // Mouse drawing (parity with touch)
+            var mouseState = Mouse.GetState();
+            bool mouseDown = mouseState.LeftButton == ButtonState.Pressed;
+            Vector2 mousePos = new Vector2(mouseState.X, mouseState.Y);
+            if (mouseDown)
+            {
+                if (prevMousePos.HasValue)
+                {
+                    // Use same color logic as touch
+                    Color mouseColor = Color.White;
+                    if (touchStateCollection.Count > 1)
+                    {
+                        Random randomizer = new Random();
+                        mouseColor = drawColors[randomizer.Next(0, 4)];
+                    }
+                    spriteBatch.Draw(Brush, prevMousePos.Value, null,
+                        mouseColor, (float)Math.Atan2(mousePos.Y - prevMousePos.Value.Y, mousePos.X - prevMousePos.Value.X), Vector2.Zero,
+                        new Vector2(Vector2.Distance(prevMousePos.Value, mousePos), 1f), SpriteEffects.None, 0f);
+                }
+                prevMousePos = mousePos;
+            }
+            else
+            {
+                prevMousePos = null;
+            }
+            spriteBatch.End();
+            base.Draw(gameTime);
+        }
+    }
+}

+ 12 - 0
MultiTouch/Core/MultiTouch.Core.csproj

@@ -0,0 +1,12 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>net8.0</TargetFramework>
+    <AssemblyName>MultiTouch.Core</AssemblyName>
+    <RootNamespace>Microsoft.Xna.Samples.MultiTouch</RootNamespace>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.*" />
+  </ItemGroup>
+</Project>

+ 0 - 120
MultiTouch/MultiTouch.iOS.csproj

@@ -1,120 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
-  <PropertyGroup>
-    <ProjectGuid>{DF8DF5E3-2FF4-46DD-9EE0-AE3C9923C6BA}</ProjectGuid>
-    <ProjectTypeGuids>{6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
-    <ProductVersion>9.0.21022</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
-    <OutputType>Exe</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>MultiTouch</RootNamespace>
-    <Thumbnail>GameThumbnail.png</Thumbnail>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
-    <DebugSymbols>True</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>False</Optimize>
-    <OutputPath>bin\iPhoneSimulator\Debug</OutputPath>
-    <DefineConstants>DEBUG</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
-    <MtouchLink>None</MtouchLink>
-    <MtouchDebug>True</MtouchDebug>
-    <MtouchI18n />
-    <MtouchUseArmv7>false</MtouchUseArmv7>
-    <AssemblyName>MultiTouch</AssemblyName>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
-    <DebugType>none</DebugType>
-    <Optimize>True</Optimize>
-    <OutputPath>bin\iPhoneSimulator\Release</OutputPath>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <MtouchI18n />
-    <MtouchUseArmv7>false</MtouchUseArmv7>
-    <AssemblyName>MultiTouch</AssemblyName>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
-    <DebugSymbols>True</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>False</Optimize>
-    <OutputPath>bin\iPhone\Debug</OutputPath>
-    <DefineConstants>DEBUG</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <MtouchDebug>True</MtouchDebug>
-    <MtouchI18n />
-    <MtouchSdkVersion>4.0</MtouchSdkVersion>
-    <MtouchUseArmv7>false</MtouchUseArmv7>
-    <AssemblyName>MultiTouch</AssemblyName>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
-    <DebugType>none</DebugType>
-    <Optimize>True</Optimize>
-    <OutputPath>bin\iPhone\Release</OutputPath>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <MtouchI18n />
-    <CodesignKey>iPhone Developer</CodesignKey>
-    <MtouchSdkVersion>4.0</MtouchSdkVersion>
-    <MtouchUseArmv7>false</MtouchUseArmv7>
-    <AssemblyName>MultiTouch</AssemblyName>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugType>none</DebugType>
-    <Optimize>False</Optimize>
-    <OutputPath>bin\Debug</OutputPath>
-    <WarningLevel>4</WarningLevel>
-    <AssemblyName>MonoGameSamplesMultiTouch</AssemblyName>
-    <MtouchUseArmv7>false</MtouchUseArmv7>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>none</DebugType>
-    <Optimize>False</Optimize>
-    <OutputPath>bin\Release</OutputPath>
-    <WarningLevel>4</WarningLevel>
-    <AssemblyName>MonoGameSamplesMultiTouch</AssemblyName>
-    <MtouchUseArmv7>false</MtouchUseArmv7>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="System" />
-    <Reference Include="System.Xml" />
-    <Reference Include="System.Core" />
-    <Reference Include="monotouch" />
-  </ItemGroup>
-  <ItemGroup>
-    <Folder Include="Content\" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="Program.cs" />
-    <Compile Include="MultiTouch.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="GameThumbnail.png" />
-    <None Include="Info.iOS.plist">
-      <Link>Info.plist</Link>
-    </None>
-  </ItemGroup>
-  <ItemGroup>
-    <Content Include="Content\circle.png">
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </Content>
-    <Content Include="Content\sqbrush.png">
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </Content>
-    <Content Include="Default.png">
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </Content>
-  </ItemGroup>
-  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
-       Other similar extension points exist, see Microsoft.Common.targets.
-  <Target Name="BeforeBuild">
-  </Target>
-  <Target Name="AfterBuild">
-  </Target>
-  -->
-</Project>

+ 45 - 0
MultiTouch/MultiTouch.sln

@@ -0,0 +1,45 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.2.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultiTouch.Windows", "MultiTouch.Windows.csproj", "{A7D5D4E1-4F8C-4D5B-8E9A-1B2C3D4E5F60}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultiTouch.Windows", "Platforms\Windows\MultiTouch.Windows.csproj", "{A7D5D4E1-4F8C-4D5B-8E9A-1B2C3D4E5F60}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultiTouch.DesktopGL", "Platforms\Desktop\MultiTouch.DesktopGL.csproj", "{B8E6E5F2-5F9D-4E6C-9FAB-2C3D4E5F6A71}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultiTouch.iOS", "Platforms\iOS\MultiTouch.iOS.csproj", "{C9F7F6F3-6FAE-4F7D-A0BC-3D4E5F6A7B82}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultiTouch.Android", "Platforms\Android\MultiTouch.Android.csproj", "{DAF8F7F4-7FBF-4F8E-B1CD-4E5F6A7B8C93}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultiTouch.Core", "Core\MultiTouch.Core.csproj", "{EAF9F8F5-8FC0-4F9F-B2DE-5F6A7B8C9D04}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{A7D5D4E1-4F8C-4D5B-8E9A-1B2C3D4E5F60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A7D5D4E1-4F8C-4D5B-8E9A-1B2C3D4E5F60}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A7D5D4E1-4F8C-4D5B-8E9A-1B2C3D4E5F60}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A7D5D4E1-4F8C-4D5B-8E9A-1B2C3D4E5F60}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B8E6E5F2-5F9D-4E6C-9FAB-2C3D4E5F6A71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B8E6E5F2-5F9D-4E6C-9FAB-2C3D4E5F6A71}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B8E6E5F2-5F9D-4E6C-9FAB-2C3D4E5F6A71}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B8E6E5F2-5F9D-4E6C-9FAB-2C3D4E5F6A71}.Release|Any CPU.Build.0 = Release|Any CPU
+		{C9F7F6F3-6FAE-4F7D-A0BC-3D4E5F6A7B82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{C9F7F6F3-6FAE-4F7D-A0BC-3D4E5F6A7B82}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{C9F7F6F3-6FAE-4F7D-A0BC-3D4E5F6A7B82}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{C9F7F6F3-6FAE-4F7D-A0BC-3D4E5F6A7B82}.Release|Any CPU.Build.0 = Release|Any CPU
+		{DAF8F7F4-7FBF-4F8E-B1CD-4E5F6A7B8C93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{DAF8F7F4-7FBF-4F8E-B1CD-4E5F6A7B8C93}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{DAF8F7F4-7FBF-4F8E-B1CD-4E5F6A7B8C93}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{DAF8F7F4-7FBF-4F8E-B1CD-4E5F6A7B8C93}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {A234CC61-6902-4EF3-9C97-BBEBCF832AC5}
+	EndGlobalSection
+EndGlobal

+ 25 - 0
MultiTouch/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" 
+          package="com.yourcompany.multitouch" 
+          android:versionCode="1" 
+          android:versionName="1.0" 
+          android:installLocation="auto">
+  
+  <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
+  
+  <application android:label="MultiTouch" android:icon="@drawable/icon">
+    <activity android:name="microsoft.xna.samples.multitouch.Activity1"
+              android:label="MultiTouch"
+              android:exported="true"
+              android:screenOrientation="fullUser"
+              android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+              android:configChanges="orientation|keyboard|keyboardHidden|screenSize|screenLayout">
+      <intent-filter>
+        <action android:name="android.intent.action.MAIN" />
+        <category android:name="android.intent.category.LAUNCHER" />
+      </intent-filter>
+    </activity>
+  </application>
+  
+  <uses-feature android:glEsVersion="0x00020000" android:required="true" />
+</manifest>

+ 35 - 0
MultiTouch/Platforms/Android/MainActivity.cs

@@ -0,0 +1,35 @@
+// ...existing code from Activity1.cs will be moved here...
+using Android.App;
+using Android.Content.PM;
+using Android.OS;
+using Android.Views;
+using Android.Widget;
+using Microsoft.Xna.Framework;
+
+namespace Microsoft.Xna.Samples.MultiTouch
+{
+    [Activity(
+        Label = "MultiTouch",
+        MainLauncher = true,
+        Icon = "@drawable/icon",
+        AlwaysRetainTaskState = true,
+        LaunchMode = LaunchMode.SingleInstance,
+        ScreenOrientation = ScreenOrientation.FullUser,
+        ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden | ConfigChanges.ScreenSize | ConfigChanges.ScreenLayout)]
+    public class Activity1 : AndroidGameActivity
+    {
+        private Game1 _game;
+
+        protected override void OnCreate(Bundle bundle)
+        {
+            base.OnCreate(bundle);
+
+            _game = new Game1();
+            var frameLayout = new FrameLayout(this);
+            frameLayout.AddView((View)_game.Services.GetService(typeof(View)));
+
+            SetContentView(frameLayout);
+            _game.Run();
+        }
+    }
+}

+ 21 - 0
MultiTouch/Platforms/Android/MultiTouch.Android.csproj

@@ -0,0 +1,21 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net8.0-android</TargetFramework>
+    <RootNamespace>Microsoft.Xna.Samples.MultiTouch</RootNamespace>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\MultiTouch.Core.csproj" />
+    <PackageReference Include="MonoGame.Framework.Android" Version="3.8.*" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Content Include="..\..\..\CompiledContent\Android\Content\Textures\circle.xnb" Link="Content\circle.xnb">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="..\..\..\CompiledContent\Android\Content\Textures\sqbrush.xnb" Link="Content\sqbrush.xnb">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+</Project>

BIN
MultiTouch/Platforms/Android/Resources/drawable/icon.png


+ 21 - 0
MultiTouch/Platforms/Desktop/MultiTouch.DesktopGL.csproj

@@ -0,0 +1,21 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net8.0</TargetFramework>
+    <RootNamespace>Microsoft.Xna.Samples.MultiTouch</RootNamespace>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\MultiTouch.Core.csproj" />
+    <PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.*" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Content Include="..\..\..\CompiledContent\Windows\Content\Textures\circle.xnb" Link="Content\circle.xnb">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="..\..\..\CompiledContent\Windows\Content\Textures\sqbrush.xnb" Link="Content\sqbrush.xnb">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+</Project>

+ 19 - 0
MultiTouch/Platforms/Desktop/Program.cs

@@ -0,0 +1,19 @@
+// ...existing code from Program.DesktopGL.cs will be moved here...
+using System;
+using Microsoft.Xna.Framework;
+
+namespace Microsoft.Xna.Samples.MultiTouch
+{
+    /// <summary>
+    /// The main entry point for DesktopGL.
+    /// </summary>
+    public static class Program
+    {
+        [STAThread]
+        static void Main()
+        {
+            using var game = new Game1();
+            game.Run();
+        }
+    }
+}

+ 22 - 0
MultiTouch/Platforms/Windows/MultiTouch.Windows.csproj

@@ -0,0 +1,22 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>WinExe</OutputType>
+    <TargetFramework>net8.0-windows</TargetFramework>
+    <UseWindowsForms>false</UseWindowsForms>
+    <RootNamespace>Microsoft.Xna.Samples.MultiTouch</RootNamespace>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\MultiTouch.Core.csproj" />
+    <PackageReference Include="MonoGame.Framework.WindowsDX" Version="3.8.*" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Content Include="..\..\..\CompiledContent\Windows\Content\Textures\circle.xnb" Link="Content\circle.xnb">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="..\..\..\CompiledContent\Windows\Content\Textures\sqbrush.xnb" Link="Content\sqbrush.xnb">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+</Project>

+ 19 - 0
MultiTouch/Platforms/Windows/Program.cs

@@ -0,0 +1,19 @@
+// ...existing code from Program.Windows.cs will be moved here...
+using System;
+using Microsoft.Xna.Framework;
+
+namespace Microsoft.Xna.Samples.MultiTouch
+{
+    /// <summary>
+    /// The main entry point for Windows DirectX.
+    /// </summary>
+    public static class Program
+    {
+        [STAThread]
+        static void Main()
+        {
+            using var game = new Game1();
+            game.Run();
+        }
+    }
+}

+ 39 - 0
MultiTouch/Platforms/iOS/Info.plist

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDisplayName</key>
+	<string>MultiTouch</string>
+	<key>CFBundleIconFiles</key>
+	<array>
+		<string>GameThumbnail.png</string>
+	</array>
+	<key>CFBundleIdentifier</key>
+	<string>com.yourcompany.multitouch</string>
+	<key>MinimumOSVersion</key>
+	<string>11.0</string>
+	<key>UIDeviceFamily</key>
+	<array>
+		<integer>1</integer>
+		<integer>2</integer>
+	</array>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+	</array>
+	<key>UISupportedInterfaceOrientations~ipad</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+	</array>
+	<key>UIRequiredDeviceCapabilities</key>
+	<array>
+		<string>opengles-2</string>
+	</array>
+</dict>
+</plist>

+ 21 - 0
MultiTouch/Platforms/iOS/MultiTouch.iOS.csproj

@@ -0,0 +1,21 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net8.0-ios</TargetFramework>
+    <RootNamespace>Microsoft.Xna.Samples.MultiTouch</RootNamespace>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\MultiTouch.Core.csproj" />
+    <PackageReference Include="MonoGame.Framework.iOS" Version="3.8.*" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Content Include="..\..\..\CompiledContent\iOS\Content\Textures\circle.xnb" Link="Content\circle.xnb">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="..\..\..\CompiledContent\iOS\Content\Textures\sqbrush.xnb" Link="Content\sqbrush.xnb">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+</Project>

+ 27 - 30
MultiTouch/Program.cs → MultiTouch/Platforms/iOS/Program.cs

@@ -1,30 +1,27 @@
-#region Using Statements
-using System;
-using MonoTouch.Foundation;
-using MonoTouch.UIKit;
-using Microsoft.Xna;
-using Microsoft.Xna.Framework.Media;
-#endregion
-
-namespace Microsoft.Xna.Samples.MultiTouch
-{
-    [Register("AppDelegate")]
-    class Program : UIApplicationDelegate
-    {
-        Game1 game;
-        public override void FinishedLaunching(UIApplication app)
-        {
-            // Fun begins..
-            game = new Game1();
-            game.Run();
-        }
-
-        /// <summary>
-        /// The main entry point for the application.
-        /// </summary>
-        static void Main(string[] args)
-        {
-            UIApplication.Main(args, null, "AppDelegate");
-        }
-    }    
-}
+// ...existing code from Program.iOS.cs will be moved here...
+using System;
+using Foundation;
+using UIKit;
+
+namespace Microsoft.Xna.Samples.MultiTouch
+{
+    [Register("AppDelegate")]
+    public class AppDelegate : UIApplicationDelegate
+    {
+        private Game1 game;
+
+        public override void FinishedLaunching(UIApplication app)
+        {
+            game = new Game1();
+            game.Run();
+        }
+
+        /// <summary>
+        /// The main entry point for the application.
+        /// </summary>
+        static void Main(string[] args)
+        {
+            UIApplication.Main(args, null, typeof(AppDelegate));
+        }
+    }
+}

+ 123 - 0
MultiTouch/README.md

@@ -0,0 +1,123 @@
+# MultiTouch Sample
+
+A MonoGame 3.8.* sample demonstrating multi-touch input and drawing functionality. This sample allows users to draw on the screen using touch input or mouse, with support for multiple simultaneous touch points.
+
+## Features
+
+- Multi-touch drawing support
+- Colorful brush strokes for multiple touch points
+- Screen clearing functionality (Space key or gamepad A button)
+- Cross-platform support for Windows, DesktopGL, iOS, and Android
+
+## Platforms & Structure
+
+This sample uses a modern, multi-project structure:
+
+- `/Core` — Shared game logic (`Game1.cs`, `MultiTouch.Core.csproj`)
+- `/Platforms/Windows` — Windows DirectX entry point and project
+- `/Platforms/Desktop` — DesktopGL entry point and project
+- `/Platforms/Android` — Android entry point and project
+- `/Platforms/iOS` — iOS entry point and project
+- `/Content` — Game assets (textures)
+
+Each platform folder contains its own `.csproj` and entry point, referencing the shared `/Core` project.
+
+## Prerequisites
+
+- .NET 8.0 or later
+- MonoGame 3.8.* (installed via NuGet packages)
+- For Android: Android SDK and appropriate build tools
+- For iOS: Xcode and iOS development tools (macOS only)
+
+## Building and Running
+
+### Visual Studio
+
+1. Open `MultiTouch.sln` in Visual Studio
+2. Set the desired platform project as the startup project (e.g., `Platforms/Windows/MultiTouch.Windows.csproj`)
+3. Build and run (F5)
+
+### VS Code
+
+1. Open the project folder in VS Code
+2. Use Ctrl+Shift+P and run "Tasks: Run Task"
+3. Select one of:
+   - `build-windows` / `run-windows`
+   - `build-desktopgl` / `run-desktopgl`
+   - `build-android` / `run-android`
+   - `build-ios` / `run-ios`
+
+Or use the launch configurations in `.vscode/launch.json` for debugging.
+
+### Command Line
+
+#### Windows
+```pwsh
+ dotnet build Platforms/Windows/MultiTouch.Windows.csproj
+ dotnet run --project Platforms/Windows/MultiTouch.Windows.csproj
+```
+#### DesktopGL
+```pwsh
+ dotnet build Platforms/Desktop/MultiTouch.DesktopGL.csproj
+ dotnet run --project Platforms/Desktop/MultiTouch.DesktopGL.csproj
+```
+#### Android
+```pwsh
+ dotnet build Platforms/Android/MultiTouch.Android.csproj
+ # Deploy to connected device or emulator
+ dotnet build Platforms/Android/MultiTouch.Android.csproj -t:Run
+```
+#### iOS (macOS only)
+```pwsh
+ dotnet build Platforms/iOS/MultiTouch.iOS.csproj
+ # Deploy to connected device or simulator
+ dotnet build Platforms/iOS/MultiTouch.iOS.csproj -t:Run
+```
+
+## Controls
+
+- **Touch/Mouse**: Draw on the screen
+- **Space** or **Gamepad A**: Clear the screen
+- **Escape** or **Gamepad Back**: Exit the application
+
+## Project Structure
+
+```
+/Core
+    Game1.cs
+    MultiTouch.Core.csproj
+/Platforms
+    /Windows
+        MultiTouch.Windows.csproj
+        Program.cs
+    /Desktop
+        MultiTouch.DesktopGL.csproj
+        Program.cs
+    /Android
+        MultiTouch.Android.csproj
+        Activity1.cs
+    /iOS
+        MultiTouch.iOS.csproj
+        Program.cs
+/Content
+    sqbrush.png
+    circle.png
+```
+
+## Content
+
+The sample uses the following content files:
+- `sqbrush.png` — Brush texture for drawing
+- `circle.png` — Circle texture (unused in current implementation)
+
+These are included as `.xnb` files and loaded directly without requiring MonoGame Content Pipeline compilation.
+
+## Notes
+
+- This project has been modernized to use:
+  - .NET 8.0 target frameworks
+  - SDK-style project files
+  - MonoGame 3.8.* NuGet packages
+  - Modern C# code patterns
+  - Platform-specific folders and entry points (no more `#if/#endif` blocks)
+- The accelerometer functionality from the original sample has been replaced with keyboard/gamepad input for cross-platform compatibility