Sword-fighting
This commit is contained in:
parent
e85828fd33
commit
b652bd512d
89
src/main.rs
89
src/main.rs
@ -54,6 +54,8 @@ struct Object {
|
||||
name: String,
|
||||
blocks: bool,
|
||||
alive: bool,
|
||||
fighter: Option<Fighter>,
|
||||
ai: Option<Ai>,
|
||||
}
|
||||
|
||||
impl Object {
|
||||
@ -66,6 +68,8 @@ impl Object {
|
||||
name: name.into(),
|
||||
blocks: blocks,
|
||||
alive: false,
|
||||
fighter: None,
|
||||
ai: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,6 +87,12 @@ impl Object {
|
||||
self.x = x;
|
||||
self.y = y;
|
||||
}
|
||||
|
||||
pub fn distance_to(&self, other: &Object) -> f32 {
|
||||
let dx = other.x - self.x;
|
||||
let dy = other.y - self.y;
|
||||
((dx.pow(2) + dy.pow(2)) as f32).sqrt()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
@ -146,6 +156,15 @@ impl Rect {
|
||||
}
|
||||
}
|
||||
|
||||
// Combat related properties and methods (monster, player, NPC).
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
struct Fighter {
|
||||
max_hp: i32,
|
||||
hp: i32,
|
||||
defense: i32,
|
||||
power: i32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
enum PlayerAction {
|
||||
TookTurn,
|
||||
@ -153,6 +172,11 @@ enum PlayerAction {
|
||||
Exit,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
enum Ai {
|
||||
Basic,
|
||||
}
|
||||
|
||||
fn handle_keys(tcod: &mut Tcod, game: &Game, objects: &mut Vec<Object>) -> PlayerAction {
|
||||
use tcod::input::Key;
|
||||
use tcod::input::KeyCode::*;
|
||||
@ -275,10 +299,26 @@ fn place_objects(room: Rect, map: &Map, objects: &mut Vec<Object>) {
|
||||
if !is_blocked(x, y, map, objects) {
|
||||
let mut monster = if rand::random::<f32>() < 0.8 {
|
||||
// 80% chance of spawning an orc
|
||||
Object::new(x, y, 'o', "orc", DESATURATED_GREEN, true)
|
||||
let mut orc = Object::new(x, y, 'o', "orc", DESATURATED_GREEN, true);
|
||||
orc.fighter = Some(Fighter {
|
||||
max_hp: 10,
|
||||
hp: 10,
|
||||
defense: 0,
|
||||
power: 3,
|
||||
});
|
||||
orc.ai = Some(Ai::Basic);
|
||||
orc
|
||||
} else {
|
||||
// 20% chance of spawning a troll
|
||||
Object::new(x, y, 'T', "troll", DARKER_GREEN, true)
|
||||
let mut troll = Object::new(x, y, 'T', "troll", DARKER_GREEN, true);
|
||||
troll.fighter = Some(Fighter {
|
||||
max_hp: 16,
|
||||
hp: 16,
|
||||
defense: 1,
|
||||
power: 4,
|
||||
});
|
||||
troll.ai = Some(Ai::Basic);
|
||||
troll
|
||||
};
|
||||
|
||||
monster.alive = true;
|
||||
@ -327,6 +367,38 @@ fn player_move_or_attack(dx: i32, dy: i32, game: &Game, objects: &mut [Object])
|
||||
}
|
||||
}
|
||||
|
||||
fn move_towards(id: usize, target_x: i32, target_y: i32, map: &Map, objects: &mut [Object]) {
|
||||
// Vector from this object to the target, and distance
|
||||
let dx = target_x - objects[id].x;
|
||||
let dy = target_y - objects[id].y;
|
||||
let distance = ((dx.pow(2) + dy.pow(2)) as f32).sqrt();
|
||||
|
||||
// Normalize it to length 1 (preserving direction), then round it and
|
||||
// convert it to integer so the movement is restricted to the map grid
|
||||
let dx = (dx as f32 / distance).round() as i32;
|
||||
let dy = (dy as f32 / distance).round() as i32;
|
||||
move_by(id, dx, dy, map, objects);
|
||||
}
|
||||
|
||||
fn ai_take_turn(monster_id: usize, tcod: &Tcod, game: &Game, objects: &mut [Object]) {
|
||||
// A basic monster takes its turn. If you can see it, it can see you.
|
||||
let (monster_x, monster_y) = objects[monster_id].pos();
|
||||
if tcod.fov.is_in_fov(monster_x, monster_y) {
|
||||
if objects[monster_id].distance_to(&objects[PLAYER]) >= 2.0 {
|
||||
// Move towards player if far away
|
||||
let (player_x, player_y) = objects[PLAYER].pos();
|
||||
move_towards(monster_id, player_x, player_y, &game.map, objects);
|
||||
} else if objects[PLAYER].fighter.map_or(false, |f| f.hp > 0) {
|
||||
// Close enough, attach! (if the player is still alive.)
|
||||
let monster = &objects[monster_id];
|
||||
println!(
|
||||
"The attack of the {} bounces off your shiny metal armor!",
|
||||
monster.name
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render_all(tcod: &mut Tcod, game: &mut Game, objects: &[Object], fov_recompute: bool) {
|
||||
if fov_recompute {
|
||||
let player = &objects[PLAYER];
|
||||
@ -398,6 +470,12 @@ fn main() {
|
||||
// Create player object
|
||||
let mut player = Object::new(0, 0, '@', "player", WHITE, true);
|
||||
player.alive = true;
|
||||
player.fighter = Some(Fighter {
|
||||
max_hp: 30,
|
||||
hp: 30,
|
||||
defense: 2,
|
||||
power: 5,
|
||||
});
|
||||
|
||||
// List of objects in the world
|
||||
let mut objects = vec![player];
|
||||
@ -437,10 +515,9 @@ fn main() {
|
||||
|
||||
// Let monsters take their turn
|
||||
if objects[PLAYER].alive && player_action != PlayerAction::DidntTakeTurn {
|
||||
for object in &objects {
|
||||
// ONly if object is not player
|
||||
if (object as *const _) != (&objects[PLAYER] as *const _) {
|
||||
println!("The {} growls!", object.name);
|
||||
for id in 0..objects.len() {
|
||||
if objects[id].ai.is_some() {
|
||||
ai_take_turn(id, &tcod, &game, &mut objects);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user