0

设置:
我正在为 iPhone 开发基于 2-D 瓷砖的游戏(鸟瞰图)。该应用程序读入一个 tile-d (.tbx) tilemap 文件,该文件具有 true 或 false 的“blocked”属性,以表示英雄是否可以通过该图块。我遍历地图中的每个图块并创建一个表示图块行和列的二维 C 数组,以保存每个图块的阻塞属性(真/假)。当我全面移动英雄时,我会用数组检查英雄的位置,看看他移动的棋子是否被阻挡。如果被阻挡,英雄的位置会与前进时的位置相反。

问题:
问题是,当英雄踩到一块被阻挡的瓷砖时,他无法离开它。瓷砖位置是正确的,因为被阻挡的瓷砖被检测到它们应该在的位置,但英雄仍然被卡住。英雄“按像素”而不是“按图块”前进。这就是全部。剩下的就是显示代码:(Hero 大小为 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] 等。你使用的是 Objective-C,而不仅仅是 C。即使你使用的是 C,在OO方式。

于 2009-10-01T14:13:22.227 回答
0

我认为问题在于您允许玩家移动到被阻挡的瓷砖上并且他被卡住了。

在尝试将玩家移动到那里之前,我会检查玩家移动的方向是否被阻挡。

于 2009-10-01T13:56:37.907 回答