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