master
mitchellhansen 5 years ago
parent 01f6f3e4ba
commit 0113f04457

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" edition = "2018"
[dependencies] [dependencies]
amethyst = "0.13.0" amethyst = "0.13.2"
log = { version = "0.4.8", features = ["serde"] } log = { version = "0.4.8", features = ["serde"] }
[features] [features]

@ -0,0 +1,6 @@
(
axes: {},
actions: {
"flap": [[Key(Space)]],
},
)

@ -1,4 +1,4 @@
( (
title: "amethyst-cli-starter-2d", title: "test",
dimensions: Some((800, 600)), dimensions: Some((432, 768)),
) )

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

@ -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,
)
]
)

@ -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>;
}

@ -1,5 +1,10 @@
mod components;
mod systems;
mod state;
use amethyst::{ use amethyst::{
input::{InputBundle, StringBindings},
core::transform::TransformBundle, core::transform::TransformBundle,
core::transform::Transform,
prelude::*, prelude::*,
renderer::{ renderer::{
plugins::{RenderFlat2D, RenderToWindow}, plugins::{RenderFlat2D, RenderToWindow},
@ -7,20 +12,38 @@ use amethyst::{
RenderingBundle, RenderingBundle,
}, },
utils::application_root_dir, 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<()> { 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 resources = app_root.join("resources");
let display_config = resources.join("display_config.ron"); 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() let game_data = GameDataBuilder::default()
.with_bundle(TransformBundle::new())? .with_bundle(TransformBundle::new())?
.with_bundle(input_bundle)?
.with(ScrollScrollables, "scroll", &[])
.with(BirbGravity{ fired: false }, "gravity", &["input_system"])
.with_bundle( .with_bundle(
RenderingBundle::<DefaultBackend>::new() RenderingBundle::<DefaultBackend>::new()
.with_plugin( .with_plugin(
@ -30,6 +53,7 @@ fn main() -> amethyst::Result<()> {
.with_plugin(RenderFlat2D::default()), .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)?; let mut game = Application::new(resources, state::MyState, game_data)?;
game.run(); game.run();

@ -1,17 +1,22 @@
use amethyst::{ use amethyst::{
assets::{AssetStorage, Loader}, assets::{AssetStorage, Loader},
core::transform::Transform, core::transform::Transform,
core::math::Vector3,
input::{get_key, is_close_requested, is_key_down, VirtualKeyCode}, input::{get_key, is_close_requested, is_key_down, VirtualKeyCode},
prelude::*, prelude::*,
renderer::{Camera, ImageFormat, SpriteRender, SpriteSheet, SpriteSheetFormat, Texture}, renderer::{Camera, ImageFormat, SpriteRender, SpriteSheet, SpriteSheetFormat, Texture},
window::ScreenDimensions, window::ScreenDimensions,
ecs::prelude::{Component, DenseVecStorage, Entity},
}; };
use log::info; use log::info;
use crate::components::*;
use std::collections::HashMap;
pub struct MyState; pub struct MyState;
impl SimpleState for MyState { impl SimpleState for MyState {
// On start will run when this state is initialized. For more // On start will run when this state is initialized. For more
// state lifecycle hooks, see: // state lifecycle hooks, see:
// https://book.amethyst.rs/stable/concepts/state.html#life-cycle // 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. // pass the world mutably to the following functions.
let dimensions = (*world.read_resource::<ScreenDimensions>()).clone(); let dimensions = (*world.read_resource::<ScreenDimensions>()).clone();
// Place the camera // Place the camera
/// function sets size of camera window
init_camera(world, &dimensions); init_camera(world, &dimensions);
// Load our sprites and display them // Load our sprites and display them
@ -36,6 +43,7 @@ impl SimpleState for MyState {
mut _data: StateData<'_, GameData<'_, '_>>, mut _data: StateData<'_, GameData<'_, '_>>,
event: StateEvent, event: StateEvent,
) -> SimpleTrans { ) -> SimpleTrans {
if let StateEvent::Window(event) = &event { if let StateEvent::Window(event) = &event {
// Check if the window should be closed // Check if the window should be closed
if is_close_requested(&event) || is_key_down(&event, VirtualKeyCode::Escape) { if is_close_requested(&event) || is_key_down(&event, VirtualKeyCode::Escape) {
@ -44,7 +52,7 @@ impl SimpleState for MyState {
// Listen to any key events // Listen to any key events
if let Some(event) = get_key(&event) { 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, // If you're looking for a more sophisticated event handling solution,
@ -55,6 +63,10 @@ impl SimpleState for MyState {
// Keep going // Keep going
Trans::None Trans::None
} }
fn update(&mut self, data: &mut StateData<'_, GameData<'_, '_>>) -> SimpleTrans {
Trans::None
}
} }
fn init_camera(world: &mut World, dimensions: &ScreenDimensions) { fn init_camera(world: &mut World, dimensions: &ScreenDimensions) {
@ -70,7 +82,7 @@ fn init_camera(world: &mut World, dimensions: &ScreenDimensions) {
.build(); .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 // Load the texture for our sprites. We'll later need to
// add a handle to this texture to our `SpriteRender`s, so // add a handle to this texture to our `SpriteRender`s, so
// we need to keep a reference to it. // 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 loader = world.read_resource::<Loader>();
let texture_storage = world.read_resource::<AssetStorage<Texture>>(); let texture_storage = world.read_resource::<AssetStorage<Texture>>();
loader.load( loader.load(
"sprites/logo.png", "sprites/flappy.png",
ImageFormat::default(), ImageFormat::default(),
(), (),
&texture_storage, &texture_storage,
@ -91,40 +103,96 @@ fn load_sprites(world: &mut World) -> Vec<SpriteRender> {
let loader = world.read_resource::<Loader>(); let loader = world.read_resource::<Loader>();
let sheet_storage = world.read_resource::<AssetStorage<SpriteSheet>>(); let sheet_storage = world.read_resource::<AssetStorage<SpriteSheet>>();
loader.load( loader.load(
"sprites/logo.ron", "sprites/flappy.ron",
SpriteSheetFormat(texture_handle), SpriteSheetFormat(texture_handle),
(), (),
&sheet_storage, &sheet_storage,
) )
}; };
// Create our sprite renders. Each will have a handle to the texture let sprite_map = vec![
// that it renders from. The handle is safe to clone, since it just (0, "day-background".to_string()),
// references the asset. (1, "night-background".to_string()),
(0..3) (2, "down-pipe".to_string()),
.map(|i| SpriteRender { (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_sheet: sheet_handle.clone(),
sprite_number: i, sprite_number: i.0,
}) }))
.collect() .collect()
} }
fn init_sprites(world: &mut World, sprites: &[SpriteRender], dimensions: &ScreenDimensions) { fn init_sprites(world: &mut World, sprites: &HashMap<String, SpriteRender>, dimensions: &ScreenDimensions) {
for (i, sprite) in sprites.iter().enumerate() {
// Center our sprites around the center of the window let background_sprite = sprites.get("day-background").unwrap();
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(); let background_object = TiledScroller {
transform.set_translation_xyz(x, y, 0.); speed: -75.0,
position: 1.0,
// Create an entity for each sprite and attach the `SpriteRender` as width: 144.0 * 3.0,
// well as the transform. If you want to add behaviour to your sprites, height: 256.0 * 3.0,
// 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 let mut transform = Transform::default();
.create_entity() transform.set_scale(Vector3::new(3.0, 3.0, 3.0));
.with(sprite.clone()) transform.set_translation_xyz(background_object.width/2.0, background_object.height/2.0, 0.0);
.with(transform)
.build();
} world
.create_entity()
.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();
} }

@ -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());
}
}
}
Loading…
Cancel
Save