2

.tmx(タイル)ファイルからレイヤーコンテンツを抽出する際に問題が発生します。PHPで完全な非圧縮データを取得し、そのイメージを少し作成したいと思います。幅、高さなどのヘッダー情報を取得することは問題ありません-SimpleXMLはそこでその仕事をしています。しかし、どういうわけかタイルレイヤーの解凍が機能していません。

データ自体はbase64およびgzipでエンコードされた文字列(sth like H4sIAAAAAAAAC+3bORKAIBQEUVzuf2YTTSwEA/gL00EnJvJQsAjcSyk7EU3v+Jn3OI)として保存されますが、base64でデコードされたコードを取得することさえ問題があります(奇妙な文字が表示され、マップをタイルで開いて「base64uncompressed」として保存すると結果は単なる空の文字列でした-もちろんgzip解凍を使用していません)

私はすでにWebを検索し、データがどのように正確に圧縮されているかを確認しました(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の記事)。今、私は本当に混乱しました。私は何を選ぶべきかわかりません-私はもう一度グーグルに尋ねて、次のものを得ました:Javaで圧縮する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レイヤーは主にgid0、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 関数の名前はひどいものです。最初にいくつかの背景。

遭遇する可能性が高い、または作成できるフォーマットが 3 つあります。彼らです:

  • Raw deflate は、 RFC 1951で定義されている、ヘッダーやトレーラーのない deflate 形式に圧縮されたデータです。
  • RFC 1950で定義されているコンパクトな zlib ヘッダーと、2 バイトのヘッダーとトレーラーとしての 4 バイトの Adler-32 チェック値で構成されるトレーラーにラップされた生のデフレート データである zlib 。
  • gzip は、gzip ヘッダーとトレーラーにラップされた生のデフレート データであり、ヘッダーは少なくとも 10 バイトであり、ファイル名、コメント、および/または追加フィールドを含むより長くなる可能性があります。 -byte CRC-32 および圧縮されていない長さモジュール 2^32。このラッパーはRFC 1952で定義されています。これは、接尾辞 が付いたファイルにあるデータです.gz

PHP 関数は、生の deflate 形式gzdeflate()gzinflate()作成およびデコードします。PHP 関数は、zlib 形式 gzcompress()を作成およびデコードします。これらの関数はいずれもgzip 形式を処理しないため、名前に「gz」を含むべきではありません! これは、gzip 形式のデータを作成またはデコードしようとする PHP コーダーにとって、永遠に混乱を招くことになります。gzuncompress()

あるようです(ただし、ドキュメントが常に存在するかどうかは明確ではありません)PHP関数gzencode()gzdecode()、簡潔なドキュメントを正しく読んでいる場合、デフォルトでgzip形式を作成およびデコードします。 gzencode()zlib 形式を生成するオプションもありgzdecode()、gzip または zlib 形式を自動的に検出し、それに応じてデコードしようとするのではないかと思います。(これは、これらすべての関数が使用する実際のzlib ライブラリの一部である機能です。)

zlib_encode()とのドキュメントzlib_decode()は不完全です (これらのページでは、「この関数は現在ドキュメント化されていません。その引数リストのみが利用可能です」と認められています)。文書化されていないencoding文字列パラメーターがありzlib_encode()、文字列に何を入れるかがわかっている場合は、3 つの形式のいずれかを選択できると思われます。にはencodingパラメータがないためzlib_decode()、おそらく 3 つの形式の中で自動検出を試みます。

于 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 マップでは、タイル画像が 1 つしかないため、次のようになります。

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 に答える