Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
5945f88
Add folder structure for mobile deployment tutorials.
olivegamestudio Jun 12, 2025
b422687
Feature/mobile deployment 1 (#1)
olivegamestudio Aug 16, 2025
cdaa253
Removed 04 debugging locally folder.
olivegamestudio Aug 21, 2025
9a22ba8
Added xml tag.
olivegamestudio Aug 28, 2025
f20f79d
Updated details about Rider and VS Code being usable.
olivegamestudio Aug 28, 2025
f66fa9d
Added relation about touchpanel to the dungeon slime example. The gam…
olivegamestudio Aug 28, 2025
ba1387c
Added a section about the bundle identifier.
olivegamestudio Aug 28, 2025
cb5c95a
Remove contractions. You'll, let's etc. (#15)
olivegamestudio Sep 1, 2025
60acf90
Merge branch 'main' into feature/MobileDeployment
SimonDarksideJ Sep 1, 2025
3173777
Merge branch 'main' into feature/MobileDeployment
SimonDarksideJ Sep 2, 2025
dec9803
Patch path to 2D tutorial
SimonDarksideJ Sep 2, 2025
68091a4
No toc in "building 2D games", updated to index page
SimonDarksideJ Sep 2, 2025
ed11443
Set link to the original tutorial for continuation.
olivegamestudio Sep 2, 2025
85bf058
Added link to Android workload. (#16)
olivegamestudio Sep 2, 2025
cfab710
Updated existing images to be figures and follow tutorial style. (#17)
olivegamestudio Sep 2, 2025
ac7cc3b
Broke up publishing into smaller parts - publishing, ios, android, ch…
olivegamestudio Sep 2, 2025
c0479e3
Added link to microsoft site about android getting started.
olivegamestudio Sep 3, 2025
f797549
Added maui link.
olivegamestudio Sep 3, 2025
cb42e6e
Add some more details about registering for developer account. (#20)
olivegamestudio Sep 6, 2025
295fae7
Add tip about disabling encryption dialog. (#21)
olivegamestudio Sep 14, 2025
90b9914
Added link to pair visual studio with mac.
olivegamestudio Sep 14, 2025
2676f5c
WIP minor changes to indicate bits need tweaking.
olivegamestudio Sep 28, 2025
f52ec09
Polishing.
olivegamestudio Sep 28, 2025
b1af154
Updates to conclusion.
olivegamestudio Sep 28, 2025
a5906bb
Updated ios publishing and polish.
olivegamestudio Oct 3, 2025
0e62b4a
Add note about signing
olivegamestudio Oct 3, 2025
69be315
Add section about API usage descriptions.
olivegamestudio Oct 12, 2025
2b159a3
Added section about API descriptions and tidy up some of sections.
olivegamestudio Oct 12, 2025
2fbf92d
Hookup to the tutorial.
olivegamestudio Oct 12, 2025
7f134a6
Prefix with `Chapter`.
olivegamestudio Oct 12, 2025
e9e2421
Add link to tutorial.
olivegamestudio Oct 12, 2025
3f8f99a
More tidyups.
olivegamestudio Oct 12, 2025
5af3400
Tidyup tabs.
olivegamestudio Oct 12, 2025
b484644
Updated scripts for .NET 8, 9 and 10. Tahoe 26 property.
olivegamestudio Oct 22, 2025
2dd9925
Add information about `UseInterpreter` and `CheckEolTargetFramework` …
olivegamestudio Oct 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
title: "Chapter 01: Setting Up MonoGame for Android and iOS Development"
description: "Get started with MonoGame mobile development by setting up your development environment, tools, and SDKs for Android and iOS platforms."
---

# Getting Started and Overview

This tutorial extends the [Dungeon Slime](https://github.com/MonoGame/MonoGame.Samples/tree/3.8.4/Tutorials/learn-monogame-2d) tutorial to mobile platforms. If you have not completed the desktop tutorial yet, we recommend finishing it first as we will be building directly on that foundation.

## What You Will Learn

By the end of this mobile tutorial series, you will have:
- Ported the **Dungeon Slime** game to run on Android and iOS
- Implemented touch controls to replace mouse and keyboard input
- Set up cross-platform project architecture for code sharing
- Learned debugging techniques for mobile development
- Published your game to both Google Play and the App Store
- Created automated deployment workflows

# Development Requirements

## Android Development

**Platform Support:** Android development can be accomplished on either Windows PC or Mac.

> [!NOTE]
> ARM64 variants of Windows do not run the Android simulator very well.
>

**Required Tools:**
- **Android Device Manager** - Used to set up simulators (accessible through Visual Studio)
- **Android SDK Manager** - Used to install the SDK platforms
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iOS mentions having an iOS developer account. Is the same setup not also required for Android?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A Google Developer account is required to publish, but not to build I think.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added comment to page to say that you do not need a paid developer account to build locally and test.


These tools are available by installing the Android Workload using the [MonoGame Getting Started Instructions](../../../../getting_started/platforms.md).

**Additional Notes:** For Windows users, ensure **Hyper-V** is enabled for better emulator performance. On Mac, Android Studio can be used alongside Rider for advanced emulator configurations.

For more information visit about getting started with Android development:

- [Getting Started with Android Development](https://learn.microsoft.com/en-us/dotnet/android/getting-started/installation/)
- [Getting Started with Maui Development](https://learn.microsoft.com/en-us/dotnet/maui/get-started/installation)

To release your game to the **Google Play Store**, you will need to sign up for a developer account at [Google Play Signup](https://play.google.com/console/signup). You will need to accept the Developer Distribution Agreement and pay a registration fee.

More information about the registration process can be found here [Registration process](https://support.google.com/googleplay/android-developer/answer/6112435).

## iOS Development

**Platform Requirement:** For iOS development you will <ins>require</ins> a Mac, whether you develop entirely on one or use the **Pair to Mac** option with Windows Visual Studio.

Since **Visual Studio for Mac** has been deprecated, [JetBrains Rider](https://www.jetbrains.com/rider/) or [VS Code](https://code.visualstudio.com/) can be used to develop for iOS. There is a non-commercial licence available of Rider.

For information about Pairing between Visual Studio and Mac, learn more [here](https://learn.microsoft.com/en-us/dotnet/maui/ios/pair-to-mac).

**Additional Requirements:**
- **Xcode** - Required for iOS development and deployment
- **Apple Developer Account** - Required for physical device deployment and App Store publishing ([enrollment link](https://developer.apple.com/programs/enroll/))

# Modern .NET Project Features

This tutorial utilizes modern .NET project management features to streamline cross-platform development:

## Central Package Management

We will be using [Central Package Management](https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management) to maintain consistent package versions across all platform projects. This ensures your shared code library and platform-specific projects use identical dependency versions.

## SLNX Solution Format

The sample projects use the new [SLNX solution format](https://devblogs.microsoft.com/dotnet/introducing-slnx-support-dotnet-cli/) for improved cross-platform development experience and better integration with modern .NET tooling.

# Next Steps

In the next chapter, we will convert the existing Windows-only Dungeon Slime game project to support iOS and Android platforms.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
101 changes: 101 additions & 0 deletions articles/tutorials/advanced/MobileDeployment/02_crossplatform/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
---
title: "Chapter 02: Setting Up Cross-Platform Projects"
description: "Learn how to convert a Windows-only MonoGame project to support iOS and Android platforms, creating a unified codebase for multi-platform deployment."
---

# What You Will Learn

In this chapter you will:
- Convert a Windows-only MonoGame project to support multiple platforms
- Understand the project structure for multi-platform games
- Set up shared code architecture for cross-platform development

# Prerequisites

- **For iOS Development:**
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section is duplicating the previous chapter, please consolidate in chapter 1.

Even in tutorials, you should follow the DRY pattern, unless essential.

- An App Store Developer Account
- **Certificates** and **Provisioning Profiles** configured and installed.
- **Mac 15.x (Sequoia) with Xcode 16 installed** - installed through the App Store.
- **For Android Development:**
- Android SDK and tools installed - through the Visual Studio Installer or through Jetbrains Rider.

# Converting the Dungeon Slime Project

The Dungeon Slime game from the 2D tutorial serves as our practical example for cross-platform conversion. This approach can be applied to any MonoGame project you want to deploy across multiple platforms.

The key principle is **code sharing** of the game logic between all platform variants - we will extract the game logic into a common library that all platform-specific projects can refer to and use.

# Cross-Platform Project Structure

When converted to support multiple platforms, your solution structure will look like this, as shown in the following figure.

| ![Figure 2-1: Cross Platform Projects](images/crossplatform_projects.png) |
| :----------------------------------------------------------------------------------------------------------------------------------------: |
| **Figure 2-1: Cross Platform Projects** |

This architecture separates concerns cleanly:
- **Shared game logic** in a common library
- **Platform-specific shells** that handle deployment and platform requirements
- **Consistent naming** for easy project management

## DungeonSlime.Common - The Shared Library

The common project contains all your game logic and uses multi-targeting to support different platforms:

```xml
<TargetFrameworks>net8.0;net8.0-ios;net8.0-android</TargetFrameworks>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The shared library should only need "net8" as it is common. Only the runtime platforms will require the specific extensions

```

## Platform-Specific Package References

Each target framework pulls in the appropriate MonoGame package:

For **iOS**:
```xml
<ItemGroup Condition="'$(TargetFramework)'=='net8.0-ios'">
<PackageReference Include="MonoGame.Framework.iOS" Version="3.8.5-develop.6" />
</ItemGroup>
```

For **Android**:

```xml
<ItemGroup Condition="'$(TargetFramework)'=='net8.0-android'">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be using
Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'"
This means the code will not need to change when the TargetFramework changes

<PackageReference Include="MonoGame.Framework.Android" Version="3.8.5-develop.6" />
</ItemGroup>
```

For **Windows**:

```xml
<ItemGroup Condition="'$(TargetFramework)'=='net8.0'">
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.5-develop.6" />
</ItemGroup>
```

## Platform-Specific Projects

The individual platform projects become lightweight shells that:

- Reference the _common_ library
- Handle platform-specific initialization
- Manage deployment settings and assets
- Contain minimal platform-specific code

## Project Structure

- **DungeonSlime.Windows** - Windows desktop version
- **DungeonSlime.Android** - Android mobile version
- **DungeonSlime.iOS** - iOS mobile version

The platform projects no longer contain the main Game class - this has been moved to the common library for sharing.

## Third-Party Library Considerations

When using external libraries like **Gum**, ensure they support cross-platform development:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would the user check, assume they do not know anything or even how to check. Please provide guidance. Especially as in this case, the existing tutorial already includes GUM.


[https://github.com/vchelaru/Gum](https://github.com/vchelaru/Gum)

```xml
<PackageReference Include="Gum.MonoGame" Version="2025.6.26.1" />
```
207 changes: 207 additions & 0 deletions articles/tutorials/advanced/MobileDeployment/03_touch/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
---
title: "Chapter 03: Touch Gesture Handling"
description: "Learn the fundamentals of touch gesture recognition in MonoGame - registration, detection, and processing."
---

Before proceeding with the cross-platform conversion, let us review how to handle touch input in MonoGame. The concepts discussed here apply to any MonoGame project. For our Dungeon Slime demo, touch input is managed by the Gum library, but understanding the fundamentals is still important.

## Gesture Registration

Before your application can respond to touch input, you must explicitly register for the gesture types you want to detect.

This is done during initialization:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initialization in which class / file, please be SPECIFIC when referring to files and locations.


```csharp
protected override void Initialize()
{
TouchPanel.DisplayWidth = GraphicsDevice.PresentationParameters.BackBufferWidth;

TouchPanel.DisplayHeight = GraphicsDevice.PresentationParameters.BackBufferHeight;

TouchPanel.EnabledGestures = GestureType.Tap |
GestureType.DoubleTap |
GestureType.Hold |
GestureType.Flick |
GestureType.FreeDrag |
GestureType.HorizontalDrag |
GestureType.VerticalDrag |
GestureType.Pinch |
GestureType.DragComplete |
GestureType.PinchComplete;

base.Initialize();
}
```

### Available Gesture Types

| Gesture Type | Description | Common Use Cases |
|--------------|-------------|------------------|
| `Tap` | Quick touch and release | Button presses, object selection |
| `DoubleTap` | Two quick taps in succession | Zoom to fit, special actions |
| `Hold` | Touch and hold for extended time | Context menus, charged actions |
| `Flick` | Quick swipe motion | Throwing objects, page navigation |
| `FreeDrag` | Continuous dragging motion | Moving objects, drawing |
| `HorizontalDrag` | Dragging constrained to horizontal | Sliders, horizontal scrolling |
| `VerticalDrag` | Dragging constrained to vertical | Vertical scrolling, pull-to-refresh |
| `Pinch` | Two-finger pinch/spread motion | Zoom in/out, scaling |
| `DragComplete` | End of any drag operation | Finalize object placement |
| `PinchComplete` | End of pinch operation | Finalize zoom level |

> [!NOTE]
> Only register for gestures you actually need. Each enabled gesture type has a small performance cost.

## Gesture Detection Loop

Touch gestures are processed using a polling approach in your `Update` method. Use `TouchPanel.IsGestureAvailable` to check if gestures are waiting to be processed:

```csharp
protected override void Update(GameTime gameTime)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DungeonSlime currently uses a dedicated input manager and separate "modules" for different inputs.

So is this creating a new input module for use by the input manager, or where is it meant to go. If this is all theory at this point, make sure to start this section with a highlighted note informing the reader "not to do anything but read" :D

{
// Process all available gestures each frame
while (TouchPanel.IsGestureAvailable)
{
GestureSample gesture = TouchPanel.ReadGesture();
ProcessGesture(gesture);
}

base.Update(gameTime);
}
```

### Why Use a Loop?

Multiple gestures can occur between frames, especially during complex touch interactions. The `while` loop ensures you process all queued gestures rather than missing any:

- **Single `if` statement** - Might miss gestures if multiple occur
- **`while` loop** - Processes all queued gestures until none remain

## Reading and Processing Gestures

Each gesture is read using `TouchPanel.ReadGesture()`, which returns a `GestureSample` containing the gesture details:

```csharp
void ProcessGesture(GestureSample gesture)
{
switch (gesture.GestureType)
{
case GestureType.Tap:
HandleTap(gesture.Position);
break;

case GestureType.Flick:
HandleFlick(gesture.Position, gesture.Delta);
break;

case GestureType.Pinch:
HandlePinch(gesture.Position, gesture.Position2);
break;

// Handle other gesture types...
}
}
```

### GestureSample Properties

Each `GestureSample` provides different data depending on the gesture type:

- **`GestureType`** - The type of gesture detected
- **`Position`** - Primary touch point location (screen coordinates)
- **`Position2`** - Secondary touch point (used for pinch gestures)
- **`Delta`** - Movement vector for drag and flick gestures
- **`Timestamp`** - When the gesture occurred

### Example: Processing Different Gesture Data

```csharp
switch (gesture.GestureType)
{
case GestureType.Tap:
// Use: Position
Vector2 tapLocation = gesture.Position;
break;

case GestureType.Flick:
// Use: Position (start), Delta (direction/speed)
Vector2 flickStart = gesture.Position;
Vector2 flickDirection = gesture.Delta;
break;

case GestureType.Pinch:
// Use: Position (finger 1), Position2 (finger 2)
Vector2 finger1 = gesture.Position;
Vector2 finger2 = gesture.Position2;
break;
}
```

## Complete Example

Here is a minimal working example demonstrating all three concepts:

```csharp
public class TouchGame : Game
{
protected override void Initialize()
{
// 1. Register for gestures
TouchPanel.EnabledGestures = GestureType.Tap | GestureType.Flick;
base.Initialize();
}

protected override void Update(GameTime gameTime)
{
// 2. Check for available gestures
while (TouchPanel.IsGestureAvailable)
{
// 3. Read and process each gesture
GestureSample gesture = TouchPanel.ReadGesture();

switch (gesture.GestureType)
{
case GestureType.Tap:
Console.WriteLine($"Tap at {gesture.Position}");
break;

case GestureType.Flick:
Console.WriteLine($"Flick from {gesture.Position} with delta {gesture.Delta}");
break;
}
}

base.Update(gameTime);
}
}
```

## Dungeon Slime Sample

In the _DungeonSlime_ game, touch input is encapsulated in a new **TouchInfo** class, which internally uses the **TouchPanel** API to detect and process gestures.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, so I can see the above was just theory but it wasn't clear previously.
Please ensure to add text at the start as to what the reader will be looking at and that the implementation will come later.

Alternatively (recommended) restructure the chapter to start with implementing and then each of the steps above while doing them. In testing of the original tutorial, readers felt they understood better being told about features as they implemented them, and it also gave them something to do while reading.


This class abstracts gesture handling and exposes methods like `IsTouchSwipeUp()`, `IsTouchSwipeDown()`, etc., making it easy to check for swipe actions.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing instructions for HOW to achieve this, best to ensure instructions are SPECIFIC in operation:

  1. Create class -> here
  2. Update the contents iteratively, explaining each section
  3. Show final file, so the reader can compare the result against their own
  4. Move on to implementation, open file X, move to line Y
  5. Show adding / updating features in existing classes with line highlights (the 2D tutorial is full of these)

Hope that helps.


The **TouchInfo** class is then integrated into the **GameController** class, allowing the game logic to respond to touch gestures in a platform-agnostic way. This modular approach keeps input handling clean and maintainable, and ensures that touch support works seamlessly alongside keyboard and gamepad input.

### Extending Move Functions with Touch Gestures

To support touch input alongside keyboard and gamepad, extend your movement functions to include checks for swipe gestures.

For example:

```csharp
public static bool MoveUp()
{
return s_keyboard.WasKeyJustPressed(Keys.Up) ||
s_keyboard.WasKeyJustPressed(Keys.W) ||
s_gamePad.WasButtonJustPressed(Buttons.DPadUp) ||
s_gamePad.WasButtonJustPressed(Buttons.LeftThumbstickUp) ||
IsTouchSwipeUp(); <=== extended to support touch
}
```

This approach ensures your game responds to swipe gestures for movement, providing a consistent experience across touch, keyboard, and gamepad input.

## Conclusion

This foundation enables you to respond to touch input across iOS and Android platforms using MonoGame's cross-platform gesture system.
Loading