score ui + cascade collapse
This commit is contained in:
parent
8d673fb3aa
commit
0fd5719473
4 changed files with 81 additions and 17 deletions
|
|
@ -12,3 +12,5 @@ pub const CANNON_Z_INDEX: f32 = 10.0;
|
||||||
pub const PROJECTILE_Z_INDEX: f32 = 11.0;
|
pub const PROJECTILE_Z_INDEX: f32 = 11.0;
|
||||||
pub const CURRENT_SHOT_Z_INDEX: f32 = 12.0;
|
pub const CURRENT_SHOT_Z_INDEX: f32 = 12.0;
|
||||||
pub const NEXT_SHOT_Z_INDEX: f32 = 12.0;
|
pub const NEXT_SHOT_Z_INDEX: f32 = 12.0;
|
||||||
|
|
||||||
|
pub const SCORE_Z_INDEX: f32 = 100.0;
|
||||||
|
|
@ -8,7 +8,7 @@ impl Plugin for LevelPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
OnEnter(GameState),
|
OnEnter(GameState),
|
||||||
(setup_level, initialize_queue, setup_cannon).chain(),
|
(setup_level, initialize_queue, setup_cannon, setup_score_ui).chain(),
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
|
|
@ -18,17 +18,20 @@ impl Plugin for LevelPlugin {
|
||||||
warmup_queue_movement, //до спавна остальных шариков
|
warmup_queue_movement, //до спавна остальных шариков
|
||||||
spawn_new_ball,
|
spawn_new_ball,
|
||||||
check_wave_completion,
|
check_wave_completion,
|
||||||
//cannon systems
|
//сохраняем порядок систем пушки
|
||||||
|
(
|
||||||
cycle_cannon_type,
|
cycle_cannon_type,
|
||||||
update_cannon_preview,
|
update_cannon_preview,
|
||||||
spawn_projectile_from_cannon,
|
spawn_projectile_from_cannon,
|
||||||
//сохранять порядок верхних трех
|
)
|
||||||
|
.chain(),
|
||||||
rotate_cannon,
|
rotate_cannon,
|
||||||
move_projectiles,
|
move_projectiles,
|
||||||
//сохраняем порядок трех
|
//сохраняем порядок ниже
|
||||||
(
|
(
|
||||||
detect_projectile_hit,
|
detect_projectile_hit,
|
||||||
check_and_remove_matches,
|
check_and_remove_matches,
|
||||||
|
update_score_text,
|
||||||
move_queue_along_track,
|
move_queue_along_track,
|
||||||
)
|
)
|
||||||
.chain(),
|
.chain(),
|
||||||
|
|
|
||||||
|
|
@ -263,20 +263,52 @@ pub fn check_and_remove_matches(
|
||||||
// --- СХЛОПЫВАНИЕ ОЧЕРЕДИ ---
|
// --- СХЛОПЫВАНИЕ ОЧЕРЕДИ ---
|
||||||
|
|
||||||
if has_left_neighbors && has_right_neighbors {
|
if has_left_neighbors && has_right_neighbors {
|
||||||
// 🔸 Удаление ВНУТРИ: сдвигаем все шарики СПРАВА влево
|
// Находим ближайшего левого соседа (максимальный индекс среди тех, что левее удаляемых)
|
||||||
println!("Closing gap ({}..{}), shifting right balls left by {}",
|
let left_neighbor_type = balls_sorted.iter()
|
||||||
|
.filter(|(_, b)| b.slot_index < removed_min_idx)
|
||||||
|
.max_by_key(|(_, b)| b.slot_index)
|
||||||
|
.map(|(_, b)| b.ball_type);
|
||||||
|
|
||||||
|
// Находим ближайшего правого соседа (минимальный индекс среди тех, что правее удаляемых)
|
||||||
|
let right_neighbor_type = balls_sorted.iter()
|
||||||
|
.filter(|(_, b)| b.slot_index > removed_max_idx)
|
||||||
|
.min_by_key(|(_, b)| b.slot_index)
|
||||||
|
.map(|(_, b)| b.ball_type);
|
||||||
|
|
||||||
|
println!("Closing gap ({}..{}), removed {} balls",
|
||||||
removed_min_idx, removed_max_idx, removed_count);
|
removed_min_idx, removed_max_idx, removed_count);
|
||||||
|
|
||||||
// Сдвигаем индексы всех шариков с index > removed_max_idx
|
// 🔥 КЛЮЧЕВОЕ: вся логика внутри проверки типов
|
||||||
|
if left_neighbor_type == right_neighbor_type {
|
||||||
|
// === ОДИНАКОВЫЕ ТИПЫ: полное схлопывание ===
|
||||||
|
println!(" → Same type ({:?}): full collapse + reset", left_neighbor_type);
|
||||||
|
|
||||||
|
// Сдвигаем индексы правых шариков влево
|
||||||
for (entity, mut ball) in balls.p1().iter_mut() {
|
for (entity, mut ball) in balls.p1().iter_mut() {
|
||||||
if ball.slot_index > removed_max_idx {
|
if ball.slot_index > removed_max_idx {
|
||||||
ball.slot_index -= removed_count;
|
ball.slot_index -= removed_count;
|
||||||
ball.slot_progress = 0.0; // "Примагничиваем" к новому слоту
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Сбрасываем прогресс ВСЕЙ очереди
|
||||||
|
for (entity, mut ball) in balls.p1().iter_mut() {
|
||||||
|
ball.slot_progress = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// записываем ласт хит, чтоб имитировать триггер каскадного уничтожения
|
||||||
|
wave.last_insert_index = Some(removed_min_idx - 1);
|
||||||
|
|
||||||
|
println!(" → Cascade armed at idx {}", removed_min_idx - 1);
|
||||||
|
} else {
|
||||||
|
// === РАЗНЫЕ ТИПЫ: НИЧЕГО не делаем ===
|
||||||
|
// Дыра остаётся, индексы и прогресс не трогаем
|
||||||
|
println!(" → Different types ({:?} vs {:?}): gap preserved",
|
||||||
|
left_neighbor_type, right_neighbor_type);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🔸 Удаление в НАЧАЛЕ или КОНЦЕ: индексы не меняем
|
// 🔸 Удаление в НАЧАЛЕ или КОНЦЕ: сбрасываем прогресс всем
|
||||||
// (опционально: можно сбросить progress у правых соседей для чёткости)
|
for (entity, mut ball) in balls.p1().iter_mut() {
|
||||||
|
ball.slot_progress = 0.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
27
src/states/level/ui.rs
Normal file
27
src/states/level/ui.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use crate::states::level::*;
|
||||||
|
|
||||||
|
pub fn setup_score_ui(
|
||||||
|
mut commands: Commands,
|
||||||
|
){
|
||||||
|
commands.spawn((
|
||||||
|
ScoreTextMarker,
|
||||||
|
Text2d::new("Score: 0"),
|
||||||
|
TextFont { font_size: 48.0, ..default() },
|
||||||
|
TextColor(Color::WHITE),
|
||||||
|
Transform::from_xyz(320.0, 300.0, SCORE_Z_INDEX),
|
||||||
|
Visibility::Visible,
|
||||||
|
LevelMarker,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_score_text(
|
||||||
|
score: Res<Score>,
|
||||||
|
mut query: Query<&mut Text2d, With<ScoreTextMarker>>,
|
||||||
|
) {
|
||||||
|
if score.is_changed() {
|
||||||
|
if let Ok(mut text) = query.single_mut() {
|
||||||
|
text.0 = format!("Score: {}", score.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue