Final product. Very incomplete but you can platform.
This commit is contained in:
parent
7f2694ab24
commit
1b14306b27
12 changed files with 332 additions and 45 deletions
|
@ -4,6 +4,9 @@ version = "0.1.0"
|
||||||
authors = ["Gnarwhal <git.aspect893@passmail.net>"]
|
authors = ["Gnarwhal <git.aspect893@passmail.net>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
image = "0.23.7"
|
||||||
|
|
||||||
[dependencies.serde]
|
[dependencies.serde]
|
||||||
version = "1"
|
version = "1"
|
||||||
features = ["derive"]
|
features = ["derive"]
|
||||||
|
|
BIN
resources/levels/level0.png
Normal file
BIN
resources/levels/level0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 284 B |
Binary file not shown.
Before Width: | Height: | Size: 206 B After Width: | Height: | Size: 306 B |
|
@ -1,12 +1,36 @@
|
||||||
List((
|
List((
|
||||||
texture_width: 16,
|
texture_width: 54,
|
||||||
texture_height: 16,
|
texture_height: 36,
|
||||||
sprites: [
|
sprites: [
|
||||||
(
|
(
|
||||||
x: 0,
|
x: 1,
|
||||||
y: 0,
|
y: 1,
|
||||||
width: 16,
|
width: 16,
|
||||||
height: 16,
|
height: 16,
|
||||||
)
|
),
|
||||||
|
(
|
||||||
|
x: 19,
|
||||||
|
y: 1,
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
x: 19,
|
||||||
|
y: 19,
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
x: 37,
|
||||||
|
y: 1,
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
x: 37,
|
||||||
|
y: 19,
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
))
|
))
|
|
@ -27,10 +27,12 @@
|
||||||
pub use self::{
|
pub use self::{
|
||||||
physics::Gravity,
|
physics::Gravity,
|
||||||
physics::Dynamic,
|
physics::Dynamic,
|
||||||
physics::Static,
|
|
||||||
|
|
||||||
player::Player,
|
player::Player,
|
||||||
|
|
||||||
|
tile::Tile,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod physics;
|
pub mod physics;
|
||||||
pub mod player;
|
pub mod player;
|
||||||
|
pub mod tile;
|
||||||
|
|
|
@ -24,15 +24,22 @@
|
||||||
*
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
use core::default::Default;
|
||||||
use amethyst::{
|
use amethyst::{
|
||||||
core::math::Vector2,
|
core::math::Vector2,
|
||||||
ecs::prelude::{Component, DenseVecStorage}
|
ecs::prelude::{Component, DenseVecStorage, NullStorage}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Gravity;
|
pub struct Gravity;
|
||||||
|
|
||||||
impl Component for Gravity {
|
impl Component for Gravity {
|
||||||
type Storage = DenseVecStorage<Self>;
|
type Storage = NullStorage<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Gravity {
|
||||||
|
fn default() -> Self {
|
||||||
|
Gravity
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Dynamic {
|
pub struct Dynamic {
|
||||||
|
@ -54,9 +61,3 @@ impl Default for Dynamic {
|
||||||
impl Component for Dynamic {
|
impl Component for Dynamic {
|
||||||
type Storage = DenseVecStorage<Self>;
|
type Storage = DenseVecStorage<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Static;
|
|
||||||
|
|
||||||
impl Component for Static {
|
|
||||||
type Storage = DenseVecStorage<Self>;
|
|
||||||
}
|
|
||||||
|
|
47
src/components/tile.rs
Normal file
47
src/components/tile.rs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Gnarwhal
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files(the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
use core::default::Default;
|
||||||
|
use amethyst::{
|
||||||
|
ecs::prelude::{Component, DenseVecStorage},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub enum Tile {
|
||||||
|
Background,
|
||||||
|
Ground,
|
||||||
|
Start,
|
||||||
|
End,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Tile {
|
||||||
|
fn default() -> Self {
|
||||||
|
Tile::Background
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for Tile {
|
||||||
|
type Storage = DenseVecStorage<Self>;
|
||||||
|
}
|
|
@ -53,7 +53,6 @@ fn main() -> amethyst::Result<()> {
|
||||||
let binding_path = resources_dir.join("bindings.ron");
|
let binding_path = resources_dir.join("bindings.ron");
|
||||||
|
|
||||||
let events_loop = EventsLoop::new();
|
let events_loop = EventsLoop::new();
|
||||||
|
|
||||||
let monitor = MonitorIdent::from_primary(&events_loop);
|
let monitor = MonitorIdent::from_primary(&events_loop);
|
||||||
|
|
||||||
let mut display_config = DisplayConfig::load(display_config_path)?;
|
let mut display_config = DisplayConfig::load(display_config_path)?;
|
||||||
|
@ -76,8 +75,9 @@ fn main() -> amethyst::Result<()> {
|
||||||
.with_plugin(RenderFlat2D::default())
|
.with_plugin(RenderFlat2D::default())
|
||||||
)?
|
)?
|
||||||
.with(systems::ForceSystem, "force_system", &[])
|
.with(systems::ForceSystem, "force_system", &[])
|
||||||
.with(systems::PlayerSystem, "player_system", &["force_system", "input_system"])
|
.with(systems::PlayerMovementSystem, "player_movement_system", &["force_system", "input_system"])
|
||||||
.with(systems::CollisionSystem, "physics_system", &["player_system"]);
|
.with(systems::CollisionSystem, "collision_system", &["player_movement_system"])
|
||||||
|
.with(systems::CameraFollowSystem, "player_post_collision_system", &["collision_system"]);
|
||||||
|
|
||||||
let mut game = Application::new(resources_dir, states::LevelState, game_data)?;
|
let mut game = Application::new(resources_dir, states::LevelState, game_data)?;
|
||||||
game.run();
|
game.run();
|
||||||
|
|
|
@ -24,21 +24,127 @@
|
||||||
*
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
use image::Rgba;
|
||||||
use amethyst::{
|
use amethyst::{
|
||||||
assets::{AssetStorage, Loader, Handle},
|
assets::{AssetStorage, Loader, Handle},
|
||||||
core::transform::Transform,
|
core::transform::Transform,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
|
ecs::Entity,
|
||||||
renderer::{Camera, ImageFormat, SpriteRender, SpriteSheet, SpriteSheetFormat, Texture}
|
renderer::{Camera, ImageFormat, SpriteRender, SpriteSheet, SpriteSheetFormat, Texture}
|
||||||
};
|
};
|
||||||
use crate::components::Dynamic;
|
use crate::components::Dynamic;
|
||||||
use crate::components::Gravity;
|
use crate::components::Gravity;
|
||||||
use crate::components::Player;
|
use crate::components::Player;
|
||||||
|
use crate::components::Tile;
|
||||||
|
|
||||||
pub const CAMERA_WIDTH: f32 = 384.0;
|
pub const CAMERA_WIDTH: f32 = 384.0;
|
||||||
pub const CAMERA_HEIGHT: f32 = 216.0;
|
pub const CAMERA_HEIGHT: f32 = 216.0;
|
||||||
|
|
||||||
pub const BLOCK_SIZE: f32 = 16.0;
|
pub const BLOCK_SIZE: f32 = 16.0;
|
||||||
|
|
||||||
|
const BACKGROUND: Rgba<u8> = Rgba::<u8>([255, 255, 255, 255]);
|
||||||
|
const GROUND: Rgba<u8> = Rgba::<u8>([0, 0, 0, 255]);
|
||||||
|
const START: Rgba<u8> = Rgba::<u8>([0, 148, 255, 255]);
|
||||||
|
const END: Rgba<u8> = Rgba::<u8>([0, 216, 68, 255]);
|
||||||
|
|
||||||
|
pub struct Level {
|
||||||
|
pub entities: Vec<Entity>,
|
||||||
|
pub width: usize,
|
||||||
|
pub height: usize,
|
||||||
|
pub left: f32,
|
||||||
|
pub bottom: f32,
|
||||||
|
pub right: f32,
|
||||||
|
pub top: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Level {
|
||||||
|
fn default() -> Self {
|
||||||
|
Level{
|
||||||
|
entities: vec![],
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
left: 0.0,
|
||||||
|
bottom: 0.0,
|
||||||
|
right: 0.0,
|
||||||
|
top: 0.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn initialize_level(world: &mut World, sprite_sheet_handle: Handle<SpriteSheet>) {
|
||||||
|
let background_sprite = SpriteRender {
|
||||||
|
sprite_sheet: sprite_sheet_handle.clone(),
|
||||||
|
sprite_number: 1,
|
||||||
|
};
|
||||||
|
let ground_sprite = SpriteRender {
|
||||||
|
sprite_sheet: sprite_sheet_handle.clone(),
|
||||||
|
sprite_number: 2,
|
||||||
|
};
|
||||||
|
let start_sprite = SpriteRender {
|
||||||
|
sprite_sheet: sprite_sheet_handle.clone(),
|
||||||
|
sprite_number: 4,
|
||||||
|
};
|
||||||
|
let end_sprite = SpriteRender {
|
||||||
|
sprite_sheet: sprite_sheet_handle,
|
||||||
|
sprite_number: 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
let level_image = image::open("resources/levels/level0.png").unwrap().into_rgba();
|
||||||
|
let width = level_image.width() as usize;
|
||||||
|
let height = level_image.height() as usize;
|
||||||
|
let center_x = BLOCK_SIZE * width as f32 / 2.0;
|
||||||
|
let center_y = BLOCK_SIZE * height as f32 / 2.0;
|
||||||
|
let mut tile_map = Vec::<Entity>::with_capacity(level_image.width() as usize * level_image.height() as usize);
|
||||||
|
for (i, pixel) in level_image.pixels().enumerate() {
|
||||||
|
let mut transform = Transform::default();
|
||||||
|
transform.set_translation_xyz(BLOCK_SIZE * ((i % width) as f32 + 0.5) - center_x, BLOCK_SIZE * -((i / width) as f32 + 0.5) + center_y, -1.0);
|
||||||
|
match *pixel {
|
||||||
|
BACKGROUND => {
|
||||||
|
tile_map.push(world
|
||||||
|
.create_entity()
|
||||||
|
.with(Tile::Background)
|
||||||
|
.with(transform)
|
||||||
|
.build());
|
||||||
|
},
|
||||||
|
GROUND => {
|
||||||
|
tile_map.push(world
|
||||||
|
.create_entity()
|
||||||
|
.with(ground_sprite.clone())
|
||||||
|
.with(Tile::Ground)
|
||||||
|
.with(transform)
|
||||||
|
.build());
|
||||||
|
},
|
||||||
|
START => {
|
||||||
|
tile_map.push(world
|
||||||
|
.create_entity()
|
||||||
|
.with(start_sprite.clone())
|
||||||
|
.with(Tile::Start)
|
||||||
|
.with(transform)
|
||||||
|
.build());
|
||||||
|
},
|
||||||
|
END => {
|
||||||
|
tile_map.push(world
|
||||||
|
.create_entity()
|
||||||
|
.with(end_sprite.clone())
|
||||||
|
.with(Tile::End)
|
||||||
|
.with(transform)
|
||||||
|
.build());
|
||||||
|
},
|
||||||
|
_ => { panic!("Invalid level bitmap tile color!"); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let level = Level {
|
||||||
|
entities: tile_map,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
left: -(BLOCK_SIZE * width as f32 / 2.0),
|
||||||
|
bottom: -(BLOCK_SIZE * height as f32 / 2.0),
|
||||||
|
right: (BLOCK_SIZE * width as f32 / 2.0),
|
||||||
|
top: (BLOCK_SIZE * height as f32 / 2.0),
|
||||||
|
};
|
||||||
|
world.insert(level);
|
||||||
|
}
|
||||||
|
|
||||||
fn initialize_camera(world: &mut World) {
|
fn initialize_camera(world: &mut World) {
|
||||||
let mut transform = Transform::default();
|
let mut transform = Transform::default();
|
||||||
transform.set_translation_xyz(0.0, 0.0, 1.0);
|
transform.set_translation_xyz(0.0, 0.0, 1.0);
|
||||||
|
@ -57,13 +163,12 @@ fn initialize_player(world: &mut World, sprite_sheet_handle: Handle<SpriteSheet>
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut transform = Transform::default();
|
let mut transform = Transform::default();
|
||||||
transform.set_translation_xyz(0.0, 48.0, 0.0);
|
transform.set_translation_xyz(BLOCK_SIZE * -11.0, BLOCK_SIZE * -12.5, 0.0);
|
||||||
|
|
||||||
world
|
world
|
||||||
.create_entity()
|
.create_entity()
|
||||||
.with(sprite_render)
|
.with(sprite_render)
|
||||||
.with(Player::default())
|
.with(Player::default())
|
||||||
.with(Transform::default())
|
|
||||||
.with(Dynamic::default())
|
.with(Dynamic::default())
|
||||||
.with(Gravity)
|
.with(Gravity)
|
||||||
.with(transform)
|
.with(transform)
|
||||||
|
@ -101,6 +206,9 @@ impl SimpleState for LevelState {
|
||||||
let sprite_sheet_handle = load_sprite_sheet(world);
|
let sprite_sheet_handle = load_sprite_sheet(world);
|
||||||
|
|
||||||
initialize_camera(world);
|
initialize_camera(world);
|
||||||
initialize_player(world, sprite_sheet_handle);
|
initialize_player(world, sprite_sheet_handle.clone());
|
||||||
|
|
||||||
|
world.register::<Tile>();
|
||||||
|
initialize_level(world, sprite_sheet_handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -28,8 +28,9 @@ pub use self::{
|
||||||
physics::ForceSystem,
|
physics::ForceSystem,
|
||||||
physics::CollisionSystem,
|
physics::CollisionSystem,
|
||||||
|
|
||||||
player::PlayerSystem,
|
|
||||||
player::PlayerBindings,
|
player::PlayerBindings,
|
||||||
|
player::PlayerMovementSystem,
|
||||||
|
player::CameraFollowSystem,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod physics;
|
pub mod physics;
|
||||||
|
|
|
@ -25,22 +25,26 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
use amethyst::{
|
use amethyst::{
|
||||||
core::timing::Time,
|
core::{
|
||||||
|
timing::Time,
|
||||||
|
math::Vector3,
|
||||||
|
},
|
||||||
core::{Transform},
|
core::{Transform},
|
||||||
derive::SystemDesc,
|
derive::SystemDesc,
|
||||||
ecs::{Join, Read, ReadStorage, System, SystemData, WriteStorage},
|
ecs::{Join, Read, ReadStorage, System, SystemData, WriteStorage},
|
||||||
};
|
};
|
||||||
use crate::components::Dynamic;
|
use crate::components::Dynamic;
|
||||||
use crate::components::Static;
|
|
||||||
use crate::components::Gravity;
|
use crate::components::Gravity;
|
||||||
|
use crate::components::Tile;
|
||||||
use crate::systems::player::FULL_HOP_TIME;
|
use crate::systems::player::FULL_HOP_TIME;
|
||||||
use crate::systems::player::FULL_HOP_HEIGHT;
|
use crate::systems::player::FULL_HOP_HEIGHT;
|
||||||
use crate::systems::player::MAX_GROUND_SPEED;
|
use crate::systems::player::MAX_GROUND_SPEED;
|
||||||
use crate::systems::player::MAX_AERIAL_SPEED;
|
use crate::systems::player::MAX_AERIAL_SPEED;
|
||||||
use crate::states::level::CAMERA_HEIGHT;
|
use crate::states::level::Level;
|
||||||
|
use crate::states::level::BLOCK_SIZE;
|
||||||
|
|
||||||
pub const FRICTION: f32 = MAX_GROUND_SPEED / 0.25;
|
pub const FRICTION: f32 = MAX_GROUND_SPEED / 0.1;
|
||||||
pub const AIR_RESISTANCE: f32 = MAX_AERIAL_SPEED / 1.0;
|
pub const AIR_RESISTANCE: f32 = MAX_AERIAL_SPEED / 0.5;
|
||||||
|
|
||||||
pub const GRAVITY: f32 = -2.0 * FULL_HOP_HEIGHT / (FULL_HOP_TIME * FULL_HOP_TIME);
|
pub const GRAVITY: f32 = -2.0 * FULL_HOP_HEIGHT / (FULL_HOP_TIME * FULL_HOP_TIME);
|
||||||
|
|
||||||
|
@ -78,26 +82,82 @@ impl<'s> System<'s> for ForceSystem {
|
||||||
#[derive(SystemDesc)]
|
#[derive(SystemDesc)]
|
||||||
pub struct CollisionSystem;
|
pub struct CollisionSystem;
|
||||||
|
|
||||||
|
fn attempt_collision(object: &mut Vector3<f32>, level: &Read<Level>, tiles: &ReadStorage<Tile>) -> u32 {
|
||||||
|
let left = (((object.x - level.left ) / BLOCK_SIZE - 0.5).floor() as usize).min(level.width - 1).max(0);
|
||||||
|
let bottom = (((object.y - level.bottom) / BLOCK_SIZE - 0.5).floor() as usize).min(level.height - 1).max(0);
|
||||||
|
let right = (((object.x - level.left ) / BLOCK_SIZE - 0.5).ceil() as usize).min(level.width - 1).max(0);
|
||||||
|
let top = (((object.y - level.bottom) / BLOCK_SIZE - 0.5).ceil() as usize).min(level.height - 1).max(0);
|
||||||
|
let mut closest = Option::<(usize, usize)>::None;
|
||||||
|
let mut distance = (BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE * BLOCK_SIZE);
|
||||||
|
for i in left..=right {
|
||||||
|
for j in bottom..=top {
|
||||||
|
match (&mut closest, tiles.get(level.entities[(level.height - j - 1) * level.width + i]).unwrap()) {
|
||||||
|
(None, Tile::Ground) | (None, Tile::Start) | (None, Tile::End) => {
|
||||||
|
closest = Some((i, j));
|
||||||
|
let dist_x = (object.x - level.left ) - (i as f32 + 0.5) * BLOCK_SIZE;
|
||||||
|
let dist_y = (object.y - level.bottom) - (j as f32 + 0.5) * BLOCK_SIZE;
|
||||||
|
distance = (dist_x, dist_y, (dist_x * dist_x + dist_y * dist_y).sqrt());
|
||||||
|
},
|
||||||
|
(Some(_), Tile::Ground) | (Some(_), Tile::Start) | (Some(_), Tile::End) => {
|
||||||
|
let dist_x = (object.x - level.left ) - (i as f32 + 0.5) * BLOCK_SIZE;
|
||||||
|
let dist_y = (object.y - level.bottom) - (j as f32 + 0.5) * BLOCK_SIZE;
|
||||||
|
let current_distance = (dist_x * dist_x + dist_y * dist_y).sqrt();
|
||||||
|
if current_distance < distance.2 {
|
||||||
|
closest = Some((i, j));
|
||||||
|
distance = (dist_x, dist_y, current_distance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(_, Tile::Background) => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some((x, y)) = closest {
|
||||||
|
if distance.0.abs() > distance.1.abs() {
|
||||||
|
object.x += (BLOCK_SIZE - distance.0.abs()) * distance.0.signum();
|
||||||
|
(2 - distance.0.signum() as i32) as u32
|
||||||
|
} else {
|
||||||
|
object.y += (BLOCK_SIZE - distance.1.abs()) * distance.1.signum();
|
||||||
|
(3 - distance.1.signum() as i32) as u32
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'s> System<'s> for CollisionSystem {
|
impl<'s> System<'s> for CollisionSystem {
|
||||||
type SystemData = (
|
type SystemData = (
|
||||||
WriteStorage<'s, Transform>,
|
WriteStorage<'s, Transform>,
|
||||||
WriteStorage<'s, Dynamic>,
|
WriteStorage<'s, Dynamic>,
|
||||||
ReadStorage<'s, Static>,
|
ReadStorage<'s, Tile>,
|
||||||
|
Read<'s, Level>,
|
||||||
Read<'s, Time>,
|
Read<'s, Time>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(&mut self, (mut transforms, mut dynamics, statics, delta_time): Self::SystemData) {
|
fn run(&mut self, (mut transforms, mut dynamics, tiles, level, delta_time): Self::SystemData) {
|
||||||
for (transform, dynamic) in (&mut transforms, &mut dynamics).join() {
|
for (transform, dynamic) in (&mut transforms, &mut dynamics).join() {
|
||||||
let translation = transform.translation_mut();
|
let translation = transform.translation_mut();
|
||||||
translation.x += dynamic.velocity.x * delta_time.delta_seconds();
|
translation.x += dynamic.velocity.x * delta_time.delta_seconds();
|
||||||
translation.y += dynamic.velocity.y * delta_time.delta_seconds();
|
translation.y += dynamic.velocity.y * delta_time.delta_seconds();
|
||||||
const FLOOR: f32 = -CAMERA_HEIGHT / 2.0 + 8.0;
|
dynamic.grounded = false;
|
||||||
if translation.y < FLOOR {
|
let mut result = 1;
|
||||||
translation.y = FLOOR;
|
while result != 0 {
|
||||||
dynamic.velocity.y = 0.0;
|
result = attempt_collision(translation, &level, &tiles);
|
||||||
dynamic.grounded = true;
|
match result {
|
||||||
} else {
|
1 => {
|
||||||
dynamic.grounded = false;
|
dynamic.velocity.x = 0.0;
|
||||||
|
},
|
||||||
|
2 => {
|
||||||
|
dynamic.velocity.y = 0.0;
|
||||||
|
dynamic.grounded = true;
|
||||||
|
},
|
||||||
|
3 => {
|
||||||
|
dynamic.velocity.x = 0.0;
|
||||||
|
},
|
||||||
|
4 => {
|
||||||
|
dynamic.velocity.y = 0.0;
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,15 +27,21 @@
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
|
|
||||||
use amethyst::{
|
use amethyst::{
|
||||||
core::timing::Time,
|
core::{
|
||||||
|
timing::Time,
|
||||||
|
Transform,
|
||||||
|
math::Vector3,
|
||||||
|
},
|
||||||
derive::SystemDesc,
|
derive::SystemDesc,
|
||||||
ecs::{Join, Read, System, SystemData, WriteStorage},
|
ecs::{Join, Read, ReadStorage, System, SystemData, WriteStorage},
|
||||||
input::{InputHandler, BindingTypes},
|
input::{InputHandler, BindingTypes},
|
||||||
|
renderer::{Camera},
|
||||||
};
|
};
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use crate::components::Dynamic;
|
use crate::components::Dynamic;
|
||||||
use crate::components::Player;
|
use crate::components::Player;
|
||||||
use crate::systems::physics::GRAVITY;
|
use crate::systems::physics::GRAVITY;
|
||||||
|
use crate::states::level::{Level, CAMERA_WIDTH, CAMERA_HEIGHT};
|
||||||
use crate::states::level::BLOCK_SIZE;
|
use crate::states::level::BLOCK_SIZE;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
@ -69,23 +75,23 @@ impl BindingTypes for PlayerBindings {
|
||||||
type Action = ActionBindings;
|
type Action = ActionBindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const FULL_HOP_TIME: f32 = 0.35;
|
pub const FULL_HOP_TIME: f32 = 0.3;
|
||||||
pub const SHORT_HOP_HEIGHT: f32 = 1.5 * BLOCK_SIZE;
|
pub const SHORT_HOP_HEIGHT: f32 = 1.25 * BLOCK_SIZE;
|
||||||
pub const FULL_HOP_HEIGHT: f32 = 3.25 * BLOCK_SIZE;
|
pub const FULL_HOP_HEIGHT: f32 = 2.25 * BLOCK_SIZE;
|
||||||
pub const AERIAL_HOP_HEIGHT: f32 = 2.25 * BLOCK_SIZE;
|
pub const AERIAL_HOP_HEIGHT: f32 = 1.25 * BLOCK_SIZE;
|
||||||
const JUMP_COUNT: usize = 2;
|
const JUMP_COUNT: usize = 2;
|
||||||
|
|
||||||
pub const MAX_GROUND_SPEED: f32 = 10.0 * BLOCK_SIZE;
|
pub const MAX_GROUND_SPEED: f32 = 6.0 * BLOCK_SIZE;
|
||||||
const GROUND_ACCELERATION: f32 = (MAX_GROUND_SPEED * 2.0) / 0.1;
|
const GROUND_ACCELERATION: f32 = (MAX_GROUND_SPEED * 2.0) / 0.1;
|
||||||
|
|
||||||
pub const MAX_AERIAL_SPEED: f32 = 12.0 * BLOCK_SIZE;
|
pub const MAX_AERIAL_SPEED: f32 = 8.0 * BLOCK_SIZE;
|
||||||
const AERIAL_ACCELERATION: f32 = (MAX_AERIAL_SPEED * 2.0) / 0.5;
|
const AERIAL_ACCELERATION: f32 = (MAX_AERIAL_SPEED * 2.0) / 0.5;
|
||||||
const AERIAL_JUMP_HORZ_BOOST: f32 = AERIAL_ACCELERATION * 0.3;
|
const AERIAL_JUMP_HORZ_BOOST: f32 = AERIAL_ACCELERATION * 0.3;
|
||||||
|
|
||||||
#[derive(SystemDesc)]
|
#[derive(SystemDesc)]
|
||||||
pub struct PlayerSystem;
|
pub struct PlayerMovementSystem;
|
||||||
|
|
||||||
impl <'s> System<'s> for PlayerSystem {
|
impl <'s> System<'s> for PlayerMovementSystem {
|
||||||
type SystemData = (
|
type SystemData = (
|
||||||
WriteStorage<'s, Dynamic>,
|
WriteStorage<'s, Dynamic>,
|
||||||
WriteStorage<'s, Player>,
|
WriteStorage<'s, Player>,
|
||||||
|
@ -160,3 +166,38 @@ impl <'s> System<'s> for PlayerSystem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(SystemDesc)]
|
||||||
|
pub struct CameraFollowSystem;
|
||||||
|
|
||||||
|
impl<'s> System<'s> for CameraFollowSystem {
|
||||||
|
type SystemData = (
|
||||||
|
WriteStorage<'s, Player>,
|
||||||
|
ReadStorage<'s, Camera>,
|
||||||
|
WriteStorage<'s, Transform>,
|
||||||
|
Read<'s, Level>,
|
||||||
|
);
|
||||||
|
|
||||||
|
fn run(&mut self, (mut players, cameras, mut transforms, level): Self::SystemData) {
|
||||||
|
let mut player_transform = Vector3::new(0.0, 0.0, 0.0);
|
||||||
|
for (current_player_transform, _) in (&transforms, &mut players).join() {
|
||||||
|
player_transform = current_player_transform.translation().clone();
|
||||||
|
}
|
||||||
|
for (camera_transform, _) in (&mut transforms, &cameras).join() {
|
||||||
|
const HALF_WIDTH: f32 = CAMERA_WIDTH / 2.0;
|
||||||
|
const HALF_HEIGHT: f32 = CAMERA_HEIGHT / 2.0;
|
||||||
|
if player_transform.x - HALF_WIDTH < level.left {
|
||||||
|
player_transform.x = level.left + HALF_WIDTH;
|
||||||
|
} else if player_transform.x + HALF_WIDTH > level.right {
|
||||||
|
player_transform.x = level.right - HALF_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if player_transform.y - HALF_HEIGHT < level.bottom {
|
||||||
|
player_transform.y = level.bottom + HALF_HEIGHT;
|
||||||
|
} else if player_transform.y + HALF_HEIGHT > level.top {
|
||||||
|
player_transform.y = level.top - HALF_HEIGHT;
|
||||||
|
}
|
||||||
|
camera_transform.set_translation_xyz(player_transform.x, player_transform.y, 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue