cocos2d-android(github version)在移动背景图层时,如何让“播放器”精灵在屏幕上居中?

时间:2012-02-29 04:53:52

标签: android cocos2d-iphone maps cocos2d-android tmx

我正在学习cocos2d-android。我一直在学习将Ray Wenderlich的一些iOS教程移植到Android上的教程。我已经完成了第一个教程,并希望继续将下一个Ray Wenderlich教程转换为Android,作为学习练习。

最初的iOS教程可以在这里找到http:// www raywenderlich com / 1163 / how-to-make-a-tile-based-game-with-cocos2d

我已将应用程序转换为android,但在行为方式上遇到了一些麻烦。

我的代码在这里:

公共类GameLayer扩展了CCLayer {

private CGSize _winSize;
protected ArrayList<CCSprite> _targets;
protected ArrayList<CCSprite> _projectiles;
protected int _projectilesDestroyed;
protected CCSprite _player;
protected CCSprite _nextProjectile;
protected CCTMXTiledMap _map;
protected CCTMXLayer _background;
protected CCTMXObjectGroup _objects;
protected HashMap<String, String> _spawnPoint;

protected GameLayer() {
    super();
    _winSize = CCDirector.sharedDirector().displaySize();
    _targets = new ArrayList<CCSprite>();
    _projectiles = new ArrayList<CCSprite>();
    _projectilesDestroyed = 0;

    // Get TMX Map and associated layers/groups
    _map = CCTMXTiledMap.tiledMap("TileMap.tmx");
    _background = _map.layerNamed("Background");
    _objects = _map.objectGroupNamed("Objects");

    // Add my background layer
    // TODO: Position layer in the correct spot.
    addChild(_background);

    _spawnPoint = _objects.objectNamed("SpawnPoint");

    _player = CCSprite.sprite("Player3.png");

    setPlayerPosition(CGPoint.ccp (100.0f, 100.0f));

    addChild(_player);
    setViewPointCentered(_player.getPosition());

    Context context = CCDirector.sharedDirector().getActivity();
    SoundEngine.sharedEngine().preloadEffect(context, R.raw.pew_pew_lei);
    SoundEngine.sharedEngine().playSound(context, R.raw.background_music_aac, true);

    this.setIsTouchEnabled(true);
    this.schedule("update");
}

public void setViewPointCentered(CGPoint pos) {
    float x = 0.0f;
    float y = 0.0f;

    x = Math.max(pos.x, _winSize.width / 2);
    y = Math.max(pos.y, _winSize.height / 2);

    x = Math.min(x,  (_map.getMapSize().width * _map.getTileSize().width) - _winSize.width / 2 );
    y = Math.min(y, (_map.getMapSize().height * _map.getTileSize().height) - _winSize.height / 2);

    CGPoint actualPos = CGPoint.ccp(x, y);

    CGPoint centerOfView = CGPoint.ccp(_winSize.width / 2, _winSize.height / 2);
    CGPoint viewPoint = CGPoint.ccpSub(centerOfView, actualPos);

    _background.setPosition(viewPoint);
}

public static CCScene scene() {
    CCScene scene = CCScene.node();
    CCLayer layer = new GameLayer();

    scene.addChild(layer);

    return scene;
}

@Override
public boolean ccTouchesBegan(MotionEvent event) {
    return true;

}

void setPlayerPosition(CGPoint position) {
    _player.setPosition(position);
}

@Override
public boolean ccTouchesEnded(MotionEvent event) {

    // Choose one of the touches to work with
    CGPoint touchLocation = CGPoint.ccp(event.getX(), event.getY());
    touchLocation = CCDirector.sharedDirector().convertToGL(touchLocation);
    touchLocation = this.convertToNodeSpace(touchLocation);

    CGPoint playerPosition = _player.getPosition();
    CGPoint diff = CGPoint.ccpSub(touchLocation, playerPosition);

    if (Math.abs(diff.x) > Math.abs(diff.y)) {
        if (diff.x > 0) {
            playerPosition.x += _map.getTileSize().width;
        } else {
            playerPosition.x -= _map.getTileSize().width;
        }
    } else {
        if (diff.y > 0) {
            playerPosition.y += _map.getTileSize().height;
        } else {
            playerPosition.y -= _map.getTileSize().height;
        }
    }

    if (playerPosition.x <= (_map.getMapSize().width * _map.getTileSize().width) &&
        playerPosition.y <= (_map.getMapSize().height * _map.getTileSize().height) &&
        playerPosition.y >= 0 &&
        playerPosition.x >= 0 ) {
        setPlayerPosition(playerPosition);
    }

    setViewPointCentered(_player.getPosition());

    return true;

}

public void finishShoot() {
    addChild(_nextProjectile);
    _projectiles.add(_nextProjectile);
}

public void update(float dt) {
    ArrayList<CCSprite> projectilesToDelete = new ArrayList<CCSprite>();

    for (CCSprite projectile : _projectiles) {
        CGRect projectileRect = CGRect.make(projectile.getPosition().x - (projectile.getContentSize().width / 2.0f),
                projectile.getPosition().y - (projectile.getContentSize().height / 2.0f),
                projectile.getContentSize().width,
                projectile.getContentSize().height);

        ArrayList<CCSprite> targetsToDelete = new ArrayList<CCSprite>();
        for (CCSprite target : _targets) {
            CGRect targetRect = CGRect.make(target.getPosition().x - (target.getContentSize().width),
                    target.getPosition().y - (target.getContentSize().height),
                    target.getContentSize().width,
                    target.getContentSize().height);

            if (CGRect.intersects(projectileRect, targetRect)) {
                targetsToDelete.add(target);
            }
        }

        for (CCSprite target : targetsToDelete) {
            _targets.remove(target);
            removeChild(target, true);
        }

        if (targetsToDelete.size() > 0) {
            projectilesToDelete.add(projectile);
        }
    }

    for (CCSprite projectile : projectilesToDelete) {
        _projectiles.remove(projectile);
        removeChild(projectile, true);
        if (++_projectilesDestroyed > 30) {
            _projectilesDestroyed = 0;
            CCDirector.sharedDirector().replaceScene(GameOverLayer.scene("You Win!"));
        }
    }
}

}

我首先抓住我的显示尺寸并从我的TMX文件创建我的平铺地图。我得到了我的背景图层并将其添加为孩子。然后我抓住我的对象图层并将我的生成点对象拉出地图(为了测试目的,我用100,100覆盖这个生成点)。我抓住我的玩家精灵并将我的玩家位置设置为100,100坐标。然后我小时候添加播放器。

接下来,我调用setViewPointCentered,根据我的玩家位置将地图移动到合适的位置。这部分工作得很好,我的地图放置在我的屏幕左下角(0,0)的左下角(0,0),我的角色是100,100从屏幕中心稍微向左和向下

当我开始向上或向右移动时会出现问题。一旦我通过屏幕的中心,我希望玩家精灵保持在屏幕中心,当我继续移动时,背景向相反的方向移动。然而,玩家和背景都移动,所以最终我的玩家到达屏幕的右边缘或上边缘,即使有足够的地图,我也无法向上或向右移动。

注意地图左上角的玩家。

Player reaching the top of screen and not staying centered as expected

注意地图右下角的玩家。

Player reaching the right of screen and not staying centered as expected

“public boolean ccTouchesEnded(MotionEvent event)”方法和“public void setViewPointCentered(CGPoint pos)”方法处理播放器和视图定位但我不认为它们正常工作。

我的一位朋友做了iOS编程并在他的iPhone上创建了应用程序并且它按预期工作,所以我想知道cocos2d的android端口是否有错误。

当我到达中间并继续在地图上向右或向上移动时,有没有人对角色为何不会在屏幕上保持居中有任何想法?

感谢您提供的任何输入。我一直在我的桌子上打了两天试图解决这个问题。

2 个答案:

答案 0 :(得分:1)

好的我明白了。

在这段代码中:

// Get TMX Map and associated layers/groups
_map = CCTMXTiledMap.tiledMap("TileMap.tmx");
_background = _map.layerNamed("Background");
_objects = _map.objectGroupNamed("Objects");

// Add my background layer
// TODO: Position layer in the correct spot.
addChild(_background);

我正在添加我的_background图层,但我真正想做的是添加我的_map:

// Get TMX Map and associated layers/groups
_map = CCTMXTiledMap.tiledMap("TileMap.tmx");
_background = _map.layerNamed("Background");
_objects = _map.objectGroupNamed("Objects");

// Add my background layer
// TODO: Position layer in the correct spot.
addChild(_map);

现在我的玩家角色在走动时仍然在我的可视屏幕的中心,除非我到达地图的边缘。

答案 1 :(得分:0)

每次触摸结束时,播放器都会按mapWidth或height移动。你应该用diff移动位置。尝试

CGPoint diff = CGPoint.ccpSub(touchLocation, playerPosition);

if (Math.abs(diff.x) > Math.abs(diff.y)) {
    if (diff.x > 0) {
        playerPosition.x += diff.x;
    } else {
        playerPosition.x -= diff.x;
    }
} else {
    if (diff.y > 0) {
        playerPosition.y += diff.y;
    } else {
        playerPosition.y -= diff.y;
    }
}