Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
21 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
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,54 @@
---
title: "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 **MonoGame 2D Dungeon Slime tutorial** to mobile platforms. If you haven't completed the desktop tutorial yet, we recommend finishing it first as we'll be building directly on that foundation.
Copy link
Collaborator

Choose a reason for hiding this comment

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

When mentioning other content or API's, provide a hyperlink back to the source content so the user does not have to search


## What You'll Learn

By the end of this mobile tutorial series, you'll have:
Copy link
Collaborator

Choose a reason for hiding this comment

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

To ensure readability for non-english speakers, the MonoGame tutorials "do not" use contractions.

Please ensure to update where they have been used, e.g. "you'll" should be "you will"

- 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. However, ARM64 variants of Windows do not run the Android simulator 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
Collaborator

Choose a reason for hiding this comment

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

is the Android SDK manager required, or is the Android DotNet workload not enough? (since the workload is already part of the MonoGame install instructions.)

Copy link
Contributor

Choose a reason for hiding this comment

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

Instructions on installing the SDK are at https://learn.microsoft.com/en-us/dotnet/android/getting-started/installation/. We should link to that documentation.

we could also link to the docs on installing the Maui workload https://learn.microsoft.com/en-us/dotnet/maui/get-started/installation. Maui is the workload which includes all the mobile bits.
The C# DevKit in VSCode can also install the Android SDK afaik.


## iOS Development

**Platform Requirement:** iOS development requires a Mac, whether you develop entirely on it 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/) is the currently recommended IDE for Mac development. Visual Studio Code is another viable option too.

**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'll 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'll convert the existing Windows-only Dungeon Slime project to support multiple platforms and explore the cross-platform project architecture.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
103 changes: 103 additions & 0 deletions articles/tutorials/advanced/MobileDeployment/02_crossplatform/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
---
title: "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'll 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

Before starting this chapter, ensure you have:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ideally, this should be included in the previous chapter, which detailed what the reader should know before starting the tutorial.
By Chapter 2, they should be "ready" to begin :D


- Read the [Building 2D Games](../building_2d_games) tutorial

- **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 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 - we'll extract the game logic into a common library that all platform-specific projects can refer to and use.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please include actual steps for updating the project for the additional platform projects. Making sure to include commands (like dotnet cli) to make it into the new pattern.

The existing sample already has a shared library which shouldn't need modification from the platform perspective, please confirm. Does it need another "shared" library?


# Cross-Platform Project Structure

When converted to support multiple platforms, your solution structure will look like this:

![Cross Platform Projects](images/crossplatform_projects.png)

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" />
Copy link
Contributor

Choose a reason for hiding this comment

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

I would recommend upgrading to the latest version of Gum before releasing this, unless of course you are concerned that you haven't spent enough time with it to verify compatibility.

Copy link
Author

Choose a reason for hiding this comment

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

I don't have an issue with updating the version number and would need to check compatibility.

```
174 changes: 174 additions & 0 deletions articles/tutorials/advanced/MobileDeployment/03_touch/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
---
title: "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's 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.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's 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);
}
}
```

This foundation enables you to respond to touch input across iOS and Android platforms using MonoGame's cross-platform gesture system.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading