bevy-snake-tutorial/src/main.rs

148 lines
4.1 KiB
Rust
Raw Normal View History

2020-11-04 10:09:02 -05:00
use bevy::prelude::*;
2020-12-24 14:07:46 -05:00
use bevy::render::pass::ClearColor;
2020-12-24 14:14:18 -05:00
use rand::prelude::random;
use std::time::Duration;
2020-11-04 10:09:02 -05:00
2020-12-24 14:01:05 -05:00
const ARENA_WIDTH: u32 = 10;
const ARENA_HEIGHT: u32 = 10;
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
struct Position {
x: i32,
y: i32,
}
struct Size {
width: f32,
height: f32,
}
impl Size {
pub fn square(x: f32) -> Self {
Self {
width: x,
height: x,
}
}
}
2020-12-24 13:41:55 -05:00
struct SnakeHead;
struct Materials {
head_material: Handle<ColorMaterial>,
2020-12-24 14:14:18 -05:00
food_material: Handle<ColorMaterial>,
}
struct Food;
struct FoodSpawnTimer(Timer);
impl Default for FoodSpawnTimer {
fn default() -> Self {
Self(Timer::new(Duration::from_millis(1000), true))
}
2020-12-24 13:41:55 -05:00
}
fn setup(commands: &mut Commands, mut materials: ResMut<Assets<ColorMaterial>>) {
2020-12-24 13:34:47 -05:00
commands.spawn(Camera2dBundle::default());
2020-12-24 13:41:55 -05:00
commands.insert_resource(Materials {
head_material: materials.add(Color::rgb(0.7, 0.7, 0.7).into()),
2020-12-24 14:14:18 -05:00
food_material: materials.add(Color::rgb(1.0, 0.0, 1.0).into()),
2020-12-24 13:41:55 -05:00
});
}
fn spawn_snake(commands: &mut Commands, materials: Res<Materials>) {
commands
.spawn(SpriteBundle {
material: materials.head_material.clone(),
sprite: Sprite::new(Vec2::new(10.0, 10.0)),
..Default::default()
})
2020-12-24 14:01:05 -05:00
.with(SnakeHead)
.with(Position { x: 3, y: 3 })
.with(Size::square(0.8));
2020-11-04 10:09:02 -05:00
}
2020-12-24 13:49:23 -05:00
fn snake_movement(
keyboard_input: Res<Input<KeyCode>>,
2020-12-24 14:04:06 -05:00
mut head_positions: Query<&mut Position, With<SnakeHead>>,
2020-12-24 13:49:23 -05:00
) {
2020-12-24 14:04:06 -05:00
for mut pos in head_positions.iter_mut() {
2020-12-24 13:49:23 -05:00
if keyboard_input.pressed(KeyCode::Left) {
2020-12-24 14:04:06 -05:00
pos.x -= 1;
2020-12-24 13:49:23 -05:00
}
if keyboard_input.pressed(KeyCode::Right) {
2020-12-24 14:04:06 -05:00
pos.x += 1;
2020-12-24 13:49:23 -05:00
}
if keyboard_input.pressed(KeyCode::Down) {
2020-12-24 14:04:06 -05:00
pos.y -= 1;
2020-12-24 13:49:23 -05:00
}
if keyboard_input.pressed(KeyCode::Up) {
2020-12-24 14:04:06 -05:00
pos.y += 1;
2020-12-24 13:49:23 -05:00
}
2020-12-24 13:45:07 -05:00
}
}
2020-12-24 14:01:05 -05:00
fn size_scaling(windows: Res<Windows>, mut q: Query<(&Size, &mut Sprite)>) {
let window = windows.get_primary().unwrap();
for (sprite_size, mut sprite) in q.iter_mut() {
sprite.size = Vec2::new(
sprite_size.width / ARENA_WIDTH as f32 * window.width() as f32,
sprite_size.height / ARENA_HEIGHT as f32 * window.height() as f32,
);
}
}
fn position_translation(windows: Res<Windows>, mut q: Query<(&Position, &mut Transform)>) {
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.get_primary().unwrap();
for (pos, mut transform) in q.iter_mut() {
transform.translation = Vec3::new(
convert(pos.x as f32, window.width() as f32, ARENA_WIDTH as f32),
convert(pos.y as f32, window.height() as f32, ARENA_HEIGHT as f32),
0.0,
);
}
}
2020-12-24 14:14:18 -05:00
fn food_spawner(
commands: &mut Commands,
materials: Res<Materials>,
time: Res<Time>,
mut timer: Local<FoodSpawnTimer>,
) {
if timer.0.tick(time.delta_seconds().finished()) {
commands
.spawn(SpriteBundle {
material: materials.food_material.clone(),
..Default::default()
})
.with(Food)
.with(Position {
x: (random::<f32>() * ARENA_WIDTH as f32) as i32,
y: (random::<f32>() * ARENA_HEIGHT as f32) as i32,
})
.with(Size::square(0.8));
}
}
2020-11-04 10:09:02 -05:00
fn main() {
App::build()
2020-12-24 14:07:46 -05:00
.add_resource(ClearColor(Color::rgb(0.04, 0.04, 0.04)))
.add_resource(WindowDescriptor {
title: "Snake!".to_string(),
width: 500.0,
height: 500.0,
..Default::default()
})
2020-11-04 10:09:02 -05:00
.add_startup_system(setup.system())
2020-12-24 13:41:55 -05:00
.add_startup_stage("game_setup", SystemStage::single(spawn_snake.system()))
2020-12-24 13:45:07 -05:00
.add_system(snake_movement.system())
2020-12-24 14:01:05 -05:00
.add_system(position_translation.system())
.add_system(size_scaling.system())
2020-12-24 14:14:18 -05:00
.add_system(food_spawner.system())
2020-12-24 13:34:47 -05:00
.add_plugins(DefaultPlugins)
2020-11-04 10:09:02 -05:00
.run();
}