2022-01-05 05:40:50 +00:00
|
|
|
use crate::common::{Color, Rect};
|
|
|
|
use crate::frame::Frame;
|
|
|
|
use crate::stage::{BackgroundType, Stage, StageTexturePaths};
|
2022-01-09 18:22:30 +00:00
|
|
|
use crate::{graphics, Context, GameResult, SharedGameState};
|
2022-01-05 05:40:50 +00:00
|
|
|
|
|
|
|
pub struct Background {
|
|
|
|
pub tick: usize,
|
|
|
|
pub prev_tick: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Background {
|
|
|
|
pub fn new() -> Self {
|
2022-01-09 18:22:30 +00:00
|
|
|
Background { tick: 0, prev_tick: 0 }
|
2022-01-05 05:40:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn tick(&mut self) -> GameResult<()> {
|
|
|
|
self.tick = self.tick.wrapping_add(1);
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn draw_tick(&mut self) -> GameResult<()> {
|
|
|
|
self.prev_tick = self.tick;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn draw(
|
|
|
|
&self,
|
|
|
|
state: &mut SharedGameState,
|
|
|
|
ctx: &mut Context,
|
|
|
|
frame: &Frame,
|
|
|
|
textures: &StageTexturePaths,
|
|
|
|
stage: &Stage,
|
|
|
|
) -> GameResult {
|
2022-01-09 18:22:30 +00:00
|
|
|
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, &textures.background)?;
|
2022-01-05 05:40:50 +00:00
|
|
|
let scale = state.scale;
|
|
|
|
let (frame_x, frame_y) = frame.xy_interpolated(state.frame_time);
|
|
|
|
|
|
|
|
match stage.data.background_type {
|
|
|
|
BackgroundType::TiledStatic => {
|
|
|
|
graphics::clear(ctx, stage.data.background_color);
|
|
|
|
|
2022-01-06 01:11:17 +00:00
|
|
|
let (bg_width, bg_height) = (batch.width() as i32, batch.height() as i32);
|
|
|
|
let count_x = state.canvas_size.0 as i32 / bg_width + 1;
|
|
|
|
let count_y = state.canvas_size.1 as i32 / bg_height + 1;
|
2022-01-05 05:40:50 +00:00
|
|
|
|
2022-01-06 01:11:17 +00:00
|
|
|
for y in -1..count_y {
|
|
|
|
for x in -1..count_x {
|
|
|
|
batch.add((x * bg_width) as f32, (y * bg_height) as f32);
|
2022-01-05 05:40:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BackgroundType::TiledParallax | BackgroundType::Tiled | BackgroundType::Waterway => {
|
|
|
|
graphics::clear(ctx, stage.data.background_color);
|
|
|
|
|
|
|
|
let (off_x, off_y) = if stage.data.background_type == BackgroundType::Tiled {
|
|
|
|
(frame_x % (batch.width() as f32), frame_y % (batch.height() as f32))
|
|
|
|
} else {
|
|
|
|
(
|
|
|
|
((frame_x / 2.0 * scale).floor() / scale) % (batch.width() as f32),
|
|
|
|
((frame_y / 2.0 * scale).floor() / scale) % (batch.height() as f32),
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2022-01-06 01:11:17 +00:00
|
|
|
let (bg_width, bg_height) = (batch.width() as i32, batch.height() as i32);
|
|
|
|
let count_x = state.canvas_size.0 as i32 / bg_width + 2;
|
|
|
|
let count_y = state.canvas_size.1 as i32 / bg_height + 2;
|
2022-01-05 05:40:50 +00:00
|
|
|
|
2022-01-06 01:11:17 +00:00
|
|
|
for y in -1..count_y {
|
|
|
|
for x in -1..count_x {
|
|
|
|
batch.add((x * bg_width) as f32 - off_x, (y * bg_height) as f32 - off_y);
|
2022-01-05 05:40:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BackgroundType::Water => {
|
|
|
|
graphics::clear(ctx, stage.data.background_color);
|
|
|
|
}
|
|
|
|
BackgroundType::Black => {
|
|
|
|
graphics::clear(ctx, stage.data.background_color);
|
|
|
|
}
|
|
|
|
BackgroundType::Scrolling => {
|
|
|
|
graphics::clear(ctx, stage.data.background_color);
|
2022-01-09 18:22:30 +00:00
|
|
|
|
|
|
|
let (bg_width, bg_height) = (batch.width() as i32, batch.height() as i32);
|
|
|
|
let offset_x = self.tick as f32 % (bg_width as f32 / 3.0);
|
|
|
|
let interp_x = (offset_x * (1.0 - state.frame_time as f32)
|
|
|
|
+ (offset_x + 1.0) * state.frame_time as f32)
|
|
|
|
* 3.0
|
|
|
|
* scale;
|
|
|
|
|
|
|
|
let count_x = state.canvas_size.0 as i32 / bg_width + 6;
|
|
|
|
let count_y = state.canvas_size.1 as i32 / bg_height + 1;
|
|
|
|
|
|
|
|
for y in -1..count_y {
|
|
|
|
for x in -1..count_x {
|
|
|
|
batch.add((x * bg_width) as f32 - interp_x, (y * bg_height) as f32);
|
|
|
|
}
|
|
|
|
}
|
2022-01-05 05:40:50 +00:00
|
|
|
}
|
|
|
|
BackgroundType::OutsideWind | BackgroundType::Outside | BackgroundType::OutsideUnknown => {
|
|
|
|
graphics::clear(ctx, Color::from_rgb(0, 0, 0));
|
|
|
|
|
|
|
|
let offset_x = (self.tick % 640) as i32;
|
|
|
|
let offset_y = ((state.canvas_size.1 - 240.0) / 2.0).floor();
|
|
|
|
|
2022-04-02 20:36:16 +00:00
|
|
|
// Sun/Moon with 100px buffers on either side
|
2022-04-02 20:45:53 +00:00
|
|
|
let (start, width, center) = if state.constants.is_switch {
|
|
|
|
(0, 427, ((state.canvas_size.0 - 427.0) / 2.0).floor())
|
2022-04-02 20:36:16 +00:00
|
|
|
} else {
|
2022-04-02 20:45:53 +00:00
|
|
|
(144, 320, ((state.canvas_size.0 - 320.0) / 2.0).floor())
|
2022-04-02 20:36:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
for x in (0..(center as i32)).step_by(100) {
|
2022-04-02 20:45:53 +00:00
|
|
|
batch.add_rect(x as f32, offset_y, &Rect::new_size(start, 0, 100, 88));
|
2022-04-02 20:36:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
batch.add_rect(center, offset_y, &Rect::new_size(0, 0, width, 88));
|
|
|
|
|
|
|
|
for x in (center as i32 + width as i32..(state.canvas_size.0 as i32)).step_by(100) {
|
2022-04-02 20:45:53 +00:00
|
|
|
batch.add_rect(x as f32, offset_y, &Rect::new_size(start, 0, 100, 88));
|
2022-01-05 05:40:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// top / bottom edges
|
|
|
|
if offset_y > 0.0 {
|
|
|
|
let scale = offset_y;
|
|
|
|
|
|
|
|
for x in (0..(state.canvas_size.0 as i32)).step_by(100) {
|
2022-01-09 18:22:30 +00:00
|
|
|
batch.add_rect_scaled(x as f32, 0.0, 1.0, scale, &Rect::new_size(128, 0, 100, 1));
|
2022-01-05 05:40:50 +00:00
|
|
|
}
|
|
|
|
|
2022-01-09 18:22:30 +00:00
|
|
|
batch.add_rect_scaled(
|
|
|
|
(state.canvas_size.0 - 320.0) / 2.0,
|
|
|
|
0.0,
|
|
|
|
1.0,
|
|
|
|
scale,
|
|
|
|
&Rect::new_size(0, 0, 320, 1),
|
|
|
|
);
|
2022-01-05 05:40:50 +00:00
|
|
|
|
|
|
|
for x in ((-offset_x * 4)..(state.canvas_size.0 as i32)).step_by(320) {
|
2022-01-09 18:22:30 +00:00
|
|
|
batch.add_rect_scaled(
|
|
|
|
x as f32,
|
|
|
|
offset_y + 240.0,
|
|
|
|
1.0,
|
|
|
|
scale + 4.0,
|
|
|
|
&Rect::new_size(0, 239, 320, 1),
|
|
|
|
);
|
2022-01-05 05:40:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for x in ((-offset_x / 2)..(state.canvas_size.0 as i32)).step_by(320) {
|
|
|
|
batch.add_rect(x as f32, offset_y + 88.0, &Rect::new_size(0, 88, 320, 35));
|
|
|
|
}
|
|
|
|
|
|
|
|
for x in ((-offset_x % 320)..(state.canvas_size.0 as i32)).step_by(320) {
|
|
|
|
batch.add_rect(x as f32, offset_y + 123.0, &Rect::new_size(0, 123, 320, 23));
|
|
|
|
}
|
|
|
|
|
|
|
|
for x in ((-offset_x * 2)..(state.canvas_size.0 as i32)).step_by(320) {
|
|
|
|
batch.add_rect(x as f32, offset_y + 146.0, &Rect::new_size(0, 146, 320, 30));
|
|
|
|
}
|
|
|
|
|
|
|
|
for x in ((-offset_x * 4)..(state.canvas_size.0 as i32)).step_by(320) {
|
|
|
|
batch.add_rect(x as f32, offset_y + 176.0, &Rect::new_size(0, 176, 320, 64));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
batch.draw(ctx)?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|