Skip to main content

Transform2D

Struct Transform2D 

Source
#[repr(C)]
pub struct Transform2D { pub position: Vec2, pub rotation: f32, pub scale: Vec2, }
Expand description

Where an entity is: position, rotation and scale.

Positions are in window pixels, (0, 0) top-left, y down (same as Ctx::draw).

let t = Transform2D::at(vec2(100.0, 50.0)).rotated(0.5);
assert_eq!(t.position, vec2(100.0, 50.0));

Fields§

§position: Vec2

Where the entity is, in world pixels.

§rotation: f32

Radians, clockwise on screen.

§scale: Vec2

Size multiplier; negative flips. Default (1, 1).

Implementations§

Source§

impl Transform2D

Source

pub fn at(position: Vec2) -> Self

A transform at position with no rotation and scale 1.

Examples found in repository?
examples/battle.rs (line 430)
419fn spawn_unit(cmds: &mut Commands, sprite: Option<Texture>, team: Team, at: Vec2) {
420    let unit = Unit {
421        team,
422        hp: HP,
423        vel: Vec2::ZERO,
424        cooldown: 0.0,
425        engaged: false,
426        push: Vec2::ZERO,
427        hit: None,
428    };
429    match sprite {
430        Some(tex) => cmds.spawn((Transform2D::at(at), Sprite::new(tex).with_color(team.color()), unit)),
431        None => cmds.spawn((Transform2D::at(at), unit)),
432    }
433}
434
435fn setup(ctx: &mut Ctx, units: usize, seed: u64, sprite: Option<Texture>) {
436    let scale = (units as f32 / UNITS_PER_MAP).max(1.0).sqrt();
437    let size = (MAP.as_vec2() * scale).as_uvec2();
438    let (nav, bases) = make_map(size, seed);
439    ctx.world.reflect::<Unit>();
440    ctx.world.reflect::<Base>();
441    let max_hp = 400.0 * (units as f32 / 1000.0).sqrt();
442    let base_entities = [Team::Red, Team::Blue].map(|team| {
443        ctx.world.spawn((
444            Transform2D::at(bases[team.index()]),
445            Base {
446                team,
447                hp: max_hp,
448                max_hp,
449                budget: 0.0,
450            },
451        ))
452    });
453    let mut battle = Battle {
454        nav,
455        fields: [FlowField::new(), FlowField::new()],
456        rally: bases,
457        bases,
458        base_entities,
459        cap: units / 2,
460        field_ms: 0.0,
461    };
462    battle.set_rally(Team::Red, bases[1]);
463    battle.set_rally(Team::Blue, bases[0]);
464    ctx.world.insert_resource(battle);
465    ctx.world.reflect_resource::<Score>();
466    ctx.events.reflect::<Fallen>();
467    ctx.world.insert_resource(Score::default());
468    ctx.world.insert_resource(Look(sprite));
469    start_round(ctx);
470}
More examples
Hide additional examples
examples/ecs.rs (line 41)
34fn spawn_crab(ctx: &mut Ctx, at: Vec2) {
35    let s = ctx.world.resource_mut::<Settings>();
36    let angle = s.random() * std::f32::consts::TAU;
37    let speed = 40.0 + s.random() * 120.0;
38    let tint = Color::rgb(0.5 + s.random() * 0.5, 0.5 + s.random() * 0.5, 0.5 + s.random() * 0.5);
39    let crab = s.crab;
40    ctx.world.spawn((
41        Transform2D::at(at),
42        Sprite::new(crab).with_color(tint),
43        Vel(Vec2::from_angle(angle) * speed),
44        Life(LIFETIME),
45    ));
46}
examples/ants.rs (line 329)
319fn spawn_ant(cmds: &mut Commands, sprite: Option<Texture>, home: Entity, at: Vec2, heading: f32) {
320    let ant = Ant {
321        home,
322        home_at: at,
323        heading,
324        carrying: false,
325        since: 0.0,
326        energy: LIFESPAN,
327        event: Event::None,
328    };
329    let t = Transform2D::at(at).rotated(heading);
330    match sprite {
331        Some(tex) => cmds.spawn((t, ant, Sprite::new(tex).with_color(Color::hex(0xD4553A)))),
332        None => cmds.spawn((t, ant)),
333    }
334}
335
336fn spawn_food(cmds: &mut Commands, rng: &mut Rng, bounds: Vec2, nests: &[Vec2]) {
337    // Not too close to any nest, so trails have to form.
338    let p = loop {
339        let p = vec2(rng.range(20.0, bounds.x - 20.0), rng.range(20.0, bounds.y - 20.0));
340        if nests.iter().all(|n| p.distance(*n) > 180.0) {
341            break p;
342        }
343    };
344    cmds.spawn((Transform2D::at(p), Food { amount: 400 }));
345}
346
347/// The simulation, shared by the windowed and headless runs.
348fn colonies(game: Game, bounds: Vec2) -> Game {
349    game.sim_system(steer(bounds))
350        .sim_system(lay_trails)
351        .sim_system(forage)
352        .sim_system_every(4, evaporate)
353        .sim_system_every(30, grow(bounds))
354}
355
356/// Nests on a grid, one per `NEST_AREA`; ants and food around them.
357fn setup(ctx: &mut Ctx, bounds: Vec2, ants: usize, sprite: Option<Texture>) {
358    ctx.world.reflect::<Ant>();
359    ctx.world.reflect::<Nest>();
360    ctx.world.reflect::<Food>();
361    ctx.world.insert_resource(Field::new(bounds));
362    ctx.world.insert_resource(AntLook(sprite));
363    let mut rng = ctx.random().stream(1);
364    let (cols, rows) = ((bounds.x / NEST_AREA.x) as usize, (bounds.y / NEST_AREA.y) as usize);
365    let (cols, rows) = (cols.max(1), rows.max(1));
366    let per_nest = (ants / (cols * rows)).max(1);
367    let mut homes = Vec::new();
368    for row in 0..rows {
369        for col in 0..cols {
370            let at = (vec2(col as f32, row as f32) + 0.5) * bounds / vec2(cols as f32, rows as f32);
371            let nest = Nest {
372                stored: 0,
373                delivered: 0,
374                max_ants: per_nest as u32 * 2,
375                ants: per_nest as u32,
376            };
377            let home = ctx.world.spawn((Transform2D::at(at), nest));
378            homes.push(at);
379            for _ in 0..per_nest {
380                spawn_ant(&mut ctx.commands, sprite, home, at, rng.angle());
381            }
382        }
383    }
384    for _ in 0..food_piles(bounds) {
385        spawn_food(&mut ctx.commands, &mut rng, bounds, &homes);
386    }
387}
examples/hotpatch.rs (line 57)
47fn main() {
48    Game::new("Crabby Engine: hot patching", 1280, 720)
49        .sim_system(spin)
50        .sim_system(wobble)
51        .sim_system(report)
52        .run(|ctx| {
53            let crab = ctx.load_texture("crab.png");
54            for i in 0..12 {
55                let at = vec2(160.0 + (i % 6) as f32 * 190.0, 220.0 + (i / 6) as f32 * 280.0);
56                ctx.world
57                    .spawn((Transform2D::at(at), Sprite::new(crab), Crab(i as f32 * 0.7)));
58            }
59        });
60}
examples/lockstep.rs (line 154)
144fn play(net: Net) {
145    Game::new("Lockstep", 800, 600)
146        .lockstep(net)
147        .system(read_keys) // frame system: input out
148        .sim_system(move_crabs) // sim system: everyone's input in
149        .system(draw)
150        .run(|ctx| {
151            ctx.world.reflect::<Crab>(); // compared between peers
152            for player in 0..2 {
153                ctx.world.spawn((
154                    Transform2D::at(vec2(250.0 + 300.0 * player as f32, 300.0)),
155                    Crab {
156                        player,
157                        push: Vec2::ZERO,
158                    },
159                ));
160            }
161        });
162    // ANCHOR_END: session
163}
examples/bunnymark_ecs.rs (line 59)
44fn spawn(ctx: &mut Ctx, n: usize, at: Vec2) {
45    let b = ctx.world.resource_mut::<Bench>();
46    let crab = b.crab;
47    let mut batch = Vec::with_capacity(n);
48    for _ in 0..n {
49        let r = &mut b.rng;
50        let vel = vec2(r.next_f32() * 400.0 - 200.0, r.next_f32() * 400.0 - 300.0);
51        let color = Color::rgb(
52            0.6 + r.next_f32() * 0.4,
53            0.6 + r.next_f32() * 0.4,
54            0.6 + r.next_f32() * 0.4,
55        );
56        batch.push((
57            Transform2D {
58                scale: Vec2::splat(b.scale),
59                ..Transform2D::at(at)
60            },
61            Sprite::new(crab).with_color(color),
62            Vel(vel),
63        ));
64    }
65    ctx.world.spawn_batch(batch);
66}
Source

pub fn rotated(self, rotation: f32) -> Self

Same transform, rotated to rotation radians.

Examples found in repository?
examples/ants.rs (line 329)
319fn spawn_ant(cmds: &mut Commands, sprite: Option<Texture>, home: Entity, at: Vec2, heading: f32) {
320    let ant = Ant {
321        home,
322        home_at: at,
323        heading,
324        carrying: false,
325        since: 0.0,
326        energy: LIFESPAN,
327        event: Event::None,
328    };
329    let t = Transform2D::at(at).rotated(heading);
330    match sprite {
331        Some(tex) => cmds.spawn((t, ant, Sprite::new(tex).with_color(Color::hex(0xD4553A)))),
332        None => cmds.spawn((t, ant)),
333    }
334}
Source

pub fn scaled(self, scale: Vec2) -> Self

Same transform, scaled by scale.

Examples found in repository?
examples/boids.rs (line 103)
87fn spawn_boids(ctx: &mut Ctx, n: usize, bounds: Vec2) {
88    ctx.world.reflect::<Vel>();
89    let tex = ctx.load_texture("crab.png");
90    let mut s = 0x9E37_79B9_7F4A_7C15u64;
91    let mut rand = move || {
92        s ^= s << 13;
93        s ^= s >> 7;
94        s ^= s << 17;
95        (s >> 40) as f32 / (1u64 << 24) as f32
96    };
97    let mut batch = Vec::with_capacity(n);
98    for _ in 0..n {
99        let pos = vec2(rand(), rand()) * bounds;
100        let vel = Vec2::from_angle(rand() * std::f32::consts::TAU) * MIN_SPEED;
101        let tint = Color::rgb(0.5 + rand() * 0.5, 0.7 + rand() * 0.3, 0.9);
102        batch.push((
103            Transform2D::at(pos).scaled(Vec2::splat(0.5)),
104            Sprite::new(tex).with_color(tint),
105            Vel(vel),
106        ));
107    }
108    ctx.world.spawn_batch(batch);
109}

Trait Implementations§

Source§

impl Clone for Transform2D

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 Transform2D

Source§

impl Debug for Transform2D

Source§

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

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

impl Default for Transform2D

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for Transform2D

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl PartialEq for Transform2D

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 Serialize for Transform2D

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for Transform2D

Auto Trait Implementations§

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> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

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<R, P> ReadPrimitive<R> for P
where R: Read + ReadEndian<P>, P: Default,

Source§

fn read_from_little_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_little_endian().
Source§

fn read_from_big_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_big_endian().
Source§

fn read_from_native_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_native_endian().
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