Skip to content
Snippets Groups Projects
Verified Commit a47f807c authored by Louis's avatar Louis :fire:
Browse files

Extrude world tiles, spawn world data

parent b7575f11
No related branches found
No related tags found
No related merge requests found
{ {
"gravity": -123.0, "gravity": -200.0,
"jump": 200.0, "jump": 200.0,
"speed": 150.0 "speed": 150.0
} }
\ No newline at end of file
assets/sprites/world.png

130 B | W: | H:

assets/sprites/world.png

130 B | W: | H:

assets/sprites/world.png
assets/sprites/world.png
assets/sprites/world.png
assets/sprites/world.png
  • 2-up
  • Swipe
  • Onion skin
assets/sprites/world_ext.png

131 B

No preview for this file type
...@@ -64,7 +64,7 @@ impl<'w, 's> AssetTypeLoader<'w, 's> { ...@@ -64,7 +64,7 @@ impl<'w, 's> AssetTypeLoader<'w, 's> {
assets: &[FixedAssetNameMapping], assets: &[FixedAssetNameMapping],
) -> Vec<Handle<Image>> { ) -> Vec<Handle<Image>> {
self.load_list(assets, |loader, path, key| { self.load_list(assets, |loader, path, key| {
let handle: Handle<Image> = loader.asset_server.load(&path); let handle: Handle<Image> = loader.asset_server.load(path);
loader loader
.handles .handles
...@@ -76,8 +76,8 @@ impl<'w, 's> AssetTypeLoader<'w, 's> { ...@@ -76,8 +76,8 @@ impl<'w, 's> AssetTypeLoader<'w, 's> {
Vec2::new(config.tile_width as f32, config.tile_height as f32), Vec2::new(config.tile_width as f32, config.tile_height as f32),
config.columns, config.columns,
config.rows, config.rows,
None, config.padding.map(|v| Vec2::new(v as f32, v as f32)),
None, config.offset.map(|v| Vec2::new(v as f32, v as f32)),
); );
let atlas_handle = loader.atlas.add(atlas); let atlas_handle = loader.atlas.add(atlas);
......
...@@ -10,6 +10,8 @@ pub struct SpriteSheetConfig { ...@@ -10,6 +10,8 @@ pub struct SpriteSheetConfig {
pub tile_height: usize, pub tile_height: usize,
pub columns: usize, pub columns: usize,
pub rows: usize, pub rows: usize,
pub padding: Option<usize>,
pub offset: Option<usize>,
} }
impl SpriteSheetConfig { impl SpriteSheetConfig {
...@@ -19,6 +21,25 @@ impl SpriteSheetConfig { ...@@ -19,6 +21,25 @@ impl SpriteSheetConfig {
tile_height: tile_wh, tile_height: tile_wh,
columns, columns,
rows, rows,
padding: None,
offset: None,
}
}
pub fn extruded_squares(
tile_wh: usize,
columns: usize,
rows: usize,
padding: Option<usize>,
offset: Option<usize>,
) -> Self {
Self {
tile_width: tile_wh,
tile_height: tile_wh,
columns,
rows,
padding,
offset,
} }
} }
...@@ -28,6 +49,26 @@ impl SpriteSheetConfig { ...@@ -28,6 +49,26 @@ impl SpriteSheetConfig {
tile_height, tile_height,
columns, columns,
rows, rows,
padding: None,
offset: None,
}
}
pub fn extruded_rectangles(
tile_width: usize,
tile_height: usize,
columns: usize,
rows: usize,
padding: Option<usize>,
offset: Option<usize>,
) -> Self {
Self {
tile_width,
tile_height,
columns,
rows,
padding,
offset,
} }
} }
} }
......
...@@ -14,14 +14,16 @@ pub fn start_preload_resources( ...@@ -14,14 +14,16 @@ pub fn start_preload_resources(
pub fn start_load_resources(mut loader: AssetTypeLoader) { pub fn start_load_resources(mut loader: AssetTypeLoader) {
loader.load_spritesheet( loader.load_spritesheet(
&SpriteSheetConfig::squares(18, 32, 64), &SpriteSheetConfig::extruded_squares(18, 32, 64, Some(2), Some(1)),
&[("sprites/world.png", "world")], &[("sprites/world_ext.png", "world")],
); );
loader.load_spritesheet( loader.load_spritesheet(
&SpriteSheetConfig::squares(24, 9, 3), &SpriteSheetConfig::squares(24, 9, 3),
&[("sprites/characters.png", "characters")], &[("sprites/characters.png", "characters")],
); );
loader.load_ldtk(&[("world.ldtk", "world")]);
} }
pub fn check_load_resources(loader: AssetTypeLoader, mut next_state: ResMut<NextState<AppState>>) { pub fn check_load_resources(loader: AssetTypeLoader, mut next_state: ResMut<NextState<AppState>>) {
......
...@@ -19,4 +19,8 @@ mod _plugin { ...@@ -19,4 +19,8 @@ mod _plugin {
pub use _plugin::EntityPluginSet; pub use _plugin::EntityPluginSet;
pub use graphics::{SimpleAnimation, SimpleAnimationBundle}; pub use graphics::{SimpleAnimation, SimpleAnimationBundle};
pub use physics::{Acceleration, PhysicsLimits, PhysicsSet, Velocity, GRAVITY_ACC, GRAVITY_VEC}; pub use physics::{
Acceleration, PhysicsLimits, PhysicsSet, PlatformerPhysicsHooks, Velocity, GRAVITY_ACC,
GRAVITY_VEC,
};
pub use player::Player;
use crate::assets::FetchPhysicsConfig; use crate::assets::FetchPhysicsConfig;
use crate::entities::Player;
use crate::system::run_in_game; use crate::system::run_in_game;
use bevy::ecs::query::Has; use bevy::ecs::query::Has;
use bevy::ecs::system::SystemParam;
use bevy::prelude::*; use bevy::prelude::*;
use bevy_rapier2d::prelude::KinematicCharacterController; use bevy_rapier2d::geometry::SolverFlags;
use bevy_rapier2d::pipeline::{ContactModificationContextView, PairFilterContextView};
use bevy_rapier2d::prelude::{
BevyPhysicsHooks, KinematicCharacterController, KinematicCharacterControllerOutput,
};
use std::time::Duration;
pub const GRAVITY_ACC: f32 = -150.0; pub const GRAVITY_ACC: f32 = -150.0;
pub const GRAVITY_VEC: Vec2 = Vec2::new(0.0, GRAVITY_ACC); pub const GRAVITY_VEC: Vec2 = Vec2::new(0.0, GRAVITY_ACC);
...@@ -53,6 +60,40 @@ impl Acceleration { ...@@ -53,6 +60,40 @@ impl Acceleration {
} }
} }
#[derive(Copy, Clone, Debug, Component)]
pub struct CoyoteTime {
elapsed: Duration,
}
impl CoyoteTime {
const LIMIT: Duration = Duration::from_millis(100);
pub fn new() -> CoyoteTime {
Self {
elapsed: Duration::ZERO,
}
}
pub fn tick(&mut self, amount: Duration) -> bool {
self.elapsed = self.elapsed.saturating_add(amount);
self.elapsed >= Self::LIMIT
}
}
fn tick_coyote_time(
time: Res<Time>,
mut commands: Commands,
mut coyote_query: Query<(Entity, &mut CoyoteTime)>,
) {
let time = time.delta();
for (entity, mut coyote_time) in &mut coyote_query {
if coyote_time.tick(time) {
commands.entity(entity).despawn_recursive();
}
}
}
#[derive(Component)]
pub struct Grounded;
fn apply_acceleration( fn apply_acceleration(
time: Res<Time>, time: Res<Time>,
mut query: Query<( mut query: Query<(
...@@ -87,6 +128,51 @@ fn apply_velocity_to_kinematics( ...@@ -87,6 +128,51 @@ fn apply_velocity_to_kinematics(
} }
} }
fn filter_collisions(mut query: Query<&mut KinematicCharacterControllerOutput>) {
for mut controller in &mut query {
for coll in &controller.collisions {
// coll.
}
}
}
#[derive(SystemParam)]
pub struct PlatformerPhysicsHooks<'w, 's> {
player_query: Query<
'w,
's,
(
&'static Transform,
&'static KinematicCharacterControllerOutput,
),
With<Player>,
>,
}
impl<'w, 's> PlatformerPhysicsHooks<'w, 's> {
pub fn fetch_player(
&self,
entity: Entity,
) -> Option<(&Transform, &KinematicCharacterControllerOutput)> {
self.player_query.get(entity).ok()
}
}
impl<'w, 's> BevyPhysicsHooks for PlatformerPhysicsHooks<'w, 's> {
fn filter_contact_pair(&self, _context: PairFilterContextView) -> Option<SolverFlags> {
info!("DAMN");
None
}
fn filter_intersection_pair(&self, _context: PairFilterContextView) -> bool {
info!("DAMN");
true
}
fn modify_solver_contacts(&self, _context: ContactModificationContextView) {
info!("MOIDIFY");
}
}
pub struct PhysicsPlugin; pub struct PhysicsPlugin;
impl Plugin for PhysicsPlugin { impl Plugin for PhysicsPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
......
...@@ -22,6 +22,7 @@ pub fn spawn_player(mut commands: Commands, assets: Res<AssetHandles>) { ...@@ -22,6 +22,7 @@ pub fn spawn_player(mut commands: Commands, assets: Res<AssetHandles>) {
..Default::default() ..Default::default()
}, },
RigidBody::KinematicPositionBased, RigidBody::KinematicPositionBased,
ActiveEvents::all(),
Collider::cuboid(8.0, 12.0), Collider::cuboid(8.0, 12.0),
KinematicCharacterController { KinematicCharacterController {
snap_to_ground: Some(CharacterLength::Absolute(0.5)), snap_to_ground: Some(CharacterLength::Absolute(0.5)),
...@@ -62,9 +63,11 @@ pub fn handle_input( ...@@ -62,9 +63,11 @@ pub fn handle_input(
.map(|phys_config| phys_config.speed) .map(|phys_config| phys_config.speed)
.unwrap_or_default(); .unwrap_or_default();
let jump = phys_config.get().map(|p| p.jump).unwrap_or_default();
for (mut velocity, controller) in &mut query { for (mut velocity, controller) in &mut query {
let delta_y = if controller.grounded && input.is_jump_just_pressed() { let delta_y = if controller.grounded && input.is_jump_just_pressed() {
Some(40.0) Some(jump)
} else { } else {
None None
}; };
......
...@@ -2,3 +2,4 @@ pub mod assets; ...@@ -2,3 +2,4 @@ pub mod assets;
pub mod debug; pub mod debug;
pub mod entities; pub mod entities;
pub mod system; pub mod system;
pub mod world;
use bevy::prelude::App; use bevy::prelude::App;
use game_core::entities::PlatformerPhysicsHooks;
use micro_ldtk::set_ldtk_tile_scale_u32;
fn main() { fn main() {
set_ldtk_tile_scale_u32(18);
App::new() App::new()
.add_plugins(game_core::system::SystemPluginSet) .add_plugins(game_core::system::SystemPluginSet)
.add_plugins(game_core::assets::AssetLoadingPlugin) .add_plugins(game_core::assets::AssetLoadingPlugin)
.add_plugins(game_core::assets::ConfigsPlugin) .add_plugins(game_core::assets::ConfigsPlugin)
.add_plugins(game_core::entities::EntityPluginSet) .add_plugins(bevy_rapier2d::plugin::RapierPhysicsPlugin::<
.add_plugins(game_core::debug::DebugPlugin) PlatformerPhysicsHooks,
.add_plugins(bevy_rapier2d::plugin::RapierPhysicsPlugin::<()>::pixels_per_meter(18.0)) >::pixels_per_meter(18.0))
.add_plugins(micro_musicbox::CombinedAudioPlugins::< .add_plugins(micro_musicbox::CombinedAudioPlugins::<
game_core::assets::AssetHandles, game_core::assets::AssetHandles,
>::new()) >::new())
.add_plugins(micro_ldtk::MicroLDTKPlugin) .add_plugins(micro_ldtk::MicroLDTKPlugin)
.add_plugins(game_core::entities::EntityPluginSet)
.add_plugins(game_core::world::WorldPlugin)
.add_plugins(game_core::debug::DebugPlugin)
.run(); .run();
} }
mod spawning;
mod _plugin {
use crate::system::AppState;
use crate::world::spawning::has_level_changed;
use bevy::app::{App, PreUpdate};
use bevy::prelude::*;
pub struct WorldPlugin;
impl Plugin for WorldPlugin {
fn build(&self, app: &mut App) {
app.add_systems(
OnEnter(AppState::InGame),
super::spawning::set_initial_level,
)
.add_systems(
PreUpdate,
super::spawning::spawn_initial_level.run_if(has_level_changed),
);
}
}
}
pub use _plugin::WorldPlugin;
use crate::assets::AssetHandles;
use crate::entities::Player;
use bevy::log::{error, info};
use bevy::prelude::{
ClearColor, Color, Commands, DetectChanges, Query, Res, ResMut, Transform, TransformBundle,
With,
};
use bevy::sprite::{SpriteSheetBundle, TextureAtlasSprite};
use bevy_rapier2d::prelude::{Collider, RigidBody};
use micro_ldtk::{entity_centre, get_ldtk_tile_scale, ActiveLevel, LevelIndex, MapQuery};
pub fn set_initial_level(mut commands: Commands) {
commands.insert_resource(ActiveLevel::new("w_0_0"));
}
pub fn has_level_changed(active: Option<Res<ActiveLevel>>) -> bool {
active.map(|a| a.is_changed()).unwrap_or(false)
}
pub fn spawn_initial_level(
mut commands: Commands,
mut query: MapQuery,
assets: Res<AssetHandles>,
mut player_q: Query<&mut Transform, With<Player>>,
l: Res<LevelIndex>,
) {
let level = match query.get_active_level() {
Some(level) => level,
None => {
error!("Didn't get the right level!");
return;
}
};
commands.insert_resource(ClearColor(
Color::hex(level.level_ref().bg_color.as_str()).unwrap_or_default(),
));
let height = level.height();
MapQuery::for_each_layer_of(level, |layer| {
layer.for_each_tile(|x, y, data| {
commands.spawn(SpriteSheetBundle {
texture_atlas: assets.atlas("world"),
sprite: TextureAtlasSprite::new(data.tile.t as usize),
transform: Transform::from_xyz(
x as f32 * get_ldtk_tile_scale(),
height - y as f32 * get_ldtk_tile_scale(),
50.0,
),
..Default::default()
});
});
});
for ent in MapQuery::get_filtered_entities_of(level, "collider") {
let (px, py) = (ent.pivot[0] - 0.5, ent.pivot[1] - 0.5);
let offset_x = ent.width as f32 * (px as f32 * -1.0);
let offset_y = ent.height as f32 * (py as f32 * -1.0);
let x = ent.px[0] as f32 + offset_x - get_ldtk_tile_scale() / 2.0;
let y = level.height() - (ent.px[1] as f32 + offset_y) + get_ldtk_tile_scale() / 2.0;
commands.spawn((
Collider::cuboid(ent.width as f32 / 2.0, ent.height as f32 / 2.0),
RigidBody::Fixed,
TransformBundle::from_transform(Transform::from_xyz(x, y, 25.0)),
));
}
for ent in MapQuery::get_filtered_entities_of(level, "spawn_point") {
let area = entity_centre(level.height_i(), ent);
for mut p in &mut player_q {
p.translation.x = area.0;
p.translation.y = area.1;
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment