Fixed parallax
parent
4abbcca1d4
commit
1661b5c3af
16
src/main.rs
16
src/main.rs
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use cgmath::{Deg, EuclideanSpace, Point2};
|
||||
use cgmath::{Deg, Point2};
|
||||
use winit::{
|
||||
event::{
|
||||
ElementState, Event, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase,
|
||||
|
@ -65,20 +65,6 @@ struct Sprite {
|
|||
parallax: Pfloat,
|
||||
}
|
||||
|
||||
impl Sprite {
|
||||
const PARALLAX_STRENGTH: Pfloat = 0.1;
|
||||
|
||||
pub fn post_parallax(parallax: Pfloat, pos: Point2<Pfloat>, camera: Camera) -> Point2<Pfloat> {
|
||||
let v = camera.pos.to_vec() - pos.to_vec();
|
||||
return pos + (v * parallax * Self::PARALLAX_STRENGTH);
|
||||
}
|
||||
|
||||
/// Returns post-parallax position in game coordinates.
|
||||
pub fn post_parallax_position(&self, camera: Camera) -> Point2<Pfloat> {
|
||||
return Self::post_parallax(self.parallax, self.pos, camera);
|
||||
}
|
||||
}
|
||||
|
||||
struct Game {
|
||||
input: InputStatus,
|
||||
last_update: Instant,
|
||||
|
|
|
@ -211,7 +211,8 @@ impl GPUState {
|
|||
let clip_sw = Point2::from((1.0, -1.0)) * game.camera.zoom;
|
||||
|
||||
for s in game.sprites() {
|
||||
let pos = s.post_parallax_position(game.camera) - game.camera.pos.to_vec();
|
||||
// Parallax is computed here, so we can check if this sprite is visible.
|
||||
let pos = (s.pos - game.camera.pos.to_vec()) / s.parallax;
|
||||
let texture = self.texture_array.get_texture(&s.name[..]);
|
||||
|
||||
// Game dimensions of this sprite post-scale.
|
||||
|
@ -263,17 +264,16 @@ impl GPUState {
|
|||
///
|
||||
/// This is only called inside self.render()
|
||||
fn make_starfield_instances(&self, game: &Game) -> Vec<StarfieldInstance> {
|
||||
let mut instances = Vec::new();
|
||||
for s in &game.system.starfield {
|
||||
// TODO: minimize operations here
|
||||
//let pos = Sprite::post_parallax(s.parallax, s.pos * 500.0, game.camera)
|
||||
// - game.camera.pos.to_vec();
|
||||
instances.push(StarfieldInstance {
|
||||
let instances: Vec<StarfieldInstance> = game
|
||||
.system
|
||||
.starfield
|
||||
.iter()
|
||||
.map(|s| StarfieldInstance {
|
||||
position: s.pos.into(),
|
||||
parallax: s.parallax,
|
||||
height: 2.0,
|
||||
});
|
||||
}
|
||||
height: s.height,
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Enforce starfield limit
|
||||
if instances.len() as u64 > Self::STARFIELD_INSTANCE_LIMIT {
|
||||
|
@ -326,7 +326,7 @@ impl GPUState {
|
|||
camera_zoom: game.camera.zoom,
|
||||
window_aspect: self.window_aspect,
|
||||
starfield_texture: 1,
|
||||
starfield_tile_size: 1000.0,
|
||||
starfield_tile_size: 80000.0,
|
||||
padding: Default::default(),
|
||||
}]),
|
||||
);
|
||||
|
|
|
@ -42,9 +42,9 @@ fn vertex_shader_main(
|
|||
global.camera_position
|
||||
- (
|
||||
fmod(
|
||||
global.camera_position + global.starfield_tile_size/2.0,
|
||||
global.camera_position + global.starfield_tile_size / 2.0,
|
||||
global.starfield_tile_size
|
||||
) - global.starfield_tile_size/2.0
|
||||
) - global.starfield_tile_size / 2.0
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -60,18 +60,16 @@ fn vertex_shader_main(
|
|||
// (Note that instance position is in a different
|
||||
// coordinate system than usual)
|
||||
let camera_pos = (instance.position + tile_center) - global.camera_position;
|
||||
let parallax_vector = -camera_pos * instance.parallax * 0.1;
|
||||
|
||||
// Translate
|
||||
pos = pos + (
|
||||
// Don't forget to correct distance for screen aspect ratio too!
|
||||
// The minus in "minus parallax_vector" is important.
|
||||
((camera_pos + parallax_vector) / global.camera_zoom)
|
||||
(camera_pos / (global.camera_zoom * instance.parallax))
|
||||
/ vec2<f32>(global.window_aspect, 1.0)
|
||||
);
|
||||
|
||||
var out: VertexOutput;
|
||||
out.position = vec4<f32>(pos, 0.0, 1.0);
|
||||
out.position = vec4<f32>(pos, 0.0, 1.0) * instance.parallax;
|
||||
out.texture_coords = vertex.texture_coords;
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ impl Spriteable for Ship {
|
|||
name: self.kind.sprite().to_owned(),
|
||||
angle: self.body.angle,
|
||||
scale: 1.0,
|
||||
parallax: 0.0,
|
||||
parallax: 1.0,
|
||||
height: self.kind.height(),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ pub struct StarfieldStar {
|
|||
// These are relative to the center of a starfield tile.
|
||||
pub pos: Point2<Pfloat>,
|
||||
pub parallax: Pfloat,
|
||||
pub height: Pfloat,
|
||||
}
|
||||
|
||||
pub struct System {
|
||||
|
@ -22,13 +23,14 @@ impl System {
|
|||
let mut rng = rand::thread_rng();
|
||||
let mut s = System {
|
||||
bodies: Vec::new(),
|
||||
starfield: (0..500)
|
||||
starfield: (0..1000)
|
||||
.map(|_| StarfieldStar {
|
||||
pos: Point2 {
|
||||
x: rng.gen_range(-500.0..500.0),
|
||||
y: rng.gen_range(-500.0..500.0),
|
||||
x: rng.gen_range(-40000.0..40000.0),
|
||||
y: rng.gen_range(-40000.0..40000.0),
|
||||
},
|
||||
parallax: rng.gen_range(10.0..11.0),
|
||||
parallax: rng.gen_range(100.0..150.0),
|
||||
height: rng.gen_range(1.0..2.0),
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
|
@ -36,19 +38,19 @@ impl System {
|
|||
s.bodies.push(Doodad {
|
||||
pos: (0.0, 0.0).into(),
|
||||
sprite: "a0".to_owned(),
|
||||
parallax: 3.0,
|
||||
parallax: 4.0,
|
||||
height: 80.0,
|
||||
});
|
||||
|
||||
s.bodies.push(Doodad {
|
||||
pos: Polar {
|
||||
center: (0.0, 0.0).into(),
|
||||
radius: 100.0,
|
||||
radius: 200.0,
|
||||
angle: Deg { 0: 31.0 },
|
||||
}
|
||||
.to_cartesian(),
|
||||
sprite: "earth".to_owned(),
|
||||
parallax: 1.0,
|
||||
parallax: 2.0,
|
||||
height: 120.0,
|
||||
});
|
||||
|
||||
|
@ -60,7 +62,7 @@ impl System {
|
|||
}
|
||||
.to_cartesian(),
|
||||
sprite: "small".to_owned(),
|
||||
parallax: -1.0,
|
||||
parallax: 0.5,
|
||||
height: 50.0,
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue