finallegend
Mr & Ms Pac-Man
- 31/12/04
- 221
- 0
Rất nhiều nhà lập trình thích làm những trò chơi hành động thực. Vì vậy những hình ảnh tĩnh sẽ không thể làm cho họ có hứng thú. Sử dụng những kỹ thuật hoạt hình đơn giản sau đây có thể tạo ra những hình ảnh chuyển động :
· Tạo ảo giác về sự chuyển động bằng cách ghi một loạt hình ảnh liên tiếp biểu diễn những thay dổi vị trí từ từ của đối tượng cần biểu diễn, rồi hiển thị lại các hình ảnh đó đủ nhanh sao cho mắt cảm thấy hình ảnh chuyển động tự nhiên không bị giật.
· Về đồ hoạ, kỹ thuật hoạt hình đạt được bằng một vài cách tuỳ thuôc vào ngôn ngữ lập trình và môi trường làm việc.
- Thứ nhất là vẽ một hình ảnh, sau đó xóa đi và vẽ lại hình ảnh đó ở vị trí khác một chút so với vị trí trước.
- Hoạt hình được tạo ra trong thời gian thực (trong đó mỗi frame được tạo ra như là một khung nhìn) và trong cả thời gian mô phỏng.
- Để tạo được thứ tự hoạt ảnh thành công, các hình ảnh phải thay thế nhau một cách đủ nhanh để đánh lừa con mắt người xem khi xem những hình ảnh liên tục, ít nhất là 14 frame mỗi giây. Đối với những ứng dụng tạo trò chơi, ta chỉ cần từ 6 – 10 frame / s để tiết kiệm tiền và thời gian xử lý của CPU. Phạm vi tốt nhất cho kỹ thuật hoạt hình chất lượng là từ 14 – 30 frame /s.
Ví dụ:
· Để tạo ra một hoạt ảnh đơn giản, ta cần ít nhất hai hình ảnh khác nhau.
A =
B =
Cách đơn giản để hiển thị hình ảnh này cần thực hiện qua các bước sau:
- Xoá ngoài màn hình
- Vẽ hình ảnh A lên màn hình
- Cập nhật hình ảnh thực
- Delay vài ms để người quan sát nắm được hình ảnh. Nếu ta dùng kỹ thuật hoạt hình 10 frame / s thì thời gian delay là 1000/10=100 ms
- Lặp lại bước 1 nhưng ở bước 2 ta thay hình ảnh A bằng hình ảnh B.
· Đối với hành động của đối tượng hoạt hoạ quá phức tạp, ví dụ như người đang chạy, các frame liên tiếp cho kỹ thuật này là 10 frame hoặc hơn. Điều đó tương đương với cần 10 file hình ảnh. Vì thấ có thể gặp một vấn đề là quản lý file. Để giảm bớt số lượng file hình ảnh, ta hợp chúng lại thành một hình ảnh.
· Ta có thể tạo hoạt ảnh đơn giản bằng cách chia hình ảnh trên thành 4 phần và vẽ mỗi phần đó lên màn hình từ trái sang phải.
Sau đây là đoạn chương trình:
// sample.rc
#include "windows.h"
100 BITMAP ninja.bmp
// replace to startup.c
LRESULT MainWndProc(HWND hWnd, UINT message, WPARAM uParam, LPARAM lParam)
{
HDC hDC, hMemDC;
HBITMAP hBitmap;
int nCnt;
switch(message)
{
case WM_LBUTTONDOWN:
hDC = GetDC(hWnd);
hBitmap = LoadBitmap(g_hInst, MAKEINTRESOURCE(100));
hMemDC = CreateCompatibleDC(hDC);
SelectObject(hMemDC, hBitmap);
ReleaseDC(hWnd,hDC);
for(nCnt=0; nCnt<4; nCnt++)
{
PatBlt(hOffscreebDC, 0, 0, 240, 320, WHITENESS); TransparentImage(hOffscreenDC,nCnt*4,0,46,57,hMemDC,nCnt*46,0,46,57, RGB(255,0,255));
Sleep(100);
UpdateDisplay(hWnd);
}
DeleteDC(hMemDC);
DeleteObject(hBitmap);
break;
case WM_KEYDOWN:
DestroyWindow(hWnd);
break;
case WM_CREATE:
InitOffscreen(240, 320);
break;
case WM_DESTROY:
DeinitOffscreen();
PostQuitMessage(0);
break;
default:
DefWindowProc(hWnd, message, uParam, lParam);
}
return 0;
}
· Bước tiếp theo, ta cần điều khiển vị trí đối tượng trên màn hình. Giả sử ta gọi đối đó là GAME OBJECT hoặc SPRITE OBJECT. Để điều khiển vị trí của đối tượng, ta cần lưu lại vị trí hiện tại của nó.
- Ta cần một kiểu dữ liệu POINT trong Win32 SDK. Kiểu dữ liệu
POINT gồm hai thành phần: x và y. Kiểu này được khai báo
như sau :
typedef _tagPOINT
{
int x;
int y;
} POINT;
- Một kiểu dữ liệu nữa cần sử dụng là kiểu SIZE, giống như kiểu
POINT nó cũng có hai thành phần cx và cy
typedef _tagSIZE
{
int cx;
int cy;
} SIZE;
- Ta sẽ sử dụng hai kiểu trên để điều khiển các đối tượng trong trò
chơi. Dùng thêm một biến là bộ đếm các frame. Nó được sử dụng
để điều khiển hành động của các đối tượng.
· Ta cần tạo ra Screen Saver như một chương trình và để đối
tượng chuyển động trên nó. Vị trí bắt đầu là ngẫu nhiên.
· Kế hoạch chương trình:
- Tạo các biến vị trí và tải nguồn ảnh vào một biến toàn cục
- Tạo vòng lặp của 10 đối tượng
- Xoá màn hình OffScreen
- Di chuyển các đối tượng bằng cách thay đổi các biến vị trí
- Cập nhật bộ đếm các frame
- Vẽ đối tượng vào vị trí của nó
- Nếu vị trí ở ngoài màn hình thì ngẫu nhiên bắt đàu một vị trí mới.
- Sau khi kết thúc vòng lặp thì cập nhật màn hình thực
- Thời gian delay là 50 ms để người quan sát nắm được hình ảnh
- Bắt đầu vòng lặp
- Huỷ bỏ ảnh được tải lên
Sau đây là đoạn chương trình:
// sample.rc
#include "windows.h"
100 BITMAP ninja.bmp
// replace to startup.c
#DEFINE TRASNCOLOR RGB(255,0,255)
sattic HBITMAP hObjBitmap;
static POINT ObjPosition[10];
static int nFrameCounter[10];
static SIZE ObjSize;
static void FirstInit(void)
{
int nCount;
InitOffscreen(240, 320);
hObjBitmap = LoadBitmap(g_hInst, MAKEINTRESOURCE(100));
ObjSize.cx = 40;
ObjSize.cy = 57;
for(nCount=0; nCount<10; nCount++)
{
ObjPosition[nCount].x = -(Random() % 100);
ObjPosition[nCount].y = Random() % (320 - ObjSize.cy);
nFrameCounter[nCount] = 0;
}
}
static void Deinit(void)
{
DeinitOffscreen();
DeleteObject(hObjBitmap);
}
static void RenderFrame(HWND hWnd)
{
HDC hDC, hMemDC;
int nCnt, x, y, frameno;
hDC = GetDC(hWnd);
hMemDC = CreateCompatibleDC(hDC);
SelectObject(hMemDC, hObjBitmap);
ReleaseDC(hWnd,hDC);
PatBlt(hOffscreebDC, 0, 0, 240, 320, WHITENESS);
for(nCnt=0; nCnt<10; nCnt++)
{
x = ObjPosition[nCnt].x;
y = ObjPosition[nCnt].y;
frameno = nFrameCounter[nCnt] * ObjSize.cx;
TransparentImage(hOffscreenDC,x,y,ObjSize.cx,ObjSize.cy,hMemDC,frameno,0,ObjSize.cx,ObjSize.cy, TRASNCOLOR);
ObjPosition[nCnt].x += 4;
if(ObjPosition[nCnt].x + ObjSize[nCnt] > 240)
ObjPosition[nCount].x = -(Random() % 100);
nFrameCounter[nCnt]++;
if(nFrameCounter[nCnt] > 4)
nFrameCounter[nCnt] = 0;
}
UpdateDisplay(hWnd);
DeleteDC(hMemDC);
}
LRESULT MainWndProc(HWND hWnd, UINT message, WPARAM uParam, LPARAM lParam)
{
switch(message)
{
case WM_TIMER:
RenerFrame(hWnd);
break;
case WM_KEYDOWN:
DestroyWindow(hWnd);
break;
case WM_CREATE:
FirstInit();
SetTimer(hWnd,1,50,0);
break;
case WM_DESTROY:
Deinit();
PostQuitMessage(0);
break;
default:
DefWindowProc(hWnd, message, uParam, lParam);
}
return 0;
}
KienDN – ThuyNT DohoaVietNam.com
· Tạo ảo giác về sự chuyển động bằng cách ghi một loạt hình ảnh liên tiếp biểu diễn những thay dổi vị trí từ từ của đối tượng cần biểu diễn, rồi hiển thị lại các hình ảnh đó đủ nhanh sao cho mắt cảm thấy hình ảnh chuyển động tự nhiên không bị giật.
· Về đồ hoạ, kỹ thuật hoạt hình đạt được bằng một vài cách tuỳ thuôc vào ngôn ngữ lập trình và môi trường làm việc.
- Thứ nhất là vẽ một hình ảnh, sau đó xóa đi và vẽ lại hình ảnh đó ở vị trí khác một chút so với vị trí trước.
- Hoạt hình được tạo ra trong thời gian thực (trong đó mỗi frame được tạo ra như là một khung nhìn) và trong cả thời gian mô phỏng.
- Để tạo được thứ tự hoạt ảnh thành công, các hình ảnh phải thay thế nhau một cách đủ nhanh để đánh lừa con mắt người xem khi xem những hình ảnh liên tục, ít nhất là 14 frame mỗi giây. Đối với những ứng dụng tạo trò chơi, ta chỉ cần từ 6 – 10 frame / s để tiết kiệm tiền và thời gian xử lý của CPU. Phạm vi tốt nhất cho kỹ thuật hoạt hình chất lượng là từ 14 – 30 frame /s.
Ví dụ:
· Để tạo ra một hoạt ảnh đơn giản, ta cần ít nhất hai hình ảnh khác nhau.
A =
B =
Cách đơn giản để hiển thị hình ảnh này cần thực hiện qua các bước sau:
- Xoá ngoài màn hình
- Vẽ hình ảnh A lên màn hình
- Cập nhật hình ảnh thực
- Delay vài ms để người quan sát nắm được hình ảnh. Nếu ta dùng kỹ thuật hoạt hình 10 frame / s thì thời gian delay là 1000/10=100 ms
- Lặp lại bước 1 nhưng ở bước 2 ta thay hình ảnh A bằng hình ảnh B.
· Đối với hành động của đối tượng hoạt hoạ quá phức tạp, ví dụ như người đang chạy, các frame liên tiếp cho kỹ thuật này là 10 frame hoặc hơn. Điều đó tương đương với cần 10 file hình ảnh. Vì thấ có thể gặp một vấn đề là quản lý file. Để giảm bớt số lượng file hình ảnh, ta hợp chúng lại thành một hình ảnh.
· Ta có thể tạo hoạt ảnh đơn giản bằng cách chia hình ảnh trên thành 4 phần và vẽ mỗi phần đó lên màn hình từ trái sang phải.
Sau đây là đoạn chương trình:
// sample.rc
#include "windows.h"
100 BITMAP ninja.bmp
// replace to startup.c
LRESULT MainWndProc(HWND hWnd, UINT message, WPARAM uParam, LPARAM lParam)
{
HDC hDC, hMemDC;
HBITMAP hBitmap;
int nCnt;
switch(message)
{
case WM_LBUTTONDOWN:
hDC = GetDC(hWnd);
hBitmap = LoadBitmap(g_hInst, MAKEINTRESOURCE(100));
hMemDC = CreateCompatibleDC(hDC);
SelectObject(hMemDC, hBitmap);
ReleaseDC(hWnd,hDC);
for(nCnt=0; nCnt<4; nCnt++)
{
PatBlt(hOffscreebDC, 0, 0, 240, 320, WHITENESS); TransparentImage(hOffscreenDC,nCnt*4,0,46,57,hMemDC,nCnt*46,0,46,57, RGB(255,0,255));
Sleep(100);
UpdateDisplay(hWnd);
}
DeleteDC(hMemDC);
DeleteObject(hBitmap);
break;
case WM_KEYDOWN:
DestroyWindow(hWnd);
break;
case WM_CREATE:
InitOffscreen(240, 320);
break;
case WM_DESTROY:
DeinitOffscreen();
PostQuitMessage(0);
break;
default:
DefWindowProc(hWnd, message, uParam, lParam);
}
return 0;
}
· Bước tiếp theo, ta cần điều khiển vị trí đối tượng trên màn hình. Giả sử ta gọi đối đó là GAME OBJECT hoặc SPRITE OBJECT. Để điều khiển vị trí của đối tượng, ta cần lưu lại vị trí hiện tại của nó.
- Ta cần một kiểu dữ liệu POINT trong Win32 SDK. Kiểu dữ liệu
POINT gồm hai thành phần: x và y. Kiểu này được khai báo
như sau :
typedef _tagPOINT
{
int x;
int y;
} POINT;
- Một kiểu dữ liệu nữa cần sử dụng là kiểu SIZE, giống như kiểu
POINT nó cũng có hai thành phần cx và cy
typedef _tagSIZE
{
int cx;
int cy;
} SIZE;
- Ta sẽ sử dụng hai kiểu trên để điều khiển các đối tượng trong trò
chơi. Dùng thêm một biến là bộ đếm các frame. Nó được sử dụng
để điều khiển hành động của các đối tượng.
· Ta cần tạo ra Screen Saver như một chương trình và để đối
tượng chuyển động trên nó. Vị trí bắt đầu là ngẫu nhiên.
· Kế hoạch chương trình:
- Tạo các biến vị trí và tải nguồn ảnh vào một biến toàn cục
- Tạo vòng lặp của 10 đối tượng
- Xoá màn hình OffScreen
- Di chuyển các đối tượng bằng cách thay đổi các biến vị trí
- Cập nhật bộ đếm các frame
- Vẽ đối tượng vào vị trí của nó
- Nếu vị trí ở ngoài màn hình thì ngẫu nhiên bắt đàu một vị trí mới.
- Sau khi kết thúc vòng lặp thì cập nhật màn hình thực
- Thời gian delay là 50 ms để người quan sát nắm được hình ảnh
- Bắt đầu vòng lặp
- Huỷ bỏ ảnh được tải lên
Sau đây là đoạn chương trình:
// sample.rc
#include "windows.h"
100 BITMAP ninja.bmp
// replace to startup.c
#DEFINE TRASNCOLOR RGB(255,0,255)
sattic HBITMAP hObjBitmap;
static POINT ObjPosition[10];
static int nFrameCounter[10];
static SIZE ObjSize;
static void FirstInit(void)
{
int nCount;
InitOffscreen(240, 320);
hObjBitmap = LoadBitmap(g_hInst, MAKEINTRESOURCE(100));
ObjSize.cx = 40;
ObjSize.cy = 57;
for(nCount=0; nCount<10; nCount++)
{
ObjPosition[nCount].x = -(Random() % 100);
ObjPosition[nCount].y = Random() % (320 - ObjSize.cy);
nFrameCounter[nCount] = 0;
}
}
static void Deinit(void)
{
DeinitOffscreen();
DeleteObject(hObjBitmap);
}
static void RenderFrame(HWND hWnd)
{
HDC hDC, hMemDC;
int nCnt, x, y, frameno;
hDC = GetDC(hWnd);
hMemDC = CreateCompatibleDC(hDC);
SelectObject(hMemDC, hObjBitmap);
ReleaseDC(hWnd,hDC);
PatBlt(hOffscreebDC, 0, 0, 240, 320, WHITENESS);
for(nCnt=0; nCnt<10; nCnt++)
{
x = ObjPosition[nCnt].x;
y = ObjPosition[nCnt].y;
frameno = nFrameCounter[nCnt] * ObjSize.cx;
TransparentImage(hOffscreenDC,x,y,ObjSize.cx,ObjSize.cy,hMemDC,frameno,0,ObjSize.cx,ObjSize.cy, TRASNCOLOR);
ObjPosition[nCnt].x += 4;
if(ObjPosition[nCnt].x + ObjSize[nCnt] > 240)
ObjPosition[nCount].x = -(Random() % 100);
nFrameCounter[nCnt]++;
if(nFrameCounter[nCnt] > 4)
nFrameCounter[nCnt] = 0;
}
UpdateDisplay(hWnd);
DeleteDC(hMemDC);
}
LRESULT MainWndProc(HWND hWnd, UINT message, WPARAM uParam, LPARAM lParam)
{
switch(message)
{
case WM_TIMER:
RenerFrame(hWnd);
break;
case WM_KEYDOWN:
DestroyWindow(hWnd);
break;
case WM_CREATE:
FirstInit();
SetTimer(hWnd,1,50,0);
break;
case WM_DESTROY:
Deinit();
PostQuitMessage(0);
break;
default:
DefWindowProc(hWnd, message, uParam, lParam);
}
return 0;
}
KienDN – ThuyNT DohoaVietNam.com

Câu lệnh for cơ bản + ví dụ

tự dịch đi, kêu là ở bên aus mà không biết tiếng Anh à 
