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

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

本文关键字:Cocos2dx c++ Android 碰撞 角色 子弹 之间 敌人      更新时间:2023-10-16

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

症状:

当一个敌人角色生成并且我用我的子弹射击它时,敌人角色被正常摧毁。但是,如果出现了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);
}

现在我的敌人角色类:

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中,然后在我的更新方法中遍历它们。我想我的问题只针对我的需求,所以这可能对任何人都没有帮助。