0

セットアップ:
iPhone 用の 2D タイル ベースのゲーム (鳥瞰図) に取り組んでいます。アプリは、ヒーローがタイルを移動できるかどうかを表す true または false の「ブロック」プロパティを持つタイルの tile-d (.tbx) タイルマップ ファイルを読み取ります。マップ内の各タイルを繰り返し処理し、タイルの行と列を表す 2 次元の C 配列を作成して、各タイルのブロックされたプロパティ (true/false) を保持します。ヒーローをボード上で移動するときは、アレイでヒーローの位置を確認して、移動したタイルがブロックされているかどうかを確認します。ブロックされた場合、ヒーローの位置は前進した分だけ反転します。

問題:
ブロックされたタイルをヒーローが踏んだ場合、そこから移動できないという問題があります。ブロックされたタイルが本来あるべき場所で検出されるという意味で、タイルの位置は正しいですが、それでもヒーローは立ち往生しています。ヒーローは「タイルごと」ではなく「ピクセルごと」に進みます。それがすべてです。残っているのはコードを表示することだけです: (ヒーローのサイズは 28 x 36 ピクセルです)

//Code from GameScreen.m





-(void)generateCollisionMap
{




for(int layer=0; layer < 2; layer++) {
            for(int yy=0; yy < _screenTilesHeight; yy++) {

                NSLog(@"Row %i", yy);

                for(int xx=0; xx < _screenTilesWide; xx++) {
                    int _globalTileID = [[[tileMap layers] objectAtIndex:layer] getGlobalTileIDAtX:xx y:yy];
                    NSString *_value = [tileMap getTilePropertyForGlobalTileID:_globalTileID key:@"blocked" defaultValue:@"false"];
                    if([_value isEqualToString:@"true"]) {

                        _blocked[xx][yy] = YES;
                        NSLog(@"Cell %i = YES", xx);

                    }else{

                        if(_blocked[xx][yy] == YES){
                        NSLog(@"Leaving Cell %i as = YES", xx);
                            //Leave As Is

                        }else{

                         _blocked[xx][yy] = NO;
                        NSLog(@"Cell %i = NO", xx);

                        }

                    }
                }
            }
            }
}





//Code from Hero.m


-(void)moveHero
{

            // Up

            if(moveDirection == 1 && !doesNeedShiftWorld) {
                heroY += _playerSpeed;
                [self checkBlocked:1];
                _currentAnimation = _upAnimation;
                _moving = YES;
            }

            // Down
            if(moveDirection == 2 && !doesNeedShiftWorld) {
                heroY -= _playerSpeed;
                [self checkBlocked:2];
                _currentAnimation = _downAnimation;
                _moving = YES;
            }

            // Left
            if(moveDirection == 3 && !doesNeedShiftWorld) {
                heroX -= _playerSpeed;
                [self checkBlocked:3];
                _currentAnimation = _leftAnimation;
                _moving = YES;
            }

            // Right
            if(moveDirection == 4 && !doesNeedShiftWorld) {
                heroX += _playerSpeed;
                [self checkBlocked:4];
               _currentAnimation = _rightAnimation;
                _moving = YES;
            }



}   



//  ... 


- (void) checkBlocked:(int)checkDirection
{

    float xx = (heroX+160.0f+_tileWidth) / _tileWidth;
    float yy = 11-((heroY+300.0f+_tileHeight) / _tileHeight); 


    switch (checkDirection) {

        case 1:

            yy -= 1;

            if([_scene isBlocked:xx y:yy] ||
               [_scene isBlocked:(heroX+160.0f) y:yy]) {
                NSLog(@"Scene Blocked at %i, %i!", (int)xx, (int)yy);
                heroY -= _playerSpeed;

            }else{

                NSLog(@"Clear at %i, %i!", (int)xx, (int)yy);

            }

            break;

        case 2:


            if([_scene isBlocked:xx y:yy] ||
               [_scene isBlocked:xx y:(heroY+300.0f)] ||
               [_scene isBlocked:(heroX+160.0f) y:(heroY+300.0f)]) {
                NSLog(@"Scene Blocked at %i, %i!", (int)xx, (int)yy);
                heroY += _playerSpeed;

            }else{

                NSLog(@"Clear at %i, %i!", (int)xx, (int)yy);

            }


            break;

        case 3:

            xx += 1;

            if([_scene isBlocked:xx y:yy] ||
               [_scene isBlocked:(heroX+160.0f) y:yy] || 
               [_scene isBlocked:(heroX+160.0f) y:(heroY+300.0f)]) {
                NSLog(@"Scene Blocked at %i, %i!", (int)xx, (int)yy);
                heroX += _playerSpeed;

            }else{

                NSLog(@"Clear at %i, %i!", (int)xx, (int)yy);

            }


            break;

        case 4:


            if([_scene isBlocked:xx y:yy] || 
               [_scene isBlocked:xx y:(heroY+300.0f)]) {
                NSLog(@"Scene Blocked at %i, %i!", (int)xx, (int)yy);
                heroX -= _playerSpeed;

            }else{

                NSLog(@"Clear at %i, %i!", (int)xx, (int)yy);

            }


            break;

    }

}
4

2 に答える 2

4

あなたの問題は、あなたがプレーヤーを動かしていて、次に彼が移動したスペースがブロックされているかどうかを確認することです。代わりに、彼が移動したい位置を把握し、ブロックされているかどうかを確認してから、ブロックされていない場合にのみ移動します。また、彼の現在のスペースを除外する句をいつでも追加できます。つまり、キャラクターがグリッドスペースを変更していない限り、いつでも移動できますが、グリッドスペースを変更しようとしたら、何かと衝突するかどうかを確認する必要があります。

以下にコードを示します。

if(moveDirection == 1 && !doesNeedShiftWorld) {
    heroY += _playerSpeed;
    [self checkBlocked:1];
    _currentAnimation = _upAnimation;
    _moving = YES;
}

次のようになります。

if(moveDirection == 1 && !doesNeedShiftWorld)
{
    //Figure out if the player is changing grid spaces.
    BOOL isChangingSpaces = ((int)((heroY + _playerSpeed) / myGridSizeVariable) != (int)(heroY / myGridSizeVariable));

    //The player should be able to move either if he isn't
    //changing grid spaces or if his destination space is free.
    if ( !isChangingSpaces || (spaceIsOpenAtX:heroX andY:heroY+_playerSpeed) )
    {
        heroY += _playerSpeed;
        _currentAnimation = _upAnimation;
        _moving = YES;
    }
}

そして、あなたは本当にあなたのコードをもっとオブジェクト指向にすることを試みるべきです。この時点では、それは完全に手続き型であり、すべての変数はグローバルであるように見えます。これは間違いなく良い方法ではありません。「checkBlocked」は「spaceIsOpenAtX:andY:」と書き直す必要があります。これは、その位置がブロックされているかどうかを確認するために、任意のX座標とY座標を配置できるためです。あなたが今やったように、あなたのコードは抽象的すぎて(実際のifステートメントチェック以外にそれらが何を意味するのかを示さずに整数を渡す)、あなたが与えた単一の使用を除いてどんな状況にも適用できませんそれ。

実際には、player.speed、player.animation、[maze spaceIsOpen]などが必要です。CだけでなくObjective-Cを使用しています。また、Cを使用している場合でも、 OOの方法。

于 2009-10-01T14:13:22.227 に答える
0

問題は、プレイヤーがブロックされたタイルに移動できるようにして、スタックすることだと思います。

プレイヤーをそこに移動させる前に、プレイヤーが移動している方向がブロックされているかどうかを確認します。

于 2009-10-01T13:56:37.907 に答える