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
Lê Viết Duy Trong việc xây dựng, thiết kế project games của bạn, có nhiều tính toán, kỹ thuật, tính năng bạn phải sử dụng file để thao tác nhằm tăng hiệu suất của chương trình, giúp lập trình viên dễ dàng đọc và viết, dễ phân tích và phát sinh. Trong bài viết này tôi và các bạn sẽ cùng tìm hiểu những đặc điểm, cách xử lý và ứng dụng của file PLIST trong Cocos2d-x 3.11.

Giới thiệu

Trong việc xây dựng, thiết kế project games của bạn, có nhiều tính toán, kỹ thuật, tính năng bạn phải sử dụng file để thao tác nhằm tăng hiệu suất của chương trình, giúp lập trình viên dễ dàng đọc và viết, dễ phân tích và phát sinh. Trong bài viết này tôi và các bạn sẽ cùng tìm hiểu những đặc điểm, cách xử lý và ứng dụng của file PLIST trong Cocos2d-x 3.11.

Tiền đề bài viết

Trong thời gian học tập Phát Triển Game Engine Với C++, tôi được tham gia vào một Project thực thế do STDIO phát triển và làm việc với Cocos2d-x, Với sự giúp đỡ của anh La Kiến Vinh và anh Đạt Trương, tôi học được nhiều điều không chỉ là kiến thức mà còn kinh nghiệm, đặc biệt trong lập trình games nói riêng và kiến thức phần mềm nói chung. Tôi luôn được khuyến khích chia sẻ các kiến thức mà mình học được, những kiến thức nhỏ nhặt nhất. 

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

Đây là bài viết trong phần Thao Tác File Với Cocos2d-x 3.x.x. Bài viết này tôi hướng đến những người mới mới bắt đầu lập trình games 2D với Cocos2d-x 3.11 và chưa có những kiến thức liên quan.

PLIST là gì?

PLIST (viết tắt của Property list) là 1 định dạng được dùng để lưu trữ các thuộc tính và giá trị có cấu trúc chặt chẽ, dễ đọc hiểu và sử dụng linh hoạt. Trong bài viết này tôi hướng dẫn sử dụng plist trên Sprite Sheet.

Cách thể hiện trong file PLIST

Các file PLIST có định dạng mở rộng là .plist.

Dưới đây là một Sprite Sheet và cách nó được thể hiện trong plist.

Trong Sprite Sheet

Ss

Trong File PLIST

<plist version="1.0">
    <dict>
        <key>frames</key>
        <dict>
            <key>Cocos2dx.png</key>
            <dict>
                <key>aliases</key>
                <array/>
                <key>spriteOffset</key>
                <string>{0,0}</string>
                <key>spriteSize</key>
                <string>{195,270}</string>
                <key>spriteSourceSize</key>
                <string>{195,270}</string>
                <key>textureRect</key>
                <string>{{0,0},{195,270}}</string>
                <key>textureRotated</key>
                <false/>
            </dict>
            <key>STDIO.png</key>
            <dict>
                <key>aliases</key>
                <array/>
                <key>spriteOffset</key>
                <string>{0,0}</string>
                <key>spriteSize</key>
                <string>{256,256}</string>
                <key>spriteSourceSize</key>
                <string>{256,256}</string>
                <key>textureRect</key>
                <string>{{195,0},{256,256}}</string>
                <key>textureRotated</key>
                <false/>
            </dict>
        </dict>
        <key>metadata</key>
        <dict>
            <key>format</key>
            <integer>3</integer>
            <key>pixelFormat</key>
            <string>RGBA8888</string>
            <key>premultiplyAlpha</key>
            <false/>
            <key>realTextureFileName</key>
            <string>SpriteSheet.png</string>
            <key>size</key>
            <string>{451,270}</string>
            <key>textureFileName</key>
            <string>SpriteSheet.png</string>
        </dict>
    </dict>
</plist>

Phân tích:

PLIST được cấu trúc bởi các tab có liên hệ chặt chẽ với nhau:

  • Mỗi một <key> <key/> thể hiện cho một phần tử  riêng biệt và luôn có một giá trị ở dưới nó
  • <dict> </dict> là một danh mục chứa nhiều các phần tử 
  • <integer> </integer> thể hiện giá trị kiểu số nguyên, <float> </float> thể hiện giá trị kiểu số thực
  • <string> </string> thể hiện giá trị là một chuỗi ký tự
  • <true/> và  <false/> thể hiện giá trị đúng sai cho phép luận lý

Ở tập tin trên thì chúng ta có:

  • Dòng 3, 36: ở đây plist chia ra 2 phần tử chính là framesmetadata, trong đó metadata chứa các dữ liệu về các định dạng và đặc tính chung của hình ảnh cũng như cách thức xử lý mà Cocos2dx sẽ ứng dụng với từng loại file plist khác nhau, còn frames chứa các đặc tính, kích thước riêng biệt của từng Sprites trong Sprite Sheet
  • Dòng 38, 39: đây là định dạng để Cocos2dx xác định cách xử lý file plist với các giá trị khác nhau từ 0 đến 3, với mỗi giá trị thì sẽ có một cách trình bày trong plist khác nhau, ở đây giá trị của tôi là 3 với cấu trúc như trên
  • Dòng 5, 20: đây là tên của 2 Sprite trên và ở dưới là các thuộc tính của nó

Cách sử dụng plist trong Cocos2d-x

Để sử dụng plist trên cho Sprite Sheet trong Cocos2d-x , ta khởi tạo các dữ liệu của plist cho Sprite Sheet trước:

SpriteFrameCache::getInstance()->addSpriteFramesWithFile("sprite_sheet.plist", "sprite_sheet.png");

Sau khi khởi tạo thì ta lấy Sprite ra sử dụng rất đơn giản:

auto m_Sprite = Sprite::createWithSpriteFrameName("STDIO.png");

Cocos2d-x đã làm hầu hết các công việc nặng nhọc cho chúng ta.

Chuyên sâu về cách xử lý plist với Cocos2d-x

Tôi sẽ giải thích chi tiết hơn về cách hoạt động của hàm addSpriteFramesWithFile để có thể ứng dụng linh hoạt hơn trong nhiều vấn đề.

Hàm này có cấu trúc như sau:

void SpriteFrameCache::addSpriteFramesWithFile(const std::string& plist, const std::string& textureFileName)
{  
    const std::string fullPath = FileUtils::getInstance()->fullPathForFilename(plist);
    ValueMap dictionary = FileUtils::getInstance()->getValueMapFromFile(fullPath);
    addSpriteFramesWithDictionary(dictionary, textureFileName);
}
  • Dòng 3: lấy đường dẫn chi tiết đến file plist thực thi
  • Dòng 4: lấy các dữ liệu trong plist ra và lưu vào ValueMap
  • Dòng 5: lấy các dữ liệu có được trong ValueMap để trích các Sprite riêng biệt ra, bắt đầu từ việc đọc metadata trước để lấy cách thức xử lý dữ liệu rồi đến đọc frames sau, cuối cùng lưu nó vào SpriteFrameCache để người dùng lấy ra sử dụng

Vậy để lấy dữ liệu trong plist ra thì ta cần xử lý với kiểu dữ liệu ValueMap:

Đây là đoạn chương trình mà tôi sẽ lấy giá trị của format trong metadata ra

 if (dictionary.find("metadata") != dictionary.end())
    {
        ValueMap& metadataDict = dictionary["metadata"].asValueMap();
        integer format = metadataDict["format"].asInt();
    }
  • Dòng 1: tìm phần tử metadata bằng hàm find(string), nếu có sẽ chạy chương trình
  • Dòng 3: dictionary["metadata"] sẽ truy cập vào phần tử metadata, sau đó lấy dữ liệu các phần tử con thuộc trong nó và lưu nó dưới dạng ValueMap
  • Dòng 4: truy cập vào phần tử format và sử dụng hàm asInt() để lấy kiểu dữ liệu số nguyên trả về, đây là giá trị cần tìm của ta

Ngoài ra, không chỉ có asInt() mà còn có các hàm dành cho các kiểu dữ liệu khác nhau như là asFloat(), asString(), asBool(),....

Từ đó, để lấy giá trị của các phần tử khác cũng tương tự như trên.

Tham khảo

http://cocos2d-x.org/

THẢO LUẬN
ĐÓNG