~starkingdoms/starkingdoms

ref: 7010c6a97904fa90e723a5fc852f3415d9da8902 starkingdoms/crates/unified/src/client/starfield.rs -rw-r--r-- 6.3 KiB
7010c6a9 — ghostly_zsh 3 layer starfield with parallax 5 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use bevy::{app::{App, Startup, Update}, asset::{AssetEvent, AssetServer, Assets}, color::Color, ecs::{event::EventReader, query::{With, Without}, system::{Commands, Query, Res, ResMut}}, image::Image, math::{Vec2, Vec3}, sprite::{Sprite, SpriteImageMode}, transform::components::Transform, window::{Window, WindowResized}};

use crate::{client::Me, ecs::{StarfieldBack, StarfieldFront, StarfieldMid}};

const BACK_STARFIELD_SIZE: f32 = 256.0;
const MID_STARFIELD_SIZE: f32 = 384.0;
const FRONT_STARFIELD_SIZE: f32 = 512.0;

pub fn starfield_plugin(app: &mut App) {
    app
        .add_systems(Startup, setup_starfield)
        .add_systems(Update, fix_starfield)
        .add_systems(Update, resize_starfield)
        .add_systems(Update, update_starfield);
}

pub fn setup_starfield(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
    window: Query<&Window>
) {
    let starfield_handle = asset_server.load("textures/starfield.png");
    let starfield_transp_handle = asset_server.load("textures/starfield_transp.png");
    let window = window.iter().next().unwrap();
    commands.spawn(Sprite {
        image: starfield_handle,
        custom_size: Some(window.size() + Vec2::splat(BACK_STARFIELD_SIZE)),
        image_mode: SpriteImageMode::Tiled {
            tile_x: true,
            tile_y: true,
            stretch_value: 1.0,
        },
        ..Default::default()
    })
        .insert(Transform::from_xyz(0.0, 0.0, 5.0))
        .insert(StarfieldBack);
    commands.spawn(Sprite {
        image: starfield_transp_handle.clone(),
        custom_size: Some(window.size() + Vec2::splat(MID_STARFIELD_SIZE)),
        image_mode: SpriteImageMode::Tiled {
            tile_x: true,
            tile_y: true,
            stretch_value: 1.0,
        },
        ..Default::default()
    })
        .insert(Transform::from_xyz(0.0, 0.0, 4.5))
        .insert(StarfieldMid);
    commands.spawn(Sprite {
        image: starfield_transp_handle,
        custom_size: Some(window.size() + Vec2::splat(FRONT_STARFIELD_SIZE)),
        image_mode: SpriteImageMode::Tiled {
            tile_x: true,
            tile_y: true,
            stretch_value: 1.0,
        },
        ..Default::default()
    })
        .insert(Transform::from_xyz(0.0, 0.0, 4.0))
        .insert(StarfieldFront);
}

pub fn fix_starfield(
    mut starfield_back: Query<&mut Sprite, (With<StarfieldBack>, Without<StarfieldMid>, Without<StarfieldFront>)>,
    mut starfield_mid: Query<&mut Sprite, (With<StarfieldMid>, Without<StarfieldBack>, Without<StarfieldFront>)>,
    mut starfield_front: Query<&mut Sprite, (With<StarfieldFront>, Without<StarfieldBack>, Without<StarfieldMid>)>,
    assets: Res<Assets<Image>>,
    mut asset_events: EventReader<AssetEvent<Image>>,
) {
    for event in asset_events.read() {
        if let AssetEvent::Added { id } = event {
            let mut starfield_back = starfield_back.single_mut().unwrap();
            if *id == starfield_back.image.id() {
                let starfield_image = assets.get(*id).unwrap();
                starfield_back.image_mode = SpriteImageMode::Tiled {
                    tile_x: true,
                    tile_y: true,
                    stretch_value: BACK_STARFIELD_SIZE / (starfield_image.size().x as f32),
                };
            }
            let mut starfield_mid = starfield_mid.single_mut().unwrap();
            if *id == starfield_mid.image.id() {
                let starfield_image = assets.get(*id).unwrap();
                starfield_mid.image_mode = SpriteImageMode::Tiled {
                    tile_x: true,
                    tile_y: true,
                    stretch_value: MID_STARFIELD_SIZE / (starfield_image.size().x as f32),
                };
            }
            let mut starfield_front = starfield_front.single_mut().unwrap();
            if *id == starfield_front.image.id() {
                let starfield_image = assets.get(*id).unwrap();
                starfield_front.image_mode = SpriteImageMode::Tiled {
                    tile_x: true,
                    tile_y: true,
                    stretch_value: FRONT_STARFIELD_SIZE / (starfield_image.size().x as f32),
                };
            }
        }
    }
}

pub fn resize_starfield(
    mut starfield_back: Query<&mut Sprite, (With<StarfieldBack>, Without<StarfieldMid>, Without<StarfieldFront>)>,
    mut starfield_mid: Query<&mut Sprite, (With<StarfieldMid>, Without<StarfieldBack>, Without<StarfieldFront>)>,
    mut starfield_front: Query<&mut Sprite, (With<StarfieldFront>, Without<StarfieldBack>, Without<StarfieldMid>)>,
    mut resize_event: EventReader<WindowResized>,
) {
    for event in resize_event.read() {
        starfield_back.single_mut().unwrap().custom_size =
            Some(Vec2::new(event.width, event.height) + Vec2::splat(BACK_STARFIELD_SIZE*2.0));
        starfield_mid.single_mut().unwrap().custom_size =
            Some(Vec2::new(event.width, event.height) + Vec2::splat(MID_STARFIELD_SIZE*2.0));
        starfield_front.single_mut().unwrap().custom_size =
            Some(Vec2::new(event.width, event.height) + Vec2::splat(FRONT_STARFIELD_SIZE*2.0));
    }
}

pub fn update_starfield(
    mut starfield_back: Query<&mut Transform, (With<StarfieldBack>, Without<Me>, Without<StarfieldMid>, Without<StarfieldFront>)>,
    mut starfield_mid: Query<&mut Transform, (With<StarfieldMid>, Without<Me>, Without<StarfieldBack>, Without<StarfieldFront>)>,
    mut starfield_front: Query<&mut Transform, (With<StarfieldFront>, Without<Me>, Without<StarfieldBack>, Without<StarfieldMid>)>,
    player: Query<&Transform, (With<Me>, Without<StarfieldFront>)>,
) {
    let Some(player) = player.iter().next() else { return };
    let mut starfield_back_pos = starfield_back.single_mut().unwrap();
    let mut starfield_mid_pos = starfield_mid.single_mut().unwrap();
    let mut starfield_front_pos = starfield_front.single_mut().unwrap();
    //starfield_pos.translation = (player.translation / STARFIELD_SIZE).round() * STARFIELD_SIZE;
    starfield_back_pos.translation = player.translation
        + (-player.translation/3.0) % BACK_STARFIELD_SIZE
        - Vec3::new(0.0, 0.0, 5.0);
    starfield_mid_pos.translation = player.translation
        + (-player.translation/2.5) % MID_STARFIELD_SIZE
        - Vec3::new(0.0, 0.0, 4.5);
    starfield_front_pos.translation = player.translation
        + (-player.translation/2.0) % FRONT_STARFIELD_SIZE
        - Vec3::new(0.0, 0.0, 4.0);
}