WHAT HAPPENED AFTER A LONG STREAM
Player movement :D Uh..miguel not paralysed Failed to flip miguel when turning Please help
This commit is contained in:
66
Cargo.lock
generated
66
Cargo.lock
generated
@@ -826,6 +826,19 @@ version = "0.14.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "61baa1bdc1f4a7ac2c18217570a7cc04e1cd54d38456e91782f0371c79afe0a8"
|
checksum = "61baa1bdc1f4a7ac2c18217570a7cc04e1cd54d38456e91782f0371c79afe0a8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bevy_rapier2d"
|
||||||
|
version = "0.27.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "17d82b9cbb851249a8859647ae3a2c5d17664df1da27ccd43fddd1faa66b58a6"
|
||||||
|
dependencies = [
|
||||||
|
"bevy",
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
"log",
|
||||||
|
"nalgebra",
|
||||||
|
"rapier2d 0.21.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_reflect"
|
name = "bevy_reflect"
|
||||||
version = "0.14.2"
|
version = "0.14.2"
|
||||||
@@ -2548,6 +2561,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "26aecdf64b707efd1310e3544d709c5c0ac61c13756046aaaba41be5c4f66a3b"
|
checksum = "26aecdf64b707efd1310e3544d709c5c0ac61c13756046aaaba41be5c4f66a3b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"approx",
|
"approx",
|
||||||
|
"glam",
|
||||||
"matrixmultiply",
|
"matrixmultiply",
|
||||||
"nalgebra-macros",
|
"nalgebra-macros",
|
||||||
"num-complex",
|
"num-complex",
|
||||||
@@ -3061,6 +3075,30 @@ dependencies = [
|
|||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parry2d"
|
||||||
|
version = "0.16.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8aa1c304489b71ab35ad4080c5a333a5fc24b2a5f244f197dedb93276c9a05"
|
||||||
|
dependencies = [
|
||||||
|
"approx",
|
||||||
|
"arrayvec",
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
"downcast-rs",
|
||||||
|
"either",
|
||||||
|
"log",
|
||||||
|
"nalgebra",
|
||||||
|
"num-derive",
|
||||||
|
"num-traits",
|
||||||
|
"ordered-float",
|
||||||
|
"rustc-hash 2.0.0",
|
||||||
|
"simba",
|
||||||
|
"slab",
|
||||||
|
"smallvec",
|
||||||
|
"spade",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parry2d"
|
name = "parry2d"
|
||||||
version = "0.17.1"
|
version = "0.17.1"
|
||||||
@@ -3261,6 +3299,29 @@ version = "0.1.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab"
|
checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rapier2d"
|
||||||
|
version = "0.21.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a9a115cec2cd9533e376e23c87a7869508691a7b38ab078cc8a8e1cd24d9d1b"
|
||||||
|
dependencies = [
|
||||||
|
"approx",
|
||||||
|
"arrayvec",
|
||||||
|
"bit-vec 0.6.3",
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
"crossbeam",
|
||||||
|
"downcast-rs",
|
||||||
|
"log",
|
||||||
|
"nalgebra",
|
||||||
|
"num-derive",
|
||||||
|
"num-traits",
|
||||||
|
"ordered-float",
|
||||||
|
"parry2d 0.16.1",
|
||||||
|
"rustc-hash 2.0.0",
|
||||||
|
"simba",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rapier2d"
|
name = "rapier2d"
|
||||||
version = "0.22.0"
|
version = "0.22.0"
|
||||||
@@ -3278,7 +3339,7 @@ dependencies = [
|
|||||||
"num-derive",
|
"num-derive",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"ordered-float",
|
"ordered-float",
|
||||||
"parry2d",
|
"parry2d 0.17.1",
|
||||||
"rustc-hash 2.0.0",
|
"rustc-hash 2.0.0",
|
||||||
"simba",
|
"simba",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
@@ -3538,7 +3599,8 @@ dependencies = [
|
|||||||
"bevy",
|
"bevy",
|
||||||
"bevy_ecs_ldtk",
|
"bevy_ecs_ldtk",
|
||||||
"bevy_ecs_tilemap",
|
"bevy_ecs_tilemap",
|
||||||
"rapier2d",
|
"bevy_rapier2d",
|
||||||
|
"rapier2d 0.22.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -8,3 +8,4 @@ bevy = "0.14.2"
|
|||||||
bevy_ecs_tilemap = "0.14"
|
bevy_ecs_tilemap = "0.14"
|
||||||
bevy_ecs_ldtk = "0.10"
|
bevy_ecs_ldtk = "0.10"
|
||||||
rapier2d = "0.22.0"
|
rapier2d = "0.22.0"
|
||||||
|
bevy_rapier2d = "0.27.0"
|
||||||
|
|||||||
@@ -391,7 +391,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__type": "IntGrid",
|
"__type": "IntGrid",
|
||||||
"identifier": "Walls",
|
"identifier": "Collisions",
|
||||||
"type": "IntGrid",
|
"type": "IntGrid",
|
||||||
"uid": 4,
|
"uid": 4,
|
||||||
"doc": null,
|
"doc": null,
|
||||||
@@ -794,7 +794,7 @@
|
|||||||
"limitScope": "PerLevel",
|
"limitScope": "PerLevel",
|
||||||
"limitBehavior": "MoveLastOne",
|
"limitBehavior": "MoveLastOne",
|
||||||
"pivotX": 0.5,
|
"pivotX": 0.5,
|
||||||
"pivotY": 0.5,
|
"pivotY": 1,
|
||||||
"fieldDefs": []
|
"fieldDefs": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1256,21 +1256,21 @@
|
|||||||
{
|
{
|
||||||
"__identifier": "Goal",
|
"__identifier": "Goal",
|
||||||
"__grid": [34,12],
|
"__grid": [34,12],
|
||||||
"__pivot": [0.5,0.5],
|
"__pivot": [0.5,1],
|
||||||
"__tags": [],
|
"__tags": [],
|
||||||
"__tile": { "tilesetUid": 36, "x": 0, "y": 0, "w": 16, "h": 16 },
|
"__tile": { "tilesetUid": 36, "x": 0, "y": 0, "w": 16, "h": 16 },
|
||||||
"__smartColor": "#EAD4AA",
|
"__smartColor": "#EAD4AA",
|
||||||
"iid": "ee9001c0-9b00-11ef-a60d-5b17cba2b0bd",
|
"iid": "265d9ca0-9b00-11ef-8557-9dc0be7be55f",
|
||||||
"width": 16,
|
"width": 16,
|
||||||
"height": 24,
|
"height": 24,
|
||||||
"defUid": 15,
|
"defUid": 15,
|
||||||
"px": [552,200],
|
"px": [552,208],
|
||||||
"fieldInstances": []
|
"fieldInstances": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__identifier": "Walls",
|
"__identifier": "Collisions",
|
||||||
"__type": "IntGrid",
|
"__type": "IntGrid",
|
||||||
"__cWid": 35,
|
"__cWid": 35,
|
||||||
"__cHei": 20,
|
"__cHei": 20,
|
||||||
@@ -1912,7 +1912,7 @@
|
|||||||
0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
1
|
1
|
||||||
],
|
],
|
||||||
"autoLayerTiles": [
|
"autoLayerTiles": [
|
||||||
@@ -1937,6 +1937,20 @@
|
|||||||
{ "px": [0,144], "src": [0,16], "f": 0, "t": 2, "d": [31,144], "a": 1 },
|
{ "px": [0,144], "src": [0,16], "f": 0, "t": 2, "d": [31,144], "a": 1 },
|
||||||
{ "px": [240,144], "src": [0,0], "f": 0, "t": 0, "d": [31,159], "a": 1 },
|
{ "px": [240,144], "src": [0,0], "f": 0, "t": 0, "d": [31,159], "a": 1 },
|
||||||
{ "px": [0,160], "src": [0,0], "f": 0, "t": 0, "d": [31,160], "a": 1 },
|
{ "px": [0,160], "src": [0,0], "f": 0, "t": 0, "d": [31,160], "a": 1 },
|
||||||
|
{ "px": [16,160], "src": [0,16], "f": 0, "t": 2, "d": [31,161], "a": 1 },
|
||||||
|
{ "px": [32,160], "src": [0,0], "f": 0, "t": 0, "d": [31,162], "a": 1 },
|
||||||
|
{ "px": [48,160], "src": [0,16], "f": 0, "t": 2, "d": [31,163], "a": 1 },
|
||||||
|
{ "px": [64,160], "src": [0,16], "f": 0, "t": 2, "d": [31,164], "a": 1 },
|
||||||
|
{ "px": [80,160], "src": [0,0], "f": 0, "t": 0, "d": [31,165], "a": 1 },
|
||||||
|
{ "px": [96,160], "src": [0,16], "f": 0, "t": 2, "d": [31,166], "a": 1 },
|
||||||
|
{ "px": [112,160], "src": [0,16], "f": 0, "t": 2, "d": [31,167], "a": 1 },
|
||||||
|
{ "px": [128,160], "src": [0,16], "f": 0, "t": 2, "d": [31,168], "a": 1 },
|
||||||
|
{ "px": [144,160], "src": [0,0], "f": 0, "t": 0, "d": [31,169], "a": 1 },
|
||||||
|
{ "px": [160,160], "src": [0,16], "f": 0, "t": 2, "d": [31,170], "a": 1 },
|
||||||
|
{ "px": [176,160], "src": [0,0], "f": 0, "t": 0, "d": [31,171], "a": 1 },
|
||||||
|
{ "px": [192,160], "src": [0,16], "f": 0, "t": 2, "d": [31,172], "a": 1 },
|
||||||
|
{ "px": [208,160], "src": [0,0], "f": 0, "t": 0, "d": [31,173], "a": 1 },
|
||||||
|
{ "px": [224,160], "src": [0,16], "f": 0, "t": 2, "d": [31,174], "a": 1 },
|
||||||
{ "px": [240,160], "src": [0,16], "f": 0, "t": 2, "d": [31,175], "a": 1 }
|
{ "px": [240,160], "src": [0,16], "f": 0, "t": 2, "d": [31,175], "a": 1 }
|
||||||
],
|
],
|
||||||
"seed": 9045717,
|
"seed": 9045717,
|
||||||
@@ -1992,22 +2006,7 @@
|
|||||||
"seed": 9284298,
|
"seed": 9284298,
|
||||||
"overrideTilesetUid": null,
|
"overrideTilesetUid": null,
|
||||||
"gridTiles": [],
|
"gridTiles": [],
|
||||||
"entityInstances": [
|
"entityInstances": []
|
||||||
{
|
|
||||||
"__identifier": "Player",
|
|
||||||
"__grid": [1,9],
|
|
||||||
"__pivot": [0.5,1],
|
|
||||||
"__tags": [],
|
|
||||||
"__tile": { "tilesetUid": 27, "x": 0, "y": 0, "w": 32, "h": 32 },
|
|
||||||
"__smartColor": "#D77643",
|
|
||||||
"iid": "8b5bc310-73f0-11ef-83af-53f2d18f6592",
|
|
||||||
"width": 16,
|
|
||||||
"height": 16,
|
|
||||||
"defUid": 14,
|
|
||||||
"px": [16,160],
|
|
||||||
"fieldInstances": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__identifier": "Player",
|
"__identifier": "Player",
|
||||||
@@ -2033,10 +2032,24 @@
|
|||||||
"overrideTilesetUid": null,
|
"overrideTilesetUid": null,
|
||||||
"gridTiles": [],
|
"gridTiles": [],
|
||||||
"entityInstances": [
|
"entityInstances": [
|
||||||
|
{
|
||||||
|
"__identifier": "Player",
|
||||||
|
"__grid": [1,9],
|
||||||
|
"__pivot": [0.5,1],
|
||||||
|
"__tags": [],
|
||||||
|
"__tile": { "tilesetUid": 27, "x": 0, "y": 0, "w": 32, "h": 32 },
|
||||||
|
"__smartColor": "#D77643",
|
||||||
|
"iid": "8b5bc310-73f0-11ef-83af-53f2d18f6592",
|
||||||
|
"width": 16,
|
||||||
|
"height": 16,
|
||||||
|
"defUid": 14,
|
||||||
|
"px": [24,160],
|
||||||
|
"fieldInstances": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"__identifier": "Goal",
|
"__identifier": "Goal",
|
||||||
"__grid": [7,1],
|
"__grid": [13,6],
|
||||||
"__pivot": [0.5,0.5],
|
"__pivot": [0.5,1],
|
||||||
"__tags": [],
|
"__tags": [],
|
||||||
"__tile": { "tilesetUid": 36, "x": 0, "y": 0, "w": 16, "h": 16 },
|
"__tile": { "tilesetUid": 36, "x": 0, "y": 0, "w": 16, "h": 16 },
|
||||||
"__smartColor": "#EAD4AA",
|
"__smartColor": "#EAD4AA",
|
||||||
@@ -2044,13 +2057,13 @@
|
|||||||
"width": 16,
|
"width": 16,
|
||||||
"height": 24,
|
"height": 24,
|
||||||
"defUid": 15,
|
"defUid": 15,
|
||||||
"px": [120,24],
|
"px": [216,112],
|
||||||
"fieldInstances": []
|
"fieldInstances": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__identifier": "Walls",
|
"__identifier": "Collisions",
|
||||||
"__type": "IntGrid",
|
"__type": "IntGrid",
|
||||||
"__cWid": 16,
|
"__cWid": 16,
|
||||||
"__cHei": 11,
|
"__cHei": 11,
|
||||||
@@ -2908,7 +2921,7 @@
|
|||||||
{
|
{
|
||||||
"__identifier": "Goal",
|
"__identifier": "Goal",
|
||||||
"__grid": [1,5],
|
"__grid": [1,5],
|
||||||
"__pivot": [0.5,0.5],
|
"__pivot": [0.5,1],
|
||||||
"__tags": [],
|
"__tags": [],
|
||||||
"__tile": { "tilesetUid": 36, "x": 0, "y": 0, "w": 16, "h": 16 },
|
"__tile": { "tilesetUid": 36, "x": 0, "y": 0, "w": 16, "h": 16 },
|
||||||
"__smartColor": "#EAD4AA",
|
"__smartColor": "#EAD4AA",
|
||||||
@@ -2922,7 +2935,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__identifier": "Walls",
|
"__identifier": "Collisions",
|
||||||
"__type": "IntGrid",
|
"__type": "IntGrid",
|
||||||
"__cWid": 85,
|
"__cWid": 85,
|
||||||
"__cHei": 14,
|
"__cHei": 14,
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_ecs_ldtk::prelude::*;
|
|
||||||
|
|
||||||
use crate::player::Player;
|
use crate::player::Player;
|
||||||
|
|
||||||
|
|
||||||
pub struct CameraPlugin;
|
pub struct CameraPlugin;
|
||||||
|
|
||||||
impl Plugin for CameraPlugin {
|
impl Plugin for CameraPlugin {
|
||||||
|
|||||||
11
src/goal.rs
11
src/goal.rs
@@ -17,13 +17,16 @@ pub struct GoalBundle {
|
|||||||
|
|
||||||
pub fn check_goal(
|
pub fn check_goal(
|
||||||
level_selection: ResMut<LevelSelection>,
|
level_selection: ResMut<LevelSelection>,
|
||||||
players: Query<&GridCoords, (With<Player>, Changed<GridCoords>)>,
|
players: Query<&Transform, (With<Player>, Changed<Transform>)>,
|
||||||
goals: Query<&GridCoords, With<Goal>>,
|
goals: Query<&Transform, With<Goal>>,
|
||||||
) {
|
) {
|
||||||
if players
|
if players
|
||||||
.iter()
|
.iter()
|
||||||
.zip(goals.iter())
|
.zip(goals.iter())
|
||||||
.any(|(player_grid_coords, goal_grid_coords)| player_grid_coords == goal_grid_coords)
|
.any(|(player_grid_coords, goal_grid_coords)| {
|
||||||
|
((player_grid_coords.translation.x - goal_grid_coords.translation.x).abs() <= 3.)
|
||||||
|
&& ((player_grid_coords.translation.y - goal_grid_coords.translation.y).abs() <= 3.)
|
||||||
|
})
|
||||||
{
|
{
|
||||||
let indices = match level_selection.into_inner() {
|
let indices = match level_selection.into_inner() {
|
||||||
LevelSelection::Indices(indices) => indices,
|
LevelSelection::Indices(indices) => indices,
|
||||||
@@ -32,4 +35,4 @@ pub fn check_goal(
|
|||||||
|
|
||||||
indices.level += 1;
|
indices.level += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::{
|
||||||
|
prelude::*,
|
||||||
|
utils::{HashMap, HashSet},
|
||||||
|
};
|
||||||
use bevy_ecs_ldtk::prelude::*;
|
use bevy_ecs_ldtk::prelude::*;
|
||||||
|
use bevy_rapier2d::{
|
||||||
|
dynamics::RigidBody,
|
||||||
|
geometry::{Collider, Friction},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Default, Component)]
|
#[derive(Default, Component)]
|
||||||
pub struct Wall;
|
pub struct Wall;
|
||||||
@@ -8,3 +15,148 @@ pub struct Wall;
|
|||||||
pub struct WallBundle {
|
pub struct WallBundle {
|
||||||
wall: Wall,
|
wall: Wall,
|
||||||
}
|
}
|
||||||
|
pub fn spawn_wall_collision(
|
||||||
|
mut commands: Commands,
|
||||||
|
wall_query: Query<(&GridCoords, &Parent), Added<Wall>>,
|
||||||
|
parent_query: Query<&Parent, Without<Wall>>,
|
||||||
|
level_query: Query<(Entity, &LevelIid)>,
|
||||||
|
ldtk_projects: Query<&Handle<LdtkProject>>,
|
||||||
|
ldtk_project_assets: Res<Assets<LdtkProject>>,
|
||||||
|
) {
|
||||||
|
/// Represents a wide wall that is 1 tile tall
|
||||||
|
/// Used to spawn wall collisions
|
||||||
|
#[derive(Clone, Eq, PartialEq, Debug, Default, Hash)]
|
||||||
|
struct Plate {
|
||||||
|
left: i32,
|
||||||
|
right: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A simple rectangle type representing a wall of any size
|
||||||
|
struct Rect {
|
||||||
|
left: i32,
|
||||||
|
right: i32,
|
||||||
|
top: i32,
|
||||||
|
bottom: i32,
|
||||||
|
}
|
||||||
|
let mut level_to_wall_locations: HashMap<Entity, HashSet<GridCoords>> = HashMap::new();
|
||||||
|
wall_query.iter().for_each(|(&grid_coords, parent)| {
|
||||||
|
if let Ok(grandparent) = parent_query.get(parent.get()) {
|
||||||
|
level_to_wall_locations
|
||||||
|
.entry(grandparent.get())
|
||||||
|
.or_default()
|
||||||
|
.insert(grid_coords);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if !wall_query.is_empty() {
|
||||||
|
level_query.iter().for_each(|(level_entity, level_iid)| {
|
||||||
|
if let Some(level_walls) = level_to_wall_locations.get(&level_entity) {
|
||||||
|
let ldtk_project = ldtk_project_assets
|
||||||
|
.get(ldtk_projects.single())
|
||||||
|
.expect("Project has to be loaded at this point");
|
||||||
|
|
||||||
|
let level = ldtk_project
|
||||||
|
.as_standalone()
|
||||||
|
.get_loaded_level_by_iid(&level_iid.to_string())
|
||||||
|
.expect("Spawned level should exist in LDtk project");
|
||||||
|
|
||||||
|
let LayerInstance {
|
||||||
|
c_wid: width,
|
||||||
|
c_hei: height,
|
||||||
|
grid_size,
|
||||||
|
..
|
||||||
|
} = level.layer_instances()[0];
|
||||||
|
|
||||||
|
let mut plate_stack: Vec<Vec<Plate>> = Vec::new();
|
||||||
|
|
||||||
|
for y in 0..height {
|
||||||
|
let mut row_plates: Vec<Plate> = Vec::new();
|
||||||
|
let mut plate_start = None;
|
||||||
|
|
||||||
|
for x in 0..width + 1 {
|
||||||
|
match (plate_start, level_walls.contains(&GridCoords { x, y })) {
|
||||||
|
(Some(s), false) => {
|
||||||
|
row_plates.push(Plate {
|
||||||
|
left: s,
|
||||||
|
right: x - 1,
|
||||||
|
});
|
||||||
|
plate_start = None;
|
||||||
|
}
|
||||||
|
(None, true) => plate_start = Some(x),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
plate_stack.push(row_plates);
|
||||||
|
}
|
||||||
|
// combine "plates" into rectangles across multiple rows
|
||||||
|
let mut rect_builder: HashMap<Plate, Rect> = HashMap::new();
|
||||||
|
let mut prev_row: Vec<Plate> = Vec::new();
|
||||||
|
let mut wall_rects: Vec<Rect> = Vec::new();
|
||||||
|
|
||||||
|
// an extra empty row so the algorithm "finishes" the rects that touch the top edge
|
||||||
|
plate_stack.push(Vec::new());
|
||||||
|
|
||||||
|
for (y, current_row) in plate_stack.into_iter().enumerate() {
|
||||||
|
for prev_plate in &prev_row {
|
||||||
|
if !current_row.contains(prev_plate) {
|
||||||
|
//remove rect so the same plate starts a new rectangle
|
||||||
|
if let Some(rect) = rect_builder.remove(prev_plate) {
|
||||||
|
wall_rects.push(rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for plate in ¤t_row {
|
||||||
|
rect_builder
|
||||||
|
.entry(plate.clone())
|
||||||
|
.and_modify(|e| e.top += 1)
|
||||||
|
.or_insert(Rect {
|
||||||
|
bottom: y as i32,
|
||||||
|
top: y as i32,
|
||||||
|
left: plate.left,
|
||||||
|
right: plate.right,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
prev_row = current_row;
|
||||||
|
}
|
||||||
|
commands.entity(level_entity).with_children(|level| {
|
||||||
|
// Spawn colliders for every rectangle..
|
||||||
|
// Making the collider a child of the level serves two purposes:
|
||||||
|
// 1. Adjusts the transforms to be relative to the level for free
|
||||||
|
// 2. the colliders will be despawned automatically when levels unload
|
||||||
|
for wall_rect in wall_rects {
|
||||||
|
level
|
||||||
|
.spawn_empty()
|
||||||
|
.insert(Collider::cuboid(
|
||||||
|
(wall_rect.right as f32 - wall_rect.left as f32 + 1.)
|
||||||
|
* grid_size as f32
|
||||||
|
/ 2.,
|
||||||
|
(wall_rect.top as f32 - wall_rect.bottom as f32 + 1.)
|
||||||
|
* grid_size as f32
|
||||||
|
/ 2.,
|
||||||
|
))
|
||||||
|
.insert(RigidBody::Fixed)
|
||||||
|
.insert(Friction::new(1.0))
|
||||||
|
.insert(Transform::from_xyz(
|
||||||
|
(wall_rect.left + wall_rect.right + 1) as f32 * grid_size as f32
|
||||||
|
/ 2.,
|
||||||
|
(wall_rect.bottom + wall_rect.top + 1) as f32 * grid_size as f32
|
||||||
|
/ 2.,
|
||||||
|
0.,
|
||||||
|
//this averages xy so it in center yes )
|
||||||
|
))
|
||||||
|
.insert(GlobalTransform::default());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub struct WallPlugin;
|
||||||
|
|
||||||
|
impl Plugin for WallPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.add_systems(Update, spawn_wall_collision)
|
||||||
|
.register_ldtk_int_cell::<WallBundle>(1) //dirt
|
||||||
|
.register_ldtk_int_cell::<WallBundle>(3); //stone
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
use crate::player::Player;
|
use crate::{goal::Goal, player::Player};
|
||||||
|
|
||||||
// Yes I used chatgpt for this
|
// Yes I used chatgpt for this
|
||||||
// sue me, it's a mundane task :P
|
// sue me, it's a mundane task :P
|
||||||
@@ -8,6 +8,7 @@ use crate::player::Player;
|
|||||||
pub fn log_positions(
|
pub fn log_positions(
|
||||||
camera_query: Query<&Transform, With<Camera2d>>,
|
camera_query: Query<&Transform, With<Camera2d>>,
|
||||||
player_query: Query<&Transform, With<Player>>,
|
player_query: Query<&Transform, With<Player>>,
|
||||||
|
goals: Query<&Transform, With<Goal>>,
|
||||||
) {
|
) {
|
||||||
// Log camera position
|
// Log camera position
|
||||||
if let Ok(camera_transform) = camera_query.get_single() {
|
if let Ok(camera_transform) = camera_query.get_single() {
|
||||||
@@ -22,4 +23,9 @@ pub fn log_positions(
|
|||||||
} else {
|
} else {
|
||||||
info!("Player not found or multiple players detected.");
|
info!("Player not found or multiple players detected.");
|
||||||
}
|
}
|
||||||
|
if let Ok(goal_transform) = goals.get_single() {
|
||||||
|
info!("Player Position: {:?}", goal_transform.translation);
|
||||||
|
} else {
|
||||||
|
info!("Player not found or multiple players detected.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
41
src/main.rs
41
src/main.rs
@@ -1,29 +1,49 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_ecs_ldtk::prelude::*;
|
use bevy_ecs_ldtk::prelude::*;
|
||||||
|
use bevy_rapier2d::plugin::{NoUserData, RapierConfiguration, RapierPhysicsPlugin, TimestepMode};
|
||||||
use camera::CameraPlugin;
|
use camera::CameraPlugin;
|
||||||
|
use goal::{check_goal, GoalBundle};
|
||||||
|
use ground_detection::GroundDetectionPlugin;
|
||||||
|
use level_structure::{WallBundle, WallPlugin};
|
||||||
use logging::log_positions;
|
use logging::log_positions;
|
||||||
use player::PlayerPlugin;
|
use player::PlayerPlugin;
|
||||||
use goal::{GoalBundle, check_goal};
|
|
||||||
use level_structure::WallBundle;
|
|
||||||
|
|
||||||
mod camera;
|
mod camera;
|
||||||
|
mod colliders;
|
||||||
|
mod goal;
|
||||||
|
mod ground_detection;
|
||||||
|
mod level_structure;
|
||||||
mod logging;
|
mod logging;
|
||||||
mod player;
|
mod player;
|
||||||
mod goal;
|
|
||||||
mod level_structure;
|
|
||||||
|
|
||||||
pub const GRID_SIZE: i32 = 16;
|
pub const GRID_SIZE: i32 = 16;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))
|
.add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))
|
||||||
.add_plugins(LdtkPlugin)
|
.add_plugins((
|
||||||
|
LdtkPlugin,
|
||||||
|
RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(100.0),
|
||||||
|
))
|
||||||
|
.insert_resource(RapierConfiguration {
|
||||||
|
gravity: Vec2::new(0.0, -2000.0),
|
||||||
|
physics_pipeline_active: true,
|
||||||
|
query_pipeline_active: true,
|
||||||
|
timestep_mode: TimestepMode::Variable {
|
||||||
|
max_dt: 1.0 / 60.0,
|
||||||
|
time_scale: 1.0,
|
||||||
|
substeps: 1,
|
||||||
|
},
|
||||||
|
scaled_shape_subdivision: 10,
|
||||||
|
force_update_from_transform_changes: false,
|
||||||
|
})
|
||||||
.add_plugins(PlayerPlugin)
|
.add_plugins(PlayerPlugin)
|
||||||
|
.add_plugins(WallPlugin)
|
||||||
|
.add_plugins(GroundDetectionPlugin)
|
||||||
.insert_resource(LevelSelection::index(0))
|
.insert_resource(LevelSelection::index(0))
|
||||||
.register_ldtk_entity::<GoalBundle>("Goal")
|
.register_ldtk_entity::<GoalBundle>("Goal")
|
||||||
.register_ldtk_int_cell::<WallBundle>(1)
|
.register_ldtk_int_cell::<WallBundle>(1)
|
||||||
.add_systems(Startup, setup)
|
.add_systems(Startup, setup)
|
||||||
.add_systems(Update, camera::camera_fit_inside_current_level)
|
|
||||||
.add_plugins(CameraPlugin)
|
.add_plugins(CameraPlugin)
|
||||||
.add_systems(Update, (translate_grid_coords_entities, check_goal))
|
.add_systems(Update, (translate_grid_coords_entities, check_goal))
|
||||||
.add_systems(Update, log_positions)
|
.add_systems(Update, log_positions)
|
||||||
@@ -33,14 +53,10 @@ fn main() {
|
|||||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
commands.spawn(LdtkWorldBundle {
|
commands.spawn(LdtkWorldBundle {
|
||||||
ldtk_handle: asset_server.load("shocked-miguel.ldtk"),
|
ldtk_handle: asset_server.load("shocked-miguel.ldtk"),
|
||||||
level_set: LEVEL_SET,
|
|
||||||
// transform: Transform::from_xyz(-256., -144., 0.),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn translate_grid_coords_entities(
|
fn translate_grid_coords_entities(
|
||||||
mut grid_coords_entities: Query<(&mut Transform, &GridCoords), Changed<GridCoords>>,
|
mut grid_coords_entities: Query<(&mut Transform, &GridCoords), Changed<GridCoords>>,
|
||||||
) {
|
) {
|
||||||
@@ -50,8 +66,3 @@ fn translate_grid_coords_entities(
|
|||||||
.extend(transform.translation.z);
|
.extend(transform.translation.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Component)]
|
|
||||||
struct Wall;
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
176
src/player.rs
176
src/player.rs
@@ -1,11 +1,28 @@
|
|||||||
use bevy::{prelude::*, utils::HashSet};
|
use bevy::prelude::*;
|
||||||
use bevy_ecs_ldtk::prelude::*;
|
use bevy_ecs_ldtk::prelude::*;
|
||||||
|
use bevy_rapier2d::dynamics::Velocity;
|
||||||
|
|
||||||
use crate::level_structure::Wall;
|
use crate::{colliders::ColliderBundle, ground_detection::GroundDetection, level_structure::Wall};
|
||||||
|
use std::f32::consts::PI;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
enum Facing {
|
||||||
|
LEFT,
|
||||||
|
#[default]
|
||||||
|
RIGHT,
|
||||||
|
}
|
||||||
#[derive(Default, Component)]
|
#[derive(Default, Component)]
|
||||||
pub(crate) struct Player;
|
pub(crate) struct Player {
|
||||||
|
direction: Facing,
|
||||||
|
}
|
||||||
|
impl Player {
|
||||||
|
fn swap_direction(&mut self) {
|
||||||
|
match self.direction {
|
||||||
|
Facing::RIGHT => self.direction = Facing::LEFT,
|
||||||
|
Facing::LEFT => self.direction = Facing::RIGHT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#[derive(Default, Bundle, LdtkEntity)]
|
#[derive(Default, Bundle, LdtkEntity)]
|
||||||
struct PlayerBundle {
|
struct PlayerBundle {
|
||||||
player: Player,
|
player: Player,
|
||||||
@@ -13,85 +30,112 @@ struct PlayerBundle {
|
|||||||
sprite_bundle: LdtkSpriteSheetBundle,
|
sprite_bundle: LdtkSpriteSheetBundle,
|
||||||
#[grid_coords]
|
#[grid_coords]
|
||||||
grid_coords: GridCoords,
|
grid_coords: GridCoords,
|
||||||
|
pub ground_detection: GroundDetection,
|
||||||
|
#[from_entity_instance]
|
||||||
|
pub collider_bundle: ColliderBundle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Resource)]
|
// #[derive(Default, Resource)]
|
||||||
struct LevelWalls {
|
// struct LevelWalls {
|
||||||
wall_locations: HashSet<GridCoords>,
|
// wall_locations: HashSet<GridCoords>,
|
||||||
level_width: i32,
|
// level_width: i32,
|
||||||
level_height: i32,
|
// level_height: i32,
|
||||||
}
|
// }
|
||||||
impl LevelWalls {
|
// impl LevelWalls {
|
||||||
fn in_wall(&self, grid_coords: &GridCoords) -> bool {
|
// fn in_wall(&self, grid_coords: &GridCoords) -> bool {
|
||||||
grid_coords.x < 0
|
// grid_coords.x < 0
|
||||||
|| grid_coords.y < 0
|
// || grid_coords.y < 0
|
||||||
|| grid_coords.x >= self.level_width
|
// || grid_coords.x >= self.level_width
|
||||||
|| grid_coords.y >= self.level_height
|
// || grid_coords.y >= self.level_height
|
||||||
|| self.wall_locations.contains(grid_coords)
|
// || self.wall_locations.contains(grid_coords)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn move_player_from_input(
|
fn player_movement(
|
||||||
mut players: Query<&mut GridCoords, With<Player>>,
|
mut query: Query<(&mut Velocity, &GroundDetection, &Player), With<Player>>,
|
||||||
input: Res<ButtonInput<KeyCode>>,
|
input: Res<ButtonInput<KeyCode>>,
|
||||||
level_walls: Res<LevelWalls>,
|
|
||||||
) {
|
) {
|
||||||
let movement_direction =
|
// let movement_direction =
|
||||||
if input.just_pressed(KeyCode::KeyW) || input.just_pressed(KeyCode::Space) {
|
// if input.just_pressed(KeyCode::KeyW) || input.just_pressed(KeyCode::Space) {
|
||||||
GridCoords::new(0, 1)
|
// GridCoords::new(0, 1)
|
||||||
} else if input.just_pressed(KeyCode::KeyA) {
|
// } else if input.just_pressed(KeyCode::KeyA) {
|
||||||
GridCoords::new(-1, 0)
|
// GridCoords::new(-1, 0)
|
||||||
} else if input.just_pressed(KeyCode::KeyS) {
|
// } else if input.just_pressed(KeyCode::KeyS) {
|
||||||
GridCoords::new(0, -1)
|
// GridCoords::new(0, -1)
|
||||||
} else if input.just_pressed(KeyCode::KeyD) {
|
// } else if input.just_pressed(KeyCode::KeyD) {
|
||||||
GridCoords::new(1, 0)
|
// GridCoords::new(1, 0)
|
||||||
} else {
|
// } else {
|
||||||
return;
|
// return;
|
||||||
};
|
// };
|
||||||
|
for (mut velocity, ground_detection, player) in &mut query {
|
||||||
|
// let right = if input.pressed(KeyCode::KeyD) { 1. } else { 0. };
|
||||||
|
// let left = if input.pressed(KeyCode::KeyA) { 1. } else { 0. };
|
||||||
|
|
||||||
for mut player_grid_coords in players.iter_mut() {
|
let right = if input.pressed(KeyCode::KeyD) {
|
||||||
let destination = *player_grid_coords + movement_direction;
|
// match player.direction {
|
||||||
if !level_walls.in_wall(&destination) {
|
// Facing::LEFT => player.direction = Facing::RIGHT,
|
||||||
*player_grid_coords = destination;
|
// Facing::RIGHT => (),
|
||||||
|
|
||||||
|
// }
|
||||||
|
1.
|
||||||
|
|
||||||
|
} else {
|
||||||
|
0.
|
||||||
|
};
|
||||||
|
let left = if input.pressed(KeyCode::KeyA) {
|
||||||
|
1.
|
||||||
|
} else {
|
||||||
|
0.
|
||||||
|
};
|
||||||
|
velocity.linvel.x = (right - left) * 200.;
|
||||||
|
|
||||||
|
if input.just_pressed(KeyCode::Space) && ground_detection.on_ground {
|
||||||
|
velocity.linvel.y = 500.;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for mut player_grid_coords in players.iter_mut() {
|
||||||
|
// let destination = *player_grid_coords + movement_direction;
|
||||||
|
// if !level_walls.in_wall(&destination) {
|
||||||
|
// *player_grid_coords = destination;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PlayerPlugin;
|
pub struct PlayerPlugin;
|
||||||
|
|
||||||
impl Plugin for PlayerPlugin {
|
impl Plugin for PlayerPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_systems(Update, (move_player_from_input, cache_wall_locations))
|
app.add_systems(Update, player_movement)
|
||||||
.register_ldtk_entity::<PlayerBundle>("Player")
|
.register_ldtk_entity::<PlayerBundle>("Player");
|
||||||
.init_resource::<LevelWalls>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cache_wall_locations(
|
// fn cache_wall_locations(
|
||||||
mut level_walls: ResMut<LevelWalls>,
|
// mut level_walls: ResMut<LevelWalls>,
|
||||||
mut level_events: EventReader<LevelEvent>,
|
// mut level_events: EventReader<LevelEvent>,
|
||||||
walls: Query<&GridCoords, With<Wall>>,
|
// walls: Query<&GridCoords, With<Wall>>,
|
||||||
ldtk_project_entities: Query<&Handle<LdtkProject>>,
|
// ldtk_project_entities: Query<&Handle<LdtkProject>>,
|
||||||
ldtk_project_assets: Res<Assets<LdtkProject>>,
|
// ldtk_project_assets: Res<Assets<LdtkProject>>,
|
||||||
) {
|
// ) {
|
||||||
for level_event in level_events.read() {
|
// for level_event in level_events.read() {
|
||||||
if let LevelEvent::Spawned(level_iid) = level_event {
|
// if let LevelEvent::Spawned(level_iid) = level_event {
|
||||||
let ldtk_project = ldtk_project_assets
|
// let ldtk_project = ldtk_project_assets
|
||||||
.get(ldtk_project_entities.single())
|
// .get(ldtk_project_entities.single())
|
||||||
.expect("LdtkProject should be loaded when level is spawned");
|
// .expect("LdtkProject should be loaded when level is spawned");
|
||||||
let level = ldtk_project
|
// let level = ldtk_project
|
||||||
.get_raw_level_by_iid(level_iid.get())
|
// .get_raw_level_by_iid(level_iid.get())
|
||||||
.expect("spawned level should exist in project");
|
// .expect("spawned level should exist in project");
|
||||||
|
|
||||||
let wall_locations = walls.iter().copied().collect();
|
// let wall_locations = walls.iter().copied().collect();
|
||||||
|
|
||||||
let new_level_walls = LevelWalls {
|
// let new_level_walls = LevelWalls {
|
||||||
wall_locations,
|
// wall_locations,
|
||||||
level_width: level.px_wid / crate::GRID_SIZE,
|
// level_width: level.px_wid / crate::GRID_SIZE,
|
||||||
level_height: level.px_hei / crate::GRID_SIZE,
|
// level_height: level.px_hei / crate::GRID_SIZE,
|
||||||
};
|
// };
|
||||||
|
|
||||||
*level_walls = new_level_walls;
|
// *level_walls = new_level_walls;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|||||||
Reference in New Issue
Block a user