Skip to content

Commit

Permalink
Merge pull request #16 from hyoi/dev-operation_with_gamepad
Browse files Browse the repository at this point in the history
ゲームパッドで操作できるようにした
  • Loading branch information
hyoi authored Nov 23, 2022
2 parents 29cd9b2 + eeaee3f commit 447932c
Show file tree
Hide file tree
Showing 12 changed files with 345 additions and 103 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "tigtag"
version = "0.6.1"
version = "0.6.2"
edition = "2021"

[dependencies.bevy]
Expand Down
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,16 @@ Note: Japanese text only.
## WASM版
https://hyoi.github.io/tigtag/
## 操作方法
`` `` `` `` キーで上下左右に移動。
`Esc`キーで一時停止(Pause)。
`Space`キーでゲーム開始など。
`Alt``Enter`でフルスクリーンとウインドウモード切替(デスクトップアプリ)。
### キーボード
- `` `` `` `` キーで上下左右に移動。
- `Space`キーでゲーム開始など。
- `Esc`キーで一時停止(Pause)。
- `Alt``Enter`でフルスクリーンとウインドウモード切替(デスクトップアプリ)。
### ゲームパッド🎮
- 十字ボタンで上下左右に移動。
- 東ボタン(A/◯等)でゲーム開始など。
- 北ボタン(Y/△等)で一時停止(Pause)。※WASMで西ボタンがPauseになる不具合確認
- 西ボタン(X/▢等)でフルスクリーンとウインドウモード切替(デスクトップアプリ)。
## コンパイル方法
デスクトップアプリにするなら`cargo run -r`でOK。
`cargo run`だとデバッグモード。(升目が表示されたり)
Expand Down Expand Up @@ -49,5 +55,5 @@ cargo install -f wasm-bindgen-cli
- [x] (v0.5.1)demoで稀に面クリするくらいに自機の逃走アルゴリズムを鍛えたい
- [ ] もちょっと鍛える余地がありそう。アイディアはあるんだが~
- [x] (v0.5.3)自機がドットのある道を通る時、WASMだとFPSが駄々下がるのをナントカしないと‥‥
- [ ] パッドで操作できるようにしたい
- [x] (v0.6.2)パッドで操作できるようにしたい
- [ ] タッチ操作できたら、ブラウザ&WASMでスマホ上で遊べる‥‥?
10 changes: 9 additions & 1 deletion src/game_play.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ pub use map::*; //pub必須(demoplayモジュールから呼び出すため)
pub use player::*; //pub必須(demoplayモジュールから呼び出すため)
pub use chasers::*; //pub必須(demoplayモジュールから呼び出すため)

mod cross_button; //ゲームパッドの十字キー入力
use cross_button::*; //プラグイン

//プラグインの設定
pub struct GamePlay;
impl Plugin for GamePlay
Expand All @@ -21,6 +24,7 @@ impl Plugin for GamePlay
.add_plugin( UiUpdate ) //header & footer UIの表示更新
.add_system( chasers::rotate_sprite ) //追手スプライトがあれば回転させる
.insert_resource( MarkAfterFetchAssets ( GameState::TitleDemo ) ) //Assetsロード後のState変更先
.add_plugin( CrossButton ) //ゲームパッドの十字キー入力
;

//GameState::TitleDemo
Expand Down Expand Up @@ -163,9 +167,13 @@ fn into_next_state_with_key<T: Component + TextUiWithHitKey>
mut record: ResMut<Record>,
mut state: ResMut<State<GameState>>,
mut inkey: ResMut<Input<KeyCode>>,
inbtn: Res<Input<GamepadButton>>,
)
{ if let Ok ( target ) = q.get_single_mut()
{ if ! inkey.just_pressed( target.key_code() ) { return }
{ //入力がないなら関数脱出
if ! inkey.just_pressed( target.key_code() )
&& ! inbtn.just_pressed( target.btn_code() )
{ return }

//GameState::GameStartへ遷移する前にゼロクリアする
let current = state.current();
Expand Down
160 changes: 160 additions & 0 deletions src/game_play/cross_button.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
use super::*;

use std::collections::HashSet;

//プラグインの設定
pub struct CrossButton;
impl Plugin for CrossButton
{ fn build( &self, app: &mut App )
{ app
.init_resource::<GamepadCrossButton>() //十字キーの入力状態を保存するResource
.add_system( read_cross_button ) //十字キーの入力読み取り
;
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

//十字キーの入力状態を保存するResource
#[derive( Resource )]
pub struct GamepadCrossButton ( Vec::<DxDy> );

impl Default for GamepadCrossButton
{ fn default() -> Self
{ Self ( Vec::with_capacity( 4 ) ) //最大4要素
}
}

//タプルの「.0」を隠すためのメソッド
impl GamepadCrossButton
{ pub fn is_empty( &self ) -> bool { self.0.is_empty() }
pub fn sides_list( &self ) -> &[ DxDy ] { &self.0 }
fn push( &mut self, dxdy: DxDy ) { self.0.push( dxdy ) }
fn clear( &mut self ) { self.0.clear() }
}

//判定用メソッド(traitはオーファンルール対策)
trait JudgeCotains
{ fn contains_right( &self ) -> bool;
fn contains_left ( &self ) -> bool;
fn contains_down ( &self ) -> bool;
fn contains_up ( &self ) -> bool;
}
impl JudgeCotains for HashSet<GamepadButtonType>
{ fn contains_right( &self ) -> bool { self.contains( &GamepadButtonType::DPadRight ) }
fn contains_left ( &self ) -> bool { self.contains( &GamepadButtonType::DPadLeft ) }
fn contains_down ( &self ) -> bool { self.contains( &GamepadButtonType::DPadDown ) }
fn contains_up ( &self ) -> bool { self.contains( &GamepadButtonType::DPadUp ) }
}

////////////////////////////////////////////////////////////////////////////////////////////////////

//十字キーの入力読み取り
fn read_cross_button
( q_player : Query< &Player >,
o_cross_button: Option<ResMut<GamepadCrossButton>>,
button_inputs: Res<Input<GamepadButton>>,
)
{ //安全装置
let Ok ( player ) = q_player.get_single() else { return }; //無ければreturn
let Some ( mut cross_button ) = o_cross_button else { return }; //無ければreturn
cross_button.clear();

//ゲームパッド(0番)の十字ボタン入力をハッシュに取得する
let pressed_btns: HashSet<_> =
{ button_inputs
.get_pressed()
.filter
( | x |
x.gamepad.id == 0 //Todo: pad 0番決め打ちでいいいのか?
&&
CROSS_BUTTON_SET.contains( &x.button_type )
)
.map( |x| x.button_type )
.collect()
};

//要素数が2未満なら
if pressed_btns.is_empty() { return }
if pressed_btns.len() == 1
{ match pressed_btns.iter().next().unwrap()
{ GamepadButtonType::DPadRight => cross_button.push( DxDy::Right ),
GamepadButtonType::DPadLeft => cross_button.push( DxDy::Left ),
GamepadButtonType::DPadDown => cross_button.push( DxDy::Down ),
GamepadButtonType::DPadUp => cross_button.push( DxDy::Up ),
_ => unimplemented!(),
}
return
}

//要素数が2つなら(十字キーの入力は最大2要素)
let right_left = if pressed_btns.contains_right() { DxDy::Right } else { DxDy::Left };
let down_up = if pressed_btns.contains_down() { DxDy::Down } else { DxDy::Up };
if player.stop //停止中なら
{ match player.side
{ DxDy::Right =>
{ cross_button.push( right_left );
cross_button.push( down_up );
},
DxDy::Left =>
{ cross_button.push( right_left );
cross_button.push( down_up );
},
DxDy::Down =>
{ cross_button.push( down_up );
cross_button.push( right_left );
},
DxDy::Up =>
{ cross_button.push( down_up );
cross_button.push( right_left );
},
}
}
else
{ //移動中なら曲がりやすい順番にする
match player.side
{ DxDy::Right =>
{ if pressed_btns.contains_right()
{ cross_button.push( down_up );
cross_button.push( DxDy::Right );
}
else
{ cross_button.push( DxDy::Left );
cross_button.push( down_up );
}
},
DxDy::Left =>
{ if pressed_btns.contains_left()
{ cross_button.push( down_up );
cross_button.push( DxDy::Left );
}
else
{ cross_button.push( DxDy::Right );
cross_button.push( down_up );
}
},
DxDy::Down =>
{ if pressed_btns.contains_down()
{ cross_button.push( right_left );
cross_button.push( DxDy::Down );
}
else
{ cross_button.push( DxDy::Up );
cross_button.push( right_left );
}
},
DxDy::Up =>
{ if pressed_btns.contains_up()
{ cross_button.push( right_left );
cross_button.push( DxDy::Up );
}
else
{ cross_button.push( DxDy::Down );
cross_button.push( right_left );
}
},
}
}
}

//End of code.
68 changes: 44 additions & 24 deletions src/game_play/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ pub fn spawn_sprite
};
let player = Player
{ grid,
next : grid,
px_start: pixel,
px_end : pixel,
fn_runaway: Some ( demo_algorithm::which_way_player_goes ), //default()に任せるとNone
next : grid,
px_start : pixel,
px_end : pixel,
o_fn_runaway: Some ( demo_algorithm::which_way_player_goes ), //default()に任せるとNone
..default()
};
cmds
Expand All @@ -60,6 +60,7 @@ pub fn move_sprite
state: ResMut<State<GameState>>,
( mut ev_clear, mut ev_over ): ( EventReader<EventClear>, EventReader<EventOver> ),
( inkey, time ): ( Res<Input<KeyCode>>, Res<Time> ),
cross_button: Res<GamepadCrossButton>,
)
{ //直前の判定でクリア/オーバーしていたらスプライトの表示を変更しない
if ev_clear.iter().next().is_some() { return }
Expand All @@ -78,33 +79,52 @@ pub fn move_sprite
}

//自機の進行方向を決める
player.stop = false;
let mut side = player.side;
if ! state.current().is_demoplay()
{ //demoでなければプレイヤーのキー入力を確認(入力がなければ停止)
if inkey.pressed( KeyCode::Up ) { side = DxDy::Up; }
else if inkey.pressed( KeyCode::Down ) { side = DxDy::Down; }
else if inkey.pressed( KeyCode::Right ) { side = DxDy::Right; }
else if inkey.pressed( KeyCode::Left ) { side = DxDy::Left; }
else { player.stop = true }

//キー入力があってもその向きに壁があれば停止
if ! player.stop
{ player.stop = map.is_wall( player.next + side )
let mut new_side = player.side;
player.stop = true; //停止フラグを立てる

if ! state.current().is_demoplay() //demoでないなら
{ if ! cross_button.is_empty() //パッド十字キー入力があるなら
{ let cross_button = cross_button.sides_list();
for &side in cross_button
{ //道なら
if map.is_passage( player.next + side )
{ new_side = side;
player.stop = false;
break;
}

//上でbrakeしない場合でも、向きだけは変える
if side == cross_button[ 0 ]
{ new_side = side;
}
}
}
else
{ //キー入力を確認(入力がなければ停止)
if inkey.pressed( KeyCode::Up ) { new_side = DxDy::Up; player.stop = false; }
else if inkey.pressed( KeyCode::Down ) { new_side = DxDy::Down; player.stop = false; }
else if inkey.pressed( KeyCode::Right ) { new_side = DxDy::Right; player.stop = false; }
else if inkey.pressed( KeyCode::Left ) { new_side = DxDy::Left; player.stop = false; }

//キー入力があっても壁があれば停止
if ! player.stop
{ player.stop = map.is_wall( player.next + new_side )
}
}
}
else
{ //四方の脇道を取得する
{ //demoの場合
let mut sides = map.get_byways_list( player.next ); //脇道のリスト
sides.retain( | side | player.next + side != player.grid ); //戻り路を排除

//demoなのでプレイヤーのキー入力を詐称する
player.stop = false;
use std::cmp::Ordering;
side = match sides.len().cmp( &1 )
new_side = match sides.len().cmp( &1 )
{ Ordering::Equal => //一本道 ⇒ 道なりに進む
sides[ 0 ],
Ordering::Greater => //三叉路または十字路
if let Some ( fnx ) = player.fn_runaway
if let Some ( fnx ) = player.o_fn_runaway
{ fnx( &player, q_chasers, map, &sides ) //外部関数で進行方向を決める
}
else
Expand All @@ -122,14 +142,14 @@ pub fn move_sprite
}

//自機の向きが変化したらスプライトを回転させる
if player.side != side
{ rotate_player_sprite( &player, &mut transform, side );
player.side = side;
if player.side != new_side
{ rotate_player_sprite( &player, &mut transform, new_side );
player.side = new_side;
}

//現在の位置と次の位置を更新する
player.grid = player.next;
if ! player.stop { player.next += side; }
if ! player.stop { player.next += new_side; }

//waitをリセットする
player.wait.reset();
Expand Down
1 change: 0 additions & 1 deletion src/public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,4 @@ pub use types::*;
pub use constants::*;
pub use misc::*;


//End of code.
Loading

0 comments on commit 447932c

Please sign in to comment.