LoginSignup
1
0

More than 3 years have passed since last update.

【CocosCreator】MapChipからAtlasを生成するツールを自作してみた。

Posted at

概要

CocosCreatorで使用する素材を探しているとツクールやウディタ用のキャラチップやマップチップばかり見つけるので、Atlas化して使えるようにしたかった。
CocosCreatorではPlistファイルがAtlasの役割のようで、バラバラなPngからPlistを作るツールはあるようだったが、マップチップのPngからPlistを生成するツールはなさそうだったので、自作した。
Plistの例を見て、それと同じようなものを作るというかなり大雑把な設計なので注意。

あと個人でいろいろ試す用に作ったけど、ツクール用の素材をCocosで使うのはライセンス的に微妙なことがあるかも知れないので、公開する場合は注意が必要かも。

参考サイト

cocos2d-x Atlas化した画像の扱い
https://qiita.com/sawasaka/items/943c238d7491146104fb
PListのファイルフォーマットについて:
https://www.codeandweb.com/blog/2016/01/29/cocos2d-plist-format-explained
CocosCreatorでマップにオブジェクトを配置する
https://qiita.com/raichi/items/5955f3e98f5ae995e57f

方針とコード

C#でPNGを読み込んでPlistを生成する。
チップのサイズは判定し難かったので、後から入力する形式にした。
C#を使ってるのは完全な趣味。

using System;
using System.Drawing;
using System.IO;

namespace PlistMakerByChip
{
    struct Vector2
    {
        public int x;
        public int y;
    }

    class Program
    {
        private static int xSize;
        private static int ySize;

        static void Main(string[] args)
        {
            foreach (var pngPath in args)
            {
                Console.WriteLine($"input :{pngPath}");
                try
                {
                    MakePlist(pngPath);
                }
                catch (Exception e)
                {
                    Console.WriteLine($"error : {e.Message}");
                }
            }
            Console.WriteLine("Finish");
            Console.ReadKey();
        }

        private static void MakePlist(string pngPath)
        {
            // チップサイズの入力受付。失敗したら返す。
            if (InputChipSize() == false) { return; }

            string plist = "";
            plist += GetBaseFirst();

            var pngSize = GetPngSize(pngPath);
            plist += GetBaseMeta(pngPath, pngSize);

            plist += GetFrameFirst();
            var chipXCount = pngSize.x / xSize;
            var chipYCount = pngSize.y / ySize;
            for (int y = 0; y < chipYCount; y++)
            {
                for (int x = 0; x < chipXCount; x++)
                {
                    plist += GetFrameMeta(pngPath, x, y, xSize, ySize);
                }
            }

            plist += GetBaseEnd();

            OutputPlist(pngPath, plist);
        }

        private static bool InputChipSize()
        {
            Console.WriteLine("1チップのXサイズを入力してください。");
            if (int.TryParse(Console.ReadLine(), out xSize) == false)
            {
                Console.WriteLine("有効な数字を入力してください。");
                return false;
            }

            Console.WriteLine("1チップのYサイズを入力してください。");
            if (int.TryParse(Console.ReadLine(), out ySize) == false)
            {
                Console.WriteLine("有効な数字を入力してください。");
                return false;
            }

            return true;
        }

        private static void OutputPlist(string pngPath, string data)
        {
            var dir = Path.GetDirectoryName(pngPath);
            var fileName = Path.GetFileNameWithoutExtension(pngPath);
            var outputPath = Path.Combine(dir, fileName + ".plist");

            File.WriteAllText(outputPath, data);
        }

        private static string GetBaseFirst()
        {
            return
                $"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                $"<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" +
                $"<plist version = \"1.0\">\n" +
                $"    <dict>\n";
        }

        private static Vector2 GetPngSize(string pngPath)
        {
            var img = Image.FromFile(pngPath);
            return new Vector2() { x = img.Width, y = img.Height };
        }

        private static string GetBaseMeta(string pngPath, Vector2 pngSize)
        {
            var fileName = Path.GetFileName(pngPath);
            return
                $"        <key>metadata</key>\n"+
                $"        <dict>\n" +
                $"            <key>format</key>\n" +
                $"            <integer>2</integer>\n" +
                $"            <key>realTextureFileName</key>\n" +
                $"            <string>{fileName}</string>\n" +
                $"            <key>size</key>\n" +
                $"            <string>{{{pngSize.x},{pngSize.y}}}</string>\n" +
                $"            <key>smartupdate</key>\n" +
                $"            <string>$TexturePacker:SmartUpdate:.....$</string>\n" +
                $"            <key>textureFileName</key>\n" +
                $"            <string>{fileName}</string>\n" +
                $"        </dict>\n";
        }

        private static string GetFrameFirst()
        {
            return
                $"        <key>frames</key>\n" +
                $"        <dict>\n";
        }

        private static string GetFrameMeta(string pngPath, int xPos, int yPos, int xSize, int ySize)
        {
            var fileName = Path.GetFileNameWithoutExtension(pngPath);
            return
                $"            <key>{fileName}_{xPos}_{yPos}</key>\n" +
                $"            <dict>\n" +
                $"                <key>frame</key>\n" +
                $"                <string>{{{{{xPos * xSize},{yPos * ySize}}},{{{xSize},{ySize}}}}}</string>\n" +
                $"                <key>offset</key>\n" +
                $"                <string>{{0,0}}</string>\n" +
                $"                <key>rotated</key>\n" +
                $"                <false/>\n" +
                $"                <key>sourceSize</key>\n" +
                $"                <string>{{{xSize},{ySize}}}</string>\n" +
                $"            </dict>\n";
        }

        private static string GetBaseEnd()
        {
            return
                $"        </dict>\n" +
                $"    </dict>\n" +
                $"</plist>";
        }
    }
}

まとめ

一応、これで作成したPlistと元PngをCocosCreatorに突っ込んだらAtlasみたいに使うことができた。
CocosCreatorを拡張して作れるようにした方が使い勝手が良かったかもと後から思った。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0