Behind Coleus

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

戦い8

昨日は23時に寝て今日は朝7:40から起きた。

最近薬を飲まずに寝れていて、何か調子がいい。普通に22時ごろに超眠くなる。

ただ、卒研のテーマが決まらず、発表が迫ってきていて、ガチ鬱である

#[derive(Event)]
pub struct GameOver {
    pub score: u32,
}
pub fn handle_game_over(
    mut game_over_event_reader: EventReader<GameOver>,
    app_state: Res<State<AppState>>,
    mut next_state: ResMut<NextState<AppState>>,
    mut next_simulation_state: ResMut<NextState<SimulationState>>,
) {
    for event in game_over_event_reader.read() {
        println!("Your final score is : {}", event.score);
        match app_state.get() {
            AppState::Game => {
                next_state.set(AppState::GameOver);
            }
            AppState::GameOver => {}
            AppState::MainMenu => {}
        }
        next_simulation_state.set(SimulationState::Paused);
    }
}
pub fn enemy_hit_player(
    mut commands: Commands,
    mut game_over_event_writer: EventWriter<GameOver>,
    player_query: Query<(Entity, &Transform), With<Player>>,
    enemy_query: Query<&Transform, With<Enemy>>,
    asset_server: Res<AssetServer>,
    score: Res<Score>,
) {
    if let Ok*1 = player_query.get_single() {
        for enemy_transform in enemy_query.iter() {
            let distance = player_transform
                .translation
                .distance(enemy_transform.translation);
            let player_radius = PLAYER_SIZE / 2.0;
            let enemy_radius = ENEMY_SIZE / 2.0;
            if distance < player_radius + enemy_radius {
                println!("Enemy hit player! Game Over!!");
                let sound_effect = "audio/explosionCrunch_000.ogg";
                commands.spawn(AudioPlayer::new(asset_server.load(sound_effect)));
                commands.entity(player_entity).despawn();
                game_over_event_writer.send(GameOver { score: score.value });
            }
        }
    }
}
        .add_systems(Update, (handle_game_over, exit_game))

順次処理をするにはイベントを使えばいいと言われたので、イベントを使ってみる。

 

今回やることは、FZoneのカードを表示して、意思を確認し、確認が出来なかったらXフェーズに移行して、確認が出来たら、撤退するカードを選ぶという関数です。

 

イベント凄いわ。今まで、複雑なステートで場合分けやったりして、例外処理に苦しんだり初期化をしないといけないことに悩んだりしたけど、イベント送っちゃえば、1対1でしか物事が起きない。

取り敢えず作ったものはこれ

use std::io;

use crate::game::{
    loading::component::{Card, Location},
    play::PlayState,
};
use bevy::prelude::*;

use super::{
    event::{PickFighter, Withdraw},
    resource::FieldCondition,
};

pub fn check_fzone_condition(
    query: Query<(&Card, &Location)>,
    mut field_conditon: ResMut<FieldCondition>,
) {
    // クエリで取得したカードをチェック
    for (card, location) in query.iter() {
        if let Location::FZone = location {
            field_conditon.has_fzone_card = true;
            println!("Fゾーンにカードが見つかりました"); // FZoneのカードが見つかった場合
            break;
        }

    }
}

pub fn check_xzone_condition(
    query: Query<(&Card, &Location)>,
    mut field_conditon: ResMut<FieldCondition>,
) {
    // クエリで取得したカードをチェック
    for (card, location) in query.iter() {
        if let Location::XZone = location {
            field_conditon.has_xzone_card = true;
            println!("Xゾーンにカードが見つかりました"); // FZoneのカードが見つかった場合
            break;
        }

    }
}

pub fn choose_fighther_to_withdraw(
    query: Query<(Entity, &Card, &Location)>,
    mut commands: Commands,
    mut withdraw_event_writer: EventWriter<Withdraw>,
    mut choose_new_card_event_reader: EventReader<PickFighter>,
) {
    for event in choose_new_card_event_reader.read() {
        let mut cards_in_fzone = Vec::new();

        println!("Fゾーンにあるあなたのカードは:");

        for (entity, card, location) in query.iter() {
            if let Location::FZone = location {
                cards_in_fzone.push(entity); // エンティティIDを保存
                println!("{}: {}[{}]", cards_in_fzone.len(), card.name, card.energy); // 番号を振って表示
            }
        }

        if cards_in_fzone.is_empty() {
            println!("No cards in hand.");
            return;
        }

        println!("Select a card by number (1-{}):", cards_in_fzone.len());

        let mut input = String::new();
        io::stdin()
            .read_line(&mut input)
            .expect("Failed to read line");

        if let Ok(selected_index) = input.trim().parse::<usize>() {
            if selected_index > 0 && selected_index <= cards_in_fzone.len() {
                let selected_entity = cards_in_fzone[selected_index - 1];

                if let Ok*2 = query.get(selected_entity) {
                    withdraw_event_writer.send(Withdraw {
                        id: selected_entity,
                    });
                    println!(" {} を撤退するファイターとして選択しました", card.name); // カード名を表示
                }
                println!("You selected card with Entity ID: {:?}", selected_entity);
            } else {
                println!("Invalid selection.");
            }
        } else {
            println!("Please enter a valid number.");
        }
    }
}

pub fn withdraw(
    mut withdraw_event_reader: EventReader<Withdraw>,
    mut choose_new_card_event_writer: EventWriter<PickFighter>,
    query: Query<(&Card, &Location)>,
    mut commands: Commands,
) {
    for event in withdraw_event_reader.read() {
        let mut sum_of_energy = 0;
        for (card, location) in query.iter() {
            if let Location::FZone = location {
                sum_of_energy += card.energy
            }
        }

        println!(
            "あなたのSゾーンのエナジーの合計は、{}です。",
            sum_of_energy
        );

        if let Ok*3 = query.get(event.id) {
            sum_of_energy += card.energy;
            if sum_of_energy > 10 {
                println!(
                    "このカードはエナジーが大きすぎて、撤退できません。もう一度選びなおしてください"
                );
                choose_new_card_event_writer.send(PickFighter);
            } else {
                println!("{}を撤退させました", card.name);
                commands.entity(event.id).insert(Location::SZone);
            }
        } else {
            // エンティティが見つからない場合の処理
            println!(
                "Entity ID: {:?} has no components or does not exist.",
                event.id
            );
        }
    }
}

pub fn check_the_will_of_withdraw() -> 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_withdraw_state(
    mut next_state: ResMut<NextState<PlayState>>,
    mut choose_new_card_event_writer: EventWriter<PickFighter>,
    field_conditon: ResMut<FieldCondition>,
) {
    let choice = check_the_will_of_withdraw();

    match choice {
        1 => {
            if field_conditon.has_fzone_card {
                println!("撤退できます");
                choose_new_card_event_writer.send(PickFighter);
            } else {
                if field_conditon.has_xzone_card {
                    println!("Fゾーンにカードが無いのでXフェーズに移行します");
                    next_state.set(PlayState::XPhase)
                } else {
                    println!(
                        "Xゾーンにカードが無いのでXフェーズをスキップしてメインフェーズに移行します"
                    );
                    next_state.set(PlayState::XPhase)
                }
            }
        }
        2 => {
            if field_conditon.has_xzone_card {
                println!("Xフェーズに移行します");
                next_state.set(PlayState::XPhase);
            } else {
                println!(
                    "Xゾーンにカードが無いのでXフェーズをスキップしてメインフェーズに移行します"
                );
                next_state.set(PlayState::MainPhase);
            }
        }

        _ => {}
    }
}
pub struct WithdrawPhasePlugin;
impl Plugin for WithdrawPhasePlugin {
    fn build(&self, app: &mut App) {
        app.insert_resource(FieldCondition::default())
            .add_event::<Withdraw>()
            .add_event::<PickFighter>()
            .add_systems(
                OnEnter(PlayState::WithdrawPhase),
                (
                    check_fzone_condition,
                    check_xzone_condition,
                    transition_withdraw_state,
                )
                    .chain(),
            )
            .add_systems(
                Update,
                (withdraw, choose_fighther_to_withdraw).run_if(in_state(PlayState::WithdrawPhase)),
            );
    }
}

結果は、



こんな風になった。
選びなおすときに、撤退するかどうかから選びなおす必要があると分かった。
また、エナジーの合計が変。何故なら、Sゾーンにあるカードは、三剣士と、ファーストエナジーで8になるはずだからだ。

pub fn withdraw(
    mut withdraw_event_reader: EventReader<Withdraw>,
    mut choose_new_card_event_writer: EventWriter<PickFighter>,
    query: Query<(&Card, &Location)>,
    mut commands: Commands,
) {
    for event in withdraw_event_reader.read() {
        let mut sum_of_energy = 0;
        for (card, location) in query.iter() {
            if let Location::FZone = location {
                sum_of_energy += card.energy
            }
        }

はい、個々が違いました。
SZoneに直します。

#[derive(Event)]
pub struct Rethink;

これを追加して、大きい撤退ファイターを選んだときは、意思から伺いなおすようにしました。Rethinkで呼び出すのは、transition_withdraw_stateという事です。
また、transition_withdraw_stateをアップデートスケジュールに直し、最初のOnEnterで、Rethinkイベントを起こすようにしました。


で、できつぁぁぁぁぁぁlっぁぁぁぁぁl

Xフェーズ

  1. 入力を受け付けXスキルを使用することを選べる。
  2. Xスキルを処理する
  3. 自動的にメインフェーズに移行する

brogmymxo.hatenablog.com

 

Xスキル含めスキルの実装は、後ででいいけど、裏向きのXゾーンのカードリストの表示

はやったほうがいい。
過去作ったシステムがあったので、それを流用する。

fn list_facedown_cards_in_xzone(
    query: Query<(Entity, &Card, &Location, &FaceCondition)>,
    facedown_cards: &mut Vec<Entity>,
) {
    println!("Facedown cards in XZone are:");

    // 裏向きのカードをリストアップ
    for (entity, card, location, face_condition) in query.iter() {
        if let Location::XZone = location {
            if let FaceCondition::Facedown = face_condition {
                facedown_cards.push(entity); // エンティティIDを保存
                println!("{}: {}", facedown_cards.len(), card.name); // 番号を振って表示
            }
        }
    }

    if facedown_cards.is_empty() {
        println!("No facedown cards in XZone.");
    }
}

取り敢えず、裏向きのカードが無い時は、Xフェーズは終了しちゃいたいから、それにする。

取り敢えずリストだけを作るシステムを作る。を作る。

fn list_facedown_cards_in_xzone(
    query: Query<(Entity, &Card, &Location, &FaceCondition)>,
    mut in_xzone_card: ResMut<FacedownXZoneCards>,
) {
    println!("Facedown cards in XZone are:");

    // 裏向きのカードをリストアップ
    for (entity, card, location, face_condition) in query.iter() {
        if let Location::XZone = location {
            if let FaceCondition::Facedown = face_condition {
                in_xzone_card.cards.push(entity); // エンティティIDを保存
                println!("{}: {}", in_xzone_card.cards.len(), card.name); // 番号を振って表示
            }
        }
    }
}

作った。

pub fn check_the_will_of_xskill() -> i32 {
    loop {
        println!("[1]:Xスキルを使う [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_x_phase(
    mut next_state: ResMut<NextState<PlayState>>,
    in_xzone_card: ResMut<FacedownXZoneCards>,
    mut pick_xzone_event_writher: EventWriter<PickXzone>,
) {
    let choice = check_the_will_of_xskill();

    match choice {
        1 => {
            if in_xzone_card.cards.is_empty() {
                println!("Xゾーンに裏側のカードがありません。メインフェーズに移行します。");
                next_state.set(PlayState::MainPhase);
            } else {
                pick_xzone_event_writher.send(PickXzone);
                println!("オープンするXゾーンのカードを選んでください。");
            }
        }
        2 => {
            println!("メインフェーズに移行します。");
            next_state.set(PlayState::MainPhase);
        }

        _ => {}
    }
}

選ぶ関数ももともと作ってある。これは戻り値で、Entity取ってたけど、イベントで返せばいいよね。


fn select_facedown_card(facedown_cards: Vec<Entity>) -> Option<Entity> {
    if facedown_cards.is_empty() {
        return None; // カードがなければ None を返す
    }

    println!("Select a card by number (1-{}):", facedown_cards.len());

    let mut input = String::new();
    std::io::stdin()
        .read_line(&mut input)
        .expect("Failed to read line");

    if let Ok(selected_index) = input.trim().parse::<usize>() {
        if selected_index > 0 && selected_index <= facedown_cards.len() {
            let selected_entity = facedown_cards[selected_index - 1];
            return Some(selected_entity); // 選択したエンティティIDを返す
        } else {
            println!("Invalid selection.");
        }
    } else {
        println!("Please enter a valid number.");
    }

    None // 何も選ばれなかったら None を返す
 
}

 

結局こういう感じになった

pub fn check_the_will_of_xskill() -> i32 {
    loop {
        println!("[1]:Xスキルを使う [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_x_phase(
    mut next_state: ResMut<NextState<PlayState>>,
    in_xzone_card: ResMut<FacedownXZoneCards>,
    mut pick_xzone_event_writher: EventWriter<PickXzone>,
) {
    let choice = check_the_will_of_xskill();

    match choice {
        1 => {
            if in_xzone_card.cards.is_empty() {
                println!("Xゾーンに裏側のカードがありません。メインフェーズに移行します。");
                next_state.set(PlayState::MainPhase);
            } else {
                pick_xzone_event_writher.send(PickXzone);
                println!("オープンするXゾーンのカードを選んでください。");
            }
        }
        2 => {
            println!("メインフェーズに移行します。");
            next_state.set(PlayState::MainPhase);
        }

        _ => {}
    }
}

pub fn list_facedown_cards_in_xzone(
    query: Query<(Entity, &Card, &Location, &FaceCondition)>,
    mut in_xzone_card: ResMut<FacedownXZoneCards>,
) {
    println!("Facedown cards in XZone are:");

    // 裏向きのカードをリストアップ
    for (entity, card, location, face_condition) in query.iter() {
        if let Location::XZone = location {
            if let FaceCondition::Facedown = face_condition {
                in_xzone_card.cards.push(entity); // エンティティIDを保存
                println!("{}: {}", in_xzone_card.cards.len(), card.name); // 番号を振って表示
            }
        }
    }
}

pub fn select_facedown_card(
    in_xzone_card: ResMut<FacedownXZoneCards>,
    mut xskill_event_writer: EventWriter<Xskill>,
    mut pick_xzone_event_reader: EventReader<PickXzone>,
) {
    for event in pick_xzone_event_reader.read() {
        println!("Select a card by number (1-{}):", in_xzone_card.cards.len());

        let mut input = String::new();
        std::io::stdin()
            .read_line(&mut input)
            .expect("Failed to read line");

        if let Ok(selected_index) = input.trim().parse::<usize>() {
            if selected_index > 0 && selected_index <= in_xzone_card.cards.len() {
                let selected_entity = in_xzone_card.cards[selected_index - 1];
                xskill_event_writer.send(Xskill {
                    open_cards: (selected_entity),
                }); // 選択したエンティティIDを返す
            } else {
                println!("Invalid selection.");
            }
        } else {
            println!("Please enter a valid number.");
        }
    }
}

pub fn xskill(mut xskill_event_reader: EventReader<Xskill>,  mut commands: Commands, mut next_state: ResMut<NextState<PlayState>>) {
    for event in xskill_event_reader.read(){
        commands.entity(event.open_cards).insert(FaceCondition::Open);
        println!("選ばれたカードをオープンしました。");
        println!("Xスキルは調整中です。そのため、メインフェーズにいきます");
        next_state.set(PlayState::MainPhase);
    }
   
}
pub struct XPhasePlugin;
impl Plugin for XPhasePlugin {
    fn build(&self, app: &mut App) {
        app.insert_resource(FacedownXZoneCards::default())
            .add_event::<PickXzone>()
            .add_event::<Xskill>()
            .add_systems(
                OnEnter(PlayState::XPhase),
                (
                    list_facedown_cards_in_xzone,
                    transition_x_phase,
                ).chain(),
            )
            .add_systems(
                Update,
                (select_facedown_card, xskill).run_if(in_state(PlayState::XPhase)),
            );
    }
}

出来たからXフェーズこれで終わりで!!

 

明日からメインフェーズやります。よろしくお願いいたします。

*1:player_entity, player_transform

*2:_, card, _

*3:card, location