input.rs (4919B)
1 use std::{collections::HashMap, time::Duration}; 2 3 use common::game::{ 4 ActionKind, Player, 5 book::{Bookshelf, BookshelfId, FloorBook, Slot, SlotAddress}, 6 state::GameState, 7 }; 8 use macroquad::prelude::*; 9 10 use crate::render::Camera; 11 12 pub(crate) fn handle_movement_input(local_player: &Player, dt: &Duration) -> Option<ActionKind> { 13 let velocity_x = if is_key_down(KeyCode::A) || is_key_down(KeyCode::Left) { 14 -GameState::MAX_PLAYER_SPEED_PX_S 15 } else if is_key_down(KeyCode::D) || is_key_down(KeyCode::Right) { 16 GameState::MAX_PLAYER_SPEED_PX_S 17 } else { 18 0. 19 }; 20 let velocity_y = if is_key_down(KeyCode::W) || is_key_down(KeyCode::Up) { 21 -GameState::MAX_PLAYER_SPEED_PX_S 22 } else if is_key_down(KeyCode::S) || is_key_down(KeyCode::Down) { 23 GameState::MAX_PLAYER_SPEED_PX_S 24 } else { 25 0. 26 }; 27 if velocity_x != 0. || velocity_y != 0. { 28 Some(ActionKind::Move { 29 new_position: local_player.position() 30 + Vec2::new(velocity_x, velocity_y) * dt.as_secs_f32(), 31 }) 32 } else { 33 None 34 } 35 } 36 37 pub(crate) fn handle_pick_up_book_input( 38 local_player: &Player, 39 camera: &Camera, 40 floor_books: &[FloorBook], 41 ) -> Option<ActionKind> { 42 if is_mouse_button_pressed(MouseButton::Left) 43 && let Some(moused_floor_book) = floor_books.iter().find(|fb| { 44 fb.collider() 45 .rect() 46 .offset(fb.position()) 47 .offset(-camera.position()) 48 .contains({ 49 let (x, y) = mouse_position(); 50 Vec2::new(x, y) 51 }) 52 && fb.position().distance(local_player.position()) 53 <= GameState::MAX_PLAYER_ACTION_RADIUS 54 }) 55 { 56 return Some(ActionKind::PickUpBook { 57 book_id: moused_floor_book.id(), 58 }); 59 } 60 None 61 } 62 63 pub(crate) fn handle_drop_book_input( 64 local_player: &Player, 65 selected_book_index: usize, 66 ) -> Option<ActionKind> { 67 if is_key_pressed(KeyCode::Q) 68 && let Some(book_id) = local_player.books().get(selected_book_index) 69 { 70 Some(ActionKind::DropBook { book_id: *book_id }) 71 } else { 72 None 73 } 74 } 75 76 pub(crate) fn get_bookshelf_mouse_address( 77 camera: &Camera, 78 bookshelves: &HashMap<BookshelfId, Bookshelf>, 79 ) -> Option<SlotAddress> { 80 let (mouse_x, mouse_y) = mouse_position(); 81 let mouse = Vec2::new(mouse_x, mouse_y); 82 for (bookshelf_id, bookshelf) in bookshelves { 83 let bookshelf_collider = bookshelf.rect().offset(-camera.position()); 84 if bookshelf_collider.contains(mouse) { 85 let shelf_index = bookshelf.shelf_count() 86 - ((mouse.y - bookshelf_collider.y - Bookshelf::FRAME_THICKNESS) 87 / (Bookshelf::BOOK_HEIGHT + Bookshelf::SHELF_THICKNESS)) 88 as usize 89 - 1; 90 let position = ((mouse.x - bookshelf_collider.x - Bookshelf::FRAME_THICKNESS) 91 / Bookshelf::BOOK_WIDTH) as usize; 92 return Some(SlotAddress::new(*bookshelf_id, shelf_index, position)); 93 } 94 } 95 None 96 } 97 98 pub(crate) fn handle_put_book_on_shelf_input( 99 bookshelves: &HashMap<BookshelfId, Bookshelf>, 100 camera: &Camera, 101 local_player: &Player, 102 selected_book_index: usize, 103 ) -> Option<ActionKind> { 104 if is_mouse_button_pressed(MouseButton::Left) 105 && let Some(slot_address) = get_bookshelf_mouse_address(camera, bookshelves) 106 && let Some(book_id) = local_player.books().get(selected_book_index) 107 && let Some(shelf) = bookshelves.get(&slot_address.bookshelf_id()) 108 && let Some(Slot::Empty) = shelf.get_slot(&slot_address) 109 // TODO Base this on the position of the slot, not the click 110 && local_player.position().distance({ 111 let (x, y) = mouse_position(); 112 Vec2::new(x, y) + camera.position() 113 }) <= GameState::MAX_PLAYER_ACTION_RADIUS 114 { 115 return Some(ActionKind::PutBookOnShelf { 116 book_id: *book_id, 117 slot_address, 118 }); 119 } 120 None 121 } 122 123 pub(crate) fn handle_take_book_off_shelf_input( 124 bookshelves: &HashMap<BookshelfId, Bookshelf>, 125 camera: &Camera, 126 local_player: &Player, 127 ) -> Option<ActionKind> { 128 if is_mouse_button_pressed(MouseButton::Left) 129 && let Some(slot_address) = get_bookshelf_mouse_address(camera, bookshelves) 130 && let Some(shelf) = bookshelves.get(&slot_address.bookshelf_id()) 131 && let Some(Slot::Book { .. }) = shelf.get_slot(&slot_address) 132 // TODO Base this on the position of the slot, not the click 133 && local_player.position().distance({ 134 let (x, y) = mouse_position(); 135 Vec2::new(x, y) + camera.position() 136 }) <= GameState::MAX_PLAYER_ACTION_RADIUS 137 { 138 return Some(ActionKind::TakeBookOffShelf { slot_address }); 139 } 140 None 141 }