#[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: Vec2Where the entity is, in world pixels.
rotation: f32Radians, clockwise on screen.
scale: Vec2Size multiplier; negative flips. Default (1, 1).
Implementations§
Source§impl Transform2D
impl Transform2D
Sourcepub fn at(position: Vec2) -> Self
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
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}Additional examples can be found in:
Sourcepub fn rotated(self, rotation: f32) -> Self
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}Sourcepub fn scaled(self, scale: Vec2) -> Self
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
impl Clone for Transform2D
impl Copy for Transform2D
Source§impl Debug for Transform2D
impl Debug for Transform2D
Source§impl Default for Transform2D
impl Default for Transform2D
Source§impl<'de> Deserialize<'de> for Transform2Dwhere
Transform2D: Default,
impl<'de> Deserialize<'de> for Transform2Dwhere
Transform2D: Default,
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
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
impl PartialEq for Transform2D
Source§impl Serialize for Transform2D
impl Serialize for Transform2D
impl StructuralPartialEq for Transform2D
Auto Trait Implementations§
impl Forget for Transform2D
impl Freeze for Transform2D
impl RefUnwindSafe for Transform2D
impl Send for Transform2D
impl Sync for Transform2D
impl Unpin for Transform2D
impl UnsafeUnpin for Transform2D
impl UnwindSafe for Transform2D
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> Component for T
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
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>
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)
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)
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 Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
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>
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)
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)
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> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<S, T> Duplex<S> for Twhere
T: FromSample<S> + ToSample<S>,
Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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 moreSource§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
impl<T> MaybeSync for T
impl<T> MaybeSync for T
Source§impl<T> Pointable for T
impl<T> Pointable for T
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
Source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
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().impl<T> Scalar for T
impl<T> SerializableAny for T
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
The inverse inclusion map: attempts to construct
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
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
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
fn from_subset(element: &SS) -> SP
The inclusion map: converts
self to the equivalent element of its superset.