Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add boss MVP #200

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 2 additions & 16 deletions assets/beach/beach.level.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,24 +50,10 @@ players:
location: [-70, 30, 0]

enemies:
- fighter: &slinger /fighters/slinger/slinger.fighter.yaml
location: [325, 0, 0]
trip_point_x: -1
- fighter: *slinger
location: [225, 50, 0]
trip_point_x: -1
- fighter: &bandit /fighters/bandit/bandit.fighter.yaml
location: [225, -10, 0]
trip_point_x: -1
- fighter: *bandit
location: [275, -50, 0]
trip_point_x: -1
- fighter: &brute /fighters/brute/brute.fighter.yaml
location: [400, -30, 0]
trip_point_x: -1
- fighter: *brute
- fighter: /fighters/big_bass/big_bass.fighter.yaml
location: [450, 20, 0]
trip_point_x: 300
boss: true

items:
- item: &bottle /items/bottle/bottle.item.yaml
Expand Down
Binary file added assets/fighters/big_bass/BigBass.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions assets/fighters/big_bass/big_bass.fighter.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Bandit

stats:
health: 350
damage: 35
movement_speed: 75

hud:
portrait:
image: portrait.png
image_size: [35, 35]

spritesheet:
image: [BigBass.png]
tile_size: [156, 176]
columns: 15
rows: 3

animation_fps: 0.12
animations:
idle:
frames: [0, 3]
repeat: true
running:
frames: [15, 24]
repeat: true
knocked_right:
frames: [0, 3]
knocked_left:
frames: [0, 3]
dying:
frames: [0, 3]
waiting:
frames: [0, 3]
repeat: false
attacking:
frames: [30, 44]

audio:
effects:
attacking:
16: hit.ogg
Binary file added assets/fighters/big_bass/hit.ogg
Binary file not shown.
Binary file added assets/fighters/big_bass/portrait.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
91 changes: 90 additions & 1 deletion src/attack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::{
self, ATTACK_HEIGHT, ATTACK_LAYER, ATTACK_WIDTH, ITEM_BOTTLE_NAME, ITEM_HEIGHT, ITEM_LAYER,
ITEM_WIDTH, THROW_ITEM_ROTATION_SPEED,
},
enemy::Boss,
input::PlayerAction,
item::item_carried_by_player,
metadata::{FighterMeta, GameMeta, ItemMeta},
Expand All @@ -43,6 +44,7 @@ impl Plugin for AttackPlugin {
.with_system(player_projectile_attack)
.with_system(player_throw)
.with_system(player_flop)
.with_system(boss_jump_attack)
.with_system(activate_hitbox)
.with_system(deactivate_hitbox)
.with_system(projectile_cleanup)
Expand All @@ -53,6 +55,11 @@ impl Plugin for AttackPlugin {
enemy_attack
.run_in_state(GameState::InGame)
.after("move_to_target"),
)
.add_system(
boss_attack
.run_in_state(GameState::InGame)
.after("move_to_target"),
);
}
}
Expand Down Expand Up @@ -401,7 +408,7 @@ fn player_flop(
fn enemy_attack(
mut query: Query<
(Entity, &mut State, &Facing, &Handle<FighterMeta>),
(With<Enemy>, With<Target>),
(With<Enemy>, With<Target>, Without<Boss>),
>,
mut event_reader: EventReader<ArrivedEvent>,
mut commands: Commands,
Expand Down Expand Up @@ -456,6 +463,88 @@ fn enemy_attack(
}
}

fn boss_attack(
mut query: Query<(Entity, &mut State), (With<Enemy>, With<Target>, With<Boss>)>,
mut event_reader: EventReader<ArrivedEvent>,
mut commands: Commands,
) {
for event in event_reader.iter() {
if let Ok((entity, mut state)) = query.get_mut(event.0) {
if *state != State::Attacking {
if rand::random() && *state != State::Waiting {
state.set(State::Waiting);
} else {
state.set(State::Attacking);

let attack_entity = commands
.spawn_bundle(TransformBundle::from_transform(Transform::default()))
.insert(Sensor(true))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(
ActiveCollisionTypes::default() | ActiveCollisionTypes::STATIC_STATIC,
)
.insert(CollisionGroups::new(
BodyLayers::ENEMY_ATTACK,
BodyLayers::PLAYER,
))
.insert(Attack { damage: 30 })
.insert(AttackFrames {
//TODO: Check if this is correct
startup: 6,
active: 4,
recovery: 5,
})
.id();

commands.entity(entity).push_children(&[attack_entity]);
}
}
}
}
}

fn boss_jump_attack(
mut query: Query<(&State, &Facing, &Animation, &mut Transform)>,
time: Res<Time>,
mut start_y: Local<Option<f32>>,
) {
for (state, facing, animation, mut transform) in query.iter_mut() {
if *state == State::Attacking {
let mut movement = Vec2::ZERO;

//TODO: Replace with movement intent eventwriter in movement rewrite!
//TODO: Fix hacky way to get a forward jump
if animation.current_frame < 3 {
if facing.is_left() {
movement.x -= 150. * time.delta_seconds();
} else {
movement.x += 150. * time.delta_seconds();
}
}

// For currently unclear reasons, the first Animation frame may run for less Bevy frames
// than expected. When this is the case, the player jumps less then it should, netting,
// at the end of the animation, a slightly negative Y than the beginning, which causes
// problems. This is a workaround.
//
if start_y.is_none() {
*start_y = Some(transform.translation.y);
}

if animation.current_frame < 1 {
movement.y += 270. * time.delta_seconds();
} else if animation.current_frame < 3 {
movement.y -= 180. * time.delta_seconds();
} else if animation.is_finished() {
movement.y = start_y.unwrap();
*start_y = None;
}

transform.translation += movement.extend(0.);
}
}
}

fn activate_hitbox(
attack_query: Query<(Entity, &AttackFrames, &Parent), Without<Collider>>,
fighter_query: Query<&Animation, With<State>>,
Expand Down
3 changes: 3 additions & 0 deletions src/enemy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ use crate::{
#[derive(Component)]
pub struct Enemy;

#[derive(Component)]
pub struct Boss;

/// X coordinate of the level that requires to be trespassed in order for the enemies to move.
/// For simplicy, once a given trip point is trespassed for the first time, it's set to f32::MIN.
#[derive(Component)]
Expand Down
11 changes: 9 additions & 2 deletions src/loading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
animation::Animation,
collisions::BodyLayers,
config::ENGINE_CONFIG,
enemy::{Enemy, EnemyBundle},
enemy::{Boss, Enemy, EnemyBundle},
input::MenuAction,
item::ItemBundle,
metadata::{BorderImageMeta, FighterMeta, GameMeta, ItemMeta, LevelMeta, Settings},
Expand Down Expand Up @@ -361,7 +361,14 @@ fn load_level(

// Spawn the enemies
for enemy in &level.enemies {
commands.spawn_bundle(EnemyBundle::new(enemy));
let mut ec = commands.spawn_bundle(EnemyBundle::new(enemy));

match enemy.boss {
Some(true) => {
ec.insert(Boss);
}
_ => {}
}
}

// Spawn the items
Expand Down
2 changes: 2 additions & 0 deletions src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ pub struct FighterSpawnMeta {
// Set only for enemies.
#[serde(default = "default_f32_min")]
pub trip_point_x: f32,
#[has_load_progress(none)]
pub boss: Option<bool>,
}

fn default_f32_min() -> f32 {
Expand Down