pub struct Sprite { /* private fields */ }
Expand description
A Sprite is an advanced version of an image element, displaying an animated picture that can have multiple states (e.g. a walking, attacking, etc. version of a player character) The sprite is initalized using an image file that contains multiple rows of images (each row representing a variant), where each row contains the same number of animation frames for each variant. Drawing the sprite repeatedly draws every frame of the selected variant in order and then repeats from the beginning.
Implementations§
source§impl Sprite
impl Sprite
sourcepub fn new(spritesheet: Image, w: u32, h: u32, frame_time: Duration) -> Self
pub fn new(spritesheet: Image, w: u32, h: u32, frame_time: Duration) -> Self
Create a new sprite using the passed ggez::graphics::Image and set the duration after which a frame change occurs. The values for the width and height of a single image within the sheet have to be passed manually. Will never fail, as the image is already loaded by ggez.
sourcepub fn from_path(
path: impl AsRef<Path>,
ctx: &Context,
w: u32,
h: u32,
frame_time: Duration
) -> Result<Self, GameError>
pub fn from_path( path: impl AsRef<Path>, ctx: &Context, w: u32, h: u32, frame_time: Duration ) -> Result<Self, GameError>
Create a new sprite from the file found at the passed path and set the duration after which a frame change occurs. The values for the width and height of a single image within the sheet have to be passed manually. May fail if the image cannot be loaded, because f.e. the path is wrong. Passing ‘wrong’ size values will yield unexpected behaviour but not panic.
Examples found in repository?
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
pub fn new(ctx: &Context) -> Result<Self, GameError> {
// Reusing the visuals from E.
let vis = ui::Visuals::new(
Color::from_rgb(180, 120, 60),
Color::from_rgb(18, 12, 6),
1.,
0.,
);
let hover_vis = ui::Visuals::new(
Color::from_rgb(160, 100, 40),
Color::from_rgb(18, 12, 6),
3.,
0.,
);
let cont_vis = ui::Visuals::new(
Color::from_rgb(60, 120, 180),
Color::from_rgb(180, 180, 190),
1.,
0.,
);
// A sprite can be loaded by specifying a path, just like an Image.
// Additionaly, you need to inform the sprite of the grid size of its sheet and the duration each frame is displayed.
let ui_sprite = sprite::Sprite::from_path(
"/moo-sheet_16_16.png",
ctx,
16,
24,
Duration::from_secs_f32(0.25),
)?
// Just like any UI element, a sprite can have visuals, tooltip, ect.
.to_element_builder(1, ctx)
.scaled(5., 5.)
.with_visuals(vis)
.with_hover_visuals(hover_vis)
.with_tooltip(
graphics::Text::new("This is a sprite! Click it to end the scene.")
.set_scale(28.)
.set_font("Bahnschrift")
.to_owned()
.to_element_builder(0, ctx)
.with_visuals(cont_vis)
.build(),
)
.as_shrink()
.build();
// Sprites can also be initiated from a sprite pool, to make repeated file system access unneccessary
// and streamline loading of multiple sprites. This requires sprites in the folder to be formatted appropriately.
let sprite_pool = sprite::SpritePool::new()
// with_folder loads all .png/.bmp/.jpg/.jpeg files from the passed folder and optionally its subfolders
.with_folder(ctx, "/", true);
// We can now init a sprite from the pool. Sprites are saved in the pool with a key corresponding to their relative path
// (from the resource folder) with the format information and file ending removed.
let non_ui_sprite = sprite_pool.init_sprite("/mage-sheet", Duration::from_secs_f32(0.2))?;
// you can also initialize a sprite pool without any folder at all
let mut sprite_pool2 = sprite::SpritePool::new();
// in this case, you can use lazy initialisation of sprites to fill the sprite pool only with those sprites currently needed.
// Lazy initilisation draws from the pool if possible, from the file system if needed (and loads into the pool in this case) and panics if it can't find anything in the fs.
// Requires a mutable sprite pool!
// For testing purposes, we are loading a sprite we have already loaded - this should be drawn from the pool.
let lazy_sprite =
sprite_pool2.init_sprite_lazy(ctx, "/mage-sheet", Duration::from_secs_f32(0.5))?;
// now load the correct sprite
let lazy_sprite =
sprite_pool2.init_sprite_lazy(ctx, "/moo-sheet", lazy_sprite.get_frame_time())?;
Ok(Self {
gui: ui_sprite,
sprite: non_ui_sprite,
sprite2: lazy_sprite,
pos: Vec2::new(50., 200.),
v: Vec2::new(4., 4.),
})
}
sourcepub fn from_path_fmt(
path: impl AsRef<Path>,
ctx: &Context,
frame_time: Duration
) -> Result<Self, GameError>
pub fn from_path_fmt( path: impl AsRef<Path>, ctx: &Context, frame_time: Duration ) -> Result<Self, GameError>
Create a new sprite using from the file found at the passed path and set the duration after which a frame change occurs.
The values for the width and height of a single image are read from the file name.
The file name needs to be formatted as name_possibly_containing_underscores_width_height.extension
.
May fail if the image cannot be loaded (e.g. if the path is wrong) or the file name is not formatted correctly.
sourcepub fn set_variant(&mut self, variant: u32)
pub fn set_variant(&mut self, variant: u32)
Sets the variant this sprite is currently displaying. Numbers that are too large to represent a valid variant will wrap around.
Examples found in repository?
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
fn update(&mut self, ctx: &mut Context) -> Result<scene_manager::SceneSwitch, GameError> {
// Actually implementing some game state logic.
// Pressing space changes the variant of the sprite.
if ctx
.keyboard
.is_key_just_pressed(winit::event::VirtualKeyCode::Space)
{
self.sprite.set_variant(self.sprite.get_variant() + 1);
}
// Move the sprite.
self.pos += self.v;
// Make the sprite bounce off the screen edges.
let scaling = 5.;
if self.pos.x - scaling * 4. < 0. || self.pos.x + scaling * 4. >= ctx.gfx.drawable_size().0
{
self.v.x *= -1.;
}
if self.pos.y - scaling * 8. < 0. || self.pos.y + scaling * 8. >= ctx.gfx.drawable_size().1
{
self.v.y *= -1.;
}
// And handle messages as usual
let messages = self.gui.manage_messages(ctx, None);
if messages.contains(&ui::UiMessage::Triggered(1)) {
return Ok(scene_manager::SceneSwitch::pop(1));
}
Ok(scene_manager::SceneSwitch::None)
}
sourcepub fn get_variant(&self) -> u32
pub fn get_variant(&self) -> u32
Returns the variant this sprite is currently displaying.
Examples found in repository?
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
fn update(&mut self, ctx: &mut Context) -> Result<scene_manager::SceneSwitch, GameError> {
// Actually implementing some game state logic.
// Pressing space changes the variant of the sprite.
if ctx
.keyboard
.is_key_just_pressed(winit::event::VirtualKeyCode::Space)
{
self.sprite.set_variant(self.sprite.get_variant() + 1);
}
// Move the sprite.
self.pos += self.v;
// Make the sprite bounce off the screen edges.
let scaling = 5.;
if self.pos.x - scaling * 4. < 0. || self.pos.x + scaling * 4. >= ctx.gfx.drawable_size().0
{
self.v.x *= -1.;
}
if self.pos.y - scaling * 8. < 0. || self.pos.y + scaling * 8. >= ctx.gfx.drawable_size().1
{
self.v.y *= -1.;
}
// And handle messages as usual
let messages = self.gui.manage_messages(ctx, None);
if messages.contains(&ui::UiMessage::Triggered(1)) {
return Ok(scene_manager::SceneSwitch::pop(1));
}
Ok(scene_manager::SceneSwitch::None)
}
sourcepub fn get_dimensions(&self) -> (f32, f32)
pub fn get_dimensions(&self) -> (f32, f32)
Returns the width and height of a single frame of this sprite.
sourcepub fn get_frame_time(&self) -> Duration
pub fn get_frame_time(&self) -> Duration
Returns the duration between two frames.
Examples found in repository?
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
pub fn new(ctx: &Context) -> Result<Self, GameError> {
// Reusing the visuals from E.
let vis = ui::Visuals::new(
Color::from_rgb(180, 120, 60),
Color::from_rgb(18, 12, 6),
1.,
0.,
);
let hover_vis = ui::Visuals::new(
Color::from_rgb(160, 100, 40),
Color::from_rgb(18, 12, 6),
3.,
0.,
);
let cont_vis = ui::Visuals::new(
Color::from_rgb(60, 120, 180),
Color::from_rgb(180, 180, 190),
1.,
0.,
);
// A sprite can be loaded by specifying a path, just like an Image.
// Additionaly, you need to inform the sprite of the grid size of its sheet and the duration each frame is displayed.
let ui_sprite = sprite::Sprite::from_path(
"/moo-sheet_16_16.png",
ctx,
16,
24,
Duration::from_secs_f32(0.25),
)?
// Just like any UI element, a sprite can have visuals, tooltip, ect.
.to_element_builder(1, ctx)
.scaled(5., 5.)
.with_visuals(vis)
.with_hover_visuals(hover_vis)
.with_tooltip(
graphics::Text::new("This is a sprite! Click it to end the scene.")
.set_scale(28.)
.set_font("Bahnschrift")
.to_owned()
.to_element_builder(0, ctx)
.with_visuals(cont_vis)
.build(),
)
.as_shrink()
.build();
// Sprites can also be initiated from a sprite pool, to make repeated file system access unneccessary
// and streamline loading of multiple sprites. This requires sprites in the folder to be formatted appropriately.
let sprite_pool = sprite::SpritePool::new()
// with_folder loads all .png/.bmp/.jpg/.jpeg files from the passed folder and optionally its subfolders
.with_folder(ctx, "/", true);
// We can now init a sprite from the pool. Sprites are saved in the pool with a key corresponding to their relative path
// (from the resource folder) with the format information and file ending removed.
let non_ui_sprite = sprite_pool.init_sprite("/mage-sheet", Duration::from_secs_f32(0.2))?;
// you can also initialize a sprite pool without any folder at all
let mut sprite_pool2 = sprite::SpritePool::new();
// in this case, you can use lazy initialisation of sprites to fill the sprite pool only with those sprites currently needed.
// Lazy initilisation draws from the pool if possible, from the file system if needed (and loads into the pool in this case) and panics if it can't find anything in the fs.
// Requires a mutable sprite pool!
// For testing purposes, we are loading a sprite we have already loaded - this should be drawn from the pool.
let lazy_sprite =
sprite_pool2.init_sprite_lazy(ctx, "/mage-sheet", Duration::from_secs_f32(0.5))?;
// now load the correct sprite
let lazy_sprite =
sprite_pool2.init_sprite_lazy(ctx, "/moo-sheet", lazy_sprite.get_frame_time())?;
Ok(Self {
gui: ui_sprite,
sprite: non_ui_sprite,
sprite2: lazy_sprite,
pos: Vec2::new(50., 200.),
v: Vec2::new(4., 4.),
})
}
sourcepub fn set_frame_time(&mut self, frame_time: Duration)
pub fn set_frame_time(&mut self, frame_time: Duration)
Set the duration to wait between displaying two succeding frames.
sourcepub fn get_cycle_time(&self) -> Duration
pub fn get_cycle_time(&self) -> Duration
Returns the required time to cycle through every frame of the sprite. Returns 0 if the sprite has a frame time of zero.
sourcepub fn draw_sprite(
&mut self,
ctx: &Context,
canvas: &mut Canvas,
param: impl Into<DrawParam>
)
pub fn draw_sprite( &mut self, ctx: &Context, canvas: &mut Canvas, param: impl Into<DrawParam> )
Draws this sprite as given by the paramters, advancing the displayed frame as needed.
Examples found in repository?
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
fn draw(&mut self, ctx: &mut Context, mouse_listen: bool) -> Result<(), GameError> {
// Once again, we first create a canvas and set a pixel sampler. Note that this time, we dont clear the background.
let mut canvas = ggez::graphics::Canvas::from_frame(ctx, None);
canvas.set_sampler(ggez::graphics::Sampler::nearest_clamp());
// Drawing of our (limited) game state.
// see if we need to mirror our sprite if it moves left
let mirroring = if self.v.x > 0. { 1. } else { -1. };
let scaling = 5.;
self.sprite.draw_sprite(
ctx,
&mut canvas,
DrawParam::new().dest_rect(Rect::new(
self.pos.x - scaling * 4. * mirroring,
self.pos.y - scaling * 8.,
scaling * mirroring,
scaling,
)),
);
let scaling = 2.;
self.sprite2.draw_sprite(
ctx,
&mut canvas,
DrawParam::new().dest_rect(Rect::new(
self.pos.x - scaling * 4. + 32.,
self.pos.y - scaling * 8. + 32.,
scaling,
scaling,
)),
);
// And once again drawing the GUI.
self.gui.draw_to_screen(ctx, &mut canvas, mouse_listen);
canvas.finish(ctx)?;
Ok(())
}