Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Native iOS Game Development w/ Rust
Wade Zimmerman
Wade Zimmerman

Posted on • Edited on • Originally published atMedium

     

Native iOS Game Development w/ Rust

My documented journey of exploring cross platform game development using purely Rust.

Seriously. It's 100% Rust!

Next article:Handling tap events


Why I Chose Rust

Rust is a popular topic of discussion when it comes to performance and modular design, but that is not why I chose this language. I chose Rust because I wanted a cross-platform system programming language.

Hindsight: Things I Like About Rust

After digging through Rust for a few weeks, I discovered some of most dreaded features turned out enjoyable. Albeit there is a learning curve, but in hindsight, I really appreciate the following features of Rust.

  • No OOP
  • Modular Code
  • Documentation Ecosystem
  • Build System
  • Package Management

My Goals for Exploring Rust

My goal is to find a language which allows me to write cross platform code without needing to jump through a bunch of hoops. As a hobbyist, I don't have a lot of time to pick up new languages or dig through the framework of the week.

To deem my exploration a success, I will continue Rust development until I publish an app on the App Store. Why? Because Swift/Obj-C are my most dreaded languages, but I can tolerate Java. So if Rust allows me to at least cut out Swift/Obj-C then I will be happy.


0. Project Environment Setup

Going into this project, I know that I will frequently modify environment variables and build scripts. So before I even start with Rust, I will add a script to my.bashrc which makes it easy to swap out large changes to my dev environment.

The following script allows me to extend my.bashrc from any project directory in my~/code folder by traversing upward until it finds a folder called.devenv. From there I can source a per-project bash script.

# get the first match from `find` while traversing upwardsfunctionfind_above{old_pwd="$PWD"while[["$PWD"==$HOME/code/*]];donew_pwd=`find"$PWD"/-maxdepth 1"$@"`if[["$new_pwd"]];thenbreakficd ..doneecho"$new_pwd"cd"$old_pwd"old_pwd=""new_pwd=""}
Enter fullscreen modeExit fullscreen mode

Here is the part where I use the method to source the local.bashrc. I have to re-source my environment every time I switch projects, but that is not a concern.

# see code aboveENVDIR=$(find_above-type d-name".devenv")if[["$ENVDIR"]];thensource"$ENVDIR/.bashrc"fi
Enter fullscreen modeExit fullscreen mode

Creating Aliases

Now that my machine can handle per-project bash environments, I setup a few commands so I could quickly jump around my code.

# ~/code/tictactoe/.devenv/.bashrcecho"detected local env:$PWD"# src directoryexportSRCDIR=$(find_above-name"src")# root directoryexportROOTDIR=$(dirname$SRCDIR)# build directoryexportBUILDDIR="$ROOTDIR/target"mkdir-p"$BUILDDIR"# lib directoryexportLIBDIR="$ROOTDIR/src"mkdir-p"$LIBDIR"# bin directoryexportBINDIR="$ROOTDIR/.devenv/bin"mkdir-p"$BINDIR"exportPATH="$BINDIR:$PATH"exportRUST_LOG="warn,handmade=debug"exportRUST_BACKTRACE=1# aliasesaliasc="cargo build"aliasclean="clean"aliass="source$HOME/.zshrc"aliasroot="cd$ROOTDIR"aliasr="cargo run"aliast="cargo test"aliasi="run-ios-sim.sh"aliascr="c && r"
Enter fullscreen modeExit fullscreen mode

1. Hello World Rust/Bevy

When I first started exploring weeks ago, I wanted to start at the lowest level possible. I wanted to write my own graphics render, and game engine. However, after about 3 days of zero progress, I gave up that dream and looked for a Rust game engine.

Installing Bevy

Of course, I downloaded the first game engine I could find. Which turned out to be a pretty nice framework. Bevy is a game engine which is designed around apps which should be highly modular. I have used the library for a few weeks, I love it still!

cargo add bevy
Enter fullscreen modeExit fullscreen mode

Writing Code using Bevy's Paradigm

Here is Hello world using Bevy on Mac OS:

usebevy::prelude::*;fnmain(){App::new().add_system(hello_world_system).run();}fnhello_world_system(){println!("Hello Rust");}
Enter fullscreen modeExit fullscreen mode

Notice how I am not directly callingprintln. This is because Bevy provides a framework which is very similar to the routing system inExpressJS. On bigger projects you can extract capabilities in modules/plugins and each plugin has access to the context for registering more systems.

Running Bevy Hello World

cargo run
Enter fullscreen modeExit fullscreen mode

Where is the GUI?

Bevy isolated all of its components into plugins so if you want to ditch the whole "game engine" thing you are free to do so! You can also run Bevy in headless mode! Although for the sake of this tutorial, you'll want to enable the default plugins.

usebevy::prelude::*;fnmain(){App::new().add_plugins(DefaultPlugins)// ....run();}// ...
Enter fullscreen modeExit fullscreen mode

2. Building for iOS (Cross Platform Upfront)

I want to immediately try to compilehello world for iOS. This saves me a lot of time upfront because if I can't get iOS to work with Rust then the project is a failure. Plus nothing is more difficult than writing a project then trying to port it to another system after the fact.

Hindsight: Caveats Lead to Discoveries

It took me much longer than I care to admit to successfully compile. Originally, I thought I needed to create a header bridge usingextern "C", but that is not the case. In fact you do not even need to touch XCode!

Bundling

There is a build tool for cargo which let's you compile and bundle for iOS without jumping through any hoops. First install the build tool:

cargo install cargo-bundle
Enter fullscreen modeExit fullscreen mode

Adding Compilation Targets

Then you need to list out all the possible build targets that Rust supports. Since I am targeting iOS, I ran the following command:

rustup target list | grep ios
Enter fullscreen modeExit fullscreen mode

If you are missing iOS as a target, then you need to add them based on your environment.

# for productionrustup target add aarch64-apple-ios# for developmentrustup target add aarch64-apple-ios-sim
Enter fullscreen modeExit fullscreen mode

Packaging for iOS Simulator

Once you have the compilation targets available on your Systemand you are on a Mac, you can use the script I wrote or copy and paste the following commands to inject your app into the simulator. Most of the commands come with XCode.

The script below usesdasel so it can query the name and bundle identifier from the projectsCargo.toml file.

brew install dasel
Enter fullscreen modeExit fullscreen mode

Then I use a series of commands provided by XCode to work with the iPhone simulator. More information about how the commands in this script work can be found using thischeat sheet.

#/usr/bin/env bashAPP_NAME="$(catCargo.toml | dasel-r toml'.package.name')"BUNDLE_ID="$(catCargo.toml | dasel-r toml'.package.metadata.bundle.identifier')"cargo bundle--target aarch64-apple-ios-simxcrun simctl boot"iPhone 12 mini"  open /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app xcrun simctlinstallbooted"target/aarch64-apple-ios-sim/debug/bundle/ios/$APP_NAME.app"xcrun simctl launch--console booted"$BUNDLE_ID"
Enter fullscreen modeExit fullscreen mode

3. Project Success!

If everything worked correctly, you should be left with an iOS App which spams "Hello Rust" to your terminal and meets the following criteria:

  • Written entirely in Rust
  • No bridging code
  • No XCode
  • Modular Design
  • Flexible Development Environment

Rust running on iPhone


To Be Continued

If you would like to document the rest of the project as a series or share the source code please leave a like, comment, or other type of reaction! It helps me stay motivated

Next article:Handling tap events

Conclusion

It is possible to write a game entirely in Rust and compile to iOS natively without XCode.

Top comments(13)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
marlon_klaus_4475911722a9 profile image
Marlon Klaus
  • Joined

Hello,
When I try this, I get the following error:
The request to open "com.marlonklaus.mytestgame" failed.
Do you have any idea? I hardcoded the bundle identifier and the app name, but Im not quite sure which bundle identifier I have to use.

Thank you in advance :)

CollapseExpand
 
wadecodez profile image
Wade Zimmerman
Code by day; blog by night
  • Location
    California
  • Education
    Networking/Software
  • Work
    Self Employed
  • Joined

Sounds like your app is making a request to the simulator but it's not going through. You probably just need to restart/delete your simulator. Which simulator are you using?

You can also try to use a different build target if you're using an older mac or different simulator.rustup target list will list out available build targets.

stackoverflow.com/questions/424519...

CollapseExpand
 
daaitch profile image
Philipp Renoth
🦀 Rust, ⬢ node.js and 🌋 Vulkan
  • Email
  • Location
    Germany
  • Work
    Software Engineer at ConSol Consulting & Solutions Software GmbH
  • Joined

Hey, thanks for sharing. Do you have any experience bringing native controls like buttons to the screen? Is it possible?

CollapseExpand
 
wadecodez profile image
Wade Zimmerman
Code by day; blog by night
  • Location
    California
  • Education
    Networking/Software
  • Work
    Self Employed
  • Joined

Was just reading about this actually. My approach was to listen for touch events and do something either when a touch just started or when it was just pressed.

However, it doesn't feel very natural. I'm thinking it would be better to include a slight delay like debounce method but I haven't gotten that far yet.

bevy-cheatbook.github.io/input/tou...

CollapseExpand
 
daaitch profile image
Philipp Renoth
🦀 Rust, ⬢ node.js and 🌋 Vulkan
  • Email
  • Location
    Germany
  • Work
    Software Engineer at ConSol Consulting & Solutions Software GmbH
  • Joined

Okay, so that wouldn't beApple's AppKit as UI, but for example bevy_ui or another UI crate?

Thread Thread
 
wadecodez profile image
Wade Zimmerman
Code by day; blog by night
  • Location
    California
  • Education
    Networking/Software
  • Work
    Self Employed
  • Joined

Don't quote me on this because I haven't done my research, but it sounds like GUI frameworks are bleeding edge for Rust. It looks like most libraries are just bindings to C. Looks like this is a goodstarting point. Also here is myTwitter

CollapseExpand
 
elasehuang profile image
Elase Huang
  • Joined

Hey, thanks for sharing. It help me lot with migrating my bevy based game to ios platform. But i'm stucked in loading assets. Is it convenient to ask how you bundle assets into .app?🤔

CollapseExpand
 
elasehuang profile image
Elase Huang
  • Joined

I have find the solution yet, addresources = ["assets"] worked for bevy assets system, but not work for image create, thanks although

CollapseExpand
 
wadecodez profile image
Wade Zimmerman
Code by day; blog by night
  • Location
    California
  • Education
    Networking/Software
  • Work
    Self Employed
  • Joined

I haven't tried loading assets into my iOS app yet, but I would try to compile to a desktop app first and see if the assets load there. If the assets load for a desktop build but not an iOS build, then I would inspect the.ipa archive folder to see if it contains an asset bundle, and if the plist in the archive points to the correct path.

You can use thetar command or you can change the.ipa extension to.zip and uncompress the files to see what's inside.

Are you getting any error messages when the images fail to load?

CollapseExpand
 
tomas_virgin_c0911c44f872 profile image
Tomas Virgin
  • Joined

Yeni programlama dillerini öğrenmek ve onları oyun geliştirme için kullanmak her zaman ilgi çekici. Rust gibi modern dillerin iOS oyunlarında nasıl çalıştığını keşfetmek benim için heyecan vericiydi. Bu süreçte ara sıra dinlenmek ve oyun dünyasından kopmamak önemliafyonkenthaber.com/afyon-dinlenme-... sitesinde zaman geçirirken, farklı oyunlara kolayca erişip biraz kafa dağıtmak benim motivasyonumu artırdı. Böyle platformlar, öğrenme sürecine küçük ama etkili molalar eklemek için harika.

CollapseExpand
 
nikolajevs86 profile image
P.Nik
  • Joined

Hi, I have followed the guide, but my app fails while trying to install itself by "xcrun simctl install booted {APP}".
The thrown error message is : domain=IXUserPresentableErrorDomain, code=4 and "This app needs to be updated by the developer to work on this version of iOS.".
Can someone advice how to fix this please?

CollapseExpand
 
binchem profile image
Binchem Peng
  • Joined

Thank you for sharing, this is really great, there is no problem on ios, but I am stuck on android, do you have any experience to share?

Some comments may only be visible to logged-in visitors.Sign in to view all comments.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Code by day; blog by night
  • Location
    California
  • Education
    Networking/Software
  • Work
    Self Employed
  • Joined

More fromWade Zimmerman

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp