Thứ Tư, 30 tháng 4, 2014

Video - Hướng dẫn cài đặt Cocos2d-x V3.0 FINAL - Install Cocos2d-x v3.0 Final - 100% Working

Lần đầu làm Video, có gì sai sót, mọi người bỏ qua. Quay đi quay lại 3-4 lần thôi,

Các bạn chú ý theo dõi kỹ nhé

Đoạn cuối có Bonus 1 tí, Các bạn xem và ủng hộ



Các Video lần sau mình sẽ làm công phu hơn

Thứ Ba, 29 tháng 4, 2014

Bài 8: Menu - từ cơ bản tới phức tạp ( Part2)

Hi 30-4, 1-5!

Tình hình là 2 ngày không được nghỉ, chả biết làm gì, đi làm thì chán chán, đi chơi thì 1 mình nên đành rảnh rỗi ngồi viết bài cho vui vậy. Các anh chị em giờ này chắc đang vi vu tận đẩu tận đâu rồi ấy nhỉ. Còn mình thì đi làm, nhưng mà không sao, double lương cũng tạm.

Bài trước chúng ta đã biết cách tạo Label chứa text và cách chỉnh font, cùng với việc tạo 1 menu chứa item để thực hiện 1 tác vụ nào đó. Để nhớ lâu, các bạn nên dùng VS 2012 gõ lại từng đoạn code nhé. Còn trong bài này chúng ta sẽ đi sâu hơn với một số công việc sau:

+ Tạo hiệu ứng chuyển cảnh cho mỗi Scene
+ Tạo công việc cho các nút của Menu
+ Thêm một chút hiệu ứng cho Label, ví dụ như chuyển động chẳng hạn.

Bắt đầu thôi. Các down file Source ở ĐÂY về, giải nén rồi paste đè vào thư mục Classes của project menu nhé.

Sau đó, bạn chỉnh file Menu.vcxproj (f:/android/project/menu/proj.win32) như thế này để không bị lỗi khi compile



Biên dịch rồi chạy thử cái xem thế nào

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

Bạn có thấy thay đổi gì không, có hiệu ứng chuyển Scene, hiệu ứng dịch chuyển chữ, và Click vào 2 menu sẽ chuyển sang Scene khác. OK. Tiếp theo chúng ta sẽ đi vào chi tiết phần code xem làm thế nào để được như vậy.

Chi tiết phần Code

Các file SceneManager.h, và MenuLayer.h không thay đổi gì so với phẩn 1. Ở phần 2 này chúng ta thấy có 2 lớp mới xuât hiện đó là CreditLayer, PlayLayer để quản lý 2 thao tác khi nhấn vào 2 menu khác nhau của chúng ta. Bạn mở 2 file CreditLayer.h, và PlayLayer.h ra nhé

Nói chung là ko có gì đặc biệt phải không , ngoài mấy cái hàm tạo, hàm hủy, rồi hàm init, hàm back ( để ấn nút Back xuất hiện ở Scene này). 2 đối tượng này có mỗi một việc là tạo ra 2 cái Layer rồi sau đó sẽ dính vào 1 Scene nào đó. Bỏ qua 2 file này nhé.

A > Tiếp theo mở file CreditLayer.cpp ra, nhìn vào hàm init() // Hàm này tạo ra 1 layer trống để gắn đối tượng. Trong hàm init () này có đoạn code cần chú ý

auto back = MenuItemFont::create("Back", CC_CALLBACK_1(CreditLayer::back,this)); (1)
auto menu = Menu::create(back, NULL); (2)
menu->setPosition(visibleSize.width/2, visibleSize.height/2);
this->addChild(menu);

(1) Đây là câu lệnh quen thuộc đã học từ bài 7, nhiệm vụ tạo ra 1 item menu tên back, khi ấn vào item menu này sẽ gọi hàm CreditLayer::back() ở phía dưới
(2) là câu lệnh cũng quen thuộc có nhiệm vụ tạo ra 1 Menu chứa cái item menu back đã tạo ở trên.
Còn đoạn bên dưới là đặt vị trí Menu trên ở chính giữa màn hình, sau đó dính cái menu này vào Layer tạo ra bởi hàm init()

B > Tiếp theo mở file PlayLayer.cpp, ta thấy rằng các dòng code hoàn toàn tương tự file CreditLayer.cpp, cũng là tạo ra 1 nút back rồi gắn vào Layer này. Các bạn nghiên cứu kỹ lại cho nhớ nhé.

C > Tiếp theo chúng ta nghiên cứu file MenuLayer.cpp, file này có code khá giống Bài 7 đã nghiên cứu, tuy nhiên, nó bổ sung thêm 1 vài code tạo hiệu ứng di chuyển mấy cái Label, xem qua chút nhỉ. Trong hàm init() ta thấy các câu lệnh quen thuộc để tạo ra các Label chứa Text với font chữ, và cỡ chữ xác định, đặt chúng lên Layer tại các vị trí. Nhưng có 1 đoạn code khá lạ, chúng ta cùng xem:

titleLeft->setPosition(titleLeftPosBegin);
Action *titleLeftAction = Sequence::create(
                            DelayTime::create(delayTime),
                            EaseBackOut::create(MoveTo::create(1.0, titleLeftPosEnd)),
                            NULL);

titleLeft->runAction(titleLeftAction); // titleLeft là 1 cái Label nhé
this->addChild(titleLeft);

Đoạn code này hiểu như sau: nhiệm vụ của nó là tạo ra một hành động có tên titleLeftAction = lệnh Sequence::create(). Hành động này cụ thể là gì? hãy xem trong hàm Sequene::create(), hàm này có 3 tham số truyền vào
DelayTime::create(delayTime) // là tạo ra thời gian trễ
 EaseBackOut::create(MoveTo::create(1.0, titleLeftPosEnd)) // MoveTo::create(1.0, titleLeftPosEnd) là hàm tạo 1 hành động di chuyển từ điểm đầu tiên titleLeftPosBegin (đã tính toán ở đoạn code bên trên - trong source) đến điểm cuối titleLeftPosEnd ( cũng đã tính toán trong source), EaseBackOut là 1 lớp tạo ra hiệu ứng ( ko biết phải dịch là gì - đây là 1 trong các hiệu ứng di chuyển thông dụng )
NULL : tham số thứ 3 này chưa hiểu lắm, để hiểu sâu hơn hãy nghiên cứu ở đây http://www.cocos2d-x.org/reference/native-cpp/V3.0rc0/index.html

Lệnh titleLeft->runAction(titleLeftAction); là thực hiện cái hành động di chuyển ở bên trên bằng cách gọi function của đối tượng titleLeft ( đây là 1 cái Label ).

this->addChild(titleLeft); // Gắn cái Label vào Layer tạo bởi init(); 

Đoạn code bên dưới cũng tương tự thế, tạo ra 1 chuyển động cho 1 cái Label khác. OK chưa

Giờ thì tới đoạn này, khá khó hiểu

   for (Node *each : menu->getChildren())
    {
each->setScale(0.0f, 0.0f);
Action *action = Sequence::create(DelayTime::create(delayTime),
                                          ScaleTo::create(0.5f, 1.0f),
                                          NULL);
delayTime += 0.2f;
each->runAction(action);
     }

Đây là vòng lặp for để duyệt các item của Menu đó chính là nút Credits và nút New Game đó ( 2 nút này được tạo ra ở bên trên - trong Source, MenuLayer.cpp)

for (Node *each : menu->getChildren()) cũng khá lại so với for (i=0; i<n; i++) cơ bản của C++ nhỉ, hêhe, nhưng chính xác nó là 1 vòng lặp để duyệt các đơn vị của 1 tập nào đó.

Trong vòng lặp

each->setScale(0.0f, 0.0f); là chỉnh cái nút menu Credits , New Game về tỉ lệ 0, biến mất còn gì, sau đó đến lệnh

Action *action = Sequence::create(DelayTime::create(delayTime),
                                          ScaleTo::create(0.5f, 1.0f),
                                          NULL);
là tạo ra 1 hành động phóng to dần cái nút này lên với tỷ lệ nhất định ScaleTo::create(0.5f, 1.0f),
sau đó là thực hiện hành động each->runAction(action);  Kết quả là tạo 1 hiệu ứng cái nút đó phóng to dần lên thôi, đơn giản và dễ hiểu quá phải không.

D > Tiếp theo chúng ta nghiên cứu file SceneManger.cpp, file này dùng để quản lý các Scene được tạo ra và chạy như thế nào, đồng thời khi chuyển từ Scene này sang scene khác có kèm 1 hiệu ứng chuyển cảnh ( như làm mờ, lộn ngược, quay đảo, v.v...)

Mở file lên nào, Trời ơi, sao code dài thế ~150 dòng code cùng với rất nhiều hàm. Vâng, bạn ạ, thực ra code dài nhưng đơn giản dễ hiểu còn hơn đoạn code ngắn mà phức tạp đọc không hiểu gì. Mình nhớ có lần làm 1 bài tập lớn, search mạng đọc 1 cái code Java thì phải có sấp sỉ 10000 dòng (Notepad ++) đọc mãi mới xong. 

Trong file này tuy nhiều code nhưng thật ra có nhiều đoạn code chức năng na ná nhau đó là tạo ra 1 hiệu ứng chuyển cảnh cho Scene, thế nên mình chỉ giới thiệu với các bạn 1-2 đoạn thôi nhé. Bạn yên tâm rằng các hiệu ứng chuyển cảnh này đều được định nghĩa bằng các lớp tương ứng của Cocos2dx V3 nhé ( ví dụ: TransitionFlipY - lộn theo trục Y,  TransitionFade - làm mờ dần, TransitionZoomFlipX - phóng to theo trục X ) vậy đó

- Bài này đang tạm dừng...

Bài 9: Làm game đầu tiên - Tạo nhân vật (Part -1)

Tài liệu tiếng Việt học Cocos2dx

Hi all!

Đúng là học thầy không tày học bạn, học bạn không bằng...tự đọc sách. Đọc sách mà cũng không xong thì khỏi học. hêhê

Nói vậy cho vui thôi, khi học bất cứ ngành nghề gì chúng ta đều phải cần tới sự hướng dẫn chỉ dạy từ những cuốn sách, từ thầy giáo hoặc bạn bè, và ngày nay là bác Google.

Sau một thời gian tìm tòi trên mạng, mình cũng tìm được Vô số sách hướng dẫn Cocos2d-x trên mạng NHƯNG, toàn phiên bản cũ 2.x đổ về trước.VÀ có một khó khăn nữa là, 

1/ Sách đó toàn tiếng ANH, TRUNG, HÀN, NHẬT. ( không đến nỗi ko thể đọc)
2/ Trong sách chỉ có một số đoạn code, hướng dẫn, giải thích. Còn lại Source đầy đủ nằm trong đĩa gốc hoặc trên 1 trang tính phí ( bán kèm sách online mà )

Có một cuốn nổi tiếng nhất là Cocos2d-x by Exam mình cũng tìm thấy nhưng cũng mắc phải 2 vấn đề trên, nên mình quyết định là tự mình tìm hiểu Engine vậy. Vì đọc sách với code cũ có khi mất thời gian viết lại code cho Engine mới .

Dù sao mình cũng sẽ chia sẻ với các bạn tài liệu này để tham khảo. bạn nào xài Engine cũ cũng rất hữu ích đấy. Trong sách này có 4 Game, mình mới có 1 game đủ source code. Chia sẻ sau nhé

Tin vui cho anh em, đã ra Cocos2d-x V3.0 FINAL

Hix!

Trong thời gian mình miệt mài viết bài về Cocos2d-x V3 RC0, RC1,RC2 thì tại trang chủ đã ra bản Cocos2d-x V3.0 FINAL rồi, vui vãi. Hi vọng là nó sẽ còn được support dài dài

Trong bản FINAL này mọi thứ hầu như đã hoàn thiện tốt phục vụ cho việc làm game của lập trình viên, Thực sự là có quá nhiều thứ hay, nhưng do trình độ có hạn và mới tìm hiểu nên không biết là có gì nổi trội hơn các bản trước không. hehe, Nhưng 1 điều chắc chắn là nó đủ sức làm được những gì 1 game 2D, 2,5D yêu cầu



Tin vui thứ 2 là: trên trang chủ đang tổ chức 1 cuộc thi viết hướng dẫn để quảng bá cho Engine này

Cocos2d-x 3.0 Tutorial Competition On
deadline đến cuối tháng 5. Như vậy là khoảng tháng 7 chúng ta sẽ có những bài Tut chất lượng ( bằng tiếng Anh) để tham khảo rồi. 

Nhưng điều này làm mình cũng hơi e ngại là cùng với chiến dịch quảng bá này liệu mai mốt Engine này có thu phí hay ko?? Haizzz! Nếu thế thì buồn lắm.

Thôi trong thời gian chờ đợi, chúng ta tự mày mò và nghiên cứu những code cũ vậy!

Chủ Nhật, 27 tháng 4, 2014

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

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á



Thứ Sáu, 25 tháng 4, 2014

Hướng dẫn Chữ To Trên Facebook

Hôm nay đang rầm rộ trào lưu chữ to trên facebook. Và sau đây mình sẽ hướng dẫn các bạn làm nó.


Đầu Tiên Vào :
https://www.facebook.com/notes/



Tạo 1 Note Mới :D


Tiêu đề: tùy ý
Nội dung : Tùy biến theo ý bạn

<div><div><p><big><big><big><big><b><big><b><b><a href="https://www.facebook.com/dovanhieu2509">Yêu anh đi anh không đòi quà</a></b></b></big></b></big></big></big></big></p></div></div>

Chúc các bạn thành công

Thứ Hai, 21 tháng 4, 2014

Giải pháp Tiếp thị lại Web với Power Editor

Power Editor là một công cụ hỗ trợ quảng cáo với nhiều tính năng nâng cao so với Facebook Ads, và được cung cấp bởi Facebook.

Hiện nay, facebook đã trở thành một kênh quảng cáo và bán hàng hiệu quả. Với khả năng hiểu biết sâu sắc về đối tượng sử dụng, facebook có thể hiển thị quảng cáo chính xác với các nhóm đối tượng được xác định trước. Điều này giúp tăng hiệu quả, tiết kiệm chi phí cho nhà quảng cáo.

Người sử dụng Facebook Ads có thể Target khách hàng theo: độ tuổi, giới tính, vị trí địa lý, ngành nghề, mối quan tâm... Trước khi lựa chọn hình thức quảng cáo phù hợp: tăng like, event... và cách thức tính phí: hiển thị, nhấp chuột, hành động cụ thể.

Nhà quảng cáo thậm chí còn có thể lựa chọn hiển thị quảng cáo với một danh sách khách hàng (UID) có sẵn. Danh sách này có thể được lấy từ các fanpage xác định, hoặc nhiều nguồn khác nhau (mail, số điện thoại, UID).

Ví dụ bạn bán đồ thể thao, ban hoàn toàn có thể target danh sách và nắm trong tay tệp UID các thành viên của một fanpage về thể thao. Điều này có thể dễ dàng thực hiện được với một số phần mềm SEO miễn phí hiện nay có trên thị trường.
Tuy nhiên việc vẫn có một cách khác để bạn có thể nhắm trúng khách hàng mục tiêu mà không cần phải thông qua các trường lọc trong Facebook Ads, cũng không cần phần mềm để quét UID. Đó là Power Editor.

Power Editor cung cấp giải pháp Remarketing khiến cho việc quảng cáo của bạn thuận lợi hơn.

Bên cạnh một số tính năng nâng cao so với Facebook Ads như: quản lý Multi-Account; Ad Like Page, Click Link; Tự thiết lập Pricing CPC, CPM, Reach, Action... Power Editor cho phép thống kê người dùng đã vào website của bạn (thông qua một đọan code). Sau đó bạn có thể hiển thị quảng cáo với đúng nhóm khách hàng này. Sản phẩm, dịch vụ của bạn sẽ được cung cấp tới đúng đối tượng khách hàng tiềm năng:

- Trước tiên bạn cần vào
https://www.facebook.com/ads/manage/powereditor/
để có thể sử dụng dịch vụ này.
Tại Menu "Thêm công cụ" các bạn chọ "Đối tượng"

Nâng cao hiệu quả quảng cáo facebook với Power Editor

Tại menu "Tạo người xem" chúng ta chọn "Đối tượng tùy chỉnh"
Nâng cao hiệu quả quảng cáo facebook với Power Editor

Tại cửa sổ tiếp theo các bạn chọn: "Đối tượng tùy chỉnh từ Trang web của bạn"
Nâng cao hiệu quả quảng cáo facebook với Power Editor

Ở cửa sổ tiếp theo các bạn tick vào Tôi chấp nhận... để đồng ý với điều khoản sử dụng dịch vụ, và nhấp vào Tạo pixel "Tiếp thị lại Web"
Nâng cao hiệu quả quảng cáo facebook với Power Editor


Các bạn copy đoạn code bên trong ô, dán vào web/blog.
Nâng cao hiệu quả quảng cáo facebook với Power Editor
Như mình thì dán vào blog
Nâng cao hiệu quả quảng cáo facebook với Power Editor


Chú ý là đoạn code phải nằm giữa 2 thẻ <head> và </head> như thế này nè. Tiếp theo là quay về Power Editer bấm vào nút "Tạo đối tượng".
Nâng cao hiệu quả quảng cáo facebook với Power Editor

Nhập tiêu đề và mô tả cho web/blog của các bạn ở đây nhé.
Và chọn thời hạn lấy "mẫu". Mặc định là 30 ngày, nhưng mình để là 90 ngày.
Sau đó các bạn nhấp vào "Tạo mới"
Nâng cao hiệu quả quảng cáo facebook với Power Editor

Thê là xong, việc còn lại chỉ là chờ đợi...
Nâng cao hiệu quả quảng cáo facebook với Power Editor

Các bạn có thể kiểm tra lượng khách hàng của mình bất cứ khi nào có thể nhé. Trong facebook ân vào "Đối tượng".

Nâng cao hiệu quả quảng cáo facebook với Power Editor
Woa...! 
Qua ba ngày mình đã có trong tay 1900 UID từ chính blog của mình, có thể chạy quảng cáo được rồi, nhưng cứ để dài dài một chút cho nhiều hơn.
Nâng cao hiệu quả quảng cáo facebook với Power Editor

Các bạn cũng có thể chọn lấy "mẫu" theo từng quốc gia cụ thể nhé.
Nâng cao hiệu quả quảng cáo facebook với Power Editor


Dài quá rồi !
Hẹn gặp lại các bạn sau nhé.

Chủ Nhật, 20 tháng 4, 2014

Bài 6 - Ball - Physics cơ bản trong Cocos2dx -v3 (Part2)




Hi cả nhà!

Thời gian qua nhanh quá mà chả làm được cái gì, chán ghê. Cũng tại mình vừa vấp phải mấy vấn đề khó giải quyết trong cocos2dx - V3 nên tìm hiểu mãi mới ra. Trong bài này mình cũng trình bày luôn vấn đề đó là gì. Bây giờ chúng ta cùng tiếp tục bài trước về Physics nhé

Ở bài trước chúng ta đã tạo mới 1 Project Ball rồi đúng không, bây giờ là phần code thể hiện physics trong đó.

Let's go!


Các bạn theo đường dẫn sau: Q/android/project/ball/class, mở file HelloWorldScene.h lên. Code của file đó sẽ như vầy:

#ifndef __HELLOWORLD_SCENE_H__

#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

USING_NS_CC;

class HelloWorld : public cocos2d::Layer

{

public:

Sprite* _ball;

PhysicsWorld* m_world;

void setPhyWorld(PhysicsWorld* world){ m_world = world; };

static cocos2d::Scene* createScene();

virtual bool init();

virtual void onAcceleration(Acceleration* acc, Event* unused_event);

bool onContactBegin(const PhysicsContact &contact);

CREATE_FUNC(HelloWorld);

};


#endif // __HELLOWORLD_SCENE_H__

Các bạn không phải sửa đổi gì nhé, mình sẽ giải thích 1 chút về mấy thứ "là lạ trong đó"cho mọi người"

Sprite* _ball; // là 1 con trỏ kiểu Sprite tên là _ball, con trỏ này để quản lý cái gọi là quả bóng trong chương trình chúng ta.

PhysicsWorld* m_world; // Con trỏ kiểu PhysicsWorld tên m_world, gán cho nó các thuộc tính vật lý

void setPhyWorld(PhysicsWorld* world){ m_world = world; }; //hàm gán thuộc tính vật lý cho m_world,

virtual void onAcceleration(Acceleration* acc, Event* unused_event); // hàm này liên quan tới gia tốc kế thì phải
bool onContactBegin(const PhysicsContact &contact); // Hàm này để phát hiện va chạm giữa 2 quả bóng

Tiếp đến các bạn mở file HelloWorldScene.cpp lên nào (file nguồn các bạn down ở bên dưới nhé, vì mình dán vào đây thì bài dài dòng quá), trong đó bạn chú ý một số đoạn sau,

Trong hàm tạo Scene : Scene* HelloWorld::createScene(){}

auto scene = Scene::createWithPhysics(); // Câu lệnh này tạo 1 Scene gắn thuộc tính Physics
---

auto layer = HelloWorld::create(); // Tạo 1 layer của lớp HelloWorld

layer->setPhyWorld(scene->getPhysicsWorld()); // đặt thuộc tính Physics cho biết m_world của đối tượng layer,

scene->getPhysicsWorld() //nghĩa là lấy Physics của scene rồi gán cho m_world của layer

tiếp theo, hàm init()

_ball = Sprite::create("Ball.jpg", Rect(0, 0, 52, 52)); // Tạo 1 quả bóng nằm trong hình vuông 52 pixel

_ball->setPosition(Point(400,600)); // đặt ở vị trí 400, 600

auto ballBody = PhysicsBody::createCircle(_ball->getContentSize().width / 2); // Tạo 1 khung body có đặc tính vật lý để phát hiện va chạm, khung này dạng tròn có đường kính = nội dung của _ball chia 2.

ballBody->setContactTestBitmask(0x1); // Cái này rất quan trọng, nếu ko có thì hàm onContactBegin ko có tác dụng, tìm trên mạng mãi mới sửa được lỗi này

_ball->setPhysicsBody(ballBody); // Gán body cho _ball

this->addChild(_ball); // thêm vào layer HelloWorld đã tạo ở trên

ball2 được tạo ra tương tự

tiếp theo, đoạn này sẽ tạo ra 1 khung bao quanh màn hình, khi quả bóng chạm vào sẽ dừng lại. nó giống một bức tường ( 1 cái hộp ) vậy thôi, không cần giải thích nhiều nhé, cứ code mà đập thôi

auto edgeSp = Sprite::create();

auto boundBody = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 3);

edgeSp->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));

edgeSp->setPhysicsBody(boundBody);

this->addChild(edgeSp);

edgeSp->setTag(0);

Tiếp theo, quan trọng nè

auto Listener = EventListenerPhysicsContact::create(); // Biến này để "lắng nghe" các tương tác vật lý xảy ra

Listener->onContactBegin=CC_CALLBACK_1(HelloWorld::onContactBegin,this); // gọi hàm onContactBegin, hàm này sẽ xử lý khi va chạm xảy ra, hàm này là hàm chồng lên( gọi là hàm overide của 1 hàm mẫu đã có của thư viện - bạn nào học C++ sẽ hiểu rõ).

_eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);

// dòng này để xử lý ông Listener bên trên kia,

Túm lại đoạn trên đây để phát hiện ra tương tác giữa 2 quả bóng bạn tạo ra, rồi gọi hàm onContactBegin để xử lý.

Bạn mới học thì cứ dập khuôn từng đoạn code, tạm thời đừng hỏi sao phải viết thế, viết khác được không ( Haizzz, ko biết giải đáp thế nào nhỉ). Viết khác được, nhưng hãy nắm chắc cái ban đầu đi đã rồi phát triển sau.

Bây giờ tới hàm onContactBegin{}, format của nó chắc chắn phải viết như sau, sau đó thêm gì thì thêm vào trong 2 dấu ngoặc

bool HelloWorld::onContactBegin(const PhysicsContact &contact)

{

return true;

}

thêm đoạn này vào để xóa 2 quả bóng khi chạm nhau

auto ObjA = (Sprite*)contact.getShapeA()->getBody()->getNode();

auto ObjB = (Sprite*)contact.getShapeB()->getBody()->getNode();

this->removeChild(ObjB,true);

this->removeChild(ObjA,true);

tiếp theo, hàm này this->setAccelerometerEnabled(true); // Gia tốc kế của máy điện thoại

Chạy thử nhé, các bạn đừng quên lệnh này nhé

cocos run -s q:android/project/ball -p win32 

Nếu bạn thấy 2 quả bóng đập vào nhau và biến mất là đã thành công

Bạn thử bỏ dòng lệnh ballBody->setContactTestBitmask(0x1); đi xem, 2 quả bóng có va vào nhau nhưng ko có gì xảy ra phải không. Hehe, mỗi dòng lệnh này mà mình tìm kiếm mất gần tuần. HIX

Vấn đề Physic đã giải quyết xong

Nâng cao lên 1 chút nào

Xóa dòng this->setAccelerometerEnabled(true); và layer->setPhyWorld(scene->getPhysicsWorld());, Xóa tiếp hàm onAcceleration, kết quả ko đổi đúng ko, tốc độ rơi vẫn thế (trên win), 2 quả bóng chạm nhau vẫn biến mất. Lệnh này hình như thiết lập gia tốc kế. Các bạn thử thiết lập và xoay màn hình điện thoại xem nhé. Quả bóng sẽ lăn theo hướng rơi xuống cạnh đáy màn hình

Nhưng thử xóa dòng _ball->setPhysicsBody(ballBody); ball2->setPhysicsBody(ball2Body); Bạn sẽ thấy 2 quả bóng đứng im luôn. Có thể thấy hàm này giống như việc đặt vào quả bóng 1 khối lượng nào đó vậy ( chắc tương đương với bán kính). Quên mất vật nặng nhẹ đều rơi như nhau với gia tốc G mà

Bây giờ thêm lại 2 lệnh setPhysicsBody bên trên, rồi thêm dòng lệnh sau: scene->getPhysicsWorld()->setGravity(Vect(0.0f,-5000.0f)); Bạn sẽ thấy quả bóng rơi rất nhanh, đó, chỗ này chính là thiết lập gia tốc trọng lực, sét càng cao thì rơi càng nhanh.

Như vậy qua bài này, bạn đã biết làm thế nào để thiết lập 1 Physics cơ bản cho chương trình rồi nhé. Sang phiên bản mới ( mình đang xài V3 RC2) bạn chỉ cần nắm mấy lệnh cơ bản sau

auto scene = Scene::createWithPhysics(); // Tạo 1 Scene có thuộc tính Physics ( đã bao gồm gia tốc )

scene->getPhysicsWorld()->setGravity(Vect(0.0f,-3000.0f)); // Thay đổi gia tốc, nhớ là phải có dấu "-"

auto ballBody = PhysicsBody::createCircle(_ball->getContentSize().width);

_ball->setPhysicsBody(ballBody);  // thiết lập thuộc tính vật lý ( cụ thể là khối lượng và ranh giới của vật thể )

ballBody->setContactTestBitmask(0x1);  // Thiết lập sự phát hiện va chạm giữa 2 vật

// và đoạn này để lắng nghe sự va chạm nếu có

auto contactListener = EventListenerPhysicsContact::create();

contactListener->onContactBegin = CC_CALLBACK_1(HelloWorld::onContactBegin, this);

_eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);

DOWN Mã nguồn và file Resource

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

Google Global Internet Access và chiêu trò lừa đảo

Một ngày đẹp trời, bạn nhận được 1 mail có ghi người gửi là: mail-noreply@googleglobalaccess.com
- một tín hiệu thường thấy từ Google.

Google Global Internet Access và chiêu trò lừa đảo

 Bạn tải file đính kèm xuống để đọc nội dung
Google Global Internet Access và chiêu trò lừa đảo Woa, bạn có cơ hội nhận một trong các giải thưởng từ Google.
Google Global Internet Access và chiêu trò lừa đảo
Bạn vội bấm vào đường link và nhập mã xác thực.
Google Global Internet Access và chiêu trò lừa đảo
Bạn cần nhập user và pass của Google để có thể nhận quà.
Sau khi nhập đầy đủ và bấm Đồng bộ thì.... xin chúc mừng, bạn có nguy cơ mất tài khoản Gmail, và rất nhiều thông tin quan trọng khác.

Chiêu trò của những kẻ mạo danh Google là:
- Nhận gửi là: Nhóm gmail
- Lại còn noreply
- Giao diện giống hệt của Google
Mình vừa bị xong, may là tài khoản mail bị gửi là là tải khoản rất quan trọng nên việc trước tiên là đi kiểm tra, xác minh thông tin. Qua đó biết được một số bạn đã bị lừa theo hình thức này. Vì thế mình đưa thông tin lên để mọi người cùng cảnh giác. Mọi người chú ý:
- Đề phòng với các dịch vụ lạ
- Lướt web ở chế độ ẩn danh (Ctrl - Shift - N) với các wesite lạ
- Cài đặt xác minh tài koản gmail 2 lần (thông qua 1 tài khoản gmail khác và số điện thoại)
- Thấu hiểu một triết lý: "chỉ có trong bẫy chuột mới có pho mát cho không"
- Chia sẻ thông tin để mọi người cùng cảnh giác.

Thứ Sáu, 18 tháng 4, 2014

Đường vào nghề SEO

Đang định check mail một lượt rồi đi ngủ mai còn về quê, định rằng trong 2 ngày tới chẳng động tới máy tính hay là SEO siếc gì cả thì gặp được mail này. Chẳng đừng được nên ngồi trả lời, định riêng thôi, nhưng nghĩ lại đây cũng là tâm sự của nhiều bạn làm SEO nên post lên đây để mọi người cùng trao đổi.

Chào Nguyễn Hoàng, tình cờ mình biết được trang web của bạn thông qua đứa em. Phải nói là văn phong của bạn rất cuốn hút và tinh thần chia sẻ rất nhiệt tình, các dự án seo được chia sẻ rất thực tế, và mình rất ấn tượng về điều đó.

Mình cũng đang trên đường trở thành seoer, nhưng con đường thật chông gai quá, tự học mà không có người dẫn đường thì quả thật giống như lạc vào một cõi mê vậy, mờ mờ ảo ảo.

Mình chia sẻ 1 chút về quá trình của mình nhé:

Mình biết đến seo từ trước tết, lúc đó vốn dĩ là dân xây dựng nên rất ít dùng đến internet để kết nối thế giới, đến cả facebook cũng không có dùng. Vì vậy, thật khá khó khi tìm hiểu mọi thứ từ con số 0.

Tình cờ mình biết được khóa học online của Lê Nam bên Vietmoz, lúc đó giá của khóa học là 3tr. Trong túi mình lúc đó chỉ còn 500k nên mình có hỏi Lê Nam và được cậu ấy đồng ý cho học.

Phải nói khóa học rất tốt vì Lê Nam trang bị kiến thức căn bản cho mọi người, tuy nhiên, hơi xui là lúc ấy mình học với 1 cậu chuyên về it nên nhiều thứ Lê nam dạy lướt qua trong khi mình vẫn còn nhiều điều chưa hiểu lắm.

Học lý thuyết là một chuyện nhưng thực hành lại là một chuyện khác, mình vẫn chưa làm được seo.

Thấy không ổn, mình làm quen với một cậu ở Cần Thơ cũng làm seo được 2 năm rồi, cậu ấy nói sẽ đào tạo mình và mình chấp nhận làm free cho cậu ấy ( dự định là 3 tháng). Phải nói là seoer ở Cần Thơ như lá mùa thu, tìm hoài mà không thấy ai cả, khi ấy mình rất vui và cực kỳ hi vọng vào một ngày mai tươi sáng.

Nhưng, cuộc sống vốn không như tưởng tượng, cậu ấy cực kỳ bận, hết làm dự án này đến dự án khác, chỉ thỉnh thoảng mới chỉ mình 1 chút mà thôi và chỉ là theo kiểu chỉ đâu đánh đó mà không có phân tích gì hết. Mình chán nản và sau 1 tháng, mình đành ở nhà tự ngâm cứu tiếp vậy. Hơi buồn.

Cùng thời điểm ấy, trên face có 1 cậu chuyên về seo tuyển làm việc thực tập online và hứa hẹn sẽ đào tạo trở thành seoer chuyên nghiệp. Làm free trong 3 tháng. mỗi tuần dạy 1 buổi cộng thêm 1 buổi hỗ trợ thắc mắc. ( quy định là phải làm việc mỗi ngày 3h/6 buổi). Mình lại thắp lên ngọn lửa hi vọng trở thành seoer pro đích thực.

Nhưng cuộc đời lại vẫn không như mơ ước, cậu ấy cũng là người khá bận rộn và lại không thể thực hiện được như những dự định ban đầu của cậu ấy. Khóa đào tạo diễn ra không tốt, không chia sẻ bằng teamview hay gobinar mà bằng hình thức ... chat trên skype ( cũng có 1 buổi online chia sẻ hình ảnh, và thêm 1 vài video ngắn để dạy mọi người) 

Mặc dù cậu ấy rất nhiệt tình, mỗi khi hỏi riêng trên face thì đều trả lời cả, nhưng seo rất cần nhiều kinh nghiệm và kỹ thuật thực hành nên việc tổ chức khóa đào tạo hoàn toàn thất bại khi chỉ dạy seo mà ko có hình ảnh. Lại buồn tiếp tập 2
 
Tính ra mình đã tham gia gần 3 tháng cho cả seoer Cần Thơ trước đây và giờ là cậu ấy. Nhưng cái mình cần thì lại không ai dạy cả. Seoer thường hứa rất nhiều mà khi thực hiện lại chẳng được bao nhiêu. Điều đó khiến mình rất nản

Hiện mình có kiến thức căn bản cũng tương đối khá, nhưng giờ vẫn còn rất thắc mắc về vấn đề phân tích đối thủ và lên chiến thuật vượt qua đối thủ như thế nào, làm thế nào để ước tính thời gian đạt mục tiêu? Giờ chẳng biết hỏi ai.

Mình thấy bạn chia sẻ rất nhiệt tình và đoán rằng bạn rất giỏi và tốt, liệu bạn có thể dành 1 buổi chia sẻ mình về vấn đề này được không? hoặc nếu được bạn có thể cho mình tham gia vào dự án của bạn được không? chỉ cần trả nửa lương so với các seoer khác mình cũng vui lòng, vì mình rất mong được học cách seo đúng đắn. Hiện giờ chủ yếu là mình đi spam các diễn đàn là chính thôi

Cảm ơn bạn đã đọc thư này, cho dù kết quả ra sao, mình cũng rất vui khi được quen với bạn và đọc bài trên blog của bạn. ( giờ mới biết bạn là mod của idichvuseo, bất ngờ quá)

có gì cứ liên hệ qua mail mình nhé: manhtienct....
Đường vào nghề SEO
Bạn thân mến, trước tiên rất cảm ơn bạn vì lời khen ngợi. Bạn nói đúng, SEO rất khó. Ngày trước, khi mình mới SEO chỉ cần viết keyword, copy bài, làm vài link rao vặt là xong. Bây giờ thì quá nhiều kiến thức, quá nhiều khái niệm, quá nhiều thuật toán và quá nhiều yếu tố tác động, chi phối kết quả SEO.

Việc bạn học mà không làm được ngay cũng là chuyện bình thường thôi. Đợt vừa rồi mình có phỏng vấn 30 bạn, chọn về làm cho công ty của đối tác 4 bạn. Các bạn đó đều học các ngành liên quan đến công nghệ, một số là từ khoa Thương mại Điện tử. Một số bạn đã học qua khóa đào tạo SEO ở các trung tâm. Khi vào mình đào tạo lại theo kiểu: sáng tranining 2 tiếng, sau đó cho làm việc luôn trên dự án của công ty, liên tục nửa tháng. Mình chuyên về nội dung, một bạn khác chuyên về kĩ thuật, cùng kèm sát rạt, sai đâu sửa đó... vậy mà cả tháng nay vẫn chưa đáp ứng được yêu cầu của mình ở Level 2 (trên 2 còn có 3, 4 - theo tiêu chí của mình). Vì vậy so với xuất phát điểm của bạn thì bạn không cần phải quá lo lắng. SEO khó mà !

Việc đi làm cộng tác viên cho các đơn vị SEO không có gì là lạ, đôi bên cùng có lợi. Vấn đề là bạn tìm được đúng người. Mình biết có một số bên tuyển ồ ạt, loại ồ ạt để tận dụng sức lao động.

Việc thực tập SEO cũng không hẳn mang lại kết quả vì nhiều nơi không phải đơn vị SEO. Họ thậm chí không phân định rõ ràng SEO là gì, hoặc đơn giản là cày link, copy nội dung. Một số nơi làm SEO nhưng nhận CTV theo kiểu lấy quan hệ, giao bừa cho phân tích một website nào đó. Các bạn "tự sướng" với nhau, bản phân tích có lẽ cuối ngày cũng chỉ cho vào thùng rác. Việc ai nấy làm. Không ai sửa sai cho các bạn.

Cái này không phải nói xấu mà là chọn mặt gửi vàng, đôi khi cũng là may mắn nữa.

Việc phân tích đối thủ và chiến lược không đơn giản, bạn có thể đọc thêm tại đây:
» SEO - nhà nghèo vượt khó !?
» SEO - nhà nghèo vượt khó !?
» SEO nhà nghèo khoan cắt bê tông
» SEO - nhà nghèo vượt khó !?
Và đọc thêm tài liệu SEO tại đây:
» Ebook SEO Copywriting
Còn rất nhiều bài viết của các anh em khác, bạn cứ chịu khó tìm hiểu trên iDVS và search Google.

Tính mình không thích đông người, nếu bạn ở Hà Nội thì có thể off cà phê với mình, face to face. Còn ở xa thì mail. Mình không giỏi, cũng chưa hẳn là tốt. Tuy nhiên, mình khuyên bạn một điều, đừng chơi đuổi hình bắt bóng với SEO.

Hãy nghĩ về bản chất của SEO!

Để mình gợi ý cho bạn: SEO, adword, facebook, Google... đều có chung bản chất. Khi bạn nhìn được bản chất của chúng bạn sẽ thấy mọi thứ đơn giản.

Ngoài ra cái gì cũng có giá của nó. Ngày mới học SEO mình làm việc 18h một ngày. Giờ ít hơn một chút nhưng cũng rất bận. Từ tháng 2, bố, mẹ mình ở quê xây nhà, bây giờ mấy tháng rồi mình cũng chưa về nữa. Nhiều người biết chuyện và không biết chuyện, thông cảm, trách móc... Rồi nhiều chuyện khác. Có một câu hỏi cho bạn rằng: có nghề tất có nghiệp, bạn có thể thành công với SEO, nhưng bạn đã bao giờ nghĩ về cái giá của thành công.

Bạn có sẵn sàng trả giá cho SEO không ?

Thứ Hai, 14 tháng 4, 2014

[ Xử Lý Ảnh] : Phần ngày 2-4-2014

3.6.4 . Dùng đạo hàm cấp 1 tăng độ nét của ảnh .

Công thức :
đạo hàm cấp 1 của 1 ảnh có tên gọi là Gradian Laplace.
Người ta quan tâm đến độ lớn của đạo hàm cấp 1 :
 Độ lớn vec tơ đạo hàm cấp  của
ký hiệu là M(x,y) :

Thường được gọi là gradient image :  
Lấy căn bậc 2 ta được : 
g(x), g(y) là ảnh. M(x,y) cũng là ảnh .

Ký hiệu cửa sổ 3x3 của ảnh :

gx=z8-z5 hoặc gx=z9-z9
gy= z6-z5 hoặc gy= z8-z6

Mặt nạ đạo hàm nên có kích thước là lẽ để có phần tử trung tâm nên Sobel mở rộng định nghĩa đạo hàm: 

để đầu ra bằng 0 ảnh trong miền bằng phẳng.

3.7 (không cần )

3.8. Dùng kỹ thuật mờ để biến đổi độ sáng và lọc trong không gian.

3.8.1. Nhắc lại lý thuyết tập hợp.


Chủ Nhật, 13 tháng 4, 2014

Bài 5: Ball - Physics cơ bản trong Cocos2dx - V3.1 ( Part 1)

Hi cả nhà!
Chán quá đi, dạo này tình hình sức khỏe đi xuống quá. Sáng nay uống 1 nhúm thuốc các thể loại giờ nôn nao chóng mặt vãi ( Sốc cmn thuôc rồi). Lần trước có 1 lần cũng uống quá liều, may chưa tiêu.

Tay chân mặt mũi, trí óc không mỏi, mà mắt mỏi và choáng quá. Thôi cố viết xong bài này rồi đi nghỉ.

Vậy là chúng ta đã đi qua được 2 bài quan trọng là cài đặt Cocos2dx và HelloWorld trong các phần trước rồi. Các bạn vẫn còn hào hứng cùng tôi đi tiếp không nào. Haizzz, chắc có một số người rớt lại phía sau hoặc bỏ cuộc rồi không biết chừng. Dù thế nào, dù 1 mình tôi cũng sẽ đi tới cùng. :))

Tôi xin nhắc lại với các bạn là: 
1/ Những gì tôi viết trong này hoàn toàn là tham khảo từ các bài code ví dụ trên mạng nước ngoài, nên có thể sẽ không theo 1 hệ thống nào cả, vì tôi ko phải là nhà viết sách chuyên nghiệp, nên không thể hệ thống lại được theo cách tốt nhất. Tôi sẽ ưu tiên cho các bài ngắn dễ hiểu, rồi đến bài dài khó hiểu, vậy thôi, hoặc theo thứ tự thời gian các bài code tôi sưu tầm được.

2/ Vì phiên bản Cocos2dx v3.0 (giờ đã là 3.2 RC0 ) này là phiên bản mới nhất nên chẳng có sách nào đâu. À, có đấy nhưng bằng tiếng Hàn + Trung, đang trong quá trình chuẩn bị dịch sang Anh, nhưng mà chắc chắn là phải mua = tiền, nhưng cũng ko biết mua ở đâu nữa, và chắc phải 1-2 năm nữa Việt Nam mình mới có. Hehê, lúc đó thì chúng nó lại ra phiên bản 4, rồi 5 và rồi chúng ta lại chờ sách. Sao luẩn quẩn vậy? chả lẽ chúng ta cứ phải chờ đợi vào người khác?

3/ Các sách cũ hơn thì hầu như không dùng được vì hồi trước tiền thân của Cocos2d - X ( nhớ là có chữ X nhé ) là Cocos2d - iphone ( cho riêng Iphone ) nên các Sách trước đây viết cho lập trình viên Iphone, các bạn nhé. Code là Oject -C chứ không phải C++ như Cocos2d - X ( đa nền ) như bây giờ. Bạn vẫn có thể sử dụng code Object - C đó để port sang code C++ , nhưng khi đó trình độ và kinh nghiệm ít nhất cũng phải 6 tháng học cocos2d-x nhé. Thôi thì chịu khó học cái mới mẻ đi.

Dài dòng lắm rồi, túm lại là, có cái để học, để làm là tốt lắm rồi, không lại rảnh rỗi sinh nông nổi thì chết.

Bắt đầu thôi

Đầu tiên bạn tạo 1 Project mới cho mình bằng CMD như sau

>cocos new Ball -p com.vn.Ball -l cpp -d Q:/android/project

Giải thích chút, lệnh trên sẽ tạo 1 Project tên Ball trong thư mục Q:/android/project

-p com.vn.Ball là cú pháp package. bạn có thể thay đổi 1 chút nhưng nhất thiết phải có 2 cái dấu chấm (.) như trên nha. Tốt nhất là làm theo mình.
-l cpp: là lựa chọn ngôn ngữ C++
- d Q:/android/project: là thư mục lưu Project thôi

OK, rồi. Bạn thấy đó cái Project Ball lần này cũng chẳng khác gì  cái Project HelloWorld hôm trước cả đâu, không tin bạn vào kiểm tra xem, cấu trúc thư mục rồi file nguồn cũng giống hệt nhau mà. Bạn tự kiểm tra nhé. Nhưng rồi chúng ta sẽ làm cho nó khác đi một chút, đó là thêm physics ( tạm gọi là thuộc tính vật lý đi) vào trong chương trình Ball này.

Physics là gì, tại sao phải thêm Physics?

Đơn giản lắm các bạn ơi. Physics là sự mô phỏng các hiện tượng vật lý trong game sao cho giống với ngoài đời thực. Sự mô phỏng này có thể giống nhiều hay ít tùy thuộc vào ý tưởng game, và quyết định của lập trình viên.

Các physic cơ bản bạn đễ nhận thấy là: Hình ảnh, Âm thanh, gia tốc rơi, chuyển động 1 vật, Va chạm nhau...

Hẹn các bạn bài sau nhé, nay mỏi mắt quá, sẽ sớm lên sóng thôi.


Thứ Sáu, 11 tháng 4, 2014

Bài 4: Hello World. Bài code đầu tiên

Hi mọi người!

Dạo này không hiểu sao ốm yếu quá, ít có thời gian nghiên cứu. Nay sức khỏe đã tạm ổn, mình sẽ tiếp tục giới thiệu với các bạn bài đầu tiên về code. Mà không biết còn ai thắc mắc về cách cài đặt không?

Hiện tại đến thời điểm mình sửa bài này (7-11-2014, đã có Cocos2d-x 3.2 RC0) rồi. Và mình khuyên các bạn là chỉ nên tải và sử dụng các phiên bản có đuôi RC.x trở lên cho tới stable ( thường là ko ghi gì sau đuôi ví dụ 3.1.1 ) chứ ko nên sử dụng các bản Alpha.x hoặc Beta.x vì chúng vẫn còn trong giai đoạn thử nghiệm sẽ mắc nhiều lỗi không đáng có. Và khi mình update các phiên bản ( chỉ việc copy vào thư mục chưa Engine thôi - nội dung trong thư mục engine cũ thì xóa đi ) hầu như không gặp bất kỳ lỗi nào khi compile, run cả trên Win, hoặc Android. Chỉ gặp các lỗi liên quan tới code do thư viện của cocos2d-x có thay đổi 1 chút xíu ở phiên bản mới, sai đâu thì IDE sẽ báo ở đó để biết cách sửa thôi.

=> Cách cài đặt của các phiên bản Engine thế hệ 3.x là giống nhau ( tới thời điểm này ) nhé

Nếu các bạn đã từng học qua các loại ngôn ngữ lập trình, hẳn đã quen với loại bài viết Hello World, Your First Application rồi nhỉ. Ai đã tìm hiểu 1 chút rồi thì có thể xem nhanh qua phần này. Mình bắt đầu nhé.

A - Tạo và chạy thử Project

Đầu tiên, tạo một Project mới với tên Hello World bằng lệnh sau trong cmd

Run/cmd
>cocos new HelloWorld -p com.vn.HelloWorld -l cpp - d q:/android/myproject

Đợi khoảng 5 phút để nó tạo Project mới cho chúng ta

Xong rồi, vào Project mới tạo theo đường dẫn

Q:/android/myproject/helloworld, cấu trúc thư mục trong đó như sau:

Classes <- Quan trọng nhất nhé, nó chứa mã nguồn cpp hay lua tùy thuộc việc bạn chọn ngôn ngữ nào khi dùng lệnh new ở phía trên.
cocos2d <- thư viện của engine Cocos2d - x.
proj.android <- dành cho việc build ứng dụng apk cho Android mobile.
proj.ios_mac  <- dành cho việc build ứng dụng cho Iphone và Mac OS ( Chỉ chạy được trên máy của Apple, hoặc máy cài Mac OS.
proj.linux <- dành cho việc build ứng dụng trên máy Linux.
proj.win32 <- dành cho việc build ứng dụng trên hệ điều hành Window 7, 8
proj.wp8-xaml <- dành cho việc build ứng dụng chạy trên Window phone 8
Resources <- chứa ảnh, font chữ, Map, định nghĩa vật lý,v.v...
.cocos-project.json <- chỉ định việc build project với ngôn ngữ nào, lua hay cpp.
CMakeLists.txt <- Danh sách thư viện phục vụ việc build project.

Tiếp theo chúng ta build và run thử trên Window nhé. Lệnh sau

>cocos run -s q:/android/myproject/helloworld -p win32

(gõ cocos run -h để được help)

Lưu ý: 
1/ Win mình xài là Win 7 32 bít, bạn nào xài XP, Win 7 -  64, Win 8 all, thì mình ko biết nhé. Các bạn thử xem thành công không. (Đã cài đặt và chạy trên win 7 - 64 ngon lành cành đào nhé.). Đã có nhiều bạn chạy Win8 OK rồi nhé

2/ Mình ko chắc xài máy ảo VMWare có chạy được không nhé

3/ Bạn có thể build thành ứng dụng .apk để chạy trên máy ảo Android, hoặc chơi máy thật luôn cho máu

>cocos compile -s q:/android/myproject/helloworld -p android --ap 16
--ap 16 là chỉ định dành cho android 4.1.2 trở lên

cài vào máy ảo

>adb install q:/android/myproject/helloworld/bin/debug/android/helloworld-debug-unligned.apk
hoặc
>cocos run -s q:/android/myproject/helloworld -p android --ap 16

Nếu không báo lỗi nào và xuất hiện ảnh như thế này, nghĩa là bạn đã thành công rồi đó. Mình cam đoan nếu các bạn cài đặt như bài trước của mình thì chắc chắn sẽ thành công.



B - Tìm hiểu Code

Bên trên mới là phần tạo và chạy thử thôi, còn trong phần này chúng ta cùng tìm hiểu những dòng lệnh đầu tiên
Các bạn vào thư mục Classes của Project, trong đó có 4 file
AppDelegate.h, AppDelegate.cpp
HelloWorldScene.h, HelloWorldScene.cpp

Mới đầu mình chỉ nên tìm hiểu 2 file HelloWorldScene.h, HelloWorldScene.cpp thôi nhé. 2 file bên trên có chức năng theo dõi thông số của ứng dụng thôi. Nhưng bạn không thể xóa 2 file này nhé

file HelloWorldScene.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

class HelloWorld : public cocos2d::Layer
{
public:
    static cocos2d::Scene* createScene();

    virtual bool init();  
    
    void menuCloseCallback(cocos2d::Ref* pSender);
    
    CREATE_FUNC(HelloWorld);
};

#endif // __HELLOWORLD_SCENE_H__

cấu trúc rất giống 1 chương trình C++ phải không, thì nó chính là C++ mà, hehee

Trước khi tìm hiểu code, các bạn nên đọc qua, hoặc ôn lại kiến thức C++ chú nhé. Mình sẽ cố gắng giải thích các hàm chức năng hoặc các điểm mới trong cocos2dx 3 thôi

static cocos2d::Scene* createScene();  //tạo ra một cảnh mới
virtual bool init(); //Khởi tạo 1 đối tượng của lớp HelloWorld
void menuCloseCallback(cocos2d::Ref* pSender); //Nút Tắt ứng dụng
CREATE_FUNC(HelloWorld); //Chưa rõ lắm, nhưng tạm coi là cần phải có đi

file tiếp theo HelloWorldScene.cpp

#include "HelloWorldScene.h"

USING_NS_CC;

// hàm tạo 1 cảnh mới trả về con trỏ Scene*
Scene* HelloWorld::createScene()
{
  
    auto scene = Scene::create();  // tạo 1 đối tượng Scene
    
    auto layer = HelloWorld::create(); // tạo đối tượng HelloWorld

// thêm đối tượng HelloWorld vào Scene
    scene->addChild(layer);

// trả về con trỏ scene
    return scene;
}

// khởi tạo đối tượng HelloWorld
bool HelloWorld::init()
{
    //////////////////////////////
    // kiểm tra khởi tạo lỗi
    if ( !Layer::init() )
    {
        return false;
    }
    
// Lấy kích thước màn, và điểm tọa độ gốc
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Point origin = Director::getInstance()->getVisibleOrigin();


    //tạo nút đóng ứng dụng

    auto closeItem = MenuItemImage::create(
                                           "CloseNormal.png",
                                           "CloseSelected.png",
                                           CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
    
// Đặt vị trí nút đóng tại điểm tính theo công thức bên dưới
closeItem->setPosition(Point(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
                                origin.y + closeItem->getContentSize().height/2));

    // Tạo menu chứa nút đóng ở bên trên, đặt vị trí
    auto menu = Menu::create(closeItem, NULL);
    menu->setPosition(Point::ZERO);
    this->addChild(menu, 1); // thêm menu vào đối tượng HelloWorld

    /////////////////////////////
   // Tạo 1 dòng Text với font arial cỡ 24 pixel
    
    auto label = LabelTTF::create("Hello World", "Arial", 24);
    
    // đặt vị trí Text
    label->setPosition(Point(origin.x + visibleSize.width/2,
                            origin.y + visibleSize.height - label->getContentSize().height));

    // Thêm text vào đối tượng HelloWorld
    this->addChild(label, 1);

    // tạo 1 đối tượng loại sprite ( là các đối tượng có thể di chuyển trong game)
    auto sprite = Sprite::create("HelloWorld.png");

    // Đặt sprite lên vị trí giữa màn hình
    sprite->setPosition(Point(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));

    // Thêm đối tượng Sprite vào HelloWorld
    this->addChild(sprite, 0);
    
   // giá trị trả về của hàm init()
    return true;
}

// Hàm đóng ứng dụng
void HelloWorld::menuCloseCallback(Ref* pSender)
{

Director::getInstance()->end(); // Kết thúc chương trình.

// Nếu là IOS thì gọi lệnh exit(0);#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)

exit(0);

#endif

}

Tới đây, hẳn mọi người đã biết cách tạo và chạy thử 1 project thế nào rồi phải không. Lại còn biết được 1 phần code đơn giản nữa cơ đấy. Trong các bài sau nâng cao hơn sẽ giúp các bạn hiểu sâu hơn về Cocos2dx trong lập trình Game di động.
Bye bye!