最近お腹が減ってしょうがない。
youtu.be
note.com
championcross.jp
昨日は掃除したり、引っ越し準備したので、疲れてプログラミングはほとんどしなかった。
今日の目標、各ステートのプラグインを作る。
ステート移行のプラグインを作る。
とりあえず、LoadingStateを作る。
- このステートがデフォルトである
- お互いのデッキを確定し、そのデータを読み込みます。
- お互いのファーストエナジーカードを確定し、そのデータを読み込みます。
- 読み込んだカードを山札にセットします。
- 山札をシャッフルします
- Sゾーンにファーストエナジーカードを裏向きで置きます。
- セットアップステートに自動で移行する
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
.id();
println!("{:?} is spawned", my_entity);
}
このようにして、作りました。
カードのタイプは、タグコンポーネントでつけました。
#[derive(States, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[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
.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
.id();
println!("{:?} is spawned", my_entity);
中略()
今気づいたけど、ファーストエナジーオープンはあとだ。
今までMinimulPluginを最初に入れていたけど、ステートを使うなら、DefaultPluginを入れないといけないらしい。

できたわ。
次の目的
あとは、setupステートを完成させる。
- ドロー機能
- マリガン機能
- じゃんけんで先行後攻を決める機能
- ターンプレイヤーを記録する機能
- ファーストエナジーオープンする機能
- 初手とファーストエナジーを記録する機能
- プレイステートに自動で移行する
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)]
#[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です。もう今日はやめます。
Card {
power: None,
name: String::from("勇敢のエナジー"),
energy: 2,
},
Location::SZone,
SpinCondition::ReSpin,
FaceCondition::Facedown,
FirstEnergy{},
Card {
power: None,
name: String::from("勇敢のエナジー"),
energy: 2,
},
Location::SZone,
SpinCondition::ReSpin,
FaceCondition::Facedown,
FirstEnergy {},
Card {
power: Some(1000),
name: String::from("リトルナイト"),
energy: 1,
},
Location::InLibrary,
SpinCondition::ReSpin,
FaceCondition::Facedown,
Fighter {},