-
Notifications
You must be signed in to change notification settings - Fork 60
Feature/mobile deployment #169
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 3 commits
5945f88
b422687
cdaa253
9a22ba8
f20f79d
f66fa9d
ba1387c
cb5c95a
60acf90
3173777
dec9803
68091a4
ed11443
85bf058
cfab710
ac7cc3b
c0479e3
f797549
cb42e6e
295fae7
90b9914
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.) There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
|
||
## 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. | ||
olivegamestudio marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
**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. |
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:** | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||
|
||
|
||
# Cross-Platform Project Structure | ||
|
||
When converted to support multiple platforms, your solution structure will look like this: | ||
|
||
 | ||
|
||
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> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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'"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These should be using |
||
<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: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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" /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
``` |
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. | ||
olivegamestudio marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
## 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: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
There was a problem hiding this comment.
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