grid movement
This commit is contained in:
@ -1,17 +1,99 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::{prelude::*, window::PrimaryWindow};
|
||||||
use bevy_inspector_egui::quick::WorldInspectorPlugin;
|
use bevy_inspector_egui::quick::WorldInspectorPlugin;
|
||||||
|
|
||||||
|
const SNAKE_HEAD_COLOR: Color = Color::srgb(0.7, 1.0, 0.7);
|
||||||
|
const ARENA_WIDTH: u32 = 20;
|
||||||
|
const ARENA_HEIGHT: u32 = 15;
|
||||||
|
const WINDOW_WIDTH: f32 = 1280.0;
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
struct SnakeHead;
|
struct SnakeHead;
|
||||||
|
|
||||||
const SNAKE_HEAD_COLOR: Color = Color::srgb(0.7, 0.7, 0.7);
|
#[derive(Component)]
|
||||||
|
struct Position {
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct Size {
|
||||||
|
width: f32,
|
||||||
|
height: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Size {
|
||||||
|
pub fn square(x: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
width: x,
|
||||||
|
height: x,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn snake_movement_system(
|
||||||
|
input: Res<ButtonInput<KeyCode>>,
|
||||||
|
|
||||||
|
mut head_transforms: Query<(&SnakeHead, &mut Position)>,
|
||||||
|
) {
|
||||||
|
for (_, mut pos) in head_transforms.iter_mut() {
|
||||||
|
if input.pressed(KeyCode::ArrowUp) {
|
||||||
|
pos.y += 1;
|
||||||
|
} else if input.pressed(KeyCode::ArrowDown) {
|
||||||
|
pos.y -= 1;
|
||||||
|
} else if input.pressed(KeyCode::ArrowLeft) {
|
||||||
|
pos.x -= 1;
|
||||||
|
} else if input.pressed(KeyCode::ArrowRight) {
|
||||||
|
pos.x += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scale_translation(
|
||||||
|
mut windows: Query<&mut Window, With<PrimaryWindow>>,
|
||||||
|
mut q: Query<(&Size, &mut Transform)>,
|
||||||
|
) {
|
||||||
|
let window = windows.single_mut();
|
||||||
|
for (sprite_size, mut transform) in q.iter_mut() {
|
||||||
|
transform.scale = Vec3::new(
|
||||||
|
sprite_size.width / ARENA_WIDTH as f32 * window.width(),
|
||||||
|
sprite_size.height / ARENA_HEIGHT as f32 * window.height(),
|
||||||
|
1.0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn position_translation(
|
||||||
|
mut windows: Query<&mut Window, With<PrimaryWindow>>,
|
||||||
|
mut q: Query<(&Position, &mut Transform)>,
|
||||||
|
) {
|
||||||
|
// We subtract half the window width because our coordinate system starts at the bottom left, and
|
||||||
|
// Translation starts from the center. We then add half the size of a single tile, because we want
|
||||||
|
// our sprites bottom left corner to be at the bottom left of a tile, not the center.
|
||||||
|
fn convert(pos: f32, bound_window: f32, bound_game: f32) -> f32 {
|
||||||
|
let tile_size = bound_window / bound_game;
|
||||||
|
pos / bound_game * bound_window - (bound_window / 2.) + (tile_size / 2.)
|
||||||
|
}
|
||||||
|
|
||||||
|
let window = windows.single_mut();
|
||||||
|
for (pos, mut transform) in q.iter_mut() {
|
||||||
|
transform.translation = Vec3::new(
|
||||||
|
convert(pos.x as f32, window.width(), ARENA_WIDTH as f32),
|
||||||
|
convert(pos.y as f32, window.height(), ARENA_HEIGHT as f32),
|
||||||
|
0.0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn setup_player(mut commands: Commands) {
|
fn setup_player(mut commands: Commands) {
|
||||||
commands.spawn(Sprite {
|
commands
|
||||||
|
.spawn(Sprite {
|
||||||
color: SNAKE_HEAD_COLOR,
|
color: SNAKE_HEAD_COLOR,
|
||||||
custom_size: Some(Vec2::new(10.0, 10.0)),
|
custom_size: Some(Vec2::new(10.0, 10.0)),
|
||||||
..default()
|
..default()
|
||||||
});
|
})
|
||||||
|
.insert(SnakeHead)
|
||||||
|
.insert(Position { x: 0, y: 0 })
|
||||||
|
.insert(Size::square(1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_camera(mut commands: Commands) {
|
fn setup_camera(mut commands: Commands) {
|
||||||
@ -19,9 +101,25 @@ fn setup_camera(mut commands: Commands) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let systems = snake_movement_system;
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins(DefaultPlugins)
|
.add_plugins(
|
||||||
|
DefaultPlugins.set(WindowPlugin {
|
||||||
|
primary_window: Some(Window {
|
||||||
|
title: "Snake".to_string(),
|
||||||
|
resolution: (
|
||||||
|
WINDOW_WIDTH,
|
||||||
|
WINDOW_WIDTH * (ARENA_HEIGHT as f32 / ARENA_WIDTH as f32),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
..default()
|
||||||
|
}),
|
||||||
|
..default()
|
||||||
|
}),
|
||||||
|
)
|
||||||
.add_plugins(WorldInspectorPlugin::new())
|
.add_plugins(WorldInspectorPlugin::new())
|
||||||
.add_systems(Startup, (setup_camera, setup_player))
|
.add_systems(Startup, (setup_camera, setup_player))
|
||||||
|
.add_systems(Update, systems)
|
||||||
|
.add_systems(PostUpdate, (scale_translation, position_translation))
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user