#include "DxLib.h"
#include "matrixlib.h"

//摩擦係数を変化させる。


//-----------------------------初期設定、宣言----------------------------

const float PIE = 3.1415926;  //πの値
const float GMS = 9.80665;  //重力加速度の値
float frametime;     //1秒当たりの呼び出し回数を計測

float ToRadian(float deg){
    return(deg*PIE/180); //度数をラジアンに変換
    }
    
Point2D ground[2]={{-100,240},{740,240}}; //地面の初期座標
Point2D sled[4] = {{0,220},{40,220},{40,240},{0,240}}; //ソリの初期座標
Point2D groundr[2],sledr[4];  //変形後の座標
    
int angle = 0; //地面の角度
const float LIM_FRIC=0.6;//静止摩擦係数
float KIN_FRIC=0.4;//動摩擦係数
const float MASS=60;//ソリの質量
int flag=0;//初期フラグは0
float speedx=0;//ソリの速度

//-------------------------グラフ表示の宣言------------------------------------
int curidx=0;
float curdist=0;
float graphary[600];


//-------------ここに画面書き換えの処理を書いていく--------------------------    
void PhysicsDraw(){
    
for(int i=0;i<curidx;i=i+1){
    DrawLine(i,480-graphary[i]*5,i,480,GetColor(255,255,255));}//グラフの表示    


float r =ToRadian(angle);//角度をラジアンに変換してrに代入

Matrix33 m=MultiMatrix(
    GetTranslateMatrix(320,240),GetRotateMatrix(r)); //移動行列×回転行列
    
m=MultiMatrix(m,GetTranslateMatrix(-320,-240)); //(移動行列×回転行列)×移動行列
    
for(int i=0;i<2;i=i+1)groundr[i]=Transform2D(ground[i],m);//元の座標を行列mで変形
for(int i=0;i<4;i=i+1)sledr[i]=Transform2D(sled[i],m);//元の座標を行列mで変形
    
DrawLine(groundr[0].x,groundr[0].y,groundr[1].x,groundr[1].y,GetColor(255,255,255));
//変形後の座標を繋げる

for(int i=0;i<3;i=i+1){
DrawLine(sledr[i].x,sledr[i].y,sledr[i+1].x,sledr[i+1].y,GetColor(0,255,255));
        }
        
DrawLine(sledr[3].x,sledr[3].y,sledr[0].x,sledr[0].y,GetColor(0,255,255));
//四角形の変形後の頂点の座標を繋げる    
    
int key=GetJoypadInputState(DX_INPUT_KEY_PAD1);//キーで動かせる関数
    
if(key&PAD_INPUT_LEFT)angle = angle-1;//左キーで角度変更
if(key&PAD_INPUT_RIGHT)angle=angle+1;//右キーで角度変更
angle=(angle+360)%360;//角度が360度を越えないようにする。
clsDx();
printfDx("角度%d度\n",angle);//角度表示

if(flag==0){
    float r=ToRadian(angle);
    float slide_f=GMS*MASS*sin(r);//ソリに働く重力:mg*sin(r)
    float normal_f=-GMS*MASS*cos(r);//ソリに働く垂直抗力:N=mg*cos(r)
    float lfric_f=normal_f*LIM_FRIC;//ソリに働く最大静止摩擦力:μ*N
    
    if(fabs(slide_f)>fabs(lfric_f))flag=1;//重力が静止摩擦力を超えたら滑り出す
    
    
    //printfDx("重力%f 静止摩擦力%f",slide_f,lfric_f);    
    }
    
if(flag==1){

    if(sledr[0].x>=200 && sledr[0].x<=300){KIN_FRIC=0.9;
    DrawLine(groundr[0].x,groundr[0].y,groundr[1].x,groundr[1].y,GetColor(100,100,255));
    }
    else KIN_FRIC=0.4;//ソリの位置によって、動摩擦係数と地面の色を変える。
    

    float r=ToRadian(angle);//角度をラジアンに変換
    float slide_f=GMS*MASS*sin(r);//ソリに働く重力:mg*sin(r)
    float normal_f=-GMS*MASS*cos(r);//ソリに働く垂直抗力:N=mg*cos(r)
    float kfric_f=normal_f*KIN_FRIC;//ソリに働く動摩擦力:μ*N
    
    //DrawLine(sledr[2].x,sledr[2].y,groundr[1].x/2,groundr[1].y/2,GetColor(250,0,0));
    
    
    if(speedx==0 && slide_f<0)kfric_f=-kfric_f;
    //もし速度が0かつ重力が負(左向き)になったら動摩擦力の向きを反転
    if(speedx<0)kfric_f=-kfric_f;
    //もし速度が負(左向き)であれば、動摩擦力の向きは正(右向き)
    
    float fslide_f=slide_f+kfric_f;//合力
    float a=fslide_f/MASS;//F=Maより
    float d=speedx*frametime+(a*frametime*frametime)/2;//d=vt+0.5*a*t^2
    speedx=speedx+a*frametime;//v=v+at
    
    for(int i=0;i<4;i=i+1)sled[i].x=sled[i].x+d;//座標の変更
    
    if((kfric_f<0 && speedx<0)||(kfric_f>0 && speedx>0)){
        flag=0; speedx=0;} //静止の条件

//-------------------------グラフの記録----------------------------------    
     //curdist=curdist+d;
     //graphary[curidx]=curdist;
     //curidx=curidx+1;
     //if(curidx>=600){curdist=0;}    
//----------------------------------------------------------------------------    
    
     clsDx();
     printfDx("動摩擦力%f 重力%f 加速度%f 速度%f\n",kfric_f,slide_f,a,speedx);
     printfDx("動摩擦係数%f",KIN_FRIC);
    }
    }      



// --------------------------時間設定-----------------------------------------                                    
    
    
void SetFrameTime(){
int s=GetNowCount();
for(int i=0;i<30;i=i+1){
    ScreenFlip();
    int e= GetNowCount();
    frametime = frametime + e - s;
    s=e;
            }
            
frametime = frametime/30/1000;
printfDx("%f",frametime);
}

//-------------------------------------------------------------------------

int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lpC, int nC)
{
    ChangeWindowMode(TRUE);  //ウィンドウモードで起動
    if(DxLib_Init() == -1)return(-1);//DXライブラリ初期化
    DrawBox(0, 0, 120, 120, 65535, TRUE);
    
     SetDrawScreen(DX_SCREEN_BACK);
     SetFrameTime();
     while(ProcessMessage()==0 && CheckHitKey(KEY_INPUT_ESCAPE)==0){
         ClsDrawScreen();
        PhysicsDraw();
        ScreenFlip();
     }

    DxLib_End();//DXライブラリ終了処理
    return(0);//終了
    
}