差分
このページの2つのバージョン間の差分を表示します。
| 両方とも前のリビジョン前のリビジョン次のリビジョン | 前のリビジョン | ||
| youtube:monogame-ball [2024/02/28 18:34] – ↷ 移動操作に合わせてリンクを書き換えました。 freemikan | youtube:monogame-ball [2024/02/28 18:36] (現在) – freemikan | ||
|---|---|---|---|
| 行 1: | 行 1: | ||
| - | ====== | + | ====== |
| - | {{youtube:sokoban.png?400|}} | + | {{:youtube:monogame-myballgame.png|}} |
| - | src/main.rs | + | ===== Game1.cs ===== |
| - | < | + | < |
| - | use bevy:: | + | using Microsoft.Xna.Framework; |
| - | use bevy:: | + | using Microsoft.Xna.Framework.Graphics; |
| + | using Microsoft.Xna.Framework.Input; | ||
| - | const ARENA_WIDTH: | + | namespace MyBallGame; |
| - | 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() { | + | public class Game1 : Game |
| - | App::new() | + | { |
| - | | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | 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(); | + | |
| - | } | + | |
| - | # | + | const int GAME_WIDTH = 320; |
| - | struct Position { | + | |
| - | | + | |
| - | y: i32, | + | |
| - | z: i32, | + | |
| - | } | + | |
| - | #[derive(Component)] | + | public Game1() |
| - | struct Cargo; | + | { |
| + | _graphics = new GraphicsDeviceManager(this); | ||
| + | Content.RootDirectory = " | ||
| + | IsMouseVisible = true; | ||
| - | #[derive(Component)] | + | _graphics.PreferredBackBufferWidth = GAME_WIDTH; |
| - | struct Player; | + | _graphics.PreferredBackBufferHeight = GAME_HEIGHT; |
| + | _graphics.ApplyChanges(); | ||
| + | } | ||
| - | #[derive(Component)] | + | protected override void Initialize() |
| - | struct Goal; | + | { |
| + | // TODO: Add your initialization logic here | ||
| - | #[derive(Default)] | + | base.Initialize(); |
| - | struct LevelCompleteEvent; | + | } |
| - | fn setup(mut commands: Commands) { | + | protected override void LoadContent() |
| - | | + | |
| + | | ||
| - | // spawn Player | + | var ballTexture = Content.Load< |
| - | commands | + | var ballRadius = ballTexture.Width / 2.0f; |
| - | | + | var ballPosition = new Vector2(GAME_WIDTH / 2.0f - ballRadius, GAME_HEIGHT / 2.0f - ballRadius); |
| - | | + | var ballVelocity = new Vector2(300.0f, 300.0f); |
| - | color: PLAYER_COLOR, | + | |
| - | | + | } |
| - | }, | + | |
| - | transform: Transform { | + | |
| - | scale: Vec3::new(TILE_SIZE.x, TILE_SIZE.y, | + | |
| - | ..default() | + | |
| - | }, | + | |
| - | | + | |
| - | | + | |
| - | .insert(Player) | + | |
| - | .insert(Position { | + | |
| - | x: ARENA_WIDTH / 2, | + | |
| - | y: 0, | + | |
| - | z: 3, | + | |
| - | }); | + | |
| - | | + | |
| - | for (x, y) in (0..ARENA_WIDTH) | + | |
| - | .step_by(2) | + | |
| - | .zip(std:: | + | |
| - | .chain( | + | |
| - | (1..ARENA_WIDTH) | + | |
| - | .step_by(2) | + | |
| - | .zip(std:: | + | |
| - | | + | |
| { | { | ||
| - | | + | |
| - | | + | |
| - | sprite: Sprite { | + | |
| - | color: CARGO_COLOR, | + | |
| - | | + | |
| - | }, | + | |
| - | transform: Transform { | + | |
| - | scale: Vec3:: | + | |
| - | | + | |
| - | }, | + | |
| - | | + | |
| - | }) | + | |
| - | | + | |
| - | .insert(Position { x, y, z: 2 }); | + | |
| - | } | + | |
| - | // spawn Goal | + | _ball.Update(gameTime, GAME_WIDTH, GAME_HEIGHT); |
| - | 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< | + | base.Update(gameTime); |
| - | for (p, mut t) in query.iter_mut() { | + | |
| - | t.translation = Vec3:: | + | |
| - | 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, | + | |
| - | | + | |
| } | } | ||
| - | } | ||
| - | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | + | protected override void Draw(GameTime gameTime) |
| - | enum Direction | + | { |
| - | Up, | + | |
| - | Down, | + | |
| - | Left, | + | |
| - | Right, | + | |
| - | None, | + | |
| - | } | + | |
| - | fn move_player_and_cargo( | + | _spriteBatch.Begin(); |
| - | keyboard_input: | + | |
| - | mut player_positions: | + | |
| - | mut cargo_positions: | + | |
| - | ) { | + | |
| - | let direction = if keyboard_input.just_pressed(KeyCode:: | + | |
| - | println!(" | + | |
| - | | + | |
| - | } else if keyboard_input.just_pressed(KeyCode:: | + | |
| - | | + | |
| - | } 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(); | + | base.Draw(gameTime); |
| + | } | ||
| + | } | ||
| - | let next_position = |p: & | + | class Ball |
| - | | + | { |
| - | 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, | + | |
| - | | + | |
| - | | + | |
| - | |p: & | + | |
| - | + | ||
| - | // try to push cargo and update player and cargo position | + | |
| - | 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) | + | |
| { | { | ||
| - | | + | |
| - | *cargo_forward | + | |
| - | | + | |
| - | | + | |
| - | } else { | + | |
| - | | + | |
| - | *player_position | + | |
| - | } | + | |
| } | } | ||
| - | } | ||
| - | fn check_level_complete( | + | public void Update(GameTime gameTime, int gameWidth, int gameHeight) |
| - | debug_input: | + | |
| - | cargo_positions: | + | float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds; |
| - | | + | |
| - | mut level_complete_writer: | + | |
| - | ) { | + | if (_position.X <= 0.0f || _position.X + _radius * 2.0f >= gameWidth) |
| - | if debug_input.just_pressed(KeyCode:: | + | |
| - | | + | _velocity.X *= -1.0f; |
| - | | + | } |
| - | | + | |
| - | for cargo in cargo_positions.iter() { | + | if (_position.Y <= 0.0f || _position.Y + _radius * 2.0f >= gameHeight) |
| - | let maybe_on_goal | + | { |
| - | | + | |
| - | .find(|gp| gp.x == cargo.x && gp.y == cargo.y); | + | |
| - | | + | |
| - | | + | |
| } | } | ||
| } | } | ||
| - | level_complete_writer.send_default(); | ||
| - | } | ||
| - | fn complete_level( | + | public void Draw(SpriteBatch spriteBatch) |
| - | mut commands: Commands, | + | { |
| - | events: EventReader< | + | |
| - | asset_server: | + | |
| - | ) { | + | |
| - | | + | |
| - | | + | |
| - | + | ||
| - | println!(" | + | |
| - | + | ||
| - | let font_size = 50.0; | + | |
| - | + | ||
| - | // show screen message | + | |
| - | commands.spawn( | + | |
| - | TextBundle:: | + | |
| - | " | + | |
| - | TextStyle { | + | |
| - | font: asset_server.load(" | + | |
| - | font_size, | + | |
| - | color: | + | |
| - | }, | + | |
| - | ) | + | |
| - | | + | |
| - | .with_style(Style { | + | |
| - | position_type: | + | |
| - | position: UiRect { | + | |
| - | // hard-code position to display text center of screen | + | |
| - | top: Val:: | + | |
| - | left: Val:: | + | |
| - | ..default() | + | |
| - | }, | + | |
| - | ..default() | + | |
| - | }), | + | |
| - | | + | |
| } | } | ||
| } | } | ||
| </ | </ | ||
| - | Cargo.toml | + | ===== Program.cs ===== |
| - | < | ||
| - | [package] | ||
| - | name = " | ||
| - | version = " | ||
| - | edition = " | ||
| - | # See more keys and their definitions at https://doc.rust-lang.org/cargo/ | + | <file csharp> |
| + | using var game = new MyBallGame.Game1(); | ||
| + | game.Run(); | ||
| + | </file> | ||
| - | [dependencies] | ||
| - | bevy = { version = " | ||
| - | |||
| - | [profile.dev] | ||
| - | opt-level = 1 | ||
| - | |||
| - | [profile.dev.package." | ||
| - | opt-level = 3 | ||
| - | </ | ||
