• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Xevion / Pac-Man / 17012447928

16 Aug 2025 08:12PM UTC coverage: 38.85% (-12.3%) from 51.196%
17012447928

Pull #3

github

Xevion
chore: add cargo checks to pre-commit
Pull Request #3: ECS Refactor

161 of 1172 new or added lines in 23 files covered. (13.74%)

9 existing lines in 4 files now uncovered.

777 of 2000 relevant lines covered (38.85%)

101.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/systems/render.rs
1
use crate::error::{GameError, TextureError};
2
use crate::map::builder::Map;
3
use crate::systems::components::{DeltaTime, DirectionalAnimated, RenderDirty, Renderable};
4
use crate::systems::movement::{Position, Velocity};
5
use crate::texture::sprite::SpriteAtlas;
6
use bevy_ecs::entity::Entity;
7
use bevy_ecs::event::EventWriter;
8
use bevy_ecs::prelude::{Changed, Or, RemovedComponents};
9
use bevy_ecs::system::{NonSendMut, Query, Res, ResMut};
10
use sdl2::rect::{Point, Rect};
11
use sdl2::render::{Canvas, Texture};
12
use sdl2::video::Window;
13

14
#[allow(clippy::type_complexity)]
NEW
15
pub fn dirty_render_system(
×
NEW
16
    mut dirty: ResMut<RenderDirty>,
×
NEW
17
    changed_renderables: Query<(), Or<(Changed<Renderable>, Changed<Position>)>>,
×
NEW
18
    removed_renderables: RemovedComponents<Renderable>,
×
NEW
19
) {
×
NEW
20
    if !changed_renderables.is_empty() || !removed_renderables.is_empty() {
×
NEW
21
        dirty.0 = true;
×
NEW
22
    }
×
NEW
23
}
×
24

25
/// Updates the directional animated texture of an entity.
26
///
27
/// This runs before the render system so it can update the sprite based on the current direction of travel, as well as whether the entity is moving.
NEW
28
pub fn directional_render_system(
×
NEW
29
    dt: Res<DeltaTime>,
×
NEW
30
    mut renderables: Query<(&Position, &Velocity, &mut DirectionalAnimated, &mut Renderable)>,
×
NEW
31
    mut errors: EventWriter<GameError>,
×
NEW
32
) {
×
NEW
33
    for (position, velocity, mut texture, mut renderable) in renderables.iter_mut() {
×
NEW
34
        let stopped = matches!(position, Position::Stopped { .. });
×
NEW
35
        let current_direction = velocity.direction;
×
36

NEW
37
        let texture = if stopped {
×
NEW
38
            texture.stopped_textures[current_direction.as_usize()].as_mut()
×
39
        } else {
NEW
40
            texture.textures[current_direction.as_usize()].as_mut()
×
41
        };
42

NEW
43
        if let Some(texture) = texture {
×
NEW
44
            if !stopped {
×
NEW
45
                texture.tick(dt.0);
×
NEW
46
            }
×
NEW
47
            let new_tile = *texture.current_tile();
×
NEW
48
            if renderable.sprite != new_tile {
×
NEW
49
                renderable.sprite = new_tile;
×
NEW
50
            }
×
51
        } else {
NEW
52
            errors.write(TextureError::RenderFailed("Entity has no texture".to_string()).into());
×
NEW
53
            continue;
×
54
        }
55
    }
NEW
56
}
×
57

58
/// A non-send resource for the map texture. This just wraps the texture with a type so it can be differentiated when exposed as a resource.
59
pub struct MapTextureResource(pub Texture<'static>);
60

61
/// A non-send resource for the backbuffer texture. This just wraps the texture with a type so it can be differentiated when exposed as a resource.
62
pub struct BackbufferResource(pub Texture<'static>);
63

64
#[allow(clippy::too_many_arguments)]
NEW
65
pub fn render_system(
×
NEW
66
    mut canvas: NonSendMut<&mut Canvas<Window>>,
×
NEW
67
    map_texture: NonSendMut<MapTextureResource>,
×
NEW
68
    mut backbuffer: NonSendMut<BackbufferResource>,
×
NEW
69
    mut atlas: NonSendMut<SpriteAtlas>,
×
NEW
70
    map: Res<Map>,
×
NEW
71
    dirty: Res<RenderDirty>,
×
NEW
72
    renderables: Query<(Entity, &Renderable, &Position)>,
×
NEW
73
    mut errors: EventWriter<GameError>,
×
NEW
74
) {
×
NEW
75
    if !dirty.0 {
×
NEW
76
        return;
×
NEW
77
    }
×
NEW
78
    // Render to backbuffer
×
NEW
79
    canvas
×
NEW
80
        .with_texture_canvas(&mut backbuffer.0, |backbuffer_canvas| {
×
NEW
81
            // Clear the backbuffer
×
NEW
82
            backbuffer_canvas.set_draw_color(sdl2::pixels::Color::BLACK);
×
NEW
83
            backbuffer_canvas.clear();
×
84

85
            // Copy the pre-rendered map texture to the backbuffer
NEW
86
            if let Err(e) = backbuffer_canvas.copy(&map_texture.0, None, None) {
×
NEW
87
                errors.write(TextureError::RenderFailed(e.to_string()).into());
×
NEW
88
            }
×
89

90
            // Render all entities to the backbuffer
NEW
91
            for (_, renderable, position) in renderables
×
NEW
92
                .iter()
×
NEW
93
                .sort_by_key::<(Entity, &Renderable, &Position), _>(|(_, renderable, _)| renderable.layer)
×
NEW
94
                .rev()
×
95
            {
NEW
96
                if !renderable.visible {
×
NEW
97
                    continue;
×
NEW
98
                }
×
NEW
99

×
NEW
100
                let pos = position.get_pixel_position(&map.graph);
×
NEW
101
                match pos {
×
NEW
102
                    Ok(pos) => {
×
NEW
103
                        let dest = Rect::from_center(
×
NEW
104
                            Point::from((pos.x as i32, pos.y as i32)),
×
NEW
105
                            renderable.sprite.size.x as u32,
×
NEW
106
                            renderable.sprite.size.y as u32,
×
NEW
107
                        );
×
NEW
108

×
NEW
109
                        renderable
×
NEW
110
                            .sprite
×
NEW
111
                            .render(backbuffer_canvas, &mut atlas, dest)
×
NEW
112
                            .err()
×
NEW
113
                            .map(|e| errors.write(TextureError::RenderFailed(e.to_string()).into()));
×
NEW
114
                    }
×
NEW
115
                    Err(e) => {
×
NEW
116
                        errors.write(e);
×
NEW
117
                    }
×
118
                }
119
            }
NEW
120
        })
×
NEW
121
        .err()
×
NEW
122
        .map(|e| errors.write(TextureError::RenderFailed(e.to_string()).into()));
×
NEW
123
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc