feat: menu system, basic state handling, more code splitting/cleanup
This commit is contained in:
parent
391ef7fd8b
commit
b8dde775f1
@ -7,7 +7,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.86"
|
anyhow = "1.0.86"
|
||||||
bevy = { version = "0.14.0", features = ["dynamic_linking"] }
|
bevy = { version = "0.14.0", features = ["dynamic_linking", "subpixel_glyph_atlas"] }
|
||||||
itertools = "0.13.0"
|
itertools = "0.13.0"
|
||||||
log = { version = "*", features = ["max_level_debug", "release_max_level_warn"] }
|
log = { version = "*", features = ["max_level_debug", "release_max_level_warn"] }
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
|||||||
23
src/common.rs
Normal file
23
src/common.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub fn button_system (
|
||||||
|
mut interaction_query: Query<
|
||||||
|
(&Interaction, &mut BackgroundColor),
|
||||||
|
(Changed<Interaction>, With<Button>),
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
for (interaction, mut color) in &mut interaction_query {
|
||||||
|
*color = BackgroundColor(match *interaction {
|
||||||
|
Interaction::Pressed => BUTTON_BG_COLOR_HOVER,
|
||||||
|
Interaction::Hovered => BUTTON_BG_COLOR_HOVER,
|
||||||
|
Interaction::None => BUTTON_BG_COLOR,
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn despawn_screen <T: Component> (to_despawn: Query<Entity, With<T>>, mut commands: Commands) {
|
||||||
|
for entity in &to_despawn {
|
||||||
|
commands.entity(entity).despawn_recursive();
|
||||||
|
}
|
||||||
|
}
|
||||||
151
src/game.rs
Normal file
151
src/game.rs
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
fn spawn_square_at (commands: &mut Commands, level: u32, position: usize, asset_server: AssetServer) {
|
||||||
|
let font = asset_server.load("proxima_thin.ttf");
|
||||||
|
let Some(&(x, y)) = sq_origins.get(position) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let text = 2i32.pow(level);
|
||||||
|
let label = Text2dBundle {
|
||||||
|
text: Text::from_section(text.to_string(), TextStyle {
|
||||||
|
font,
|
||||||
|
font_size: 44.,
|
||||||
|
color: Color::WHITE,
|
||||||
|
}),
|
||||||
|
transform: Transform {
|
||||||
|
translation: Vec3::new(x, y, 0.0),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
commands.spawn(SpriteBundle {
|
||||||
|
sprite: Sprite {
|
||||||
|
color: sq_colors[level as usize % sq_colors.len()],
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
transform: Transform {
|
||||||
|
translation: Vec3::new(x, y, 0.0),
|
||||||
|
scale: Vec3::new(148.0, 148.0, 1.0),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
commands.spawn(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_scoreboard (score: Res<Score>, mut query: Query<&mut Text, With<ScoreboardUi>>) {
|
||||||
|
let mut text = query.single_mut();
|
||||||
|
text.sections[1].value = score.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_field (
|
||||||
|
mut commands: Commands,
|
||||||
|
asset_server: Res<AssetServer>,
|
||||||
|
field: Res<Field>,
|
||||||
|
) {
|
||||||
|
for (idx, &val) in field.iter().enumerate() {
|
||||||
|
if val > 0 {
|
||||||
|
spawn_square_at(&mut commands, val, idx, asset_server.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enter (
|
||||||
|
mut commands: Commands,
|
||||||
|
asset_server: Res<AssetServer>,
|
||||||
|
mut field: ResMut<Field>,
|
||||||
|
) {
|
||||||
|
let thread = &mut thread_rng();
|
||||||
|
|
||||||
|
let mut start = vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1];
|
||||||
|
|
||||||
|
start.shuffle(thread);
|
||||||
|
*field = Field(start);
|
||||||
|
|
||||||
|
ui(commands, asset_server)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ui (
|
||||||
|
mut commands: Commands,
|
||||||
|
asset_server: Res<AssetServer>,
|
||||||
|
) {
|
||||||
|
let font = asset_server.load("proxima.ttf");
|
||||||
|
|
||||||
|
|
||||||
|
commands.spawn((
|
||||||
|
ScoreboardUi,
|
||||||
|
TextBundle::from_sections([
|
||||||
|
TextSection::new(
|
||||||
|
"score: ",
|
||||||
|
TextStyle {
|
||||||
|
font: font.clone(),
|
||||||
|
font_size: SCOREBOARD_FONT_SIZE,
|
||||||
|
color: TEXT_COLOR,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextSection::from_style(TextStyle {
|
||||||
|
font,
|
||||||
|
font_size: SCOREBOARD_FONT_SIZE,
|
||||||
|
color: SCORE_COLOR,
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
.with_style(Style {
|
||||||
|
position_type: PositionType::Absolute,
|
||||||
|
top: SCOREBOARD_TEXT_PADDING,
|
||||||
|
left: SCOREBOARD_TEXT_PADDING,
|
||||||
|
..default()
|
||||||
|
}),
|
||||||
|
));
|
||||||
|
|
||||||
|
draw_board(&mut commands);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn draw_board (commands: &mut Commands) {
|
||||||
|
let borders = [-305., 305.];
|
||||||
|
let lines = [-150., 0., 150.];
|
||||||
|
|
||||||
|
let border_width = 10.;
|
||||||
|
let line_width = 1.;
|
||||||
|
let length = 620.;
|
||||||
|
|
||||||
|
let border_color = Color::BLACK;
|
||||||
|
let line_color = Color::srgba(0., 0., 0., 0.667);
|
||||||
|
let bg_color = Color::srgba(0.2, 0.01, 0.5, 0.632);
|
||||||
|
|
||||||
|
// bg
|
||||||
|
commands.spawn(SpriteBundle {
|
||||||
|
sprite: Sprite { color: bg_color, ..Default::default() },
|
||||||
|
transform: Transform {
|
||||||
|
scale: Vec3::new(length, length, 1.0),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
let line = |color: Color, translation: Vec3, scale: Vec3| SpriteBundle {
|
||||||
|
sprite: Sprite { color, ..Default::default() },
|
||||||
|
transform: Transform { translation, scale, ..Default::default() },
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
// @TODO variable grid size
|
||||||
|
for border in 0..2 {
|
||||||
|
commands.spawn(line(border_color, Vec3::new(borders[border], 0.0, 0.0), Vec3::new(border_width, length, 1.0)));
|
||||||
|
commands.spawn(line(border_color, Vec3::new(0.0, borders[border], 0.0), Vec3::new(length, border_width, 1.0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
for mesh in 0..3 {
|
||||||
|
commands.spawn(line(line_color, Vec3::new(lines[mesh], 0.0, 0.0), Vec3::new(line_width, length, 1.0)));
|
||||||
|
commands.spawn(line(line_color, Vec3::new(0.0, lines[mesh], 0.0), Vec3::new(length, line_width, 1.0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn run (mut commands: Commands) {
|
||||||
|
|
||||||
|
}
|
||||||
77
src/main.rs
77
src/main.rs
@ -1,4 +1,7 @@
|
|||||||
mod setup;
|
mod setup;
|
||||||
|
mod game;
|
||||||
|
mod menu;
|
||||||
|
mod common;
|
||||||
mod prelude;
|
mod prelude;
|
||||||
|
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
@ -7,76 +10,25 @@ use prelude::*;
|
|||||||
impl Plugin for SqPlugin {
|
impl Plugin for SqPlugin {
|
||||||
fn build (&self, app: &mut App) {
|
fn build (&self, app: &mut App) {
|
||||||
|
|
||||||
let thread = &mut thread_rng();
|
|
||||||
|
|
||||||
let mut start = vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1];
|
|
||||||
|
|
||||||
start.shuffle(thread);
|
|
||||||
|
|
||||||
// add things to your app here
|
// add things to your app here
|
||||||
app
|
app
|
||||||
.insert_resource(Score(0))
|
|
||||||
.insert_resource(ClearColor(BG_COLOR))
|
.insert_resource(ClearColor(BG_COLOR))
|
||||||
.insert_resource(Field(start))
|
.insert_state(State4096::Menu)
|
||||||
|
.insert_state(InGameState::Static)
|
||||||
|
.insert_resource(Score(0))
|
||||||
|
.insert_resource(Field(vec![]))
|
||||||
|
.add_systems(Startup, setup::setup)
|
||||||
|
.add_systems(Update, (game::render_field, game::update_scoreboard, game::run).run_if(in_state(State4096::Game)))
|
||||||
|
.add_systems(Update, (menu::actions, common::button_system).run_if(in_state(State4096::Menu)))
|
||||||
|
.add_systems(OnEnter(State4096::Menu), menu::enter)
|
||||||
|
.add_systems(OnExit(State4096::Menu), common::despawn_screen::<menu::Menu>)
|
||||||
|
.add_systems(OnEnter(State4096::Game), game::enter)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn spawn_square_at (commands: &mut Commands, level: u32, position: usize, asset_server: AssetServer) {
|
|
||||||
let font = asset_server.load("proxima_thin.ttf");
|
|
||||||
let Some(&(x, y)) = sq_origins.get(position) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let text = 2i32.pow(level);
|
|
||||||
let label = Text2dBundle {
|
|
||||||
text: Text::from_section(text.to_string(), TextStyle {
|
|
||||||
font,
|
|
||||||
font_size: 44.,
|
|
||||||
color: Color::WHITE,
|
|
||||||
}),
|
|
||||||
transform: Transform {
|
|
||||||
translation: Vec3::new(x, y, 0.0),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
commands.spawn(SpriteBundle {
|
|
||||||
sprite: Sprite {
|
|
||||||
color: sq_colors[level as usize % sq_colors.len()],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
transform: Transform {
|
|
||||||
translation: Vec3::new(x, y, 0.0),
|
|
||||||
scale: Vec3::new(148.0, 148.0, 1.0),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
|
|
||||||
commands.spawn(label);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_scoreboard (score: Res<Score>, mut query: Query<&mut Text, With<ScoreboardUi>>) {
|
|
||||||
let mut text = query.single_mut();
|
|
||||||
text.sections[1].value = score.to_string();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_field (
|
|
||||||
mut commands: Commands,
|
|
||||||
asset_server: Res<AssetServer>,
|
|
||||||
field: Res<Field>,
|
|
||||||
) {
|
|
||||||
for (idx, &val) in field.iter().enumerate() {
|
|
||||||
if val > 0 {
|
|
||||||
spawn_square_at(&mut commands, val, idx, asset_server.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn main () {
|
fn main () {
|
||||||
App::new()
|
App::new()
|
||||||
@ -87,8 +39,5 @@ fn main () {
|
|||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}), SqPlugin))
|
}), SqPlugin))
|
||||||
.add_systems(Startup, setup::setup)
|
|
||||||
.add_systems(Update, update_scoreboard)
|
|
||||||
.add_systems(Update, render_field)
|
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|||||||
107
src/menu.rs
Normal file
107
src/menu.rs
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct Menu;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub enum MenuAction {
|
||||||
|
New,
|
||||||
|
Continue,
|
||||||
|
Leaderboards,
|
||||||
|
Settings,
|
||||||
|
Quit,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn enter (mut commands: Commands, asr: Res<AssetServer>) {
|
||||||
|
let f1 = asr.load("proxima.ttf");
|
||||||
|
let f2 = asr.load("proxima_thin.ttf");
|
||||||
|
|
||||||
|
|
||||||
|
commands.spawn((NodeBundle {
|
||||||
|
style: Style {
|
||||||
|
width: Val::Percent(100.0),
|
||||||
|
height: Val::Percent(100.0),
|
||||||
|
align_items: AlignItems::Center,
|
||||||
|
justify_content: JustifyContent::FlexStart,
|
||||||
|
flex_direction: FlexDirection::Column,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
border_color: BorderColor(Color::srgb(0.749, 0.737, 0.569)),
|
||||||
|
..Default::default()
|
||||||
|
}, Menu)).with_children(|p| {
|
||||||
|
p.spawn(TextBundle {
|
||||||
|
text: Text::from_section("4096 Game", TextStyle {
|
||||||
|
font_size: 72.0, color: Color::BLACK, font: f1.clone()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
p.spawn(TextBundle {
|
||||||
|
text: Text::from_section("totally not a clone of some game that was popular 10 years ago", TextStyle {
|
||||||
|
font_size: 20.0, color: Color::BLACK, font: f2.clone()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
create_button(p, &asr, Some(UiRect::top(Val::Px(120.0))), "New Game", MenuAction::New);
|
||||||
|
create_button(p, &asr, None, "Continue", MenuAction::Continue);
|
||||||
|
create_button(p, &asr, None, "Leaderboards", MenuAction::Leaderboards);
|
||||||
|
create_button(p, &asr, None, "Settings", MenuAction::Settings);
|
||||||
|
create_button(p, &asr, None, "Quit to OS", MenuAction::Quit);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn create_button (parent: &mut ChildBuilder, asset_server: &Res<AssetServer>, extra_margin: Option<UiRect>, text: impl Into<String>, action: MenuAction) {
|
||||||
|
let font = asset_server.load("proxima_thin.ttf");
|
||||||
|
parent.spawn((ButtonBundle {
|
||||||
|
style: Style {
|
||||||
|
margin: if let Some(extra_margin) = extra_margin { extra_margin } else { Default::default() },
|
||||||
|
width: Val::Px(350.0),
|
||||||
|
height: Val::Px(65.0),
|
||||||
|
border: UiRect::all(Val::Px(5.0)),
|
||||||
|
// horizontally center child text
|
||||||
|
justify_content: JustifyContent::Center,
|
||||||
|
// vertically center child text
|
||||||
|
align_items: AlignItems::Center,
|
||||||
|
..default()
|
||||||
|
|
||||||
|
},
|
||||||
|
// border_radius: BorderRadius::all(Val::Px(12.)),
|
||||||
|
// image: UiImage::default().with_color(BUTTON_BG_COLOR),
|
||||||
|
// background_color: BackgroundColor(BUTTON_BG_COLOR),
|
||||||
|
..Default::default()
|
||||||
|
}, action)).with_children(|p| {
|
||||||
|
p.spawn(TextBundle {
|
||||||
|
text: Text::from_section(text, TextStyle {
|
||||||
|
font_size: 40.0, color: Color::WHITE, font
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn actions (
|
||||||
|
interaction_query: Query<
|
||||||
|
(&Interaction, &MenuAction),
|
||||||
|
(Changed<Interaction>, With<Button>),
|
||||||
|
>,
|
||||||
|
mut app_exit_events: EventWriter<AppExit>,
|
||||||
|
mut game_state: ResMut<NextState<State4096>>,
|
||||||
|
) {
|
||||||
|
for (interaction, menu_action) in &interaction_query {
|
||||||
|
if *interaction == Interaction::Pressed {
|
||||||
|
match menu_action {
|
||||||
|
MenuAction::Quit => {
|
||||||
|
app_exit_events.send(AppExit::Success);
|
||||||
|
},
|
||||||
|
MenuAction::New => {
|
||||||
|
game_state.set(State4096::Game);
|
||||||
|
},
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,10 +12,28 @@ pub struct ScoreboardUi;
|
|||||||
pub struct Field (pub Vec<u32>);
|
pub struct Field (pub Vec<u32>);
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(States, Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||||
|
pub enum State4096 {
|
||||||
|
#[default]
|
||||||
|
Menu,
|
||||||
|
Game,
|
||||||
|
GameOver,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(States, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub enum InGameState {
|
||||||
|
Static,
|
||||||
|
Transtion (Vec<u32>), // target state,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub const BG_COLOR: Color = Color::srgb(0.949, 0.937, 0.769);
|
pub const BG_COLOR: Color = Color::srgb(0.949, 0.937, 0.769);
|
||||||
pub const SCOREBOARD_FONT_SIZE: f32 = 44.0;
|
pub const SCOREBOARD_FONT_SIZE: f32 = 44.0;
|
||||||
pub const TEXT_COLOR: Color = Color::BLACK;
|
pub const TEXT_COLOR: Color = Color::BLACK;
|
||||||
pub const SCORE_COLOR: Color = Color::srgb(0.0, 0.05, 0.66);
|
pub const SCORE_COLOR: Color = Color::srgb(0.0, 0.05, 0.66);
|
||||||
|
pub const BUTTON_BG_COLOR: Color = Color::srgb(0.5, 0.5, 0.99);
|
||||||
|
pub const BUTTON_BG_COLOR_HOVER: Color = Color::srgb(0.9, 0.2, 0.89);
|
||||||
|
|
||||||
pub const SCOREBOARD_TEXT_PADDING: Val = Val::Px(22.0);
|
pub const SCOREBOARD_TEXT_PADDING: Val = Val::Px(22.0);
|
||||||
|
|
||||||
pub struct SqPlugin;
|
pub struct SqPlugin;
|
||||||
|
|||||||
72
src/setup.rs
72
src/setup.rs
@ -6,75 +6,7 @@ pub fn setup (
|
|||||||
mut _materials: ResMut<Assets<ColorMaterial>>,
|
mut _materials: ResMut<Assets<ColorMaterial>>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
) {
|
) {
|
||||||
let font = asset_server.load("proxima.ttf");
|
|
||||||
|
|
||||||
commands.spawn(Camera2dBundle::default());
|
commands.spawn(Camera2dBundle::default());
|
||||||
|
let _: Handle<Font> = asset_server.load("proxima.ttf");
|
||||||
commands.spawn((
|
let _: Handle<Font> = asset_server.load("proxima_thin.ttf");
|
||||||
ScoreboardUi,
|
|
||||||
TextBundle::from_sections([
|
|
||||||
TextSection::new(
|
|
||||||
"score: ",
|
|
||||||
TextStyle {
|
|
||||||
font: font.clone(),
|
|
||||||
font_size: SCOREBOARD_FONT_SIZE,
|
|
||||||
color: TEXT_COLOR,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
TextSection::from_style(TextStyle {
|
|
||||||
font,
|
|
||||||
font_size: SCOREBOARD_FONT_SIZE,
|
|
||||||
color: SCORE_COLOR,
|
|
||||||
}),
|
|
||||||
])
|
|
||||||
.with_style(Style {
|
|
||||||
position_type: PositionType::Absolute,
|
|
||||||
top: SCOREBOARD_TEXT_PADDING,
|
|
||||||
left: SCOREBOARD_TEXT_PADDING,
|
|
||||||
..default()
|
|
||||||
}),
|
|
||||||
));
|
|
||||||
|
|
||||||
draw_board(&mut commands);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn draw_board (commands: &mut Commands) {
|
|
||||||
let borders = [-305., 305.];
|
|
||||||
let lines = [-150., 0., 150.];
|
|
||||||
|
|
||||||
let border_width = 10.;
|
|
||||||
let line_width = 1.;
|
|
||||||
let length = 620.;
|
|
||||||
|
|
||||||
let border_color = Color::BLACK;
|
|
||||||
let line_color = Color::srgba(0., 0., 0., 0.667);
|
|
||||||
let bg_color = Color::srgba(0.2, 0.01, 0.5, 0.632);
|
|
||||||
|
|
||||||
// bg
|
|
||||||
commands.spawn(SpriteBundle {
|
|
||||||
sprite: Sprite { color: bg_color, ..Default::default() },
|
|
||||||
transform: Transform {
|
|
||||||
scale: Vec3::new(length, length, 1.0),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
|
|
||||||
let line = |color: Color, translation: Vec3, scale: Vec3| SpriteBundle {
|
|
||||||
sprite: Sprite { color, ..Default::default() },
|
|
||||||
transform: Transform { translation, scale, ..Default::default() },
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
// @TODO variable grid size
|
|
||||||
for border in 0..2 {
|
|
||||||
commands.spawn(line(border_color, Vec3::new(borders[border], 0.0, 0.0), Vec3::new(border_width, length, 1.0)));
|
|
||||||
commands.spawn(line(border_color, Vec3::new(0.0, borders[border], 0.0), Vec3::new(length, border_width, 1.0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
for mesh in 0..3 {
|
|
||||||
commands.spawn(line(line_color, Vec3::new(lines[mesh], 0.0, 0.0), Vec3::new(line_width, length, 1.0)));
|
|
||||||
commands.spawn(line(line_color, Vec3::new(0.0, lines[mesh], 0.0), Vec3::new(length, line_width, 1.0)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user