Fixing blurry images
2D games in Rust with ggez
TL; DR - if you are making a pixel art game with rust + ggez and scaling the textures, then you probably want to set the default filtering to Nearest, with the line
graphics::set_default_filter(ctx, graphics::FilterMode::Nearest);
The problem
This basic ggez example that draws an image to the screen.
use ggez;
use ggez::event;
use ggez::graphics;
use ggez::nalgebra;
use ggez::{Context, GameResult};
struct MainState {
image: graphics::Image,
}
impl MainState {
fn new(ctx: &mut Context) -> GameResult<MainState> {
let s = MainState {
image: graphics::Image::new(ctx, "/character.png")?,
};
Ok(s)
}
}
impl event::EventHandler for MainState {
fn update(&mut self, _ctx: &mut Context) -> GameResult {
Ok(())
}
fn draw(&mut self, ctx: &mut Context) -> GameResult {
graphics::draw(
ctx,
&self.image,
graphics::DrawParam::new().scale(nalgebra::Vector2::new(3.0, 3.0)),
)?;
graphics::present(ctx)?;
Ok(())
}
}
pub fn main() -> GameResult {
let cb = ggez::ContextBuilder::new("pixel art example", "ggez");
let (ctx, event_loop) = &mut cb.build()?;
let state = &mut MainState::new(ctx)?;
event::run(ctx, event_loop, state)
}
The result is not what you might expect if you're looking for crisp pixel art. You end up with the blurry image below.
There are two ways around this.
Set the default filtering mode for all images to FilterMode::Nearest
pub fn main() -> GameResult {
let cb = ggez::ContextBuilder::new("pixel art example", "ggez");
graphics::set_default_filter(ctx, graphics::FilterMode::Nearest);
let (ctx, event_loop) = &mut cb.build()?;
let state = &mut MainState::new(ctx)?;
event::run(ctx, event_loop, state)
}
Set the filter mode on an image by image basis
impl MainState {
fn new(ctx: &mut Context) -> GameResult<MainState> {
let mut image = graphics::Image::new(ctx, "/map.png")?
image.set_filter(graphics::FilterMode::Nearest);
let s = MainState { image };
Ok(s)
}
}
Result
In our example, since we're only drawing a single image, the result is the same, nice crisp, non-blurry pixel art!
Links
- I first needed this for OpenMoonstone commit
- I've noticed other people using ggez have run into this as well in this issue
- Art from Open Game Art
Code for this article is available at GitHub - joetsoi/ggez-tutorials in the blurry directory.
Meta
- Written - 13th January 2020
- Updated - 20th January 2020
Code tested on
- rustc 1.40.0 (73528e339 2019-12-16)
- ggez 0.5.1