#playdate-sdk #api #gaming #gamedev #env-var #safe #hand

nightly craydate

A safe Rust API for the Playdate hand held gaming system

8 releases

0.1.7 Apr 27, 2022
0.1.6 Apr 27, 2022

#595 in Development tools

MIT/Apache

635KB
16K SLoC

Craydate

This crate and its related crates together provide a safe Rust API for the Playdate hand held gaming system. It is built on the Playdate C Api.

The name is crustacean pun, with our dear friends the crayfishes.

Requirements

Using these crates requires the Playdate SDK, which has its own license. Install the SDK and add an environment variable named PLAYDATE_SDK_PATH that points to the directory where you installed it, such as PLAYDATE_SDK_PATH=C:\playdate.

This crate uses unstable features in order to provide a #![no_std] application to run on the Playdate simulator and hardware device. Thus it requires use of the Rust nightly compiler.

Getting Started

Building a #![no_std] application that is compiled for the Playdate simulator requires a bit of extra Cargo setup, which we try to make easy for you. The dependency structure of your project will look like this:

- your-game-project**
  ├── [dependencies] your-game** (`#![no_std]` crate)
  |   ├── [dependencies] craydate (`#![no_std]` crate)
  |   └── [dependencies] euclid (with `default-features = false` and `features = ["libm"]`)
  └── [build-dependencies] craydate-build

** = is specific to your game and provided by the game developer.

Note that your game's crate must include the #![no_std] directive in its crate root in order to build for the Playdate device.

The euclid crate is used in the craydate public Apis, which is why you will need it. The features listed above are specified to make the crate compatible with a #![no_std] application.

If you choose not to use the root project crate talked about below, then you do not need the craydate-build in [build-dependencies], but will be responsible to build the pdx image and install it yourself.

The root project crate

We provide an template of a root project crate at craydate-project, which will act as the coordination point to build your game for the Playdate simulator and the Playdate device. To use it, please rename and customize it for your game.

To start using it, download the latest release, unzip it and edit it as follows. See below for more details.

  1. Ensure your PLAYDATE_SDK_PATH environment variable is set to the location of the Playdate SDK.
  2. In the Cargo.toml file, change the name to include your game's name, such as foo-project for the game crate foo.
  3. In the Cargo.toml file, change the game dependency's package and path to point to your game's crate.
  4. In the Cargo.toml file, if you want to use it, change the game-assets dependency's package and path to point to your game's asset-generating crate (when you have one, you can leave it commented out with a # for now).
  5. If you have a game-assets dependency for generating assets, uncomment and fix the call to it from src/bin/make_pdx.rs (when you have one, you can ignore this for now).
  6. If you have a game-assets dependency for generating assets, uncomment "game-assets" in the bins feature (when you have one, you can ignore this for now). It would look like bins = ["craydate-build", game-assets"].

Development Workflow

To build your game for the Playdate simulator, simply build your customized root project your-game-project crate with the Cargo --lib flag, which will build your game as a dependency.

After building the game, the root project crate (if based on craydate-project) includes 2 binaries to help you get it onto the Playdate simulator or a hardware device. Build them by building your root project your-game-project crate with the Cargo --bins flag. The binaries are:

  • make_pdx
  • run_simulator

make_pdx

Combines your built game, along with any asset files into a pdx image for the device or simulator.

The your-game-assets dependency seen above is an optional place to construct and collect assets for your game that will be included by make_pdx when building the game's pdx image. To do so, edit the make_pdx.rs file to call your-game-assets. Assets should be collected into env!("PDX_SOURCE_DIR"). For example:

  your_game_assets::generate_assets(env!("PDX_SOURCE_DIR"))?;

The make_pdx binary would then include those assets into your game's pdx image.

run_simulator

Runs the Playdate simulator, loading the pdx image generated by make_pdx.

VSCode

We provide configurations for VSCode in the template root project craydate-project to build and use the make_pdx and run_simulator binaries correctly. The .vscode/settings.json file configures these tasks. You should not need to change the configuration unless you move the .vscode directory out of the root project crate.

  • The "projectRootCrate" variable should point to the root project crate. By default, since the .vscode directory is inside that crate, it is ".".
  • The "rust-analyzer.linkedProjects" variable should point to the root project crate's Cargo.toml file. By default it is "./Cargo.toml".

When running the simulator with this task, VSCode will capture the stdout and stderr output of the game and write it to a file called stdout.txt in the project's root directory.

Panics

The Cargo.toml for the root project crate must also set panic = "abort". This is included in the template root project craydate-project crate:

[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"

Otherwise you will get a compilation error:

error: language item required, but not found: `eh_personality`
  |
  = note: this can occur when a binary crate with `#![no_std]` is compiled for a target where `eh_personality` is defined in the standard library

Your first game

Your game's crate must include a function that will be called after the Playdate system initializes. This function should contain your game's main game loop. It's simplest form would look like:

#[craydate::main]
async fn main(api: craydate::Api) -> ! {
  let events = api.system.system_event_watcher();
  loop {
    match events.next().await {
      craydate::SystemEvent::NextFrame { inputs, .. } => {
        // Read inputs, update game state and draw.
      }
      _ => (),
    }
  }
}

Then, handle the various events that can be returned from next(). In particular, handle input, update game state, and draw to the screen when the SystemEvent::NextFrame event happens. You can access the Playdate device through the craydate::Api parameter to main().

Logging to the Playdate simulator's console, for debugging, is possible through the craydate::log() and craydate::log_error() functions.

Platforms

Currently the craydate project only supports development for the Windows simulator. We will expand support to the Playdate hardware device once we get access to one. Simulators on other platforms (e.g. Mac) are possible, and would only need changes to the root project crate.

  • The "osx.craydateHostTarget" setting may need to change if you're working on an ARM-based mac.
  • The "linux.craydateHostTarget" setting hasn't been tested to see if it's correct.
  • A MacOSX simulator build has not been tested and may not link.
  • A Linux simulator build has not been tested and may not link.
  • There's no VSCode task to install the pdx on a Playdate device yet.
  • The build for a Playdate device has not been tested yet and may not load at all.

License

This project is licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Craydate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Dependencies

~2.5MB
~60K SLoC