use std::time::Duration;
use crate::core_game_engine::{BOARD_WIDTH, InGameTime};
use crate::settings::{
SlotMachine,
graphics_settings::{
MaybeOverride::{self, Keep, Override},
TileTexture, UnwrapTileFromStr,
tile_coloring::ColorID,
},
};
#[derive(PartialEq, PartialOrd, Clone, Debug, serde::Serialize, serde::Deserialize)]
pub enum LineClearEffect {
Inline(LineClearInlineEffect),
Particle(LineClearParticleEffect),
}
#[derive(PartialEq, PartialOrd, Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct LineClearInlineEffect {
#[serde(rename = "anim_idcs")]
pub anim_indices: [usize; 2 * BOARD_WIDTH],
#[serde(rename = "anim_lastidx")]
pub anim_lastidx: usize,
#[serde(rename = "col_anim")]
pub color_animation: Vec<MaybeOverride<ColorID>>,
}
#[derive(PartialEq, PartialOrd, Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct LineClearParticleEffect {
#[serde(rename = "dur_override")]
pub duration_override: MaybeOverride<InGameTime>,
#[serde(rename = "anim")]
pub animation: Vec<(MaybeOverride<TileTexture>, MaybeOverride<ColorID>)>,
#[serde(rename = "accel")]
pub acceleration: (f32, f32),
#[serde(rename = "mm_base")]
pub momentum_base: (f32, f32),
#[serde(rename = "mm_rand")]
pub momentum_rand: (f32, f32),
#[serde(rename = "mm_xpos")]
pub momentum_xpos: f32,
}
pub fn line_clear_effect_presets() -> SlotMachine<LineClearEffect> {
let slots = vec![
("None".to_owned(), LineClearEffect::none()),
(
"Disappear halfway".to_owned(),
LineClearEffect::vanish_delayed(),
),
("Disappear instantly".to_owned(), LineClearEffect::instant()),
("Blink".to_owned(), LineClearEffect::blink()),
("Flash white".to_owned(), LineClearEffect::flash_white()),
(
"Clear left-to-right".to_owned(),
LineClearEffect::left_to_right(),
),
("Clear outward".to_owned(), LineClearEffect::outward()),
("White clear inward".to_owned(), LineClearEffect::inward()),
("Burn outward".to_owned(), LineClearEffect::burn_outward()),
("Pop".to_owned(), LineClearEffect::pop()),
("Pop (more)".to_owned(), LineClearEffect::pop_high()),
(
"Confetti (gratuitous)".to_owned(),
LineClearEffect::confetti(),
),
("Stardust".to_owned(), LineClearEffect::stardust()),
("Blast".to_owned(), LineClearEffect::blast()),
("Sparks".to_owned(), LineClearEffect::sparks()),
(
"Sparks Braille".to_owned(),
LineClearEffect::sparks_braille(),
),
("Sparks ASCII".to_owned(), LineClearEffect::sparks_ascii()),
];
SlotMachine::with_unmodifiable_slots(slots, "Line clear".to_owned())
}
impl LineClearEffect {
pub fn none() -> Self {
LineClearEffect::Particle(LineClearParticleEffect {
duration_override: Override(Duration::ZERO),
animation: Vec::new(),
acceleration: (0.0, 0.0),
momentum_base: (0.0, 0.0),
momentum_rand: (0.0, 0.0),
momentum_xpos: 0.0,
})
}
pub fn vanish_delayed() -> Self {
LineClearEffect::Inline(LineClearInlineEffect {
anim_indices: [1; 2 * BOARD_WIDTH],
anim_lastidx: 2,
color_animation: Vec::new(),
})
}
pub fn instant() -> Self {
LineClearEffect::Inline(LineClearInlineEffect {
anim_indices: [0; 2 * BOARD_WIDTH],
anim_lastidx: 1,
color_animation: Vec::new(),
})
}
pub fn left_to_right() -> Self {
LineClearEffect::Inline(LineClearInlineEffect {
anim_indices: [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
],
anim_lastidx: 19,
color_animation: vec![Keep],
})
}
pub fn outward() -> Self {
LineClearEffect::Inline(LineClearInlineEffect {
anim_indices: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
anim_lastidx: 9,
color_animation: vec![Keep],
})
}
pub fn inward() -> Self {
LineClearEffect::Inline(LineClearInlineEffect {
anim_indices: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0],
anim_lastidx: 9,
color_animation: vec![Override(ColorID::WHITE)],
})
}
pub fn burn_outward() -> Self {
let color_animation = [
ColorID::WHITE,
ColorID::WHITE,
ColorID::YELLOW,
ColorID::ORANGE,
ColorID::RED,
]
.map(Override)
.into();
LineClearEffect::Inline(LineClearInlineEffect {
anim_indices: [
18, 8, 16, 6, 14, 4, 12, 2, 10, 0, 1, 11, 3, 13, 5, 15, 7, 17, 9, 19,
],
anim_lastidx: 19,
color_animation,
})
}
pub fn flash_white() -> Self {
LineClearEffect::Inline(LineClearInlineEffect {
anim_indices: [1; 2 * BOARD_WIDTH],
anim_lastidx: 0,
color_animation: vec![Override(ColorID::WHITE), Keep, Override(ColorID::WHITE)],
})
}
pub fn blink() -> Self {
LineClearEffect::Particle(LineClearParticleEffect {
duration_override: Keep,
animation: [Keep, Override(" ".tile()), Keep, Override(" ".tile())]
.map(|t| (t, Keep))
.into(),
acceleration: (0.0, 0.0),
momentum_base: (0.0, 0.0),
momentum_rand: (0.0, 0.0),
momentum_xpos: 0.0,
})
}
pub fn pop() -> Self {
let mut animation = vec![(Keep, Keep); 8];
animation[0] = (Keep, Override(ColorID::WHITE));
LineClearEffect::Particle(LineClearParticleEffect {
duration_override: Override(Duration::from_millis(1000)),
animation,
acceleration: (0.0, -200.0),
momentum_base: (0.0, 30.0),
momentum_rand: (10.0, 5.0),
momentum_xpos: 75.0,
})
}
pub fn pop_high() -> Self {
let mut animation = vec![(Keep, Keep); 8];
animation[0] = (Keep, Override(ColorID::WHITE));
LineClearEffect::Particle(LineClearParticleEffect {
duration_override: Override(Duration::from_millis(1000)),
animation,
acceleration: (0.0, -200.0),
momentum_base: (0.0, 45.0),
momentum_rand: (50.0, 5.0),
momentum_xpos: 0.0,
})
}
pub fn confetti() -> Self {
let color_animation = [
ColorID::WHITE,
ColorID::YELLOW,
ColorID::ORANGE,
ColorID::RED,
ColorID::PURPLE,
ColorID::BLUE,
ColorID::CYAN,
ColorID::GREEN,
ColorID::YELLOW,
ColorID::ORANGE,
ColorID::RED,
ColorID::PURPLE,
ColorID::BLUE,
ColorID::CYAN,
ColorID::GREEN,
]
.map(Override);
let animation = color_animation
.into_iter()
.map(|recolor| (Keep, recolor))
.collect();
LineClearEffect::Particle(LineClearParticleEffect {
duration_override: Override(Duration::from_millis(1000)),
animation,
acceleration: (0.0, -200.0),
momentum_base: (0.0, 55.0),
momentum_rand: (55.0, 25.0),
momentum_xpos: 45.0,
})
}
pub fn blast() -> Self {
let color_animation = [
ColorID::WHITE,
ColorID::YELLOW,
ColorID::ORANGE,
ColorID::RED,
ColorID::PURPLE,
]
.map(Override);
let animation = color_animation
.into_iter()
.map(|recolor| (Keep, recolor))
.collect();
LineClearEffect::Particle(LineClearParticleEffect {
duration_override: Override(Duration::from_millis(500)),
animation,
acceleration: (0.0, 10.0),
momentum_base: (0.0, -40.0),
momentum_rand: (50.0, 10.0),
momentum_xpos: 100.0,
})
}
pub fn stardust() -> Self {
let color_animation = [
ColorID::WHITE,
ColorID::GREEN,
ColorID::CYAN,
ColorID::CYAN,
ColorID::BLUE,
ColorID::PURPLE,
]
.map(Override);
let animation = color_animation.map(|recolor| (Keep, recolor)).into();
LineClearEffect::Particle(LineClearParticleEffect {
duration_override: Override(Duration::from_millis(450)),
animation,
acceleration: (650.0, 80.0),
momentum_base: (0.0, 0.0),
momentum_rand: (70.0, 10.0),
momentum_xpos: 100.0,
})
}
pub fn sparks() -> Self {
let color_animation = [
ColorID::WHITE,
ColorID::CYAN,
ColorID::YELLOW,
ColorID::ORANGE,
ColorID::RED,
ColorID::PURPLE,
]
.map(Override);
let animation = color_animation.map(|recolor| (Keep, recolor)).into();
LineClearEffect::Particle(LineClearParticleEffect {
duration_override: Override(Duration::from_millis(400)),
animation,
acceleration: (0.0, 0.0),
momentum_base: (0.0, 0.0),
momentum_rand: (60.0, 60.0),
momentum_xpos: 100.0,
})
}
pub fn sparks_braille() -> Self {
let tile_animation = ["⢾⡷", "⡱⢎", "⡡⢊", "⡁⢈", "⡀⠈"].map(|ss| Override(ss.tile()));
let color_animation = [
ColorID::WHITE,
ColorID::YELLOW,
ColorID::GREEN,
ColorID::CYAN,
ColorID::BLUE,
ColorID::PURPLE,
ColorID::RED,
]
.map(Override);
let animation = tile_animation.into_iter().zip(color_animation).collect();
LineClearEffect::Particle(LineClearParticleEffect {
duration_override: Override(Duration::from_millis(300)),
animation,
acceleration: (0.0, 0.0),
momentum_base: (0.0, 40.0),
momentum_rand: (0.0, 40.0),
momentum_xpos: 100.0,
})
}
pub fn sparks_ascii() -> Self {
let tile_animation =
["@@", "$$", "##", "%%", "**", "++", "~~", ".."].map(|ss| Override(ss.tile()));
let color_animation = [
ColorID::WHITE,
ColorID::GREEN,
ColorID::CYAN,
ColorID::YELLOW,
ColorID::CYAN,
ColorID::BLUE,
ColorID::PURPLE,
ColorID::RED,
]
.map(Override);
let animation = tile_animation.into_iter().zip(color_animation).collect();
LineClearEffect::Particle(LineClearParticleEffect {
duration_override: Override(Duration::from_millis(500)),
animation,
acceleration: (0.0, 0.0),
momentum_base: (0.0, 40.0),
momentum_rand: (0.0, 40.0),
momentum_xpos: 100.0,
})
}
}