Jamkit is a small set of simple, plug-and-play Utilities to facilitate a game jam submission
It's not intended to support every possible permutation / feature for what it provides, rather it should give you something good enough and then get out of the way.
A native and wasm-compatible API for quickly saving and loading files. This is accomplished via implementing the WorldModifiable trait for the type that you would like to save. It saves it to an application specific folder for your app.
View Example
fn main(){
app.add_plugins(PersistenceBackendPlugin("bevy_jamkit".to_owned()))
app.add_plugins(PersistentFilePlugin::<SaveData, ExampleState>::new(
"save.json",
ExampleState::ResolveSave,
ExampleState::Title,
));
}
#[derive(Clone, Copy, Serialize, Deserialize)]
struct SaveData {
counter: u32,
}
impl WorldModifiable for SaveData {
fn extract(world: &mut World) -> Self {
let data = world.resource::<GameData>();
SaveData {
counter: data.count,
}
}
fn apply(self, world: &mut World) {
info!("Applying");
world.insert_resource(GameData {
count: self.counter,
});
}
}
#[derive(Resource)]
struct GameData {
pub count: u32,
}
enum ExampleState {
#[default]
ResolveSave,
Title,
Playing,
}Jamkit provides a very simple title screen that shows some logo-type and a set of buttons that will transition a specified state
Title Scene Example
app.add_plugins(SimpleTitleScreen {
spawn_state: ExampleState::Title,
title_label: "EXAMPLE GAME".to_owned(),
button_cfgs: vec![("Play".to_string(), ExampleState::Playing)],
background_img_path: Some("examplebg.png".to_string()),
phantom_data: std::marker::PhantomData::<UiAssets>,
});Jamkit provides a simple jukebox that will play the specified tracks in order.
Note: Each track must be specified as WASM does not currently support loading folders
Jukebox Example
app.add_plugins(JukeboxPlugin(vec![
"music/OrbitSkinCrawlers.mp3".to_owned(),
"music/SolitaryTerminal.mp3".to_owned(),
]));Jamkit provides a basic theming and UiKit that provides labels, buttons, and Key/Mouse input prompts.
All widgets return impl Bundle to allow users to mix in their own required gameplay components
Example UI
cmds.spawn((
Name::new("Game UI"),
Node {
width: Val::Percent(100.0),
top: Val::Percent(5.0),
display: Display::Flex,
flex_direction: FlexDirection::Column,
align_items: AlignItems::Center,
justify_content: JustifyContent::SpaceBetween,
..default()
},
children![
(
Name::new("Logo Text"),
assets.ui_logo_label_justified("EXAMPLE", assets.palette().primary, Justify::Center),
),
(
Name::new("Hint"),
assets.ui_detail_label("Press Space to increment the counter", assets.palette().secondary)
),
(assets.key_prompt_stacked(KeyCode::Space, "Add One".to_string()),),
(
Name::new("Counter"),
CounterLabel,
assets.ui_label(gamedata.count.to_string(), assets.palette().interaction),
),
(
Name::new("Save Button"),
assets.ui_button("Save", &assets.button_cfg(), assets.palette().primary),
BundleEffect::new(|entcmds| {
entcmds.observe(save);
})
),
assets.mouse_prompt(PointerButton::Primary, "Click Save Button".to_owned()),
],
));See the examples/example.rs for full example
A basic component that allows you to modify an entity after it's been spawned, but define that modification as a part of a impl Bundle. Used primarily as a way to attach an entity-observer to a declarative/bundled UI
Example:
(
Name::new("Save Button"),
assets.ui_button("Save", &assets.button_cfg(), assets.palette().primary),
BundleEffect::new(|entcmds| {
entcmds.observe(save);
})
)