一、 计算机角色的简单动画
先是使用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));
}
最后结果如下: