Using items
This commit is contained in:
parent
838dd7749e
commit
3a31fab361
104
src/main.rs
104
src/main.rs
@ -47,6 +47,7 @@ const MSG_X: i32 = BAR_WIDTH + 2;
|
||||
const MSG_WIDTH: i32 = SCREEN_WIDTH - BAR_WIDTH - 2;
|
||||
const MSG_HEIGHT: usize = PANEL_HEIGHT as usize - 1;
|
||||
const MAX_ROOM_ITEMS: i32 = 2;
|
||||
const INVENTORY_WIDTH: i32 = 50;
|
||||
|
||||
struct Tcod {
|
||||
root: Root,
|
||||
@ -68,6 +69,7 @@ struct Object {
|
||||
alive: bool,
|
||||
fighter: Option<Fighter>,
|
||||
ai: Option<Ai>,
|
||||
item: Option<Item>,
|
||||
}
|
||||
|
||||
impl Object {
|
||||
@ -82,6 +84,7 @@ impl Object {
|
||||
alive: false,
|
||||
fighter: None,
|
||||
ai: None,
|
||||
item: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -316,6 +319,27 @@ fn handle_keys(tcod: &mut Tcod, game: &mut Game, objects: &mut Vec<Object>) -> P
|
||||
TookTurn
|
||||
}
|
||||
|
||||
(Key { code: Text, .. }, "g", true) => {
|
||||
// Pick up an item
|
||||
let item_id = objects
|
||||
.iter()
|
||||
.position(|object| object.pos() == objects[PLAYER].pos() && object.item.is_some());
|
||||
if let Some(item_id) = item_id {
|
||||
pick_item_up(item_id, game, objects);
|
||||
}
|
||||
DidntTakeTurn
|
||||
}
|
||||
|
||||
(Key { code: Text, .. }, "i", true) => {
|
||||
// Show the inventory
|
||||
inventory_menu(
|
||||
&game.inventory,
|
||||
"Press the key next to an item to use it, or any other to cancel.\n",
|
||||
&mut tcod.root,
|
||||
);
|
||||
TookTurn
|
||||
}
|
||||
|
||||
_ => DidntTakeTurn,
|
||||
}
|
||||
}
|
||||
@ -438,6 +462,7 @@ fn place_objects(room: Rect, map: &Map, objects: &mut Vec<Object>) {
|
||||
if !is_blocked(x, y, map, objects) {
|
||||
// Create a healing potion
|
||||
let mut object = Object::new(x, y, '!', "healing potion", VIOLET, false);
|
||||
object.item = Some(Item::Heal);
|
||||
objects.push(object);
|
||||
}
|
||||
}
|
||||
@ -546,6 +571,85 @@ fn monster_death(monster: &mut Object, game: &mut Game) {
|
||||
monster.name = format!("remains of {}", monster.name);
|
||||
}
|
||||
|
||||
fn menu<T: AsRef<str>>(header: &str, options: &[T], width: i32, root: &mut Root) -> Option<usize> {
|
||||
// Limit the amount of menu options
|
||||
assert!(
|
||||
options.len() <= 26,
|
||||
"Cannot have a menu with more than 26 options."
|
||||
);
|
||||
|
||||
// Calculate total height for the header (after auto-wrap) and one line per option
|
||||
let header_height = root.get_height_rect(0, 0, width, SCREEN_HEIGHT, header);
|
||||
let height = options.len() as i32 + header_height;
|
||||
|
||||
// Create an off-screen console that represents the menu's window
|
||||
let mut window = Offscreen::new(width, height);
|
||||
|
||||
// Print the header, with auto-wrap
|
||||
window.set_default_foreground(WHITE);
|
||||
window.print_rect_ex(
|
||||
0,
|
||||
0,
|
||||
width,
|
||||
height,
|
||||
BackgroundFlag::None,
|
||||
TextAlignment::Left,
|
||||
header,
|
||||
);
|
||||
|
||||
// Print all the options
|
||||
for (index, option_text) in options.iter().enumerate() {
|
||||
let menu_letter = (b'a' + index as u8) as char;
|
||||
let text = format!("({}) {}", menu_letter, option_text.as_ref());
|
||||
window.print_ex(
|
||||
0,
|
||||
header_height + index as i32,
|
||||
BackgroundFlag::None,
|
||||
TextAlignment::Left,
|
||||
text,
|
||||
);
|
||||
}
|
||||
|
||||
// Blit the contents of the menu window to the root console
|
||||
let x = SCREEN_WIDTH / 2 - width / 2;
|
||||
let y = SCREEN_HEIGHT / 2 - height / 2;
|
||||
blit(&window, (0, 0), (width, height), root, (x, y), 1.0, 0.7);
|
||||
|
||||
// Present the root console to the player and wait for a key-press
|
||||
root.flush();
|
||||
let key = root.wait_for_keypress(true);
|
||||
|
||||
// Convert the ASCII code to an index; if it corresponds to an option, return it
|
||||
if key.printable.is_alphabetic() {
|
||||
let index = key.printable.to_ascii_lowercase() as usize - 'a' as usize;
|
||||
if index < options.len() {
|
||||
Some(index)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn inventory_menu(inventory: &[Object], header: &str, root: &mut Root) -> Option<usize> {
|
||||
// Show a menu with each inventory item as an option
|
||||
let options = if inventory.len() == 0 {
|
||||
vec!["Inventory is empty.".into()]
|
||||
} else {
|
||||
inventory.iter().map(|item| item.name.clone()).collect()
|
||||
};
|
||||
|
||||
let inventory_index = menu(header, &options, INVENTORY_WIDTH, root);
|
||||
|
||||
// If an item was chosen, return it
|
||||
if inventory.len() > 0 {
|
||||
inventory_index
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn render_bar(
|
||||
panel: &mut Offscreen,
|
||||
x: i32,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user