init
This commit is contained in:
442
Cargo.lock
generated
442
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@ authors = ["Hilmar Wiegand <me@hwgnd.de>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
amethyst = "0.13.0"
|
||||
amethyst = "0.13.2"
|
||||
log = { version = "0.4.8", features = ["serde"] }
|
||||
|
||||
[features]
|
||||
|
||||
6
resources/bindings.ron
Normal file
6
resources/bindings.ron
Normal file
@@ -0,0 +1,6 @@
|
||||
(
|
||||
axes: {},
|
||||
actions: {
|
||||
"flap": [[Key(Space)]],
|
||||
},
|
||||
)
|
||||
@@ -1,4 +1,4 @@
|
||||
(
|
||||
title: "amethyst-cli-starter-2d",
|
||||
dimensions: Some((800, 600)),
|
||||
title: "test",
|
||||
dimensions: Some((432, 768)),
|
||||
)
|
||||
|
||||
BIN
resources/sprites/flappy.png
Normal file
BIN
resources/sprites/flappy.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
42
resources/sprites/flappy.ron
Normal file
42
resources/sprites/flappy.ron
Normal file
@@ -0,0 +1,42 @@
|
||||
(
|
||||
texture_width: 512,
|
||||
texture_height: 512,
|
||||
sprites: [
|
||||
( // Daytime background
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 144,
|
||||
height: 256,
|
||||
),
|
||||
( // Nighttime background
|
||||
x: 146,
|
||||
y: 0,
|
||||
width: 144,
|
||||
height: 256,
|
||||
),
|
||||
( // Down Pipe
|
||||
x: 56,
|
||||
y: 323,
|
||||
width: 26,
|
||||
height: 160,
|
||||
),
|
||||
( // Up Pipe
|
||||
x: 84,
|
||||
y: 323,
|
||||
width: 26,
|
||||
height: 160,
|
||||
),
|
||||
( // Ground
|
||||
x: 292,
|
||||
y: 0,
|
||||
width: 168,
|
||||
height: 56,
|
||||
),
|
||||
( // Floppy
|
||||
x: 3,
|
||||
y: 490,
|
||||
width: 17,
|
||||
height: 13,
|
||||
)
|
||||
]
|
||||
)
|
||||
38
src/components.rs
Normal file
38
src/components.rs
Normal file
@@ -0,0 +1,38 @@
|
||||
use amethyst::{
|
||||
core::transform::TransformBundle,
|
||||
core::transform::Transform,
|
||||
prelude::*,
|
||||
renderer::{
|
||||
plugins::{RenderFlat2D, RenderToWindow},
|
||||
types::DefaultBackend,
|
||||
RenderingBundle,
|
||||
},
|
||||
utils::application_root_dir,
|
||||
core::SystemDesc,
|
||||
derive::SystemDesc,
|
||||
ecs::prelude::{Component, DenseVecStorage, Entity},
|
||||
ecs::prelude::{Join, ReadStorage, System, SystemData, WriteStorage},
|
||||
};
|
||||
|
||||
|
||||
// Falling object component to bucket us into something the system can manipulate
|
||||
#[derive(Clone)]
|
||||
pub struct TiledScroller {
|
||||
pub speed: f32,
|
||||
pub width: f32,
|
||||
pub height: f32,
|
||||
pub position: f32,
|
||||
}
|
||||
impl Component for TiledScroller {
|
||||
type Storage = DenseVecStorage<Self>;
|
||||
}
|
||||
|
||||
// Falling object component to bucket us into something the system can manipulate
|
||||
pub struct Birb {
|
||||
pub vertical_speed: f32,
|
||||
pub starting_height: f32,
|
||||
pub position: f32,
|
||||
}
|
||||
impl Component for Birb {
|
||||
type Storage = DenseVecStorage<Self>;
|
||||
}
|
||||
30
src/main.rs
30
src/main.rs
@@ -1,5 +1,10 @@
|
||||
mod components;
|
||||
mod systems;
|
||||
mod state;
|
||||
use amethyst::{
|
||||
input::{InputBundle, StringBindings},
|
||||
core::transform::TransformBundle,
|
||||
core::transform::Transform,
|
||||
prelude::*,
|
||||
renderer::{
|
||||
plugins::{RenderFlat2D, RenderToWindow},
|
||||
@@ -7,20 +12,38 @@ use amethyst::{
|
||||
RenderingBundle,
|
||||
},
|
||||
utils::application_root_dir,
|
||||
core::SystemDesc,
|
||||
derive::SystemDesc,
|
||||
ecs::prelude::{Component, DenseVecStorage, Entity},
|
||||
ecs::prelude::{Join, ReadStorage, System, SystemData, WriteStorage},
|
||||
};
|
||||
|
||||
mod state;
|
||||
use crate::components::*;
|
||||
use crate::systems::*;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
||||
fn main() -> amethyst::Result<()> {
|
||||
amethyst::start_logger(Default::default());
|
||||
|
||||
let app_root = application_root_dir()?;
|
||||
//amethyst::start_logger(Default::default());
|
||||
|
||||
// Gets the root directory of the application
|
||||
let mut app_root = PathBuf::from_str("/home/mrh/source/amethyst-starter-2d/")?;
|
||||
|
||||
// join on the resources path, and the config.
|
||||
let resources = app_root.join("resources");
|
||||
let display_config = resources.join("display_config.ron");
|
||||
let binding_path = resources.join("bindings.ron");
|
||||
|
||||
let input_bundle = InputBundle::<StringBindings>::new()
|
||||
.with_bindings_from_file(binding_path)?;
|
||||
|
||||
//
|
||||
let game_data = GameDataBuilder::default()
|
||||
.with_bundle(TransformBundle::new())?
|
||||
.with_bundle(input_bundle)?
|
||||
.with(ScrollScrollables, "scroll", &[])
|
||||
.with(BirbGravity{ fired: false }, "gravity", &["input_system"])
|
||||
.with_bundle(
|
||||
RenderingBundle::<DefaultBackend>::new()
|
||||
.with_plugin(
|
||||
@@ -30,6 +53,7 @@ fn main() -> amethyst::Result<()> {
|
||||
.with_plugin(RenderFlat2D::default()),
|
||||
)?;
|
||||
|
||||
// Creates the app with the startup state and bound game data
|
||||
let mut game = Application::new(resources, state::MyState, game_data)?;
|
||||
game.run();
|
||||
|
||||
|
||||
116
src/state.rs
116
src/state.rs
@@ -1,17 +1,22 @@
|
||||
use amethyst::{
|
||||
assets::{AssetStorage, Loader},
|
||||
core::transform::Transform,
|
||||
core::math::Vector3,
|
||||
input::{get_key, is_close_requested, is_key_down, VirtualKeyCode},
|
||||
prelude::*,
|
||||
renderer::{Camera, ImageFormat, SpriteRender, SpriteSheet, SpriteSheetFormat, Texture},
|
||||
window::ScreenDimensions,
|
||||
ecs::prelude::{Component, DenseVecStorage, Entity},
|
||||
};
|
||||
|
||||
use log::info;
|
||||
use crate::components::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct MyState;
|
||||
|
||||
impl SimpleState for MyState {
|
||||
|
||||
// On start will run when this state is initialized. For more
|
||||
// state lifecycle hooks, see:
|
||||
// https://book.amethyst.rs/stable/concepts/state.html#life-cycle
|
||||
@@ -23,7 +28,9 @@ impl SimpleState for MyState {
|
||||
// pass the world mutably to the following functions.
|
||||
let dimensions = (*world.read_resource::<ScreenDimensions>()).clone();
|
||||
|
||||
|
||||
// Place the camera
|
||||
/// function sets size of camera window
|
||||
init_camera(world, &dimensions);
|
||||
|
||||
// Load our sprites and display them
|
||||
@@ -36,6 +43,7 @@ impl SimpleState for MyState {
|
||||
mut _data: StateData<'_, GameData<'_, '_>>,
|
||||
event: StateEvent,
|
||||
) -> SimpleTrans {
|
||||
|
||||
if let StateEvent::Window(event) = &event {
|
||||
// Check if the window should be closed
|
||||
if is_close_requested(&event) || is_key_down(&event, VirtualKeyCode::Escape) {
|
||||
@@ -44,7 +52,7 @@ impl SimpleState for MyState {
|
||||
|
||||
// Listen to any key events
|
||||
if let Some(event) = get_key(&event) {
|
||||
info!("handling key event: {:?}", event);
|
||||
// info!("handling key event: {:?}", event);
|
||||
}
|
||||
|
||||
// If you're looking for a more sophisticated event handling solution,
|
||||
@@ -55,6 +63,10 @@ impl SimpleState for MyState {
|
||||
// Keep going
|
||||
Trans::None
|
||||
}
|
||||
|
||||
fn update(&mut self, data: &mut StateData<'_, GameData<'_, '_>>) -> SimpleTrans {
|
||||
Trans::None
|
||||
}
|
||||
}
|
||||
|
||||
fn init_camera(world: &mut World, dimensions: &ScreenDimensions) {
|
||||
@@ -70,7 +82,7 @@ fn init_camera(world: &mut World, dimensions: &ScreenDimensions) {
|
||||
.build();
|
||||
}
|
||||
|
||||
fn load_sprites(world: &mut World) -> Vec<SpriteRender> {
|
||||
fn load_sprites(world: &mut World) -> HashMap<String, SpriteRender> {
|
||||
// Load the texture for our sprites. We'll later need to
|
||||
// add a handle to this texture to our `SpriteRender`s, so
|
||||
// we need to keep a reference to it.
|
||||
@@ -78,7 +90,7 @@ fn load_sprites(world: &mut World) -> Vec<SpriteRender> {
|
||||
let loader = world.read_resource::<Loader>();
|
||||
let texture_storage = world.read_resource::<AssetStorage<Texture>>();
|
||||
loader.load(
|
||||
"sprites/logo.png",
|
||||
"sprites/flappy.png",
|
||||
ImageFormat::default(),
|
||||
(),
|
||||
&texture_storage,
|
||||
@@ -91,40 +103,96 @@ fn load_sprites(world: &mut World) -> Vec<SpriteRender> {
|
||||
let loader = world.read_resource::<Loader>();
|
||||
let sheet_storage = world.read_resource::<AssetStorage<SpriteSheet>>();
|
||||
loader.load(
|
||||
"sprites/logo.ron",
|
||||
"sprites/flappy.ron",
|
||||
SpriteSheetFormat(texture_handle),
|
||||
(),
|
||||
&sheet_storage,
|
||||
)
|
||||
};
|
||||
|
||||
// Create our sprite renders. Each will have a handle to the texture
|
||||
// that it renders from. The handle is safe to clone, since it just
|
||||
// references the asset.
|
||||
(0..3)
|
||||
.map(|i| SpriteRender {
|
||||
let sprite_map = vec![
|
||||
(0, "day-background".to_string()),
|
||||
(1, "night-background".to_string()),
|
||||
(2, "down-pipe".to_string()),
|
||||
(3, "up-pipe".to_string()),
|
||||
(4, "ground".to_string()),
|
||||
(5, "floppy".to_string()),
|
||||
];
|
||||
|
||||
sprite_map.iter()
|
||||
.map(|i| (i.1.clone(), SpriteRender {
|
||||
sprite_sheet: sheet_handle.clone(),
|
||||
sprite_number: i,
|
||||
})
|
||||
sprite_number: i.0,
|
||||
}))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn init_sprites(world: &mut World, sprites: &[SpriteRender], dimensions: &ScreenDimensions) {
|
||||
for (i, sprite) in sprites.iter().enumerate() {
|
||||
// Center our sprites around the center of the window
|
||||
let x = (i as f32 - 1.) * 100. + dimensions.width() * 0.5;
|
||||
let y = (i as f32 - 1.) * 100. + dimensions.height() * 0.5;
|
||||
let mut transform = Transform::default();
|
||||
transform.set_translation_xyz(x, y, 0.);
|
||||
fn init_sprites(world: &mut World, sprites: &HashMap<String, SpriteRender>, dimensions: &ScreenDimensions) {
|
||||
|
||||
let background_sprite = sprites.get("day-background").unwrap();
|
||||
|
||||
|
||||
let background_object = TiledScroller {
|
||||
speed: -75.0,
|
||||
position: 1.0,
|
||||
width: 144.0 * 3.0,
|
||||
height: 256.0 * 3.0,
|
||||
};
|
||||
|
||||
let mut transform = Transform::default();
|
||||
transform.set_scale(Vector3::new(3.0, 3.0, 3.0));
|
||||
transform.set_translation_xyz(background_object.width/2.0, background_object.height/2.0, 0.0);
|
||||
|
||||
|
||||
// Create an entity for each sprite and attach the `SpriteRender` as
|
||||
// well as the transform. If you want to add behaviour to your sprites,
|
||||
// you'll want to add a custom `Component` that will identify them, and a
|
||||
// `System` that will iterate over them. See https://book.amethyst.rs/stable/concepts/system.html
|
||||
world
|
||||
.create_entity()
|
||||
.with(sprite.clone())
|
||||
.with(background_sprite.clone()) // Sprite Render
|
||||
.with(background_object.clone())
|
||||
.with(transform.clone())
|
||||
.build();
|
||||
|
||||
transform.set_translation_xyz(3.0*144.0/2.0*3.0, 3.0*256.0/2.0, 0.0);
|
||||
|
||||
world
|
||||
.create_entity()
|
||||
.with(background_sprite.clone()) // Sprite Render
|
||||
.with(TiledScroller {
|
||||
speed: -75.0,
|
||||
position: 2.0,
|
||||
width: 0.0,
|
||||
height: 0.0
|
||||
})
|
||||
.with(transform.clone())
|
||||
.build();
|
||||
|
||||
let ground_sprite = sprites.get("ground").unwrap();
|
||||
transform.set_translation_xyz(3.0*168.0/2.0*3.0, 3.0*56.0/2.0, 0.1);
|
||||
|
||||
world
|
||||
.create_entity()
|
||||
.with(ground_sprite.clone()) // Sprite Render
|
||||
.with(TiledScroller {
|
||||
speed: -100.0,
|
||||
position: 2.0,
|
||||
width: 0.0,
|
||||
height: 0.0,
|
||||
})
|
||||
.with(transform.clone())
|
||||
.build();
|
||||
|
||||
let birb_sprite = sprites.get("floppy").unwrap();
|
||||
transform.set_translation_xyz(dimensions.width()/2.0, dimensions.height()/2.0, 0.2);
|
||||
|
||||
|
||||
world
|
||||
.create_entity()
|
||||
.with(birb_sprite.clone()) // Sprite Render
|
||||
.with(Birb {
|
||||
vertical_speed: 0.0,
|
||||
position: 0.0,
|
||||
starting_height: 0.0
|
||||
})
|
||||
.with(transform)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
62
src/systems.rs
Normal file
62
src/systems.rs
Normal file
@@ -0,0 +1,62 @@
|
||||
use amethyst::{
|
||||
core::SystemDesc,
|
||||
core::timing::Time,
|
||||
core::transform::{Transform, TransformBundle},
|
||||
derive::SystemDesc,
|
||||
ecs::prelude::{},
|
||||
ecs::prelude::{
|
||||
Component, DenseVecStorage, Entity, Join, Read,
|
||||
ReadStorage, System, SystemData, WriteStorage
|
||||
},
|
||||
input::{InputHandler, StringBindings},
|
||||
};
|
||||
|
||||
use log::info;
|
||||
use crate::components::*;
|
||||
|
||||
pub struct ScrollScrollables;
|
||||
|
||||
// This system iterates all the objects with transform (and falling object) component
|
||||
impl<'a> System<'a> for ScrollScrollables {
|
||||
type SystemData = (
|
||||
WriteStorage<'a, Transform>,
|
||||
WriteStorage<'a, TiledScroller>,
|
||||
Read<'a, Time>,
|
||||
);
|
||||
|
||||
fn run(&mut self, (mut transforms, mut scrolling, time): Self::SystemData) {
|
||||
for (mut transform, mut object) in (&mut transforms, &mut scrolling).join() {
|
||||
|
||||
// I need to tile it by it's width
|
||||
transform.prepend_translation_x(object.speed * time.delta_seconds());
|
||||
if transform.translation().x+144.0*1.5 < 0.0 {
|
||||
transform.set_translation_x(144.0*3.0/2.0*3.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BirbGravity {
|
||||
pub fired: bool,
|
||||
}
|
||||
|
||||
// This system iterates all the objects with transform (and falling object) component
|
||||
impl<'a> System<'a> for BirbGravity {
|
||||
type SystemData = (
|
||||
WriteStorage<'a, Transform>,
|
||||
WriteStorage<'a, Birb>,
|
||||
Read<'a, Time>,
|
||||
Read<'a, InputHandler<StringBindings>>,
|
||||
);
|
||||
|
||||
fn run(&mut self, (mut transforms, mut scrolling, time, input): Self::SystemData) {
|
||||
for (mut transform, mut object) in (&mut transforms, &mut scrolling).join() {
|
||||
|
||||
if input.action_is_down("flap").expect("No action") {
|
||||
object.vertical_speed = 500.0;
|
||||
}
|
||||
object.vertical_speed -= 1000.0 * time.delta_seconds();
|
||||
transform.prepend_translation_y(object.vertical_speed * time.delta_seconds());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user