haw-gj13-game/src/game/player.rs

196 lines
6 KiB
Rust
Raw Normal View History

2024-11-23 22:55:19 +01:00
use std::{any::Any, hash::Hash, time::Duration};
2024-11-23 21:53:08 +01:00
use animation::{run_animations, AnimBundle, Animation};
2024-11-23 18:28:37 +01:00
use bevy::{ecs::system::SystemId, prelude::*, sprite::MaterialMesh2dBundle, utils::HashMap};
2024-11-22 22:26:20 +01:00
use bevy_rapier2d::prelude::*;
2024-11-22 22:55:45 +01:00
use crate::{AppState, METER};
2024-11-22 22:26:20 +01:00
2024-11-23 22:55:19 +01:00
use super::{scene::PlayerCoords, set::IngameSet, PLAYER_DEPTH};
mod animation;
#[derive(Component)]
2024-11-23 19:21:51 +01:00
struct Player {
move_cooldown: Timer,
}
impl Default for Player {
fn default() -> Self {
Self {
move_cooldown: Timer::from_seconds(0.01, TimerMode::Repeating),
}
}
}
2024-11-23 18:28:37 +01:00
#[derive(Resource)]
2024-11-23 18:33:27 +01:00
pub struct PlayerSpawnOneshot(pub SystemId);
2024-11-23 18:28:37 +01:00
impl FromWorld for PlayerSpawnOneshot {
fn from_world(world: &mut World) -> Self {
Self(world.register_system(add_player))
}
}
2024-11-23 18:29:50 +01:00
pub(super) fn player_plugin(app: &mut App) {
2024-11-23 21:53:08 +01:00
app.add_systems(
Update,
(
move_player,
debug_player_pos,
run_animations::<PlayerAnimations>,
),
)
.init_resource::<PlayerSpawnOneshot>();
}
2024-11-23 18:10:34 +01:00
#[derive(Component, Hash, PartialEq, Eq, Default)]
enum PlayerAnimations {
#[default]
Idle,
Walk,
}
2024-11-23 19:21:51 +01:00
fn debug_player_pos(query: Query<&Transform, With<Player>>) {
let trans = query.single();
}
fn move_player(
kb_input: Res<ButtonInput<KeyCode>>,
mut query: Query<(
&mut Velocity,
2024-11-23 22:55:19 +01:00
&mut Transform,
2024-11-23 19:21:51 +01:00
&mut Player,
&mut KinematicCharacterController,
2024-11-23 22:19:17 +01:00
&mut Sprite,
&mut PlayerAnimations,
2024-11-23 19:21:51 +01:00
)>,
2024-11-23 20:19:49 +01:00
mut camera_query: Query<&mut Transform, (With<Camera2d>, Without<Player>)>,
2024-11-23 21:42:35 +01:00
phys: Query<&KinematicCharacterControllerOutput>,
player_coords: Res<PlayerCoords>,
2024-11-23 19:21:51 +01:00
time: Res<Time>,
) {
2024-11-23 22:55:19 +01:00
let (mut vel, mut p_transform, mut player, mut controller, mut sprite, mut anim_state) =
2024-11-23 22:19:17 +01:00
query.single_mut();
2024-11-23 20:19:49 +01:00
let (mut cam_transform) = camera_query.single_mut();
2024-11-23 21:42:35 +01:00
let (output) = phys.get_single();
2024-11-23 19:21:51 +01:00
if player.move_cooldown.tick(time.delta()).finished() {
let mut moved = false;
2024-11-23 21:42:35 +01:00
let mut move_x = 0;
let mut move_y = 0;
2024-11-23 20:19:49 +01:00
let mut jump = false;
2024-11-23 22:19:17 +01:00
let grounded = output.is_ok_and(|x| x.grounded);
2024-11-23 19:21:51 +01:00
if kb_input.pressed(KeyCode::KeyA) {
moved = true;
2024-11-23 21:42:35 +01:00
move_x -= 1;
2024-11-23 19:21:51 +01:00
}
if kb_input.pressed(KeyCode::KeyD) {
moved = true;
2024-11-23 21:42:35 +01:00
move_x += 1;
}
2024-11-23 22:55:19 +01:00
if kb_input.pressed(KeyCode::Space) && vel.linvel.y < 0.1 && grounded {
2024-11-23 21:42:35 +01:00
moved = true;
move_y += 1;
2024-11-23 19:21:51 +01:00
}
2024-11-23 20:19:49 +01:00
let orig = cam_transform.translation;
cam_transform.translation -= ((orig - p_transform.translation.xy().extend(0.0)) / 30.0);
2024-11-23 21:42:35 +01:00
controller.translation = Some(Vec2::new(move_x as f32 * 6., 0. - 0.01));
2024-11-23 22:55:19 +01:00
vel.linvel += Vec2::new(0., move_y as f32 * 6. * METER);
2024-11-23 22:19:17 +01:00
2024-11-23 22:24:45 +01:00
if move_x != 0 && grounded {
2024-11-23 22:19:17 +01:00
*anim_state = PlayerAnimations::Walk;
sprite.flip_x = move_x == -1;
2024-11-23 22:24:45 +01:00
} else if move_x == 0 && grounded {
2024-11-23 22:19:17 +01:00
*anim_state = PlayerAnimations::Idle;
}
2024-11-23 22:55:19 +01:00
if p_transform.translation.y < -10. * player_coords.block_size {
p_transform.translation =
Vec2::new(player_coords.x, player_coords.y).extend(PLAYER_DEPTH);
}
2024-11-23 19:21:51 +01:00
}
}
2024-11-23 19:00:54 +01:00
fn add_player(
2024-11-23 01:40:50 +01:00
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
mut texture_atlas_layouts: ResMut<Assets<TextureAtlasLayout>>,
2024-11-23 16:24:16 +01:00
asset_server: Res<AssetServer>,
2024-11-23 18:42:52 +01:00
player_coords: Res<PlayerCoords>,
2024-11-23 01:40:50 +01:00
) {
let tex_idle = asset_server.load("idle.png");
let layout_idle = TextureAtlasLayout::from_grid(UVec2::splat(512), 2, 1, None, None);
let layout_idle_handle = texture_atlas_layouts.add(layout_idle);
let tex_walk = asset_server.load("walk.png");
let layout_walk = TextureAtlasLayout::from_grid(UVec2::splat(512), 4, 1, None, None);
let layout_walk_handle = texture_atlas_layouts.add(layout_walk);
let anims = animation::AnimationManager::default()
.insert(
PlayerAnimations::Idle,
2024-11-23 21:53:08 +01:00
Animation::new(layout_idle_handle.clone(), 2, 4, tex_idle.clone()),
)
.insert(
PlayerAnimations::Walk,
2024-11-23 21:53:08 +01:00
Animation::new(layout_walk_handle.clone(), 4, 10, tex_walk.clone()),
);
2024-11-23 18:10:34 +01:00
2024-11-23 19:00:54 +01:00
commands
.spawn((
2024-11-23 19:21:51 +01:00
Player::default(),
2024-11-23 19:00:54 +01:00
AnimBundle {
tag: PlayerAnimations::Idle,
mgr: anims,
},
SpriteBundle {
2024-11-23 21:53:08 +01:00
sprite: Sprite {
custom_size: Some(Vec2::splat(1.)),
..Default::default()
},
2024-11-23 19:00:54 +01:00
transform: (*player_coords).into(),
2024-11-23 21:53:08 +01:00
texture: tex_idle,
2024-11-23 19:00:54 +01:00
..Default::default()
},
2024-11-23 21:53:08 +01:00
TextureAtlas {
layout: layout_idle_handle,
index: 0,
},
2024-11-23 19:00:54 +01:00
))
.insert((
RigidBody::Dynamic,
player_coords.get_collider(),
2024-11-23 21:42:35 +01:00
LockedAxes::ROTATION_LOCKED,
2024-11-23 19:00:54 +01:00
Velocity::default(),
2024-11-23 22:55:19 +01:00
AdditionalMassProperties::MassProperties(MassProperties {
local_center_of_mass: Vec2 { x: 0.5, y: 0.5 },
mass: 10000.0,
principal_inertia: 1.,
}),
2024-11-23 19:00:54 +01:00
))
.insert(KinematicCharacterController {
2024-11-23 20:19:49 +01:00
//translation: todo!(),
//custom_shape: todo!(),
2024-11-23 22:55:19 +01:00
custom_mass: Some(10000.0),
2024-11-23 20:19:49 +01:00
//up: todo!(),
2024-11-23 21:02:15 +01:00
offset: CharacterLength::Absolute(0.01),
slide: true,
2024-11-23 20:19:49 +01:00
//autostep: Some(CharacterAutostep {
// max_height: CharacterLength::Relative(0.1),
// min_width: CharacterLength::Absolute(1.0),
// include_dynamic_bodies: false,
//}),
//max_slope_climb_angle: todo!(),
//min_slope_slide_angle: todo!(),
2024-11-23 22:55:19 +01:00
apply_impulse_to_dynamic_bodies: true,
2024-11-23 21:42:35 +01:00
snap_to_ground: Some(CharacterLength::Absolute(0.5)),
2024-11-23 20:19:49 +01:00
//filter_flags: todo!(),
//filter_groups: todo!(),
2024-11-23 21:02:15 +01:00
// normal_nudge_factor: 1.,
2024-11-23 18:10:34 +01:00
..Default::default()
2024-11-23 19:00:54 +01:00
});
}