[][src]Trait tokyo::behavior::Behavior

pub trait Behavior: Send + Debug {
    fn next_command(&mut self, _: &Analyzer) -> Option<GameCommand>;
fn box_clone(&self) -> Box<dyn Behavior>; }

Behavior trait abstracts an action or a series of actions that a Player can take. It may be useful if you want to model a complex behavior, that spans multiple ticks, or whose interpretation changes dynamically. You can use Sequence::with_slice() to combine multiple behaviors.

Some Behaviors take Target as an argument to dynamically specify which player to act against. See its documentation for details (later in this file).

Examples

A stateful usage of Behavior.

impl Handlar for Player {
    fn tick(...) {
        self.analyzer.push_state(state, Instant::now());

        if let Some(next_command) = self.current_behavior.next_command(&self.analyzer) {
            return Some(next_command);
        }

        // Creates a Behavior and stores it in the Player struct, as we need to
        // persist the state across ticks and keep track of the number of times it
        // fired.
        self.current_behavior = Self::next_behavior();

        self.current_behavior.next_command(&analyzer)
    }

    fn next_behavior() -> Sequence {
        // Behavior to keep chasing the target (in this case, the player with
        // the highest score.) It yields to the next behavior when the distance
        // to the player is less than 200.0.
        let chase = Chase { target: Target::HighestScore, distance: 200.0 };

        // Behavior to fire at the target player twice.
        let fire = FireAt::with_times(Target::HighestScore, 2);

        // A sequence of behaviors: chase and then fire twice.
        Sequence::with_slice(&[&chase, &fire])
    }
}

A stateless usage of Behavior.

impl Handlar for Player {
    fn tick(...) {
        self.analyzer.push_state(state, Instant::now());

        // Find one of the bullets that are colliding within a second.
        if let Some(bullet) = self.analyzer.bullets_colliding(Duration::from_secs(1)).next() {
            let angle = bullet.velocity.tangent();

            // Try to dodge from the bullet by moving to a direction roughly
            // perpendicular to the bullet velocity.
            let dodge = Sequence::with_slice(&[
                &Rotate::with_margin_degrees(angle, 30.0),
                &Forward::with_steps(1),
            ]);

            // This Behavior works without persisting it somewhere for the next tick() as
            // in the previous example. At the next tick(), Rotate behavior will most likely
            // return None, proceeding immediately to the Forward behavior. If the situation
            // changes e.g. the bullet hit someone else, or there are other bullets
            // colliding, then it may take the Rotate behavior again, but it's likely an
            // optimal adjustment (assuming your logic of selecting a bullet to dodge is
            // stable.)
            return dodge.next_command(&self.analyzer);
        }
        None
    }
}

Required methods

fn next_command(&mut self, _: &Analyzer) -> Option<GameCommand>

fn box_clone(&self) -> Box<dyn Behavior>

Loading content...

Implementors

impl Behavior for Chase[src]

impl Behavior for Dodge[src]

impl Behavior for Fire[src]

impl Behavior for FireAt[src]

impl Behavior for Forward[src]

impl Behavior for Noop[src]

impl Behavior for Rotate[src]

impl Behavior for Sequence[src]

Loading content...