Skip to content

Commit

Permalink
design: fade-in/fade-out on tutorial dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
LiteHell committed May 20, 2024
1 parent 054859c commit a0a1b2a
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 17 deletions.
153 changes: 146 additions & 7 deletions game/src/game/tutorial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,10 @@ use super::{
janggu_state_with_tick::{self, JangguStateWithTick},
},
render_video::VideoFileRenderer,
util::confirm_dialog::{render_confirm_dialog, DialogButton},
util::confirm_dialog::render_confirm_dialog,
};

fn ask_for_tutorial(common_context: &mut GameCommonContext) -> bool {
let ask_started_at = Instant::now();
let mut selected = None;
let mut janggu_state = JangguStateWithTick::new();

Expand All @@ -46,8 +45,15 @@ fn ask_for_tutorial(common_context: &mut GameCommonContext) -> bool {
)
.unwrap();

'running: loop {
let tick = ask_started_at.elapsed().as_millis();
// show video only
let video_only_duration = 150;
let video_only_started_at = Instant::now();
loop {
let tick = video_only_started_at.elapsed().as_millis();

if tick > video_only_duration {
break;
}

for i in common_context.event_pump.poll_iter() {
if event_loop_common(&i, &mut common_context.coins) {
Expand All @@ -56,9 +62,87 @@ fn ask_for_tutorial(common_context: &mut GameCommonContext) -> bool {
}
}

// Decode background video
background_video.wanted_time_in_second = Rational64::new(
common_context.game_initialized_at.elapsed().as_millis() as i64,
1000,
);

common_context.canvas.clear();

// render bga
background_video.render_frame(&mut background_video_texture);
common_context
.canvas
.copy(&background_video_texture, None, None)
.unwrap();

render_common(common_context);
common_context.canvas.present();
}

// fade in
let fade_in_started_at = Instant::now();
let fade_in_duration = 300;
let timeout = 10;
loop {
let fade_in_tick = fade_in_started_at.elapsed().as_millis();

if fade_in_tick > fade_in_duration {
break;
}

for i in common_context.event_pump.poll_iter() {
if event_loop_common(&i, &mut common_context.coins) {
background_video.stop_decoding();
return false;
}
}

// Decode background video
background_video.wanted_time_in_second = Rational64::new(
common_context.game_initialized_at.elapsed().as_millis() as i64,
1000,
);

common_context.canvas.clear();

// render bga
background_video.render_frame(&mut background_video_texture);
common_context
.canvas
.copy(&background_video_texture, None, None)
.unwrap();

// render dialog
render_confirm_dialog(
common_context,
format!("튜토리얼을 진행하시겠습니까?\n남은 시간: {}", timeout).as_str(),
None,
None,
(common_context.game_initialized_at.elapsed().as_millis() as f64 % 1000.0) / 1000.0,
Some((ezing::sine_out(fade_in_tick as f64 / fade_in_duration as f64) * 255.0) as u8),
);

render_common(common_context);
common_context.canvas.present();
}

// show dialog
let dialog_started_at = Instant::now();
'running: loop {
let tick = dialog_started_at.elapsed().as_millis();

for i in common_context.event_pump.poll_iter() {
if event_loop_common(&i, &mut common_context.coins) {
selected = Some(false);
break 'running;
}
}

// break when timeout
let elapsed_secs = ask_started_at.elapsed().as_secs();
if elapsed_secs > 10 {
let elapsed_secs = dialog_started_at.elapsed().as_secs();
if elapsed_secs > timeout {
break 'running;
}

Expand Down Expand Up @@ -99,13 +183,68 @@ fn ask_for_tutorial(common_context: &mut GameCommonContext) -> bool {
common_context,
format!(
"튜토리얼을 진행하시겠습니까?\n남은 시간: {}",
10 - elapsed_secs
timeout - elapsed_secs
)
.as_str(),
None,
None,
(common_context.game_initialized_at.elapsed().as_millis() as f64 % 1000.0) / 1000.0,
None,
);
render_common(common_context);
common_context.canvas.present();
}

// fade out
let fade_out_started_at = Instant::now();
let fade_out_duration = 300;
let last_elapsed_secs = timeout - dialog_started_at.elapsed().as_secs().min(10);
loop {
let fade_out_tick = fade_out_started_at.elapsed().as_millis();

if fade_out_tick > fade_out_duration {
break;
}

for i in common_context.event_pump.poll_iter() {
if event_loop_common(&i, &mut common_context.coins) {
background_video.stop_decoding();
return false;
}
}

// Decode background video
background_video.wanted_time_in_second = Rational64::new(
common_context.game_initialized_at.elapsed().as_millis() as i64,
1000,
);

common_context.canvas.clear();

// render bga
background_video.render_frame(&mut background_video_texture);
common_context
.canvas
.copy(&background_video_texture, None, None)
.unwrap();

// render dialog
render_confirm_dialog(
common_context,
format!(
"튜토리얼을 진행하시겠습니까?\n남은 시간: {}",
last_elapsed_secs
)
.as_str(),
None,
None,
(common_context.game_initialized_at.elapsed().as_millis() as f64 % 1000.0) / 1000.0,
Some(
((1.0 - ezing::sine_out(fade_out_tick as f64 / fade_out_duration as f64)) * 255.0)
as u8,
),
);

render_common(common_context);
common_context.canvas.present();
}
Expand Down
25 changes: 15 additions & 10 deletions game/src/game/util/confirm_dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,14 @@ macro_rules! create_button_texture {
}};
}

pub enum DialogButton {
Yes,
No,
}

/// Renders dialog at center
pub fn render_confirm_dialog(
common_context: &mut GameCommonContext,
message: &str,
yes_button_text: Option<&str>,
no_button_text: Option<&str>,
animation_progress: f64,
alpha: Option<u8>,
) {
// Set font-size, line-height and load font
let font_size = 38;
Expand All @@ -130,7 +126,7 @@ pub fn render_confirm_dialog(
.expect("Failed to load font");

let texture_creator = common_context.canvas.texture_creator();
let font_textures: Vec<Texture> = message
let mut font_textures: Vec<Texture> = message
.split('\n')
.into_iter()
.map(|x| render_font_texture!(texture_creator, font, font_color, x))
Expand Down Expand Up @@ -177,7 +173,7 @@ pub fn render_confirm_dialog(
assert!(min_button_gap <= button_gap && button_gap <= max_button_gap);

// Render button area
let button_area = texture_creator
let mut button_area = texture_creator
.create_texture_from_surface({
// Calculate width and height
let width = button_gap * 2
Expand Down Expand Up @@ -296,7 +292,7 @@ pub fn render_confirm_dialog(
let dialog_y = ((viewport.height() - dialog_height) / 2) as i32;
common_context
.canvas
.set_draw_color(Color::RGBA(0x62, 0x62, 0x62, 255));
.set_draw_color(Color::RGBA(0x62, 0x62, 0x62, alpha.unwrap_or(255)));
common_context
.canvas
.fill_rect(Rect::new(
Expand All @@ -308,9 +304,10 @@ pub fn render_confirm_dialog(
.unwrap();

// Copy background
let background = texture_creator
let mut background = texture_creator
.load_texture("assets/dialog/bg.png")
.expect("Failed to load background texture");
background.set_alpha_mod(alpha.unwrap_or(255));
common_context
.canvas
.copy(
Expand All @@ -321,7 +318,11 @@ pub fn render_confirm_dialog(
.unwrap();

// Copy font textures
for (line_idx, line_texture) in font_textures.iter().enumerate() {
for (line_idx, line_texture) in font_textures.iter_mut().enumerate() {
if let Some(alpha) = alpha {
line_texture.set_alpha_mod(alpha);
}

common_context
.canvas
.copy(
Expand All @@ -342,6 +343,10 @@ pub fn render_confirm_dialog(
// Copy button
let button_area_bottom = dialog_y + (dialog_height - dialog_padding_y) as i32;
let button_area_y = button_area_bottom - button_area.query().height as i32;
if let Some(alpha) = alpha {
button_area.set_alpha_mod(alpha);
}

common_context
.canvas
.copy(
Expand Down

0 comments on commit a0a1b2a

Please sign in to comment.