www.youtube.com
結局菓子パンがガンだったって話だよな。 ケーキも菓子パンなどの加工食品は、GDPを挙げることに貢献するけど、社会の牌を拡張するわけではないから、過労になったり、浪費・食品ロスを生み出して、社会全体に対して負荷をかけるだけのものなんだよな。 それが競争社会と連動して、さらに人間が不幸になる仕組みになっている。 よく女の子がケーキをご褒美!!って言って食べてる。 それはつまり、ケーキを食べたくなるような高負荷の環境にいて、それにあわせてケーキ屋が睡眠時間を削ってこだわったより甘いものを食べる。こういう世界じゃ上手く行かないんだよ。
動画に「小麦をいかに効率よく吸収させるか」という観点でパンを作っていると書いてあって、これは主食という面でパンを捉えてるから牌を拡張する話なんだよ。 別枠で小麦ではなく主食のコメを育てることに注力してるだろ。それはつまり、牌を増やして皆で幸せになることを目的にしてるんだよ。
カードプレイの二人対戦化をしていく。
カードの選択をしていない(イベントからエンティティidを取得している関数は、機能を分割する必要が無いと考えたので、With<Player1>を抜いた)関数は別に関係ないと考えた。
.add_systems(
Update,
(
play_start,
select_hand,
check_played_card_type,
play_fighter_spin_szone,
play_zero_energy_fighter,
play_fighter_finish,
play_fighter_from_hand,
energy_adjustment,
play_tactics_with_penalty_from_hand,
)
.run_if(in_state(GameState::Play)),
);
この中で言うと、select_hand, play fighter_spin playtacticsspin energy_ajustmentだけが、複数人たいおうしないといけないやつで、あとは大丈夫
pub fn select_hand_opponent(
mut select_hand_event_reader: EventReader<SelectHand>,
hand: ResMut<Player2Hand>,
szone: ResMut<Player2SZone>,
mut check_played_card_type_event_writer: EventWriter<CheckPlayedCardType>,
query: Query<(Entity, &Card, &SpinCondition), With<Player2>>,
query_option: Query<(Entity, &Card, Option<&Fighter>, Option<&Tactics>), With<Player2>>,
mut main_phase_management_event_writer: EventWriter<MainPhaseManagement>,
) {
for event in select_hand_event_reader.read() {
let total_energy_in_szone_respin: u32 = szone
.cards
.filter_map(|entity| {
if let Ok*1 = query.get(*entity) {
if let SpinCondition::ReSpin = spincondition {
Some(card.energy) // リスピン中のカードのエナジーを取得
} else {
None
}
} else {
None
}
})
.sum();
println!(
"現在のSゾーンのリスピン状態のカードの合計エナジー: {}",
total_energy_in_szone_respin
);
// 手札のカードの情報を番号付きで表示
println!("手札のカード:[エナジー(タクティクスの必要エナジーは表示されません)]");
for (index, &entity) in hand.cards.iter().enumerate() {
if let Ok*2 = query.get(entity) {
println!("{}: {} [{}]", index + 1, card.name, card.energy);
}
}
// ユーザーからの入力を受け取る
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 <= hand.cards.len() {
let selected_entity = hand.cards[selected_index - 1];
query_option.get(selected_entity)
{
println!("{} はタクティクスです。", card.name);
if tactics.required_energy <= total_energy_in_szone_respin {
println!("{} を選択しました。", card.name);
check_played_card_type_event_writer.send(CheckPlayedCardType {
played_card_id: selected_entity,
});
} else {
println!(
"選択したタクティクスの必要エナジーが合計エナジーを超えています。再度選択してください。"
);
main_phase_management_event_writer.send(MainPhaseManagement);
}
} else {
// ファイターの場合の処理
if card.energy <= total_energy_in_szone_respin {
println!("{} を選択しました。", card.name);
check_played_card_type_event_writer.send(CheckPlayedCardType {
played_card_id: selected_entity,
});
} else {
println!(
"選択したファイターのエナジーが合計エナジーを超えています。再度選択してください。"
);
main_phase_management_event_writer.send(MainPhaseManagement);
}
}
} else {
println!("無効な選択です。");
main_phase_management_event_writer.send(MainPhaseManagement);
}
} else {
println!("無効な選択です。");
main_phase_management_event_writer.send(MainPhaseManagement);
}
} else {
println!("有効な番号を入力してください。");
}
}
}
pub fn play_tactics_spin_szone_opponent(
szone: ResMut<Player2SZone>,
mut play_tactics_spin_szone_event_reader: EventReader<PlayTacticsSpinSzone>,
query: Query<(Entity, &Card, &SpinCondition, &Tactics), With<Player2>>,
query2: Query<(Entity, &Card, &SpinCondition), With<Player2>>,
mut commands: Commands,
mut main_phase_management_event_writer: EventWriter<MainPhaseManagement>,
mut select_hand_event_writer: EventWriter<SelectHand>,
mut play_tactics_from_hand_event_writer: EventWriter<PlayTacticsFromHand>,
mut energy_adjustment_event_writer: EventWriter<EnergyAdjustment>,
) {
for event in play_tactics_spin_szone_event_reader.read() {
let mut available_cards = Vec::new();
let mut spin_targets: Vec<Entity> = Vec::new();
let mut used_energy_for_tactics = 0;
//Sゾーンのカードのエナジーの合計をスピンコンディション関係なく取得。
let mut total_energy_in_szone: u32 = szone
.cards
.filter_map(|entity| {
if let Ok*4 = query2.get(*entity) {
Some(card.energy) // リスピン中のカードのエナジーを取得
} else {
None
}
})
.sum();
let energy: u32 = if let Ok*5 = query.get(event.played_card_id) {
} else {
// played_cardが無効な場合の処理
println!("無効なplayed_cardです。");
continue; // 次のイベントに進む
};
// Sゾーンのカードをリストアップ
for &entity in &szone.cards {
if let Ok*6 = query2.get(entity) {
if let SpinCondition::ReSpin = spincondition {
available_cards.push(entity);
println!(
"{}: {} (Sゾーン)[{}]",
available_cards.len(),
card.name,
card.energy
);
}
}
}
// played_cardのエナジーが0の場合の処理
if energy == 0 {
println!("played_cardのエナジーが0です。");
// エナジーが0の場合の独自のロジックをここに追加
continue; // または、特定の処理を実行
}
// 選択ループ
while used_energy_for_tactics < energy {
println!(
"スピンさせるカードを選択してください (1-{}) 0:やりなおす",
available_cards.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 {
println!("選択をキャンセルし、メインフェーズに戻ります。");
main_phase_management_event_writer.send(MainPhaseManagement);
return; // ループを抜ける
}
if selected_index > 0 && selected_index <= available_cards.len() {
let selected_entity = available_cards[selected_index - 1];
// すでに選択されたカードか確認
if spin_targets.contains(&selected_entity) {
println!("このカードはすでに選択されています。");
continue; // 再選択を促す
}
if let Ok*7 = query2.get(selected_entity) {
// スピンさせるカードのリストを作る
spin_targets.push(selected_entity);
used_energy_for_tactics += card.energy;
println!(
"{} をスピンさせる対象として追加しました (現在の合計使用エナジー: {})",
);
}
} else {
println!("無効な選択です。");
}
} else {
println!("有効な番号を入力してください。");
}
}
println!(
"合計エナジーが達成されました。スピン対象: {:?}",
spin_targets
);
if let Ok*8 = query2.get(event.played_card_id) {
total_energy_in_szone += card.energy;
println!(
"プレイするタクティクスも含めたエナジーは{}です。",
total_energy_in_szone
);
}
println!("スピン予定のカード:");
for target in &spin_targets {
if let Ok*9 = query2.get(*target) {
println!("- {} [エナジー: {}]", card.name, card.energy);
}
}
if total_energy_in_szone > 10 {
println!("エナジーの調整が発生します。");
let choice = check_the_will_of_spinning_cards();
match choice {
1 => {
//エレメントについての言及は全くしていないことに注意!!
println!("スピンさせました。");
for target in &spin_targets {
commands.entity(*target).insert(SpinCondition::Spin);
}
let penalty = total_energy_in_szone - 10;
println!("送信するペナルティエナジー: {}", penalty);
energy_adjustment_event_writer.send(EnergyAdjustment {
played_card_id: event.played_card_id,
spin_cards_list: spin_targets,
penalty_energy: penalty,
});
}
2 => {
println!("やり直します");
select_hand_event_writer.send(SelectHand);
}
_ => {}
}
} else {
let choice = check_the_will_of_spinning_cards();
match choice {
1 => {
//エレメントについての言及は全くしていないことに注意!!
println!("スピンさせました。");
for target in &spin_targets {
commands.entity(*target).insert(SpinCondition::Spin);
}
play_tactics_from_hand_event_writer.send(PlayTacticsFromHand {
played_card_id: event.played_card_id,
spin_cards_list: spin_targets,
});
}
2 => {
println!("やり直します");
select_hand_event_writer.send(SelectHand);
}
_ => {}
}
}
}
}
pub fn energy_adjustment_opponent(
mut energy_adjustment_event_reader: EventReader<EnergyAdjustment>,
szone: ResMut<Player2SZone>,
query: Query<(Entity, &Card), (With<Player2>, Without<FirstEnergy>)>,
mut commands: Commands,
mut tactics_with_penalty_event_writer: EventWriter<PlayTacticsWithPenaltyFromHand>,
mut select_hand_event_writer: EventWriter<SelectHand>,
) {
for event in energy_adjustment_event_reader.read() {
let mut selected_cards: Vec<Entity> = Vec::new();
let mut total_energy_for_penalty: u32 = 0;
let penalty_energy = event.penalty_energy;
// Sゾーンのカードを取得
let available_cards: Vec<(Entity, &Card)> = szone
.cards
.filter_map(|&entity| query.get(entity).ok())
.collect();
let high_energy_cards: Vec<(Entity, &Card)> = available_cards
.filter(|(_, card)| card.energy >= penalty_energy)
.cloned()
.collect();
if !high_energy_cards.is_empty() {
println!("ペナルティエナジー以上のカードがあります。選択可能なカード:");
for (index, (entity, card)) in high_energy_cards.iter().enumerate() {
println!("{}: {} [エナジー: {}]", index + 1, card.name, card.energy);
}
// ユーザーにカードを選ばせる
loop {
// 無効な選択時に再入力を促すループ
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 <= high_energy_cards.len() {
let selected_entity = high_energy_cards[selected_index - 1].0;
selected_cards.push(selected_entity);
if let Ok*10 = query.get(selected_entity) {
total_energy_for_penalty += card.energy;
println!("選択したカード: {} [エナジー: {}]", card.name, card.energy);
}
break; // 有効な選択がされたらループを抜ける
} else {
println!("無効な選択です。再度選択してください。");
}
} else {
println!("有効な番号を入力してください。再度選択してください。");
}
}
} else {
println!("ペナルティエナジー以上のカードはありません。全てのカードを表示します。");
for (index, (entity, card)) in available_cards.iter().enumerate() {
println!("{}: {} [エナジー: {}]", index + 1, card.name, card.energy);
}
// ユーザーにカードを選ばせる
while total_energy_for_penalty <= penalty_energy {
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 <= available_cards.len() {
let selected_entity = available_cards[selected_index - 1].0;
// 既に選択されたカードか確認
if !selected_cards.contains(&selected_entity) {
selected_cards.push(selected_entity);
if let Ok*11 = query.get(selected_entity) {
total_energy_for_penalty += card.energy;
println!(
"選択したカード: {} [エナジー: {}]",
card.name, card.energy
);
}
} else {
println!("このカードは既に選択されています。");
}
} else {
println!("無効な選択です。再度選択してください。");
}
} else {
println!("有効な番号を入力してください。再度選択してください。");
}
println!(
total_energy_for_penalty, penalty_energy
);
if total_energy_for_penalty > penalty_energy {
}
// 再度ペナルティエナジー以上のカードがあるか確認
let high_energy_cards: Vec<(Entity, &Card)> = available_cards
.filter(|(_, card)| card.energy >= penalty_energy - total_energy_for_penalty)
.cloned()
.collect();
if !high_energy_cards.is_empty() {
println!("ペナルティエナジーの差以上のカードがあります。選択可能なカード:");
for (index, (entity, card)) in high_energy_cards.iter().enumerate() {
println!("{}: {} [エナジー: {}]", index + 1, card.name, card.energy);
}
}
}
}
// 最終的に選んだカードのリストを表示
println!("最終的に選ばれたカード:");
for entity in selected_cards.clone() {
if let Ok*12 = query.get(entity) {
println!("- {} [エナジー: {}]", card.name, card.energy);
}
}
println!("ペナルティを受け入れますか?");
let choice = check_the_will_of_spinning_cards();
match choice {
1 => {
for entity in selected_cards.clone() {
commands.entity(entity).insert(Location::XZone);
commands.entity(entity).insert(SpinCondition::ReSpin);
commands.entity(entity).insert(FaceCondition::Facedown);
}
tactics_with_penalty_event_writer.send(PlayTacticsWithPenaltyFromHand {
played_card_id: event.played_card_id,
spin_cards_list: event.spin_cards_list.clone(),
penalty_card_list: selected_cards.clone(),
});
}
2 => {
println!("やりなおします");
for target in &event.spin_cards_list {
commands.entity(*target).insert(SpinCondition::ReSpin);
}
println!("スピンしたカードを元に戻しました。");
select_hand_event_writer.send(SelectHand);
}
_ => {}
}
// 意思決定関数を入れた
}
}
.add_systems(
Update,
(
play_start,
select_hand,
check_played_card_type,
play_fighter_spin_szone,
play_zero_energy_fighter,
play_fighter_finish,
play_fighter_from_hand,
energy_adjustment,
play_tactics_with_penalty_from_hand,
)
.run_if(in_state(Controller::Player)),
).add_systems(
Update,
(
play_start,
select_hand_opponent,
check_played_card_type,
play_fighter_spin_szone_opponent,
play_zero_energy_fighter,
play_fighter_finish,
play_fighter_from_hand,
energy_adjustment_opponent,
play_tactics_with_penalty_from_hand,
)
.run_if(in_state(Controller::Opponent)),
);



これで、カードをプレイする機能の二人化が出来た。
次はバトルだ!!
.add_systems(
Update,
(
attack_start,
select_attacker,
choose_card_being_attacked,
handle_being_attacked,
first_energy_penalty,
attack_szone,
attack_fzone,
choose_withdraw_or_gy,
opponent_choose_withdraw_or_gy,
attack_end,
choose_guard,
)
.run_if(in_state(GameState::Play)),
);
elect attacker, choose card being, first_energy_penalty, chosse_withdraw_or_gy, opponent_chosse_withdraw_or_gy, choose_guardを対戦仕様にした
pub fn select_attacker_opponent(
fzone: ResMut<Player2FZone>,
query: Query<(Entity, &Card, &Fighter, &Location, &SpinCondition), With<Player2>>, // Fighterコンポーネントを追加
mut attack_event_writer: EventWriter<Attack>,
mut select_attacker_event_reader: EventReader<SelectAttacker>,
mut main_phase_management_event_writer: EventWriter<MainPhaseManagement>,
) {
for _event in select_attacker_event_reader.read() {
let mut available_fighters = Vec::new();
println!("Fゾーンにある攻撃可能なあなたのファイターは:");
for &entity in &fzone.cards {
if let Ok*13 = query.get(entity) {
if !fighter.summoned_sick {
if let SpinCondition::ReSpin = spincondition {
available_fighters.push(entity);
println!(
"{}: {}[{}]",
available_fighters.len(),
card.name,
fighter.power
); // 召喚酔いでない場合
}
}
}
}
if available_fighters.is_empty() {
println!("召喚酔いしていないファイターがFゾーンにありません。");
main_phase_management_event_writer.send(MainPhaseManagement);
}
println!(
"ファイターを選択してください (1-{} または 0で戻る):",
available_fighters.len()
);
loop {
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 {
// 0を選択した場合、管理フェーズに戻る
main_phase_management_event_writer.send(MainPhaseManagement);
break; // ループを抜ける
} else if selected_index > 0 && selected_index <= available_fighters.len() {
let selected_entity = available_fighters[selected_index - 1];
if let Ok*14 = query.get(selected_entity) {
attack_event_writer.send(Attack {
attacker_id: selected_entity,
});
println!("{} を攻撃するファイターとして選択しました", card.name); // カード名を表示
}
break; // 有効な選択が行われたらループを抜ける
} else {
println!("無効な選択です。もう一度入力してください。");
}
} else {
println!("有効な番号を入力してください。");
}
}
}
}
↓これ引数のリソースを変えてなかった。追記
pub fn choose_card_being_attacked_opponent(
szone_opponent: ResMut<Player2SZone>,
fzone_opponent: ResMut<Player2FZone>,
query: Query<(Entity, &Card, Option<&Fighter>, &SpinCondition), With<Player2>>, // Fighterコンポーネントを追加
mut commands: Commands,
mut being_attacked_event_writer: EventWriter<BeingAttacked>,
mut attack_event_reader: EventReader<Attack>,
mut choose_guard_event_writer: EventWriter<ChooseGuard>,
mut select_attacker_event_writer: EventWriter<SelectAttacker>,
) {
for event in attack_event_reader.read() {
let mut available_cards = Vec::new();
// Sゾーンのカードをリストアップ
for &entity in &szone_opponent.cards {
if let Ok*15 = query.get(entity) {
available_cards.push(entity);
if let Some(fighter) = fighter_option {
println!(
"{}: {} (Sゾーン)[パワー: {}]",
available_cards.len(),
card.name,
fighter.power
);
} else {
println!("{}: {} (Sゾーン)", available_cards.len(), card.name);
}
}
}
// Fゾーンのスピン中のカードをリストアップ
for &entity in &fzone_opponent.cards {
if let Ok*16 = query.get(entity) {
if let SpinCondition::Spin = spincondition {
available_cards.push(entity);
// スピンしている場合
if let Some(fighter) = fighter {
println!(
"{}: {} (Fゾーン)[パワー: {}]",
available_cards.len(),
card.name,
fighter.power
);
} else {
println!("{}: {} (Fゾーン)", available_cards.len(), card.name);
}
}
}
}
if available_cards.is_empty() {
println!("攻撃対象となるカードがありません。");
return;
}
println!("攻撃対象を選択してください (1-{}):", available_cards.len());
loop {
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 {
// 0が選択された場合、操作をキャンセル
println!("攻撃をキャンセルしました。");
select_attacker_event_writer.send(SelectAttacker);
return; // メソッドを終了
} else if selected_index > 0 && selected_index <= available_cards.len() {
let selected_entity = available_cards[selected_index - 1];
if let Ok*17 = query.get(selected_entity) {
choose_guard_event_writer.send(ChooseGuard {
attacked_card_id: selected_entity,
attacker_id: event.attacker_id,
});
println!("{} を攻撃対象として選択しました", card.name); // カード名を表示
println!("攻撃ファイターをスピンしました。");
commands
.entity(event.attacker_id)
.insert(SpinCondition::Spin);
}
break; // 有効な選択が行われたらループを抜ける
} else {
println!("無効な選択です。もう一度入力してください。");
}
} else {
println!("有効な番号を入力してください。");
}
}
}
}
pub fn choose_guard_opponent(
query: Query<(Entity, &Card, &SpinCondition, &Fighter), (With<Player1>, With<Guard>)>,
fzone_opponent: ResMut<Player1FZone>,
mut choose_guard_eventreader: EventReader<ChooseGuard>,
mut attack_fzone_event_writer: EventWriter<AttackFZone>,
mut being_attacked_event_writer: EventWriter<BeingAttacked>,
mut commands: Commands,
) {
for event in choose_guard_eventreader.read() {
let mut has_respin = false;
// fzone_opponent に含まれるエンティティをループ
let mut available_guards = Vec::new();
for &entity in &fzone_opponent.cards {
if let Ok*18 = query.get(entity) {
if let SpinCondition::ReSpin = spincondition {
available_guards.push(entity);
println!(
"{}: {}[{}]",
available_guards.len(),
card.name,
fighter.power
); // 召喚酔いでない場合
}
}
}
if available_guards.is_empty() {
println!("ガードはありません");
being_attacked_event_writer.send(BeingAttacked {
attacker_id: event.attacker_id,
attacked_card_id: event.attacked_card_id,
});
} else {
println!(
"ガードファイターを選んでいます。 (1-{})[0]でガードをやめる",
available_guards.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 {
// 攻撃をやめる場合
println!("ガードされませんでした");
being_attacked_event_writer.send(BeingAttacked {
attacked_card_id: event.attacked_card_id,
attacker_id: event.attacker_id,
});
}
if selected_index > 0 && selected_index <= available_guards.len() {
let selected_entity = available_guards[selected_index - 1];
if let Ok*19 = query.get(selected_entity) {
attack_fzone_event_writer.send(AttackFZone {
attacked_card_id: selected_entity,
attacker_id: event.attacker_id,
});
println!("{} にガードされました", card.name); // カード名を表示
commands.entity(selected_entity).insert(SpinCondition::Spin);
println!("{}はスピンしました", card.name);
}
} else {
println!("ガードされませんでした");
being_attacked_event_writer.send(BeingAttacked {
attacked_card_id: event.attacked_card_id,
attacker_id: event.attacker_id,
});
}
} else {
println!("有効な番号を入力してください。");
}
}
}
}
pub fn choose_withdraw_or_gy_opponent(
mut choose_withdraw_event_writer: EventReader<ChooseWithdrawOrGY>,
mut commands: Commands,
query: Query<(Entity, &Card, &Location)>,
szone: ResMut<Player2SZone>,
mut attack_end_event_writer: EventWriter<AttackEnd>,
) {
for event in choose_withdraw_event_writer.read() {
let mut total_energy = 0;
for entity in szone.cards.iter() {
if let Ok*20 = query.get(*entity) {
total_energy += card.energy;
}
}
println!("合計エナジーは現在:{}", total_energy);
if let Ok*21 = query.get(event.attacker_id) {
println!("{}はエナジー:{}", card.name, card.energy);
total_energy += card.energy;
}
let choice = check_the_will_of_withdraw_or_gy();
match choice {
1 => {
if total_energy > 10 {
println!(
"このカードはエナジーが大きすぎて、撤退できません。自動的に墓地に行きます。"
);
commands
.entity(event.attacker_id)
.insert(Location::GraveYard);
commands
.entity(event.attacker_id)
.insert(SpinCondition::ReSpin);
} else {
println!("撤退させました");
commands.entity(event.attacker_id).insert(Location::SZone);
}
}
2 => {
println!("墓地に行きました");
commands
.entity(event.attacker_id)
.insert(Location::GraveYard);
commands
.entity(event.attacker_id)
.insert(SpinCondition::ReSpin);
}
_ => {}
}
attack_end_event_writer.send(AttackEnd {
attacker_id: event.attacker_id,
});
}
}
pub fn opponent_choose_withdraw_or_gy_opponent(
mut opponent_choose_withdraw_event_writer: EventReader<OpponentWithdrawOrGY>,
mut commands: Commands,
query: Query<(Entity, &Card, &Location)>,
szone_opponent: ResMut<Player1SZone>,
mut attack_end_event_writer: EventWriter<AttackEnd>,
) {
for event in opponent_choose_withdraw_event_writer.read() {
let mut total_energy = 0;
for entity in szone_opponent.cards.iter() {
if let Ok*22 = query.get(*entity) {
total_energy += card.energy;
}
}
println!("合計エナジーは現在:{}", total_energy);
if let Ok*23 = query.get(event.attacked_card_id) {
println!("{}はエナジー:{}", card.name, card.energy);
total_energy += card.energy;
}
let choice = check_the_will_of_withdraw_or_gy();
match choice {
1 => {
if total_energy > 10 {
println!(
"このカードはエナジーが大きすぎて、撤退できません。自動的に墓地に行きます。"
);
commands
.entity(event.attacked_card_id)
.insert(Location::GraveYard);
commands
.entity(event.attacked_card_id)
.insert(SpinCondition::ReSpin);
} else {
println!("撤退させました");
commands
.entity(event.attacked_card_id)
.insert(Location::SZone);
}
}
2 => {
println!("墓地に行きました");
commands
.entity(event.attacked_card_id)
.insert(Location::GraveYard);
commands
.entity(event.attacked_card_id)
.insert(SpinCondition::ReSpin);
}
_ => {}
}
attack_end_event_writer.send(AttackEnd {
attacker_id: event.attacker_id,
});
}
}
pub fn first_energy_penalty_opponent(
mut first_energy_penalty_event_reader: EventReader<FirstEnergyPenalty>,
mut commands: Commands,
mut in_library_cards: ResMut<InLibraryCards>,
mut attack_end_event_writer: EventWriter<AttackEnd>,
) {
for event in first_energy_penalty_event_reader.read() {
if let Some(&top_card) = in_library_cards.cards.first() {
commands.entity(top_card).insert(Location::XZone);
in_library_cards.cards.remove(0); // 先頭のカードを削除
println!("プレイヤー2は1枚ペナルティを受けました。");
} else {
println!("No cards available in the deck.");
}
attack_end_event_writer.send(AttackEnd {
attacker_id: event.attacker_id,
});
}
}
これらの関数の引数を調整した。
.add_systems(
Update,
(
attack_start,
select_attacker_opponent,
choose_card_being_attacked_opponent,
handle_being_attacked,
first_energy_penalty_opponent,
attack_szone,
attack_fzone,
choose_withdraw_or_gy_opponent,
opponent_choose_withdraw_or_gy_opponent,
attack_end,
choose_guard_opponent,
)
.run_if(in_state(Controller::Opponent)),
)
こういう風にインサートした。

choose being attackedがplayerのカードになってしまっていたので、直した。
勝利条件も情熱が置かれたのに、player2が買ってるから直す。
situation log opponentも、勝利条件を逆にしてきたので大丈夫多分。

run_if メインフェーズが無いので、複数のイベントが発信されたりしてバグることが多い。

複数のイベントが発信は無くなったけ、ターンエンド関数が上手くいっていないと思う。
ちょっと原因が分からないから、全部にステートでrun ifつけてくる。
結構うまくいくようになったんだけど、

今度は、攻撃ファイターを選ばないと2回イベントが出るようになってる問題を解決する。
pub fn select_attacker_opponent(
fzone: ResMut<Player2FZone>,
query: Query<(Entity, &Card, &Fighter, &Location, &SpinCondition), With<Player2>>, // Fighterコンポーネントを追加
mut attack_event_writer: EventWriter<Attack>,
mut select_attacker_event_reader: EventReader<SelectAttacker>,
mut main_phase_management_event_writer: EventWriter<MainPhaseManagement>,
) {
for _event in select_attacker_event_reader.read() {
let mut available_fighters = Vec::new();
println!("Fゾーンにある攻撃可能なあなたのファイターは:");
for &entity in &fzone.cards {
if let Ok*24 = query.get(entity) {
if !fighter.summoned_sick {
if let SpinCondition::ReSpin = spincondition {
available_fighters.push(entity);
println!(
"{}: {}[{}]",
available_fighters.len(),
card.name,
fighter.power
); // 召喚酔いでない場合
}
}
}
}
if available_fighters.is_empty() {
println!("召喚酔いしていないファイターがFゾーンにありません。");
main_phase_management_event_writer.send(MainPhaseManagement);
}
println!(
"ファイターを選択してください (1-{} または 0で戻る):",
available_fighters.len()
);
loop {
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 {
// 0を選択した場合、管理フェーズに戻る
main_phase_management_event_writer.send(MainPhaseManagement);
break; // ループを抜ける
} else if selected_index > 0 && selected_index <= available_fighters.len() {
let selected_entity = available_fighters[selected_index - 1];
if let Ok*25 = query.get(selected_entity) {
attack_event_writer.send(Attack {
attacker_id: selected_entity,
});
println!("{} を攻撃するファイターとして選択しました", card.name); // カード名を表示
}
break; // 有効な選択が行われたらループを抜ける
} else {
println!("無効な選択です。もう一度入力してください。");
}
} else {
println!("有効な番号を入力してください。");
}
}
}
}
if available_fighters.is_empty() {
println!("召喚酔いしていないファイターがFゾーンにありません。");
main_phase_management_event_writer.send(MainPhaseManagement);
}
これが呼び出されたら、この関数を脱出する必要があるね。
if available_fighters.is_empty() {
println!("召喚酔いしていないファイターがFゾーンにありません。");
main_phase_management_event_writer.send(MainPhaseManagement);
return;
}
return;をつけた。
ガードを選ばせるときも、ガードが無ければイベント発信して、return;するようにした。
また、対応するopponent関数にも反映した
これ手札を選ばせるときとかも入れた方がいいね。
pub fn select_hand(
mut select_hand_event_reader: EventReader<SelectHand>,
hand: ResMut<Player1Hand>,
szone: ResMut<Player1SZone>,
mut check_played_card_type_event_writer: EventWriter<CheckPlayedCardType>,
query: Query<(Entity, &Card, &SpinCondition), With<Player1>>,
query_option: Query<(Entity, &Card, Option<&Fighter>, Option<&Tactics>), With<Player1>>,
mut main_phase_management_event_writer: EventWriter<MainPhaseManagement>,
) {
for event in select_hand_event_reader.read() {
let total_energy_in_szone_respin: u32 = szone
.cards
.filter_map(|entity| {
if let Ok*26 = query.get(*entity) {
if let SpinCondition::ReSpin = spincondition {
Some(card.energy) // リスピン中のカードのエナジーを取得
} else {
None
}
} else {
None
}
})
.sum();
if hand.cards.is_empty() {
println!("手札にカードがありません");
main_phase_management_event_writer.send(MainPhaseManagement);
return;
}
println!(
"現在のSゾーンのリスピン状態のカードの合計エナジー: {}",
total_energy_in_szone_respin
);
省略
このように手札が無い時の条件を入れた。
今気づいたけど

XZoneのカードの表記がちょっとおかしいね。後で直そう。

手札にカードが無い時でも2重でイベントが出ないようになった。

相打ちでも2重にイベントが出るようになってる。
pub fn attack_fzone(
mut attack_fzone_event_reader: EventReader<AttackFZone>,
mut battle_fighter_win_event_writer: EventWriter<BattleFighterWin>,
mut attack_end_event_writer: EventWriter<AttackEnd>,
mut choose_withdraw_event_writer: EventWriter<ChooseWithdrawOrGY>,
mut opponent_choose_withdraw_event_writer: EventWriter<OpponentWithdrawOrGY>,
query: Query<(Entity, &Card, &Fighter)>,
) {
for event in attack_fzone_event_reader.read() {
// クエリから攻撃者と攻撃対象の情報を取得
let attacker_query = query.get(event.attacker_id);
let attacked_query = query.get(event.attacked_card_id);
match (attacker_query, attacked_query) {
(
) => {
let attacker_power = attacker_fighter.power; // 攻撃者のパワーを取得
let attacked_power = attacked_fighter.power; // 攻撃対象のパワーを取得
// 攻撃者のパワーが攻撃対象のパワーより大きい場合
if attacker_power > attacked_power {
println!("バトルに勝ちました。");
battle_fighter_win_event_writer.send(BattleFighterWin {
winner_id: event.attacker_id,
});
opponent_choose_withdraw_event_writer.send(OpponentWithdrawOrGY {
attacker_id: event.attacker_id,
attacked_card_id: event.attacked_card_id,
});
}
if attacker_power == attacked_power {
println!("相打ちです");
opponent_choose_withdraw_event_writer.send(OpponentWithdrawOrGY {
attacker_id: event.attacker_id,
attacked_card_id: event.attacked_card_id,
});
choose_withdraw_event_writer.send(ChooseWithdrawOrGY {
attacker_id: event.attacker_id,
attacked_card_id: event.attacked_card_id,
});
}
if attacker_power < attacked_power {
println!("バトルに負けました");
battle_fighter_win_event_writer.send(BattleFighterWin {
winner_id: event.attacked_card_id,
});
choose_withdraw_event_writer.send(ChooseWithdrawOrGY {
attacker_id: event.attacker_id,
attacked_card_id: event.attacked_card_id,
});
}
// 攻撃終了イベントを発行
}
_ => {
// もしいずれかのエンティティが見つからない場合のエラーログ
println!("攻撃者または攻撃対象の情報が見つかりません。");
}
}
}
}
相打ちイベントを作って、それで処理しよう。
単純にChooseWithdrawOrGYとOpponentChooseWithdrawOrGYを両方同時に処理する関数を作ればいいだけや。ただ、オンライン化する際には、だれが入力するかを注意しないといけない。なので、イベントを二つに分けよう。
pub fn aiuchi(
mut aiuchi_event_reader: EventReader<Aiuchi>,
mut commands: Commands,
query: Query<(Entity, &Card, &Location)>,
szone_opponent: ResMut<Player2SZone>,
szone: ResMut<Player1SZone>,
mut attack_end_event_writer: EventWriter<AttackEnd>,
) {
for event in aiuchi_event_reader.read() {
let mut total_energy = 0;
for entity in szone.cards.iter() {
if let Ok*29 = query.get(*entity) {
total_energy += card.energy;
}
}
println!("あなたのSゾーンの合計エナジーは現在:{}", total_energy);
if let Ok*30 = query.get(event.attacker_id) {
println!("{}はエナジー:{}", card.name, card.energy);
total_energy += card.energy;
}
let choice = check_the_will_of_withdraw_or_gy();
match choice {
1 => {
if total_energy > 10 {
println!(
"このカードはエナジーが大きすぎて、撤退できません。自動的に墓地に行きます。"
);
commands
.entity(event.attacker_id)
.insert(Location::GraveYard);
commands
.entity(event.attacker_id)
.insert(SpinCondition::ReSpin);
} else {
println!("撤退させました");
commands.entity(event.attacker_id).insert(Location::SZone);
}
}
2 => {
println!("墓地に行きました");
commands
.entity(event.attacker_id)
.insert(Location::GraveYard);
commands
.entity(event.attacker_id)
.insert(SpinCondition::ReSpin);
}
_ => {}
}
let mut total_energy = 0;
for entity in szone_opponent.cards.iter() {
if let Ok*31 = query.get(*entity) {
total_energy += card.energy;
}
}
println!("相手のSゾーンの合計エナジーは現在:{}", total_energy);
if let Ok*32 = query.get(event.attacked_card_id) {
println!("{}はエナジー:{}", card.name, card.energy);
total_energy += card.energy;
}
let choice = check_the_will_of_withdraw_or_gy();
match choice {
1 => {
if total_energy > 10 {
println!(
"このカードはエナジーが大きすぎて、撤退できません。自動的に墓地に行きます。"
);
commands
.entity(event.attacked_card_id)
.insert(Location::GraveYard);
commands
.entity(event.attacked_card_id)
.insert(SpinCondition::ReSpin);
} else {
println!("撤退させました");
commands.entity(event.attacked_card_id).insert(Location::SZone);
}
}
2 => {
println!("墓地に行きました");
commands
.entity(event.attacked_card_id)
.insert(Location::GraveYard);
commands
.entity(event.attacked_card_id)
.insert(SpinCondition::ReSpin);
}
_ => {}
}
attack_end_event_writer.send(AttackEnd {
attacker_id: event.attacker_id,
});
}
}
書いてきた。
ちゃんとopponentの方も書いて、登録しておいた。

オッケーそう。
これで終わりかぁ???

ガードされなかった時、またバグってるぞー
if selected_index == 0 {
// 攻撃をやめる場合
println!("ガードされませんでした");
being_attacked_event_writer.send(BeingAttacked {
attacked_card_id: event.attacked_card_id,
attacker_id: event.attacker_id,
});
return;
}
こういう風に、return;を追加してイベントは一つにさせた。

これでイベントが一つしか出ないようになった。OK
よっしゃこれで、Xゾーンのバグを直せる。
ただ、Xスキルは調整中なので、ちょっと待ってよ。

こういう、フェイズの終わりに、次のフェイズの名前が書いてあるのが変だから、
最後に書くのをやめて、start なんちゃら関数に、表示させる機能をつける。

OKOK
あとやることは、カードの効果の実装と、Xゾーンの順番の実装。エレメントの実装はあとでもいい。
Xゾーンにかかわる部分のリストとして、
Xフェーズ、メインの状況判断関数、ペナルティ、Sゾーンへの攻撃、ファーストエナジーへの攻撃、これだけ、
それらを調整する。
まず、初期設定で、Xゾーンにあるカードもあるので、それは
pub fn list_facedown_cards_in_xzone(
query: Query<(Entity, &Card, &Location, &FaceCondition), With<Player1>>,
mut in_xzone_card: ResMut<FacedownXZoneCards>,
mut list_facedown_cards_in_xzone_event_reader: EventReader<ListFacedownCardsInXzone>,
mut x_phase_management_event_writer: EventWriter<XPhaseManagement>,
) {
for event in list_facedown_cards_in_xzone_event_reader.read() {
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); // 番号を振って表示
}
}
}
x_phase_management_event_writer.send(XPhaseManagement);
}
}
これを改造した関数を、ローディングで貼ることによって、調整する。
pub fn list_facedown_cards_in_xzone(
query: Query<(Entity, &Card, &Location, &FaceCondition), With<Player1>>,
mut in_xzone_card: ResMut<FacedownXZoneCards>,
) {
println!("初期設定で裏向きでXゾーンにあるカードをロードしました。");
// 裏向きのカードをリストアップ ただ、順番が滅茶滅茶な事に注意!!これはデバッグ用の機能
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 list_facedown_cards_in_xzone_opponent(
query: Query<(Entity, &Card, &Location, &FaceCondition), With<Player2>>,
mut in_xzone_card: ResMut<FacedownXZoneCardsOpponent>,
) {
println!("初期設定で裏向きでXゾーンにあるカードをロードしました。");
// 裏向きのカードをリストアップ ただ、順番が滅茶滅茶な事に注意!!これはデバッグ用の機能
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); // 番号を振って表示
}
}
}
}
これをローディングステートでチェックできるようにした。
その次に、リストアップはやめて、
Xフェーズでは、既に裏になっているカードのエンティティIDを表示するようにした。
pub fn see_facedown_cards_in_xzone(
query: Query<(Entity, &Card, &Location, &FaceCondition), With<Player1>>,
mut in_xzone_card: ResMut<FacedownXZoneCards>,
mut list_facedown_cards_in_xzone_event_reader: EventReader<ListFacedownCardsInXzone>,
mut x_phase_management_event_writer: EventWriter<XPhaseManagement>,
) {
for event in list_facedown_cards_in_xzone_event_reader.read() {
println!("Facedown cards in XZone are:");
println!("{:?}", in_xzone_card.cards);
x_phase_management_event_writer.send(XPhaseManagement);
}
}
pub fn see_facedown_cards_in_xzone_opponent(
query: Query<(Entity, &Card, &Location, &FaceCondition), With<Player2>>,
mut in_xzone_card: ResMut<FacedownXZoneCardsOpponent>,
mut list_facedown_cards_in_xzone_event_reader: EventReader<ListFacedownCardsInXzone>,
mut x_phase_management_event_writer: EventWriter<XPhaseManagement>,
) {
for event in list_facedown_cards_in_xzone_event_reader.read() {
println!("Facedown cards in XZone are:");
println!("{:?}", in_xzone_card.cards);
x_phase_management_event_writer.send(XPhaseManagement);
}
}
これにより、順番が保持される。
Sゾーンの攻撃では、与えるペナルティが、相手のXゾーンに行くので、Opponentバージョンも作らなければいけなくなった。
pub fn attack_szone(
mut attack_szone_event_reader: EventReader<AttackSZone>,
mut battle_fighter_win_event_writer: EventWriter<BattleFighterWin>,
mut destroyed_fighter_event_writer: EventWriter<DestroyedFighter>,
mut attack_end_event_writer: EventWriter<AttackEnd>,
mut in_xzone_card: ResMut<FacedownXZoneCardsOpponent>,
query: Query<(Entity, &Card, &Fighter)>,
mut commands: Commands,
) {
for event in attack_szone_event_reader.read() {
// クエリから攻撃者と攻撃対象の情報を取得
let attacker_query = query.get(event.attacker_id);
let attacked_query = query.get(event.attacked_card_id);
match (attacker_query, attacked_query) {
(
) => {
let attacker_power = attacker_fighter.power; // 攻撃者のパワーを取得
let attacked_power = attacked_fighter.power; // 攻撃対象のパワーを取得
// 攻撃者のパワーが攻撃対象のパワーより大きい場合
if attacker_power > attacked_power {
println!(
"{:?} は {:?} に勝利しました",
attacker_card.name, attacked_card.name
);
// 勝利イベントを発行
battle_fighter_win_event_writer.send(BattleFighterWin {
winner_id: event.attacker_id,
});
// 攻撃対象を破壊するイベントを発行
destroyed_fighter_event_writer.send(DestroyedFighter {
destroyed_fighter_id: event.attacked_card_id,
});
commands
.entity(event.attacked_card_id)
.insert(SpinCondition::ReSpin);
commands
.entity(event.attacked_card_id)
.insert(Location::XZone);
commands
.entity(event.attacked_card_id)
.insert(FaceCondition::Facedown);
println!(
"{:?}は破壊されました。Xゾーンに送られます。",
event.attacked_card_id
);
in_xzone_card.cards.push(event.attacked_card_id);
} else {
// 攻撃者のパワーが攻撃対象のパワー以下の場合
println!("何も起きませんでした");
}
// 攻撃終了イベントを発行
attack_end_event_writer.send(AttackEnd {
attacker_id: event.attacker_id,
});
}
_ => {
// もしいずれかのエンティティが見つからない場合のエラーログ
println!("攻撃者または攻撃対象の情報が見つかりません。");
}
}
}
}
in_xzone_card.cards.push(event.attacked_card_id); を追加した。
println!("ペナルティを受け入れますか?");
let choice = check_the_will_of_spinning_cards();
match choice {
1 => {
for entity in selected_cards.clone() {
commands.entity(entity).insert(Location::XZone);
commands.entity(entity).insert(SpinCondition::ReSpin);
commands.entity(entity).insert(FaceCondition::Facedown);
in_xzone_cards.cards.push(entity);
}
これは、エナジーの調整にいれた。
pub fn first_energy_penalty_opponent(
mut first_energy_penalty_event_reader: EventReader<FirstEnergyPenalty>,
mut commands: Commands,
mut in_library_cards: ResMut<InLibraryCards>,
mut in_xzone_card: ResMut<FacedownXZoneCards>,
mut attack_end_event_writer: EventWriter<AttackEnd>,
) {
for event in first_energy_penalty_event_reader.read() {
if let Some(&top_card) = in_library_cards.cards.first() {
commands.entity(top_card).insert(Location::XZone);
in_library_cards.cards.remove(0); // 先頭のカードを削除
println!("プレイヤー1は1枚ペナルティを受けました。");
in_xzone_card.cards.push(top_card);
} else {
println!("No cards available in the deck.");
}
attack_end_event_writer.send(AttackEnd {
attacker_id: event.attacker_id,
});
}
}
これは、ファーストエナジーに攻撃した時に入れるようにした。


出来てそうではある。
attack tacticsでやってなかった。
mut attack_tactics_event_reader: EventReader<AttackTactics>,
mut battle_tactics_win_event_writer: EventWriter<BattleTacticsWin>,
mut destroyed_tactics_event_writer: EventWriter<DestroyedTactics>,
mut attack_end_event_writer: EventWriter<AttackEnd>,
mut in_xzone_card: ResMut<FacedownXZoneCards>,
mut commands: Commands,
) {
for event in attack_tactics_event_reader.read() {
battle_tactics_win_event_writer.send(BattleTacticsWin {
attacker_id: event.attacker_id,
});
println!("{:?}はバトルに勝利しました", event.attacker_id);
commands
.entity(event.attacked_card_id)
.insert(FaceCondition::Facedown);
commands
.entity(event.attacked_card_id)
.insert(Location::XZone);
commands
.entity(event.attacked_card_id)
.insert(SpinCondition::ReSpin);
in_xzone_card.cards.push(event.attacked_card_id);
destroyed_tactics_event_writer.send(DestroyedTactics {
destroyed_tactics_id: event.attacked_card_id,
});
println!(
"{:?}は破壊されました。Xゾーンに送られます。",
event.attacked_card_id
);
attack_end_event_writer.send(AttackEnd {
attacker_id: event.attacker_id,
});
}
}
やっときました。

気付いたけど、プレイステートじゃないと動かないようにした方がいいね。
直してきた。

何故かペナルティ付きだと、カード情報が更新されないバグを発見。
ちょっと知らんわこれは

攻撃対象で変なの選ぶと、戻らないバグ loop書いて、直してきた。
あとやるべきなのは、カードの効果の実装。