CocosCreator 逆向获取资源

CocosCreator 逆向获取资源

1.config.c4356.json 这个是资源合图的配置文件,类似这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"importBase": "import",
"nativeBase": "native",
"name": "game",
"deps": [
"internal",
"main"
],
"uuids": [
"00MU1uoNJOzZuYRoYQkUXe",
"00S5oIEDtCG60Kl7adj9xj",
"00U+S2NXpLg7BwH6bhC16k",
"00gzFYm71OU4+3YRuzhq0V",
"006NBLmEdFTpxa9XxNOCz7",

2. 0cbf09746.31828.json 这个是资源数据的文件,拆图要从这个配置文件里面读取数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

[1, [
"fdoJXLgx1GAa2UhGATlj3o",
"a0NtTOrBZL5aN9Nk+ssT9X",
"1c77f033a@6c48a",
"1efea47a9@6c48a",
"144d0b04a@6c48a",
"19af2a573@6c48a",
"14ef92480@6c48a",
"1100357f9@6c48a",
"1f6e96908@6c48a",
"c8UMGlaStAx6yBCY19cWuX@f9941",
"11trv1xBtGD4BfZPj1X45L@f9941",
"baIUdvKGZPgZxNbjWTFuRI",
"1csudwc5pMh7yyJgOKUNVS@f9941",
"1d11763eb@6c48a",
"c2oLIs8AdL2o7Eqe/KljSQ@f9941",

3. 拆plist合图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import json
# 读取原始JSON文件
with open('./config.8b7c8.json', 'r', encoding='utf-8') as f:
    data = json.load(f)
# 用于存储包含 /plist/ 的字符串
plist_entries = []
# 遍历数据以找到所有包含 /plist/ 的字符串
def find_plist_entries(value):
    if isinstance(value, list):
        for item in value:
            find_plist_entries(item)
    elif isinstance(value, dict):
        for item in value.values():
            find_plist_entries(item)
    elif isinstance(value, str) and "/plist/" in value:
        plist_entries.append(value)
# 开始查找
find_plist_entries(data)
# 将结果写入新的JSON文件
with open('new_json_file.json', 'w', encoding='utf-8') as f:
    json.dump(plist_entries, f, ensure_ascii=False, indent=4)
print("已成功将包含 /plist/ 的条目写入新的 JSON 文件。")

生成用到所有plist的json文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[
    "res/plist/marquee/33Phoenix_0001_s",
    "fishComm/plist/fish/NewYearPack/plist/Default",
    "fishComm/plist/fish/NewYearPack/plist/Img_Light_BlurPlate",
    "fishComm/plist/fish/NewYearPack/plist/BG_W_Light01_000_239",
    "fishComm/plist/freeBullet/3D/D_gun_fire_fire",
    "fishComm/plist/card/RewardCircleBonusIcon",
    "fishComm/plist/fish/DragonBoat/particle/DragonBoat/ef_coin0_only0000",
    "res/plist/originPlist/Fish_11",
    "fishComm/plist/fish/NewYearPack/plist/FrameFx",
    "fishComm/plist/fish/DragonBoat/particle/DragonBoat/a_ard4_tail_shinning",
    "fishComm/plist/card/bigwin/roll_light0005",
    "res/plist/feature/logo_1_ru",
    "fishComm/plist/fish/NewYearPack/plist/ef_image 8",
    "fishComm/plist/card/bigwin/EXP_IconSweep01_14",
    "fishComm/plist/card/auto-atlas",
    "fishComm/plist/fish/DragonBoat/plist/Img_LightDot_Blur"
]

排一下序把一样的文件名整合在一起

1
2
3
4
5
6
7
8
9
10
import json
# 读取包含 /plist/ 条目的JSON文件
with open('./new_json_file.json', 'r', encoding='utf-8') as f:
    plist_entries = json.load(f)
# 对条目进行排序
sorted_plist_entries = sorted(plist_entries)
# 将排序后的结果写入新的JSON文件
with open('sorted_json_file.json', 'w', encoding='utf-8') as f:
    json.dump(sorted_plist_entries, f, ensure_ascii=False, indent=4)
print("已成功将排序后的条目写入新的 JSON 文件。")

排序后的文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

[
    "fishComm/plist/CommRewardCircle/Dt_foot_fire",
    "fishComm/plist/CommRewardCircle/ForestDance_Ray_01/spriteFrame",
    "fishComm/plist/CommRewardCircle/LightReward2_01/spriteFrame",
    "fishComm/plist/CommRewardCircle/LightReward2_02/spriteFrame",
    "fishComm/plist/CommRewardCircle/LightReward2_03/spriteFrame",
    "fishComm/plist/CommRewardCircle/LightReward2_04/spriteFrame",
    "fishComm/plist/CommRewardCircle/LightReward2_05/spriteFrame",
    "fishComm/plist/CommRewardCircle/LightReward2_06/spriteFrame",
    "fishComm/plist/CommRewardCircle/LightReward2_07/spriteFrame",
    "fishComm/plist/CommRewardCircle/RewardCircleLight/spriteFrame",
    "fishComm/plist/CommRewardCircle/RewardColorBg/spriteFrame",
    "fishComm/plist/CommRewardCircle/RewardColorBg2_01/spriteFrame",
    "fishComm/plist/CommRewardCircle/RewardColorBg2_Out/spriteFrame",
    "fishComm/plist/CommRewardCircle/RewardNameBg/spriteFrame",
    "fishComm/plist/CommRewardCircle/a_ard4_tail_shinning",
    "fishComm/plist/CommRewardCircle/a_ard4_tail_shinning/spriteFrame",
    "fishComm/plist/CommRewardCircle/a_ard4_tail_shinning/texture",
    "fishComm/plist/CommRewardCircle/a_effect_01/spriteFrame",
    "fishComm/plist/CommRewardCircle/a_light_01/spriteFrame",
    "fishComm/plist/card/Backpack_Card_01",
    "fishComm/plist/card/Backpack_Card_01/spriteFrame",

整理一个Fish_4.json的文件去拆分小图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[
"c_g_0002",
    "mg_0001",
    "mg_0005",
    "mg_0006",
    "c_g_0004",
    "c_g_0001",
    "mg_0007",
    "c_g_0005",
    "mg_0003",
    "c_g_0006",
    "c_g_0007",
    "mg_0002",
    "c_g_0003",
    "mg_0004",
    "c_g_0008"]

再去0cbf09746.31828.json这个文件去里找出Fish_4.json里面key一样的图去拆分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import json
import os
from PIL import Image
def load_json(file_path):
    with open(file_path, 'r', encoding='utf-8') as f:
        return json.load(f)
def find_item_by_name(data, name):
    if isinstance(data, dict):
        if data.get("name") == name:
            return data
        for value in data.values():
            result = find_item_by_name(value, name)
            if result:
                return result
    elif isinstance(data, list):
        for item in data:
            result = find_item_by_name(item, name)
            if result:
                return result
    return None
def split_image(big_image_path, names, data, output_dir):
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    big_image = Image.open(big_image_path)
    for name in names:
        item = find_item_by_name(data, name)
        if not item:
            print(f"❌ 未找到:{name}")
            continue
        rect = item['rect']
        offset = item['offset']
        original_size = item['originalSize']
        rotated = item.get('rotated', False)
        x, y, w, h = rect['x'], rect['y'], rect['width'], rect['height']
        if rotated:
            # rotated:高宽交换
            box = (x, y, x + h, y + w)
        else:
            box = (x, y, x + w, y + h)
        sub_img = big_image.crop(box)
        if rotated:
            sub_img = sub_img.rotate(90, expand=True)
        # 创建空画布,原始尺寸
        canvas = Image.new('RGBA', (original_size['width'], original_size['height']), (0, 0, 0, 0))
        # 偏移位置(y 方向为负,因为是从中心计算)
        paste_x = int((original_size['width'] - sub_img.width) / 2 + offset['x'])
        paste_y = int((original_size['height'] - sub_img.height) / 2 - offset['y'])
        canvas.paste(sub_img, (paste_x, paste_y))
        output_path = os.path.join(output_dir, f"{name}.png")
        canvas.save(output_path)
        print(f"✅ 保存成功: {output_path}")
# === 文件路径 ===
names_file_path = "Fish_4.json"       # 包含名字列表的 JSON
data_file_path = "data.json"          # 包含大图 metadata 的 JSON
big_image_path = "Fish_4.png"         # 大图路径
output_dir = "Fish_4"                 # 输出目录
# === 执行 ===
names = load_json(names_file_path)
data = load_json(data_file_path)
split_image(big_image_path, names, data, output_dir)

4.spine动画资源提取

* 先要找出spIne的图片文件
* 根据图片的大小去0cbf09746.31828.json里面搜比如图片大小是820x820
* 这个就是spine的用到的atlas文件
* 把这个复制出来新建的个texture_atlas.txt
* 用代码生成atlas文件
1
2
3
4
5
  [231, "Dking",
          "\nDking.png\nsize: 820,820\nformat: RGBA8888\nfilter: Linear,Linear\nrepeat: none\nL_hand\n  rotate: false\n  xy: 560, 564\n  size: 51, 55\n  orig: 51, 55\n  offset: 0, 0\n  index: -1\nR_hand\n  rotate: true\n  xy: 468, 404\n  size: 67, 80\n  orig: 67, 81\n  offset: 0, 0\n  index: -1\nT_LBlag0126\n  rotate: false\n  xy: 550, 394\n  size: 64, 80\n  orig: 64, 81\n  offset: 0, 0\n  index: -1\nT_LBlag0128\n  rotate: false\n  xy: 681, 484\n  size: 70, 75\n  orig: 70, 77\n  offset: 0, 1\n  index: -1\nT_LBlag0130\n  rotate: false\n  xy: 455, 110\n  size: 73, 73\n  orig: 73, 74\n  offset: 0, 0\n  index: -1\nT_LBlag0132\n  rotate: false\n  xy: 383, 29\n  size: 74, 71\n  orig: 75, 72\n  offset: 0, 0\n  index: -1\nT_LBlag0134\n  rotate: true\n  xy: 383, 102\n  size: 75, 70\n  orig: 77, 70\n  offset: 1, 0\n  index: -1\nT_LBlag0136\n  rotate: true\n  xy: 682, 250\n  size: 77, 67\n  orig: 77, 68\n  offset: 0, 0\n  index: -1\nT_LBlag0138\n  rotate: true\n  xy: 614, 310\n  size: 78, 66\n  orig: 79, 67\n  offset: 0, 0\n  index: -1\nT_LBlag0140\n  rotate: true\n  xy: 538, 476\n  size: 86, 55\n  orig: 86, 55\n  offset: 0, 0\n  index: -1\nT_LBlag0142\n  rotate: false\n  xy: 617, 94\n  size: 77, 50\n  orig: 77, 50\n  offset: 0, 0\n  index: -1\nT_LBlag0144\n  rotate: true\n  xy: 753, 392\n  size: 75, 61\n  orig: 76, 61\n  offset: 0, 0\n  index: -1\nT_LBlag0146\n  rotate: true\n  xy: 682, 329\n  size: 71, 69\n  orig: 71, 69\n  offset: 0, 0\n  index: -1\nT_LBlag0148\n  rotate: false\n  xy: 751, 230\n  size: 66, 75\n  orig: 66, 77\n  offset: 0, 1\n  index: -1\nT_LBlag0150\n  rotate: false\n  xy: 459, 27\n  size: 59, 81\n  orig: 59, 81\n  offset: 0, 0\n  index: -1\nT_LBlag0152\n  rotate: false\n  xy: 397, 292\n  size: 45, 96\n  orig: 45, 97\n  offset: 0, 0\n  index: -1\nT_LBlag0154\n  rotate: false\n  xy: 503, 307\n  size: 45, 95\n  orig: 46, 95\n  offset: 0, 0\n  index: -1\nT_LBlag0156\n  rotate: true\n  xy: 444, 259\n  size: 46, 94\n  orig: 46, 95\n  offset: 0, 0\n  index: -1\nT_LBlag0158\n  rotate: true\n  xy: 550, 262\n  size: 46, 94\n  orig: 46, 95\n  offset: 0, 0\n  index: -1\nT_LBlag0160\n  rotate: true\n  xy: 540, 214\n  size: 46, 94\n  orig: 47, 95\n  offset: 0, 0\n  index: -1\nT_LBlag0162\n  rotate: true\n  xy: 728, 653\n  size: 49, 89\n  orig: 50, 91\n  offset: 0, 1\n  index: -1\nT_LBlag0164\n  rotate: true\n  xy: 532, 159\n  size: 53, 86\n  orig: 53, 86\n  offset: 0, 0\n  index: -1\nT_LBlag0166\n  rotate: true\n  xy: 530, 102\n  size: 55, 85\n  orig: 56, 85\n  offset: 1, 0\n  index: -1\nT_LBlag0168\n  rotate: true\n  xy: 520, 42\n  size: 58, 85\n  orig: 58, 85\n  offset: 0, 0\n  index: -1\nT_LBlag0170\n  rotate: false\n  xy: 753, 307\n  size: 60, 83\n  orig: 60, 84\n  offset: 0, 1\n  index: -1\nT_LBlag0172\n  rotate: false\n  xy: 550, 310\n  size: 62, 82\n  orig: 62, 82\n  offset: 0, 0\n  index: -1\nT_LFlag0148\n  rotate: false\n  xy: 636, 192\n  size: 80, 56\n  orig: 80, 56\n  offset: 0, 0\n  index: -1\nT_RFlag0126\n  rotate: false\n  xy: 2, 2\n  size: 77, 101\n  orig: 77, 101\n  offset: 0, 0\n  index: -1\nT_RFlag0128\n  rotate: true\n  xy: 380, 621\n  size: 55, 107\n  orig: 55, 107\n  offset: 0, 0\n  index: -1\nT_RFlag0130\n  rotate: false\n  xy: 144, 2\n  size: 55, 104\n  orig: 55, 105\n  offset: 0, 0\n  index: -1\nT_RFlag0132\n  rotate: false\n  xy: 201, 2\n  size: 55, 104\n  orig: 55, 104\n  offset: 0, 0\n  index: -1\nT_RFlag0134\n  rotate: false\n  xy: 258, 2\n  size: 55, 104\n  orig: 55, 104\n  offset: 0, 0\n  index: -1\nT_RFlag0136\n  rotate: true\n  xy: 454, 564\n  size: 55, 104\n  orig: 55, 104\n  offset: 0, 0\n  index: -1\nT_RFlag0138\n  rotate: true\n  xy: 489, 621\n  size: 55, 105\n  orig: 55, 106\n  offset: 0, 0\n  index: -1\nT_RFlag0140\n  rotate: true\n  xy: 596, 626\n  size: 50, 103\n  orig: 50, 104\n  offset: 0, 0\n  index: -1\nT_RFlag0142\n  rotate: false\n  xy: 81, 2\n  size: 47, 101\n  orig: 48, 101\n  offset: 1, 0\n  index: -1\nT_RFlag0144\n  rotate: false\n  xy: 753, 469\n  size: 52, 98\n  orig: 52, 99\n  offset: 0, 1\n  index: -1\nT_RFlag0146\n  rotate: false\n  xy: 444, 307\n  size: 57, 95\n  orig: 58, 96\n  offset: 0, 0\n  index: -1\nT_RFlag0148\n  rotate: true\n  xy: 613, 561\n  size: 63, 92\n  orig: 63, 93\n  offset: 0, 0\n  index: -1\nT_RFlag0150\n  rotate: false\n  xy: 468, 473\n  size: 68, 89\n  orig: 69, 89\n  offset: 1, 0\n  index: -1\nT_RFlag0152\n  rotate: false\n  xy: 378, 533\n  size: 74, 86\n  orig: 74, 86\n  offset: 0, 0\n  index: -1\nT_RFlag0154\n  rotate: true\n  xy: 595, 486\n  size: 73, 84\n  orig: 73, 84\n  offset: 0, 0\n  index: -1\nT_RFlag0156\n  rotate: false\n  xy: 707, 569\n  size: 72, 82\n  orig: 73, 82\n  offset: 0, 0\n  index: -1\nT_RFlag0158\n  rotate: false\n  xy: 678, 402\n  size: 73, 80\n  orig: 73, 80\n  offset: 0, 0\n  index: -1\nT_RFlag0160\n  rotate: false\n  xy: 380, 179\n  size: 73, 78\n  orig: 73, 79\n  offset: 0, 0\n  index: -1\nT_RFlag0162\n  rotate: false\n  xy: 616, 390\n  size: 60, 94\n  orig: 60, 95\n  offset: 0, 0\n  index: -1\nT_RFlag0164\n  rotate: false\n  xy: 418, 428\n  size: 48, 103\n  orig: 48, 104\n  offset: 0, 0\n  index: -1\nT_RFlag0166\n  rotate: false\n  xy: 315, 30\n  size: 66, 107\n  orig: 66, 108\n  offset: 0, 0\n  index: -1\nT_RFlag0168\n  rotate: false\n  xy: 318, 279\n  size: 77, 110\n  orig: 77, 111\n  offset: 0, 1\n  index: -1\nT_RFlag0170\n  rotate: false\n  xy: 338, 419\n  size: 78, 112\n  orig: 78, 112\n  offset: 0, 0\n  index: -1\nT_RFlag0172\n  rotate: false\n  xy: 301, 139\n  size: 77, 108\n  orig: 78, 108\n  offset: 0, 0\n  index: -1\nT_head\n  rotate: false\n  xy: 144, 108\n  size: 155, 139\n  orig: 155, 139\n  offset: 0, 0\n  index: -1\nT_shell\n  rotate: false\n  xy: 204, 675\n  size: 174, 143\n  orig: 174, 143\n  offset: 0, 0\n  index: -1\nT_tail\n  rotate: true\n  xy: 607, 37\n  size: 55, 77\n  orig: 55, 77\n  offset: 0, 0\n  index: -1\nbody\n  rotate: false\n  xy: 686, 34\n  size: 59, 58\n  orig: 59, 58\n  offset: 0, 0\n  index: -1\nbody02\n  rotate: false\n  xy: 2, 621\n  size: 200, 197\n  orig: 200, 198\n  offset: 0, 0\n  index: -1\nhair01\n  rotate: false\n  xy: 646, 267\n  size: 33, 41\n  orig: 33, 41\n  offset: 0, 0\n  index: -1\nhair02\n  rotate: false\n  xy: 164, 534\n  size: 25, 32\n  orig: 25, 33\n  offset: 0, 0\n  index: -1\nhair03\n  rotate: false\n  xy: 164, 568\n  size: 38, 51\n  orig: 38, 52\n  offset: 0, 1\n  index: -1\nhair04\n  rotate: false\n  xy: 781, 601\n  size: 33, 50\n  orig: 33, 50\n  offset: 0, 0\n  index: -1\nhair05\n  rotate: true\n  xy: 338, 391\n  size: 26, 47\n  orig: 26, 48\n  offset: 0, 1\n  index: -1\nhat\n  rotate: false\n  xy: 455, 185\n  size: 75, 72\n  orig: 76, 73\n  offset: 1, 0\n  index: -1\nhead\n  rotate: false\n  xy: 2, 453\n  size: 160, 166\n  orig: 161, 166\n  offset: 1, 0\n  index: -1\njaw\n  rotate: false\n  xy: 620, 146\n  size: 79, 44\n  orig: 79, 45\n  offset: 0, 1\n  index: -1\nlight01\n  rotate: true\n  xy: 2, 279\n  size: 172, 140\n  orig: 172, 141\n  offset: 0, 0\n  index: -1\nlight02\n  rotate: false\n  xy: 380, 678\n  size: 172, 140\n  orig: 172, 141\n  offset: 0, 0\n  index: -1\nlight03\n  rotate: true\n  xy: 2, 105\n  size: 172, 140\n  orig: 172, 141\n  offset: 0, 0\n  index: -1\nlight04\n  rotate: false\n  xy: 554, 678\n  size: 172, 140\n  orig: 172, 141\n  offset: 0, 0\n  index: -1\nlight05\n  rotate: false\n  xy: 204, 533\n  size: 172, 140\n  orig: 172, 141\n  offset: 0, 0\n  index: -1\nlight06\n  rotate: false\n  xy: 164, 391\n  size: 172, 140\n  orig: 172, 141\n  offset: 0, 0\n  index: -1\nneck\n  rotate: true\n  xy: 728, 704\n  size: 114, 89\n  orig: 114, 90\n  offset: 0, 1\n  index: -1\nshell_lighting\n  rotate: false\n  xy: 144, 249\n  size: 172, 140\n  orig: 172, 141\n  offset: 0, 0\n  index: -1\n",
          [
            "Dking.png"
          ],

* 生成atlas文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import re
import os
def parse_texture_atlas(file_path):
    with open(file_path, 'r', encoding='utf-8') as file:
        data = file.read()
   
    # 将\n替换为换行符
    data = data.replace('\\n', '\n')
   
    # 使用正则表达式匹配整体信息
    overall_pattern = re.compile(
        r'(?P<image_name>[^\s]+)\n'
        r'size:\s*(?P<size>\d+,\d+)\n'
        r'format:\s*(?P<format>[^\s]+)\n'
        r'filter:\s*(?P<filter>[^\s]+,[^\s]+)\n'
        r'repeat:\s*(?P<repeat>[^\s]+)\n'
    )
   
    overall_match = overall_pattern.search(data)
    if not overall_match:
        raise ValueError("整体信息匹配失败")
   
    overall_info = {
        'image_name': overall_match.group('image_name'),
        'size': list(map(int, overall_match.group('size').split(','))),
        'format': overall_match.group('format'),
        'filter': overall_match.group('filter').split(','),
        'repeat': overall_match.group('repeat')
    }
   
    # 使用正则表达式匹配条目
    entry_pattern = re.compile(
        r'(?P<name>.+?)\n\s*'
        r'rotate:\s*(?P<rotate>\w+)\n\s*'
        r'xy:\s*(?P<xy>\d+,\s*\d+)\n\s*'
        r'size:\s*(?P<size>\d+,\s*\d+)\n\s*'
        r'orig:\s*(?P<orig>\d+,\s*\d+)\n\s*'
        r'offset:\s*(?P<offset>\d+,\s*\d+)\n\s*'
        r'index:\s*(?P<index>-?\d+)\n'
    )
   
    matches = entry_pattern.findall(data)
   
    texture_data = []
    for match in matches:
        name, rotate, xy, size, orig, offset, index = match
        texture_data.append({
            'name': name,
            'rotate': rotate,  # 将 'false' 转换为布尔值 False
            'xy': list(map(int, xy.split(','))),
            'size': list(map(int, size.split(','))),
            'orig': list(map(int, orig.split(','))),
            'offset': list(map(int, offset.split(','))),
            'index': int(index)
        })
   
    return overall_info, texture_data
def save_parsed_data(file_path, overall_info, data):
    with open(file_path, 'w', encoding='utf-8') as file:
        # 写入整体信息
        file.write(f"{overall_info['image_name']}\n")
        file.write(f"size: {overall_info['size'][0]},{overall_info['size'][1]}\n")
        file.write(f"format: {overall_info['format']}\n")
        file.write(f"filter: {overall_info['filter'][0]},{overall_info['filter'][1]}\n")
        file.write(f"repeat: {overall_info['repeat']}\n")
       
        # 写入条目信息
        for item in data:
            file.write(f"{item['name']}\n")
            file.write(f"  rotate: {item['rotate']}\n")
            file.write(f"  xy: {item['xy'][0]},{item['xy'][1]}\n")
            file.write(f"  size: {item['size'][0]},{item['size'][1]}\n")
            file.write(f"  orig: {item['orig'][0]},{item['orig'][1]}\n")
            file.write(f"  offset: {item['offset'][0]},{item['offset'][1]}\n")
            file.write(f"  index: {item['index']}\n")
# 主函数
def main():
    input_file = 'texture_atlas.txt'
    overall_info, parsed_data = parse_texture_atlas(input_file)
   
    # 去掉 image_name 中的 .png 扩展名
    base_name = overall_info['image_name'].rsplit('.', 1)[0]
    output_file = f"{base_name}.atlas"
   
    save_parsed_data(output_file, overall_info, parsed_data)
if __name__ == "__main__":
    main()

最后就再找到spine的json文件就大功告成了 只要把skeleton后面的复制出来就行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

 [231, "Dking",
          "\nDking.png\nsize: 820,820\nformat: RGBA8888\nfilter: Linear,Linear\nrepeat: none\nL_hand\n  rotate: false\n  xy: 560, 564\n  size: 51, 55\n  orig: 51, 55\n  offset: 0, 0\n  index: -1\nR_hand\n  rotate: true\n  xy: 468, 404\n  size: 67, 80\n  orig: 67, 81\n  offset: 0, 0\n  index: -1\nT_LBlag0126\n  rotate: false\n  xy: 550, 394\n  size: 64, 80\n  orig: 64, 81\n  offset: 0, 0\n  index: -1\nT_LBlag0128\n  rotate: false\n  xy: 681, 484\n  size: 70, 75\n  orig: 70, 77\n  offset: 0, 1\n  index: -1\nT_LBlag0130\n  rotate: false\n  xy: 455, 110\n  size: 73, 73\n  orig: 73, 74\n  offset: 0, 0\n  index: -1\nT_LBlag0132\n  rotate: false\n  xy: 383, 29\n  size: 74, 71\n  orig: 75, 72\n  offset: 0, 0\n  index: -1\nT_LBlag0134\n  rotate: true\n  xy: 383, 102\n  size: 75, 70\n  orig: 77, 70\n  offset: 1, 0\n  index: -1\nT_LBlag0136\n  rotate: true\n  xy: 682, 250\n  size: 77, 67\n  orig: 77, 68\n  offset: 0, 0\n  index: -1\nT_LBlag0138\n  rotate: true\n  xy: 614, 310\n  size: 78, 66\n  orig: 79, 67\n  offset: 0, 0\n  index: -1\nT_LBlag0140\n  rotate: true\n  xy: 538, 476\n  size: 86, 55\n  orig: 86, 55\n  offset: 0, 0\n  index: -1\nT_LBlag0142\n  rotate: false\n  xy: 617, 94\n  size: 77, 50\n  orig: 77, 50\n  offset: 0, 0\n  index: -1\nT_LBlag0144\n  rotate: true\n  xy: 753, 392\n  size: 75, 61\n  orig: 76, 61\n  offset: 0, 0\n  index: -1\nT_LBlag0146\n  rotate: true\n  xy: 682, 329\n  size: 71, 69\n  orig: 71, 69\n  offset: 0, 0\n  index: -1\nT_LBlag0148\n  rotate: false\n  xy: 751, 230\n  size: 66, 75\n  orig: 66, 77\n  offset: 0, 1\n  index: -1\nT_LBlag0150\n  rotate: false\n  xy: 459, 27\n  size: 59, 81\n  orig: 59, 81\n  offset: 0, 0\n  index: -1\nT_LBlag0152\n  rotate: false\n  xy: 397, 292\n  size: 45, 96\n  orig: 45, 97\n  offset: 0, 0\n  index: -1\nT_LBlag0154\n  rotate: false\n  xy: 503, 307\n  size: 45, 95\n  orig: 46, 95\n  offset: 0, 0\n  index: -1\nT_LBlag0156\n  rotate: true\n  xy: 444, 259\n  size: 46, 94\n  orig: 46, 95\n  offset: 0, 0\n  index: -1\nT_LBlag0158\n  rotate: true\n  xy: 550, 262\n  size: 46, 94\n  orig: 46, 95\n  offset: 0, 0\n  index: -1\nT_LBlag0160\n  rotate: true\n  xy: 540, 214\n  size: 46, 94\n  orig: 47, 95\n  offset: 0, 0\n  index: -1\nT_LBlag0162\n  rotate: true\n  xy: 728, 653\n  size: 49, 89\n  orig: 50, 91\n  offset: 0, 1\n  index: -1\nT_LBlag0164\n  rotate: true\n  xy: 532, 159\n  size: 53, 86\n  orig: 53, 86\n  offset: 0, 0\n  index: -1\nT_LBlag0166\n  rotate: true\n  xy: 530, 102\n  size: 55, 85\n  orig: 56, 85\n  offset: 1, 0\n  index: -1\nT_LBlag0168\n  rotate: true\n  xy: 520, 42\n  size: 58, 85\n  orig: 58, 85\n  offset: 0, 0\n  index: -1\nT_LBlag0170\n  rotate: false\n  xy: 753, 307\n  size: 60, 83\n  orig: 60, 84\n  offset: 0, 1\n  index: -1\nT_LBlag0172\n  rotate: false\n  xy: 550, 310\n  size: 62, 82\n  orig: 62, 82\n  offset: 0, 0\n  index: -1\nT_LFlag0148\n  rotate: false\n  xy: 636, 192\n  size: 80, 56\n  orig: 80, 56\n  offset: 0, 0\n  index: -1\nT_RFlag0126\n  rotate: false\n  xy: 2, 2\n  size: 77, 101\n  orig: 77, 101\n  offset: 0, 0\n  index: -1\nT_RFlag0128\n  rotate: true\n  xy: 380, 621\n  size: 55, 107\n  orig: 55, 107\n  offset: 0, 0\n  index: -1\nT_RFlag0130\n  rotate: false\n  xy: 144, 2\n  size: 55, 104\n  orig: 55, 105\n  offset: 0, 0\n  index: -1\nT_RFlag0132\n  rotate: false\n  xy: 201, 2\n  size: 55, 104\n  orig: 55, 104\n  offset: 0, 0\n  index: -1\nT_RFlag0134\n  rotate: false\n  xy: 258, 2\n  size: 55, 104\n  orig: 55, 104\n  offset: 0, 0\n  index: -1\nT_RFlag0136\n  rotate: true\n  xy: 454, 564\n  size: 55, 104\n  orig: 55, 104\n  offset: 0, 0\n  index: -1\nT_RFlag0138\n  rotate: true\n  xy: 489, 621\n  size: 55, 105\n  orig: 55, 106\n  offset: 0, 0\n  index: -1\nT_RFlag0140\n  rotate: true\n  xy: 596, 626\n  size: 50, 103\n  orig: 50, 104\n  offset: 0, 0\n  index: -1\nT_RFlag0142\n  rotate: false\n  xy: 81, 2\n  size: 47, 101\n  orig: 48, 101\n  offset: 1, 0\n  index: -1\nT_RFlag0144\n  rotate: false\n  xy: 753, 469\n  size: 52, 98\n  orig: 52, 99\n  offset: 0, 1\n  index: -1\nT_RFlag0146\n  rotate: false\n  xy: 444, 307\n  size: 57, 95\n  orig: 58, 96\n  offset: 0, 0\n  index: -1\nT_RFlag0148\n  rotate: true\n  xy: 613, 561\n  size: 63, 92\n  orig: 63, 93\n  offset: 0, 0\n  index: -1\nT_RFlag0150\n  rotate: false\n  xy: 468, 473\n  size: 68, 89\n  orig: 69, 89\n  offset: 1, 0\n  index: -1\nT_RFlag0152\n  rotate: false\n  xy: 378, 533\n  size: 74, 86\n  orig: 74, 86\n  offset: 0, 0\n  index: -1\nT_RFlag0154\n  rotate: true\n  xy: 595, 486\n  size: 73, 84\n  orig: 73, 84\n  offset: 0, 0\n  index: -1\nT_RFlag0156\n  rotate: false\n  xy: 707, 569\n  size: 72, 82\n  orig: 73, 82\n  offset: 0, 0\n  index: -1\nT_RFlag0158\n  rotate: false\n  xy: 678, 402\n  size: 73, 80\n  orig: 73, 80\n  offset: 0, 0\n  index: -1\nT_RFlag0160\n  rotate: false\n  xy: 380, 179\n  size: 73, 78\n  orig: 73, 79\n  offset: 0, 0\n  index: -1\nT_RFlag0162\n  rotate: false\n  xy: 616, 390\n  size: 60, 94\n  orig: 60, 95\n  offset: 0, 0\n  index: -1\nT_RFlag0164\n  rotate: false\n  xy: 418, 428\n  size: 48, 103\n  orig: 48, 104\n  offset: 0, 0\n  index: -1\nT_RFlag0166\n  rotate: false\n  xy: 315, 30\n  size: 66, 107\n  orig: 66, 108\n  offset: 0, 0\n  index: -1\nT_RFlag0168\n  rotate: false\n  xy: 318, 279\n  size: 77, 110\n  orig: 77, 111\n  offset: 0, 1\n  index: -1\nT_RFlag0170\n  rotate: false\n  xy: 338, 419\n  size: 78, 112\n  orig: 78, 112\n  offset: 0, 0\n  index: -1\nT_RFlag0172\n  rotate: false\n  xy: 301, 139\n  size: 77, 108\n  orig: 78, 108\n  offset: 0, 0\n  index: -1\nT_head\n  rotate: false\n  xy: 144, 108\n  size: 155, 139\n  orig: 155, 139\n  offset: 0, 0\n  index: -1\nT_shell\n  rotate: false\n  xy: 204, 675\n  size: 174, 143\n  orig: 174, 143\n  offset: 0, 0\n  index: -1\nT_tail\n  rotate: true\n  xy: 607, 37\n  size: 55, 77\n  orig: 55, 77\n  offset: 0, 0\n  index: -1\nbody\n  rotate: false\n  xy: 686, 34\n  size: 59, 58\n  orig: 59, 58\n  offset: 0, 0\n  index: -1\nbody02\n  rotate: false\n  xy: 2, 621\n  size: 200, 197\n  orig: 200, 198\n  offset: 0, 0\n  index: -1\nhair01\n  rotate: false\n  xy: 646, 267\n  size: 33, 41\n  orig: 33, 41\n  offset: 0, 0\n  index: -1\nhair02\n  rotate: false\n  xy: 164, 534\n  size: 25, 32\n  orig: 25, 33\n  offset: 0, 0\n  index: -1\nhair03\n  rotate: false\n  xy: 164, 568\n  size: 38, 51\n  orig: 38, 52\n  offset: 0, 1\n  index: -1\nhair04\n  rotate: false\n  xy: 781, 601\n  size: 33, 50\n  orig: 33, 50\n  offset: 0, 0\n  index: -1\nhair05\n  rotate: true\n  xy: 338, 391\n  size: 26, 47\n  orig: 26, 48\n  offset: 0, 1\n  index: -1\nhat\n  rotate: false\n  xy: 455, 185\n  size: 75, 72\n  orig: 76, 73\n  offset: 1, 0\n  index: -1\nhead\n  rotate: false\n  xy: 2, 453\n  size: 160, 166\n  orig: 161, 166\n  offset: 1, 0\n  index: -1\njaw\n  rotate: false\n  xy: 620, 146\n  size: 79, 44\n  orig: 79, 45\n  offset: 0, 1\n  index: -1\nlight01\n  rotate: true\n  xy: 2, 279\n  size: 172, 140\n  orig: 172, 141\n  offset: 0, 0\n  index: -1\nlight02\n  rotate: false\n  xy: 380, 678\n  size: 172, 140\n  orig: 172, 141\n  offset: 0, 0\n  index: -1\nlight03\n  rotate: true\n  xy: 2, 105\n  size: 172, 140\n  orig: 172, 141\n  offset: 0, 0\n  index: -1\nlight04\n  rotate: false\n  xy: 554, 678\n  size: 172, 140\n  orig: 172, 141\n  offset: 0, 0\n  index: -1\nlight05\n  rotate: false\n  xy: 204, 533\n  size: 172, 140\n  orig: 172, 141\n  offset: 0, 0\n  index: -1\nlight06\n  rotate: false\n  xy: 164, 391\n  size: 172, 140\n  orig: 172, 141\n  offset: 0, 0\n  index: -1\nneck\n  rotate: true\n  xy: 728, 704\n  size: 114, 89\n  orig: 114, 90\n  offset: 0, 1\n  index: -1\nshell_lighting\n  rotate: false\n  xy: 144, 249\n  size: 172, 140\n  orig: 172, 141\n  offset: 0, 0\n  index: -1\n",
          [
            "Dking.png"
          ],
          {
            "skeleton": {
              "hash": "PhLNTXfihU8MU1GCGz7yxI+xXZM",
              "spine": "3.5.51",
              "width": 349,
              "height": 445,
              "images": "./images1.5改亮/"
            },
            "bones": [
              {
                "name": "root",
                "color": "00ffd3ff"
              },
              {