2个二维运动图形方面的模拟程序
寒假写的代码第一个是模拟泊松运动核心代码:BOOL CCollisionaDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
ShowWindow(SW_MAXIMIZE);
CClientDC tempdc(this);
MYDC.CreateCompatibleDC(&tempdc);
RECT rt;
GetClientRect(&rt);
bmp.CreateCompatibleBitmap(&tempdc,rt.right,rt.bottom);
MYDC.SelectObject(&bmp);
CBrush brush;
brush.CreateSolidBrush(RGB(255,255,255));
MYDC.FillRect(&rt,&brush);
srand(time(NULL));
//初始化小球
for(int i=0;i<BALLNUM;i++)
{
ball.x=rand()%rt.right;
ball.y=rand()%rt.bottom;
ball.deltax=rand()%11-5;
ball.deltax+=(ball.deltax>0)?1:-1;
ball.deltay=rand()%11-5;
ball.deltay+=(ball.deltay>0)?1:-1;
ball.deltay=1;
ball.xcount=0;
ball.ycount=0;
ball.radius=rand()%MAXRADIU+40;
ball.color=RGB(rand()&0xff,rand()&0xff,rand()&0xff);
ball.iscollision=FALSE;
}
// ball.x=200;
// ball.x=200;
// ball.y=100;
// ball.y=500;
// ball.deltax=100;
// ball.deltax=100;
// ball.deltay=1;
// ball.deltay=2;
// ball.xcount=0;
// ball.ycount=0;
// ball.xcount=0;
// ball.ycount=0;
// ball.radius=20;
// ball.radius=20;
// ball.color=RGB(255,0,0);
// ball.color=RGB(0,255,0);
// ball.iscollision=FALSE;
// ball.iscollision=FALSE;
SetTimer(0,10,NULL);
return TRUE; // return TRUE unless you set the focus to a control
}
void CCollisionaDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
CDialog::OnSysCommand(nID, lParam);
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CCollisionaDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
RECT rt;
GetClientRect(&rt);
CBrush nulbrush(RGB(255,255,255));
MYDC.FillRect(&rt,&nulbrush);
CClientDC dc(this);
for(int i=0;i<BALLNUM;i++)
{
CBrush brush(ball.color);
MYDC.SelectObject(&brush);
MYDC.Ellipse(ball.x-ball.radius,ball.y-ball.radius,ball.x+ball.radius,ball.y+ball.radius);
brush.DeleteObject();
}
dc.BitBlt(0,0,rt.right,rt.bottom,&MYDC,0,0,SRCCOPY);
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CCollisionaDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CCollisionaDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
RECT rt;
GetClientRect(&rt);
int i,j;
//做移动
for(i=0;i<BALLNUM;i++)
{
ball.xcount++;
ball.ycount++;
if(ball.deltax > 0)
{
if(ball.xcount >= ball.deltax)
{
ball.x+=2;
ball.xcount=0;
}
}
else
{
if(ball.xcount >= -ball.deltax)
{
ball.x-=2;
ball.xcount=0;
}
}
if(ball.deltay > 0)
{
if(ball.ycount >= ball.deltay)
{
ball.y+=2;
ball.ycount=0;
}
}
else
{
if(ball.ycount >= -ball.deltay)
{
ball.y-=2;
ball.ycount=0;
}
}
//判断边界
#define MARGIN 0
if(ball.x-ball.radius < MARGIN)
{
ball.x=MARGIN+ball.radius;
if(ball.deltax<0)
ball.deltax=-ball.deltax;
}
else if(ball.x+ball.radius > rt.right-MARGIN)
{
ball.x=rt.right-MARGIN-ball.radius;
if(ball.deltax>0)
ball.deltax=-ball.deltax;
}
if(ball.y-ball.radius < MARGIN)
{
ball.y=MARGIN+ball.radius;
if(ball.deltay<0)
ball.deltay=-ball.deltay;
}
else if(ball.y+ball.radius > rt.bottom-MARGIN)
{
ball.y=rt.bottom-MARGIN-ball.radius;
if(ball.deltay>0)
ball.deltay=-ball.deltay;
}
}
//判断碰撞
for(i=0;i < BALLNUM;i++)
{
int count=0;
for(j=0;j != i && j < BALLNUM;j++)
{
if((ball.x-ball.x)*(ball.x-ball.x)+(ball.y-ball.y)*(ball.y-ball.y) <= (ball.radius+ball.radius)*(ball.radius+ball.radius))
{ //碰撞以后利用水平方向以及垂直方向动量守恒定律和能量守恒定律
//f1'=(R1*R1*R1*f2+2*R2*R2*R2*f1-R2*R2*R2*f2)/
//f2'=(2*R1*R1*R1*f2-R1*R1*R1*f1+2*R2*R2*R2*f1)/
if(!ball.iscollision || !ball.iscollision)
{
int r31=ball.radius*ball.radius*ball.radius;//R1*R1*R1
int r32=ball.radius*ball.radius*ball.radius;//R2*R2*R2
double newxcount1=(ball.deltax*ball.deltax*(r31+r32))/float(r31*ball.deltax+2*r32*ball.deltax-r32*ball.deltax);
double newycount1=(ball.deltay*ball.deltay*(r31+r32))/float(r31*ball.deltay+2*r32*ball.deltay-r32*ball.deltay);
double newxcount2=(ball.deltax*ball.deltax*(r31+r32))/float(2*r31*ball.deltax-r31*ball.deltax+r32*ball.deltax);
double newycount2=(ball.deltay*ball.deltay*(r31+r32))/float(2*r31*ball.deltay-r31*ball.deltay+r32*ball.deltay);
if(newxcount1 > 100)
{
ball.deltax=100;
}
else if(newxcount1 >= 1)
{
ball.deltax=newxcount1;
}
else if(newxcount1 >= 0)
{
ball.deltax=1;
}
else if(newxcount1 > -1)
{
ball.deltax=-1;
}
else if(newxcount1 >= -100)
{
ball.deltax=newxcount1;
}
else
{
ball.deltax=-100;
}
if(newycount1 > 100)
{
ball.deltay=100;
}
else if(newycount1 >= 1)
{
ball.deltay=newycount1;
}
else if(newycount1 >= 0)
{
ball.deltay=1;
}
else if(newycount1 > -1)
{
ball.deltay=-1;
}
else if(newycount1 >= -100)
{
ball.deltay=newycount1;
}
else
{
ball.deltay=-100;
}
if(newxcount2 > 100)
{
ball.deltax=100;
}
else if(newxcount2 >= 1)
{
ball.deltax=newxcount2;
}
else if(newxcount2 >= 0)
{
ball.deltax=1;
}
else if(newxcount2 > -1)
{
ball.deltax=-1;
}
else if(newxcount2 >= -100)
{
ball.deltax=newxcount2;
}
else
{
ball.deltax=-100;
}
if(newycount2 > 100)
{
ball.deltay=100;
}
else if(newycount2 >= 1)
{
ball.deltay=newycount2;
}
else if(newycount2 >= 0)
{
ball.deltay=1;
}
else if(newycount2 > -1)
{
ball.deltay=-1;
}
else if(newycount2 >= -100)
{
ball.deltay=newycount2;
}
else
{
ball.deltay=-100;
}
ball.iscollision=TRUE;
ball.iscollision=TRUE;
}
break;
}
else
{
count++;
}
}
if(count < BALLNUM-1)
ball.iscollision=TRUE;
else
ball.iscollision=FALSE;
}
Invalidate(FALSE);
CDialog::OnTimer(nIDEvent);
}
第二个是模拟碰撞
这个有bug,0xAA55可以帮我看看
核心代码:
BOOL CPosonDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
ShowWindow(SW_MAXIMIZE);
CClientDC tempdc(this);
MYDC.CreateCompatibleDC(&tempdc);
RECT rt;
GetClientRect(&rt);
bmp.CreateCompatibleBitmap(&MYDC,rt.right,rt.bottom);
MYDC.SelectObject(&bmp);
CBrush brush(RGB(255,255,255));
MYDC.FillRect(&rt,&brush);
for(int i=0;i<100;i++)
{
pt.x=rand()%rt.right;
pt.y=rand()%rt.bottom;
}
SetTimer(0,1,NULL);
return TRUE; // return TRUE unless you set the focus to a control
}
void CPosonDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CPosonDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
//CDialog::OnPaint();
RECT rt;
GetClientRect(&rt);
CBrush nulbrush(RGB(255,255,255));
MYDC.FillRect(&rt,&nulbrush);
CPaintDC dc(this);
CBrush brush(RGB(0,0,0));
MYDC.SelectObject(&brush);
for(int i=0;i<100;i++)
{
MYDC.Ellipse(pt.x-5,pt.y-5,pt.x+5,pt.y+5);
}
dc.BitBlt(0,0,rt.right,rt.bottom,&MYDC,0,0,SRCCOPY);
brush.DeleteObject();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CPosonDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CPosonDlg::OnClose()
{
// TODO: Add your message handler code here and/or call default
bmp.DeleteObject();
CDialog::OnClose();
}
void CPosonDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
RECT rt;
GetClientRect(&rt);
for(int i=0;i<100;i++)
{
int len=rand()%10;
switch(rand()%4)
{
case 0:
pt.y-=len;
if(pt.y < 0)
{
pt.y=rand()%rt.bottom;
}
break;
case 1:
pt.y+=len;
if(pt.y >= rt.bottom)
{
pt.y=rand()%rt.bottom;
}
break;
case 2:
pt.x+=len;
if(pt.x >= rt.right)
{
pt.x=rand()%rt.right;
}
break;
case 3:
pt.x-=len;
if(pt.x < 0)
{
pt.x=rand()%rt.right;
}
break;
}
}
Invalidate(FALSE);
CDialog::OnTimer(nIDEvent);
}
页:
[1]