doukutsu-rs/src/components/number_popup.rs

116 lines
3.3 KiB
Rust

use crate::common::{interpolate_fix9_scale, Rect};
use crate::entity::GameEntity;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::game::frame::Frame;
use crate::game::shared_game_state::SharedGameState;
#[derive(Debug, Copy, Clone)]
pub struct NumberPopup {
pub value: i16,
pub x: i32,
pub y: i32,
pub prev_x: i32,
pub prev_y: i32,
counter: u16,
throttle: u16,
value_display: i16,
}
impl NumberPopup {
pub fn new() -> NumberPopup {
NumberPopup { value: 0, x: 0, y: 0, prev_x: 0, prev_y: 0, counter: 0, throttle: 0, value_display: 0 }
}
pub fn set_value(&mut self, value: i16) {
if self.counter > 32 {
self.counter = 32;
}
self.value = value;
}
pub fn add_value(&mut self, value: i16) {
self.set_value(self.value + value);
}
pub fn set_value_throttled(&mut self, value: i16) {
self.throttle = 16;
self.set_value(value);
}
pub fn add_value_throttled(&mut self, value: i16) {
self.set_value_throttled(self.value + value);
}
}
impl GameEntity<()> for NumberPopup {
fn tick(&mut self, _state: &mut SharedGameState, _custom: ()) -> GameResult<()> {
if self.throttle > 0 {
self.throttle = self.throttle.saturating_sub(1);
}
if self.value == 0 || self.throttle > 0 {
return Ok(());
}
self.value_display = self.value;
self.counter += 1;
if self.counter == 80 {
self.counter = 0;
self.value = 0;
self.value_display = 0;
}
Ok(())
}
fn draw(&self, state: &mut SharedGameState, ctx: &mut Context, frame: &Frame) -> GameResult<()> {
if self.value_display == 0 {
return Ok(());
}
// tick 0 - 32 - move up by 0.5 pixels
// tick 33 - 72 - stay
// tick 73 - 80 - fade up
let y_offset = self.counter.min(32) as f32 * 0.5;
let clip = self.counter.max(72) - 72;
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "TextBox")?;
let (frame_x, frame_y) = frame.xy_interpolated(state.frame_time);
let x = interpolate_fix9_scale(self.prev_x, self.x, state.frame_time) - frame_x;
let y = interpolate_fix9_scale(self.prev_y, self.y, state.frame_time) - frame_y - y_offset;
let n = format!("{:+}", self.value_display);
let x = x - n.len() as f32 * 4.0;
for (offset, chr) in n.chars().enumerate() {
match chr {
'+' => {
batch.add_rect(x + offset as f32 * 8.0, y, &Rect::new_size(32, 48 + clip, 8, 8 - clip));
}
'-' => {
batch.add_rect(x + offset as f32 * 8.0, y, &Rect::new_size(40, 48 + clip, 8, 8 - clip));
}
'0'..='9' => {
let number_set = if self.value_display < 0 { 64 } else { 56 };
let idx = chr as u16 - '0' as u16;
batch.add_rect(
x + offset as f32 * 8.0,
y,
&Rect::new_size(idx * 8, number_set + clip, 8, 8 - clip),
);
}
_ => {}
}
}
batch.draw(ctx)?;
Ok(())
}
}