下次X轴坐标=在X轴上的速度分量+当前X轴坐标
下次Y轴坐标=在Y轴上的速度分量+当前Y轴坐标
2.加速运动
加速运动就是具有加速度的运动,它的速度会随着时间而改变。
公式我们可以表示如下:
V=Vo+at
这是高中物理运动学里最基本的公式了~其中,V为当前速度,V0为初速度,a为加速度,t为物体从速度为V0时记起的时间
那么同样将此速度分解,我们得到:
Vx=Vxo+axt
Vy=Vyo+ayt
我们设时间间隔t=1
则我们可以推算出加入加速度之后,物体下一刻所在的位置:
Sx=Sxo+Vx*1
Sy=Syo+Vy*1
将这两个公式运用到我们的代码里面就可以实现加速运动的模拟了。
这些知识都是非常基础的,实现方式都非常的简单,但是还有颇多细节,希望好学的你能多思考,多挖掘。
二、在一个完整的demo中将知识融会贯通
了解了基本运动学的原理之后,下面我们就来一起看下这节笔记里面的demo,在实例中将本节知识融会贯通。
这节的demo是一个匀速运动,碰到窗口边缘时就进行反弹的“愤怒的小鸟”,非常的可爱。
浅墨感觉学完这节后大家就可以自己实现win7里的那个”多彩气泡“的屏幕保护程序,有兴趣的朋友可以试着写写看,调用一些Windows API函数就来了。
好了,我们依旧贴出详细注释的源代码~
#div_code img{border:0px;}<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--> [cpp] view plaincopyprint?
#include " stdafx.h "
#include
// 全局变量声明
HINSTANCE hInst;
HBITMAP bg,bird;
HDC hdc,mdc,bufdc;
HWND hWnd;
DWORD tPre,tNow,tCheck;
RECT rect; // 定义一个RECT结构体,用于储存内部窗口区域的坐标
int x = 50 ,y = 50 ,vx = 15 ,vy = 15 ; // x与y是小鸟在窗口中的贴图坐标,vx与vy为小鸟在x与y轴运动的速度分量
// 全局函数声明
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int );
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void MyPaint(HDC hdc);
//**** WinMain函数,程序入口点函数 **************************************
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
MyRegisterClass(hInstance);
// 初始化
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE ;
}
// 消息循环
GetMessage( & msg, NULL , NULL , NULL ); // 初始化msg
while ( msg.message! = WM_QUIT )
{
if ( PeekMessage( & msg, NULL , 0 , 0 ,PM_REMOVE) )
{
TranslateMessage( & msg );
DispatchMessage( & msg );
}
else
{
tNow = GetTickCount();
if (tNow - tPre >= 40 )
MyPaint(hdc);
}
}
return msg.wParam;
}
//**** 设计一个窗口类,类似填空题,使用窗口结构体 *********************
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style. = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0 ;
wcex.cbWndExtra = 0 ;
wcex.hInstance = hInstance;
wcex.hIcon = NULL ;
wcex.hCursor = NULL ;
wcex.hCursor = LoadCursor( NULL , IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1 );
wcex.lpszMenuName = NULL ;
wcex.lpszClassName = " canvas " ;
wcex.hIconSm = NULL ;
return RegisterClassEx( & wcex);
}
//**** 初始化函数 *************************************
// 加载位图资源并取得内部窗口区域信息
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HBITMAP bmp;
hInst = hInstance;
hWnd = CreateWindow( " canvas " , " 浅墨的窗口 " , WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0 , CW_USEDEFAULT, 0 , NULL , NULL , hInstance, NULL );
if (!hWnd)
{
return FALSE ;
}
MoveWindow(hWnd, 10 , 10 , 600 , 450 , true );
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
hdc = GetDC(hWnd);
mdc = CreateCompatibleDC(hdc);
bufdc = CreateCompatibleDC(hdc);
bmp = CreateCompatibleBitmap(hdc, 640 , 480 );
SelectObject(mdc,bmp);
bg = (HBITMAP)LoadImage( NULL , " bg.bmp " ,IMAGE_BITMAP, 640 , 480 ,LR_LOADFROMFILE);
bird = (HBITMAP)LoadImage( NULL , " angrybird.bmp " ,IMAGE_BITMAP, 120 , 60 ,LR_LOADFROMFILE);
GetClientRect(hWnd, & rect); // 取得内部窗口区域的大小
MyPaint(hdc);
return TRUE ;
}
//**** 自定义绘图函数 *********************************
// 1 .进行窗口贴图
// 2 .计算小鸟贴图坐标并判断小鸟是否碰到窗口边沿
void MyPaint(HDC hdc)
{
SelectObject(bufdc,bg);
BitBlt(mdc, 0 , 0 , 640 , 480 ,bufdc, 0 , 0 ,SRCCOPY);
SelectObject(bufdc,bird);
BitBlt(mdc,x,y, 60 , 60 ,bufdc, 60 , 0 ,SRCAND);
BitBlt(mdc,x,y, 60 , 60 ,bufdc, 0 , 0 ,SRCPAINT);
BitBlt(hdc, 0 , 0 , 640 , 480 ,mdc, 0 , 0 ,SRCCOPY);
// 计算X轴贴图坐标与速度
x += vx;
if (x <= 0 )
{
x = 0 ;
vx = - vx;
}
else if (x >= rect.right - 60 )
{
x = rect.right - 60 ;
vx = - vx;
}
// 计算Y轴贴图坐标与速度
y += vy;
if (y <= 0 )
{
y = 0 ;
vy = - vy;
}
else if (y >= rect.bottom - 60 )
{
y = rect.bottom - 60 ;
vy = - vy;
}
tPre = GetTickCount(); // 记录此次绘图时间
}
**** 消息处理函数 ***********************************
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_KEYDOWN: // 按键消息
if (wParam == VK_ESCAPE) // 按下【Esc】键
PostQuitMessage( 0 );
break;
case WM_DESTROY: // 窗口结束消息
DeleteDC(mdc);
DeleteDC(bufdc);
DeleteObject(bg);
DeleteObject(bird);
ReleaseDC(hWnd,hdc);
PostQuitMessage( 0 );
break;
default: // 其他消息
return DefWindowProc(hWnd, message, wParam, lParam);
}
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--> [cpp] view plaincopyprint?
#include " stdafx.h "
#include
// 全局变量声明
HINSTANCE hInst;
HBITMAP bg,bird;
HDC hdc,mdc,bufdc;
HWND hWnd;
DWORD tPre,tNow,tCheck;
RECT rect; // 定义一个RECT结构体,用于储存内部窗口区域的坐标
int x = 50 ,y = 50 ,vx = 15 ,vy = 15 ; // x与y是小鸟在窗口中的贴图坐标,vx与vy为小鸟在x与y轴运动的速度分量
// 全局函数声明
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int );
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void MyPaint(HDC hdc);
//**** WinMain函数,程序入口点函数 **************************************
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
MyRegisterClass(hInstance);
// 初始化
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE ;
}
// 消息循环
GetMessage( & msg, NULL , NULL , NULL ); // 初始化msg
while ( msg.message! = WM_QUIT )
{
if ( PeekMessage( & msg, NULL , 0 , 0 ,PM_REMOVE) )
{
TranslateMessage( & msg );
DispatchMessage( & msg );
}
else
{
tNow = GetTickCount();
if (tNow - tPre >= 40 )
MyPaint(hdc);
}
}
return msg.wParam;
}
//**** 设计一个窗口类,类似填空题,使用窗口结构体 *********************
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style. = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0 ;
wcex.cbWndExtra = 0 ;
wcex.hInstance = hInstance;
wcex.hIcon = NULL ;
wcex.hCursor = NULL ;
wcex.hCursor = LoadCursor( NULL , IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1 );
wcex.lpszMenuName = NULL ;
wcex.lpszClassName = " canvas " ;
wcex.hIconSm = NULL ;
return RegisterClassEx( & wcex);
}
//**** 初始化函数 *************************************
// 加载位图资源并取得内部窗口区域信息
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HBITMAP bmp;
hInst = hInstance;
hWnd = CreateWindow( " canvas " , " 浅墨的窗口 " , WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0 , CW_USEDEFAULT, 0 , NULL , NULL , hInstance, NULL );
if (!hWnd)
{
return FALSE ;
}
MoveWindow(hWnd, 10 , 10 , 600 , 450 , true );
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
hdc = GetDC(hWnd);
mdc = CreateCompatibleDC(hdc);
bufdc = CreateCompatibleDC(hdc);
bmp = CreateCompatibleBitmap(hdc, 640 , 480 );
SelectObject(mdc,bmp);
bg = (HBITMAP)LoadImage( NULL , " bg.bmp " ,IMAGE_BITMAP, 640 , 480 ,LR_LOADFROMFILE);
bird = (HBITMAP)LoadImage( NULL , " angrybird.bmp " ,IMAGE_BITMAP, 120 , 60 ,LR_LOADFROMFILE);
GetClientRect(hWnd, & rect); // 取得内部窗口区域的大小
MyPaint(hdc);
return TRUE ;
}
//**** 自定义绘图函数 *********************************
// 1 .进行窗口贴图
// 2 .计算小鸟贴图坐标并判断小鸟是否碰到窗口边沿
void MyPaint(HDC hdc)
{
SelectObject(bufdc,bg);
BitBlt(mdc, 0 , 0 , 640 , 480 ,bufdc, 0 , 0 ,SRCCOPY);
SelectObject(bufdc,bird);
BitBlt(mdc,x,y, 60 , 60 ,bufdc, 60 , 0 ,SRCAND);
BitBlt(mdc,x,y, 60 , 60 ,bufdc, 0 , 0 ,SRCPAINT);
BitBlt(hdc, 0 , 0 , 640 , 480 ,mdc, 0 , 0 ,SRCCOPY);
// 计算X轴贴图坐标与速度
x += vx;
if (x <= 0 )
{
x = 0 ;
vx = - vx;
}
else if (x >= rect.right - 60 )
{
x = rect.right - 60 ;
vx = - vx;
}
// 计算Y轴贴图坐标与速度
y += vy;
if (y <= 0 )
{
y = 0 ;
vy = - vy;
}
else if (y >= rect.bottom - 60 )
{
y = rect.bottom - 60 ;
vy = - vy;
}
tPre = GetTickCount(); // 记录此次绘图时间
}
**** 消息处理函数 ***********************************
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_KEYDOWN: // 按键消息
if (wParam == VK_ESCAPE) // 按下【Esc】键
PostQuitMessage( 0 );
break;
case WM_DESTROY: // 窗口结束消息
DeleteDC(mdc);
DeleteDC(bufdc);
DeleteObject(bg);
DeleteObject(bird);
ReleaseDC(hWnd,hdc);
PostQuitMessage( 0 );
break;
default: // 其他消息
return DefWindowProc(hWnd, message, wParam, lParam);
}
转载于:http://blog.itpub.net/27212986/viewspace-739026/