1
1

More than 5 years have passed since last update.

PowerAppsでバトルゲームを作ろう!(その2:戦闘画面)

Last updated at Posted at 2018-09-11

前回記事

こちらをどうぞ!
PowerAppsでバトルゲームを作ろう!(その1)

ダメージ計算式の設計

バトルゲームっていうのは、相手に攻撃した時の
ダメージ量によりHPを削っていき、最終的に相手のHPを0にした方が勝ち
というルールです。
したがって、画面を作る前にダメージ計算式を設計する必要があります。

ダメージ(ATP)算出計算式

自分の攻撃力=OAP
自分の防御力=ODF
自分の運=OLK
敵の攻撃力=EAP
敵の防御力=EDF
敵の運=ELK
攻撃時補正値倍率(RTM)=OLK-ELK (0以下の場合は0.5)
ATP = (OAP-EDF) + (乱数(0~5)×RTM)

素早さの使い道

こちらは先行・後行の判定で使用します。
※命中率の計算式でも使えると思いますが割愛。

では、引き続き作っていきます!

戦闘画面(Battle_Screen)

image.png

変数の作成

この画面で作成する変数は以下の通りです。

変数名 変数種別 説明 初期値
1P_Current_HP UpdateContext 1Pの現在HP 1P_MAX_HP
2P_Current_HP UpdateContext 2Pの現在HP 2P_MAX_HP
1PTurn UpdateContext 1Pのターンかどうか 1P_SPD>2P_SPD:true
2PTurn UpdateContext 2Pのターンかどうか 2P_SPD>=1P_SPD:true
1P_Rand_Times UpdateContext 1PのRTM ※計算式参照
2P_Rand_Times UpdateContext 2PのRTM ※計算式参照
1P_Attack_Ponit UpdateContext 1PのATK Blank()
2P_Attack_Ponit UpdateContext 2PのATK Blank()

変数はBattle_ScreenのOnVisibleプロパティにて宣言します。

Battle_Screen(OnVisible)
UpdateContext({'1P_Current_HP':1P_MAX_HP,'2P_Current_HP':Var_2P_Max_HP});
If(1P_SPD>2P_SPD,UpdateContext({'1PTurn':true,'2PTurn':false}),UpdateContext({'1PTurn':false,'2PTurn':true}));
UpdateContext({'1P_Rand_Times':If((1P_LCK-2P_LCK)<0,0.5,(1P_LCK-2P_LCK))});
UpdateContext({'2P_Rand_Times':If((2P_LCK-1P_LCK)<0,0.5,(2P_LCK-1P_LCK))});
UpdateContext({'1P_Attack_Ponit':Blank(),'2P_Attack_Ponit':Blank()})

1P画面の作り方

image.png

①HP表示エリア(1P_HP_Display)

ここは以下のように設定します。

1P_HP_Display(Text)
If('1P_Current_HP'>0,Round('1P_Current_HP',0)&"/"&1P_MAX_HP,"0/"&1P_MAX_HP)

②HPゲージ(1P_HP_Gage)、(1P_HP_Gage_Frame)

現在HPが減るにつれて、最大HPとの割合をゲージにて表現します
また、HPが50%未満で色が黄色に
HPが30%未満で赤色という感じで表現しています。

ここは実は二つのオブジェクトが存在しています。
外枠で使用する1P_HP_Gage_Frameと
実際の表示部分である1P_HP_Gageです。
image.png

実際に様々な関数を入れていくのは、1P_HP_Gageになります。
関数を入れるプロパティはHeight,Width,X,Y,Fillの5つです。

1P_HP_Gage(Height)
'1P_HP_Gage_Frame'.Height-('1P_HP_Gage_Frame'.BorderThickness*2)
1P_HP_Gage(Width)
('1P_HP_Gage_Frame'.Width-('1P_HP_Gage_Frame'.BorderThickness*2))*('1P_Current_HP'/1P_MAX_HP)
1P_HP_Gage(X)
'1P_HP_Gage_Frame'.X+('1P_HP_Gage_Frame'.BorderThickness)
1P_HP_Gage(Y)
'1P_HP_Gage_Frame'.Y+('1P_HP_Gage_Frame'.BorderThickness)
1P_HP_Gage(Fill)
If(('1P_Current_HP'/1P_MAX_HP) >= 0.5,LightGreen,
    If(('1P_Current_HP'/1P_MAX_HP) >= 0.3,Yellow,Red))

③1P攻撃ボタン(1P_ATK_Button)

このボタンこそ、まさにバトルシステムの演算コントロールそのものとなります。
押せるのは、1P_TurnがTrueの時のみです。
また、1Pもしくは2PのHPが0以下になったら非表示にする必要があります。
なので、Visible及びOnSelect の2つのプロパティを設定します。

1P_ATK_Button(Visible)
If('2P_Current_HP'<=0,false,If('1P_Current_HP'<=0,false,'1PTurn'))
1P_ATK_Button(OnSelect)
UpdateContext({'1P_Attack_Ponit':(1P_PWR-2P_DFS)+Round((Rand()*5)*'1P_Rand_Times',0)});
If('1P_Attack_Ponit'>0,UpdateContext({'2P_Current_HP':('2P_Current_HP'-'1P_Attack_Ponit')}),"");
UpdateContext({'1PTurn':false,'2PTurn':true})

補足説明

1行目で、ATK値を算出しています。
Rand関数は0~1の数値からランダムで設定されますので、これを5倍すると0~5の数値からランダムで設定されることになります。
なお、Round関数を使用したのは、整数に丸めないと数値が小数点10何位までになってしまうため割合が非常に多岐に渡ってしまう為です。
2行目で、2Pの現在HPから算出したATKを引いています。ただし、ATKは0以下になる場合がありますのでその場合は何もしないように設定しています。
3行目でターンを1Pから2Pに切り替えます。

2P画面の作り方

1P画面と一緒です。

メッセージウィンドウ(Battle_Message)

この部分です。
image.png

こちらは単純なラベルを使っていて、Textプロパティに関数をセットしています。
ダメージが15以上は会心の一撃と表現しています。
また、ダメージが0以下の場合はダメージを与えられないという表現もしています。

Battle_Message(Text)
If(And(IsBlank('1P_Attack_Ponit'),IsBlank('2P_Attack_Ponit')),"",
    If('1P_Current_HP'<=0,"2Pの勝利!",
    If('2P_Current_HP'<=0,"1Pの勝利!",
    If(And('1P_Attack_Ponit'>15,'2PTurn'),Concatenate("1Pは2Pに会心の一撃!2Pは",Text('1P_Attack_Ponit',"[$-ja-JP]####"),"のダメージ"),
    If(And('1P_Attack_Ponit'>0,'2PTurn'),Concatenate("1Pは2Pにこうげき!2Pは",Text('1P_Attack_Ponit',"[$-ja-JP]####"),"のダメージ"),
    If(And('1P_Attack_Ponit'<=0,'2PTurn'),"1Pは2Pにダメージを与えられない!",
    If(And('2P_Attack_Ponit'>15,'1PTurn'),Concatenate("2Pは1Pに会心の一撃!1Pは",Text('2P_Attack_Ponit',"[$-ja-JP]####"),"のダメージ"),
    If(And('2P_Attack_Ponit'>0,'1PTurn'),Concatenate("2Pは1Pにこうげき!1Pは",Text('2P_Attack_Ponit',"[$-ja-JP]####"),"のダメージ"),
    "2Pは1Pにダメージを与えられない!"))))))))

戦闘終了ボタン(Battle_End_Button)

image.png
1Pもしくは2PのHPが0以下になれば戦闘は終了になり表示されます。
なので、Visible及びOnSelectプロパティを設定します。

Battle_End_Button(Visible)
If('2P_Current_HP'<=0,true,If('1P_Current_HP'<=0,true,false
Battle_End_Button(OnSelect)
Navigate('Player_Param_Set',ScreenTransition.Cover)

これで、戦闘画面の作成は完了です!

まとめ

ゲーム作るの楽しいですwwwww
というか意外に戦闘システムっていうのを作るのが結構大変なんだというのが分かって
結構有意義になったこと。
そして、ゲーム作りを通して、PowerAppsの作成技術がさらに上がった!(ような気がする・・・)

そして伝説(カスタマイズ)へ・・・

1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1