Migrating from Corona SDK to Solar2D: Step-by-Step Checklist

Creating Cross-Platform Apps with Corona SDK — Best PracticesCorona SDK (now maintained as Solar2D) is a lightweight, Lua-based framework designed for rapid development of 2D mobile applications and games. Its simplicity, fast iteration via live reloading, and cross-platform capabilities make it an attractive choice for indie developers and small teams. This article covers best practices for building robust, performant, and maintainable cross-platform apps using Corona SDK/Solar2D.


Why choose Corona SDK / Solar2D?

Corona SDK provides:

  • Fast development cycle with live simulator and quick builds.
  • Single Lua codebase that targets iOS, Android, Windows, macOS, and more.
  • Built-in APIs for graphics, audio, touch, networking, and native UI components.
  • Extensive plugin ecosystem and active community support.

These strengths let developers focus on app logic and user experience rather than platform-specific plumbing.


Project setup and organization

A clean, consistent project structure simplifies cross-platform development and reduces bugs.

Recommended structure:

  • main.lua — app entry point
  • conf.lua — configuration (content scaling, orientation)
  • build.settings — platform-specific settings and plugins
  • /scenes — scene modules (using Composer or another scene manager)
  • /assets — images, fonts, audio (organized by type and resolution)
  • /libs — third-party libraries and utilities
  • /controllers — game/app logic
  • /models — data models and persistence
  • /views — UI components
  • /platform — small platform-specific adapters (in-app purchases, ads)

Tips:

  • Use Composer (built-in scene manager) or an alternative like Storyboard replacement patterns to manage screens and transitions.
  • Keep main.lua minimal: initialize services, configure global settings, and go to the initial scene.
  • Isolate platform-specific code in /platform adapters to avoid scattering conditional logic.

Cross-platform asset handling

Handling assets for multiple screen sizes and densities is crucial.

Content scaling:

  • Configure content scaling in conf.lua. A common approach is to design for a “base” content width and height and use dynamic scaling for various devices.
  • Example conf.lua settings:
    • Set content width/height and use “letterbox” or “zoomEven” to preserve aspect ratio.
    • Provide multiple image resolutions and use Solar2D’s dynamic image selection by naming (e.g., image.png, [email protected], [email protected]).

Organize assets:

  • Store separate folders for high-density assets if necessary, but prefer Solar2D’s automatic image suffix handling.
  • Use vector-like approaches where possible (e.g., Shapes, polygons) to reduce bitmap dependency.

Optimize images:

  • Use appropriate formats: PNG for UI with transparency, JPEG for photos.
  • Compress images and remove metadata.
  • Trim unused alpha and reduce color depth when acceptable.

Responsive UI and layout

Design UI to adapt rather than hard-code positions.

Anchoring and alignment:

  • Use display.contentCenterX/Y and calculated offsets instead of absolute coordinates.
  • Create utility functions for left/center/right alignment that factor in content scaling and safe areas (notches).

Safe areas and notches:

  • Query system.safeArea or platform-specific APIs to get top/bottom insets and adjust layout to avoid overlap with status bars and notches.

Relative sizing:

  • Size UI elements relative to screen dimensions or parent containers.
  • Use display.newGroup() to create reusable UI groups that can be scaled and positioned as units.

Font scaling:

  • Use a base font size and multiply by a scale factor derived from screen height/width to maintain legibility.

Performance optimization

Small inefficiencies multiply on low-end devices. Optimize early and measure.

Graphics:

  • Minimize display objects—reuse objects and use sprite sheets (image sheets) instead of many individual images.
  • Use texture atlases to reduce texture binds and draw calls.
  • Avoid excessive use of display.newText for high-frequency updates; use cached snapshots or replacing textures.

Physics:

  • Reduce physics body complexity (use simple shapes).
  • Turn off physics simulation when not needed (physics.pause()).
  • Limit active physics objects and joints.

Memory:

  • Release unused textures with display.remove() and set references to nil.
  • Use collectgarbage(“collect”) sparingly and only where appropriate.
  • Watch for Lua table leaks—ensure listeners and timers are removed on scene exit.

Audio:

  • Use audio.loadSound for short effects and audio.loadStream for music.
  • Dispose audio handles when not needed.

Profiling:

  • Use the Solar2D profiler and print memory stats during development to catch leaks.
  • Test on real devices, including low-end Android hardware.

Input and touch handling

Make touch interactions consistent across devices and platforms.

Unified touch listeners:

  • Use Runtime:addEventListener(“touch”, …) or local object touch listeners depending on the context.
  • Implement gesture recognizers (tap, swipe, pinch) in a central utility to maintain consistency.

Multi-touch:

  • Enable multitouch where needed: system.activate(“multitouch”) or platform-appropriate APIs.
  • Debounce inputs to prevent accidental multi-triggering on slower devices.

Accessibility:

  • Provide larger touch targets for essential controls.
  • Respect platform font scaling and accessibility settings where possible.

Platform-specific features and plugins

Abstract platform differences behind adapter modules.

Build.settings and plugins:

  • Declare required plugins and platform permissions in build.settings.
  • Use conditional requires and platform checks (system.getInfo(“platformName”)) inside adapter modules.

Examples of platform-specific features:

  • In-app purchases: wrap store.* APIs in an IAP adapter with uniform callbacks.
  • Push notifications: centralize registration, token handling, and handlers.
  • Ads and analytics: create adapters to switch providers or disable in development.

Keep platform checks centralized; avoid sprinkling system.getInfo checks across the codebase.


Networking and backend integration

Design resilient network logic for mobile conditions.

HTTP and sockets:

  • Use network.request for RESTful calls and LuaSocket/websocket plugins for persistent connections.
  • Implement exponential backoff and retry logic for unstable networks.

Data handling:

  • Serialize data with JSON (json.encode/decode) and validate responses.
  • Cache important data locally (via Lua files or native storage) and implement sync strategies for offline use.

Security:

  • Always use HTTPS. Verify TLS where possible.
  • Avoid storing sensitive tokens in plain text; use native.keychain or encryption plugins when available.

Rate limits and batching:

  • Batch small requests where feasible to conserve battery and reduce overhead.
  • Respect backend rate limits and implement client-side throttling.

Data persistence

Choose the right persistence mechanism for your needs.

Options:

  • System.pathForFile with io.* functions for small JSON or flat-file storage.
  • sqlite3 plugin for structured relational data and queries.
  • Native preference/keychain plugins for secure storage of tokens.

Best practices:

  • Use an abstraction layer (e.g., dataStore.save/get) so storage backend can change without affecting app logic.
  • Handle migrations: when schema changes, provide a migration path to update existing user data.

Testing and CI

Automate builds and tests to ensure cross-platform quality.

Automated builds:

  • Use CI services to run builds for iOS and Android (export automation or build service integrations).
  • Automate signing and provisioning profiles securely (use environment variables and secrets).

Testing:

  • Unit-test Lua modules where possible.
  • Use device farms or cloud testing services to run UI tests across multiple devices and OS versions.

Debugging:

  • Use Composer scene enter/exit logs and centralized error handlers to capture stack traces.
  • Implement remote logging/analytics (with user consent) to capture uncaught errors.

Monetization and store compliance

Prepare for app store requirements early.

Monetization strategies:

  • Ads: integrate via adapter, ensure proper pause/resume behavior and resource cleanup.
  • IAP: implement consumable/non-consumable flows and validate receipts server-side where possible.
  • Paid apps: provide robust upgrade and restore functionality on both platforms.

Store policies:

  • Follow App Store and Google Play guidelines for privacy, permissions, and ad behavior.
  • Provide a privacy policy URL and comply with data collection notices, especially for EU/CCPA.

Internationalization and localization

Design for multiple languages and regions from the start.

String management:

  • Store localized strings in external JSON or Lua files keyed by locale.
  • Avoid concatenating localized fragments; use format strings with placeholders.

Layout adjustments:

  • Allow UI to expand for longer translations.
  • Handle right-to-left (RTL) layouts by mirroring UI where necessary.

Date, time, and numbers:

  • Use locale-aware formatting for dates/times and numeric values where appropriate.

Packaging and release

Prepare separate builds and test flighting.

Configuration:

  • Use build.settings to manage icons, splash screens, required permissions, and supported orientations per platform.
  • Keep versioning consistent across manifests and metadata.

Testing releases:

  • Use staged rollouts to detect platform-specific issues early.
  • Gather crash reports and user feedback in early releases before global rollout.

Migration path: Corona SDK to Solar2D

If you’re moving from classic Corona SDK, Solar2D continues compatibility with most APIs but check:

  • Plugin availability and any breaking changes.
  • Build pipeline differences; set up Solar2D’s build servers or local builds.
  • Update deprecated APIs and test thoroughly across targets.

Example: Minimal cross-platform scene structure

Below is a concise pattern (pseudocode) for a scene initializer and platform adapter usage:

-- main.lua local composer = require("composer") display.setStatusBar(display.HiddenStatusBar) composer.gotoScene("scenes.home") 
-- platform/iap_adapter.lua local M = {} local platform = system.getInfo("platformName") function M.init()   if platform == "iPhone OS" or platform == "iPad" then     -- init Apple IAP   elseif platform == "Android" then     -- init Google Play IAP   end end return M 

Final checklist

  • Use a consistent project structure and Composer for scenes.
  • Handle multiple resolutions via conf.lua and image suffixes.
  • Optimize textures, physics, and audio; profile on real devices.
  • Abstract platform-specific code into adapters.
  • Implement robust networking with offline support and HTTPS.
  • Test on multiple devices and automate builds.
  • Prepare for store compliance, localization, and secure data handling.

Creating cross-platform apps with Corona SDK/Solar2D is about balancing rapid iteration with disciplined architecture. Follow these best practices to keep your code maintainable, performant, and ready for multiple platforms.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *