Skip to main content

Turns

Struct Turns 

Source
pub struct Turns { /* private fields */ }
Expand description

Which entities update this tick, from Ctx::turns.

Implementations§

Source§

impl Turns

Source

pub fn includes(self, entity: Entity) -> bool

true if entity’s turn is this tick.

if ctx.turns(8).includes(e) { /* expensive update */ }
Examples found in repository?
examples/ants.rs (line 233)
215fn forage(ctx: &mut Ctx) {
216    let turn = ctx.turns(2);
217    let mut food_grid = SpatialGrid::new(8.0);
218    food_grid.rebuild_from(
219        ctx.world
220            .query::<(Entity, &Transform2D, &Food)>()
221            .iter()
222            .map(|(e, t, _)| (e, t.position)),
223    );
224    let grid = &food_grid;
225    ctx.world
226        .query::<(Entity, &Transform2D, &mut Ant)>()
227        .par_for_each(|(e, t, ant)| {
228            ant.event = Event::None;
229            if ant.energy <= 0.0 {
230                ant.event = Event::Starved;
231                return;
232            }
233            if !turn.includes(e) {
234                return;
235            }
236            let at_home = t.position.distance(ant.home_at) < NEST_RADIUS;
237            if ant.carrying {
238                if at_home {
239                    ant.carrying = false;
240                    ant.since = 0.0;
241                    ant.energy = LIFESPAN;
242                    ant.heading += std::f32::consts::PI;
243                    ant.event = Event::Delivered;
244                }
245            } else if at_home {
246                ant.since = 0.0;
247            } else if let Some(f) = grid.nearest(t.position, 4.0, |_| true) {
248                ant.carrying = true;
249                ant.since = 0.0;
250                ant.heading += std::f32::consts::PI;
251                ant.event = Event::PickedUp(f.entity);
252            }
253        });
254
255    let (mut picked, mut delivered) = (Vec::new(), Vec::new());
256    let cmds = &mut ctx.commands;
257    ctx.world
258        .query::<(Entity, &Ant)>()
259        .for_each(|(e, ant)| match ant.event {
260            Event::None => {}
261            Event::Starved => cmds.despawn(e),
262            Event::PickedUp(food) => picked.push(food),
263            Event::Delivered => delivered.push(ant.home),
264        });
265    for f in picked {
266        if let Some(food) = ctx.world.get_mut::<Food>(f) {
267            food.amount = food.amount.saturating_sub(1);
268            if food.amount == 0 {
269                ctx.world.despawn(f);
270            }
271        }
272    }
273    for nest in delivered {
274        if let Some(n) = ctx.world.get_mut::<Nest>(nest) {
275            n.stored += 1;
276            n.delivered += 1;
277        }
278    }
279}
More examples
Hide additional examples
examples/battle.rs (line 268)
218fn fight() -> impl FnMut(&mut Ctx) {
219    // Per team: a fine grid for friends (only the closest few matter) and a
220    // coarse one for enemies (seen from afar). Marching armies far from the
221    // enemy then cost almost nothing to search, however packed they are.
222    let mut near = [
223        SpatialGrid::new(PERSONAL_SPACE * 2.0),
224        SpatialGrid::new(PERSONAL_SPACE * 2.0),
225    ];
226    let mut far = [SpatialGrid::new(SIGHT), SpatialGrid::new(SIGHT)];
227    let mut positions: Vec<(Entity, Vec2, Team)> = Vec::new();
228    move |ctx: &mut Ctx| {
229        let (dt, random, look) = (ctx.dt(), ctx.random(), ctx.turns(4));
230        let crowding = ctx.sim_tick().is_multiple_of(2);
231        ctx.world
232            .query::<(Entity, &Transform2D, &Unit)>()
233            .par_collect_into(&mut positions, |(e, t, u)| (e, t.position, u.team));
234        // The four grids are independent: build them at the same time.
235        let [near_red, near_blue] = &mut near;
236        let [far_red, far_blue] = &mut far;
237        let all = &positions;
238        let of = |team: Team| all.iter().filter(move |p| p.2 == team).map(|&(e, at, _)| (e, at));
239        rayon::scope(|s| {
240            if crowding {
241                s.spawn(|_| near_red.rebuild_from(of(Team::Red)));
242                s.spawn(|_| near_blue.rebuild_from(of(Team::Blue)));
243            }
244            s.spawn(|_| far_red.rebuild_from(of(Team::Red)));
245            s.spawn(|_| far_blue.rebuild_from(of(Team::Blue)));
246        });
247        let over = ctx.world.resource::<Score>().winner.is_some();
248        let battle = ctx.world.remove_resource::<Battle>().expect("battle");
249        let (near, far, b) = (&near, &far, &battle);
250        ctx.world
251            .query::<(Entity, &mut Transform2D, &mut Unit)>()
252            .par_for_each(|(e, t, unit)| {
253                let mut rng = random.of(e);
254                let me = t.position;
255                unit.hit = None;
256                unit.cooldown -= dt;
257                if crowding {
258                    let mut push = Vec2::ZERO;
259                    near[unit.team.index()].for_each_in_radius(me, PERSONAL_SPACE, |other| {
260                        if other.entity != e {
261                            let away = me - other.position;
262                            push += away / (away.length_squared() + 0.01);
263                        }
264                    });
265                    unit.push = push.clamp_length_max(1.0);
266                }
267                let mut nearest = None;
268                if unit.engaged || look.includes(e) {
269                    let enemies = &far[unit.team.enemy().index()];
270                    nearest = enemies
271                        .nearest(me, REACH, |_| true)
272                        .or_else(|| enemies.nearest(me, SIGHT, |_| true))
273                        .map(|g| (g.position.distance_squared(me), g.entity, g.position));
274                    unit.engaged = nearest.is_some();
275                }
276                let enemy_base = b.bases[unit.team.enemy().index()];
277                let mut want = match nearest {
278                    Some((d2, target, _)) if d2 < REACH * REACH => {
279                        if unit.cooldown <= 0.0 {
280                            unit.cooldown = COOLDOWN * rng.range(0.8, 1.2);
281                            unit.hit = Some(Hit::Unit(target));
282                        }
283                        Vec2::ZERO
284                    }
285                    Some((_, _, at)) => (at - me).normalize_or_zero() * SPEED,
286                    None if me.distance(enemy_base) < BASE_RADIUS + REACH => {
287                        if unit.cooldown <= 0.0 && !over {
288                            unit.cooldown = COOLDOWN;
289                            unit.hit = Some(Hit::Base);
290                        }
291                        Vec2::ZERO
292                    }
293                    None => b.fields[unit.team.index()].direction_at(me) * SPEED,
294                };
295                let slow = b.nav.cell_at(me).and_then(|c| b.nav.cost(c.x, c.y)).unwrap_or(1).max(1) as f32;
296                want = want / slow + unit.push * SPEED;
297                unit.vel = unit.vel.lerp(want, 0.2) + rng.unit_vec2() * 2.0;
298                // Slide along walls instead of walking into them.
299                let next = me + unit.vel * dt;
300                if b.nav.walkable(next) {
301                    t.position = next;
302                } else if b.nav.walkable(vec2(next.x, me.y)) {
303                    t.position.x = next.x;
304                } else if b.nav.walkable(vec2(me.x, next.y)) {
305                    t.position.y = next.y;
306                }
307            });
308        ctx.world.insert_resource(battle);
309    }
310}
Source

pub fn dt(self) -> f32

Time since an entity’s previous turn: every times ctx.dt().

let turn = ctx.turns(4);
assert_eq!(turn.dt(), ctx.dt() * 4.0);

Trait Implementations§

Source§

impl Clone for Turns

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Turns

Source§

impl Debug for Turns

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for Turns

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for Turns

Auto Trait Implementations§

§

impl Forget for Turns

§

impl Freeze for Turns

§

impl RefUnwindSafe for Turns

§

impl Send for Turns

§

impl Sync for Turns

§

impl Unpin for Turns

§

impl UnsafeUnpin for Turns

§

impl UnwindSafe for Turns

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Component for T
where T: Send + Sync + 'static,

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

impl<T> DowncastSend for T
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync> ⓘ

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_sync(self: Box<T>) -> Box<dyn Any + Send + Sync>

Converts Box<Trait> (where Trait: DowncastSync) to Box<dyn Any + Send + Sync>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync> ⓘ

Converts Arc<Trait> (where Trait: DowncastSync) to Arc<Any>, which can then be downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

Source§

impl<T> MaybeSync for T
where T: Sync + ?Sized,

Source§

impl<T> MaybeSync for T
where T: Sync + ?Sized,

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Scalar for T
where T: 'static + Clone + PartialEq + Debug,

Source§

impl<T> SerializableAny for T
where T: 'static + Any + Clone + for<'a> Send + Sync,

Source§

impl<T, S> SimdFrom<T, S> for T
where S: Simd,

Source§

fn simd_from(_simd: S, value: T) -> T

Source§

impl<F, T, S> SimdInto<T, S> for F
where T: SimdFrom<F, S>, S: Simd,

Source§

fn simd_into(self, simd: S) -> T

Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Upcast<T> for T

Source§

fn upcast(&self) -> Option<&T>

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more