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

Posted on Updated on

Last weekend I got really stuck with something for a game I am building that had to do with collisions. The link is here on Stackoverflow:

http://stackoverflow.com/questions/31352254/collision-between-enemy-characters-and-bullets-shot-cocos2dx-c-android

Would greatly appreciate it if anybody has a few ideas on how I can work around this idea ..

————————-

My problem is the collision detection that i wrote for my enemy character objects and bullet objects.

The symtoms:
When 1 enemy character spawns and i shoot it with my bullets, the enemy character is destroyed as normal. But, if 2 or more enemy characters spawn and i shoot the first enemy that was spawned it does nothing. The last character that was spawned and shot is destroyed without issue.

How i tried to fix it:
I decided to give each enemy character a unique ID by creating an int variable and randomize it each time an enemy is spawned. This ensures me that each enemy character object will definately have a unique identifier so that if i shoot them, I can somehow match that unique ID with my bullet.

However, I dont know how to work around that. The code below just deletes every enemy character associated with any randomized tags

My question:
How can I set my bullet objects to hold every unique ID of my enemy characters, so that when the bullet hits one (doesn’t matter which specific order) it will search then compare the unique IDs it has to the enemy character ID it has shot?

Apologies if my question is unclear or if my coding style is horrible.

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

And now my enemy character 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));
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s