Bruh
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target/
|
||||||
4635
Cargo.lock
generated
Normal file
4635
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
10
Cargo.toml
Normal file
10
Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "arcade_dreams"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bevy = "0.14.2"
|
||||||
|
bevy_ecs_tilemap = "0.14"
|
||||||
|
bevy_ecs_ldtk = "0.10"
|
||||||
|
rapier2d = "0.22.0"
|
||||||
166
src/main.rs
Normal file
166
src/main.rs
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
use bevy::{prelude::*, utils::HashSet};
|
||||||
|
use bevy_ecs_ldtk::prelude::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))
|
||||||
|
.add_plugins(LdtkPlugin)
|
||||||
|
.insert_resource(LevelSelection::index(0))
|
||||||
|
.register_ldtk_entity::<PlayerBundle>("Player")
|
||||||
|
.init_resource::<LevelWalls>()
|
||||||
|
.register_ldtk_entity::<GoalBundle>("Goal")
|
||||||
|
.register_ldtk_int_cell::<WallBundle>(1)
|
||||||
|
.add_systems(
|
||||||
|
Update,
|
||||||
|
(
|
||||||
|
move_player_from_input,
|
||||||
|
translate_grid_coords_entities,
|
||||||
|
cache_wall_locations,
|
||||||
|
check_goal,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.add_systems(Startup, setup)
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
|
let mut camera = Camera2dBundle::default();
|
||||||
|
camera.projection.scale = 0.5;
|
||||||
|
camera.transform.translation.x += 1280.0 / 4.0;
|
||||||
|
camera.transform.translation.y += 720.0 / 4.0;
|
||||||
|
commands.spawn(camera);
|
||||||
|
|
||||||
|
commands.spawn(LdtkWorldBundle {
|
||||||
|
ldtk_handle: asset_server.load("shocked-miguel.ldtk"),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#[derive(Default, Component)]
|
||||||
|
struct Player;
|
||||||
|
|
||||||
|
#[derive(Default, Bundle, LdtkEntity)]
|
||||||
|
struct PlayerBundle {
|
||||||
|
player: Player,
|
||||||
|
#[sprite_sheet_bundle]
|
||||||
|
sprite_bundle: LdtkSpriteSheetBundle,
|
||||||
|
#[grid_coords]
|
||||||
|
grid_coords: GridCoords,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Component)]
|
||||||
|
struct Goal;
|
||||||
|
|
||||||
|
#[derive(Default, Bundle, LdtkEntity)]
|
||||||
|
struct GoalBundle {
|
||||||
|
goal: Goal,
|
||||||
|
#[sprite_sheet_bundle]
|
||||||
|
sprite_sheet_bundle: LdtkSpriteSheetBundle,
|
||||||
|
#[grid_coords]
|
||||||
|
grid_coords: GridCoords,
|
||||||
|
}
|
||||||
|
fn move_player_from_input(
|
||||||
|
mut players: Query<&mut GridCoords, With<Player>>,
|
||||||
|
input: Res<ButtonInput<KeyCode>>,
|
||||||
|
level_walls: Res<LevelWalls>,
|
||||||
|
) {
|
||||||
|
let movement_direction = if input.just_pressed(KeyCode::KeyW) {
|
||||||
|
GridCoords::new(0, 1)
|
||||||
|
} else if input.just_pressed(KeyCode::KeyA) {
|
||||||
|
GridCoords::new(-1, 0)
|
||||||
|
} else if input.just_pressed(KeyCode::KeyS) {
|
||||||
|
GridCoords::new(0, -1)
|
||||||
|
} else if input.just_pressed(KeyCode::KeyD) {
|
||||||
|
GridCoords::new(1, 0)
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const GRID_SIZE: i32 = 16;
|
||||||
|
|
||||||
|
fn translate_grid_coords_entities(
|
||||||
|
mut grid_coords_entities: Query<(&mut Transform, &GridCoords), Changed<GridCoords>>,
|
||||||
|
) {
|
||||||
|
for (mut transform, grid_coords) in grid_coords_entities.iter_mut() {
|
||||||
|
transform.translation =
|
||||||
|
bevy_ecs_ldtk::utils::grid_coords_to_translation(*grid_coords, IVec2::splat(GRID_SIZE))
|
||||||
|
.extend(transform.translation.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Component)]
|
||||||
|
struct Wall;
|
||||||
|
|
||||||
|
#[derive(Default, Bundle, LdtkIntCell)]
|
||||||
|
struct WallBundle {
|
||||||
|
wall: Wall,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Resource)]
|
||||||
|
struct LevelWalls {
|
||||||
|
wall_locations: HashSet<GridCoords>,
|
||||||
|
level_width: i32,
|
||||||
|
level_height: i32,
|
||||||
|
}
|
||||||
|
impl LevelWalls {
|
||||||
|
fn in_wall(&self, grid_coords: &GridCoords) -> bool {
|
||||||
|
grid_coords.x < 0
|
||||||
|
|| grid_coords.y < 0
|
||||||
|
|| grid_coords.x >= self.level_width
|
||||||
|
|| grid_coords.y >= self.level_height
|
||||||
|
|| self.wall_locations.contains(grid_coords)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn cache_wall_locations(
|
||||||
|
mut level_walls: ResMut<LevelWalls>,
|
||||||
|
mut level_events: EventReader<LevelEvent>,
|
||||||
|
walls: Query<&GridCoords, With<Wall>>,
|
||||||
|
ldtk_project_entities: Query<&Handle<LdtkProject>>,
|
||||||
|
ldtk_project_assets: Res<Assets<LdtkProject>>,
|
||||||
|
) {
|
||||||
|
for level_event in level_events.read() {
|
||||||
|
if let LevelEvent::Spawned(level_iid) = level_event {
|
||||||
|
let ldtk_project = ldtk_project_assets
|
||||||
|
.get(ldtk_project_entities.single())
|
||||||
|
.expect("LdtkProject should be loaded when level is spawned");
|
||||||
|
let level = ldtk_project
|
||||||
|
.get_raw_level_by_iid(level_iid.get())
|
||||||
|
.expect("spawned level should exist in project");
|
||||||
|
|
||||||
|
let wall_locations = walls.iter().copied().collect();
|
||||||
|
|
||||||
|
let new_level_walls = LevelWalls {
|
||||||
|
wall_locations,
|
||||||
|
level_width: level.px_wid / GRID_SIZE,
|
||||||
|
level_height: level.px_hei / GRID_SIZE,
|
||||||
|
};
|
||||||
|
|
||||||
|
*level_walls = new_level_walls;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_goal(
|
||||||
|
level_selection: ResMut<LevelSelection>,
|
||||||
|
players: Query<&GridCoords, (With<Player>, Changed<GridCoords>)>,
|
||||||
|
goals: Query<&GridCoords, With<Goal>>,
|
||||||
|
) {
|
||||||
|
if players
|
||||||
|
.iter()
|
||||||
|
.zip(goals.iter())
|
||||||
|
.any(|(player_grid_coords, goal_grid_coords)| player_grid_coords == goal_grid_coords)
|
||||||
|
{
|
||||||
|
let indices = match level_selection.into_inner() {
|
||||||
|
LevelSelection::Indices(indices) => indices,
|
||||||
|
_ => panic!("level selection should always be Indices in this game"),
|
||||||
|
};
|
||||||
|
|
||||||
|
indices.level += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
69
src/player.rs
Normal file
69
src/player.rs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_ecs_ldtk::prelude::*;
|
||||||
|
use bevy_rapier2d::dynamics::Velocity;
|
||||||
|
|
||||||
|
use crate::{climbing::Climber, inventory::Inventory};
|
||||||
|
use crate::{colliders::ColliderBundle, ground_detection::GroundDetection};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Debug, Default, Component)]
|
||||||
|
pub struct Player;
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Bundle, LdtkEntity)]
|
||||||
|
pub struct PlayerBundle {
|
||||||
|
#[sprite_bundle("player.png")]
|
||||||
|
pub sprite_bundle: SpriteBundle,
|
||||||
|
#[from_entity_instance]
|
||||||
|
pub collider_bundle: ColliderBundle,
|
||||||
|
pub player: Player,
|
||||||
|
#[worldly]
|
||||||
|
pub worldly: Worldly,
|
||||||
|
pub climber: Climber,
|
||||||
|
pub ground_detection: GroundDetection,
|
||||||
|
|
||||||
|
// Build Items Component manually by using `impl From<&EntityInstance>`
|
||||||
|
#[from_entity_instance]
|
||||||
|
items: Inventory,
|
||||||
|
|
||||||
|
// The whole EntityInstance can be stored directly as an EntityInstance component
|
||||||
|
#[from_entity_instance]
|
||||||
|
entity_instance: EntityInstance,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn player_movement(
|
||||||
|
input: Res<ButtonInput<KeyCode>>,
|
||||||
|
mut query: Query<(&mut Velocity, &mut Climber, &GroundDetection), With<Player>>,
|
||||||
|
) {
|
||||||
|
for (mut velocity, mut climber, ground_detection) in &mut query {
|
||||||
|
let right = if input.pressed(KeyCode::KeyD) { 1. } else { 0. };
|
||||||
|
let left = if input.pressed(KeyCode::KeyA) { 1. } else { 0. };
|
||||||
|
|
||||||
|
velocity.linvel.x = (right - left) * 200.;
|
||||||
|
|
||||||
|
if climber.intersecting_climbables.is_empty() {
|
||||||
|
climber.climbing = false;
|
||||||
|
} else if input.just_pressed(KeyCode::KeyW) || input.just_pressed(KeyCode::KeyS) {
|
||||||
|
climber.climbing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if climber.climbing {
|
||||||
|
let up = if input.pressed(KeyCode::KeyW) { 1. } else { 0. };
|
||||||
|
let down = if input.pressed(KeyCode::KeyS) { 1. } else { 0. };
|
||||||
|
|
||||||
|
velocity.linvel.y = (up - down) * 200.;
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.just_pressed(KeyCode::Space) && (ground_detection.on_ground || climber.climbing) {
|
||||||
|
velocity.linvel.y = 500.;
|
||||||
|
climber.climbing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PlayerPlugin;
|
||||||
|
|
||||||
|
impl Plugin for PlayerPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.add_systems(Update, player_movement)
|
||||||
|
.register_ldtk_entity::<PlayerBundle>("Player");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user