Fixed starfield tiling

master
Mark 2023-12-21 12:29:54 -08:00
parent 53927a9944
commit bf60fda4f2
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
1 changed files with 24 additions and 20 deletions

View File

@ -52,7 +52,7 @@ impl StarField {
q.x as i16, q.x as i16,
q.y as i16, q.y as i16,
(5.0 - (1.0 * wp.par)) as i16, (5.0 - (1.0 * wp.par)) as i16,
Color::RGBA(255, 255, 255, 100), Color::RGB(100, 100, 100),
)?; )?;
} }
return Ok(()); return Ok(());
@ -64,35 +64,38 @@ impl StarField {
let ww = w / 2.0; let ww = w / 2.0;
let hh = h / 2.0; let hh = h / 2.0;
// Camera position relative to the center of this field.
let pos_in_field = Cartesian::new( let pos_in_field = Cartesian::new(
dc.camera.pos.x.signum() * (((dc.camera.pos.x.abs() + ww) % w) - ww), dc.camera.pos.x.signum() * (((dc.camera.pos.x.abs() + ww) % w) - ww),
dc.camera.pos.y.signum() * (((dc.camera.pos.y.abs() + hh) % h) - hh), dc.camera.pos.y.signum() * (((dc.camera.pos.y.abs() + hh) % h) - hh),
); );
// Field center in world coordinates // Center of this field, in world coordinates
let field_center = dc.camera.pos - pos_in_field; let field_center = dc.camera.pos - pos_in_field;
// screen coordinates of top left position of starfield // Compute tile bounds.
let field_tl = // We use neighboring tiles' corners instead of this tile's corner to properly account for parallax.
WorldPosition::new(field_center + Cartesian::new(-ww, hh), 3.0).screen_position(dc); // If we use the current tiles corners, we'll see stars appear when a tile is drawn--parallax moves them
// into view. The bounds below guarantee that no *other* tiles' stars will be drawn inside.
//
// bound_nw is the screen position of the bottom-right corner of north-west tile
// bound_se is the screen position of the top-right corner of south-east tile
let bound_nw =
WorldPosition::new(field_center + Cartesian::new(-ww, hh), 4.0).screen_position(dc);
let bound_se =
WorldPosition::new(field_center + Cartesian::new(ww, -hh), 4.0).screen_position(dc);
let field_br = // Naturally, we show tiles only if we can see their edges.
WorldPosition::new(field_center + Cartesian::new(ww, -hh), 3.0).screen_position(dc); let north = bound_nw.y > 0.0;
let south = bound_se.y < dc.window_size.y;
dc.canvas.aa_circle( let east = bound_se.x < dc.window_size.x;
field_tl.x as i16, let west = bound_nw.x > 0.0;
field_tl.y as i16,
5,
Color::RGB(255, 0, 0),
)?;
dc.canvas.set_draw_color(Color::RGB(0, 0, 0));
let north = field_tl.y > 0.0;
let south = field_br.y < dc.window_size.y;
let east = field_br.x < dc.window_size.x;
let west = field_tl.x > 0.0;
// Draw center tile
self.draw_with_offset(dc, pos_in_field, Cartesian::new(0.0, 0.0))?; self.draw_with_offset(dc, pos_in_field, Cartesian::new(0.0, 0.0))?;
// Draw surrounding tiles
// (which are just offset clones of the main one)
if north { if north {
self.draw_with_offset(dc, pos_in_field, Cartesian::new(0.0, h))?; self.draw_with_offset(dc, pos_in_field, Cartesian::new(0.0, h))?;
} }
@ -118,6 +121,7 @@ impl StarField {
self.draw_with_offset(dc, pos_in_field, Cartesian::new(-w, -h))?; self.draw_with_offset(dc, pos_in_field, Cartesian::new(-w, -h))?;
} }
// draw_circle doesn't clean up the color it uses, so we do that here.
dc.canvas.set_draw_color(Color::RGB(0, 0, 0)); dc.canvas.set_draw_color(Color::RGB(0, 0, 0));
return Ok(()); return Ok(());
} }