Nội dung bài viết
Đăng ký học lập trình C++
Tại STDIO bạn được dạy nền tảng lập trình tốt nhất.
Đăng ký học
Trong quá trình phát triển ứng dụng, việc phát sinh ra lỗi ở một thành phần nào đó trong ứng dụng là điều không thể tránh khỏi. Dự án càng lớn, khả năng phát hiện lỗi càng thấp và chi phí cần sử dụng để giải quyết vấn đề càng lớn. Do đó, chúng ta nên quản lý dự án thành các thành phần riêng biệt.

Giới thiệu

Trong lập trình game, và điều này đúng cho nhiều lĩnh vực khác, việc gom nhóm các đối tượng để thực hiện từng chức năng riêng biệt là rất cần thiết. Việc phân chia các đối tượng và xử lý riêng biệt theo chức năng không chỉ giúp mã nguồn đỡ phức tạp mà còn tối ưu cho giai đoạn bảo trì sản phẩm sau này. Nắm bắt tư tưởng đó, tôi và các anh em trong nhóm tái phát triển dự án Sins đã áp dụng phương pháp này trong sản phẩm. Bài viết này nhằm chia sẻ một chút về phương pháp lập trình này và cách hiện thực nó trong Cocos2d-x.

Tiền đề bài viết

STDIO Games đã định hướng tư tưởng cho tôi về phương pháp Lập trình Hướng thành phần (Component-base Programming). Dự án Sins là dự án thực tế đầu tiên mà tôi có cơ hội sử dụng phương pháp này để phát triển, và việc này đã mang lại hiệu quả nhất định cho đến thời điểm này.

STDIO là sự chia sẻ, do đó tôi thực hiện bài viết này nhằm chia sẻ những điều đọng lại với tôi trong suốt quá trình thực hiện dự án. Bài viết này còn là lời cảm ơn đến nhóm phát triển dự án Sins đã mang đến một sản phẩm chất lượng và sâu sắc.

Đối tượng hướng đến

Bài viết dành riêng cho các lập trình viên đã có kinh nghiệm với Cocos2d-x và có tư tưởng lập trình tốt.

Tham khảo: Giới Thiệu Về Component-base Development.

Tư tưởng thành phần hoá

Trong quá trình phát triển ứng dụng, việc phát sinh ra lỗi ở một thành phần nào đó trong ứng dụng là điều không thể tránh khỏi. Dự án càng lớn, việc phát hiện lỗi và chi phí cần sử dụng càng trở nên phức tạp hơn. Do đó, chúng ta nên quản lý dự án thành các thành phần riêng biệt.

Trong thực tế, đối với Project Sins, chúng tôi phân chia Scene Gameplay thành các thành phần chính như sau:

  • Background: Hình ảnh nền của game. Background trong Sins bao gồm một bức ảnh tĩnh cùng với một số hiệu ứng đặc biệt.
  • Sidebar: Cột hiển thị thông tin bên trái của màn hình. Tại đây quản lý các thông số về Score, Highscore và một số button tuỳ chỉnh khác.
  • Gameboard:  Khu vực chơi chính của game, quản lý các Sin, các hiệu ứng của Sin và hiệu ứng khác.

Ngoài ra còn có các component hỗ trợ như Popup, Notification, … với những chức năng riêng biệt mà tôi không đề cập đến trong bài viết này.

Với cách hiện thực này, các chức năng sẽ được gom nhóm lại để phát triển riêng biệt. Các thành viên trong nhóm phát triển sẽ hiếm gặp tình trạng xung đột do nhiều người cùng thực hiện một công việc giống nhau. Mặt khác, khi cần bổ sung một chức năng nào đó, chẳng hạn như thêm một hiệu ứng vào background, ta sẽ dễ dàng nhận biết vị trí hiện thực của chức năng đó.

Hiện thực trong Cocos2d-x

Phần hiện thực tôi chỉ nêu ra một số điểm cần lưu ý khi sử dụng phương pháp này trong Cocos2d-x. Chi tiết các bạn vui lòng tham khảo project demo đính kèm bên dưới.

Lớp SceneGamePlay của Project Sins được hiện thực như sau:

class SceneGamePlay : public SceneBase
{
public:
       static cocos2d::Scene* createScene();

       virtual bool init();
       virtual void onExit();

       CREATE_FUNC(SceneGamePlay);
protected:
private:
       Sidebar*                     m_sidebar;
       Background*                  m_background;
       GameBoard*				    m_gameboard;
};

Scene này bao gồm ba component chính là Sidebar, Background và GameBoard. Mỗi component là một node riêng biệt kế thừa từ Node của Cocos2d-x. Hiện thực các component này như sau:

class Background : public Node
{
public:
       virtual bool init();
       virtual void onExit();

       CREATE_FUNC(Background);
protected:
       Sprite*                    m_background;
       NodeGrid*                  m_gridNodeTarget;

       Size                       m_visibleSize;
       Point                      m_origin;
private:
};
class Sidebar : public Node
{
public:
       virtual bool init();
       virtual void onExit();

       CREATE_FUNC(Sidebar);
protected:
       Sprite*                    m_title;
       Sprite*                    m_background;
};
class GameBoard : public Node
{
public:
	virtual bool init();
	virtual void onExit();

	CREATE_FUNC(GameBoard);
protected:
	Sprite*			m_gameboard;
};

Không quá đi sâu vào phần hiện thực, việc sử dụng các component này rất đơn giản. Trong SceneGamePlay.cpp, tôi khởi tạo các component này bằng phương thức create() và addChild vào scene theo các lớp tương ứng:

m_background = Background::create();
this->addChild(m_background, Z_BACKGROUND);

m_sidebar = Sidebar::create();
this->addChild(m_sidebar, Z_SIDEBAR);

m_gameboard = GameBoard::create();
this->addChild(m_gameboard, Z_GAMEBOARD);

Đối với các thành phần riêng trong game của bạn, thao tác thực hiện cũng tương tự theo các bước:

  • Khởi tạo component kế thừa từ Node.
  • Cài đặt các phương thức create(), init(), onExit() và các phương thức cần thiết khác.
  • Sử dụng như một đối tượng bình thường, sử dụng thao tác addChild vào đối tượng khác để hiển thị và xử lý cho đối tượng đó.

Download Demo

Project Demo dưới đây là các thư mục Classes và Resources trong một project Cocos2d-x. Bạn vui lòng khởi tạo project Cocos2d-x trên Windows trước và thay thế 2 folder tương ứng trong Demo. Tham khảo bài viết Cài Đặt Cocos2d-x Và Khởi Tạo Project Trên Windows của tác giả Nguyễn Minh Hiếu.

ProjectDemo.zip.

THẢO LUẬN