Crates.io | cargo-devcade |
lib.rs | cargo-devcade |
version | 0.8.0 |
source | src |
created_at | 2023-03-13 20:45:47.771014 |
updated_at | 2023-04-08 20:17:14.270077 |
description | CLI tool for building and packaging devcade games |
homepage | |
repository | |
max_upload_size | |
id | 809245 |
size | 258,995 |
cargo-devcade
is a helper for building and deploying devcade games with Rust!
Installation is simple:
cargo install cargo-devcade
Psst! Make sure you also have cross
installed and working too!
cargo-devcade
and bevy
!Though it's not required, I recommend you use bevy
and devcaders
to put stuff on the screen.
Once you have cargo-devcade
installed, we can make a new project:
cargo new ferris-spinner
cd ferris-spinner
Now, let's add some dependencies we'll need:
cargo add bevy devcaders
Mary Note:
Oh, and don't forget the icons! icon.png
and banner.png
should exist in the store_icons
folder of your crate root:
mkdir store_icons
curl https://placehold.it/800x450.png -Lo store_icons/banner.png
curl https://placehold.it/512x512.png -Lo store_icons/icon.png
Before we do anything else, let's do a test build to make our project is set up properly:
cargo devcade package
This should run a build, and package your app for production.
If it didn't work, maybe you hit a bug... Or more likely you set it up wrong!
Bevy is pretty neat, here's a tiny game we can try with:
use bevy::{prelude::*, window::WindowMode};
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
mode: WindowMode::Fullscreen,
..default()
}),
..default()
}))
.add_startup_system(setup_system)
.add_system(hello_world_system)
.run();
}
fn setup_system() {
println!("Welcome to ferris spin!");
}
fn hello_world_system() {
println!("hello world");
}
Cool, let's give it a run:
cargo run
It does... nothing! ...Except print 'hello world' a bunch of times and make a window.
That's because we're not drawing anything yet!
Let's grab some pictures from the interwebz to use in our game:
mkdir assets
curl https://rustacean.net/assets/rustacean-flat-happy.png -o assets/ferris.png
Cool! Now let's make a camera and a ferris at startup:
#[derive(Component)]
struct Ferris {}
fn setup_system(mut commands: Commands, asset_server: Res<AssetServer>) {
println!("Welcome to ferris spin!");
// Add a camera so we can see stuff:
commands.spawn(Camera2dBundle::default());
// Draw a ferris in the middle of the screen
commands.spawn((
Ferris {},
SpriteBundle {
texture: asset_server.load("ferris.png"),
transform: Transform::from_xyz(100., 0., 0.),
..default()
},
));
}
And now:
cargo run
You should see a crab on your screen. If you don't and got some kind of error... Open an issue?
An interesting bevy pattern showed up here, did you spot it?
In bevy, sometimes we link a dummy component (in this case Ferris
) so it can be looked-up later. We'll see some of that syntax in the next step
Hey, this is cool, but what if we could move the crab around?
fn hello_world_system(mut sprite_position: Query<(&mut Ferris, &mut Transform)>) {
for (_, mut transform) in &mut sprite_position {
transform.translation.x -= 1.0;
}
println!("hello world");
}
But uh... What if we could actually control it?
Hmm... But how? Maybe that devcaders
library we added earlier could help us...
use devcaders::{DevcadeControls, Player, Button};
fn hello_world_system(
time: Res<Time>,
mut sprite_position: Query<(&mut Ferris, &mut Transform)>,
devcade_controls: DevcadeControls,
) {
for (_, mut transform) in &mut sprite_position {
if devcade_controls.pressed(Player::P1, Button::StickLeft) {
transform.translation.x -= 5.0 * time.delta_seconds();
}
if devcade_controls.pressed(Player::P1, Button::StickRight) {
transform.translation.x += 5.0 * time.delta_seconds();
}
}
println!("hello world");
}
Cool! Now our crab moves when we move the joystick.
For a full list of controls and their meanings, check devcaders' Button
enum
If you don't have a controller attached, you can use the V
and N
keys instead!
For more information, or to learn more, visit bevyengine.org!
So... We should make it possible to exit.
Add these lines to our system to exit on menu button press (by either player!):
if devcade_controls.pressed(Player::P1, Button::Menu)
|| devcade_controls.pressed(Player::P2, Button::Menu)
{
std::process::exit(0);
}
Publishing to devcade is easy:
cargo devcade package