0

私は、SDLの使い方を学ぶのに役立つ非常にシンプルなビデオゲームを設計しています。衝突検出で問題が発生しました。ゲームマップを(タイルを使用して)描画するために、というクラスで、というクラスMapへのポインターの2D配列を作成しますTile。このMapクラスにはset_tiles、ファイルからタイルを読み取ることによってすべてのタイルを定義するという関数があり.MAPます。Heroまた、ヒーローに関するすべての関数と変数を含む、というクラスもあります。すべて非常に些細なことです。ただし、他の場所から配列を読み取ろうとすると、奇妙な結果が生成されます(バグテストにより、x値とy値が数千ずれていることがわかりましたが、そこで間違いを犯した可能性があります)。これがコードです。

SDL_Surface* Map::set_tiles ( SDL_Surface* tile_image ) {

Setup setup;

//Make a temporary map to draw the tiles to
Uint32 rmask, gmask, bmask, amask;
if ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) {
    rmask = 0x00000000;
    gmask = 0x00000000;
    bmask = 0x00000000;
    amask = 0x00000000;
}
else {
    rmask = 0x00000000;
    gmask = 0x00000000;
    bmask = 0x00000000;
    amask = 0x00000000;
}
SDL_Surface* temp_map = SDL_CreateRGBSurface(SDL_SWSURFACE, MAP_WIDTH, MAP_HEIGHT, 32, rmask, gmask, bmask, amask);

//Open the map
std::ifstream map ( "Test.map" );

//Catch any errors
if ( map.fail() ) return NULL;

//Initialize the tiles
for ( int y = 0; y < MAP_HEIGHT / TILE_HEIGHT; y++ ) {
    for ( int x = 0; x < MAP_WIDTH / TILE_WIDTH; x++ ) {
        //Determines the tile type
        int tile_type = -1;

        //Read the tile type from the map
        map >> tile_type;

        //Make sure it's a real tile
        if ( tile_type < 0 || tile_type >= TILE_SPRITES ) {
            map.close();
            return NULL;
        }

        //Error check for the .map file
        if ( map.fail() ) {
            map.close();
            return NULL;
        }

        //Add the tile to the array
        tile_array[x][y] = &Tile ( x, y, tile_type );

        //Create the temp. image crop
        SDL_Rect* temp_crop = &tile_array[x][y]->get_crop();

        //Edit the temp. map
        setup.apply_surface ( x * TILE_WIDTH, y * TILE_HEIGHT, tile_image, temp_map, temp_crop );
    }

}

map.close();

//Return the modified map
return temp_map;

}

さて、どこかで読もうとすると問題があります。IE

bool Hero::collision_check ( Map map ) {
for ( int y = 0; y < MAP_HEIGHT / TILE_HEIGHT; y++ ) {
    for ( int x = 0; x < MAP_WIDTH / TILE_WIDTH; x++ ) {
        Tile* tile = map.tile_array[x][y];
        if ( collision ( box, tile->get_box() ) ) {
            //Switch the effect based on the tile type
            switch ( tile->get_type() ) {
            case TILE_RED:
            case TILE_GREEN:
            case TILE_BLUE:
                return false;
                break;
            case TILE_CENTER:
            case TILE_TOP:
            case TILE_TOPRIGHT:
            case TILE_RIGHT:
            case TILE_BOTTOMRIGHT:
            case TILE_BOTTOM:
            case TILE_BOTTOMLEFT:
            case TILE_LEFT:
            case TILE_TOPLEFT:
                return true;
                break;
            default:
                return false;
            }
        }
    }
}
return false;
}

ポインター(または他のほとんどのもの)に関しては、私はマスターではありません。私の問題を説明する明らかな欠陥はありますか?

4

2 に答える 2

1

これは、スコープ外になる一時的なものへのポインタになります。

 tile_array[x][y] = &Tile ( x, y, tile_type );

あなたはおそらく探しています

 tile_array[x][y] = new Tile ( x, y, tile_type );

PS1:上部のifステートメントはあまり役に立たないようです

PS2:次回は、すべてのコードではなく最小限の例を投稿すると役立ちます-人々は、コードが多すぎて読み通せない投稿を無視する傾向があります

編集:

あなたがしていることは基本的に:

Foo* fp;
// a Foo() is created, its address assigned to fp,
// but it is then destroyed at the end of the statement
fp = &Foo(2);
// now fp is a pointer to unallocated memory and using it causes undefined behaviour
fp.val; // this value is now undefined
于 2013-02-20T21:30:35.660 に答える
1

行で

tile_array[x][y] = &Tile ( x, y, tile_type );

一時的なアドレスをベクターに割り当てています。その式が終了するとすぐに、一時オブジェクトが破棄され、保存したポインターが無効なオブジェクトを指すようになります。Tileオブジェクトへのポインタを格納する代わりに、タイルオブジェクト自体をに格納しますtile_array

于 2013-02-20T21:32:43.863 に答える