1
0
Fork 0
mirror of https://github.com/doukutsu-rs/doukutsu-rs synced 2025-02-02 07:36:57 +00:00

add flash effect and implement <FLA

This commit is contained in:
Alula 2021-03-15 22:10:16 +01:00
parent 12b2556b40
commit b34422ac7f
No known key found for this signature in database
GPG key ID: 3E00485503A1D8BA
4 changed files with 133 additions and 4 deletions

111
src/components/flash.rs Normal file
View file

@ -0,0 +1,111 @@
use crate::common::{Color, Rect};
use crate::entity::GameEntity;
use crate::frame::Frame;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::framework::graphics;
use crate::shared_game_state::SharedGameState;
pub enum FlashState {
None,
Cross(i32, i32, u16),
Blink(u16),
}
pub struct Flash {
state: FlashState,
}
impl Flash {
pub fn new() -> Flash {
Flash {
state: FlashState::None
}
}
pub fn set_cross(&mut self, x: i32, y: i32) {
self.state = FlashState::Cross(x, y, 0);
}
pub fn set_blink(&mut self) {
self.state = FlashState::Blink(0);
}
pub fn stop(&mut self) {
self.state = FlashState::None;
}
}
impl GameEntity<()> for Flash {
fn tick(&mut self, state: &mut SharedGameState, _custom: ()) -> GameResult<()> {
match self.state {
FlashState::None => {}
FlashState::Cross(x, y, tick) => {
self.state = if tick > 128 {
FlashState::None
} else {
FlashState::Cross(x, y, tick + 1)
};
}
FlashState::Blink(tick) => {
self.state = if tick > 20 {
FlashState::None
} else {
FlashState::Blink(tick + 1)
};
}
}
Ok(())
}
fn draw(&self, state: &mut SharedGameState, ctx: &mut Context, frame: &Frame) -> GameResult<()> {
const WHITE: Color = Color::new(1.0, 1.0, 1.0, 1.0);
match self.state {
FlashState::None => {}
FlashState::Cross(x, y, tick) => {
let tick = tick as f32 + state.frame_time as f32;
let frame_pos = frame.xy_interpolated(state.frame_time, state.scale);
let (cen_x, cen_y) = (
(x as f32 / 512.0) - frame_pos.0,
(y as f32 / 512.0) - frame_pos.1
);
let width = if tick > 100.0 {
(1.0 - (tick - 100.0).max(0.0) / 28.0).powf(2.0) * state.canvas_size.0
} else {
(1.0 - (0.97f32).powf(tick)).max(0.0) * state.canvas_size.0
};
let mut rect = Rect {
left: 0,
top: ((cen_y - width) * state.scale) as isize,
right: (state.canvas_size.0 * state.scale) as isize,
bottom: ((cen_y + width) * state.scale) as isize
};
graphics::draw_rect(ctx, rect, WHITE)?;
if tick <= 100.0 {
rect = Rect {
left: ((cen_x - width) * state.scale) as isize,
top: 0,
right: ((cen_x + width) * state.scale) as isize,
bottom: (state.canvas_size.1 * state.scale) as isize
};
graphics::draw_rect(ctx, rect, WHITE)?;
}
}
FlashState::Blink(tick) => {
if tick / 2 % 2 != 0 {
graphics::clear(ctx, WHITE);
}
}
}
Ok(())
}
}

View file

@ -1,5 +1,6 @@
pub mod boss_life_bar;
pub mod draw_common;
pub mod flash;
pub mod hud;
pub mod inventory;
pub mod stage_select;

View file

@ -1,11 +1,11 @@
use log::info;
use num_traits::{abs, clamp};
use crate::weapon::bullet::BulletManager;
use crate::caret::CaretType;
use crate::common::{fix9_scale, interpolate_fix9_scale, Color, Direction, FadeDirection, FadeState, Rect};
use crate::components::boss_life_bar::BossLifeBar;
use crate::components::draw_common::{draw_number, Alignment};
use crate::components::flash::Flash;
use crate::components::hud::HUD;
use crate::components::stage_select::StageSelect;
use crate::entity::GameEntity;
@ -30,6 +30,7 @@ use crate::shared_game_state::{Season, SharedGameState};
use crate::stage::{BackgroundType, Stage};
use crate::text_script::{ConfirmSelection, ScriptMode, TextScriptExecutionState, TextScriptLine, TextScriptVM};
use crate::texture_set::SizedBatch;
use crate::weapon::bullet::BulletManager;
use crate::weapon::WeaponType;
pub struct GameScene {
@ -37,6 +38,7 @@ pub struct GameScene {
pub stage: Stage,
pub boss_life_bar: BossLifeBar,
pub stage_select: StageSelect,
pub flash: Flash,
pub hud_player1: HUD,
pub hud_player2: HUD,
pub frame: Frame,
@ -86,6 +88,7 @@ impl GameScene {
inventory_player2: Inventory::new(),
boss_life_bar: BossLifeBar::new(),
stage_select: StageSelect::new(),
flash: Flash::new(),
hud_player1: HUD::new(Alignment::Left),
hud_player2: HUD::new(Alignment::Right),
frame: Frame {
@ -1104,7 +1107,13 @@ impl GameScene {
}
self.boss.tick(
state,
([&mut self.player1, &mut self.player2], &self.npc_list, &mut self.stage, &self.bullet_manager),
(
[&mut self.player1, &mut self.player2],
&self.npc_list,
&mut self.stage,
&self.bullet_manager,
&mut self.flash,
),
)?;
self.player1.tick_map_collisions(state, &self.npc_list, &mut self.stage);
@ -1365,12 +1374,15 @@ impl Scene for GameScene {
_ => {}
}
self.flash.tick(state, ())?;
TextScriptVM::run(state, self, ctx)?;
#[cfg(feature = "scripting")]
state.lua.scene_tick(self);
self.tick = self.tick.wrapping_add(1);
if state.control_flags.control_enabled() {
self.tick = self.tick.wrapping_add(1);
}
Ok(())
}
@ -1458,6 +1470,7 @@ impl Scene for GameScene {
{
self.draw_light_map(state, ctx)?;
}
self.flash.draw(state, ctx, &self.frame)?;
/*graphics::set_canvas(ctx, None);
state.game_canvas.draw(ctx, DrawParam::new()

View file

@ -1544,6 +1544,11 @@ impl TextScriptVM {
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
}
OpCode::FLA => {
game_scene.flash.set_blink();
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
}
OpCode::INI => {
exec_state = TextScriptExecutionState::Reset;
}
@ -1572,7 +1577,6 @@ impl TextScriptVM {
| OpCode::KE2
| OpCode::CRE
| OpCode::CSS
| OpCode::FLA
| OpCode::MLP
| OpCode::SPS
| OpCode::FR2