Bài 3.3: Di chuyển hình vẽ
Sau khi đã vẽ được hình, lần này ta sẽ thêm chuyền động thêm vào hình vẽ. Tại đây, ta sẽ tạo một ví dụ Shape applet về di chuyển hình vẽ
Lần này không phải là di chuyển bởi điều khiển của user, mà là tự động biển đổi vị trí theo thời gian. Đối với xử lý như này thì sử dụng timer là thích hợp.
Tại BREW, có chức năng timer thông báo cho ta biết sau khi một khoảng thời gian nhất định trôi qua. Việc setting timer được thực hiện bằng hàm ISHELL_SetTimer()
Khi tìm hiểu 「BREW API reference」, ta thấy đó là hàm số như dưới đây
int ISHELL_SetTimer
(
IShell * pIShell, // IShell object
int32 dwMSecs, // chỉ định thời gian timer sẽ thông báo, đơn vị là mili giây
PFNNOTIFY pfn, // hàm số nhận thông báo của timer (callback function)
void * pUser // user data
)
Tìm hiểu về PFNNOTIFY, nhận thấy hàm số nhận thông báo của timer thì cần phải có protype như sau.
void TimerCallback(void * pData)
Sử dụng cái này, ta sẽ có thể tạo chuyển động cho hình vẽ được.
Tuy nhiên đừng vội. Tại đây xuất hiện một vấn đề quan trọng. Để có thể di chuyển được hình vẽ mỗi khi timer thông báo, thì phải ghi nhớ tọa độ của hình vẽ vào đâu ?
Tại BREW, có quy định hạn chế (limitation) quan trọng mà ta chưa nói. Đó là [tạo BREW không dùng được biến global ] . Ngoài ra, cũng không sử dụng được biến tĩnh (static variable) của ngôn ngữ C. Đây là hạn chế không thể tránh khỏi bởi lý do cấu trúc hệ thống của BREW.
* Trường hợp sử dụng C++ để lập trình BREW, không được sử dụng static member variable.
Customize applet structure
Vậy ta phải làm thế nào để có thể ghi nhớ được các dữ liệu global?
Tại BREW, các global data được đặt tại applet structure. Trong các ví dụ trước, với applet structure thì ta mới chỉ sử dụng AEEApplet, thực ra thì người lập trình có thể tùy ý định nghĩa applet structure theo ý mình.
Trong ví dụ di chuyển hình vẽ lần này, ta định nghĩa applet structure như sau.
// customized applet structure
typedef struct
{
AEEApplet a; // member đầu tiên phải luôn có kiểu là AEEApplet
int x0, y0, r0; // tọa độ tâm và bán kính hình 0
int x1, y1, r1; // tọa độ tâm và bán kính hình 1
int x2, y2, r2; // tọa độ tâm và bán kính hình 2
} ShapeApplet;
Như trên đây, [ member đầu tiên trong applet structure phải có kiểu là AEEApplet ]. Chỉ cần thỏa mãn điều kiện này, còn lại thì ta có thể tùy ý thêm biến member vào trong applet structure.
Trường hợp sửa lại định nghĩa của applet structure, thì ta cũng phải sửa lại implementation của hàm AEEClsCreateInstance().
Đầu tiên, tại hàm AEEClsCreateInstance() (hàm tạo ra applet structure), khi gọi hàm AEEApplet_New(), càn thiết phải chỉ định size của applet structure của mình. Lý do bởi vì cần phải chuẩn bị trước vùng nhớ cần thiết cho applet structure.
Ngoài ra thông thường, sau khi gọi hàm AEEApplet_New(), sẽ thực hiện initialize đối với applet structure.
// // Hàm số tạo BREW applet // được suppỏt tại BREW module này // int AEEClsCreateInstance(AEECLSID ClsId,IShell * pIShell,IModule * po,void ** ppObj) { *ppObj = NULL; if (ClsId == AEECLSID_SHAPE) { if (AEEApplet_New(sizeof(ShapeApplet), ClsId, pIShell, po, (IApplet**)ppObj, (AEEHANDLER)Shape_HandleEvent, NULL) == TRUE) { // thực hiện initialize cho applet structure ShapeApplet* app = *ppObj; app->x0 = 20 + RandInt(60); app->y0 = 20 + RandInt(60); app->x1 = 20 + RandInt(60); app->y1 = 20 + RandInt(60); app->x2 = 20 + RandInt(60); app->y2 = 20 + RandInt(60); app->r0 = 4 + RandInt(10); app->r1 = 4 + RandInt(10); app->r2 = 4 + RandInt(10); return (AEE_SUCCESS); } } return (EFAILED); }
* Hàm RandInt() trong code này là hàm trả lại giá trị random, và được định nghĩa riêng. Về code chi tiết hãy download và tham khảo source code.
Như trên đây, khi thực hiện sửa applet structure, thì parameter IApplet* được đưa cho event handler sẽ có thể convert thành ShapeApplet*
//
// event handler của Shape applet
//
static boolean Shape_HandleEvent(IApplet * pi, AEEEvent eCode,
uint16 wParam, uint32 dwParam)
{
switch (eCode)
{
case EVT_APP_START:
Shape_OnAppStart((ShapeApplet*) pi);
return TRUE;
case EVT_APP_STOP:
return TRUE;
default:
break;
}
return FALSE;
}
Dưới đây là phần code còn lại của Shape applet.
// // được gọi khi Shape application được khởi động // static void Shape_OnAppStart(ShapeApplet* app) { // thiết định vẽ hình và timer Shape_OnTimer(app); } // // hàm được gọi bởi timer // static void Shape_OnTimer(ShapeApplet* app) { IGraphics* graphic; // di chuyện hình vẽ app->x0 += RandInt(3) - 1; app->y0 += RandInt(3) - 1; app->x1 += RandInt(3) - 1; app->y1 += RandInt(3) - 1; app->x2 += RandInt(3) - 1; app->y2 += RandInt(3) - 1; app->r0 = ABS(app->r0 + RandInt(3) - 1); app->r1 = ABS(app->r1 + RandInt(3) - 1); app->r2 = ABS(app->r2 + RandInt(3) - 1); // get IGraphics object ISHELL_CreateInstance(app->a.m_pIShell, AEECLSID_GRAPHICS, &graphic); // thực hiện vẽ Shape_OnDraw(app, graphic); // hủy IGraphics object IGRAPHICS_Release(graphic); // thiết đặt lại timer (100 mili giây sau) ISHELL_SetTimer(app->a.m_pIShell, 100, Shape_OnTimer, app); } // // xử lỹ vẽ hình // static void Shape_OnDraw(ShapeApplet* app, IGraphics* graphic) { AEECircle c0, c1, c2; AEETriangle tri; // clear màn hình bằng màu trắng IGRAPHICS_SetBackground(graphic, 255, 255, 255); IGRAPHICS_ClearViewport(graphic); // vẽ các tam giác tri.x0 = app->x0; tri.y0 = app->y0; tri.x1 = app->x1; tri.y1 = app->y1; tri.x2 = app->x2; tri.y2 = app->y2; IGRAPHICS_SetFillMode(graphic, FALSE); IGRAPHICS_SetColor(graphic, 0, 0, 0, 0); IGRAPHICS_DrawTriangle(graphic, &tri); // vẽ hình tròn c0.cx = app->x0; c0.cy = app->y0; c0.r = app->r0; c1.cx = app->x1; c1.cy = app->y1; c1.r = app->r1; c2.cx = app->x2; c2.cy = app->y2; c2.r = app->r2; IGRAPHICS_SetFillMode(graphic, TRUE); IGRAPHICS_SetFillColor(graphic, 255, 0, 0, 0); IGRAPHICS_DrawCircle(graphic, &c0); IGRAPHICS_SetFillColor(graphic, 0, 255, 0, 0); IGRAPHICS_DrawCircle(graphic, &c1); IGRAPHICS_SetFillColor(graphic, 0, 0, 255, 0); IGRAPHICS_DrawCircle(graphic, &c2); // hiển thị thực tế xử lý vẽ màn hình IGRAPHICS_Update(graphic); }
Toàn bộ source code:
Tags: Brew








lexa Ranking:
Gửi nhận xét: