// ■伸縮する棒と二つの球 // 左ボタンクリックで大きな球の位置を指定。。 #include "myWin.h" #include "stdlib.h" #include "time.h" #include "math.h" #define frand()((double)rand()/(RAND_MAX+1)) typedef struct{ double X, Y;} point; typedef struct{ point Position, Velocity,Acc; double Mass; } mass; static double SpringLength; //バネの長さ static double Kfact; //バネ定数 static double Myu ; //粘性抵抗 static double Gravity;//重力 static mass P1;//質点1 static mass P2;//質点2 static point Force ;//力 static HDC hBuff; static HBITMAP hBM; //ビットマップ表示用 void drawLine(int X1, int Y1, int X2, int Y2, int Color, int bColor){//■バネ部分 HPEN pen=CreatePen(PS_SOLID, 3, Color) ; SelectObject(hBuff, pen) ; MoveToEx(hBuff,X1,Y1,NULL);LineTo(hBuff, X2, Y2); DeleteObject(pen); pen=CreatePen(PS_SOLID, 1, bColor) ; SelectObject(hBuff, pen) ; MoveToEx(hBuff,X1,Y1,NULL);LineTo(hBuff, X2, Y2); DeleteObject(pen); } void drawEllipse(int X1, int Y1, int X2, int Y2, int lColor, int bColor){//■ボール HPEN pen=CreatePen(PS_SOLID, 1, lColor) ; SelectObject(hBuff, pen) ; HBRUSH brush=CreateSolidBrush(bColor) ; SelectObject(hBuff, brush); Ellipse(hBuff,X1,Y1, X2,Y2) ; DeleteObject(brush) ; DeleteObject(pen); } void drawBox(int X1, int Y1, int X2, int Y2, int lColor, int bColor){// HPEN pen=CreatePen(PS_NULL, 1, lColor) ; SelectObject(hBuff, pen) ; HBRUSH brush=CreateHatchBrush(HS_FDIAGONAL, bColor); SelectObject(hBuff, brush); Rectangle(hBuff,X1,Y1, X2,Y2); DeleteObject(brush) ; DeleteObject(pen) ; pen=CreatePen(PS_SOLID,2,lColor) ;SelectObject(hBuff, pen); MoveToEx(hBuff,X1,Y1,NULL);LineTo(hBuff, X2, Y1); DeleteObject(pen); } void crearBitmap(){ //■ビットマップクリア SelectObject(hBuff,GetStockObject(NULL_PEN)); PatBlt(hBuff,0, 0,1000,400,WHITENESS); } void update(){//■変更 double DX = P1.Position.X - P2.Position.X; double DY = P1.Position.Y - P2.Position.Y; double DL = sqrt(DX * DX + DY * DY), HX = DX / DL, HY = DY / DL; double FL = -Kfact * (DL - SpringLength); Force.X = HX * FL, Force.Y = HY * FL; P1.Acc.X = Force.X * 0.5 / P1.Mass; P1.Acc.Y = Force.Y * 0.5 / P1.Mass; P2.Acc.X = -Force.X * 0.5 / P2.Mass; P2.Acc.Y = -Force.Y * 0.5 / P2.Mass; P1.Velocity.X = (P1.Acc.X + P1.Velocity.X) * (1 - Myu); P1.Velocity.Y = (P1.Acc.Y + P1.Velocity.Y + Gravity) * (1 - Myu); P2.Velocity.X = (P2.Acc.X + P2.Velocity.X) * (1 - Myu); P2.Velocity.Y = (P2.Acc.Y + P2.Velocity.Y + Gravity) * (1 - Myu); P1.Position.X = P1.Position.X + P1.Velocity.X; P1.Position.Y = P1.Position.Y + P1.Velocity.Y; P2.Position.X = P2.Position.X + P2.Velocity.X; P2.Position.Y = P2.Position.Y + P2.Velocity.Y; if(P1.Position.Y > 245){ P1.Position.Y = 245; P1.Velocity.Y = -P1.Velocity.Y; if(abs(P1.Velocity.Y)>2) Beep(700,25); } if(P2.Position.Y > 255){ P2.Position.Y = 255;P2.Velocity.Y = -P2.Velocity.Y; if(abs(P2.Velocity.Y)>2) Beep(1400,25); } } void initData(){//初期設定 P1.Mass = 1500; P2.Mass = 200; SpringLength = 100; Myu = 0.02; Kfact = 10; Gravity = 0.98; srand((int)time(NULL)); P1.Position.Y = 10; P1.Position.X = 300; P2.Position.Y = 0;P2.Position.X = 20; } void display(){//■表示 crearBitmap(); drawBox(0,265, 500, 300, 0,0x55FF); int X1 = (int)P1.Position.X, Y1 = (int)P1.Position.Y; int X2 = (int)P2.Position.X, Y2 = (int)P2.Position.Y; drawLine(X1+10, Y1+10, X2+5, Y2+5, 0x77, 0x7777); drawEllipse(X1,Y1,X1+20,Y1+20, 0, 0xFF7700); drawEllipse(X2,Y2,X2+10,Y2+10, 0, 0xFF); } void procTimer(HWND hw, WPARAM wp,LPARAM lp){ //■タイマー処理 double X1 = P1.Position.X, Y1 = P1.Position.Y; double X2 = P2.Position.X, Y2 = P2.Position.Y; if(abs(P1.Velocity.X) < 0.8 && abs(P1.Velocity.Y) < 0.8 && abs(P2.Velocity.X) < 0.8 && abs(P2.Velocity.Y) < 0.8 && P1.Position.Y > 244 && P2.Position.Y > 254 ) KillTimer(hw,1); update(); display(); InvalidateRect(hw,NULL,TRUE); } void procLButtonDown(HWND hw, WPARAM wp,LPARAM lp){ //■左ボタン処理 P1.Position.X=(double)(LOWORD(lp))-10; P1.Position.Y=(double)(HIWORD(lp))-10; display(); InvalidateRect(hw,NULL,TRUE); SetTimer(hw,1,50,NULL); //画面キャプチャするときはここをコメント } void procRButtonDown(HWND hw, WPARAM wp,LPARAM lp){ //■左ボタン処理 update();//画面キャプチャするときは右ボタンで次の画面に進む(タイマーの替わり) display(); InvalidateRect(hw,NULL,TRUE); } void initBitmap(HWND hw){ //■ビットマップ初期設定 HDC hdc=GetDC(hw); hBM=CreateCompatibleBitmap(hdc,1000,400); hBuff=CreateCompatibleDC(hdc); SelectObject(hBuff,hBM); crearBitmap(); ReleaseDC(hw,hdc); } void procCreate(HWND hw, WPARAM wp,LPARAM lp){ //■Create時処理 SetWindowText(hw,TEXT("伸縮する棒と2つの球(左クリックで大きな球の位置指定)")); MoveWindow(hw,0,0,500,400,TRUE); initBitmap(hw); initData();display(); InvalidateRect(hw,NULL,TRUE); SetTimer(hw,1,50,NULL); //画面キャプチャするときはここをコメント } void procPaint(HWND hw, WPARAM wp,LPARAM lp){ //■Paint時処理 PAINTSTRUCT ps; HDC hdc=BeginPaint(hw, &ps); BitBlt(hdc, 0,0,1000,400,hBuff,0,0,SRCCOPY); EndPaint(hw,&ps); } LRESULT CALLBACK WndProc(HWND hw, UINT msg, WPARAM wp,LPARAM lp){//■Window Procedure switch(msg){ case WM_DESTROY : PostQuitMessage(0) ; return 0; case WM_CREATE : procCreate(hw,wp,lp) ; return 0; case WM_PAINT : procPaint(hw,wp,lp) ; return 0; case WM_TIMER : procTimer(hw,wp,lp) ; return 0; case WM_LBUTTONDOWN : procLButtonDown(hw,wp,lp) ; break; case WM_RBUTTONDOWN : procRButtonDown(hw,wp,lp) ; break; } return DefWindowProc(hw,msg,wp,lp); }