敌人角色和子弹射击之间的碰撞 - (Cocos2dx, C++, Android)

Collision between enemy characters and bullets shot - (Cocos2dx, C++, Android)

我的问题是我为敌人角色对象和子弹对象编写的碰撞检测。

符号:

当我用子弹射击 1 个敌方角色时,敌方角色会正常被摧毁。 但是,如果生成了 2 个或更多敌人角色并且我射击了第一个生成的敌人,它什么都不做。 最后一个被生成和射击的角色被毫无问题地摧毁。

我是如何修复它的:

我决定通过创建一个 int 变量给每个敌人角色一个唯一的 ID,并在每次生成敌人时随机化它。 这确保我每个敌人角色对象肯定会有一个唯一的标识符,这样如果我射击他们,我可以以某种方式将那个唯一的 ID 与我的子弹相匹配。

但是,我不知道如何解决这个问题。下面的代码只是删除与任何随机标签相关联的每个敌人角色

我的问题:

我如何设置我的子弹对象来保存我的敌人角色的每个唯一 ID,以便当子弹击中一个(无论具体顺序如何)时它会搜索然后将它具有的唯一 ID 与已击中敌方角色ID?

如果我的问题不清楚或者我的编码风格很糟糕,我们深表歉意。

GameScene.cpp

/**
 * @param ENEMY_SPAWN_FREQUENCY value is 0.002, set to make them spawn automatically every few seconds
 */
void GameScene::updateScheduler() {
    this -> scheduleUpdate();
    this -> schedule(schedule_selector(GameScene::spawnEnemyCharacter),      ENEMY_SPAWN_FREQUENCY * visibleSize.width);
}

// ...

bool GameScene::onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event) {

    // fire button
    auto target = (Sprite*)this -> getChildByTag(FIRE_BUTTON_TAG);
    Rect rect   = target        -> getBoundingBox();
    Point p     = touch         -> getLocation();

    // initialize bullets
    if (rect.containsPoint(p)) {
        GameScene::spawnBullets(PLAYER_TAG, playerCharacter->getPositionX(), playerCharacter->getPositionY()+100, 0, REFERENCE_SIZE_Y);
        return true;
    }

    // ...

    return false;
}

// ... somewhere below my GameScene.cpp class

void GameScene::spawnBullets(int shooter_id, int x, int y, int p_x, int p_y) {

    // load bullet sprites. 
    SpriteFrameCache::getInstance() -> addSpriteFramesWithFile("bullets.plist");

    // ... 

    auto bulletBody   = PhysicsBody::createBox(bullet_sprite -> getContentSize());
    bulletBody       -> setDynamic(true);
    bulletBody       -> setGravityEnable(false);
    bulletBody       -> setCollisionBitmask(BULLET_COLLISION_BITMASK);
    bulletBody       -> setContactTestBitmask(true);

    bullet_sprite    -> setPhysicsBody(bulletBody);
    bullet_sprite    -> setPosition(Point( x, y));
    bullet_sprite    -> setScale(0.2f);
    bullet_sprite    -> setTag(BULLET_TAG);
    this             -> addChild(bullet_sprite);

    // animate bullet object so that it shoots
    bullet_obj.fireBullet(bullet_sprite, p_x, p_y);
}

// ... somewhere further down this class i define my enemy characters to be spawned as enemy objects in the below method

void GameScene::spawnEnemyCharacter(float dt) {
    int random_tag = rand();        // ensure that each enemy character object has a unique random id as its tag
    enemyCharacter_obj.spawnEnemy(this, random_tag);
    enemy_tags.push_back(random_tag);

// ... destroy enemy characters if hit by bullet:

bool GameScene::onContactBegin( cocos2d::PhysicsContact &contact ) {
    PhysicsBody *a = contact.getShapeA() -> getBody();
    PhysicsBody *b = contact.getShapeB() -> getBody();

    if (BULLET_COLLISION_BITMASK == a->getCollisionBitmask() && ENEMY_COLLISION_BITMASK == b-> getCollisionBitmask() ||
        BULLET_COLLISION_BITMASK == b->getCollisionBitmask() && ENEMY_COLLISION_BITMASK == a-> getCollisionBitmask() ) {

        // delete enemys with random tag
        for (std::vector<int>::iterator itl = enemy_tags.begin(); itl != enemy_tags.end(); ++itl) {
            enemyCharacter_obj.destroyEnemyCharacter(this, *itl);
        }    
        this -> removeChild(bullet_sprite);
    }

    return true;
}

Bullet.cpp

void Bullet::fireBullet(Sprite* bullet_sprite, int x, int y) {
    auto bulletAction  = Sequence::create( MoveBy::create(BULLETSPEED, Point(x, y)), CallFuncN::create( CC_CALLBACK_1(Bullet::doRemoveFromParentAndCleanup, this, true)), NULL);
    bullet_sprite     -> runAction(bulletAction);
}

现在我的敌人角色class:

void EnemyCharacter::spawnEnemy(cocos2d::Layer* layer, int random_tag) {

    // データ読み込み
    SpriteFrameCache::getInstance() -> addSpriteFramesWithFile("enemies.plist");

    // 敵キャラクター
    enemyCharacter   = Sprite::createWithSpriteFrameName("enemy_1.png");
    auto enemyCharacterBody  = PhysicsBody::createBox(enemyCharacter -> getContentSize() / 5);

    // ...

    auto enemyCharacterPosition = (random * visibleSize.height ) + ( enemyCharacter -> getContentSize().height / 2);
    enemyCharacterBody         -> setDynamic(false);
    enemyCharacterBody         -> setCollisionBitmask(ENEMY_COLLISION_BITMASK);
    enemyCharacterBody         -> setContactTestBitmask(true);
    enemyCharacter             -> setScale(0.3f);
    enemyCharacter             -> setTag(random_tag);
    enemyCharacter             -> setPhysicsBody(enemyCharacterBody);
    enemyCharacter             -> setPosition( Point( ((random * visibleSize.width) + (enemyCharacter->getContentSize().width / 2)), visibleSize.height ) );
    layer                 -> addChild(enemyCharacter);

    // ...
}

// .. further down this class 

void EnemyCharacter::destroyEnemyCharacter(cocos2d::Layer* layer, int randomized_tag) {
    layer-> removeChild(layer -> getChildByTag(randomized_tag));
}

在我的案例中,我最终使用了 Box2D,将每个对象添加到 CCArray 中,然后在我的更新方法中遍历它们。我认为我的问题仅针对我的需求,因此这可能对任何人都没有用