Behind Coleus

大学生なのに特別大学で楽しいことが一 つもない。虐待と男子校病のせいにしてみる。→日本脱出しました 今ジャカルタにいます。→ジャカルタから帰ってきました。

戦い5

最近お腹が減ってしょうがない。

youtu.be

note.com

championcross.jp

昨日は掃除したり、引っ越し準備したので、疲れてプログラミングはほとんどしなかった。

今日の目標、各ステートのプラグインを作る。
ステート移行のプラグインを作る。
とりあえず、LoadingStateを作る。

  1. このステートがデフォルトである
  2. お互いのデッキを確定し、そのデータを読み込みます。
  3. お互いのファーストエナジーカードを確定し、そのデータを読み込みます。
  4. 読み込んだカードを山札にセットします。
  5. 山札をシャッフルします
  6. Sゾーンにファーストエナジーカードを裏向きで置きます。
  7. セットアップステートに自動で移行する

1は前回デフォルトにせっていしたのでOK
2はいまあるset up システムをあさいんすればOK 
3は別のシステムを作らないといけない。
4はコンポーネントを与えればいいだけ?
5はこの前作ったcards in libraryとshuffle deck システムでOK
6は新しく作らないとだめ
7はステートの移行でワンパン

取り敢えず、ファーストエナジーのエンティティを作成する際に、コンポーネントの構成に悩んでいたが、カード情報はすべてCardコンポーネントで与えて、クラス、カードタイプなどは、タグコンポーネントでやります。
つまるところ、昔やった、

#[derive(Component)]
pub struct Player {}

こういうのでカードの属性を与えます。

#[derive(Component)]
pub struct Fighter {}

#[derive(Component)]
pub struct FirstEnergy {}
fn setup_first_energy(mut commands: Commands) {
    let my_entity = commands
        .spawn*1
        .id();

    println!("{:?} is spawned", my_entity);
}

このようにして、作りました。

カードのタイプは、タグコンポーネントでつけました。

#[derive(States, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum GameState {
    #[default]
    Loading,
    Setup,
    GameOver,
    Play,
}
#[derive(Component)]
pub struct Fighter {}

#[derive(Component)]
pub struct FirstEnergy {}

struct LoadingPlugin;

impl Plugin for LoadingPlugin {
    fn build(&self, app: &mut App) {
        app.add_systems(
            OnEnter(GameState::Loading),
            (
                setup_deck,
                setup_first_energy,
                cards_in_deck,
                first_energy_open,
                automatically_move_to_setup_state
            )
                .chain(),
        );
    }
}
#[derive(Component)]
struct Card {
    power: Option<u32>,
    name: String,
    energy: u32,
}
fn setup_first_energy(mut commands: Commands) {
    let my_entity = commands
        .spawn*2
        .id();

    println!("{:?} is spawned", my_entity);
}
fn automatically_move_to_setup_state(mut next_state: ResMut<NextState<GameState>>) {
    next_state.set(GameState::Loading);
    println!("ローディング終了しました。")
}
fn first_energy_open(
    query: Query<(Entity, &Card, &Location), With<FirstEnergy>>, // 正しい構文
    mut commands: Commands,
) {
    for (entity, card, location) in query.iter() {
        commands.entity(entity).insert(FaceCondition::Open);
        println!("ファーストエナジーオープン!!");
        println!("ファーストエナジーは、{}, です。", card.name)
    }
}
fn setup_deck(mut commands: Commands) {
    let my_entity = commands
        .spawn*3
        .id();

    println!("{:?} is spawned", my_entity);

中略()

今気づいたけど、ファーストエナジーオープンはあとだ。

今までMinimulPluginを最初に入れていたけど、ステートを使うなら、DefaultPluginを入れないといけないらしい。

できたわ。

次の目的
あとは、setupステートを完成させる。

  1. ドロー機能
  2. マリガン機能
  3. じゃんけんで先行後攻を決める機能
  4. ターンプレイヤーを記録する機能
  5. ファーストエナジーオープンする機能
  6. 初手とファーストエナジーを記録する機能
  7. プレイステートに自動で移行する

1はできてる、2は場合分けのための修正が必要34はできてる。5 はさっき先に作っちゃった。6はリストを作ってさせよう。

struct FirstHandPlugin;

impl Plugin for FirstHandPlugin {
    fn build(&self, app: &mut App) {
        app.add_systems(
            PostStartup,
            (
                shuffle_deck,
                draw_a_card,
                draw_a_card,
                draw_a_card,
                draw_a_card,
                draw_a_card,
                show_last_hands,
                return_all_hands_to_deck,
                shuffle_deck,
                draw_a_card,
                draw_a_card,
                draw_a_card,
                draw_a_card,
                draw_a_card,
                show_last_hands,
            )
                .chain(),
        );
    }
}

これを書き直せばいい。

この前、一つのシステムにしようとしたら引数でさんざん言われたので、
これの場合分けはステートで管理する。

pub fn transition_to_main_menu_state(
    keyboard_input: Res<ButtonInput<KeyCode>>,
    app_state: Res<State<AppState>>,
    mut next_state: ResMut<NextState<AppState>>,
) {
    if keyboard_input.just_pressed(KeyCode::KeyM) {
        match app_state.get() {
            AppState::Game => {
                next_state.set(AppState::MainMenu);
                println!("You backed to the MainMenu State")
            }
            AppState::GameOver => {
                next_state.set(AppState::MainMenu);
                println!("You backed to the MainMenu State")
            }
            AppState::MainMenu => {}
        }
    }
}

これを参考にして、マリガン1回目だったらなにをするっていうのをやる。
ステートは4つ作った。

#[derive(States, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum MulliganState {
    #[default]
    Default,
    First,
    Second,
    Over,
}

シャッフルして5枚引いて戻して入力を受け付けるのを Default
入力が1だったら、Firstに行って、2だったらOverに行く それ以外だったら、もう一度入力を呼び出す。
Firstでは引き直して、入力受け付ける。1だったら、Secondに行く、2だったら、Overそれ以外はもう一度
Secondでは、入力を受け付けず、引き直したら、それでOverに移行

fn check_the_will_of_mulligan() -> i32 {
    loop {
        println!("[1]:マリガンをする [2]:キープする");
        let mut input = String::new();
        io::stdin()
            .read_line(&mut input)
            .expect("Failed to read line");

        // 入力を整数に変換し、結果を返す
        match input.trim().parse::<i32>() {
            Ok(choice) if choice == 1 || choice == 2 => return choice,
            _ => println!("無効な選択です。もう一度入力してください。"),
        }
    }
}

過去の関数を改造して、ちゃんとした答えをしないとエラーが出るようにした。

pub fn transition_mulligan_state(
    mulligan_state: Res<State<MulliganState>>,
    mut next_state: ResMut<NextState<MulliganState>>,
) {
    let choice = check_the_will_of_mulligan();
    match choice {
        1 => match mulligan_state.get() {
            MulliganState::Default => {
                next_state.set(MulliganState::First);
                println!("マリガン1回目です");
            }
            MulliganState::First => {
                next_state.set(MulliganState::Second);
                println!("マリガン2回目です");
            }
            MulliganState::Second => {
                next_state.set(MulliganState::Over);
                println!("もうマリガンできません")
            }
            MulliganState::Over => {}
        },

        2 => {
            next_state.set(MulliganState::Over);
        }

        _ => {}
    }
}

回答が1の時、とかやってたけど、どちらかというとステートで分類した方がいいと考えたので、変えた
エラーが出過ぎて絶望してたら、ステートの初期化が出来てませんでした。
結局これにやります。


pub fn transition_mulligan_state(
    mulligan_state: Res<State<MulliganState>>,
    mut next_state: ResMut<NextState<MulliganState>>,
) {
    let choice = check_the_will_of_mulligan();

       match mulligan_state.get() {
            MulliganState::Default => {
                match choice {
                   1 =>  {
                        println!("マリガン1回目です");
                        next_state.set(MulliganState::First);
                    }
                    2 => {
                        next_state.set(MulliganState::Over);

                    }

                    _ => {
                    }
                }

            }

            MulliganState::First => {
                match choice {
                   1 =>  {
                    println!("マリガン2回目です");
                    next_state.set(MulliganState::Second);
                    }
                    2 => {
                        next_state.set(MulliganState::Over);

                    }

                    _ => {
                    }
                }

            }
            MulliganState::Second => {
            }

            MulliganState::Over => {}
        }

    }


で、初期手札のリストも保存するようにした。


fn check_last_hand(
    mut first_hand: ResMut<FirstHand>, // リソースとして受け取る
    query: Query<(Entity, &Card, &Location)>,
) {
    first_hand.cards.clear(); // 前回の結果をクリア
    println!("your first hands are:");

    for (entity, card, location) in query.iter() {
        if let Location::InHand = location {
            first_hand.cards.push(entity); // エンティティIDをリストに追加
            println!("{}, ", card.name);
        }
    }
}
        .insert_resource(FirstHand::default())
#[derive(Default, Resource)]
struct FirstHand {
    cards: Vec<Entity>,
}

ほいよ

で、最終的には4つのステートに分けて、これにした。

struct SetupPlugin;

impl Plugin for SetupPlugin {
    fn build(&self, app: &mut App) {
        app.add_systems(
            OnEnter(GameState::Setup),
            (
                return_all_hands_to_deck,
                shuffle_deck,
                draw_a_card,
                draw_a_card,
                draw_a_card,
                draw_a_card,
                draw_a_card,
                show_hands,
                transition_mulligan_state,
            )
                .chain(),
        )
        .add_systems(
            OnEnter(MulliganState::First),
            (
                return_all_hands_to_deck,
                shuffle_deck,
                draw_a_card,
                draw_a_card,
                draw_a_card,
                draw_a_card,
                draw_a_card,
                show_hands,
                transition_mulligan_state
            )
                .chain(),
        )
        .add_systems(
            OnEnter(MulliganState::Second),
            (
                return_all_hands_to_deck,
                shuffle_deck,
                draw_a_card,
                draw_a_card,
                draw_a_card,
                draw_a_card,
                draw_a_card,
                automatically_move_to_over_state,
            )
                .chain(),
        )
        .add_systems(
            OnEnter(MulliganState::Over),
            (
                check_last_hand,
                choose_first,
                first_energy_open,
                automatically_move_to_play_state,
            ).chain(),
        );
    }
}

これで、ちゃんとインサートしたらいけました。

あとは、まぁ自動移行するための関数

fn automatically_move_to_over_state(mut next_state: ResMut<NextState<MulliganState>>) {
    next_state.set(MulliganState::Over);
    println!("最終手札が確定しました")
}

fn automatically_move_to_play_state(mut next_state: ResMut<NextState<GameState>>) {
    next_state.set(GameState::Play);
    println!("対戦を開始します")
}

書きました

見なさいよこれを!!
うまくできてるでしょう!!

3って打っても、やり直しになってる。
OKです。もう今日はやめます。



 

 

 

 

 

 

 

 

 

*1:

            Card {
                power: None,
                name: String::from("勇敢のエナジー"),
                energy: 2,
            },
            Location::SZone,
            SpinCondition::ReSpin,
            FaceCondition::Facedown,
            FirstEnergy{},
       

*2:

            Card {
                power: None,
                name: String::from("勇敢のエナジー"),
                energy: 2,
            },
            Location::SZone,
            SpinCondition::ReSpin,
            FaceCondition::Facedown,
            FirstEnergy {},
       

*3:

            Card {
                power: Some(1000),
                name: String::from("リトルナイト"),
                energy: 1,
            },
            Location::InLibrary,
            SpinCondition::ReSpin,
            FaceCondition::Facedown,
            Fighter {},