ゲームプログラマーの寄り道

ゲームプログラマの寄り道

ソースコード公開系ブログ

ソースコード公開系ブログ

ドンキの例のWiFiカメラ(スマモッチャー)を遊んでみた

スマモッチャー とは

f:id:shin--go:20200224205720j:plain

簡単に表すと  

非公式modが公開

  • modにより以下が拡張される
    • クラウドサービス(中華)への通信なし
    • RTSP / onvifサーバー
    • SSHサーバー
    • Telnetサーバー
    • busyboxのアップデート
    • うなり音が減少
    • WebUIアクセス
    • FTPサーバー github.com

IPアドレスを調べる

$ arp -a

コマンドプロンプトから同一LANに繋いでいるIPアドレスが見れるので、どれかがカメラになります。
同じMACアドレスを見たら分かるかも

ストリーミング再生

f:id:shin--go:20200224152941p:plain

RTSP認証を求められた場合

  • 比較的新しい個体は認証が求められる
    • ユーザー名:admin
    • パスワード:なし
      f:id:shin--go:20200224153232p:plain

顔認識してみる

  • スマモッチャーからRTSPで取得した映像から顔認識する
  • PythonOpenCVでお手軽に出来るはず

OpenCVをインストール

$ pip install opencv-python

ソースコード

import sys
import cv2 # OpenCV のインポート

cap = cv2.VideoCapture("rtsp://admin:@192.168.x.xx:554/") # 配信のURLを指定

if cap.isOpened() is False:
    print("can not open camera")
    sys.exit()

# 評価器を読み込み
# https://github.com/opencv/opencv/tree/master/data/haarcascades
cascade = cv2.CascadeClassifier('path') #haarcascade_frontalface_alt2.xmlのパス
eye_cascade = cv2.CascadeClassifier('path') #haarcascade_eye_tree_eyeglasses.xmlのパス

def mosaic(src, ratio=0.1):
    small = cv2.resize(src, None, fx=ratio, fy=ratio, interpolation=cv2.INTER_NEAREST)
    return cv2.resize(small, src.shape[:2][::-1], interpolation=cv2.INTER_NEAREST)

def mosaic_area(src, x, y, width, height, ratio=0.1):
    dst = src.copy()
    dst[y:y + height, x:x + width] = mosaic(dst[y:y + height, x:x + width], ratio)
    return dst

while True:
    # VideoCaptureから1フレーム読み込む
    ret, frame = cap.read()

    # そのままの大きさだと処理速度がきついのでリサイズ
    frame = cv2.resize(frame, (int(frame.shape[1]*0.5), int(frame.shape[0]*0.5)))

    # 処理速度を高めるために画像をグレースケールに変換したものを用意
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    
    
    # 顔検出
    facerect = cascade.detectMultiScale(
       gray,
       scaleFactor=1.11,
       minNeighbors=3,
       minSize=(100, 100)
    )

    if len(facerect) != 0:
        for x, y, w, h in facerect:
            # 顔の部分(この顔の部分に対して目の検出をかける)
            face_gray = gray[y: y + h, x: x + w]
  
            # くり抜いた顔の部分を表示(処理には必要ない。ただ見たいだけ。)
            show_face_gray = cv2.resize(face_gray, (int(gray.shape[1]), int(gray.shape[0])))
            cv2.imshow('face', show_face_gray)
  
            # 顔の部分から目の検出
            eyes = eye_cascade.detectMultiScale(
                face_gray,
                scaleFactor=1.11, # ここの値はPCのスペックに依存するので適宜修正してください
                minNeighbors=3,
                minSize=(15, 15)
            )
  
            if len(eyes) == 0:
                # 目が閉じられたとみなす
                cv2.putText(
                    frame,
                    'close your eyes',
                    (x, y - 10), # 位置を少し調整
                    cv2.FONT_HERSHEY_PLAIN,
                    2,
                    (0, 255,0),
                    2,
                    cv2.LINE_AA
                )
            else:
                for (ex, ey, ew, eh) in eyes:
                    # 目の部分にモザイク処理
                    frame = mosaic_area(
                        frame,
                        int((x + ex) - ew / 2),
                        int(y + ey),
                        int(ew * 2.5),
                        eh
                    )
  
            # 顔検出した部分に枠を描画
            cv2.rectangle(
                frame,
                (x, y),
                (x + w, y + h),
                (255, 255, 255),
                thickness=2
            )
  
    cv2.imshow('frame', frame)

    # キー入力を1ms待って、k が27(ESC)だったらBreakする
    k = cv2.waitKey(1)
    if k == 27:
        break

# キャプチャをリリースして、ウィンドウをすべて閉じる
cap.release()
cv2.destroyAllWindows()

感想

  • セキュリティさえ気お付ければ、遊べるIPカメラ
  • ネットワークカメラモジュールがドン・キホーテで直ぐに手に入る事を考えればお値打ち
  • OpenCVと組み合わせれば、テレビを見なくなったら消すなど出来そう

用語

肥大化したクソコード

先にコードだけ置いとく、

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.UI;  ////ここを追加////

public class CarInput : MonoBehaviour
{
    Xbox360_JoyPad pad;
    // Use this for initialization
    uint padIndex = 0;
    /*定数----------------------------------*/
    const int PLAY = 20;//遊びの範囲(度数)要調整
    const float RANGE = (PLAY * 0.5f) / 180.0f;//遊びの範囲
    readonly Vector2 SPEED = new Vector2(0.1f, 0.05f);
    const int TOP = 6;
    const int LEFT = 5;
    const int RIGHT = 4;
    const int UP = 12;
    const int DOWN = 13;
    /*クラス内変数---------------------------*/
    bool isShiftLever = false;//シフトレバーが入っているか
    bool isShiftPaddle = false;//パドル押されているか
    bool preIsShiftLever = false;//前フレーム情報
    bool preIsShiftPaddle = false;//前フレーム情報

    int shiftLever = 1;
    int preShiftNumber = 1;
    int inputDire = 0;
    bool logicoolG29 = false;//G29かどうか
    float keyBrake = 0.0f;
    float keyAccel = 0.0f;
    float keySteer = 0.0f;
    float handleSteer = 0.0f;
    Func<uint, float> FuncsPedal = (value) => { return 1.0f - ((float)value / (float)ushort.MaxValue); };//ペダル用正規化の関数
    Func<uint, int, float> FuncsPedalButton = (PadButtons, value) => { return (PadButtons & value) != 0 ? 1.0f : 0.0f; };//ボタンからペダル用正規化の関数
    Func<uint, float> FuncsSteer = (value) =>
    {
        float steer = ((float)value * 2.0f - (float)ushort.MaxValue) / (float)ushort.MaxValue;
        if (RANGE > Mathf.Abs(steer))//ハンドル値
        {
            return 0.0f;
        }
        return steer;
    };//ステア用正規化の関数
    Func<uint, int, int, bool> FuncsPushJudge = (PadButtons, buttonX, buttonY) => { return (((PadButtons & buttonX) != 0) || ((PadButtons & buttonY) != 0)) ? true : false; };//入力判定の関数
    Func<uint, int, int, int, int> FuncsShift = (padButtons, shiftNumber, buttonX, buttonY) =>
    {
        if (((padButtons & buttonX) != 0) && (shiftNumber < TOP))
        {
            return 1;
        }
        else if (((padButtons & buttonY) != 0) && (0 < shiftNumber))
        {
            return -1;
        }
        return 0;
    };//入力判定の関数
      /*--------------------------------------*/

    /*プロパティ-----------------------------*/
    public float Accel { private set; get; }
    public float Brake { private set; get; }
    public float Steer { private set; get; }
    public float Clutch { private set; get; }
    public int ShiftNumber { private set; get; } = 1;
    public int ShiftChange { private set; get; }
    public bool Klaxon { private set; get; }
    public bool StartDown { private set; get; }
    public static CarInput instance;
    //Text text;
    struct Control
    {
        public const string DrivingForceGT = "GT";
        public const string G25 = "G25";
        public const string G29 = "G29";
        public const string F310 = "F310";
        public const string Dual = "Dual";
        public const string SteeringWheel = "SteeringWheel";
        public const string GamePad = "GamePad";
    }

    Dictionary<string, int> device = new Dictionary<string, int>()
    {
        { Control.DrivingForceGT,-1},
        { Control.G25,-1},
        {Control.G29,-1},
        {Control.F310,-1},
        { Control.Dual,-1},
        {Control.SteeringWheel,-1},
        { Control.GamePad,-1}
    };
    public enum PadCode
    {
        A,
        B,
        X,
        Y,
        Start,
        Back,
        LeftDirectional,
        RightDirectional,
        UpDirectional,
        DownDirectional,
        LeftStick,
        RightStick,
        RightBumper,
        LeftBumper
    };
    public enum SteeringCode
    {
        Circle,
        Triangle,
        Square,
        Cross,
        Start,
        Select,
        LeftDirectional,
        RightDirectional,
        LeftPaddle,
        RightPaddle,
        UpDirectional,
        DownDirectional,
        Left3,
        Right3,
        Right2,
        Left2,
        Ps,
        Plus,
        Minus,
        Klaxon,
        Return,
        RightTurn,
        LeftTurn
    };


    public class GamePadStatus
    {
        public bool A = false;
        public bool B = false;
        public bool X = false;
        public bool Y = false;
        public bool Start = false;
        public bool Back = false;
        public bool LeftDirectional = false;
        public bool RightDirectional = false;
        public bool UpDirectional = false;
        public bool DownDirectional = false;
        public bool LeftStick = false;
        public bool RightStick = false;
        public bool RightBumper = false;
        public bool LeftBumper = false;

        public Vector2 LeftStickAxis = Vector2.zero;
        public Vector2 RightStickAxis = Vector2.zero;

        public float LeftTrigger = 0;
        public float RightTrigger = 0;

    }
    GamePadStatus preGamePadState = new GamePadStatus();
    GamePadStatus gamePadState = new GamePadStatus();
    public GamePadStatus GamePadState { private set { gamePadState = value; } get { return gamePadState; } }
    public class GameSteeringStatus
    {
        public bool Circle = false;
        public bool Triangle = false;
        public bool Square = false;
        public bool Cross = false;
        public bool Start = false;
        public bool Select = false;
        public bool LeftDirectional = false;
        public bool RightDirectional = false;
        public bool LeftPaddle = false;
        public bool RightPaddle = false;
        public bool UpDirectional = false;
        public bool DownDirectional = false;
        public bool Left3 = false;
        public bool Right3 = false;
        public bool Right2 = false;
        public bool Left2 = false;
        public bool Ps = false;
        public bool Plus = false;
        public bool Minus = false;
        public bool Klaxon = false;
        public bool Return = false;
        public bool RightTurn = false;
        public bool LeftTurn = false;

        public float LeftPedal = 0;
        public float RightPedal = 0;
        public float Steering = 0;

    }
    GameSteeringStatus preGameSteeringState = new GameSteeringStatus();
    GameSteeringStatus gameSteeringState = new GameSteeringStatus();
    public GameSteeringStatus GameSteeringState { private set { gameSteeringState = value; } get { return gameSteeringState; } }
    public bool GetSteeringDown(SteeringCode num)
    {
        switch (num)
        {
            case SteeringCode.Circle:
                return GameSteeringState.Circle && !preGameSteeringState.Circle ? true : false;
            case SteeringCode.Cross:
                return GameSteeringState.Cross && !preGameSteeringState.Cross ? true : false;
            case SteeringCode.DownDirectional:
                return GameSteeringState.DownDirectional && !preGameSteeringState.DownDirectional ? true : false;
            case SteeringCode.Klaxon:
                return GameSteeringState.Klaxon && !preGameSteeringState.Klaxon ? true : false;
            case SteeringCode.Left2:
                return GameSteeringState.Left2 && !preGameSteeringState.Left2 ? true : false;
            case SteeringCode.Left3:
                return GameSteeringState.Left3 && !preGameSteeringState.Left3 ? true : false;
            case SteeringCode.LeftDirectional:
                return GameSteeringState.LeftDirectional && !preGameSteeringState.LeftDirectional ? true : false;
            case SteeringCode.LeftPaddle:
                return GameSteeringState.LeftPaddle && !preGameSteeringState.LeftPaddle ? true : false;
            case SteeringCode.LeftTurn:
                return GameSteeringState.LeftTurn && !preGameSteeringState.LeftTurn ? true : false;
            case SteeringCode.Minus:
                return GameSteeringState.Minus && !preGameSteeringState.Minus ? true : false;
            case SteeringCode.Plus:
                return GameSteeringState.Plus && !preGameSteeringState.Plus ? true : false;
            case SteeringCode.Ps:
                return GameSteeringState.Ps && !preGameSteeringState.Ps ? true : false;
            case SteeringCode.Return:
                return GameSteeringState.Return && !preGameSteeringState.Return ? true : false;
            case SteeringCode.Right2:
                return GameSteeringState.Right2 && !preGameSteeringState.Right2 ? true : false;
            case SteeringCode.Right3:
                return GameSteeringState.Right3 && !preGameSteeringState.Right3 ? true : false;
            case SteeringCode.RightDirectional:
                return GameSteeringState.RightDirectional && !preGameSteeringState.RightDirectional ? true : false;
            case SteeringCode.RightPaddle:
                return GameSteeringState.RightPaddle && !preGameSteeringState.RightPaddle ? true : false;
            case SteeringCode.RightTurn:
                return GameSteeringState.RightTurn && !preGameSteeringState.RightTurn ? true : false;
            case SteeringCode.Select:
                return GameSteeringState.Select && !preGameSteeringState.Select ? true : false;
            case SteeringCode.Square:
                return GameSteeringState.Square && !preGameSteeringState.Square ? true : false;
            case SteeringCode.Start:
                return GameSteeringState.Start && !preGameSteeringState.Start ? true : false;
            case SteeringCode.Triangle:
                return GameSteeringState.Triangle && !preGameSteeringState.Triangle ? true : false;
            case SteeringCode.UpDirectional:
                return GameSteeringState.UpDirectional && !preGameSteeringState.UpDirectional ? true : false;
        }
        return false;

    }
    public bool GetPadDown(PadCode num)
    {
        switch (num)
        {
            case PadCode.A:
                return GamePadState.A && !preGamePadState.A ? true : false;
            case PadCode.B:
                return GamePadState.B && !preGamePadState.B ? true : false;
            case PadCode.Back:
                return GamePadState.Back && !preGamePadState.Back ? true : false;
            case PadCode.DownDirectional:
                return GamePadState.DownDirectional && !preGamePadState.DownDirectional ? true : false;
            case PadCode.LeftBumper:
                return GamePadState.LeftBumper && !preGamePadState.LeftBumper ? true : false;
            case PadCode.LeftDirectional:
                return GamePadState.LeftDirectional && !preGamePadState.LeftDirectional ? true : false;
            case PadCode.LeftStick:
                return GamePadState.LeftStick && !preGamePadState.LeftStick ? true : false;
            case PadCode.RightBumper:
                return GamePadState.RightBumper && !preGamePadState.RightBumper ? true : false;
            case PadCode.RightDirectional:
                return GamePadState.RightDirectional && !preGamePadState.RightDirectional ? true : false;
            case PadCode.RightStick:
                return GamePadState.RightStick && !preGamePadState.RightStick ? true : false;
            case PadCode.Start:
                return GamePadState.Start && !preGamePadState.Start ? true : false;
            case PadCode.UpDirectional:
                return GamePadState.UpDirectional && !preGamePadState.UpDirectional ? true : false;
            case PadCode.X:
                return GamePadState.X && !preGamePadState.X ? true : false;
            case PadCode.Y:
                return GamePadState.Y && !preGamePadState.Y ? true : false;
        }
        return false;
    }

    private void Awake()
    {

        //text = GetComponent<Text>();
        if (instance == null)
        {
            instance = this;
           
            StartCoroutine(PreInPut());
        }
        else
        {
            Destroy(this);
        }

    }

    private void Update()
    {
        Debug.Log(GetSteeringDown(SteeringCode.Select));
        List<string> names = new List<string>(Input.GetJoystickNames());
        for (int i = 0; i < names.Count; ++i)
        {
            DebugLogger.Log(i + ":" + names[i]);
            if (names[i].Contains(Control.G25))
            {
                device[Control.G25] = i;
                device[Control.SteeringWheel] = i;
            }
            else if (names[i].Contains(Control.G29))
            {
                device[Control.G29] = i;
                device[Control.SteeringWheel] = i;
            }
            else if (names[i].Contains(Control.DrivingForceGT))
            {
                device[Control.DrivingForceGT] = i;
                device[Control.SteeringWheel] = i;
            }
            else if (names[i].Contains(Control.Dual))
            {
                device[Control.Dual] = i;
                device[Control.GamePad] = i;
            }
            else if (names[i].Contains(Control.F310))
            {
                device[Control.F310] = i;
                device[Control.GamePad] = i;
            }
        }
        
      
        pad = new Xbox360_JoyPad();
        uint[] pads = pad.GetJoypads();
        foreach (uint p in pads)
        {
            DebugLogger.Log("ジョイパッド:" + p);

            padIndex = p;
        }

        JoyPad.JOYERR err = pad.GetPosEx(padIndex);
        JoyPad.JOYINFOEX ex = pad.JoyInfoEx;
        if (err != JoyPad.JOYERR.NOERROR)
        {
            DebugLogger.Log("キーボード ^^");
            ShiftNumber += KeyShift();
            KeyAccel();
            Accel = keyAccel;

            KeyBrake();
            Brake = keyBrake;

            KeySteer();
            Steer = keySteer;
        }
        else if (device[Control.SteeringWheel] >= 0)
        {
            gameSteeringState = new GameSteeringStatus();
            DebugLogger.Log("コントローラ");
            if (device[Control.G29] >= 0)
            {
                logicoolG29 = false;
            }
            else
            {
                logicoolG29 = true;
            }
            DrivingForceGT(ref gameSteeringState);
            Inputs();
            //text.text = "";
            //text.text += "dwButtonNumber:" + pad.dwButtonNumber.ToString() + '\n';
            //text.text += "dwButtons:" + pad.dwButtons.ToString() + '\n';
            //text.text += "dwFlags:" + pad.dwFlags.ToString() + '\n';
            //text.text += "dwPOV:" + pad.dwPOV.ToString() + '\n';
            //text.text += "dwReserved1:" + pad.dwReserved1.ToString() + '\n';
            //text.text += "dwReserved2:" + pad.dwReserved2.ToString() + '\n';
            //text.text += "dwRpos:" + pad.dwRpos.ToString() + '\n';
            //text.text += "dwSize:" + pad.dwSize.ToString() + '\n';
            //text.text += "dwUpos:" + pad.dwUpos.ToString() + '\n';
            //text.text += "dwVpos:" + pad.dwVpos.ToString() + '\n';
            //text.text += "dwXpos:" + pad.dwXpos.ToString() + '\n';
            //text.text += "dwYpos:" + pad.dwYpos.ToString() + '\n';
            //text.text += "dwZpos:" + pad.dwZpos.ToString() + '\n';
            //ShiftNumber += KeyShift();

            //if (KeyAccel() >= pad.Trigger)
            //{
            //	Accel = keyAccel;
            //}

            //if (KeyBrake() >= pad.RightStickY)
            //{
            //	Brake = keyBrake;
            //}

            //if ((KeySteer() >= 0) == (handleSteer >= 0))
            //{
            //	if (Mathf.Abs(keySteer) >= Mathf.Abs(handleSteer))
            //	{
            //		Steer = keySteer;
            //	}
            //}
            //else
            //{
            //	Steer = keySteer + handleSteer;
            //}
        }
        else if (device[Control.GamePad] >= 0)
        {
            gamePadState = new GamePadStatus();
            if (device[Control.Dual] >= 0)
            {
                DirectInput(ref gamePadState);

            }
            else
            {
                XInput(ref gamePadState);
            }
            Accel = gamePadState.RightTrigger;
            Brake = gamePadState.LeftTrigger;
            Steer = FuncsSteer(pad.dwXpos);
            isShiftPaddle = FuncsPushJudge(pad.dwButtons, 32, 16);
            if (!preIsShiftPaddle && isShiftPaddle) //パドルシフト
            {
                ShiftNumber += FuncsShift(pad.dwButtons, ShiftNumber, 32, 16);
            }

            //text.text = "";
            //	text.text+= "Accel:" + Accel.ToString() + '\n';
            //	text.text += "Brake:" + Brake.ToString() + '\n';
            //	text.text += "Steer:" + Steer.ToString() + '\n';
            //	text.text += "ShiftNumber:" + ShiftNumber.ToString() + '\n';
            //text.text += "A:" + gamepadState.A.ToString() + '\n';
            //text.text += "B:" + gamepadState.B.ToString() + '\n';
            //text.text += "X:" + gamepadState.X.ToString() + '\n';
            //text.text += "Y:" + gamepadState.Y.ToString() + '\n';
            //text.text += "Start:" + gamepadState.Start.ToString() + '\n';
            //text.text += "Back:" + gamepadState.Back.ToString() + '\n';
            //text.text += "RightBumper:" + gamepadState.RightBumper.ToString() + '\n';
            //text.text += "LeftBumper:" + gamepadState.LeftBumper.ToString() + '\n';
            //text.text += "LeftTrigger:" + gamepadState.LeftTrigger.ToString() + '\n';
            //text.text += "RightTrigger:" + gamepadState.RightTrigger.ToString() + '\n';
            //text.text += "LeftStick:" + gamepadState.LeftStick.ToString() + '\n';
            //text.text += "RightStick:" + gamepadState.RightStick.ToString() + '\n';
            //text.text += "UpDirectional:" + gamepadState.UpDirectional.ToString() + '\n';
            //text.text += "RightDirectional:" + gamepadState.RightDirectional.ToString() + '\n';
            //text.text += "DownDirectional:" + gamepadState.DownDirectional.ToString() + '\n';
            //text.text += "LeftDirectional:" + gamepadState.LeftDirectional.ToString() + '\n';
            //text.text += "RightStickAxis:" + gamepadState.RightStickAxis.ToString() + '\n';
            //text.text += "LeftStickAxis:" + gamepadState.LeftStickAxis.ToString() + '\n';

            //text.text = "";
            //text.text += "dwButtonNumber:" + pad.dwButtonNumber.ToString() + '\n';
            //text.text += "dwButtons:" + pad.dwButtons.ToString() + '\n';
            //text.text += "dwFlags:" + pad.dwFlags.ToString() + '\n';
            //text.text += "dwPOV:" + pad.dwPOV.ToString() + '\n';
            //text.text += "dwReserved1:" + pad.dwReserved1.ToString() + '\n';
            //text.text += "dwReserved2:" + pad.dwReserved2.ToString() + '\n';
            //text.text += "dwRpos:" + pad.dwRpos.ToString() + '\n';
            //text.text += "dwSize:" + pad.dwSize.ToString() + '\n';
            //text.text += "dwUpos:" + pad.dwUpos.ToString() + '\n';
            //text.text += "dwVpos:" + pad.dwVpos.ToString() + '\n';
            //text.text += "dwXpos:" + pad.dwXpos.ToString() + '\n';
            //text.text += "dwYpos:" + pad.dwYpos.ToString() + '\n';
            //text.text += "dwZpos:" + pad.dwZpos.ToString() + '\n';
        }

        preIsShiftLever = isShiftLever;//前回更新
        preIsShiftPaddle = isShiftPaddle;

        ShiftChange = (preShiftNumber != ShiftNumber) ? Math.Sign(ShiftNumber - preShiftNumber) : 0;
        preShiftNumber = ShiftNumber;

    }

    //private void OnGUI()
    //{
    //	GUIStyle style = new GUIStyle
    //	{
    //		fontSize = 50
    //	};
    //	style.normal.textColor = Color.red;

    //	GUILayout.Label(text.text.ToString(), style);
    //}
    IEnumerator PreInPut()
    {
        while (true)
        {
            yield return null;
            preGamePadState = GamePadState;
            preGameSteeringState = GameSteeringState;
        }
    }
   
    void DrivingForceGT(ref GameSteeringStatus gameSteeringStatus)
    {
        gameSteeringStatus.Circle = (pad.dwButtons & 4) != 0 ? true : false;
        gameSteeringStatus.Cross = (pad.dwButtons & 1) != 0 ? true : false;
        gameSteeringStatus.Triangle = (pad.dwButtons & 8) != 0 ? true : false;
        gameSteeringStatus.Square = (pad.dwButtons & 2) != 0 ? true : false;
        switch (pad.dwPOV)
        {
            case 0:
                gameSteeringStatus.UpDirectional = true;
                break;
            case 4500:
                gameSteeringStatus.UpDirectional = true;
                gameSteeringStatus.RightDirectional = true;
                break;
            case 9000:
                gameSteeringStatus.RightDirectional = true;
                break;
            case 13500:
                gameSteeringStatus.RightDirectional = true;
                gameSteeringStatus.DownDirectional = true;
                break;
            case 18000:
                gameSteeringStatus.DownDirectional = true;
                break;
            case 22500:
                gameSteeringStatus.DownDirectional = true;
                gameSteeringStatus.LeftDirectional = true;
                break;
            case 27000:
                gameSteeringStatus.LeftDirectional = true;
                break;
            case 31500:
                gameSteeringStatus.LeftDirectional = true;
                gameSteeringStatus.UpDirectional = true;
                break;
        }
        gameSteeringStatus.Left3 = (pad.dwButtons & 2048) != 0 ? true : false;
        gameSteeringStatus.Right3 = (pad.dwButtons & 1024) != 0 ? true : false;
        gameSteeringStatus.Left2 = (pad.dwButtons & 128) != 0 ? true : false;
        gameSteeringStatus.Right2 = (pad.dwButtons & 64) != 0 ? true : false;
        gameSteeringStatus.LeftPaddle = (pad.dwButtons & 32) != 0 ? true : false;
        gameSteeringStatus.RightPaddle = (pad.dwButtons & 16) != 0 ? true : false;
        gameSteeringStatus.Minus = (pad.dwButtons & 262144) != 0 ? true : false;
        gameSteeringStatus.Plus = (pad.dwButtons & 32768) != 0 ? true : false;
        gameSteeringStatus.Ps = (pad.dwButtons & 1048576) != 0 ? true : false;
        gameSteeringStatus.Klaxon = (pad.dwButtons & 524288) != 0 ? true : false;
        gameSteeringStatus.Start = (pad.dwButtons & 512) != 0 ? true : false;
        gameSteeringStatus.Select = (pad.dwButtons & 256) != 0 ? true : false;
        gameSteeringStatus.Return = (pad.dwButtons & 16384) != 0 ? true : false;
        gameSteeringStatus.RightTurn = (pad.dwButtons & 65536) != 0 ? true : false;
        gameSteeringStatus.LeftTurn = (pad.dwButtons & 131072) != 0 ? true : false;
    }
    void XInput(ref GamePadStatus gamepadState)
    {
        //Steer = FuncsSteer(pad.dwXpos);
        //Accel = FuncsPedalButton(pad.dwButtons, 128);
        //Brake = FuncsPedalButton(pad.dwButtons, 64);
        //isShiftPaddle = FuncsPushJudge(pad.dwButtons, 32, 16);
        //if (!preIsShiftPaddle && isShiftPaddle) //パドルシフト
        //{
        //	ShiftNumber += FuncsShift(pad.dwButtons, ShiftNumber, 32, 16);
        //}
        gamepadState.A = (pad.dwButtons & 1) != 0 ? true : false;
        gamepadState.B = (pad.dwButtons & 2) != 0 ? true : false;
        gamepadState.X = (pad.dwButtons & 4) != 0 ? true : false;
        gamepadState.Y = (pad.dwButtons & 8) != 0 ? true : false;
        if (pad.dwZpos < 32767)
        {
            gamepadState.RightTrigger = 1.0f - (((float)pad.dwZpos - 128.0f) / (32767.0f - 128.0f));
        }
        else if (32767 < pad.dwZpos)
        {
            gamepadState.LeftTrigger = (((float)pad.dwZpos - 32767.0f) / (65408.0f - 32767.0f));
        }
        gamepadState.LeftBumper = (pad.dwButtons & 16) != 0 ? true : false;
        gamepadState.RightBumper = (pad.dwButtons & 32) != 0 ? true : false;
        gamepadState.Back = (pad.dwButtons & 64) != 0 ? true : false;
        gamepadState.Start = (pad.dwButtons & 128) != 0 ? true : false;
        gamepadState.LeftStick = (pad.dwButtons & 256) != 0 ? true : false;
        gamepadState.RightStick = (pad.dwButtons & 512) != 0 ? true : false;
        switch (pad.dwPOV)
        {
            case 0:
                gamepadState.UpDirectional = true;
                break;
            case 4500:
                gamepadState.UpDirectional = true;
                gamepadState.RightDirectional = true;
                break;
            case 9000:
                gamepadState.RightDirectional = true;
                break;
            case 13500:
                gamepadState.RightDirectional = true;
                gamepadState.DownDirectional = true;
                break;
            case 18000:
                gamepadState.DownDirectional = true;
                break;
            case 22500:
                gamepadState.DownDirectional = true;
                gamepadState.LeftDirectional = true;
                break;
            case 27000:
                gamepadState.LeftDirectional = true;
                break;
            case 31500:
                gamepadState.LeftDirectional = true;
                gamepadState.UpDirectional = true;
                break;
        }
        gamepadState.LeftStickAxis.y = 1.0f - ((float)pad.dwYpos / (float)ushort.MaxValue);
        gamepadState.LeftStickAxis.x = (float)pad.dwXpos / (float)ushort.MaxValue;
        gamepadState.RightStickAxis.y = 1.0f - ((float)pad.dwRpos / (float)ushort.MaxValue);
        gamepadState.RightStickAxis.x = (float)pad.dwUpos / (float)ushort.MaxValue;

    }
    void DirectInput(ref GamePadStatus gamepadState)
    {
        //Steer = FuncsSteer(pad.dwXpos);
        //Accel = FuncsPedalButton(pad.dwButtons, 128);
        //Brake = FuncsPedalButton(pad.dwButtons, 64);
        //isShiftPaddle = FuncsPushJudge(pad.dwButtons, 32, 16);
        //if (!preIsShiftPaddle && isShiftPaddle) //パドルシフト
        //{
        //	ShiftNumber += FuncsShift(pad.dwButtons, ShiftNumber, 32, 16);
        //}
        gamepadState.A = (pad.dwButtons & 2) != 0 ? true : false;
        gamepadState.B = (pad.dwButtons & 4) != 0 ? true : false;
        gamepadState.X = (pad.dwButtons & 1) != 0 ? true : false;
        gamepadState.Y = (pad.dwButtons & 8) != 0 ? true : false;
        gamepadState.LeftBumper = (pad.dwButtons & 16) != 0 ? true : false;
        gamepadState.RightBumper = (pad.dwButtons & 32) != 0 ? true : false;
        gamepadState.LeftTrigger = (pad.dwButtons & 64) != 0 ? 1.0f : 0.0f;
        gamepadState.RightTrigger = (pad.dwButtons & 128) != 0 ? 1.0f : 0.0f;
        gamepadState.Back = (pad.dwButtons & 256) != 0 ? true : false;
        gamepadState.Start = (pad.dwButtons & 512) != 0 ? true : false;
        gamepadState.LeftStick = (pad.dwButtons & 1024) != 0 ? true : false;
        gamepadState.RightStick = (pad.dwButtons & 2048) != 0 ? true : false;
        switch (pad.dwPOV)
        {
            case 0:
                gamepadState.UpDirectional = true;
                break;
            case 4500:
                gamepadState.UpDirectional = true;
                gamepadState.RightDirectional = true;
                break;
            case 9000:
                gamepadState.RightDirectional = true;
                break;
            case 13500:
                gamepadState.RightDirectional = true;
                gamepadState.DownDirectional = true;
                break;
            case 18000:
                gamepadState.DownDirectional = true;
                break;
            case 22500:
                gamepadState.DownDirectional = true;
                gamepadState.LeftDirectional = true;
                break;
            case 27000:
                gamepadState.LeftDirectional = true;
                break;
            case 31500:
                gamepadState.LeftDirectional = true;
                gamepadState.UpDirectional = true;
                break;
        }
        gamepadState.LeftStickAxis.y = 1.0f - ((float)pad.dwYpos / (float)ushort.MaxValue);
        gamepadState.LeftStickAxis.x = (float)pad.dwXpos / (float)ushort.MaxValue;
        gamepadState.RightStickAxis.y = 1.0f - ((float)pad.dwRpos / (float)ushort.MaxValue);
        gamepadState.RightStickAxis.x = (float)pad.dwZpos / (float)ushort.MaxValue;
    }

    int KeyShift()
    {
        if (Input.GetKeyDown(KeyCode.UpArrow) || Input.GetKeyDown(KeyCode.DownArrow))
        {
            if (Input.GetKeyDown(KeyCode.UpArrow) && (ShiftNumber < TOP))
            {
                return 1;
            }
            else if (Input.GetKeyDown(KeyCode.DownArrow) && (0 < ShiftNumber))
            {
                return -1;
            }
        }
        return 0;
    }
    float KeyAccel()
    {
        if (Input.GetKey(KeyCode.W))
        {
            keyAccel += SPEED.y;
        }
        else if (0 < keyAccel)
        {
            keyAccel -= SPEED.y;
        }
        if (-SPEED.y < keyAccel && keyAccel < SPEED.y)
        {
            keyAccel = 0;
        }
        if (keyAccel < 0)
        {
            keyAccel = 0;
        }
        else if (1 < keyAccel)
        {
            keyAccel = 1;
        }

        return keyAccel;
    }
    float KeyBrake()
    {
        if (Input.GetKey(KeyCode.S))
        {
            keyBrake += SPEED.y;
        }
        else if (0 < keyBrake)
        {
            keyBrake -= SPEED.y;
        }
        if (-SPEED.y < keyBrake && keyBrake < SPEED.y)
        {
            keyBrake = 0;
        }
        if (keyBrake < 0)
        {
            keyBrake = 0;
        }
        else if (1 < keyBrake)
        {
            keyBrake = 1;
        }

        return keyBrake;
    }
    float KeySteer()
    {
        inputDire = 0;

        if (Input.GetKey(KeyCode.D))
        {
            ++inputDire;
        }
        if (Input.GetKey(KeyCode.A))
        {
            --inputDire;
        }

        if (inputDire != 0)
        {
            keySteer = (Math.Abs(keySteer) <= 1) ? inputDire : keySteer + SPEED.x * inputDire;
        }
        else
        {
            if (keySteer != 0)
            {
                if (keySteer < 0)
                {
                    keySteer = (keySteer > SPEED.x) ? 0 : keySteer + SPEED.x;
                }
                else
                {
                    keySteer = (keySteer < SPEED.x) ? 0 : keySteer - SPEED.x;
                }
            }
        }

        return keySteer;
    }

    public void Inputs(/*Action shiftChange*/)
    {
        Func<int, int, bool> PushJudge = (buttonX, buttonY) => { return (((pad.Buttons & 1 << buttonX) != 0) || ((pad.Buttons & 1 << buttonY) != 0)) ? true : false; };//入力判定の関数

        Accel = pad.Trigger;//アクセル値

        Brake = pad.RightStickY;//ブレーキ値

        Clutch = pad.LeftStickY;//クラッチ値
        if (RANGE > Mathf.Abs(pad.LeftStickX))//ハンドル値
        {
            Steer = handleSteer = 0.0f;
        }
        else if (pad.LeftStickX > 0)
        {
            Steer = handleSteer = (pad.LeftStickX - RANGE) / ((float)Int16.MaxValue - RANGE);
        }
        else
        {
            Steer = handleSteer = -(pad.LeftStickX + RANGE) / ((float)Int16.MinValue + RANGE);
        }
        if (logicoolG29)
        {
            for (int i = 1; i <= 7; ++i)
            {
                if ((1 << i + 11 & pad.Buttons) != 0)
                {
                    if (i == 7)
                    {
                        i = 0;
                    }
                    shiftLever = i;
                    isShiftLever = true;
                    break;
                }
                else
                {
                    isShiftLever = false;
                }
            }
        }
        else
        {
            isShiftLever = PushJudge(UP, DOWN);//入力判定
        }

        isShiftPaddle = PushJudge(RIGHT, LEFT);

        if (!preIsShiftLever && isShiftLever)//レバー
        {
            if (logicoolG29)
            {
                ShiftNumber = shiftLever;
            }
            else
            {
                if (((pad.Buttons & 1 << UP) != 0) && (ShiftNumber < TOP))
                {
                    ShiftNumber += 1;
                }
                else if (((pad.Buttons & 1 << DOWN) != 0) && (0 < ShiftNumber))
                {
                    ShiftNumber -= 1;
                }
            }
        }
        else if (!preIsShiftPaddle && isShiftPaddle) //パドルシフト
        {
            if (((pad.Buttons & 1 << RIGHT) != 0) && (ShiftNumber < TOP))
            {
                ShiftNumber += 1;
            }
            else if (((pad.Buttons & 1 << LEFT) != 0) && (0 < ShiftNumber))
            {
                ShiftNumber -= 1;
            }
        }
    }

    public void Init(bool gearReset = false)
    {
        isShiftLever = false;
        isShiftPaddle = false;
        preIsShiftLever = false;
        preIsShiftPaddle = false;

        if (gearReset)
        {
            shiftLever = 1;
            preShiftNumber = 1;

            ShiftNumber = 1;
        }

        inputDire = 0;
        keyBrake = 0.0f;
        keyAccel = 0.0f;
        keySteer = 0.0f;
        handleSteer = 0.0f;
    }
    public void SetReverse()
    {
        ShiftNumber = 0;
    }

    class JoyPad
    {
        protected IntPtr ptr;
        public JOYINFOEX JoyInfoEx;

        public JoyPad()
        {
            JoyInfoEx = new JOYINFOEX();
            JoyInfoEx.dwSize = (uint)Marshal.SizeOf(typeof(JOYINFOEX));
            JoyInfoEx.dwFlags = JOY_RETURNALL;

            ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(JOYINFOEX)));

            Marshal.StructureToPtr(JoyInfoEx, ptr, false);
        }

        ~JoyPad()
        {
            Marshal.FreeCoTaskMem(ptr);
        }

        public JOYERR GetPosEx(uint JoyID)
        {
            JOYERR err = joyGetPosEx(JoyID, ptr);

            JoyInfoEx = (JOYINFOEX)Marshal.PtrToStructure(ptr, JoyInfoEx.GetType());

            return (err);
        }

        public uint[]
            GetJoypads()
        {
            List<uint> pads = new List<uint>();
            uint end = joyGetNumDevs();

            for (uint i = 0; i < end; i++)
            {
                if (GetPosEx(i) != JOYERR.NOERROR)
                { continue; }
                pads.Add(i);
            }

            return (pads.ToArray());
        }

        [DllImport("winmm.dll", SetLastError = true, CharSet = CharSet.Auto)]
        protected static extern uint joyGetNumDevs();

        [DllImport("winmm.dll", SetLastError = true, CharSet = CharSet.Auto)]
        protected static extern JOYERR joyGetPosEx(uint uJoyID, IntPtr pji);

        [StructLayout(LayoutKind.Sequential)]
        public struct JOYINFOEX
        {
            public UInt32 dwSize;                /* size of structure */
            public UInt32 dwFlags;               /* flags to indicate what to return */
            public UInt32 dwXpos;                /* x position */
            public UInt32 dwYpos;                /* y position */
            public UInt32 dwZpos;                /* z position */
            public UInt32 dwRpos;                /* rudder/4th axis position */
            public UInt32 dwUpos;                /* 5th axis position */
            public UInt32 dwVpos;                /* 6th axis position */
            public UInt32 dwButtons;             /* button states */
            public UInt32 dwButtonNumber;        /* current button number pressed */
            public UInt32 dwPOV;                 /* point of view state */
            public UInt32 dwReserved1;           /* reserved for communication between winmm & driver */
            public UInt32 dwReserved2;           /* reserved for future expansion */
        }

        /* joystick error return values */
        public enum JOYERR
        {
            NOERROR = (0),               /* no error */
            PARMS = (160 + 5),           /* bad parameters */
            NOCANDO = (160 + 6),         /* request not completed */
            UNPLUGGED = (160 + 7),       /* joystick is unplugged */
        }


        /* public constants used with JOYINFO and JOYINFOEX structures and MM_JOY* messages */
        public const UInt32 JOY_BUTTON1 = 0x0001;
        public const UInt32 JOY_BUTTON2 = 0x0002;
        public const UInt32 JOY_BUTTON3 = 0x0004;
        public const UInt32 JOY_BUTTON4 = 0x0008;
        public const UInt32 JOY_BUTTON1CHG = 0x0100;
        public const UInt32 JOY_BUTTON2CHG = 0x0200;
        public const UInt32 JOY_BUTTON3CHG = 0x0400;
        public const UInt32 JOY_BUTTON4CHG = 0x0800;

        /* public constants used with JOYINFOEX */
        public const UInt32 JOY_BUTTON5 = 0x00000010;
        public const UInt32 JOY_BUTTON6 = 0x00000020;
        public const UInt32 JOY_BUTTON7 = 0x00000040;
        public const UInt32 JOY_BUTTON8 = 0x00000080;
        public const UInt32 JOY_BUTTON9 = 0x00000100;
        public const UInt32 JOY_BUTTON10 = 0x00000200;
        public const UInt32 JOY_BUTTON11 = 0x00000400;
        public const UInt32 JOY_BUTTON12 = 0x00000800;
        public const UInt32 JOY_BUTTON13 = 0x00001000;
        public const UInt32 JOY_BUTTON14 = 0x00002000;
        public const UInt32 JOY_BUTTON15 = 0x00004000;
        public const UInt32 JOY_BUTTON16 = 0x00008000;
        public const UInt32 JOY_BUTTON17 = 0x00010000;
        public const UInt32 JOY_BUTTON18 = 0x00020000;
        public const UInt32 JOY_BUTTON19 = 0x00040000;
        public const UInt32 JOY_BUTTON20 = 0x00080000;
        public const UInt32 JOY_BUTTON21 = 0x00100000;
        public const UInt32 JOY_BUTTON22 = 0x00200000;
        public const UInt32 JOY_BUTTON23 = 0x00400000;
        public const UInt32 JOY_BUTTON24 = 0x00800000;
        public const UInt32 JOY_BUTTON25 = 0x01000000;
        public const UInt32 JOY_BUTTON26 = 0x02000000;
        public const UInt32 JOY_BUTTON27 = 0x04000000;
        public const UInt32 JOY_BUTTON28 = 0x08000000;
        public const UInt32 JOY_BUTTON29 = 0x10000000;
        public const UInt32 JOY_BUTTON30 = 0x20000000;
        public const UInt32 JOY_BUTTON31 = 0x40000000;
        public const UInt32 JOY_BUTTON32 = 0x80000000;

        /* public constants used with JOYINFOEX structure */
        public const UInt32 JOY_POVCENTERED = 65535;
        public const UInt32 JOY_POVFORWARD = 0;
        public const UInt32 JOY_POVRIGHT = 9000;
        public const UInt32 JOY_POVBACKWARD = 18000;
        public const UInt32 JOY_POVLEFT = 27000;

        public const UInt32 JOY_RETURNX = 0x00000001;
        public const UInt32 JOY_RETURNY = 0x00000002;
        public const UInt32 JOY_RETURNZ = 0x00000004;
        public const UInt32 JOY_RETURNR = 0x00000008;
        public const UInt32 JOY_RETURNU = 0x00000010;     /* axis 5 */
        public const UInt32 JOY_RETURNV = 0x00000020;     /* axis 6 */
        public const UInt32 JOY_RETURNPOV = 0x00000040;
        public const UInt32 JOY_RETURNBUTTONS = 0x00000080;
        public const UInt32 JOY_RETURNRAWDATA = 0x00000100;
        public const UInt32 JOY_RETURNPOVCTS = 0x00000200;
        public const UInt32 JOY_RETURNCENTERED = 0x00000400;
        public const UInt32 JOY_USEDEADZONE = 0x00000800;
        public const UInt32 JOY_RETURNALL =
            (JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ |
            JOY_RETURNR | JOY_RETURNU | JOY_RETURNV |
            JOY_RETURNPOV | JOY_RETURNBUTTONS);
        public const UInt32 JOY_CAL_READALWAYS = 0x00010000;
        public const UInt32 JOY_CAL_READXYONLY = 0x00020000;
        public const UInt32 JOY_CAL_READ3 = 0x00040000;
        public const UInt32 JOY_CAL_READ4 = 0x00080000;
        public const UInt32 JOY_CAL_READXONLY = 0x00100000;
        public const UInt32 JOY_CAL_READYONLY = 0x00200000;
        public const UInt32 JOY_CAL_READ5 = 0x00400000;
        public const UInt32 JOY_CAL_READ6 = 0x00800000;
        public const UInt32 JOY_CAL_READZONLY = 0x01000000;
        public const UInt32 JOY_CAL_READRONLY = 0x02000000;
        public const UInt32 JOY_CAL_READUONLY = 0x04000000;
        public const UInt32 JOY_CAL_READVONLY = 0x08000000;

        /* joystick ID public constants */
        public const UInt32 JOYSTICKID1 = 0;
        public const UInt32 JOYSTICKID2 = 1;

        /* joystick driver capabilites */
        public const UInt32 JOYCAPS_HASZ = 0x0001;
        public const UInt32 JOYCAPS_HASR = 0x0002;
        public const UInt32 JOYCAPS_HASU = 0x0004;
        public const UInt32 JOYCAPS_HASV = 0x0008;
        public const UInt32 JOYCAPS_HASPOV = 0x0010;
        public const UInt32 JOYCAPS_POV4DIR = 0x0020;
        public const UInt32 JOYCAPS_POVCTS = 0x0040;
    }

    class Xbox360_JoyPad : JoyPad
    {
        public bool ButtonA
        { get { return ((JoyInfoEx.dwButtons & JOY_BUTTON1) != 0); } }

        public bool ButtonB
        { get { return ((JoyInfoEx.dwButtons & JOY_BUTTON2) != 0); } }

        public bool ButtonX
        { get { return ((JoyInfoEx.dwButtons & JOY_BUTTON3) != 0); } }

        public bool ButtonY
        { get { return ((JoyInfoEx.dwButtons & JOY_BUTTON4) != 0); } }

        public bool ButtonLeftShoulder
        { get { return ((JoyInfoEx.dwButtons & JOY_BUTTON5) != 0); } }

        public bool ButtonRightShoulder
        { get { return ((JoyInfoEx.dwButtons & JOY_BUTTON6) != 0); } }

        public bool ButtonBack
        { get { return ((JoyInfoEx.dwButtons & JOY_BUTTON7) != 0); } }

        public bool ButtonStart
        { get { return ((JoyInfoEx.dwButtons & JOY_BUTTON8) != 0); } }

        public bool ButtonLeftStick
        { get { return ((JoyInfoEx.dwButtons & JOY_BUTTON9) != 0); } }

        public bool ButtonRightStick
        { get { return ((JoyInfoEx.dwButtons & JOY_BUTTON10) != 0); } }



        public int Buttons
        { get { return (int)JoyInfoEx.dwButtons; } }
        public float LeftStickX
        { get { return (float)JoyInfoEx.dwXpos - Int16.MaxValue; } }
        //(float)JoyInfoEx.dwXpos - Int16.MaxValue
        public float LeftStickY
        { get { return 1.0f - ((float)JoyInfoEx.dwYpos / UInt16.MaxValue); } }

        public float RightStickX
        { get { return 1.0f - ((float)JoyInfoEx.dwUpos / UInt16.MaxValue); } }

        public float RightStickY
        { get { return 1.0f - ((float)JoyInfoEx.dwRpos / UInt16.MaxValue); } }

        public float Trigger
        { get { return 1.0f - ((float)JoyInfoEx.dwZpos / UInt16.MaxValue); } }
        //以下テスト用
        public UInt32 dwButtonNumber
        { get { return JoyInfoEx.dwButtonNumber; } }
        public UInt32 dwButtons
        { get { return JoyInfoEx.dwButtons; } }
        public UInt32 dwFlags
        { get { return JoyInfoEx.dwFlags; } }
        public UInt32 dwPOV
        { get { return JoyInfoEx.dwPOV; } }
        public UInt32 dwReserved1
        { get { return JoyInfoEx.dwReserved1; } }
        public UInt32 dwReserved2
        { get { return JoyInfoEx.dwReserved2; } }
        public UInt32 dwRpos
        { get { return JoyInfoEx.dwRpos; } }
        public UInt32 dwSize
        { get { return JoyInfoEx.dwSize; } }
        public UInt32 dwUpos
        { get { return JoyInfoEx.dwUpos; } }
        public UInt32 dwVpos
        { get { return JoyInfoEx.dwVpos; } }
        public UInt32 dwXpos
        { get { return JoyInfoEx.dwXpos; } }
        public UInt32 dwYpos
        { get { return JoyInfoEx.dwYpos; } }
        public UInt32 dwZpos
        { get { return JoyInfoEx.dwZpos; } }
    }

}

C++でゲームコントローラを取得

#pragma comment(lib, "winmm.lib")

#include <stdio.h>
#include <windows.h>

int main() {

	JOYINFOEX JoyInfoEx;
	JoyInfoEx.dwSize = sizeof(JOYINFOEX);
	JoyInfoEx.dwFlags = JOY_RETURNALL;

	for (unsigned int i = 0; i < joyGetNumDevs(); i++) {//サポートされているジョイスティックの数を返す
		if (JOYERR_NOERROR == joyGetPosEx(i, &JoyInfoEx))
			printf("ジョイスティック No.%d 接続されています\n", i);
	}
	Sleep(1000);

	while (1) {
		if (JOYERR_NOERROR == joyGetPosEx(0, &JoyInfoEx)) { //0番のジョイスティックの情報を見る
			printf("address = %d\t", &JoyInfoEx);
			printf("dwXpos = 0x%x\t"
				"dwYpos = 0x%x\t"
				"dwButtons = 0x%x\n",
				JoyInfoEx.dwXpos,
				JoyInfoEx.dwYpos,
				JoyInfoEx.dwButtons);

		}
		else {
			printf("エラー\n");
		}
		Sleep(100);
	}
	return 0;
}

マジックナンバーを駆逐せよ!

10回だけ処理をするプログラムを書くとき、こう書いてますか?

10回処理コード

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Hoge : MonoBehaviour {
    int value = 0;
    void Start()
    {
    }
    void Update()
    {
        if (value < 10)
        {
            Debug.Log("Play!!");
            ++value;
        }
    }
}

はい、こんな事をしてしまったら、膝蹴りが飛んで来ますね。
https://img.gifmagazine.net/gifmagazine/images/7879/original.gif

なので、マジックナンバーを消してみるとこうなります。

マジックナンバー駆逐

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Hoge : MonoBehaviour {
    int value = 0;
    int number = 10;
    void Start()
    {
    }
    void Update()
    {
        if (value < number)
        {
            Debug.Log("Play!!");
            ++value;
        }
    }
}

こうなりますが、こうするとカウント部分と条件部分で変数が二つになってしまいます。
変数はなるべく、見栄えの部分とメモリの為に増やしたくない。
実際に変数を減らした上でマジックナンバーを使わない方法を考えてみた。

変数減らしたコード

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Hoge : MonoBehaviour {
    int value = 10;
    void Start()
    {
    }
    void Update()
    {
        if (-value != value)
        {
            Debug.Log("Play!!");
            --value;
        }
    }
}

こうすると変数も一つで、マジックナンバー警察も来ないというプログラムの出来上がり。
ただ、少し変態的なソースコードになりました。
https://img.gifmagazine.net/gifmagazine/images/647670/original.gif

***募集***
一緒にブログを運営してくれる人募集しています。
主な作業は修理作業です。画像足りなかったら拾ってくるとか、誤字の修正などです。
見出し増やすなど、見た目に関する所お願いします。
Twitterに連絡くれれば反応できます。

しんーーご (@shi_k_7) | Twitter

フェードイン・フェードアウトするUIプログラム

www.youtube.com

早い話がボンバーマンみたいなREADY、GOみたいな演出がしたかったんです。
また、量産型クソコード

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UIstart : MonoBehaviour {
   
    private RectTransform hoge;
	private int frame = 0;
    private RectTransform ret;
    private RectTransform go;
    private RectTransform end;
    private RectTransform hurry;
    int i= -10;
    TimerScript timerScript;
    float j = -1.5f;
    int end_frame = 0;
    void Start()
    {
        hoge = transform.GetChild(0).gameObject.GetComponent<RectTransform>();
		hoge.sizeDelta = new Vector2(1920, -30);
        ret = transform.GetChild(1).gameObject.GetComponent<RectTransform>();
        ret.localPosition = new Vector3(1500, 0, 0);
        go = transform.GetChild(2).gameObject.GetComponent<RectTransform>();
        go.localPosition = new Vector3(1500, 0, 0);
        hurry = transform.GetChild(3).gameObject.GetComponent<RectTransform>();
        hurry.localPosition = new Vector3(1500, 0, 0);
        timerScript= GetComponent<TimerScript>();
        end = transform.GetChild(4).gameObject.GetComponent<RectTransform>();
        end.localPosition = new Vector3(1500, 200, 0);
    }

    // Update is called once per frame
    void Update()
    {
        if (timerScript.count <= 0)
        {
            ++end_frame;
        }
       
        if (frame <= 10 || (timerScript.count <= 0 && end_frame <= 10))
        {
            if(timerScript.count <= 0 && end_frame == 1)
            {
                hoge.localPosition= new Vector3(0, 200, 0);
            }
            hoge.sizeDelta += new Vector2(0, 30);
        }
        else if (20 < frame && frame <= 30)
        {
            ++i;
            ret.localPosition = new Vector3(1500.0f * (Mathf.Pow(i, 2) / 100.0f), 0, 0);

        }
        else if (50 < frame && frame <= 60)
        {
            ++i;
            ret.localPosition = new Vector3(1500.0f * (-Mathf.Pow(i, 2) / 100.0f), 0, 0);

        }
        else if (70 < frame && frame <= 80)
        {
            ++i;
            go.localPosition = new Vector3(1500.0f * (Mathf.Pow(i, 2) / 100.0f), 0, 0);
        }
        else if (90 < frame && frame <= 100)
        {
            ++i;
            go.localPosition = new Vector3(1500.0f * (-Mathf.Pow(i, 2) / 100.0f), 0, 0);
            hoge.sizeDelta -= new Vector2(0, 30);
        }
        if (timerScript.count <= 60 && j <= 1.5f)
        {
            j += 0.025f;
            hurry.localPosition = new Vector3(1500.0f * (-Mathf.Tan(j) / 15.0f), 0, 0);
        }
        if(timerScript.count <= 0 && 20 < end_frame && end_frame <= 30)
        {
            ++i;
            end.localPosition = new Vector3(1500.0f * (Mathf.Pow(i, 2) / 100.0f), 200, 0);
        }
        if (i>=10)
        {
            i = -10;
        }
		++frame;
	}
}

#1

 if (timerScript.count <= 60 && j <= 1.5f)
        {
            j += 0.025f;
            hurry.localPosition = new Vector3(1500.0f * (-Mathf.Tan(j) / 15.0f), 0, 0);
        }

ここだけtanの値をつかって画面中央辺りに来たらゆっくりになる奴にしてます。

***募集***
一緒にブログを運営してくれる人募集しています。
主な作業は修理作業です。画像足りなかったら拾ってくるとか、誤字の修正などです。
見出し増やすなど、見た目に関する所お願いします。
Twitterに連絡くれれば反応できます。

しんーーご (@shi_k_7) | Twitter

ゲームパッドを使用した4人同時入力

assetstore.unity.com
このアセットを使用した4人入力です。

過去のクソコードです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GamepadInput; 
public class Player : Type
{
    //プレイヤーの動くスピード
    public float speed;
    //プレイヤーの体力
    public int HP;
    public bool shot;
    GameObject child;
	public GameObject clown;
    public GameObject Resurrection;
    PlayerGeneretion generetion;
    public int PlayerNumber;
    public Vector3 V3;
    TimerScript timerScript;
    public AudioClip DamageSound;
    public AudioClip ResuscitationSound;
    public AudioClip ItemSound;
    public AudioClip ItemSoundRare;
    public int sound;
    public int soundRare;
    public float ShotDelete;
    public bool alive;
	GameObject Obj;
    Phase ph;
	bool one=true;
    public enum PlayerNo
    {
        none,
        one,
        two,
        three,
        four
    }
    public PlayerNo playerNo;

    //初期化
    void Start()
    {
        alive = true;
        speed = 6;
        ShotDelete = 15;
        V3 = transform.position;
        HP = 3;
        child = transform.Find("shot_point").gameObject;
        timerScript= GameObject.Find("Canvas").GetComponent<TimerScript>();
        generetion = GameObject.Find("GeneretionPlayer").GetComponent<PlayerGeneretion>();
        ph = GameObject.Find("Phase").GetComponent<Phase>();
    }
    void Update()
    {
		if(Rank.win== (int)playerNo&&one)
		{
			Obj = (GameObject)Instantiate(clown, this.transform.position+new Vector3(0,3,0), Quaternion.identity);
			Obj.transform.parent = transform;
			one = false;
		}else if(Rank.win != (int)playerNo)
		{
			foreach (Transform child in transform)
			{
				if (child.name == "SI_CrownIcon(Clone)")
				{
					GameObject.Destroy(child.gameObject);
				}
			}
			one = true;
		}
        if (HP <= 0)
        {
            alive = false;
            ++sound;
            if (sound > 120)
            {
                sound = 0;
                Destroy();
                Destroy(gameObject);
            }
        }
        Movingrotation();
    }
    //移動回転処理
    private void Movingrotation()
    {
        GamepadState keyState1 = GamePad.GetState(GamePad.Index.One);
        GamepadState keyState2 = GamePad.GetState(GamePad.Index.Two);
        GamepadState keyState3 = GamePad.GetState(GamePad.Index.Three);
        GamepadState keyState4 = GamePad.GetState(GamePad.Index.Four);
        if ((alive == true&&timerScript.count>0)&&ph.Starttime == true)
        {
            //1P
            if (playerNo == PlayerNo.one)
            {
                //押されたキーの向きに向く
                if (keyState1.Down || keyState1.Up || Input.GetKey(KeyCode.UpArrow) || Input.GetKey(KeyCode.DownArrow))
                {
                    if (keyState1.Up || Input.GetKey(KeyCode.UpArrow))
                    {
                        transform.eulerAngles = new Vector3(0, 0, 0);
                    }
                    else
                    {
                        transform.eulerAngles = new Vector3(0, 180, 0);
                    }
                    //今向いている方向に移動する
                    transform.position += transform.forward * speed * Time.deltaTime;
                }else
                if (keyState1.Right || keyState1.Left || Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.RightArrow))
                {
                    if (keyState1.Right || Input.GetKey(KeyCode.RightArrow))
                    {
                        transform.eulerAngles = new Vector3(0, 90, 0);
                    }
                    else
                    {
                        transform.eulerAngles = new Vector3(0, -90, 0);
                    }
                    //今向いている方向に移動する
                    transform.position += transform.forward * speed * Time.deltaTime;
                }
            }
            //2P
            if (playerNo == PlayerNo.two)
            {
                //押されたキーの向きに向く
                if (keyState2.Down || keyState2.Up || Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.S))
                {
                    if (keyState2.Up || Input.GetKey(KeyCode.W))
                    {
                        transform.eulerAngles = new Vector3(0, 0, 0);
                    }
                    else
                    {
                        transform.eulerAngles = new Vector3(0, 180, 0);
                    }
                    //今向いている方向に移動する
                    transform.position += transform.forward * speed * Time.deltaTime;
                }
				else
				if (keyState2.Right || keyState2.Left || Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D))
                {
                    if (keyState2.Right || Input.GetKey(KeyCode.D))
                    {
                        transform.eulerAngles = new Vector3(0, 90, 0);
                    }
                    else
                    {
                        transform.eulerAngles = new Vector3(0, -90, 0);
                    }
                    //今向いている方向に移動する
                    transform.position += transform.forward * speed * Time.deltaTime;
                }
            }
            //3P
            if ((playerNo == PlayerNo.three))
            {
                //押されたキーの向きに向く
                if (keyState3.Down || keyState3.Up || Input.GetKey(KeyCode.T) || Input.GetKey(KeyCode.G))
                {
                    if (keyState3.Up || Input.GetKey(KeyCode.T))
                    {
                        transform.eulerAngles = new Vector3(0, 0, 0);
                    }
                    else
                    {
                        transform.eulerAngles = new Vector3(0, 180, 0);
                    }
                    //今向いている方向に移動する
                    transform.position += transform.forward * speed * Time.deltaTime;
                }
				else
				if (keyState3.Right || keyState3.Left || Input.GetKey(KeyCode.F) || Input.GetKey(KeyCode.H))
                {
                    if (keyState3.Right || Input.GetKey(KeyCode.H))
                    {
                        transform.eulerAngles = new Vector3(0, 90, 0);
                    }
                    else
                    {
                        transform.eulerAngles = new Vector3(0, -90, 0);
                    }
                    //今向いている方向に移動する
                    transform.position += transform.forward * speed * Time.deltaTime;
                }
            }
            //4P
            if (playerNo == PlayerNo.four)
            {
                //押されたキーの向きに向く
                if (keyState4.Down || keyState4.Up || Input.GetKey(KeyCode.I) || Input.GetKey(KeyCode.K))
                {
                    if (keyState4.Up || Input.GetKey(KeyCode.I))
                    {
                        transform.eulerAngles = new Vector3(0, 0, 0);
                    }
                    else
                    {
                        transform.eulerAngles = new Vector3(0, 180, 0);
                    }
                    //今向いている方向に移動する
                    transform.position += transform.forward * speed * Time.deltaTime;
                }
				else
				if (keyState4.Right || keyState4.Left || Input.GetKey(KeyCode.J) || Input.GetKey(KeyCode.L))
                {
                    if (keyState4.Right || Input.GetKey(KeyCode.L))
                    {
                        transform.eulerAngles = new Vector3(0, 90, 0);
                    }
                    else
                    {
                        transform.eulerAngles = new Vector3(0, -90, 0);
                    }
                    //今向いている方向に移動する
                    transform.position += transform.forward * speed * Time.deltaTime;
                }
            }
        }
    }
    private void OnTriggerEnter(Collider other)
    {
        //当たったものが弾なら入る
        if (other.gameObject.GetComponent<Type>().objtype == Objtype.bullet)
        {
            //弾の発射元じゃないならHPを減らす
            if (other.gameObject.GetComponent<Bullet>().ShotPlayer != gameObject)
            {
                --HP;
                if (HP != 0)
                {
                    GetComponent<AudioSource>().PlayOneShot(DamageSound);
                }
                else
                {
                    GetComponent<AudioSource>().PlayOneShot(ResuscitationSound);
                }
            }
        }
        if (other.GetComponent<Type>().objtype == Objtype.item)
        {
            soundRare = Random.Range(0, 10);
            if (soundRare != 5)
            {
                GetComponent<AudioSource>().PlayOneShot(ItemSound);
            }
            else
            {
                GetComponent<AudioSource>().PlayOneShot(ItemSoundRare);
            }
        }
    }
    private void Destroy()
    {
        generetion.vs[PlayerNumber] = false;
        //Instantiate(Resurrection, V3, Quaternion.identity);
        switch ((int)playerNo)
        {
            case 1:
                ++Rank.no_1;
                break;
            case 2:
                ++Rank.no_2;
                break;
            case 3:
                ++Rank.no_3;
                break;
            case 4:
                ++Rank.no_4;
                break;
            default:
                break;
        }
    }
}
***募集***
一緒にブログを運営してくれる人募集しています。
主な作業は修理作業です。画像足りなかったら拾ってくるとか、誤字の修正などです。
見出し増やすなど、見た目に関する所お願いします。
Twitterに連絡くれれば反応できます。

しんーーご (@shi_k_7) | Twitter

LogitechGSDKのバグ?ハンドルコントローラの状態が取得できない。

assetstore.unity.com
こちらのアセットを使っているのですが、ノートパソコンに持って来て開発しようとした時。

ハンコンの値が取れん!?

原因

//LogitechGSDK.cs
//593行
 try
        {
            ret = (DIJOYSTATE2ENGINES)Marshal.PtrToStructure(LogiGetStateENGINES(index), typeof(DIJOYSTATE2ENGINES));
        }
        catch (System.ArgumentException)
        {
            Debug.Log("Exception catched");
        }

catchに入ってしまう。>||LogiGetStateENGINES(index)||<と>||typeof(DIJOYSTATE2ENGINES)||<を >||Debug.Log||<してみると、
>||LogiGetStateENGINES(index)||<が取れてない
DIJOYSTATE2構造体の単純化バージョンが返ってくるらしい。戻り値の型はIntPtrで32ビットのポインタ。
早い話がコントローラの状態が取れていないか、コントローラのポインタが取れていないということだ。
DLLがC++なので、分からない。


***募集***
一緒にブログを運営してくれる人募集しています。
主な作業は修理作業です。画像足りなかったら拾ってくるとか、誤字の修正などです。
見出し増やすなど、見た目に関する所お願いします。
Twitterに連絡くれれば反応できます。

しんーーご (@shi_k_7) | Twitter

Unityでの壁貫通しない三人称カメラのソースコード

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CheckObstacles : MonoBehaviour {
    // カメラの元の位置
    [SerializeField]
    private Vector3 cameraPrePosition;
    [SerializeField]
    private Transform player;
    private RaycastHit hit;
    // カメラの移動スピード
    [SerializeField]
    private float cameraMoveSpeed = 3f;
    private const float _distance = 5.2f;//
    private Vector3 _offset = new Vector3(0f, 1.0f, -_distance);

    private Vector3 _lookDown = new Vector3(30f, 0f, 0f);
    [SerializeField]
    bool ON=true;
    void Start()
    {
        // player = transform.root;
        // 初期位置を設定
        transform.position = player.TransformPoint(_offset);
        transform.LookAt(player/*, Vector3.up*/);
    }
    void Update()
    {
  Vector3 desiredPosition = player.TransformPoint(_offset);
            if (desiredPosition.y < player.position.y)
            {
                desiredPosition.y = player.position.y;
            }

        // カメラが障害物と接触してたら障害物の場所に移動
        if (Physics.Linecast(player.position/* + Vector3.up*/, transform.position, out hit, LayerMask.GetMask("Field", "Enemy", "EnemyHit"))&& Vector3.Distance(player.position,transform.position)< _distance)
        {
            transform.position = Vector3.Lerp(transform.position, hit.point, cameraMoveSpeed * Time.deltaTime);
            
            // 障害物と接触してなければ元のカメラ位置に移動
        }
        else if(ON)
        {
          
            Vector3 lerp = Vector3.Lerp(transform.position, desiredPosition, cameraMoveSpeed * Time.deltaTime);
            Vector3 toTarget = player.position - lerp;
            toTarget.Normalize();
            toTarget *= _distance;
            transform.position = player.position - toTarget;
            // 元の位置ではない時だけ元の位置に移動
            //if (transform.localPosition != cameraPrePosition)
            //{
            //    transform.localPosition = Vector3.Lerp(transform.localPosition, cameraPrePosition, cameraMoveSpeed * Time.deltaTime);
            //}
        }
        transform.LookAt(player/*, Vector3.up*/);
   //     transform.Rotate(_lookDown);
        // レイを視覚的に確認
        Debug.DrawLine(player.position /*+ Vector3.up*/, transform.position, Color.red, 0f, false);
    }
    //オブジェクトが衝突したとき
    void OnTriggerEnter(Collider other)
    {
        ON = false;
    }

    //オブジェクトが離れた時
    void OnTriggerExit(Collider other)
    {
        ON = true;
    }

    //オブジェクトが触れている間
    void OnTriggerStay(Collider other)
    {
        if(Vector3.Distance(player.position, transform.position) >= _distance)
        {
            ON = true;
        }
    }
}
***募集***
一緒にブログを運営してくれる人募集しています。
主な作業は修理作業です。画像足りなかったら拾ってくるとか、誤字の修正などです。
見出し増やすなど、見た目に関する所お願いします。
Twitterに連絡くれれば反応できます。

しんーーご (@shi_k_7) | Twitter