interpolator
This commit is contained in:
parent
74fa53a30a
commit
c64d698e04
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1,2 @@
|
|||
[toolchain]
|
||||
channel = "nightly"
|
|
@ -0,0 +1,42 @@
|
|||
use std::time::{Duration, Instant};
|
||||
use skunk2d::Vec2;
|
||||
|
||||
pub struct Interpolator {
|
||||
start: Instant,
|
||||
end: Instant,
|
||||
length: Duration
|
||||
}
|
||||
|
||||
impl Interpolator {
|
||||
pub fn new(start: Instant, length: Duration) -> Self {
|
||||
Interpolator {
|
||||
start,
|
||||
end: start + length,
|
||||
length
|
||||
}
|
||||
}
|
||||
|
||||
//interpolator that will always return 1.0f64
|
||||
pub fn fake() -> Self {
|
||||
//ugly <_<
|
||||
let meh = Instant::now() - Duration::from_secs(100);
|
||||
Interpolator::new(meh, Duration::from_secs(1))
|
||||
}
|
||||
|
||||
pub fn get(&self, pos: Instant) -> f64 {
|
||||
(pos - self.start).div_duration_f64(self.length).max(0f64).min(1f64)
|
||||
}
|
||||
|
||||
pub fn apply_vec2(&self, pos: Instant, v1: Vec2<i32>, v2: Vec2<i32>) -> Vec2<i32> {
|
||||
let p = self.get(pos);
|
||||
let delta = v2 - v1;
|
||||
if delta.x.abs() > 100 || delta.y.abs() > 100 {
|
||||
v2
|
||||
} else {
|
||||
Vec2 {
|
||||
x: (v1.x as f64 + delta.x as f64 * p).round() as i32,
|
||||
y: (v1.y as f64 + delta.y as f64 * p).round() as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
20
src/main.rs
20
src/main.rs
|
@ -1,5 +1,8 @@
|
|||
#![feature(div_duration)]
|
||||
|
||||
mod unit_kind;
|
||||
mod unit;
|
||||
mod interpolator;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
@ -32,20 +35,22 @@ impl Game {
|
|||
pub fn tick(&mut self, window_state: &mut WindowState) {
|
||||
window_state.log(format!("tick: {}", self.current_tick).as_str());
|
||||
|
||||
self.unit.borrow_mut().pos.y = self.current_tick % self.map.size().y;
|
||||
self.unit.borrow_mut().set_pos(Vec2{x: 5, y: self.current_tick % self.map.size().y});
|
||||
}
|
||||
}
|
||||
|
||||
impl skunk2d::Game for Game {
|
||||
fn new(window_state: &mut WindowState) -> Self {
|
||||
setup_palette(window_state);
|
||||
let tileset = Tileset::load("assets/hex2.gif", Vec2{x: 2, y: 1});
|
||||
let kind = UnitKind::new("bob");
|
||||
window_state.scramble_palette();
|
||||
let tick_duration = Duration::from_secs(1) / 10;
|
||||
let tileset = Tileset::load("assets/hex3.gif", Vec2{x: 1, y: 1});
|
||||
let kind = UnitKind::new("tank", 1, tick_duration);
|
||||
Game {
|
||||
map: HexMap::new(Vec2{x: 11, y: 11}, tileset, Vec2{ x: 23, y: 13 }),
|
||||
map: HexMap::new(Vec2{x: 26, y: 22}, tileset, Vec2{ x: 72, y: 24 }),
|
||||
unit: kind.spawn(Vec2{x: 5, y: 5}),
|
||||
last_tick: Instant::now(),
|
||||
tick_duration: Duration::from_secs(1) / 10,
|
||||
tick_duration,
|
||||
current_tick: 0
|
||||
}
|
||||
}
|
||||
|
@ -62,12 +67,13 @@ impl skunk2d::Game for Game {
|
|||
}
|
||||
|
||||
fn draw(&self, target: &mut Image) {
|
||||
let now = Instant::now();
|
||||
target.clear();
|
||||
target.draw_hexmap(Vec2::zero(), &self.map);
|
||||
self.unit.borrow().draw(target, &self.map);
|
||||
self.unit.borrow().draw(target, &self.map, now);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
run::<Game>(640, 360);
|
||||
run::<Game>(1920, 1080);
|
||||
}
|
||||
|
|
24
src/unit.rs
24
src/unit.rs
|
@ -1,14 +1,32 @@
|
|||
use std::rc::Rc;
|
||||
use std::time::Instant;
|
||||
use skunk2d::{HexMap, Image, Vec2};
|
||||
use crate::interpolator::Interpolator;
|
||||
use crate::unit_kind::UnitKind;
|
||||
|
||||
pub struct Unit {
|
||||
pub kind: Rc<UnitKind>,
|
||||
pub pos: Vec2<i32>
|
||||
pub pos: Vec2<i32>,
|
||||
pub interpolator: Interpolator,
|
||||
pub old_pos: Vec2<i32>
|
||||
}
|
||||
|
||||
impl Unit {
|
||||
pub fn draw(&self, target: &mut Image, map: &HexMap) {
|
||||
target.draw_image( map.coord_to_pixel(self.pos), &self.kind.sprite);
|
||||
pub fn draw(&self, target: &mut Image, map: &HexMap, time: Instant) {
|
||||
let old_pos = map.coord_to_pixel(self.old_pos);
|
||||
let new_pos = map.coord_to_pixel(self.pos);
|
||||
let pos = self.interpolator.apply_vec2(time, old_pos, new_pos);
|
||||
//todo: don't hardcode offset :P
|
||||
target.draw_image( pos + Vec2{x: 0, y: -24}, &self.kind.sprite);
|
||||
}
|
||||
|
||||
pub fn set_pos(&mut self, pos: Vec2<i32>) {
|
||||
self.interpolator = Interpolator::new(Instant::now(), self.kind.movement_duration);
|
||||
self.old_pos = self.pos;
|
||||
self.pos = pos;
|
||||
}
|
||||
|
||||
pub fn add_pos(&mut self, pos: Vec2<i32>) {
|
||||
self.set_pos(self.pos + pos);
|
||||
}
|
||||
}
|
|
@ -1,25 +1,34 @@
|
|||
use std::cell::RefCell;
|
||||
use std::ops::Mul;
|
||||
use std::rc::Rc;
|
||||
use std::time::Duration;
|
||||
use skunk2d::{Image, Vec2};
|
||||
use crate::interpolator::Interpolator;
|
||||
use crate::unit::Unit;
|
||||
|
||||
pub struct UnitKind {
|
||||
pub sprite: Rc<Image>,
|
||||
pub name: String
|
||||
pub name: String,
|
||||
pub speed: i32,
|
||||
pub movement_duration: Duration
|
||||
}
|
||||
|
||||
impl UnitKind {
|
||||
pub fn new(name: &str) -> Rc<Self> {
|
||||
pub fn new(name: &str, speed: i32, tick_duration: Duration) -> Rc<Self> {
|
||||
UnitKind {
|
||||
sprite: Image::load(format!("assets/units/{}.gif", name).as_str()),
|
||||
name: name.into()
|
||||
name: name.into(),
|
||||
speed,
|
||||
movement_duration: tick_duration.mul(speed as u32)
|
||||
}.into()
|
||||
}
|
||||
|
||||
pub fn spawn(self: Rc<Self>, pos: Vec2<i32>) -> Rc<RefCell<Unit>> {
|
||||
RefCell::new(Unit {
|
||||
kind: self,
|
||||
pos
|
||||
pos,
|
||||
interpolator: Interpolator::fake(),
|
||||
old_pos: pos
|
||||
}).into()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue