Bài 7 - Menu, từ cơ bản tới phức tạp (Part 1)

Người đăng: share-nhungdieuhay on Chủ Nhật, 27 tháng 4, 2014

Hi, cả lò! (Trời bắt đầu thành cái lò nung tới nơi rồi)

Mọi người nghiên cứu tới đâu rồi nhỉ, còn ai chưa qua được bước cài đặt không? Mình đảm bảo làm theo mình chắc chắn thành công nhé. Xin thông báo với tất cả 1 tin mừng đó là phiên bản Cocos2dx-3 đã ra phiên bản FINAL rồi nhé, nghĩa là bản chính thức, đã khắc phục được tất cả các lỗi. Vậy chúng ta yên tâm học tiếp thôi. Nắm vững được 1 phiên bản thì sau này có ra V4,V5 cũng không khó để tiếp cận.

Ở bài trước, chúng ta đã học qua 1 Bài về Physic cơ bản trong Game và cách tạo chúng = engine Cocos2dx v3. À, trong Engine này sử dụng 2 thư viện Physic để xây dựng game, đó là Chipmunk, và Box 2D. Bài trước là dựa trên Chipmunk nhé, đơn giản, gần gũi hơn Box 2D. Sau này mình sẽ tìm hiểu nốt cái Box 2D và giới thiệu với mọi người. Giờ thì đi tiếp nào, Trong bài này, mình sẽ hướng dẫn mọi người làm mấy cái Menu có thể thao tác được để thực hiện 1 công việc nào đó.

Bắt đầu thôi. Tạo 1 Project mới tên Menu như sau, mở cmd lên gõ vào

>cocos new menu -p com.vn.menu -l cpp -d f:android/project

Sau khi Project mới được tạo, bạn chạy luôn lệnh này giúp mình

>cocos compile -s f:android/project/menu -p win32


Đây là biên dịch lần đầu, mục đích là liên kết tới các thư viện của Engine. Lần biên dịch đầu tiên thường lâu là vì thế. Các lần sau thì nhàn hơn nhiều bởi hầu hết chúng ta chỉ thay đổi ở Class và Resource mà thôi.

B1) Copy code và chạy thử
Bạn mở thư mục Classes theo đường dẫn sau F:/android/project/menu/Classes ( có thể khác trên máy bạn)  có chứa 4 file quen thuộc phải không. Nhưng trong bài này chúng ta sẽ không dùng lớp HelloWorldScene nữa mà thay thế bằng 2 lớp khác là MenuLayer và SceneManger.

Bạn xóa 2 file HelloWorldScene.cpp và HelloWorldScene.h, download file nguồn sau tại ĐÂY và copy paste 4 file trong đó vào thư mục Classes. Tiếp theo bạn mở file AppDelegate.cpp, ở dòng #include thứ 2  bạn thay HelloWorldScene.h =  SceneManager.h, 
bỏ dòng auto scene = HelloWorld::createScene();
và director->runWithScene(scene); đi nhé. 
Thêm vào 1 dòng lệnh sau SceneManager::goMenu(); vào bên dưới 2 dòng trên

Xong rồi, trước khi biên dịch chạy thử bạn mở file Menu.vcxproj theo đường dẫn sau F:/android/project/menu/proj.win32/ rồi tìm "HelloWorldScene.cpp" bạn sẽ thấy 4 tên file cơ bản được đặt ở đây khi biên dịch (HelloWorldScene.h, HelloWorldScene.cpp, AppDelegate.cpp, AppDelegate.h )

Vì ở trên bạn đã xóa HelloWorldScene.h và HelloWorldScene.cpp đi rồi nên ở đây bạn cũng phải xóa đi. Đồng thời thêm vào 4 file SceneManager.h, SceneManager.cpp, MenuLayer.h , MenuLayer.cpp vào Menu.vcxproj để trình biên dịch sẽ xử lý thêm 4 file này khi chúng ta biên dịch lại 1 lần nữa để chạy. Cách thêm thì như hình



Chạy thử = lệnh

>cocos run -s f:.android/project/menu -p win32

Rất tiếc! LỖI 1 đống nhé. Cũng phải thôi vì mã nguồn có lẽ không phù hợp với phiên bản Engine đang dùng, phải sửa lại đôi chút. Hoặc là tác giả của source bị sai mấy câu lệnh chẳng hạn. Căn cứ vào mấy cái lỗi để sửa thôi

B2) Nghiên cứu file nguồn 1 chút nhỉ

Nhìn vào thông báo lỗi, khá nhiều lỗi luôn, và không phải lỗi nào cũng có thẻ hiểu được. Sau 1 thời gian có kinh nghiệm chắc chắn bạn sẽ fix được các lỗi này thôi. Quả thật mình cũng không biết phải diễn giải các lỗi này ra đây thế nào nữa hì. Tốt nhất là kiểm tra lại mã nguồn của chúng ta xem có sai sót gì không.

Ở phần trên sẽ báo có 8 lỗi: Identifier 'Object' .....

Mở 2 file Header là SceneManager.h, MenuLayer.h , thêm vào đó dồng USING_NS_CC; vào dưới các dòng #include, cả 2 file nhé. compile lại xem, build được luôn, nhưng chạy thử file exe trong F:/android/project/menu/bin thì lại báo lỗi stop working.

Theo kinh nghiệm của mình thì, khi Build không gặp lỗi gì, tức là code đã chuẩn theo phiên bản Engine. Nhưng khi chạy mà báo lỗi Stop working thì có thể do 2 lỗi sau, không tương thích với hệ thống ( build trên 32 mang chạy trên 64 chẳng hạn) và lỗi thứ 2 là do Resource ( file hình ảnh, âm thanh, font, ...) đã bị thiếu. 

Trong trường hợp này mình cố tình ko copy 1 file font "Marker Felt.ttf" vào thư mục Resource nên build ok nhưng chạy bị lỗi. Bạn copy file "Marker Felt.ttf" từ F:/android/project/menu/Resource/font ra ngay bên ngoài thư mục Resource ( cùng cấp với mấy hình ảnh HelloWorld đó)


Compile lại xem nào


>cocos run -s f:.android/project/menu -p win32

OK nhé


B3) Nghiên cứu Code

Bạn mở 2 file header là SceneManager.h, MenuLayer.h và ngó qua chút: không có gì đặc biệt lắm phải không, ở đó chứa khai báo các hàm hoặc thuộc tính của một lớp. Cách khai báo bạn ôn lại 1 chút trong C++ là hiểu được thôi. Mình sẽ đi vào phần chính ở dưới

(Các bạn theo dõi file CODE nhé, vì nếu chép ra đây thì dài và rối lắm. Chúng ta giải thích là chính thôi)
+ Mở file SceneManager.cpp, trong này có 3 hàm 

void SceneManager::goMenu(), hàm này tạo ra 1 layer ( cái này cũng gọi là lớp nhưng không giống Class nhé. Class là chỉ các đối tượng với thuộc tính và hàm, còn layer giống như 1 mặt phẳng để đặt các thứ khác lên nó, hình dung như thế đi). Sau đó hàm này gọi tiếp 1 hàm void SceneManager::go(Layer* layer)

void SceneManager::go(Layer* layer) thực hiện 2 công việc, truyền layer vừa tạo ở trên cho 1 hàm Scene* SceneManager::wrap(Layer *layer) để xử lý cái layer này,việc xử lý bằng hàm Wrap sẽ trả lại 1 Scene. Sau đó kiểm tra xem có scene nào đang chạy không, nếu có thì thay thế = Scene mới có layer vừa tạo. nếu không có Scene nào đang chạy thì chạy với Scene có layer vừa tạo.

Scene* SceneManager::wrap(Layer *layer) thực hiện công việc là lấy tham số layer truyền vào, đặt lên 1 Scene mới tạo, trả lại giá trị là 1 Scene.

+ Mở file MenuLayer.cpp trong đó cũng lại có 3 hàm

* bool MenuLayer::init(), hàm init luôn trả về bool nhé

Trong này mình sẽ giải thích một số dòng lệnh "lạ"

TTFConfig config_font96("Marker Felt.ttf", 96);

TTFConfig config_font52("Marker Felt.ttf", 52);

//Chình font "Marker Felt.ttf" thành 2 cỡ 96, và 52 (pixel??)

Label *titleLeft = Label::createWithTTF(config_font96, "Menu ");

// Tạo 1 Label ( nhãn )  titleLeft có hiện dòng chữ "Menu" sử dụng font config_font96, các lênh tương tự bên dưới nhé
    
MenuItemFont *startNew = MenuItemFont::create("New Game", CC_CALLBACK_1(MenuLayer::onNewGame, this));

// Tạo biến menu item startNew hiện từ "New Game", khi ấn lên menu item này sẽ gọi hàm onNewGame() của lớp MenuLayer, lệnh dưới tương tụ tạo menu item "Credits"

Menu *menu = Menu::create(startNew, credits, NULL);
// Tạo 1 biến menu có chứa 2 menu item con đã tạo ở trên là startNew  và credits

1 đoạn bên dưới là công việc nhàm chán đặt vị trí trên màn hình = lệnh setPostion(); và đặt các đối tượng vào layer = lệnh this->addChild();

có 1 câu này
 menu->alignItemsVerticallyWithPadding(80.0f); // căn chỉnh theo chiều dọc các đối tượng của biến menu cách nhau 1 khoảng 80 (pixel??)

- 2 hàm bên dưới onNewGame(), onCredits() thực hiện công việc đơn giản là lại gọi hàm tạo 1 Scene mới khi ấn vào 2 menu tạo ở trên

Tổng kết lại, trong bài này học được :

+ Tạo 1 label với font = lệnh
TTFConfig config_font96("Marker Felt.ttf", 96); 
Label *titleLeft = Label::createWithTTF(config_font96, "Menu ");

+ Tạo 1 đối tượng menu item có thể ấn được 
MenuItemFont *startNew = MenuItemFont::create("New Game", CC_CALLBACK_1(MenuLayer::onNewGame, this));

Menu *menu = Menu::create(startNew, credits, NULL);

Xong rồi. 1 bài đơn giản  mà phải diễn giải dài quá các bạn ạ, nếu bài nào mà dài, nhiều đối tượng chắc chết quá



{ 0 nhận xét... read them below or add one }

Đăng nhận xét