Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fat callback functions for the Physics Contact event #4

Open
Roout opened this issue Sep 1, 2020 · 1 comment
Open

Fat callback functions for the Physics Contact event #4

Roout opened this issue Sep 1, 2020 · 1 comment
Labels
architecture References to design and structure of the application enhancement New feature or request

Comments

@Roout
Copy link
Owner

Roout commented Sep 1, 2020

bool OnContactBegin(cocos2d::PhysicsContact& contact) {
enum { BODY_A, BODY_B };
cocos2d::PhysicsShape * const shapes[2] = {
contact.getShapeA(),
contact.getShapeB()
};
cocos2d::PhysicsBody * const bodies[2] = {
shapes[BODY_A]->getBody(),
shapes[BODY_B]->getBody()
};
cocos2d::Node * const nodes[2] = {
bodies[BODY_A]->getNode(),
bodies[BODY_B]->getNode()
};
if( !nodes[BODY_A] || !nodes[BODY_B] ) {
return false;
}
const bool isUnitSensor[2] = {
shapes[BODY_A]->getCategoryBitmask() == Utils::CreateMask(core::CategoryBits::GROUND_SENSOR),
shapes[BODY_B]->getCategoryBitmask() == Utils::CreateMask(core::CategoryBits::GROUND_SENSOR)
};
// There are nodes one of which is with unit sensor attached
// i.e. basicaly it's unit and other collidable body
if ( isUnitSensor[BODY_A] || isUnitSensor[BODY_B] ) {
Unit * unit { dynamic_cast<Unit*>(isUnitSensor[BODY_A]? nodes[BODY_A] : nodes[BODY_B]) };
unit->SetContactWithGround(true);
return true;
}
/// Platform & Unit
const int bodyMasks[2] = {
bodies[BODY_A]->getCategoryBitmask(),
bodies[BODY_B]->getCategoryBitmask()
};
const bool isPlatform[2] = {
bodyMasks[BODY_A] == Utils::CreateMask(core::CategoryBits::PLATFORM),
bodyMasks[BODY_B] == Utils::CreateMask(core::CategoryBits::PLATFORM)
};
if( isPlatform[BODY_A] || isPlatform[BODY_B] ) {
const auto platformIndex { isPlatform[BODY_A]? BODY_A: BODY_B };
const auto moveUpwards { helper::IsGreater(bodies[platformIndex ^ 1]->getVelocity().y, 0.f, 0.000001f) };
// Ordinates before collision:
const auto unitBottomOrdinate { nodes[platformIndex ^ 1]->getPosition().y };
const auto platformTopOrdinate {
nodes[platformIndex]->getPosition().y +
nodes[platformIndex]->getContentSize().height / 2.f
};
const auto canPassThrough { helper::IsLesser(unitBottomOrdinate, platformTopOrdinate, 0.00001f) };
return !(moveUpwards || canPassThrough);
}
/// Spikes & Unit
const bool isTrap[2] = {
bodyMasks[BODY_A] == Utils::CreateMask(core::CategoryBits::TRAP),
bodyMasks[BODY_B] == Utils::CreateMask(core::CategoryBits::TRAP)
};
if( isTrap[BODY_A] || isTrap[BODY_B] ) {
const auto trapIndex { isTrap[BODY_A]? BODY_A: BODY_B };
const auto unit { dynamic_cast<Unit*>(nodes[trapIndex^1]) };
const auto trap { dynamic_cast<Traps::Trap*>(nodes[trapIndex]) };
trap->CurseTarget(unit);
return false;
}
/// Projectile & (Unit or Barrel)
const bool isProjectile[2] = {
bodyMasks[BODY_A] == Utils::CreateMask(core::CategoryBits::PROJECTILE),
bodyMasks[BODY_B] == Utils::CreateMask(core::CategoryBits::PROJECTILE)
};
const auto unitMask { Utils::CreateMask(core::CategoryBits::HERO, core::CategoryBits::ENEMY) };
const bool isUnit[2] = {
(bodyMasks[BODY_A] & unitMask) > 0,
(bodyMasks[BODY_B] & unitMask) > 0
};
if( isProjectile[BODY_A] || isProjectile[BODY_B] ) {
const auto projectileIndex { isProjectile[BODY_A]? BODY_A: BODY_B };
const auto proj { dynamic_cast<Projectile*>(nodes[projectileIndex]) };
// damage target if possible
if(isUnit[projectileIndex ^ 1]) {
const auto unit { dynamic_cast<Unit*>(nodes[projectileIndex^1]) };
unit->AddCurse<Curses::CurseClass::INSTANT>(
Curses::CurseHub::ignored,
proj->GetDamage()
);
} else if( bodyMasks[projectileIndex ^ 1] == Utils::CreateMask(core::CategoryBits::BARREL)) {
const auto barrel { dynamic_cast<Barrel*>(nodes[projectileIndex^1]) };
barrel->Explode();
}
// destroy projectile
proj->Collapse();
// end contact, no need to process collision
return false;
}
return true;
}
bool OnContactSeparate(cocos2d::PhysicsContact& contact) {
enum { BODY_A, BODY_B };
cocos2d::PhysicsShape * const shapes[2] = {
contact.getShapeA(),
contact.getShapeB()
};
cocos2d::PhysicsBody * const bodies[2] = {
shapes[BODY_A]->getBody(),
shapes[BODY_B]->getBody()
};
cocos2d::Node * const nodes[2] = {
bodies[BODY_A]->getNode(),
bodies[BODY_B]->getNode()
};
if( !nodes[BODY_A] || !nodes[BODY_B] ) {
return false;
}
const int bodyMasks[2] = {
bodies[BODY_A]->getCategoryBitmask(),
bodies[BODY_B]->getCategoryBitmask()
};
bool isUnitSensor[2] = {
shapes[BODY_A]->getCategoryBitmask() == Utils::CreateMask(core::CategoryBits::GROUND_SENSOR),
shapes[BODY_B]->getCategoryBitmask() == Utils::CreateMask(core::CategoryBits::GROUND_SENSOR)
};
if (nodes[BODY_A] && nodes[BODY_B] && (isUnitSensor[BODY_A] || isUnitSensor[BODY_B]) ) {
Unit * heroView { dynamic_cast<Unit*>(isUnitSensor[BODY_A]? nodes[BODY_A] : nodes[BODY_B]) };
bool onGround {
isUnitSensor[BODY_A]?
helper::IsEquel(bodies[BODY_A]->getVelocity().y, 0.f, 0.000001f):
helper::IsEquel(bodies[BODY_B]->getVelocity().y, 0.f, 0.000001f)
};
heroView->SetContactWithGround(onGround);
return true;
}
// handle contact of spikes and unit
const bool isTrap[2] = {
bodyMasks[BODY_A] == Utils::CreateMask(core::CategoryBits::TRAP),
bodyMasks[BODY_B] == Utils::CreateMask(core::CategoryBits::TRAP)
};
if( isTrap[BODY_A] || isTrap[BODY_B] ) {
const auto trapIndex { isTrap[BODY_A]? BODY_A: BODY_B };
const auto unit { dynamic_cast<Unit*>(nodes[trapIndex^1]) };
const auto trap { dynamic_cast<Traps::Trap*>(nodes[trapIndex]) };
trap->RemoveCurse(unit);
return false;
}
return true;
}

Need to be breaked and divided between different application layers cuz it's obviously not responsibility of only the LevelScene

@Roout Roout added enhancement New feature or request architecture References to design and structure of the application labels Sep 1, 2020
@Roout Roout changed the title Overloaded callback functions Fat callback functions for the Physics Contact event Sep 1, 2020
@Roout
Copy link
Owner Author

Roout commented Sep 17, 2020

ANother problem with Fat contact function is the huge number of dynamic casts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
architecture References to design and structure of the application enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant