use crate::{display::ColorScheme, state::{CommanderDamage, Game, MainScreenItem, Screen, SettingScreenEntry, SettingScreenItem, SystemState}}; const CMDDMGLIST: [MainScreenItem;6] = [ MainScreenItem::Dmg1, MainScreenItem::Dmg2, MainScreenItem::Dmg3, MainScreenItem::Dmg4, MainScreenItem::Dmg5, MainScreenItem::Dmg6, ]; pub fn get_touch_action(x: f32, y: f32, gesture: u8, ctx: &mut SystemState) -> () { let x = x - 120.; let y = -(y - 120.); let touch_rad = (x*x)+(y*y); let angle; let next_state; if (gesture == 0x3) | (gesture == 0x4) { ctx.screen = match &ctx.screen { Screen::Main(_) => Screen::Settings(SettingScreenItem { entry: SettingScreenEntry::NewGame, inner: false , prev: None}), Screen::Settings(_) => Screen::Main(MainScreenItem::Life), }; return; } match &ctx.screen { Screen::Main(selected) => { let mut bottom_selectable_list: [Option;5] = [const {None};5]; let mut pos = 0; if ctx.settings.show_cmd_tax { bottom_selectable_list[pos] = Some(crate::state::MainScreenItem::Tax); pos += 1; } if ctx.settings.show_energy { bottom_selectable_list[pos] = Some(crate::state::MainScreenItem::Energy); pos+=1; }; if ctx.settings.show_experience { bottom_selectable_list[pos] = Some(crate::state::MainScreenItem::Experience); pos+=1; }; if ctx.settings.show_tickets { bottom_selectable_list[pos] = Some(crate::state::MainScreenItem::Tickets); pos+=1; }; if ctx.settings.show_infect { bottom_selectable_list[pos] = Some(crate::state::MainScreenItem::Poison); }; let bottom_count = bottom_selectable_list.iter().fold(0, |acc, x| acc+x.is_some() as u8); if touch_rad > (70.*70.) { angle = atan2_norm(y, x)*90.; //ctx.game.life = angle as i32; //debug let top; let check_angles = if y >= 0. { if ctx.settings.opponenets == 0 { return; } top = true; ctx.positions.get_top_list(ctx.settings.opponenets) } else { if bottom_count == 0 { return; } top = false; ctx.positions.get_bottom_list(bottom_count) }; let touch_item = match check_angles.iter().position(|x| (x.angle.to_degrees()-angle).abs()<15.) { Some(loc) => loc, None => return, }; let sel_match = if top { Some(CMDDMGLIST.into_iter().nth(touch_item).unwrap_or(MainScreenItem::Dmg1)) } else { bottom_selectable_list[touch_item] }; if let Some(selected_item) = sel_match { if selected_item == *selected { next_state = Screen::Main(MainScreenItem::Life); } else { next_state = Screen::Main(selected_item); } } else { next_state = Screen::Main(MainScreenItem::Life); } } else { match selected { crate::state::MainScreenItem::Life => { let d = touch_inc_dec(y, gesture); ctx.game.life = ctx.game.life.saturating_add(d as i32); }, crate::state::MainScreenItem::Dmg1 => { cmd_dmg_w_swap(ctx, x, y, gesture, 0); }, crate::state::MainScreenItem::Dmg2 => { cmd_dmg_w_swap(ctx, x, y, gesture, 1); }, crate::state::MainScreenItem::Dmg3 => { cmd_dmg_w_swap(ctx, x, y, gesture, 2); }, crate::state::MainScreenItem::Dmg4 => { cmd_dmg_w_swap(ctx, x, y, gesture, 3); }, crate::state::MainScreenItem::Dmg5 => { cmd_dmg_w_swap(ctx, x, y, gesture, 4); }, crate::state::MainScreenItem::Dmg6 => { cmd_dmg_w_swap(ctx, x, y, gesture, 5); }, crate::state::MainScreenItem::Tax => { cmd_tax_w_swap(ctx, x, y, gesture); }, crate::state::MainScreenItem::Energy => { let d = touch_inc_dec(y, gesture); ctx.game.energy = ctx.game.energy.saturating_add_signed(d.into()); }, crate::state::MainScreenItem::Experience => { let d = touch_inc_dec(y, gesture); ctx.game.experience = ctx.game.experience.saturating_add_signed(d.into()); }, crate::state::MainScreenItem::Tickets => { let d = touch_inc_dec(y, gesture); ctx.game.tickets = ctx.game.tickets.saturating_add_signed(d.into()); }, crate::state::MainScreenItem::Poison => { let d = touch_inc_dec(y, gesture); ctx.game.infect = ctx.game.infect.saturating_add_signed(d.into()); }, }; next_state = ctx.screen; }; }, Screen::Settings(selected) => { if !selected.inner { if gesture == 0x01_u8 { next_state = Screen::Settings(SettingScreenItem { entry: selected.entry.prev(), inner: false, prev: selected.prev }); } else if gesture == 0x02_u8 { next_state = Screen::Settings(SettingScreenItem { entry: selected.entry.next(), inner: false, prev: selected.prev }); } else { if y > 55. { next_state = Screen::Settings(SettingScreenItem { entry: selected.entry.prev(), inner: false, prev: selected.prev}); } else if y < -55. { next_state = Screen::Settings(SettingScreenItem { entry: selected.entry.next(), inner: false, prev: selected.prev }); } else { let prev = match selected.entry { SettingScreenEntry::NewGame => None, SettingScreenEntry::Opponents => Some(ctx.settings.opponenets as u32), SettingScreenEntry::StartingLife => Some(ctx.settings.starting_life as u32), SettingScreenEntry::Colors => Some(Into::::into(ctx.settings.color_scheme) as u32), SettingScreenEntry::Brightness => Some(ctx.settings.brightness.into()), SettingScreenEntry::ShowTax => Some(ctx.settings.show_cmd_tax as u32), SettingScreenEntry::ShowEnergy => Some(ctx.settings.show_energy as u32), SettingScreenEntry::ShowExperience => Some(ctx.settings.show_experience as u32), SettingScreenEntry::ShowTickets => Some(ctx.settings.show_tickets as u32), SettingScreenEntry::ShowPoison => Some(ctx.settings.show_infect as u32), }; next_state = Screen::Settings(SettingScreenItem { entry: selected.entry, inner: true, prev: prev}); } } } else { if x < -75. { match selected.entry { SettingScreenEntry::NewGame => { ctx.game = Game { life: ctx.settings.starting_life, cmd_dmg: [CommanderDamage{main: 0, partner: 0, is_partner: false};6], cmd_tax: CommanderDamage { main: 0, partner: 0, is_partner: false }, infect: 0, energy: 0, experience: 0, tickets: 0, monarch: false, }; next_state = Screen::Main(MainScreenItem::Life); }, _ => { next_state = Screen::Settings(SettingScreenItem { entry: selected.entry, inner: false, prev: None }) } } } else if x > 75. { match selected.entry { SettingScreenEntry::NewGame => {}, SettingScreenEntry::Opponents => { ctx.settings.opponenets = selected.prev.unwrap_or(0) as u8; }, SettingScreenEntry::StartingLife => { ctx.settings.starting_life = selected.prev.unwrap_or(0) as i32; }, SettingScreenEntry::Colors => { ctx.settings.color_scheme =Into::::into(selected.prev.unwrap_or(0) as u8); }, SettingScreenEntry::Brightness => { ctx.settings.brightness = selected.prev.unwrap_or(0).into(); }, SettingScreenEntry::ShowTax => { ctx.settings.show_cmd_tax = selected.prev.unwrap_or_default() != 0; }, SettingScreenEntry::ShowEnergy => { ctx.settings.show_energy = selected.prev.unwrap_or_default() != 0; }, SettingScreenEntry::ShowExperience => { ctx.settings.show_experience = selected.prev.unwrap_or_default() != 0; }, SettingScreenEntry::ShowTickets => { ctx.settings.show_tickets = selected.prev.unwrap_or_default() != 0; }, SettingScreenEntry::ShowPoison => { ctx.settings.show_infect = selected.prev.unwrap_or_default() != 0; }, } next_state = Screen::Settings(SettingScreenItem { entry: selected.entry, inner: false, prev: None }) } else { match selected.entry { SettingScreenEntry::NewGame => { }, SettingScreenEntry::Opponents => { ctx.settings.opponenets = ctx.settings.opponenets.saturating_add_signed(touch_inc_dec(y, gesture)); }, SettingScreenEntry::StartingLife => { ctx.settings.starting_life = ctx.settings.starting_life.saturating_add(touch_inc_dec(y, gesture) as i32); }, SettingScreenEntry::Colors => { if y > 40. { ctx.settings.color_scheme = ctx.settings.color_scheme.dec(); } else if y < -40. { ctx.settings.color_scheme = ctx.settings.color_scheme.inc(); } }, SettingScreenEntry::Brightness => { let tmp = touch_inc_dec(y, gesture); if tmp > 0 { ctx.settings.brightness = ctx.settings.brightness.inc(); } else { ctx.settings.brightness = ctx.settings.brightness.dec(); } }, SettingScreenEntry::ShowTax => { let det = select_button(x, y, gesture); if let Some(i) = det { ctx.settings.show_cmd_tax = i; } }, SettingScreenEntry::ShowEnergy => { let det = select_button(x, y, gesture); if let Some(i) = det { ctx.settings.show_energy = i; } }, SettingScreenEntry::ShowExperience => { let det = select_button(x, y, gesture); if let Some(i) = det { ctx.settings.show_experience = i; } }, SettingScreenEntry::ShowTickets => { let det = select_button(x, y, gesture); if let Some(i) = det { ctx.settings.show_tickets = i; } }, SettingScreenEntry::ShowPoison => { let det = select_button(x, y, gesture); if let Some(i) = det { ctx.settings.show_infect = i; } }, } next_state = Screen::Settings(SettingScreenItem { entry: selected.entry, inner: selected.inner, prev: selected.prev }) } } } } ctx.screen = next_state; } /// Approximates `atan2(y,x)` normalized to the `[0, 4)` range with a maximum /// error of `0.1620` degrees. fn atan2_norm(lhs: f32, rhs: f32) -> f32 { const SIGN_MASK: u32 = 0x8000_0000; const B: f32 = 0.596_227; let y = lhs; let x = rhs; // Extract sign bits from floating point values let ux_s = SIGN_MASK & x.to_bits(); let uy_s = SIGN_MASK & y.to_bits(); // Determine quadrant offset let q = ((!ux_s & uy_s) >> 29 | ux_s >> 30) as f32; // Calculate arctangent in the first quadrant let bxy_a = (B * x * y).abs(); let n = bxy_a + y * y; let atan_1q = n / (x * x + bxy_a + n); // Translate it to the proper quadrant let uatan_2q = (ux_s ^ uy_s) | atan_1q.to_bits(); q + f32::from_bits(uatan_2q) } fn touch_inc_dec(y: f32, gesture: u8) -> i8 { if gesture == 0x05 { if y >= 0. { 1 } else { -1 } } else if gesture == 0x02 { 5 } else if gesture == 0x01 { -5 } else { 0 } } fn touch_left_right(x: f32, y: f32, gesture: u8) -> (i8, bool) { if x <= 0. { (touch_inc_dec(y, gesture), true) } else { (touch_inc_dec(y, gesture), false) } } fn cmd_dmg_calc(ctx: &mut SystemState, x: f32, y: f32, gesture: u8, pos: usize) { if ctx.game.cmd_dmg[pos].is_partner { let (d, left) = touch_left_right(x, y, gesture); if left { ctx.game.cmd_dmg[pos].main = ctx.game.cmd_dmg[pos].main.saturating_add_signed(d); } else { ctx.game.cmd_dmg[pos].partner = ctx.game.cmd_dmg[pos].partner.saturating_add_signed(d); } } else { let d = touch_inc_dec(y, gesture); ctx.game.cmd_dmg[pos].main = ctx.game.cmd_dmg[pos].main.saturating_add_signed(d); } } fn cmd_tax_calc(ctx: &mut SystemState, x: f32, y: f32, gesture: u8) { if ctx.game.cmd_tax.is_partner { let (mut d, left) = touch_left_right(x, y, gesture); if d >= 0 { d = 2; } else { d =-2; } if left { ctx.game.cmd_tax.main = ctx.game.cmd_tax.main.saturating_add_signed(d); } else { ctx.game.cmd_tax.partner = ctx.game.cmd_tax.partner.saturating_add_signed(d); } } else { let mut d = touch_inc_dec(y, gesture); if d >= 0 { d = 2; } else { d =-2; } ctx.game.cmd_tax.main = ctx.game.cmd_tax.main.saturating_add_signed(d); } } /// true is left selection false is right selection fn select_button(x: f32, y: f32, _gesture: u8) -> Option { if (y<60.) & (y>-60.) { if x<=0. { Some(true) } else { Some(false) } } else { None } } fn cmd_dmg_w_swap(ctx: &mut SystemState, x: f32, y: f32, gesture: u8, pos: usize) { if (x>-20.) & (x<20.) & (y< -30.)&(y>-50.) { ctx.game.cmd_dmg[pos].is_partner = !ctx.game.cmd_dmg[pos].is_partner; } else { cmd_dmg_calc(ctx, x, y, gesture, pos); } } fn cmd_tax_w_swap(ctx: &mut SystemState, x: f32, y: f32, gesture: u8) { if (x>-20.) & (x<20.) & (y< -30.)&(y>-50.) { ctx.game.cmd_tax.is_partner = !ctx.game.cmd_tax.is_partner; } else { cmd_tax_calc(ctx, x, y, gesture); } }