差分
このページの2つのバージョン間の差分を表示します。
| 両方とも前のリビジョン前のリビジョン次のリビジョン | 前のリビジョン | ||
| youtube:bevy-sokoban [2024/02/28 18:26] – 削除 - 外部編集 (不明な日付) 127.0.0.1 | youtube:bevy-sokoban [2024/02/29 11:49] (現在) – freemikan | ||
|---|---|---|---|
| 行 1: | 行 1: | ||
| + | ====== 倉庫番 ====== | ||
| + | |||
| + | {{youtube: | ||
| + | |||
| + | ===== src/main.rs ===== | ||
| + | |||
| + | |||
| + | <file rust> | ||
| + | use bevy:: | ||
| + | use bevy:: | ||
| + | |||
| + | const ARENA_WIDTH: | ||
| + | const ARENA_HEIGHT: | ||
| + | const TILE_SIZE: Vec2 = Vec2:: | ||
| + | const SCREEN_SIZE: | ||
| + | TILE_SIZE.x * ARENA_WIDTH as f32, | ||
| + | TILE_SIZE.y * ARENA_HEIGHT as f32, | ||
| + | ); | ||
| + | const PLAYER_COLOR: | ||
| + | const CARGO_COLOR: | ||
| + | const GOAL_COLOR: Color = Color:: | ||
| + | |||
| + | fn main() { | ||
| + | App::new() | ||
| + | .add_plugins(DefaultPlugins.set(WindowPlugin { | ||
| + | window: WindowDescriptor { | ||
| + | title: " | ||
| + | width: SCREEN_SIZE.x, | ||
| + | height: SCREEN_SIZE.y, | ||
| + | ..default() | ||
| + | }, | ||
| + | ..default() | ||
| + | })) | ||
| + | .insert_resource(ClearColor(Color:: | ||
| + | .add_startup_system(setup) | ||
| + | .add_system(bevy:: | ||
| + | .add_system_set( | ||
| + | SystemSet:: | ||
| + | .with_run_criteria(FixedTimestep:: | ||
| + | .with_system(move_player_and_cargo) | ||
| + | .with_system(position_translation.after(move_player_and_cargo)) | ||
| + | .with_system(check_level_complete.after(move_player_and_cargo)) | ||
| + | .with_system(complete_level.after(check_level_complete)), | ||
| + | ) | ||
| + | .add_event::< | ||
| + | .run(); | ||
| + | } | ||
| + | |||
| + | # | ||
| + | struct Position { | ||
| + | x: i32, | ||
| + | y: i32, | ||
| + | z: i32, | ||
| + | } | ||
| + | |||
| + | # | ||
| + | struct Cargo; | ||
| + | |||
| + | # | ||
| + | struct Player; | ||
| + | |||
| + | # | ||
| + | struct Goal; | ||
| + | |||
| + | # | ||
| + | struct LevelCompleteEvent; | ||
| + | |||
| + | fn setup(mut commands: Commands) { | ||
| + | commands.spawn(Camera2dBundle:: | ||
| + | |||
| + | // spawn Player | ||
| + | commands | ||
| + | .spawn(SpriteBundle { | ||
| + | sprite: Sprite { | ||
| + | color: PLAYER_COLOR, | ||
| + | ..default() | ||
| + | }, | ||
| + | transform: Transform { | ||
| + | scale: Vec3:: | ||
| + | ..default() | ||
| + | }, | ||
| + | ..default() | ||
| + | }) | ||
| + | .insert(Player) | ||
| + | .insert(Position { | ||
| + | x: ARENA_WIDTH / 2, | ||
| + | y: 0, | ||
| + | z: 3, | ||
| + | }); | ||
| + | |||
| + | // spawn Cargo | ||
| + | for (x, y) in (0..ARENA_WIDTH) | ||
| + | .step_by(2) | ||
| + | .zip(std:: | ||
| + | .chain( | ||
| + | (1..ARENA_WIDTH) | ||
| + | .step_by(2) | ||
| + | .zip(std:: | ||
| + | ) | ||
| + | { | ||
| + | commands | ||
| + | .spawn(SpriteBundle { | ||
| + | sprite: Sprite { | ||
| + | color: CARGO_COLOR, | ||
| + | ..default() | ||
| + | }, | ||
| + | transform: Transform { | ||
| + | scale: Vec3:: | ||
| + | ..default() | ||
| + | }, | ||
| + | ..default() | ||
| + | }) | ||
| + | .insert(Cargo) | ||
| + | .insert(Position { x, y, z: 2 }); | ||
| + | } | ||
| + | |||
| + | // spawn Goal | ||
| + | for x in 0..ARENA_WIDTH { | ||
| + | commands | ||
| + | .spawn(SpriteBundle { | ||
| + | sprite: Sprite { | ||
| + | color: GOAL_COLOR, | ||
| + | ..default() | ||
| + | }, | ||
| + | transform: Transform { | ||
| + | scale: Vec3:: | ||
| + | ..default() | ||
| + | }, | ||
| + | ..default() | ||
| + | }) | ||
| + | .insert(Goal) | ||
| + | .insert(Position { | ||
| + | x, | ||
| + | y: ARENA_HEIGHT - 1, | ||
| + | z: 1, | ||
| + | }); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | fn position_translation(mut query: Query< | ||
| + | for (p, mut t) in query.iter_mut() { | ||
| + | t.translation = Vec3::new( | ||
| + | p.x as f32 * TILE_SIZE.x - (SCREEN_SIZE.x / 2.0) + (TILE_SIZE.x / 2.0), | ||
| + | p.y as f32 * TILE_SIZE.y - (SCREEN_SIZE.y / 2.0) + (TILE_SIZE.y / 2.0), | ||
| + | p.z as f32, | ||
| + | ); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | # | ||
| + | enum Direction { | ||
| + | Up, | ||
| + | Down, | ||
| + | Left, | ||
| + | Right, | ||
| + | None, | ||
| + | } | ||
| + | |||
| + | fn move_player_and_cargo( | ||
| + | keyboard_input: | ||
| + | mut player_positions: | ||
| + | mut cargo_positions: | ||
| + | ) { | ||
| + | let direction = if keyboard_input.just_pressed(KeyCode:: | ||
| + | println!(" | ||
| + | Direction:: | ||
| + | } else if keyboard_input.just_pressed(KeyCode:: | ||
| + | Direction:: | ||
| + | } else if keyboard_input.just_pressed(KeyCode:: | ||
| + | Direction:: | ||
| + | } else if keyboard_input.just_pressed(KeyCode:: | ||
| + | Direction:: | ||
| + | } else { | ||
| + | Direction:: | ||
| + | }; | ||
| + | |||
| + | let mut player_position = player_positions.single_mut(); | ||
| + | |||
| + | let next_position = |p: & | ||
| + | Direction:: | ||
| + | x: p.x, | ||
| + | y: p.y + step, | ||
| + | z: p.z, | ||
| + | }, | ||
| + | Direction:: | ||
| + | x: p.x, | ||
| + | y: p.y - step, | ||
| + | z: p.z, | ||
| + | }, | ||
| + | Direction:: | ||
| + | x: p.x - step, | ||
| + | y: p.y, | ||
| + | z: p.z, | ||
| + | }, | ||
| + | Direction:: | ||
| + | x: p.x + step, | ||
| + | y: p.y, | ||
| + | z: p.z, | ||
| + | }, | ||
| + | _ => *p, | ||
| + | }; | ||
| + | |||
| + | let inside_arene = | ||
| + | |p: & | ||
| + | |||
| + | // try to push cargo and update player and cargo position if it possible | ||
| + | let new_player_position = next_position(& | ||
| + | let new_cargo_position = next_position(& | ||
| + | let new_cargo_position_empty = cargo_positions | ||
| + | .iter() | ||
| + | .all(|cp| !(cp.x == new_cargo_position.x && cp.y == new_cargo_position.y)); | ||
| + | |||
| + | if let Some(mut cargo_forward) = cargo_positions | ||
| + | .iter_mut() | ||
| + | .find(|cp| cp.x == new_player_position.x && cp.y == new_player_position.y) | ||
| + | { | ||
| + | if new_cargo_position_empty && inside_arene(& | ||
| + | *cargo_forward = new_cargo_position; | ||
| + | *player_position = new_player_position; | ||
| + | } | ||
| + | } else { | ||
| + | if inside_arene(& | ||
| + | *player_position = new_player_position; | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | fn check_level_complete( | ||
| + | debug_input: | ||
| + | cargo_positions: | ||
| + | goal_positions: | ||
| + | mut level_complete_writer: | ||
| + | ) { | ||
| + | if debug_input.just_pressed(KeyCode:: | ||
| + | level_complete_writer.send_default(); | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | for cargo in cargo_positions.iter() { | ||
| + | let maybe_on_goal = goal_positions | ||
| + | .iter() | ||
| + | .find(|gp| gp.x == cargo.x && gp.y == cargo.y); | ||
| + | if maybe_on_goal.is_none() { | ||
| + | return; | ||
| + | } | ||
| + | } | ||
| + | level_complete_writer.send_default(); | ||
| + | } | ||
| + | |||
| + | fn complete_level( | ||
| + | mut commands: Commands, | ||
| + | events: EventReader< | ||
| + | asset_server: | ||
| + | ) { | ||
| + | if !events.is_empty() { | ||
| + | events.clear(); | ||
| + | |||
| + | println!(" | ||
| + | |||
| + | let font_size = 50.0; | ||
| + | |||
| + | // show screen message | ||
| + | commands.spawn( | ||
| + | TextBundle:: | ||
| + | " | ||
| + | TextStyle { | ||
| + | font: asset_server.load(" | ||
| + | font_size, | ||
| + | color: Color:: | ||
| + | }, | ||
| + | ) | ||
| + | .with_text_alignment(TextAlignment:: | ||
| + | .with_style(Style { | ||
| + | position_type: | ||
| + | position: UiRect { | ||
| + | // hard-code position to display text center of screen | ||
| + | top: Val:: | ||
| + | left: Val:: | ||
| + | ..default() | ||
| + | }, | ||
| + | ..default() | ||
| + | }), | ||
| + | ); | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ===== Cargo.toml ===== | ||
| + | |||
| + | |||
| + | < | ||
| + | [package] | ||
| + | name = " | ||
| + | version = " | ||
| + | edition = " | ||
| + | |||
| + | # See more keys and their definitions at https:// | ||
| + | |||
| + | [dependencies] | ||
| + | bevy = { version = " | ||
| + | |||
| + | [profile.dev] | ||
| + | opt-level = 1 | ||
| + | |||
| + | [profile.dev.package." | ||
| + | opt-level = 3 | ||
| + | </ | ||
