-2

GWTを使用してWebクライアントベースのオンラインゲームを開発しようとしています。

ゲームの仕組みは今では非常にうまく機能しており、開発計画の次のステップに進みたいと思っていますが、クライアントのデータを文字列に格納するために作成した単純なエンコード/デコード関数で立ち往生しています。 。

私が取った手順はそれほど複雑ではありません。実行時に、サーバーはクライアントのCanvasに描画されるゲームオブジェクトの「ImageStates」を作成します。各ImageStateには、特定の時間に、どこに、何を描画する必要があるかなどの詳細を含む、いくつかのレイヤーが含まれています。

ObjectInput / OutputStreamをGZip-CompressionとByteInputStreamsと組み合わせて試しましたが、最初の2つのGWT実装が見つからなかったため、別の解決策を考えなければならず、gwt-lzmaに出くわしました。

私の目標は、これらの詳細を1つの文字列にエンコードし、サーバーで圧縮し、圧縮されたデータをクライアントに送信し、そこで解凍してデコードし、クライアントが「読み取る」ことができるようにすることです。そのために、エンコード関数とデコード関数を作成しました。

エンコーダー:

public static String encodeImageStateContainer(HashMap<String,HashMap<Long,ImageState>> imageStateContainer){
    StringBuilder mainStringBuilder = new StringBuilder();

    Iterator<Entry<String,HashMap<Long,ImageState>>> imageStateContainerIterator = imageStateContainer.entrySet().iterator();
    while(imageStateContainerIterator.hasNext()){
        Entry<String,HashMap<Long,ImageState>> tempImageStateManagerMetadata = imageStateContainerIterator.next();

        HashMap<Long,ImageState> tempImageStateManager = tempImageStateManagerMetadata.getValue();

        if(tempImageStateManager.size() > 0){

            if(mainStringBuilder.length() > 0){
                mainStringBuilder.append('}');  //Divisor between Image State Managers
            }

            mainStringBuilder.append(tempImageStateManagerMetadata.getKey());
            mainStringBuilder.append('|');  //Divisor between Name and following Data

            StringBuilder subOneStringBuilder = new StringBuilder();            

            Iterator<Entry<Long,ImageState>> tempImageStateManagerIterator = tempImageStateManager.entrySet().iterator();
            while(tempImageStateManagerIterator.hasNext()){
                Entry<Long,ImageState> tempImageStateMetaData = tempImageStateManagerIterator.next();

                if(subOneStringBuilder.length() > 0){
                    subOneStringBuilder.append(')');    //Divisor between Image Objects
                }

                subOneStringBuilder.append(tempImageStateMetaData.getKey());
                subOneStringBuilder.append('-');    //Divisor between Object Id and Image State Data

                StringBuilder subTwoStringBuilder = new StringBuilder();
                ImageState tempImageState = tempImageStateMetaData.getValue();
                subOneStringBuilder.append(tempImageState.getFirstFrameId());   //1. => First Frame Id
                subOneStringBuilder.append(';');    //Divisor between Image State data types
                subOneStringBuilder.append(tempImageState.getFramesPerLayer()); //2. => Total Frame Count
                subOneStringBuilder.append(';');
                subOneStringBuilder.append(tempImageState.getMinumimScaleFactor()); //3. => Minimum Scale Factor
                subOneStringBuilder.append(';');

                ImageStateLayer[] tempImageStateLayers = tempImageState.getImageStateLayers();
                for(int layerId = 0; layerId < tempImageStateLayers.length; ++layerId){

                    if(subTwoStringBuilder.length() > 0){
                        subTwoStringBuilder.append('/');    //Divisor between Image State Layers
                    }

                    //Frame Arrays
                    String[] imageNativePath = tempImageStateLayers[layerId].getImageNativePath();
                    short[] offsetX = tempImageStateLayers[layerId].getOffsetX();
                    short[] offsetY = tempImageStateLayers[layerId].getOffsetY();
                    short[] orientation = tempImageStateLayers[layerId].getOrientation();

                    //Finalization Arrays
                    byte[] imagePathChange = tempImageStateLayers[layerId].getImagePathChange();
                    byte[] offsetXChange = tempImageStateLayers[layerId].getOffsetXChange();
                    byte[] offsetYChange = tempImageStateLayers[layerId].getOffsetYChange();
                    byte[] orientationChange = tempImageStateLayers[layerId].getOrientationChange();


                    //Image Path Data
                    StringBuilder subThreeStrignBuilder = new StringBuilder();
                    for(int imagePathId = 0; imagePathId < imageNativePath.length; ++imagePathId){

                        if(subThreeStrignBuilder.length() > 0){
                            subThreeStrignBuilder.append('#');  //Divisor between Frame Data Sets
                        }

                        subThreeStrignBuilder.append(imageNativePath[imagePathId]);
                        subThreeStrignBuilder.append(',');  //Divisor between Frame Data Set Data
                        subThreeStrignBuilder.append(imagePathChange[imagePathId]);
                    }

                    subTwoStringBuilder.append(subThreeStrignBuilder.toString());
                    subTwoStringBuilder.append('[');    //Divisor between Frame Data Types

                    //OffsetX Data
                    subThreeStrignBuilder = new StringBuilder();
                    for(int offsetXId = 0; offsetXId < offsetX.length; ++offsetXId){

                        if(subThreeStrignBuilder.length() > 0){
                            subThreeStrignBuilder.append('#');  //Divisor between Frame Data Sets
                        }

                        subThreeStrignBuilder.append(offsetX[offsetXId]);
                        subThreeStrignBuilder.append(',');  //Divisor between Frame Data Set Data
                        subThreeStrignBuilder.append(offsetXChange[offsetXId]);
                    }

                    subTwoStringBuilder.append(subThreeStrignBuilder.toString());
                    subTwoStringBuilder.append('[');    //Divisor between Frame Data Types

                    //OffsetY Data
                    subThreeStrignBuilder = new StringBuilder();
                    for(int offsetYId = 0; offsetYId < offsetY.length; ++offsetYId){

                        if(subThreeStrignBuilder.length() > 0){
                            subThreeStrignBuilder.append('#');  //Divisor between Frame Data Sets
                        }

                        subThreeStrignBuilder.append(offsetY[offsetYId]);
                        subThreeStrignBuilder.append(',');  //Divisor between Frame Data Set Data
                        subThreeStrignBuilder.append(offsetYChange[offsetYId]);
                    }

                    subTwoStringBuilder.append(subThreeStrignBuilder.toString());
                    subTwoStringBuilder.append('[');    //Divisor between Frame Data Types

                    //Orientation Data
                    subThreeStrignBuilder = new StringBuilder();
                    for(int orientationId = 0; orientationId < orientation.length; ++orientationId){

                        if(subThreeStrignBuilder.length() > 0){
                            subThreeStrignBuilder.append('#');  //Divisor between Frame Data Sets
                        }

                        subThreeStrignBuilder.append(orientation[orientationId]);
                        subThreeStrignBuilder.append(',');  //Divisor between Frame Data Set Data
                        subThreeStrignBuilder.append(orientationChange[orientationId]);
                    }

                    subTwoStringBuilder.append(subThreeStrignBuilder.toString());

                }
                subOneStringBuilder.append(subTwoStringBuilder.toString());             
            }
            mainStringBuilder.append(subOneStringBuilder.toString());
        }
    }

    return mainStringBuilder.toString();
}

デコーダー:

public static HashMap<String,HashMap<Long,ImageState>> decodeImageStateContainer(String data){      

    String[] imageStateManagerArray = data.split("\\}");
    HashMap<String,HashMap<Long,ImageState>> imageStateManagerContainer = new HashMap<String,HashMap<Long,ImageState>>(imageStateManagerArray.length);

    for(int managerId = 0; managerId < imageStateManagerArray.length; ++managerId){
        String[] tempImageStateData = imageStateManagerArray[managerId].split("\\|");

        HashMap<Long,ImageState> tempImageStateManager = new HashMap<Long,ImageState>();
        imageStateManagerContainer.put(tempImageStateData[0], tempImageStateManager);

        String[] tempImageStateManagerObjects = tempImageStateData[1].split("\\)");

        for(int objectId = 0; objectId < tempImageStateManagerObjects.length; ++objectId){
            String[] tempImageObjectData = tempImageStateManagerObjects[objectId].split("\\-");

            long imageObjectId = Long.parseLong(tempImageObjectData[0]);
            String[] imageStateMetaData = tempImageObjectData[1].split("\\;");              
            ImageState tempImageState = new ImageState(Integer.parseInt(imageStateMetaData[1]), Integer.parseInt(imageStateMetaData[0]), Integer.parseInt(imageStateMetaData[2]));
            tempImageStateManager.put(imageObjectId, tempImageState);

            String[] tempImageStateLayerMetaData = imageStateMetaData[3].split("\\/");
            ImageStateLayer[] tempImageStateLayers = new ImageStateLayer[tempImageStateLayerMetaData.length];

            for(int layerId = 0; layerId < tempImageStateLayerMetaData.length; ++layerId){
                String[] layerElements = tempImageStateLayerMetaData[layerId].split("\\[");     

                String[] imageNativePathDetails = layerElements[0].split("\\#");
                String[] offsetXDetails = layerElements[1].split("\\#");
                String[] offsetYDetails = layerElements[2].split("\\#");
                **String[] orientationDetails = layerElements[3].split("\\#");**

                //Image Path Data
                String[] imageNativePaths = new String[imageNativePathDetails.length];
                byte[] imagePathChange = new byte[imageNativePathDetails.length];
                for(int id = 0; id < imageNativePathDetails.length; ++id){                      
                    String[] imagePathDetailElements = imageNativePathDetails[id].split("\\,");
                    imageNativePaths[id] = imagePathDetailElements[0];
                    imagePathChange[id] = Byte.parseByte(imagePathDetailElements[1]);
                }

                //OffsetX Data
                short[] offsetX = new short[offsetXDetails.length];
                byte[] offsetXChange = new byte[offsetXDetails.length];
                for(int id = 0; id < offsetXDetails.length; ++id){
                    String[] offsetXDetailElements = offsetXDetails[id].split("\\,");
                    offsetX[id] = Short.parseShort(offsetXDetailElements[0]);
                    offsetXChange[id] = Byte.parseByte(offsetXDetailElements[1]);
                }

                //OffsetY Data
                short[] offsetY = new short[offsetYDetails.length];
                byte[] offsetYChange = new byte[offsetYDetails.length];
                for(int id = 0; id < offsetYDetails.length; ++id){
                    String[] offsetYDetailElements = offsetYDetails[id].split("\\,");
                    offsetY[id] = Short.parseShort(offsetYDetailElements[0]);
                    offsetYChange[id] = Byte.parseByte(offsetYDetailElements[1]);
                }

                //Orientation Data
                short[] orientation = new short[orientationDetails.length];
                byte[] orientationChange = new byte[orientationDetails.length];
                for(int id = 0; id < orientationDetails.length; ++id){
                    String[] orientationDetailElements = orientationDetails[id].split("\\,");
                    orientation[id] = Short.parseShort(orientationDetailElements[0]);
                    orientationChange[id] = Byte.parseByte(orientationDetailElements[1]);
                }

                //Create the Layer and Add it to the Array
                tempImageStateLayers[layerId] = new ImageStateLayer(imageNativePaths,new short[][]{offsetX,offsetY,orientation}, new byte[][]{imagePathChange,offsetXChange,offsetYChange,orientationChange});

            }

            //Connect the Reference to the layers with the Image State
            tempImageState.setImageStateLayers(tempImageStateLayers);

        }           

    }       

    return imageStateManagerContainer;
}

今私の問題:サーバーでエンコードしてすぐにデコードする場合デコーダーのこの特定の位置でIndexOutofBoundsExceptionが発生するまで、エンコードの約3サイクルかかります。最後の行は、エラーが次のように見える行です。スタックトレース:

for(int layerId = 0; layerId < tempImageStateLayerMetaData.length; ++layerId){
                String[] layerElements = tempImageStateLayerMetaData[layerId].split("\\[");     

                String[] imageNativePathDetails = layerElements[0].split("\\#");
                String[] offsetXDetails = layerElements[1].split("\\#");
                String[] offsetYDetails = layerElements[2].split("\\#");
                String[] orientationDetails = layerElements[3].split("\\#");

私は専門家だとは言えませんが、エンコーダーをテストした後、エンコーダーによって生成された文字列は常に有効であり、このエラーが発生した文字列も完全であると断言できます。デコード機能に問題があるはずですが、何ができるのかわかりません。

私が言ったように、最初の3サイクルは適切にエンコードおよびデコードされ、エンコードするデータは劇的に変化しませんでした。エンコードされた文字列が4要素よりも小さい文字列配列を持つことにつながる可能性はありません。基本的に、私のコードを理解している限り、このエラーは存在しません。

文字列が適切に分割されないのは、ある種のメモリ割り当ての問題である可能性があると思いますが、それは無知なプログラマーの考えにすぎません。

どんな助けでも深く感謝します!

4

1 に答える 1

2

私は自分の問題の解決策を見つけました:

エンコード中に、文字列に数値型を出力していました。セパレータシンボルを選択している間、負の値を取りませんでした。その結果、数字の前に「-」が考慮され、「-」で分割しようとすると、文字列が制御不能に分割されました。マイナスを別の文字に置き換えたところ、すべてが正常に機能するようになりました。

于 2012-05-25T12:26:07.693 に答える