Search…

Quản Lý Vị Trí Của Các Đối Tượng trong Cocos2d-x

29/09/20203 min read
Hướng dẫn quản lý vị trí các đối tượng trong Cocos2d-x.

Trong lập trình game nói chung và lập trình game với Cocos2d-x nói riêng, việc xử lý “cứng” các đối tượng (như vị trí, tỷ lệ, góc quay,…) là điều nên tránh. Khi đem sản phẩm lên màn hình có tỷ lệ khác, vị trí các đối tượng có thể sẽ không còn được như mong muốn.

Do đó, việc quản lý động các đối tượng sẽ tối ưu hơn trong lập trình game đa màn hình. Bài viết sau giới thiệu cách hiện thực đơn giản giải quyết vấn đề trên trong Cocos2d-x.

Lớp Dictionary

Cocos2d-x đã hiện thực sẵn lớp Dictionary, hỗ trợ lập trình viên đọc file theo cấu trúc của file XML. Các key/value sẽ được lưu trữ trong file dưới dạng tag.

File lưu trữ position phải tuân theo 1 cấu trúc định sẵn với phần ở rộng mặc định của file là .plist. 

Hiện thực đơn giản file plist để minh họa với các key/value như sau:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
       "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>title</key>
    <string>540,1250</string>
    
    <key>button_play </key>
    <string>540,800</string>

    <key>button_sound</key>
    <string>200,1400</string>
</dict>
</plist>

Các phương thức cần lưu ý khi sử dụng Dictionary:

createWithContentsOfFile

Đối số truyền vào là đường dẫn đến file plist. Nếu đường dẫn không tồn tại sẽ trả về nullptr. Thông qua hàm này, toàn bộ dữ liệu có trong file plist sẽ được xử lý thành các bộ key/value. Cần tạo sẵn 1 đối tượng Dictionary để lưu trữ lại các bộ key/value này.

valueForKey

Hàm có tác dụng trả về value có dạng const __String* với key tương ứng. Nếu key không tồn tại sẽ trả về 1 chuỗi rỗng.

Các kiểu dữ liệu phức tạp cấp cao như array hay dict sẽ không được trình bày trong bài viết này. Dữ liệu ở dạng chuỗi sẽ hiệu quả nhất, có thể thao tác để chuyển từ chuỗi sang các kiểu dữ liệu mong muốn.

Hiện thực lớp PositionManager

Lớp PositionManager có các phương thức chính là loadObjectsPositiongetObjectPosition.

Hiện thực 2 phương thức này bên dưới. Khai báo lớp PositionManager như sau:

class PositionManager
{
private:
    static PositionManager* m_instance;

private:
    PositionManager();
    ~PositionManager();

public:
    static PositionManager* getInstance();

    void    loadObjectsPosition(const char* pListPath);
    Vec2    getObjectPosition(const String* objectPosition);
    
    // Your variable to store object position (Vec2)
    Vec2    m_title;
    Vec2    m_buttonPlay;
    Vec2    m_buttonSound;
}

Do chỉ có duy nhất 1 PositionManager tồn tại trong game nên áp dụng kỹ thuật Singleton để quản lý thuận tiện.

loadObjectsPosition

Hàm loadObjectsPosition có tác dụng lưu trữ vị trí của các đối tượng được load vào file plist.

void PositionManager::loadObjectsPosition(const char* pListPath)
{
    Dictionary* objectsListPosition = Dictionary::createWithContentsOfFile(pListPath);

    // get title position
    const __String* strTitlePosition = objectsListPosition->valueForKey("title");
    PositionManager::getInstance()->m_title = getObjectPosition(strTitlePosition);
    
    // get play button position
    const __String* strButtonPlayPosition = objectsListPosition->valueForKey("button_play");
    PositionManager::getInstance()->m_buttonPlay= getObjectPosition(strButtonPlayPosition);
    
    // get sound button position
    const __String* strButtonSoundPosition = objectsListPosition->valueForKey("button_sound");
    PositionManager::getInstance()->m_buttonSound= getObjectPosition(strButtonSoundPosition);
}

Value dạng chuỗi sẽ được lưu trữ lại trong các biến const __String* và được phân tích (parse) để lưu trữ lại vào PositionManager dưới dạng Vec2. Các kiểu dữ liệu int, float, bool, … được lưu trữ trực tiếp qua hàm valueForKey.

getObjectPosition

Hàm getObjectPosition hỗ trợ parse dữ liệu từ dạng const __String* sang Vec2.

Việc phân tích dữ liệu chuỗi sang các kiểu dữ liệu khác khá đơn giản và có nhiều cách hiện thực khác nhau. Dưới đây là cách sử dụng trong Project Zero:

Vec2 PositionManager::getObjectPosition(const __String* strObjectPosition)
{
    Vec2 objectPosition;

    int value = 0;
    for(size_t i = 0; i < strObjectPosition->_string.length(); i++)
    {
        if(strObjectPosition->_string[i] >= '0' && strObjectPosition->_string[i] <= '9')
        {
            value *= 10;
            value += (strObjectPosition->_string[i] - '0');
        }
        else
        {
            objectPosition.x = value;
            value = 0;
        }
    }

    objectPosition.y = value;
    return objectPosition;
}
IO Stream

IO Stream Co., Ltd

30 Trinh Dinh Thao, Hoa Thanh ward, Tan Phu district, Ho Chi Minh city, Vietnam
+84 28 22 00 11 12
developer@iostream.co

383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024