//-----------------------------------------
#include <stdio.h>
#include <math.h>
#define pi 3.1416
#define ID_TM_MAIN 100
#define INTERVAL 50
#define FLOORTHICK 150
#define SCALE (WndWidth/10.0)
void DrawFloor (int Thickness, int R, int G, int B);
class CBall
{
private:
double Radius, Mass, RInertia, ContactSpeed;
struct { double position; double speed; } Linear;
struct { double angle; double speed; } Angular;
struct { double Static; double kinetic; } Friction;
public:
CBall (double Radius, double Mass, double Lspeed, double Aspeed, double Fkinetic, double Fstatic = 0.50)
{
CBall::Radius = Radius;
CBall::Mass = Mass;
CBall::Linear.speed = Lspeed;
CBall::Linear.position = 0;
CBall::Angular.speed = Aspeed;
CBall::Angular.angle = 0;
Friction.kinetic = Fkinetic;
Friction.Static = Fstatic;
RInertia = (2.0/5.0)* pow(Radius, 2.0)* Mass;
};
~CBall (void)
{};
void Move (int Interval)
{
const double g = 9.80;
double dt = (double)Interval / 1000;
double Force;
ContactSpeed = Linear.speed + Radius* Angular.speed;
if(ContactSpeed > 0)
Force = -Mass* g* Friction.kinetic;
else if (ContactSpeed < 0)
Force = Mass* g* Friction.kinetic;
else if (ContactSpeed == 0)
Force = 0;
Linear.speed += Force / Mass* dt;
Angular.speed += Radius* Force / RInertia* dt;
Linear.position += Linear.speed* dt;
Angular.angle += Angular.speed* dt;
InvalidateRect(hWnd, NULL, TRUE);
};
void Draw (HDC hDC, int R, int G, int B, int LineWidth=2)
{
char Print [32];
sprintf(Print, "contact speed : %.2lf m/s", ContactSpeed);
TextOutA(hDC, 10, 60, (LPSTR)Print, strlen(Print));
sprintf(Print, "linear speed : %.2lf m/s", Linear.speed);
TextOutA(hDC, 10, 75, (LPSTR)Print, strlen(Print));
sprintf(Print, "angular speed : %.2lf rad/s", Angular.speed);
TextOutA(hDC, 10, 90, (LPSTR)Print, strlen(Print));
// Draw ball
HBRUSH MyBrush, OldBrush;
MyBrush = CreateSolidBrush(RGB(R, G, B));
OldBrush = (HBRUSH)SelectObject(hDC, MyBrush);
Ellipse(hDC, (Linear.position-Radius)*SCALE, -2*Radius*SCALE, (Linear.position+Radius)*SCALE, 0*SCALE);
SelectObject(hDC, OldBrush);
DeleteObject(MyBrush);
// Draw line
HPEN MyPen, OldPen;
MyPen = CreatePen(PS_DASH, LineWidth, RGB(192-R, 192-G, 192-B));
OldPen = (HPEN)SelectObject(hDC, MyPen);
MoveToEx(hDC, Linear.position*SCALE, -Radius*SCALE, NULL);
LineTo(hDC, (Linear.position + Radius*cos(Angular.angle))*SCALE, -(Radius*(1+sin(Angular.angle)))*SCALE);
SelectObject(hDC, OldPen);
DeleteObject(MyPen);
}
};
HDC hDC;
CBall Ball (/*Radius*/0.3, /*Mass*/1.0,
/*LinearSpeed*/0.0, /*AngularSpeed*/-5*pi, /*KineticCoefficient*/0.015);
LRESULT CALLBACK WndProc (HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
char Print [64];
switch(iMessage) {
case WM_CREATE :
return 0;
case WM_PAINT :
hDC = BeginPaint(hWnd, &ps);
SetViewportOrgEx(hDC, 0, WndHeight - FLOORTHICK, NULL);
DrawFloor(FLOORTHICK, 192, 192, 192);
Ball.Draw(hDC, 0, 0, 192);
sprintf(Print, "%s", "과베저장소 | www.kwabe.com");
SetTextAlign(hDC, TA_RIGHT);
TextOutA(hDC, WndWidth - 20, 90, (LPSTR)Print, strlen(Print));
EndPaint(hWnd, &ps);
return 0;
case WM_TIMER :
switch(wParam) {
case ID_TM_MAIN :
Ball.Move(INTERVAL);
break;
}
return 0;
case WM_RBUTTONDOWN :
SetTimer(hWnd, ID_TM_MAIN, INTERVAL, NULL);
return 0;
case WM_DESTROY :
KillTimer(hWnd, ID_TM_MAIN);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, iMessage, wParam, lParam);
}
void DrawFloor (int Thickness, int R, int G, int B)
{
HBRUSH MyBrush, OldBrush;
MyBrush = CreateSolidBrush(RGB(R, G, B));
OldBrush = (HBRUSH)SelectObject(hDC, MyBrush);
Rectangle(hDC, 0, 0, WndWidth, Thickness);
SelectObject(hDC ,OldBrush);
DeleteObject(MyBrush);
}
댓글 0