# Solar2D

Export Solar2D (Corona SDK) games to HTML5 and wire the SDK through the JavaScript Module Loader.

Source: https://docs.wavedash.com/engines/solar2d

<GithubLink href="https://github.com/wvdsh/examples/tree/main/example-solar2d" label="View the example on GitHub" />
<PlaytestLink href="https://wavedash.com/playtest/solar2d-example/7dfd33fc-8c87-400c-bc25-5bf04480ed32" />

[Solar2D](https://solar2d.com/) (formerly Corona SDK) is a Lua framework with a first-party HTML5 export target. The export bundles your Lua into a WebAssembly build of the Solar2D runtime.

## Export your game

Open the project in the Solar2D Simulator and choose **File → Build → HTML5 (Beta)**. Pick an output folder **outside** the project directory (the builder refuses to write into the source folder) — `~/Desktop` or `/tmp` works. Then move the contents into `./build/`:

```bash
mv ~/Desktop/example-solar2d.html5/* build/
```

The output includes `index.html`, the engine JS bundle, and your game's compiled Lua.

<Note>
HTML5 export is still labeled **Beta** in the Solar2D simulator, and there's no maintained headless CLI — the GUI builder is the supported path.
</Note>

## Content dimensions and orientation

Solar2D's `config.lua` `content.width` / `content.height` are always the **portrait** dimensions — Solar2D swaps them at runtime based on `orientation.default` in `build.settings`. A landscape game needs both sides set:

```lua
-- config.lua
application = {
    content = {
        width  = 1080,       -- portrait width  → landscape height
        height = 1920,       -- portrait height → landscape width
        scale  = "letterBox",
        fps    = 60,
    },
}
```

```lua
-- build.settings
settings = {
    orientation = {
        default   = "landscapeRight",
        supported = { "landscapeRight", "landscapeLeft" },
    },
}
```

Without the `orientation` block, Solar2D's HTML5 build defaults to portrait and renders the canvas rotated 90° relative to what `content.width/height` suggest.

Make gameplay constants proportional to `display.contentWidth` / `display.contentHeight` so changing the content size in `config.lua` is the only knob you need:

```lua
local W, H = display.contentWidth, display.contentHeight
local PADDLE_H   = H / 6           -- ~16.7% of height
local PADDLE_SPD = H * 5 / 6       -- pixels per second
```

## SDK integration

Solar2D's HTML5 target supports a [**JavaScript Module Loader**](https://docs.coronalabs.com/guide/html5/plugins/index.html): any `<name>.js` file at the project root that defines a global object named `<name>` becomes loadable as `require "<name>"` in Lua. This is the clean way to call `window.Wavedash` from Lua without post-build patching the exported HTML.

Drop a `wavedash.js` next to your `main.lua`:

<Urgent>
**Calling `Wavedash.init()` is required.** Your game stays hidden behind the Wavedash loading screen until you do. Call it once your game is ready to play.
</Urgent>

```javascript
// wavedash.js
var Wavedash = window.Wavedash;
var wavedash = {
    init: function () {
        Wavedash.init();
    },
    updateLoadProgressZeroToOne: function (p) {
        Wavedash.updateLoadProgressZeroToOne(p);
    },
};
```

Then call it from `main.lua`, guarded by `system.getInfo("platform")` so the Lua still runs fine in the desktop Simulator:

```lua
-- main.lua
if system.getInfo("platform") == "html5" then
    local wavedash = require "wavedash"
    wavedash.updateLoadProgressZeroToOne(0.3)   -- engine ready
    -- load assets, set up scene ...
    wavedash.updateLoadProgressZeroToOne(0.7)   -- assets loaded
    -- final setup ...
    wavedash.updateLoadProgressZeroToOne(1)     -- all done
    wavedash.init()
end

-- ... rest of your game ...
```

Call `updateLoadProgressZeroToOne(...)` with intermediate values during any async setup. `init()` automatically signals load completion, so call it last.

## wavedash.toml

```toml
game_id = "YOUR_GAME_ID_HERE"
upload_dir = "./build"
entrypoint = "index.html"
```

## Other SDK features

Expose each SDK method you need by adding another property on the `wavedash` global in `wavedash.js`:

```javascript
var wavedash = {
    // ... init / updateLoadProgressZeroToOne as above ...
    uploadLeaderboardScore: function (id, score) {
        Wavedash.uploadLeaderboardScore(id, score, true);
    },
    setAchievement: function (id) {
        Wavedash.setAchievement(id, true);
    },
};
```

`uploadLeaderboardScore` takes the leaderboard's **ID** (returned by `getLeaderboard("name")`), not the name itself. Lua doesn't have native promise/await semantics, so the cleanest path is to resolve the ID once at game start in `wavedash.js` and expose it as a Lua-readable global:

```javascript
// in wavedash.js, after Wavedash is in scope:
Wavedash.getLeaderboard("high-scores").then(function (lb) {
    if (lb.success) wavedash.highScoresId = lb.data.id;
});
```

Then from Lua:

```lua
wavedash.setAchievement("first_win")
-- once highScoresId is populated:
wavedash.uploadLeaderboardScore(wavedash.highScoresId, score)
```

See the [SDK reference](/sdk/overview) for the full API.

<Warning>
The `build.settings` `html5.templateFile` key is silently ignored by Solar2D's HTML5 builder (it's for other targets only). Don't try to wire the SDK through a custom HTML template — use the JavaScript Module Loader pattern above.
</Warning>
