//*************************************************************************************************
// バレット処理 (bullet.cpp)
// Author : YUHEI KAN
//*************************************************************************************************

//*************************************************************************************************
// ヘッダ
//*************************************************************************************************
#include "main.h"
#include "particle.h"

//*************************************************************************************************
// 定数定義
//*************************************************************************************************
#define PARTICLE_TEXTURE_MAX ( 2 )                //読み込むテクスチャの枚数

#define NUM_POLYGON ( 2 )
#define NUM_VERTEX  ( 4 )


//*************************************************************************************************
// 構造体
//*************************************************************************************************

//*************************************************************************************************
// グローバル変数
//*************************************************************************************************
LPDIRECT3DTEXTURE9 g_pTextureParticle[PARTICLE_TEXTURE_MAX]; //テクスチャインターフェースポインタ
LPDIRECT3DVERTEXBUFFER9 g_pVtxBufferParticle;               //頂点バッファ管理インターフェースポインタ
PARTICLE g_aParticle[PARTICLE_MAX];                   //弾情報
int nCntFPSParticle;                              //FPSカウンタ

//*************************************************************************************************
// プロトタイプ宣言
//*************************************************************************************************
HRESULT MakeVertexParticle ( LPDIRECT3DDEVICE9 pDevice );
void SetVertexParticle ( VERTEX_2D* pVtx, int nTexNum );

//*************************************************************************************************
// バレット初期化処理
//*************************************************************************************************
void InitParticle ( void )
{
    //変数初期化
    nCntFPSParticle = 0;                           //FPSカウンタ

    //Direct3Dデバイスの取得
    LPDIRECT3DDEVICE9 pDevice = GetDevice ( );

    //Direct3DデバイスのNULLチェック
    if ( pDevice != NULL )
    {
        //頂点の作成
        if ( FAILED ( MakeVertexParticle ( pDevice ) ) )
        {
            MessageBox ( NULL, "頂点の作成に失敗しました", "終了メッセージ", MB_OK );
        }

        //テクスチャの読み込み
        if ( FAILED ( D3DXCreateTextureFromFile ( pDevice, "data/TEXTURE/effect000.jpg", &g_pTextureParticle[0] ) )
            || FAILED ( D3DXCreateTextureFromFile ( pDevice, "data/TEXTURE/effect000.jpg", &g_pTextureParticle[1] ) ) )
        {
            MessageBox ( NULL, "テクスチャの読み込みに失敗しました", "終了メッセージ", MB_OK );
        }
    }

    //バレット初期化
    for ( int nCntParticle = 0; nCntParticle < PARTICLE_MAX; nCntParticle++ )
    {
        g_aParticle[nCntParticle].bUse = false;
    }
}

//*************************************************************************************************
// バレット更新処理
//*************************************************************************************************
void UpdateParticle ( void )
{
     //頂点の設定
     VERTEX_2D* pVtx;                                //仮想アドレス用ポインタ

    //頂点バッファをロックして、仮想アドレスを取得する
    g_pVtxBufferParticle->Lock ( 0, 0, (void**)&pVtx, 0 );

    for ( int nCntParticle = 0; nCntParticle < PARTICLE_MAX; nCntParticle++ )
    {
        if ( !g_aParticle[nCntParticle].bUse )
        {
            continue;
        }
        //g_aParticle[nCntParticle].Pos += g_aParticle[nCntParticle].Speed;

        //寿命の更新
        g_aParticle[nCntParticle].nLife--;
        if ( g_aParticle[nCntParticle].nLife <= 0 )
        {
            g_aParticle[nCntParticle].bUse = false;
        }
        else
        {
            //加速度の加算
            g_aParticle[nCntParticle].Speed.x *= g_aParticle[nCntParticle].Acceleration.x;
            g_aParticle[nCntParticle].Speed.y *= g_aParticle[nCntParticle].Acceleration.y;

            //位置の更新
            g_aParticle[nCntParticle].Pos.x += g_aParticle[nCntParticle].Speed.x;
            g_aParticle[nCntParticle].Pos.y += g_aParticle[nCntParticle].Speed.y;
        }
        if ( g_aParticle[nCntParticle].bUse == true )
        {
            SetVertexParticle ( pVtx, nCntParticle );
        }
    }

    //頂点バッファのロックを解除
    g_pVtxBufferParticle->Unlock ( );
}

//*************************************************************************************************
// バレット描画処理
//*************************************************************************************************
void DrawParticle ( void )
{
    //Direct3Dデバイスの取得
    LPDIRECT3DDEVICE9 pDevice = GetDevice ( );

    //Direct3DデバイスのNULLチェック
    if ( pDevice != NULL )
    {
        //頂点バッファを設定(ストリーム)
        pDevice->SetStreamSource ( 0, g_pVtxBufferParticle, 0, sizeof ( VERTEX_2D ) );

        //頂点フォーマットの設定
        pDevice->SetFVF ( FVF_VERTEX_2D );


        //加算合成
        pDevice->SetRenderState ( D3DRS_BLENDOP, D3DBLENDOP_ADD );      //アルファブレンド
        pDevice->SetRenderState ( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );     //テクスチャα
        pDevice->SetRenderState ( D3DRS_DESTBLEND, D3DBLEND_ONE );         //背景α

        //テクスチャの設定
        pDevice->SetTexture ( 0, g_pTextureParticle[0] );

        for ( int nCntParticle = 0; nCntParticle < PARTICLE_MAX; nCntParticle++ )
        {
            if ( g_aParticle[nCntParticle].bUse == true )
            {
                //プリミティブの描画
                pDevice->DrawPrimitive ( D3DPT_TRIANGLESTRIP,           //プリッミティブの種類
                    0 + nCntParticle * 4,                                 //オフセット(頂点数)
                    NUM_POLYGON );                                      //プリミティブ数
            }
        }

        pDevice->SetRenderState ( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); //背景α
    }
}

//*************************************************************************************************
// バレット終了処理
//*************************************************************************************************
void UninitParticle ( void )
{
    //テクスチャインターフェースの解放
    if ( g_pTextureParticle != NULL )
    {
        for ( int nCntRelease = 0; nCntRelease < PARTICLE_TEXTURE_MAX; nCntRelease++ )
        {
            g_pTextureParticle[nCntRelease]->Release();
            g_pTextureParticle[nCntRelease] = NULL;
        }
    }

    //頂点バッファ管理インターフェースの解放
    if ( g_pVtxBufferParticle != NULL )
    {
        g_pVtxBufferParticle->Release();
        g_pVtxBufferParticle= NULL;
    }
}

//*************************************************************************************************
// 頂点の作成
//*************************************************************************************************
HRESULT MakeVertexParticle ( LPDIRECT3DDEVICE9 pDevice )
{
    if ( FAILED (pDevice->CreateVertexBuffer ( 
        sizeof ( VERTEX_2D ) * NUM_VERTEX * PARTICLE_MAX,  //作成したい頂点バッファのサイズ
        D3DUSAGE_WRITEONLY,                          //VertexBufferの使い方を指定
        FVF_VERTEX_2D,                               //
        D3DPOOL_MANAGED,                             //メモリ管理（誰が管理するか）
        &g_pVtxBufferParticle,                          //
        NULL ) ) )
    {
        return E_FAIL;
    }
    else
    {
    }

    return S_OK;
}

//*************************************************************************************************
// 頂点の設定
//*************************************************************************************************
void SetVertexParticle ( VERTEX_2D* pVtx, int nTexNum )
{
    //頂点座標の設定(2D座標)
    pVtx[ 0 + nTexNum * 4 ].pos = D3DXVECTOR3 ( g_aParticle[nTexNum].Pos.x, g_aParticle[nTexNum].Pos.y, 0.0f );
    pVtx[ 1 + nTexNum * 4 ].pos = D3DXVECTOR3 ( g_aParticle[nTexNum].Pos.x + 50.0f, g_aParticle[nTexNum].Pos.y, 0.0f );
    pVtx[ 2 + nTexNum * 4 ].pos = D3DXVECTOR3 ( g_aParticle[nTexNum].Pos.x, g_aParticle[nTexNum].Pos.y + 50.0f, 0.0f );
    pVtx[ 3 + nTexNum * 4 ].pos = D3DXVECTOR3 ( g_aParticle[nTexNum].Pos.x + 50.0f, g_aParticle[nTexNum].Pos.y + 50.0f, 0.0f );

    //rhwの設定(必ず1.0f)
    pVtx[ 0 + nTexNum * 4 ].rhw = 
    pVtx[ 1 + nTexNum * 4 ].rhw = 
    pVtx[ 2 + nTexNum * 4 ].rhw = 
    pVtx[ 3 + nTexNum * 4 ].rhw = 1.0f;

    //頂点カラー(0〜255の整数値)
    pVtx[ 0 + nTexNum * 4 ].color = D3DXCOLOR( g_aParticle[nTexNum].Color.r, g_aParticle[nTexNum].Color.g, g_aParticle[nTexNum].Color.b, g_aParticle[nTexNum].Color.a );
    pVtx[ 1 + nTexNum * 4 ].color = D3DXCOLOR( g_aParticle[nTexNum].Color.r, g_aParticle[nTexNum].Color.g, g_aParticle[nTexNum].Color.b, g_aParticle[nTexNum].Color.a );
    pVtx[ 2 + nTexNum * 4 ].color = D3DXCOLOR( g_aParticle[nTexNum].Color.r, g_aParticle[nTexNum].Color.g, g_aParticle[nTexNum].Color.b, g_aParticle[nTexNum].Color.a );
    pVtx[ 3 + nTexNum * 4 ].color = D3DXCOLOR( g_aParticle[nTexNum].Color.r, g_aParticle[nTexNum].Color.g, g_aParticle[nTexNum].Color.b, g_aParticle[nTexNum].Color.a );

    //テクスチャ座標の設定
    pVtx[ 0 + nTexNum * 4 ].tex = D3DXVECTOR2 ( 0.0f, 0.0f );
    pVtx[ 1 + nTexNum * 4 ].tex = D3DXVECTOR2 ( 1.0f, 0.0f );
    pVtx[ 2 + nTexNum * 4 ].tex = D3DXVECTOR2 ( 0.0f, 1.0f );
    pVtx[ 3 + nTexNum * 4 ].tex = D3DXVECTOR2 ( 1.0f, 1.0f );
}

//*************************************************************************************************
// 弾の設定
//*************************************************************************************************
void SetParticle ( float Pos_x, float Pos_y, float Speed_x, float Speed_y, int nLife, float Color_r, float Color_g, float Color_b, float Color_a )
{
    for ( int nCntParticle = 0; nCntParticle < PARTICLE_MAX; nCntParticle++ )
    {
        if ( g_aParticle[nCntParticle].bUse == false )
        {
            g_aParticle[nCntParticle].Pos.x = Pos_x;
            g_aParticle[nCntParticle].Pos.y = Pos_y;
            g_aParticle[nCntParticle].Speed.x = Speed_x;
            g_aParticle[nCntParticle].Speed.y = Speed_y;
            g_aParticle[nCntParticle].nLife = nLife;
            g_aParticle[nCntParticle].Color.r = 0.5;
            g_aParticle[nCntParticle].Color.g = 0.5;
            g_aParticle[nCntParticle].Color.b = 0.5;
            g_aParticle[nCntParticle].Color.a = 0.5;
            g_aParticle[nCntParticle].bUse = true;
            break;
        }
    }
}

//*************************************************************************************************
// パーティクル情報の取得
//*************************************************************************************************
PARTICLE *GetParticle ( void )
{
    return &g_aParticle[0];
}