void Pingus::draw (DrawingContext& gc) { // Add 10 to z_pos so that the pingu gets drawn above the node it is // standing one if (final_target_node != NoNode && current_node == NoNode) { gc.draw(arrow, path->get_dot(final_target_node)->get_pos() + Vector3f(0, 0, 10)); } if (!is_walking()) { gc.draw(sprite_standing, pos); } else { // FIXME: Replace the sprite and add up/down here float direction = get_direction(); if (direction >= 0 && direction < 180) gc.draw(sprite[Direction::RIGHT], pos + Vector3f(0, 0, 10)); else gc.draw(sprite[Direction::LEFT], pos + Vector3f(0, 0, 10)); } }
void Pingus::update (float delta) { float direction = get_direction(); if (direction >= 0 && direction < 180) sprite[Direction::RIGHT].update(delta); else sprite[Direction::LEFT].update(delta); if (is_walking()) update_walk(delta); }
void Unit::set_path( const std::shared_ptr<std::vector<ks::Vertex> >& path) { assert(path->size()); if (is_walking()) { _path->erase(_path->begin() + 1, _path->end()); } #ifdef DEBUG_UNIT_PATHS _debug_path.clear(); #endif std::vector<ks::Vertex>::reverse_iterator it; for (it = path->rbegin(); it != path->rend(); it++) { _path->push_back(*it); #ifdef DEBUG_UNIT_PATHS auto shape = std::make_unique<sf::RectangleShape>(); shape->setFillColor(sf::Color::Red); shape->setSize(sf::Vector2f(8, 8)); shape->setPosition(sf::Vector2f(it->x, it->y)); _debug_path.push_back(std::move(shape)); #endif } if (! is_walking()) { double x = (*_path)[0].x; double y = (*_path)[0].y; set_position(x , y); } }
void fight_ai (struct anim *k) { /* non-fightable characters don't fight */ if (! is_fightable_anim (k)) return; /* controllables and non-fighters doesn't need AI to fight */ if (k->controllable || ! k->fight) return; /* if forgetting about an enemy, no need to fight */ if (k->enemy_refraction > 0) return; /* without an enemy or awareness, no need to fight */ if (k->enemy_id == -1) { if (is_in_fight_mode (k)) leave_fight_mode (k); return; } /* first thing, enter in fight mode */ if (! is_in_fight_mode (k)) { enter_fight_mode (k); return; } /* who's the enemy? */ struct anim *ke = get_anim_by_id (k->enemy_id); /* what's the facing opposite direction? */ enum dir odir = (k->f.dir == LEFT) ? RIGHT : LEFT; /* get positions */ struct pos p, pe; survey (_m, pos, &k->f, NULL, &p, NULL); survey ((k->f.dir != ke->f.dir) ? _m : _mba, pos, &ke->f, NULL, &pe, NULL); pos2room (&pe, p.room, &pe); /* remember the place the enemy was last seen */ if (pe.room == p.room && pe.floor == p.floor) k->enemy_pos = pe; else if (pe.floor > p.floor && is_valid_pos (&k->enemy_pos) && ! is_strictly_traversable (&k->enemy_pos)) k->enemy_pos.place = pe.place; if (is_valid_pos (&k->enemy_pos) && is_strictly_traversable (&k->enemy_pos)) { struct pos pp; int d = (p.place < k->enemy_pos.place) ? -1 : +1; while (is_strictly_traversable (prel (&k->enemy_pos, &pp, +0, d))) k->enemy_pos = pp; } /* prevent enemy from passing through */ if (ke->type == KID && is_in_range (k, ke, ATTACK_RANGE) && ! is_in_fight_mode (ke) && ! ke->immortal && ! (is_kid_climb (&ke->f) && ke->i <= 7) && ke->f.dir != k->f.dir && ke->current_lives > 0 && ke->has_sword && ! is_kid_fall (&ke->f) && ! is_kid_hang (&ke->f) && ! is_kid_jump_air (&ke->f) && ! is_kid_run_jump_air (&ke->f) && is_safe_to_attack (ke)) { place_on_the_ground (&ke->f, &ke->f.c); kid_take_sword (ke); ke->auto_taken_sword = true; } /* prevent enemy from hiding near */ if (ke->type == KID && is_in_range (k, ke, INVERSION_RANGE) && ! is_in_fight_mode (ke) && ke->current_lives > 0) { if (is_safe_to_walkb (k)) fight_walkb (k); else if (is_safe_to_turn (k)) fight_turn (k); return; } /* if the enemy is on the back, turn */ if (is_on_back (k, ke) && is_anim_seeing (k, ke, odir) && p.floor == pe.floor && ! is_in_range (k, ke, INVERSION_RANGE)) { if (is_safe_to_turn (k)) fight_turn (k); else if (is_safe_to_walkb (k)) fight_walkb (k); return; } /* if too near to a wall, back off to have room for an attack */ if (fight_crel (k, +0, +1) == WALL && is_safe_to_walkb (k)) { fight_walkb (k); return; } /* /\* if the enemy can be followed in the opposite direction, turn *\/ */ /* if (! is_safe_to_follow (k, ke, k->f.dir) */ /* && is_safe_to_follow (k, ke, odir)) { */ /* fight_turn (k); */ /* return; */ /* } */ /* if the enemy is trying to bypass, attack him */ if (! is_in_fight_mode (ke) && ! ke->has_sword && ! is_kid_stairs (&ke->f) && ke->f.dir != k->f.dir && ke->current_lives > 0 && ! is_on_back (k, ke) && ((is_kid_run (&ke->f) && is_in_range (k, ke, 3 * PLACE_WIDTH - 4)) || (is_kid_run_jump (&ke->f) && is_in_range (k, ke, 4 * PLACE_WIDTH - 4)) || (is_kid_jump_air (&ke->f) && ke->i < 9 && is_in_range (k, ke, 4 * PLACE_WIDTH)))) { if (is_safe_to_attack (k)) fight_attack (k); else if (is_safe_to_walkb (k)) fight_walkb (k); return; } /* stays at least in the fight range. Advance, unless the enemy is not running towards you */ if (! is_in_range (k, ke, FIGHT_RANGE + 10) && ! is_kid_stairs (&ke->f) && (ke->f.dir == k->f.dir || p.room != pe.room || p.floor != pe.floor || ! (is_kid_run (&ke->f) || is_kid_run_jump (&ke->f) || is_kid_jump (&ke->f))) && is_safe_to_follow (k, ke, k->f.dir)) { fight_walkf (k); return; } /* if the enemy is not targeting you, do nothing more */ if (ke->enemy_id != -1 && ke->enemy_id != k->id) return; /* in fight range, if the enemy is not attacking, go towards attack range (with probability, unless the enemy is not in fight mode, then go immediately) */ if (is_in_range (k, ke, FIGHT_RANGE + 10) && ! is_in_range (k, ke, ATTACK_RANGE) && ! is_kid_stairs (&ke->f) && is_safe_to_follow (k, ke, k->f.dir) && (prandom (99) <= k->skill.advance_prob || ! is_in_fight_mode (ke)) && ! is_attacking (ke) && (! is_in_fight_mode (ke) || is_walking (ke) || ke->i >= 6 + prandom (24))) { fight_walkf (k); return; } /* in attack range, if being attacked, defend yourself (with probability) and counter attack (with probability handled elsewhere) */ if (is_in_range (k, ke, ATTACK_RANGE + 16) && ! is_on_back (k, ke) && (is_attacking (ke) && ke->i == 0) && (prandom (99) <= k->skill.defense_prob || k->refraction > 0) && ke->current_lives > 0) { fight_defense (k); fight_attack (k); return; } /* if attacking, counter defend (with probability handled elsewhere) */ if (is_in_range (k, ke, ATTACK_RANGE + 16) && is_attacking (k)) { fight_defense (k); fight_attack (k); return; } /* in attack range, if not being attacked, attack (with probability, unless the enemy is not in fight mode, then attack immediately) */ if (is_in_range (k, ke, ATTACK_RANGE) && ! is_attacking (ke) && ! is_on_back (k, ke) && ! is_kid_stairs (&ke->f) && ! ((is_kid_climb (&ke->f) || is_kid_successfully_climbing (&ke->f)) && ke->i >= 1) && ke->current_lives > 0 && (prandom (99) <= k->skill.attack_prob || ! is_in_fight_mode (ke))) { if (is_safe_to_attack (k)) fight_attack (k); else if (is_safe_to_walkb (k)) fight_walkb (k); return; } /* in hit range, back off (with probability) */ if (is_in_range (k, ke, HIT_RANGE - 10) && is_safe_to_walkb (k) && ! k->refraction && ! is_walkingb (ke) && prandom (99) <= k->skill.return_prob) { fight_walkb (k); return; } }