gamebridge: Twitch Control #2

Merged
cadey merged 29 commits from gamebridge into master 2020-05-11 22:40:05 +00:00
2 changed files with 100 additions and 2 deletions
Showing only changes of commit cafe38aae6 - Show all commits

View File

@ -20,6 +20,7 @@ pub(crate) struct State {
controller: [u8; 4],
last_got: Box<Instant>,
ok: bool,
frame: u64,
}
pub(crate) type MTState = Arc<RwLock<State>>;
@ -36,6 +37,7 @@ fn main() -> Result<()> {
controller: [0; 4],
last_got: Box::new(Instant::now()),
ok: true,
frame: 0,
};
Arc::new(RwLock::new(st))
@ -48,6 +50,10 @@ fn main() -> Result<()> {
spawn(move || twitch::run(st));
}
const LERP_TIME: f64 = 1.0; // 15 frames to lerp stick positions down to 0
let mut xmax_frame: u64 = 0;
let mut ymax_frame: u64 = 0;
loop {
let mut data = [0; 3];
debug!("waiting for vblank");
@ -58,9 +64,56 @@ fn main() -> Result<()> {
match str {
"OK\n" => {
let mut data = st.write().unwrap();
data.frame += 1;
let mut stickx = data.controller[2] as i8;
let mut sticky = data.controller[3] as i8;
let dist = stick_distance(stickx, sticky);
if dist <= 10 {
stickx = 0;
sticky = 0;
xmax_frame = 0;
ymax_frame = 0;
}
stickx = match stickx {
0 => stickx,
127 => {
xmax_frame = data.frame;
stickx - 10
},
-128 => {
xmax_frame = data.frame;
stickx + 10
},
_ => {
let t = (data.frame - xmax_frame) as f64 / (LERP_TIME as f64);
lerp(stickx, 0, t)
},
};
sticky = match stickx {
0 => sticky,
127 => {
ymax_frame = data.frame;
sticky - 10
},
-128 => {
ymax_frame = data.frame;
sticky + 10
},
_ => {
let t = (data.frame - ymax_frame) as f64 / (LERP_TIME as f64);
lerp(sticky, 0, t)
},
};
input.write(&data.controller)?;
data.controller[0] = 0;
data.controller[1] = 0;
data.controller[2] = stickx as u8;
data.controller[3] = sticky as u8;
}
"BYE" => {
warn!("asked to exit by the game");
@ -73,3 +126,42 @@ fn main() -> Result<()> {
};
}
}
fn lerp(start: i8, end: i8, t: f64) -> i8 {
(start as f64 * (1.0 - t) + (end as f64) * t) as i8
}
fn stick_distance(x: i8, y: i8) -> i8 {
let x = (x as f64).powi(2);
let y = (y as f64).powi(2);
(x + y).sqrt() as i8
}
#[cfg(test)]
mod test {
#[test]
fn lerp_scale() {
for case in [(0.1, 10), (0.5, 31)].iter() {
let t = case.0;
let start = 127.0 * t;
assert_eq!(crate::lerp(start as i8, 0, t), case.1);
}
}
#[test]
fn stick_distance() {
for case in [
(0, 0, 0),
(127, 0, 127),
(64, 64, 90),
(-64, 64, 90),
(-64, -64, 90),
]
.iter()
{
let x = case.0;
let y = case.1;
assert_eq!(crate::stick_distance(x, y), case.2);
}
}
}

View File

@ -70,8 +70,6 @@ async fn run_loop(
}
wait_and_join(&mut control, &mut dispatcher, channels).await;
let mut stickx: i8 = 0;
let mut sticky: i8 = 0;
loop {
tokio::select! {
@ -84,6 +82,14 @@ async fn run_loop(
Some(msg) = pmsg.next() => {
let mut hi = HiButtons::NONE;
let mut lo = LoButtons::NONE;
let mut stickx: i8 = 0;
let mut sticky: i8 = 0;
{
let data = st.read().unwrap();
stickx = data.controller[2] as i8;
sticky = data.controller[3] as i8;
}
let mut data = msg.data.to_string();
let data = data.to_ascii_lowercase();