2

我在从 .tmx(平铺)文件中提取图层内容时遇到问题。我想在 PHP 中获得完整的未压缩数据并制作一个小图像。获取宽度、高度等标题信息是没有问题的——SimpleXML 在那里完成了它的工作。但不知何故,瓦片层的解压缩不起作用。

数据本身存储为base64和gzip编码的字符串(类似H4sIAAAAAAAAC+3bORKAIBQEUVzuf2YTTSwEA/gL00EnJvJQsAjcSyk7EU3v+Jn3OI),但我什至在获取base64解码代码时遇到问题(它只是给了我奇怪的字符,当我重新打开平铺地图并将其保存为“base64 uncompressed”结果只是一个空字符串 -当然使用 gzip 解压缩)。

我已经通过网络搜索并查看了数据是如何精确压缩的(Github 文章)。似乎我必须使用该gzinflate()命令而不是所有其他命令(例如 gzuncompress),但这对我也不起作用。

我现在拥有的代码如下:

<?php
  // Get the raw xml data
  $map_xml = new SimpleXML(file_get_contents("map.tmx"));
  $data = $map_xml["layer"][0]["data"]["@content"]; // I would make a loop here
  $content =gzinflate(base64_decode($map_content)); // gives me and error

  var_dump($data); // results in nothing
?>

经过更多研究后,我发现我应该使用 zlib 过滤器(php.net 文章)。现在我真的很困惑,我不知道我应该选择什么 - 我再次询问谷歌并得到以下信息:Compressing with Java Decompressing with PHP。根据答案,我必须在使用 base64 和 gzip 方法之前裁剪我们的标题。

现在我的问题是:我必须先剪掉标题吗?如果是,我该怎么做?如果没有,那我怎样才能得到未压缩的数据呢?

我真的希望有人可以在这里帮助我!

4

3 回答 3

4

如前所述,Php 的 gzinflate 和 gzuncompress 名称不正确。但是,我们可以利用接受原始压缩数据的 gzinflate。gzip 标头长 10 个字节,可以使用 substr 剥离。使用上面的示例,我尝试了以下操作:

$base64content = "H4sIAAAAAAAAC+3bORKAIBQEUVzuf2YTTSwEA/gL00EnJvJQsAjcSyk7EU3v+Jn3OI";
$compressed = substr( base64_decode($base64content), 10);
$content = gzinflate($compressed);

这为您提供了一个表示原始数据的字符串。您的 TMX 层主要由 gid 0、2 和 3 组成,因此如果您将其打印出来,您只会看到空白。要获得有用的数据,您需要对字符调用 ord:

$chars = str_split($content);
$values = array();
foreach($chars as $char) {
    $values[] = ord($char);
}
var_dump( implode(',', $values) );  // This gives you the equivalent of saving your TMX file with tile data stored as csv

希望有帮助。

于 2012-10-29T22:29:47.160 回答
2

哇,这些 PHP 函数的名字太可怕了。先来点背景。

您可能会遇到或能够制作三种格式。他们是:

  • 原始 deflate,这是压缩为没有标题或尾部的 deflate 格式的数据,在RFC 1951中定义。
  • zlib,它是包装在紧凑的 zlib 标头和预告片中的原始 deflate 数据,其中包含一个两字节的标头和一个四字节的 Adler-32 校验值作为预告片,在RFC 1950中定义。
  • gzip,它是包装在 gzip 标头和预告片中的原始 deflate 数据,其中标头至少为 10 个字节,并且可以更长地包含文件名、注释和/或额外字段,以及带有 4 个字节的 8 字节预告片-byte CRC-32 和一个未压缩的长度模块 2^32。此包装器在RFC 1952中定义。这是您将在后缀为 的文件中找到的数据.gz

PHP 函数gzdeflate()gzinflate()创建和解码原始 deflate 格式。PHP 函数gzcompress()gzuncompress()创建和解码 zlib 格式。 这些函数都不应该在名称中包含“gz”,因为它们不能处理 gzip 格式!对于试图创建或解码 gzip 格式数据的 PHP 编码人员来说,这将永远感到困惑。

似乎有(但文档不清楚它们是否总是存在)PHP 函数gzencode()gzdecode()如果我正确阅读了简洁的文档,默认情况下会创建和解码 gzip 格式。 gzencode()还有一个生成 zlib 格式的选项,我怀疑它gzdecode()会尝试自动检测 gzip 或 zlib 格式并相应地解码。(这是所有这些函数都使用的实际zlib 库的一部分。)

zlib_encode()和的文档zlib_decode()不完整(这些页面承认:“此函数当前未记录;只有它的参数列表可用”),因此很难说出它们在做什么。如果您知道要在字符串中放入什么,则有一个未记录的encoding字符串参数zlib_encode()可能允许您选择三种格式之一。没有encoding参数zlib_decode(),所以它可能会尝试在三种格式中自动检测。

于 2012-05-16T14:30:57.877 回答
1

我知道这已经过时了,但我确实花了一整天的时间在玩这段代码。
我做的事情真的很挑剔。但是,这里有一个快速函数可以将 TMX 文件转换为每个图层上每个图块的 ID 数组。

功劳归于其他回答者,他们帮助我拼凑出我出错的地方。

<?php

function getLayer($getLayerName = '')
{
    $xml = simplexml_load_file('level.tmx');
    $values = array();
    foreach($xml->layer as $child)
    {
        $name = $child->attributes()->name;

        if(!empty($getLayerName))
            if($name != $getLayerName)
                continue;

        $data = gzinflate(substr(base64_decode(trim($child->data)), 10));
        $chars = str_split($data);
        $i = 0;
        foreach($chars as $char)
        {
            $charID = ord($char);
            if($i % 4 == 0) // I'm only interested in the tile IDs
            {
                $values[(String) $name][] = $charID;
            }
            $i++;
        }
    }
    return $values;
}

print_r(getLayer());
//or you could use getLayer('LayerName') to get a single layer!

?>

在我的示例 3x3 地图上,只有一张平铺图像,我得到以下信息:

Array
(
    [floor] => Array
        (
            [0] => 1
            [1] => 1
            [2] => 1
            [3] => 1
            [4] => 1
            [5] => 1
            [6] => 1
            [7] => 1
            [8] => 1
        )

    [layer2] => Array
        (
            [0] => 0
            [1] => 0
            [2] => 1
            [3] => 0
            [4] => 1
            [5] => 0
            [6] => 1
            [7] => 1
            [8] => 0
        )

)

希望这个功能对任何需要它的人来说都很方便。

于 2013-04-25T15:09:07.953 回答