cocos2d-android (версия для github) Как сохранить спрайт игрока в центре экрана при перемещении фонового слоя? - PullRequest
1 голос
/ 29 февраля 2012

Я в процессе изучения cocos2d-android. Я следовал учебному пособию, которое портировало некоторые учебники Рэя Вендерлиха по iOS на Android. Я закончил первые уроки и хотел продолжить, преобразовав следующий урок Рэя Вендерлиха в Android самостоятельно в качестве упражнения для обучения.

Оригинальное руководство по iOS можно найти здесь http: // www raywenderlich com / 1163 / Как сделать игру на основе плитки с 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 чуть левее и ниже от центра экрана .

Проблема возникает, когда я начинаю двигаться вверх или вправо. Пройдя через центр экрана, я ожидаю, что спрайт игрока останется в центре экрана, а фон продолжит двигаться в противоположном направлении. Однако и игрок, и фон перемещаются, поэтому в конечном итоге мой игрок подходит к правому или верхнему краю экрана, и я больше не могу двигаться вверх или вправо, даже если осталось много карт.

Обратите внимание на игрока в левом верхнем углу карты.

Игрок достигает верхней части экрана и не остается в центре, как ожидалось

Обратите внимание на игрока в правом нижнем углу карты.

Игрок достигает правой части экрана и не остается в центре, как ожидалось

Метод "public boolean ccTouchesEnded (MotionEvent)" и метод "public void setViewPointCentered (CGPoint pos)" управляют игроком и позиционированием вида, но я не думаю, что они работают правильно.

Мой друг занимается программированием iOS и создал приложение на своем iPhone, и оно работает, как и ожидалось, поэтому мне интересно, есть ли ошибка в порте android cocos2d.

У кого-нибудь есть идеи о том, почему персонаж не будет оставаться в центре экрана, когда я доберусь до середины и продолжу двигаться вправо или вверх по карте?

Спасибо за любой вклад, который вы можете предоставить. Я два дня бился головой о стол, пытаясь понять это.

Ответы [ 2 ]

1 голос
/ 02 марта 2012

ОК, я понял это.

В этом фрагменте кода:

// 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);

Теперь мой персонаж игрока остается в центре моего видимого экрана во время хождения по кругу, пока я не доберусь до края карты.

0 голосов
/ 29 февраля 2012

Каждый раз, когда касание заканчивается, игрок перемещается на карту ширины или высоты. Вы должны переместить позицию с помощью различий. Попробуйте

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;
    }
}
...