@@ 1,6 1,7 @@
mod incoming_planets;
mod incoming_parts;
mod key_input;
+mod starfield;
use std::net::{SocketAddr, UdpSocket};
use std::time::SystemTime;
@@ 15,6 16,7 @@ use bevy_replicon_renet2::RenetChannelsExt;
use crate::client::incoming_parts::incoming_parts_plugin;
use crate::client::incoming_planets::incoming_planets_plugin;
use crate::client::key_input::key_input_plugin;
+use crate::client::starfield::starfield_plugin;
use crate::ecs::{Ball, CursorWorldCoordinates, Ground, MainCamera, Player, SendBallHere};
pub struct ClientPlugin {
@@ 53,7 55,8 @@ impl Plugin for ClientPlugin {
.add_systems(Update, find_me)
.add_plugins(incoming_planets_plugin)
.add_plugins(incoming_parts_plugin)
- .add_plugins(key_input_plugin);
+ .add_plugins(key_input_plugin)
+ .add_plugins(starfield_plugin);
}
}
@@ 74,6 77,10 @@ fn find_me(mut commands: Commands, q_clients: Query<(Entity, &Player), Added<Pla
fn setup_graphics(mut commands: Commands) {
commands.spawn(Camera2d::default())
.insert(MainCamera);
+ commands.spawn(Sprite {
+
+ ..default()
+ });
}
fn follow_camera(mut camera: Query<&mut Transform, (With<MainCamera>, Without<Me>)>, mut player: Query<&Transform, With<Me>>) {
@@ 0,0 1,73 @@
+use bevy::{app::{App, Startup, Update}, asset::{AssetEvent, AssetServer, Assets}, ecs::{event::EventReader, query::{With, Without}, system::{Commands, Query, Res, ResMut}}, image::Image, math::Vec2, sprite::{Sprite, SpriteImageMode}, transform::components::Transform, window::{Window, WindowResized}};
+
+use crate::{client::Me, ecs::StarfieldFront};
+
+const 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 window = window.iter().next().unwrap();
+ commands.spawn(Sprite {
+ image: starfield_handle,
+ custom_size: Some(window.size() + Vec2::splat(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, 0.0))
+ .insert(StarfieldFront);
+}
+
+pub fn fix_starfield(
+ mut starfield_front: Query<&mut Sprite, With<StarfieldFront>>,
+ 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_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: STARFIELD_SIZE / (starfield_image.size().x as f32),
+ };
+ }
+ }
+ }
+}
+
+pub fn resize_starfield(
+ mut starfield_front: Query<&mut Sprite, With<StarfieldFront>>,
+ mut resize_event: EventReader<WindowResized>,
+) {
+ for event in resize_event.read() {
+ starfield_front.single_mut().unwrap().custom_size =
+ Some(Vec2::new(event.width, event.height) + Vec2::splat(STARFIELD_SIZE));
+ }
+}
+
+pub fn update_starfield(
+ mut starfield: Query<&mut Transform, (With<StarfieldFront>, Without<Me>)>,
+ player: Query<&Transform, (With<Me>, Without<StarfieldFront>)>,
+) {
+ let Some(player) = player.iter().next() else { return };
+ let mut starfield_pos = starfield.single_mut().unwrap();
+ starfield_pos.translation = (player.translation / STARFIELD_SIZE).round() * STARFIELD_SIZE;
+}
@@ 13,6 13,10 @@ pub struct Ball;
pub struct Ground;
#[derive(Component)]
pub struct MainCamera;
+#[derive(Component)]
+pub struct StarfieldFront;
+#[derive(Component)]
+pub struct StarfieldBack;
#[derive(Resource, Default)]
pub struct CursorWorldCoordinates(pub Option<Vec2>);