Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
df92fb7
Add screenshots from deploying to iOS simulator and Android emulator.
olivegamestudio Jun 27, 2025
1bd8ffe
Set landscape orientation.
olivegamestudio Jun 27, 2025
5e4888c
Android documentation started.
olivegamestudio Jul 6, 2025
dcc5c03
Updated android doc.
olivegamestudio Jul 9, 2025
0056374
More information about csproj.
olivegamestudio Jul 9, 2025
3d9901b
Fix image link.
olivegamestudio Jul 9, 2025
cc2e451
Merge branch 'feature/04_sharing_logic' into feature/MobileDeployment-1
olivegamestudio Jul 9, 2025
aff4913
Initial notes for part 1.
olivegamestudio Jun 27, 2025
e32ff21
Updated doc and images.
olivegamestudio Jun 27, 2025
a2f1ed6
Add android doc and images.
olivegamestudio Jun 27, 2025
7d35937
Add android project image.
olivegamestudio Jun 27, 2025
830fd3d
Work on the cross platform changes.
olivegamestudio Jul 9, 2025
b459168
Merge branch 'feature/01_updating_libs' into feature/MobileDeployment-1
olivegamestudio Jul 12, 2025
3b1d78e
Merge branch 'feature/02_add_ios_project' into feature/MobileDeployme…
olivegamestudio Jul 12, 2025
c30969e
More tidy ups.
olivegamestudio Jul 12, 2025
6ccaa55
notes
olivegamestudio Jul 16, 2025
3a5d5bb
Restructure.
olivegamestudio Jul 19, 2025
805539b
Update for debugging.
olivegamestudio Jul 19, 2025
7c4b1ff
Updated image.
olivegamestudio Jul 19, 2025
7ac3dc2
Renamed screenshots.
olivegamestudio Jul 19, 2025
d302cf8
Add iOS simulator.
olivegamestudio Jul 20, 2025
67424fa
Adding rider images.
olivegamestudio Jul 23, 2025
a598d37
Added getting started section.
olivegamestudio Jul 27, 2025
998f90a
Refactoring folders.
olivegamestudio Jul 28, 2025
bc4c9eb
Parts 1 and 2. Setup 3 and 4 the right order.
olivegamestudio Aug 5, 2025
4a8829f
Update mobile development tutorial: refine iOS section, add modern .N…
olivegamestudio Aug 12, 2025
4fbb7c6
Updated versions of library.
olivegamestudio Aug 12, 2025
72db5a2
Cropped image better and removed unnecessary one.
olivegamestudio Aug 12, 2025
22410f1
Touch tutorial.
olivegamestudio Aug 12, 2025
5db17da
Publishing documentation.
olivegamestudio Aug 12, 2025
5793d99
Include transporter images.
olivegamestudio Aug 12, 2025
3a77290
Updated documents and tidy ups.
olivegamestudio Aug 16, 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
Empty file.
Empty file.
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.

## What You'll Learn

By the end of this mobile tutorial series, you'll 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. 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

## 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:

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

- **For iOS Development:**
- 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.

# 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>
```

## 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'">
<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:

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

```xml
<PackageReference Include="Gum.MonoGame" Version="2025.6.26.1" />
```
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:

```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)
{
// 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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

# Android
Copy link

Copilot AI Aug 16, 2025

Choose a reason for hiding this comment

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

The file is missing the frontmatter metadata (title and description) that is present in other tutorial chapters. This creates inconsistency in the documentation structure.

Copilot uses AI. Check for mistakes.

![](images/game_android_target.png)

![](images/game_android_device.png)

![](images/game_android_device2.png)

![](images/game_android_orientation.png)

# iOS Signing

XCode --> Settings

![](images/xcode_certificates.png)

![](images/xcode_signing.png)

```
Copy link

Copilot AI Aug 16, 2025

Choose a reason for hiding this comment

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

The XML code block is missing the language identifier. Add 'xml' to the code block declaration for proper syntax highlighting.

Suggested change
```
```xml

Copilot uses AI. Check for mistakes.
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<CodesignKey>iPhone Distribution</CodesignKey>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<CodesignKey>iPhone Developer</CodesignKey>
</PropertyGroup>
```

# Debugging

![](images/game_ios_simulator.png)

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