What this guide is for
This website explains how to make a simple 2D game with LÖVE2D, then prepare it for Android and iPhone/iPad. It is written for beginners, so the steps are simple and practical.
You can use this guide for small games, party games, puzzle games, arcade games, and simple mobile apps made with Lua and LÖVE2D.
1. Build the game
Make your LÖVE project with main.lua, conf.lua, and your assets.
2. Package it
Use love-android for Android or the LÖVE iOS/Xcode project for iPhone and iPad.
3. Test it
Test on real devices before you send it to Google Play or Apple App Store review.
4. Publish it
Create the store page, add screenshots, complete privacy forms, upload the signed build, and submit for review.
5. Monetize it
Plan ads and in-app purchases early so privacy, billing, testing, and store disclosures are ready before review.
Which path should you start with?
Start with Android if you are new
Android is usually easier to start with because you can build it from Windows, macOS, or Linux using Android Studio and Gradle.
Use iOS if you have a Mac
iOS publishing needs macOS, Xcode, an Apple Developer account, signing, App Store Connect, and TestFlight.
Important current requirements
Store rules change over time, so always check Google and Apple official pages again before your final release.
How a LÖVE2D game is structured
LÖVE2D games are written in Lua. The most important file is main.lua. When LÖVE starts your game, it looks for this file first.
A simple LÖVE project usually looks like this:
my-game/
main.lua
conf.lua
assets/
images/
audio/
fonts/
src/
player.lua
menu.lua
main.lua starts the game. conf.lua stores basic settings. assets holds images, sounds, fonts, and music. src can hold extra Lua files when your project grows.
The 3 main LÖVE functions
love.load()
Runs once when the game starts. Load images, sounds, fonts, variables, and settings here.
love.update(dt)
Runs every frame. Use it for movement, timers, input, physics, and game logic.
love.draw()
Runs every frame after update. Use it to draw text, sprites, UI, backgrounds, and effects.
Small test game
function love.load()
message = "Hello from LÖVE2D!"
end
function love.update(dt)
-- dt means delta time. It helps movement feel smooth.
end
function love.draw()
love.graphics.print(message, 40, 40)
end
Example conf.lua
conf.lua is optional, but it is useful. It runs before the game starts and lets you set title, size, identity, and other settings.
function love.conf(t)
t.identity = "mygame"
t.window.title = "My Game"
t.window.width = 1280
t.window.height = 720
t.window.resizable = false
end
t.identity. It helps LÖVE know where your save data belongs.
What is a .love file?
A .love file is your game packed into one file. It is basically a zip file with your game files inside it.
The important rule: main.lua must be at the top level of the archive, not hidden inside another folder.
Correct:
game.love
main.lua
conf.lua
assets/
Wrong:
game.love
my-game-folder/
main.lua
Mobile game tips before packaging
- Make UI scale to different screen sizes.
- Use touch controls, not only keyboard controls.
- Compress large images and audio files.
- Test portrait and landscape early.
- Do not use copyrighted music, images, or characters.
- Test saving/loading before store release.
Publish a LÖVE2D game to Google Play
For Android, the normal path is to use the official love-android project. You put your LÖVE game inside the Android project, build a release file, sign it, and upload it to Google Play Console.
APK vs AAB
| File type | Use it for | Beginner explanation |
|---|---|---|
| APK | Testing on your phone | An installable Android app file. Good for quick testing. |
| AAB | Google Play upload | Android App Bundle. Google Play uses it to generate optimized APKs for users. |
Android setup steps
- Install Android Studio. It includes the Android SDK and tools you need.
- Clone love-android. This is the Android wrapper/project for LÖVE games.
- Add your LÖVE game files. Put your game inside the embed assets folder.
- Set app information. App name, package name, version code, version name, orientation, and permissions.
- Build debug APK. Test it on your phone first.
- Build release AAB. This is normally what you upload to Google Play.
- Complete Play Console setup. Store page, data safety, age rating, screenshots, and testing.
Updated notes from older Android tutorials
Older LÖVE2D Android videos are still useful for understanding the basic idea: install Android tools, clone love-android, put your game into the Android project, build an APK, and test it on a real phone. Some details have changed, so use the current love-android README and Google Play rules for final builds.
Clone with submodules
Use git clone --recurse-submodules. Missing submodules can cause errors like missing native LÖVE libraries during the build.
Match the toolchain
love-android currently lists JDK 17, CMake 3.21+, Android SDK API 34, and Android NDK 26.1.10909125 for its source build. Follow the README if those versions change.
Use modern packaging
Older APKTool or manual repackaging methods are obsolete. Use the embed folder or game.love method and the current Gradle tasks.
Test APK, release AAB
An APK is still useful for device testing. Google Play release should use a signed Android App Bundle unless you have a specific reason not to.
Example command workflow
This is a common terminal workflow. On Windows, use Git Bash, PowerShell, or Android Studio terminal.
git clone --recurse-submodules https://github.com/love2d/love-android
cd love-android
mkdir -p app/src/embed/assets
cp -R /path/to/your/game/* app/src/embed/assets/
./gradlew assembleEmbedNoRecordDebug
./gradlew assembleEmbedNoRecordRelease
./gradlew bundleEmbedNoRecordRelease
NoRecord if your game does not need microphone access. Only use a recording/microphone build if your game actually needs microphone permission.
How to embed your game
| Method | Where to put files | When to use it |
|---|---|---|
| Folder embed | app/src/embed/assets/main.lua with your assets beside it. |
Best for normal development because files are easy to inspect and replace. |
| Single .love file | app/src/embed/assets/game.love |
Good when your game already packages cleanly as a .love archive. |
| Prebuilt LÖVE Android app | Open a .love file with a LÖVE Android package from the official releases. |
Useful for quick testing, but not a final branded Play Store app. |
game.love, main.lua must be at the top level inside the archive, not inside an extra folder.
Android settings you must understand
applicationIdorapp.application_id: your unique package name, likecom.yourstudio.yourgame.versionCode: an internal number. Increase it every update.versionName: the visible version, like1.0.0.targetSdk: the Android version you target. Google Play currently requires Android 15 / API 35 or higher for new apps and updates.- Signing key / keystore: the private key used to sign your app. Keep it safe.
app.name=My Puzzle Game
app.application_id=com.yourstudio.mypuzzlegame
app.orientation=landscape
app.version_code=1
app.version_name=1.0.0
Google Play requirements to remember
Install and test on a real Android device
For development, use a debug APK on a real device before you prepare the store build. Android Studio and ADB are usually faster and cleaner than copying APK files manually.
- Enable Developer options and USB debugging on the phone.
- Connect by USB, or use wireless debugging on Android 11 or higher.
- Check the device with
adb devices. - Install the debug APK with
adb install -r path/to/your-game.apk. - Run the game, rotate the device if supported, test touch input, save/load, audio pause/resume, and performance.
- Use
adb logcatwhen the game crashes or shows a black screen.
Before uploading to Google Play
- Test the APK on a real Android phone.
- Build a signed release AAB.
- Check that the game saves data correctly.
- Check that screen orientation is correct.
- Remove unused permissions.
- Prepare screenshots, icon, feature graphic, description, and privacy policy.
Publish a LÖVE2D game to the Apple App Store
iOS publishing is more manual than Android. You need a Mac, Xcode, an Apple Developer account, signing, provisioning, App Store Connect, and TestFlight.
iOS setup steps
- Use a Mac. iOS builds require Xcode, and Xcode runs on macOS.
- Install Xcode. Use the version Apple currently requires for App Store uploads.
- Join Apple Developer Program. You need this for App Store publishing and device signing.
- Download LÖVE source and Apple dependencies. Match versions when possible.
- Open the Xcode project. Select the iOS target.
- Add your game. Include your game files or packaged
game.love. - Set signing. Use your team, bundle ID, capabilities, version, and build number.
- Test with real device and TestFlight. Then submit for review.
Example iOS source setup
This is a common source-based setup pattern. The exact branch/version should match the LÖVE version you want to use.
git clone --depth 1 --branch 11.5 https://github.com/love2d/love.git
git clone --depth 1 --branch 11.5 https://github.com/love2d/love-apple-dependencies.git
cp -R love-apple-dependencies/iOS/libraries love/platform/xcode/ios/
cp -R love-apple-dependencies/shared love/platform/xcode/
open love/platform/xcode/love.xcodeproj
What signing means in simple words
Apple signing proves that the app comes from your Apple Developer account and that it is allowed to run on devices or be uploaded to App Store Connect.
Bundle ID
A unique app ID, like com.yourstudio.yourgame. It must match App Store Connect.
Team
Your Apple Developer account or company account.
Provisioning profile
A file that says which app, account, and devices/distribution type are allowed.
Capabilities
Special features like Game Center, iCloud, Push Notifications, or Sign in with Apple.
App Store Connect flow
- Create a new app record in App Store Connect.
- Set the name, bundle ID, SKU, platform, and primary language.
- Upload your build from Xcode Organizer or Transporter.
- Add screenshots, description, keywords, age rating, privacy details, and pricing.
- Test using TestFlight.
- Submit the app for App Review.
iOS beginner warnings
- Use the correct Xcode version before uploading.
- Increase the build number every upload.
- Use a real iPhone/iPad for testing, not only Simulator.
- Do not add capabilities you do not use.
- Answer privacy and age-rating questions carefully.
- Apple review can reject apps for crashes, misleading content, missing privacy info, or broken features.
Store listing, screenshots, and privacy
Publishing is not only about the build file. Google and Apple also check your store page, screenshots, privacy answers, age rating, and policies.
Google Play store page
| Item | What to prepare |
|---|---|
| App title | Clear app/game name. Keep it short and not misleading. |
| Short description | One small sentence explaining the game. |
| Full description | Explain gameplay, features, controls, and what makes it fun. |
| Icon | High-quality icon, usually 512 × 512 PNG for Play Console assets. |
| Feature graphic | A wide promo image, commonly 1024 × 500. |
| Screenshots | Use real screenshots from the game. Do not fake gameplay. |
| Data safety | Explain what data you collect, share, and why. |
| Privacy policy | Recommended and often required, especially with ads, analytics, accounts, or online features. |
Apple App Store page
| Item | What to prepare |
|---|---|
| App name | Usually max 30 characters. Use a clear name. |
| Subtitle | Short line that explains the app/game quickly. |
| Description | Explain the game, features, and why someone should download it. |
| Keywords | Search terms that help people find your game. |
| Screenshots | Prepare screenshots for required device sizes. |
| App privacy | Answer Apple privacy questions about data collection and tracking. |
| Age rating | Required. Answer honestly about violence, gambling, user content, etc. |
| Export compliance | May be required depending on encryption and app features. |
Simple store description template
Short description:
A simple and fun 2D game made for quick mobile play.
Full description:
Play [Game Name], a simple 2D game where you [main action].
Features:
- Easy controls
- Fast rounds
- Clean 2D style
- Fun gameplay for short sessions
Download now and start playing.
Privacy policy reminder
Even if your game does not collect data, stores may still ask you to confirm that clearly.
Monetization basics for mobile games
Ads and in-app purchases can help a free game earn money, but they also add policy, privacy, testing, and support work. Decide what you will sell or show before release so the app, store listing, and privacy answers all match.
Which monetization type should you use?
| Type | Good for | Common risks |
|---|---|---|
| Ads | Free games, casual games, rewarded bonuses, optional extra lives, or light monetization. | Privacy disclosures, consent, bad placement, accidental clicks, child-directed content rules, and lower user trust if ads interrupt gameplay. |
| Consumable IAP | Coins, gems, extra lives, boosts, hints, or other items that can be bought again after use. | Must grant items reliably, prevent duplicate grants, support refunds, and make prices clear. |
| Non-consumable IAP | Remove ads, premium upgrade, permanent level packs, characters, skins, or extra game modes. | Must restore purchases on new devices and never charge twice for the same permanent item. |
| Subscriptions | Live service games, ongoing content, seasonal benefits, cloud services, or premium memberships. | Requires clear renewal terms, cancellation handling, entitlement checks, and stronger customer support. |
Ads setup checklist
Google Play / Android
- Create an AdMob account and register the app to get an AdMob App ID.
- Add the Google Mobile Ads SDK to the Android project and add the AdMob App ID in
AndroidManifest.xml. - Use current SDK requirements. As of June 2026, the AdMob Android guide shows minimum SDK 23 or higher, compile SDK 35 or higher, and
play-services-ads:25.3.0. - Initialize the ads SDK once, ideally at app launch, after handling any required consent or request flags.
- Use test ads while developing. Never click your own live ads to test them.
- Expect the
com.google.android.gms.permission.AD_IDpermission to be merged by recent Google Mobile Ads SDK versions if advertising ID access is used.
Apple / iOS
- Use the iOS version of your ad SDK and follow that SDK's App Store privacy instructions.
- Complete App Store Connect privacy details for every ad SDK and analytics SDK included in the app.
- If the app tracks users or accesses the device advertising identifier, use App Tracking Transparency before tracking.
- Do not fingerprint users or use hidden device signals to identify a user.
- Test ad loading on a real device before TestFlight or App Review.
Best ad formats for simple games
Banner
Small ad that stays on screen. Best for menus or non-action screens. Avoid placing it near gameplay buttons where players can tap by accident.
Interstitial
Full-screen ad shown at natural breaks, such as after a level or after returning to the main menu. Do not show it during active gameplay.
Rewarded
Player chooses to watch an ad for a reward, such as coins, a revive, or a hint. Make the reward clear before the ad starts.
App open
Shown when the app opens or resumes. Use carefully because it can feel aggressive if the player wants to start quickly.
Privacy and consent for ads
- On Google Play, complete the Data safety form based on what your app and third-party SDKs collect or share. The developer is responsible for accurate declarations.
- If ads use personal data or advertising identifiers, explain that in the privacy policy and store forms.
- For regions that require consent, use a consent flow before requesting personalized ads. Google's User Messaging Platform SDK can manage privacy choices for AdMob.
- For iOS 14.5 or later, Apple requires App Tracking Transparency permission before tracking users or accessing the advertising identifier.
- If the game is for children or teens, check Google Play Families, AdMob family rules, Apple kids category rules, and age rating answers before showing ads.
Google Play in-app purchases
For digital goods or features sold inside a Google Play-distributed game, use Google Play's billing system unless a specific policy exception applies. Digital game examples include coins, extra lives, characters, ad-free upgrades, new levels, and subscriptions.
Product setup
- Create products in Play Console under Monetize with Play > Products.
- Plan product IDs carefully. Product IDs are unique for the app and cannot be changed or reused after creation.
- Activate products before release. A product must be active and available in the user's country or region.
- Declare the
com.android.vending.BILLINGpermission in the Android app manifest.
Billing library
- Use the latest supported Google Play Billing Library for new work.
- As of June 2026, Google documents Billing Library 9 migration and a two-year version deprecation cycle.
- Billing Library 7 can be used for new apps or updates until August 31, 2026. Billing Library 8 can be used until August 31, 2027.
- Keep one active
BillingClientconnection when possible and handle service reconnection.
Purchase flow you should support
- Load products from the store. Do not hardcode final prices in your UI; show the localized price returned by the store.
- Start the official purchase flow. Use Play Billing on Android or StoreKit on iOS.
- Verify the purchase. For stronger security, verify purchases with your backend before granting expensive items.
- Grant the reward once. Add coins, unlock premium, or remove ads only after a valid purchase result.
- Acknowledge or consume. Acknowledge non-consumables and subscriptions. Consume consumables only after the item is granted.
- Restore and query purchases. On app start and after reinstall, check existing entitlements so users keep what they paid for.
- Handle refunds and cancellations. Remove or update entitlements when a purchase is refunded, canceled, expired, or revoked.
Apple in-app purchases
For iPhone and iPad, create purchases in App Store Connect and use StoreKit in the iOS app. Apple supports consumable, non-consumable, auto-renewable subscription, and non-renewing subscription products.
- Create the product in App Store Connect with a clear reference name and product ID.
- Use StoreKit to load product information, start payments, handle transaction updates, and deliver the purchased content.
- Provide a restore purchases option for restorable products, such as non-consumables and subscriptions.
- Use StoreKit Testing, sandbox testing, and TestFlight before App Review. In-app purchases in TestFlight use the sandbox environment, are free for testers, and do not carry into production.
- Submit in-app purchases for review with the app when required.
LÖVE2D integration note
- Keep game rewards in Lua, but keep store purchase validation in native code or on a backend.
- Never unlock paid items only from a local Lua flag that can be edited easily.
- For "remove ads", save the entitlement and check it before loading any ad placement.
- For coins or gems, use server validation if the economy matters or if purchases are expensive.
Store disclosure checklist
Google Play
- Mark that the app contains ads if ads are shown.
- Complete Data safety for ads, analytics, identifiers, purchases, crash reporting, and any SDKs.
- Disclose in-app purchases in the store listing where required.
- Use clear product titles, descriptions, and prices.
- Test purchases with license testers or an internal/closed testing track.
Apple App Store
- Complete App privacy details for every SDK and data type.
- Use ATT if tracking is performed.
- Make the purchase UI clear about price, duration, renewal, and what the player receives.
- Include restore purchases for restorable products.
- Test with sandbox and TestFlight before submitting for review.
Official monetization links
Final publishing checklist
Use this page before you send your app for review.
Game quality
Code
- No startup crash
- No missing files
- No console errors
- Save/load tested
Mobile UI
- Buttons work with touch
- Text is readable
- UI fits different screens
- Orientation is correct
Performance
- Images compressed
- Audio optimized
- No huge unused files
- Stable FPS on phone
Android checklist
- Package name is final, for example
com.yourstudio.yourgame. versionCodeincreased.versionNamecorrect.- love-android cloned with submodules, or submodules initialized after cloning.
- JDK, Android SDK, NDK, and CMake versions match the current love-android README.
- Target API requirement checked.
- Release build signed.
- AAB built for Google Play.
- APK tested on a real Android phone through Android Studio, ADB, or a trusted manual install.
- Keystore backed up safely.
- Ad SDK, Play Billing Library, and purchase products checked if monetization is used.
AD_IDandBILLINGpermissions checked and only included when needed.
iOS checklist
- Mac and correct Xcode version ready.
- Bundle ID is final and matches App Store Connect.
- Signing team selected.
- Version and build number set.
- Real iPhone/iPad tested.
- TestFlight tested.
- App Store Connect metadata completed.
- StoreKit products, restore purchases, sandbox purchases, and ATT prompt checked if monetization is used.
Store checklist
- Icon ready.
- Screenshots ready.
- Short description ready.
- Full description ready.
- Privacy policy URL ready.
- Data safety / app privacy completed.
- Contains ads / in-app purchase disclosures completed if used.
- Ad placements, consent flow, and purchase restore flow tested.
- Age rating completed.
- Release notes written.
Common problems and simple answers
Why does my .love file not run?
Most of the time, main.lua is not at the top level of the archive. Open the file and make sure main.lua is not inside another folder.
Should I upload APK or AAB to Google Play?
Use APK for testing. Use AAB for Google Play release.
Can I still follow older LÖVE2D Android videos?
Use them for the general workflow, but check current instructions before building. The useful parts are still cloning love-android with submodules, installing Android SDK/NDK tools, embedding your game, and testing on a real device. Avoid outdated APKTool or manual repackaging steps unless the current love-android docs explicitly say to use them.
Do I need to copy APK files manually to my phone?
No. Manual copying can work for quick testing, but Android Studio or adb install -r path/to/app.apk is usually faster. If you install from a file manager, Android may require "install unknown apps" permission for that file manager.
Why is Android Studio showing Gradle errors?
Common reasons are wrong JDK version, missing Android SDK/NDK, old Gradle files, or mixing incompatible LÖVE/love-android versions. Use a released tag and follow that version's instructions.
Do I need microphone permission?
No, not unless your game actually records audio or uses the microphone. For most games, use the NoRecord build variant.
Can I publish iOS from Windows?
Not normally. iOS publishing needs Xcode, and Xcode requires macOS.
What is the difference between version and build number?
The version is what users see, like 1.0.0. The build number is an internal upload number. You must increase it every upload, especially on iOS.
What is love-release?
love-release is a helper tool for packaging LÖVE games, mostly useful for desktop or .love workflows. For mobile stores, learn the official Android and iOS build paths first.
Do I need a privacy policy?
You should have one if your app collects data, uses ads, analytics, crash reporting, accounts, online features, purchases, or third-party SDKs. Even simple games may need privacy answers in the store dashboard.
Can I add ads to a LÖVE2D mobile game?
Yes, but usually not from Lua alone. You normally add the ad SDK to the Android or iOS wrapper project, then bridge ad events back to your LÖVE game.
Can I sell coins, remove ads, or unlock levels?
Yes. Use Google Play Billing for Android digital goods and StoreKit for Apple platforms. Use consumable products for repeat purchases like coins, and non-consumable products for permanent unlocks like remove ads.
Should I use rewarded ads or interstitial ads?
Rewarded ads are usually safer for small games because the player chooses to watch them. Interstitial ads should only appear at natural breaks, not during active gameplay or near touch controls.
Useful official links
- LÖVE Wiki
- love-android GitHub
- LÖVE GitHub
- love-apple-dependencies GitHub
- Google Play target API requirement
- Android App Bundle guide
- Install Android NDK and CMake
- Run apps on a hardware device
- Android Debug Bridge
- Google Play billing system
- Google Mobile Ads SDK for Android
- Apple upcoming requirements
- Apple In-App Purchase