一、 計算機角色的簡單動畫
先是使用Windows本身定時器創建程序的代碼:
#include "stdafx.h"
#include "MyGameFrame.h"
#include <stdio.h>
// 全局變量:
HINSTANCE hInst;
HWND hWnd;
HDC hdc, mdc;
HBITMAP horse[8]; //圖像位圖
int num; //當前圖像幀數
// 此代碼模塊中包含的函數的前向聲明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitWindow(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// 初始化全局字符串
MyRegisterClass(hInstance);
// 執行應用程序初始化:
if (!InitWindow(hInstance, nCmdShow))//初始化窗口
{
return FALSE;//如果不成功則返回FALSE,並退出程序
}
MSG msg; //創建消息類對象
char filename[20] = "";
int i;
hdc = GetDC(hWnd);
mdc = CreateCompatibleDC(hdc);
//加載位圖
for (i = 0; i<8; i++) {
sprintf_s(filename, "horse%d.bmp", i);
horse[i] = (HBITMAP)LoadImage(NULL, filename, IMAGE_BITMAP, 405, 300, LR_LOADFROMFILE);
}
num = 0;
//創建定時器
SetTimer(hWnd, 1, 60, NULL);
SelectObject(mdc, horse[num]);
BitBlt(hdc, 0, 0, 405, 300, mdc, 0, 0, SRCCOPY);
num++;
PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);//賦初值
while (msg.message != WM_QUIT) //進入遊戲消息循環:
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg); //獲得遊戲玩家輸入的消息;
DispatchMessage(&msg);//分配玩家消息並響應用戶消息。
}
}
return (int)msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex =
{
wcex.cbSize = sizeof(WNDCLASSEX),
CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW,
WndProc,0,0,
hInstance,
LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYGAMEFRAME)),
LoadCursor(NULL, IDC_ARROW),
(HBRUSH)(COLOR_WINDOW + 1),NULL,
_T("GameFrame"),
LoadIcon(NULL,MAKEINTRESOURCE(IDI_SMALL))
};
return RegisterClassEx(&wcex);
}
BOOL InitWindow(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 將實例句柄存儲在全局變量中
hWnd = CreateWindow
(
_T("GameFrame"),
_T("遊戲框架"),
WS_OVERLAPPEDWINDOW^WS_THICKFRAME^WS_MAXIMIZEBOX,//普通樣式,不能改變大小,不能最大化
CW_USEDEFAULT, CW_USEDEFAULT, 405, 300, nullptr, nullptr, hInstance, nullptr
);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg) //判斷消息
{
case WM_CREATE:
//執行初始化代碼
return(0);
break;
case WM_TIMER:
if (num == 8)
num = 0;
SelectObject(mdc, horse[num]);
BitBlt(hdc, 0, 0, 405, 300, mdc, 0, 0, SRCCOPY);
num++;
break;
case WM_DESTROY:
DeleteDC(mdc);
ReleaseDC(hWnd, hdc);
for (int i = 0; i<8; i++)
DeleteObject(horse[i]);
KillTimer(hWnd, 1);
PostQuitMessage(0);
break;
default:
break;
}
return (DefWindowProc(hwnd, msg, wparam, lparam));
}
動畫效果如下
二、接下來是繪製計算機角色的循環動畫
使用遊戲運行時間產生事件消息的代碼:
首先我們需要在全局變量上添加
//DWORD全稱Double Word,是指註冊表的鍵值,每個word爲2個字節的長度,DWORD 雙字即爲4個字節,每個字節是8位,共32位。
DWORD tNow,tPre; //當前時間與結束時間
刪除
//創建定時器
SetTimer(hWnd, 1, 60, NULL);
將消息循環函數更改爲
while (msg.message != WM_QUIT) //進入遊戲消息循環:
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg); //獲得遊戲玩家輸入的消息;
DispatchMessage(&msg);//分配玩家消息並響應用戶消息。
}
else
{
tNow = GetTickCount(); //取得目前時間
if (tNow - tPre >= 40) { //可在while循環外設置tpre初值
if (num == 8) num = 0;
SelectObject(mdc, horse[num]);
BitBlt(hdc, 0, 0, 405, 300, mdc, 0, 0, SRCCOPY);
tPre = GetTickCount(); //取得結束時間
num++;
}
}
}
刪除WndProc()函數中的
Case VM_TIMER相關處理內容
case WM_TIMER:
if (num == 8)
num = 0;
SelectObject(mdc, horse[num]);
BitBlt(hdc, 0, 0, 405, 300, mdc, 0, 0, SRCCOPY);
num++;
break;
以及刪除VM_DESTROY中
KillTimer(hWnd, 1);
運行結果同定時器處理結果。
三、接下來是繪製計算機角色的透明動畫
#include "stdafx.h"
#include "MyGameFrame.h"
#include <stdio.h>
// 全局變量:
HINSTANCE hInst;
HWND hWnd;
HDC hdc, mdc;
HBITMAP bmp; //
HBITMAP horse; //圖像位圖
HBITMAP bg; //背景
int num; //當前圖像幀數
//DWORD全稱Double Word,是指註冊表的鍵值,每個word爲2個字節的長度,DWORD 雙字即爲4個字節,每個字節是8位,共32位。
DWORD tNow, tPre; //當前時間與結束時間
//爲了防止遊戲畫面更新時出現透明貼圖過程中產生的閃爍現象。製作透明動畫必須在一個暫存的內存DC上完成每一張走動圖的透明然後再貼到窗口上。
HDC bufdc;
// 此代碼模塊中包含的函數的前向聲明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitWindow(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// 初始化全局字符串
MyRegisterClass(hInstance);
// 執行應用程序初始化:
if (!InitWindow(hInstance, nCmdShow))//初始化窗口
{
return FALSE;//如果不成功則返回FALSE,並退出程序
}
MSG msg; //創建消息類對象
char filename[20] = "";
hdc = GetDC(hWnd);
mdc = CreateCompatibleDC(hdc);
bufdc = CreateCompatibleDC(hdc);//緩存DC
//創建與指定的設備環境相關的設備兼容的位圖
bmp = CreateCompatibleBitmap(hdc, 960, 720);
SelectObject(mdc, bmp);
horse = (HBITMAP)LoadImage(NULL, "horse.bmp", IMAGE_BITMAP, 1624, 300, LR_LOADFROMFILE);
bg = (HBITMAP)LoadImage(NULL, "bg.bmp", IMAGE_BITMAP, 960, 720, LR_LOADFROMFILE);
int x, y;
//繪製圖畫(一幀)
num = 0; //顯示圖號
x = -50; //貼圖起始X座標
y = 150; //貼圖起始Y 座標
SelectObject(bufdc, bg);
BitBlt(mdc, 0, 0, 960, 720, bufdc, 0, 0, SRCCOPY);
SelectObject(bufdc, horse);
//透明處理
BitBlt(mdc, x, y, 203, 150, bufdc, num * 203, 150, SRCAND);
BitBlt(mdc, x, y, 203, 150, bufdc, num * 203, 0, SRCPAINT);
BitBlt(hdc, 0, 0, 960, 720, mdc, 0, 0, SRCCOPY);
//結束時間
//GetTickCount()函數,該函數的返回值是DWORD型,表示以毫秒爲單位的計算機啓動後經歷的時間間隔
tPre = GetTickCount();
num++;
//動畫移動
x += 20;
if (x >= 900)
x = -50;
PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);//賦初值
while (msg.message != WM_QUIT) //進入遊戲消息循環:
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg); //獲得遊戲玩家輸入的消息;
DispatchMessage(&msg);//分配玩家消息並響應用戶消息。
}
else
{
tNow = GetTickCount();//獲取當前時間
if (tNow - tPre >= 100)//程序每隔100個單位時間進行一次繪圖操作
{
if (num == 8) num = 0;
SelectObject(bufdc, bg);
BitBlt(mdc, 0, 0, 960, 720, bufdc, 0, 0, SRCCOPY);
SelectObject(bufdc, horse);
//透明操作
BitBlt(mdc, x, y, 203, 150, bufdc, num * 203, 150, SRCAND);
BitBlt(mdc, x, y, 203, 150, bufdc, num * 203, 0, SRCPAINT);
BitBlt(hdc, 0, 0, 960, 720, mdc, 0, 0, SRCCOPY);
tPre = GetTickCount();//獲取結束時間
num++;
//動畫移動
x += 20;
if (x >= 900)
x = -50;
}
}
}
return (int)msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex =
{
wcex.cbSize = sizeof(WNDCLASSEX),
CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW,
WndProc,0,0,
hInstance,
LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYGAMEFRAME)),
LoadCursor(NULL, IDC_ARROW),
(HBRUSH)(COLOR_WINDOW + 1),NULL,
_T("GameFrame"),
LoadIcon(NULL,MAKEINTRESOURCE(IDI_SMALL))
};
return RegisterClassEx(&wcex);
}
BOOL InitWindow(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 將實例句柄存儲在全局變量中
hWnd = CreateWindow
(
_T("GameFrame"),
_T("遊戲框架"),
WS_OVERLAPPEDWINDOW^WS_THICKFRAME^WS_MAXIMIZEBOX,//普通樣式,不能改變大小,不能最大化
CW_USEDEFAULT, CW_USEDEFAULT, 960, 720, nullptr, nullptr, hInstance, nullptr
);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg) //判斷消息
{
case WM_CREATE:
//執行初始化代碼
return(0);
break;
case WM_DESTROY:
DeleteDC(mdc);
ReleaseDC(hWnd, hdc);
DeleteObject(horse);
PostQuitMessage(0);
break;
default:
break;
}
return (DefWindowProc(hwnd, msg, wparam, lparam));
}
最後結果如下: