Cheatsheet
Starting a Project
To create a new project, you can run the command turbo init <PROJECT-NAME>
. For example, we could run the following command if we want to make a project called hello-world
:
turbo init hello-world
This will create a new project directory with the following structure:
hello-world/ # Your project's root directory.
├── src/ # The directory of your code.
│ └── lib.rs # The main file for the game.
├── Cargo.toml # Rust project manifest.
└── turbo.toml # Turbo configuration.
Once the project has been initialized, you can run it with turbo run -w <PROJECT-NAME>
. For example, to run the hello-world
project we created with the previous command:
turbo run -w hello-world
Updating Your Config
When you initialize a project, you'll see a file called turbo.toml
in your project directory. If you open that file, you should see something like this:
name = "hello-world"
version = "0.1.0"
authors = ["Your Name"]
description = "An awesome game made in Turbo!"
[canvas]
width = 256
height = 144
Managing Assets
Assets go in special subdirectories within the project directory. All asset folders are optional, so if you don't have a certain kind of asset, there is no need to add an empty directory.
your-project-dir/ # Your project's root directory.
├── sprites/ # The directory of your sprite assets.
├── fonts/ # The directory of your font assets.
├── audio/ # The directory of your audio assets.
├── shaders/ # The directory of your shaders.
├── src/ # The directory of your code.
│ └── lib.rs # The main file for the game.
├── Cargo.toml # Rust project manifest.
└── turbo.toml # Turbo configuration.
Drawing Shapes
// Draw a 20x40px blue rectangle
rect!(w = 20, h = 40, x = 70, y = 70, color = 0xff00ffff)
// Draw an 16px diameter magenta circle
circ!(d = 16, x = 120, y = 64, color = 0xff00ffff)
Displaying Text
// Basic text
text!("Hello, world!");
// Customized text with specified position, color, and font size
text!(
"Greetings, earthlings >:3",
x = 30,
y = 40,
color = 0x00ff00ff,
font = "small"
);
Handling Mouse & Touch Controls
// The pointer control works for both mouse and touch inputs
let p = pointer();
// Get the pointer x position
let pointer_x = p.x;
// Get the pointer y position
let pointer_y = p.y;
// Check if the pointer was just pressed this frame (mouse click or touch)
if pointer.just_pressed() {
// ...
}
Handling Gamepad Controls
// Get player 1's gamepad (Pass a 1 instead of a 0 for player 2's gamepad)
let gp = gamepad(0);
// Check if the `Up` button was just pressed this frame.
if gp.up.just_pressed() {
// ...
}
// Check if the `Down` button is currently being pressed.
if gp.down.just_pressed() {
// ...
}
// Check if the `A` button was just released this frame.
if gp.a.just_released() {
// ...
}
// Check if the `B` button is currently not being pressed.
if gp.b.released() {
// ...
}
Generating Random Numbers
// Get a random number
let n = rand();
// Check if a random number is even
let is_even = rand() % 2 == 0;
// Check if a random number is odd
let is_odd = rand() % 2 != 0;
// Get a random number between 1-100
let n = 1 + (rand() % 100);
// Probability Ranges
match n {
1..=10 => { ... } // 10% chance
11..=50 => { ... } // 40% chance
_ => { ... } // 50% chance
}
Tracking Time
In most cases, using the current game "tick" is sufficient for working with time in a game. It starts at 0
and increases by one each time a new frame is rendered.
let t = tick();
When you need an actual unix timestamp, we've also got you covered:
let timestamp = time::now();
Adjusting the Camera
// Get the camera position
let (x, y, z) = camera::xyz();
// Set the camera position
// The position you set here is the center of the viewport in pixels. By default the camera starts at half of the width and height of your game's resolution.
camera::set_xy(100, 100);
// Move the camera position relative to the current camera position
camera::move_x(5.0);
camera::move_y(8.0);
// Reset the camera to its original position
camera::reset();
Debugging
Turbo's logging system prints directly to your terminal, making it easy to trace variable values, game state, and behavior during runtime. Whether you're narrowing down a bug or watching a value evolve, log!
is your go-to for visibility without disruption.
// Log a static message
log!("o hai!");
// Log a single value
let some_var = "foo";
log!("one value: {:?}", some_var);
// Log multiple values
let another_var = 42;
log!("multiple values: {:?} {:?}", some_var, another_var);
// Log game state
log!("My game state = {:?}", self);
Turbo Game Structure
Turbo provides a straightforward way to initialize the standard game state.
-Create a new struct with GameState values. -Initialize the state in the new() function. -Run the game loop from the update() function. Turbo games run at 60 fps.
Here is an example using the appropriate format.
use turbo::*;
// Turbo procedural macro
#[turbo::game]
#[derive(Debug, Clone, PartialEq, BorshSerialize, BorshDeserialize)]
struct GameState {
x_position: i32,
y_position: i32,
}
impl GameState{
fn new()->Self{
// Return the GameState's initial value.
// You can also run initialization code here before returning the state.
Self {
x_position: 30,
y_position: 40,
}
}
fn update(&mut self){
// Update State
// The bulk of your game's logic goes here. Mutate state as-needed.
}
}