feat: basic input handling (kb and gamepad!)
This commit is contained in:
parent
b8dde775f1
commit
631ad0c274
215
src/game.rs
215
src/game.rs
@ -1,80 +1,29 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
fn spawn_square_at (commands: &mut Commands, level: u32, position: usize, asset_server: AssetServer) {
|
#[derive(Component)]
|
||||||
let font = asset_server.load("proxima_thin.ttf");
|
pub struct FieldView;
|
||||||
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 (
|
pub fn enter (
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
mut field: ResMut<Field>,
|
mut field: ResMut<Field>,
|
||||||
) {
|
) {
|
||||||
|
let font = asset_server.load("proxima_thin.ttf");
|
||||||
let thread = &mut thread_rng();
|
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];
|
let borders = [-305., 305.];
|
||||||
|
let lines = [-150., 0., 150.];
|
||||||
|
|
||||||
start.shuffle(thread);
|
let border_width = 10.;
|
||||||
*field = Field(start);
|
let line_width = 1.;
|
||||||
|
let length = 620.;
|
||||||
ui(commands, asset_server)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ui (
|
|
||||||
mut commands: Commands,
|
|
||||||
asset_server: Res<AssetServer>,
|
|
||||||
) {
|
|
||||||
let font = asset_server.load("proxima.ttf");
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
ScoreboardUi,
|
ScoreboardUi,
|
||||||
@ -100,23 +49,7 @@ pub fn ui (
|
|||||||
..default()
|
..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
|
// bg
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn(SpriteBundle {
|
||||||
sprite: Sprite { color: bg_color, ..Default::default() },
|
sprite: Sprite { color: bg_color, ..Default::default() },
|
||||||
@ -143,9 +76,131 @@ fn draw_board (commands: &mut Commands) {
|
|||||||
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(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)));
|
commands.spawn(line(line_color, Vec3::new(0.0, lines[mesh], 0.0), Vec3::new(length, line_width, 1.0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
render_field(commands, asset_server, field.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
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 run (mut commands: Commands) {
|
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()
|
||||||
|
}, FieldView));
|
||||||
|
|
||||||
|
commands.spawn((label, FieldView));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn process_inputs (
|
||||||
|
kb: Res<ButtonInput<KeyCode>>,
|
||||||
|
gamepads: Res<Gamepads>,
|
||||||
|
button_inputs: Res<ButtonInput<GamepadButton>>,
|
||||||
|
_axes: Res<Axis<GamepadAxis>>,
|
||||||
|
field: ResMut<Field>,
|
||||||
|
score: ResMut<Score>,
|
||||||
|
) {
|
||||||
|
|
||||||
|
for key in kb.get_just_pressed() {
|
||||||
|
match key {
|
||||||
|
KeyCode::ArrowUp | KeyCode::KeyW => {
|
||||||
|
return move_field(MoveDirection::Up, field, score);
|
||||||
|
},
|
||||||
|
KeyCode::ArrowDown | KeyCode::KeyS => {
|
||||||
|
return move_field(MoveDirection::Down, field, score);
|
||||||
|
},
|
||||||
|
KeyCode::ArrowLeft | KeyCode::KeyA => {
|
||||||
|
return move_field(MoveDirection::Left, field, score);
|
||||||
|
},
|
||||||
|
KeyCode::ArrowRight | KeyCode::KeyD => {
|
||||||
|
return move_field(MoveDirection::Right, field, score);
|
||||||
|
},
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for gamepad in gamepads.iter() {
|
||||||
|
use GamepadButtonType as GBT;
|
||||||
|
|
||||||
|
// is_current_gamepad_button_pressed (i ain't writing this)
|
||||||
|
let icgbp = |gbt: GamepadButtonType| button_inputs.just_pressed(GamepadButton::new(gamepad, gbt));
|
||||||
|
|
||||||
|
// @TODO: think about throttling stick inputs; if this is possible, reintroduce stick
|
||||||
|
// controls (with custom actuation point)
|
||||||
|
// https://bevy-cheatbook.github.io/input/gamepad.html#gamepad-settings
|
||||||
|
if icgbp(GBT::DPadLeft) {
|
||||||
|
return move_field(MoveDirection::Left, field, score);
|
||||||
|
} else if icgbp(GBT::DPadRight) {
|
||||||
|
return move_field(MoveDirection::Right, field, score);
|
||||||
|
} else if icgbp(GBT::DPadUp) {
|
||||||
|
return move_field(MoveDirection::Up, field, score);
|
||||||
|
} else if icgbp(GBT::DPadDown) {
|
||||||
|
return move_field(MoveDirection::Down, field, score);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn move_field (
|
||||||
|
direction: MoveDirection,
|
||||||
|
field: ResMut<Field>,
|
||||||
|
score: ResMut<Score>
|
||||||
|
) {
|
||||||
|
|
||||||
|
println!("{:?} {:?}", direction, score);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn redraw_field () {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,12 +14,12 @@ impl Plugin for SqPlugin {
|
|||||||
// add things to your app here
|
// add things to your app here
|
||||||
app
|
app
|
||||||
.insert_resource(ClearColor(BG_COLOR))
|
.insert_resource(ClearColor(BG_COLOR))
|
||||||
.insert_state(State4096::Menu)
|
.insert_state(State4096::Game)
|
||||||
.insert_state(InGameState::Static)
|
.insert_state(InGameState::Static)
|
||||||
.insert_resource(Score(0))
|
.insert_resource(Score(0))
|
||||||
.insert_resource(Field(vec![]))
|
.insert_resource(Field(vec![]))
|
||||||
.add_systems(Startup, setup::setup)
|
.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, (game::update_scoreboard, game::process_inputs).run_if(in_state(State4096::Game)))
|
||||||
.add_systems(Update, (menu::actions, common::button_system).run_if(in_state(State4096::Menu)))
|
.add_systems(Update, (menu::actions, common::button_system).run_if(in_state(State4096::Menu)))
|
||||||
.add_systems(OnEnter(State4096::Menu), menu::enter)
|
.add_systems(OnEnter(State4096::Menu), menu::enter)
|
||||||
.add_systems(OnExit(State4096::Menu), common::despawn_screen::<menu::Menu>)
|
.add_systems(OnExit(State4096::Menu), common::despawn_screen::<menu::Menu>)
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
pub use bevy::prelude::*;
|
pub use bevy::prelude::*;
|
||||||
pub use rand::{ seq::SliceRandom, thread_rng, Rng };
|
pub use rand::{ seq::SliceRandom, thread_rng, Rng };
|
||||||
|
|
||||||
#[derive(Resource, Deref, DerefMut)]
|
#[derive(Resource, Deref, DerefMut, Debug)]
|
||||||
pub struct Score (pub usize);
|
pub struct Score (pub usize);
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
@ -11,6 +11,13 @@ pub struct ScoreboardUi;
|
|||||||
#[derive(Resource, Deref, DerefMut)]
|
#[derive(Resource, Deref, DerefMut)]
|
||||||
pub struct Field (pub Vec<u32>);
|
pub struct Field (pub Vec<u32>);
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub enum MoveDirection {
|
||||||
|
Up,
|
||||||
|
Down,
|
||||||
|
Left,
|
||||||
|
Right
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(States, Clone, Debug, Default, PartialEq, Eq, Hash)]
|
#[derive(States, Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||||
pub enum State4096 {
|
pub enum State4096 {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user