Added basic parallax
parent
6ad23b4410
commit
c0db69bd76
|
@ -5,6 +5,7 @@ use crate::{physics::Pfloat, Sprite, Spriteable};
|
||||||
pub struct Doodad {
|
pub struct Doodad {
|
||||||
pub sprite: String,
|
pub sprite: String,
|
||||||
pub pos: Point2<Pfloat>,
|
pub pos: Point2<Pfloat>,
|
||||||
|
pub parallax: Pfloat,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Spriteable for Doodad {
|
impl Spriteable for Doodad {
|
||||||
|
@ -14,6 +15,7 @@ impl Spriteable for Doodad {
|
||||||
name: self.sprite.clone(),
|
name: self.sprite.clone(),
|
||||||
angle: Deg { 0: 0.0 },
|
angle: Deg { 0: 0.0 },
|
||||||
scale: 1.0,
|
scale: 1.0,
|
||||||
|
parallax: self.parallax,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
29
src/main.rs
29
src/main.rs
|
@ -1,5 +1,5 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use cgmath::{Deg, Point2};
|
use cgmath::{Deg, EuclideanSpace, Point2};
|
||||||
use winit::{
|
use winit::{
|
||||||
event::{
|
event::{
|
||||||
ElementState, Event, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase,
|
ElementState, Event, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase,
|
||||||
|
@ -51,6 +51,22 @@ struct Sprite {
|
||||||
// This sprite's rotation
|
// This sprite's rotation
|
||||||
// (relative to north, measured ccw)
|
// (relative to north, measured ccw)
|
||||||
angle: Deg<Pfloat>,
|
angle: Deg<Pfloat>,
|
||||||
|
|
||||||
|
// Parallax factor.
|
||||||
|
// More positive => farther away
|
||||||
|
// More negative => closer
|
||||||
|
// Zero: no parallax.
|
||||||
|
parallax: Pfloat,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sprite {
|
||||||
|
const PARALLAX_STRENGTH: Pfloat = 0.1;
|
||||||
|
|
||||||
|
// Returns post-parallax position in game coordinates.
|
||||||
|
pub fn post_parallax_position(&self, camera: Camera) -> Point2<f32> {
|
||||||
|
let v = camera.pos.to_vec() - self.pos.to_vec();
|
||||||
|
return self.pos + (v * self.parallax * Self::PARALLAX_STRENGTH);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Game {
|
struct Game {
|
||||||
|
@ -95,11 +111,11 @@ impl Game {
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.input.key_right {
|
if self.input.key_right {
|
||||||
self.player.body.rot(Deg { 0: 15.0 } * t);
|
self.player.body.rot(Deg { 0: 35.0 } * t);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.input.key_left {
|
if self.input.key_left {
|
||||||
self.player.body.rot(Deg { 0: -15.0 } * t);
|
self.player.body.rot(Deg { 0: -35.0 } * t);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.input.v_scroll != 0.0 {
|
if self.input.v_scroll != 0.0 {
|
||||||
|
@ -119,6 +135,13 @@ impl Game {
|
||||||
sprites.append(&mut self.system.sprites());
|
sprites.append(&mut self.system.sprites());
|
||||||
sprites.push(self.player.sprite());
|
sprites.push(self.player.sprite());
|
||||||
|
|
||||||
|
// Make sure sprites are drawn in the correct order
|
||||||
|
// (note the reversed a, b in the comparator)
|
||||||
|
//
|
||||||
|
// TODO: use a gpu depth buffer with parallax as z-coordinate?
|
||||||
|
// Might be overkill.
|
||||||
|
sprites.sort_by(|a, b| b.parallax.total_cmp(&a.parallax));
|
||||||
|
|
||||||
return sprites;
|
return sprites;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,13 +260,15 @@ impl GPUState {
|
||||||
|
|
||||||
let mut instances: Vec<SpriteInstance> = Vec::new();
|
let mut instances: Vec<SpriteInstance> = Vec::new();
|
||||||
for s in sprites {
|
for s in sprites {
|
||||||
let pos = s.pos - camera.pos.to_vec();
|
let pos = s.post_parallax_position(camera) - camera.pos.to_vec();
|
||||||
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.
|
||||||
// We really need height / 2 to check if we're on the screen,
|
//
|
||||||
// but we omit the division so we get a small "margin"
|
// We only need height / 2 to check if we're on the screen,
|
||||||
// and so we can re-use this value.
|
// but we omit the division.
|
||||||
|
// This gives us a small margin, and lets us re-use the value
|
||||||
|
// without an extra multiply.
|
||||||
let height = texture.height * s.scale;
|
let height = texture.height * s.scale;
|
||||||
let width = height * texture.aspect;
|
let width = height * texture.aspect;
|
||||||
|
|
||||||
|
@ -277,7 +279,6 @@ impl GPUState {
|
||||||
|| pos.x > clip_sw.x + width
|
|| pos.x > clip_sw.x + width
|
||||||
|| pos.y < clip_sw.y - height
|
|| pos.y < clip_sw.y - height
|
||||||
{
|
{
|
||||||
println!("skip {}", s.name);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub struct TextureArray {
|
||||||
texture_indices: HashMap<String, u32>,
|
texture_indices: HashMap<String, u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const TEX: &[&str] = &["error", "red", "gypsum", "earth", "a0"];
|
const TEX: &[&str] = &["error", "small", "gypsum", "earth", "a0"];
|
||||||
|
|
||||||
pub struct Texture {
|
pub struct Texture {
|
||||||
pub index: u32, // Index in texture array
|
pub index: u32, // Index in texture array
|
||||||
|
|
|
@ -35,6 +35,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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ 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,
|
||||||
});
|
});
|
||||||
|
|
||||||
s.bodies.push(Doodad {
|
s.bodies.push(Doodad {
|
||||||
|
@ -22,11 +23,18 @@ impl System {
|
||||||
}
|
}
|
||||||
.to_cartesian(),
|
.to_cartesian(),
|
||||||
sprite: "earth".to_owned(),
|
sprite: "earth".to_owned(),
|
||||||
|
parallax: 1.0,
|
||||||
});
|
});
|
||||||
|
|
||||||
s.bodies.push(Doodad {
|
s.bodies.push(Doodad {
|
||||||
pos: (1000.0, 1000.0).into(),
|
pos: Polar {
|
||||||
|
center: (0.0, 0.0).into(),
|
||||||
|
radius: 200.0,
|
||||||
|
angle: Deg { 0: 270.0 },
|
||||||
|
}
|
||||||
|
.to_cartesian(),
|
||||||
sprite: "small".to_owned(),
|
sprite: "small".to_owned(),
|
||||||
|
parallax: -1.0,
|
||||||
});
|
});
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
|
|
Loading…
Reference in New Issue