Created
May 30, 2021 04:00
-
-
Save feo52/5d45238d0c02136c6343e7e64f39ff07 to your computer and use it in GitHub Desktop.
Hadoken Code HP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEngine.Profiling; | |
public class script : MonoBehaviour | |
{ | |
/// <summary>指の状態</summary> | |
private enum Finger | |
{ | |
Zero = 0, | |
/// <summary>押している</summary> | |
Hold, | |
/// <summary>押した</summary> | |
Pressed, | |
} | |
/// <summary>キーの指定</summary> | |
[Flags] | |
private enum Key | |
{ | |
Zero = 0, | |
/// <summary>十字キー左下方向</summary> | |
J1 = 0x00000001, | |
/// <summary>十字キー↓方向</summary> | |
J2 = 0x00000002, | |
/// <summary>十字キー右下方向</summary> | |
J3 = 0x00000004, | |
/// <summary>十字キー←方向</summary> | |
J4 = 0x00000010, | |
/// <summary>十字キー真ん中</summary> | |
J5 = 0x00000020, | |
/// <summary>十字キー→方向</summary> | |
J6 = 0x00000040, | |
/// <summary>十字キー左上方向</summary> | |
J7 = 0x00000100, | |
/// <summary>十字キー↑方向</summary> | |
J8 = 0x00000200, | |
/// <summary>十字キー右上方向</summary> | |
J9 = 0x00000400, | |
/// <summary>弱パンチ(ライトパンチ)</summary> | |
LP = 0x00010000, | |
/// <summary>中パンチ(ミドルパンチ)</summary> | |
MP = 0x00020000, | |
/// <summary>強パンチ(ハードパンチ)</summary> | |
HP = 0x00040000, | |
/// <summary>弱キック(ライトキック)</summary> | |
LK = 0x00100000, | |
/// <summary>中キック(ミドルキック)</summary> | |
MK = 0x00200000, | |
/// <summary>強キック(ハードキック)</summary> | |
HK = 0x00400000, | |
} | |
/// <summary>技のコマンド保持用</summary> | |
private class MoveCommand | |
{ | |
/// <summary>入力コマンドキー(enum Finger)</summary> | |
public Finger DoFinger; | |
/// <summary>入力コマンドキー(enum Key)</summary> | |
public Key InputKey; | |
/// <summary>次のコマンドキー受付猶予時間(最終コマンドは必ず0にすること)</summary> | |
public int NextTime; | |
/// <summary>次のコマンドキー同時押し可否(最終コマンドは必ず0にすること)0はThisFrame判定 1はNextFrame判定</summary> | |
public int SlipTime; | |
} | |
/// <summary>GC Alloc 対策用</summary> | |
private static Key StaticInputKey; | |
private static int StaticNextTime; | |
private static int StaticSlipTime; | |
private static int StaticFrameCount; | |
/// <summary>技のコマンドリスト(二次元リスト)</summary> | |
private List<List<MoveCommand>> MoveCommandList = new List<List<MoveCommand>>() | |
{ | |
new List<MoveCommand>() | |
{ | |
// 波動拳 状態は押している キーは左 次の入力は 6フレーム以内 次の入力同時押し不可NextFrame判定 | |
new MoveCommand { DoFinger = Finger.Hold, InputKey = Key.J2, NextTime = 6, SlipTime = 1 }, | |
// 波動拳 状態は押している キーは左下 次の入力は 6フレーム以内 次の入力同時押し不可NextFrame判定 | |
new MoveCommand { DoFinger = Finger.Hold, InputKey = Key.J3, NextTime = 6, SlipTime = 1 }, | |
// 波動拳 状態は押している キーは右 次の入力は 7フレーム以内 次の入力同時押し可能ThisFrame判定 | |
new MoveCommand { DoFinger = Finger.Hold, InputKey = Key.J6, NextTime = 7, SlipTime = 0 }, | |
// 波動拳 状態は押した キーはP 最後なので 0に必ずする 最後なので 0に必ずする | |
new MoveCommand { DoFinger = Finger.Pressed, InputKey = Key.HP, NextTime = 0, SlipTime = 0 }, | |
}, | |
}; | |
/// <summary> | |
/// InputGetKeyData追加処理。 | |
/// Update()を毎フレームにてキー情報の更新のために1回呼ぶ。 | |
/// </summary> | |
/// | |
/// Update()メソッド | |
/// 毎フレームにてキー情報の更新 | |
/// | |
/// 下記プロパティに各種状態を保持(読み取り専用) | |
/// 設定される数値は enum Key 参照 | |
/// Hold = Input.GetKey | |
/// Pressed = Input.GetKeyDown | |
/// | |
private class InputGetKeyDataForMoveCommand | |
{ | |
public Key Hold { get; private set; } = Key.Zero; | |
public Key Pressed { get; private set; } = Key.Zero; | |
public void Update() | |
{ | |
//十字キーの状態を取得 | |
float x = Input.GetAxisRaw("Horizontal"); | |
float y = Input.GetAxisRaw("Vertical"); | |
int joyStick = 5; | |
joyStick += (int)x; | |
joyStick += (int)y * 3; | |
//十字キーおよびパンチキックの"押している"状態を変数に設定 | |
Hold = Key.Zero; | |
if (joyStick == 1) Hold |= Key.J1; | |
if (joyStick == 2) Hold |= Key.J2; | |
if (joyStick == 3) Hold |= Key.J3; | |
if (joyStick == 4) Hold |= Key.J4; | |
if (joyStick == 5) Hold |= Key.J5; | |
if (joyStick == 6) Hold |= Key.J6; | |
if (joyStick == 7) Hold |= Key.J7; | |
if (joyStick == 8) Hold |= Key.J8; | |
if (joyStick == 9) Hold |= Key.J9; | |
if (Input.GetKey(KeyCode.I)) Hold |= Key.LP; | |
if (Input.GetKey(KeyCode.O)) Hold |= Key.MP; | |
if (Input.GetKey(KeyCode.P)) Hold |= Key.HP; | |
if (Input.GetKey(KeyCode.J)) Hold |= Key.LK; | |
if (Input.GetKey(KeyCode.K)) Hold |= Key.MK; | |
if (Input.GetKey(KeyCode.L)) Hold |= Key.HK; | |
//パンチキックの"押した"状態を変数に設定 | |
Pressed = Key.Zero; | |
if (Input.GetKeyDown(KeyCode.I)) Pressed |= Key.LP; | |
if (Input.GetKeyDown(KeyCode.O)) Pressed |= Key.MP; | |
if (Input.GetKeyDown(KeyCode.P)) Pressed |= Key.HP; | |
if (Input.GetKeyDown(KeyCode.J)) Pressed |= Key.LK; | |
if (Input.GetKeyDown(KeyCode.K)) Pressed |= Key.MK; | |
if (Input.GetKeyDown(KeyCode.L)) Pressed |= Key.HK; | |
} | |
} | |
/// <summary>InputGetKeyData追加処理用</summary> | |
private InputGetKeyDataForMoveCommand InputGetKeyData = new InputGetKeyDataForMoveCommand(); | |
/// <summary> | |
/// InputGetKeyDataの履歴保持用(極小版) | |
/// </summary> | |
/// 以下を保持。 | |
/// 何フレーム目の情報か | |
/// どのキーを押しているか | |
/// どのキーを押したか | |
private class InputGetKeyTinyHistory | |
{ | |
public int FrameCount; | |
public Key Hold; | |
public Key Pressed; | |
} | |
/// <summary>InputGetKeyDataの履歴保持最大フレーム数</summary> | |
private static readonly int InputGetKeyDataHistoryMax = 150; | |
/// <summary>InputGetKeyDataの履歴保持用(極小版)</summary> | |
private List<InputGetKeyTinyHistory> InputGetKeyTinyHistoryList = new List<InputGetKeyTinyHistory>(InputGetKeyDataHistoryMax); | |
private InputGetKeyTinyHistory[] InputGetKeyTinyHistoryData = new InputGetKeyTinyHistory[InputGetKeyDataHistoryMax]; | |
private InputGetKeyTinyHistory InputGetKeyTinyHistoryDataRow = null; | |
/// <summary>処理時間計測用のストップウォッチ</summary> | |
private System.Diagnostics.Stopwatch DebugStopwatch1 = new System.Diagnostics.Stopwatch(); | |
private System.Diagnostics.Stopwatch DebugStopwatch2 = new System.Diagnostics.Stopwatch(); | |
private System.Diagnostics.Stopwatch DebugStopwatch3 = new System.Diagnostics.Stopwatch(); | |
void Start() | |
{ | |
// 技のコマンドリストの順序を反転 | |
// 波動拳は下⇒右下⇒右⇒Pだが、 | |
// 処理順はP⇒右⇒右下⇒下の順序で判定を行なうため反転。 | |
foreach (List<MoveCommand> MoveCommandData in MoveCommandList) MoveCommandData.Reverse(); | |
// InputGetKeyDataの履歴保持用のインスタンス作成 | |
for (int i = 0; i < InputGetKeyDataHistoryMax; ++i) | |
{ | |
InputGetKeyTinyHistoryData[i] = new InputGetKeyTinyHistory(); | |
} | |
// フレームレートの設定 | |
Application.targetFrameRate = 60; | |
} | |
void Update() | |
{ | |
// GC Alloc 等確認用プロファイラースタート | |
Profiler.BeginSample("check_GC_Alloc"); | |
// 処理時間計測用のストップウォッチスタート | |
DebugStopwatch1.Restart(); | |
DebugStopwatch1.Start(); | |
// InputGetKeyData追加処理更新 | |
InputGetKeyData.Update(); | |
// InputGetKeyDataの履歴保持用に今回のフレームのキー情報を取得 | |
int i = Time.frameCount % InputGetKeyDataHistoryMax; | |
InputGetKeyTinyHistoryData[i].FrameCount = Time.frameCount; | |
InputGetKeyTinyHistoryData[i].Hold = InputGetKeyData.Hold; | |
InputGetKeyTinyHistoryData[i].Pressed = InputGetKeyData.Pressed; | |
// InputGetKeyDataの履歴保持用Listが最大数以上の場合には先頭から順次削除 | |
while (InputGetKeyTinyHistoryList.Count >= InputGetKeyDataHistoryMax) InputGetKeyTinyHistoryList.RemoveAt(0); | |
// InputGetKeyDataの履歴保持用Listの末尾に今回のフレームのキー情報を追加 | |
InputGetKeyTinyHistoryList.Add(InputGetKeyTinyHistoryData[i]); | |
// 技のコマンドリストを順次判定処理 | |
// 本コードは波動拳だけなので1回転のみ | |
foreach (List<MoveCommand> MoveCommandData in MoveCommandList) | |
{ | |
bool allow = false; | |
int index = 0; | |
StaticFrameCount = Time.frameCount; | |
// 処理時間計測用のストップウォッチスタート | |
DebugStopwatch2.Restart(); | |
DebugStopwatch2.Start(); | |
// 技のコマンドのひとつひとつを順次判定処理 | |
// 波動拳は下⇒右下⇒右⇒Pなので4回転 | |
// foreach1回目はP の判定 | |
// foreach2回目は右 の判定 | |
// foreach3回目は右下の判定 | |
// foreach4回目は下 の判定 | |
foreach (MoveCommand record in MoveCommandData) | |
{ | |
// GC Alloc 対策 | |
StaticInputKey = record.InputKey; | |
StaticNextTime = record.NextTime; | |
StaticSlipTime = record.SlipTime; | |
// 処理時間計測用のストップウォッチスタート | |
DebugStopwatch3.Restart(); | |
DebugStopwatch3.Start(); | |
// 技のコマンドのひとつひとつを順次判定処理 | |
// 波動拳は下⇒右下⇒右⇒Pなので4回判定 | |
// foreach1回目はP の判定 | |
// foreach2回目は右 の判定 | |
// foreach3回目は右下の判定 | |
// foreach4回目は下 の判定 | |
InputGetKeyTinyHistoryDataRow = record.DoFinger switch | |
{ | |
Finger.Hold => InputGetKeyTinyHistoryList.FindLast(row => ((StaticFrameCount - StaticNextTime) <= row.FrameCount) && (row.FrameCount <= (StaticFrameCount - StaticSlipTime)) && ((row.Hold & StaticInputKey) == StaticInputKey)), | |
Finger.Pressed => InputGetKeyTinyHistoryList.FindLast(row => ((StaticFrameCount - StaticNextTime) <= row.FrameCount) && (row.FrameCount <= (StaticFrameCount - StaticSlipTime)) && ((row.Pressed & StaticInputKey) == StaticInputKey)), | |
_ => null | |
}; | |
// 抽出データが存在する場合 | |
if (InputGetKeyTinyHistoryDataRow != null) | |
{ | |
//次の判定用に判定用のStaticFrameCountを更新。allowを1にする。 | |
StaticFrameCount = InputGetKeyTinyHistoryDataRow.FrameCount; | |
allow = true; | |
} | |
// 抽出データが存在しない場合は波動拳コマンド入力受付否認。 | |
else | |
{ | |
allow = false; | |
break; | |
} | |
index++; | |
// 処理時間計測用のストップウォッチストップ | |
if (DebugStopwatch3.IsRunning) DebugStopwatch3.Stop(); | |
} | |
// 処理時間計測用のストップウォッチストップ | |
if (DebugStopwatch2.IsRunning) DebugStopwatch2.Stop(); | |
// コマンド入力受付承認? | |
if (allow) | |
{ | |
// Consoleデバック表示 | |
Debug.Log($"{Time.frameCount}fr [判定所要時間]{DebugStopwatch2.ElapsedTicks,6:D}ticks, [受付承認技名]波動拳"); | |
} | |
else if (index > 0) | |
{ | |
// Consoleデバック表示 | |
Debug.Log($"{Time.frameCount}fr [判定所要時間]{DebugStopwatch2.ElapsedTicks,6:D}ticks, [受付否認技名]波動拳"); | |
} | |
} | |
// 処理時間計測用のストップウォッチストップ | |
if (DebugStopwatch1.IsRunning) DebugStopwatch1.Stop(); | |
// GC Alloc 等確認用プロファイラーストップ | |
Profiler.EndSample(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment