1#include <game/bases/d_cc.hpp>
2#include <game/bases/d_actor.hpp>
3#include <game/bases/d_s_stage.hpp>
4#include <game/bases/d_bg.hpp>
5#include <game/sLib/s_GlobalData.hpp>
46 for (
unsigned int i = 0; i < ARRAY_SIZE(
mCollOffsetX); i++) {
94 mCcData.mSize = collInfo->mSize;
98 mCcData.mVsDamage = collInfo->mVsDamage;
105 set(actor, collInfo);
115 const static hitCheck hitCheckFuncTbl[3] = {
120 _hitCheck[0][0] = hitCheckFuncTbl[dScStage_c::m_loopType];
156 float _unused = (1.0f / 256.f);
157 if (
mShape == CC_SHAPE_CIRCLE) {
164 if (std::fabs(xDist) > std::fabs(
mCcData.mSize.x - other->
mCcData.mSize.x)) {
169 if (std::fabs(yDist) > std::fabs(
mCcData.mSize.y - other->
mCcData.mSize.y)) {
188 if ((c1->
mInfo & CC_NO_HIT) || (c2->
mInfo & CC_NO_HIT)) {
202 u32 catInteract1 = collInfo1.
mVsKind;
203 u32 catMask1 = 1 << collInfo1.
mKind;
206 u32 catInteract2 = collInfo2.
mVsKind;
207 u32 catMask2 = 1 << collInfo2.
mKind;
212 if ((catInteract1 & catMask2) && (catInteract2 & catMask1)) {
214 u32 attInteract1 = collInfo1.mVsDamage;
215 u32 attCatMask1 = 1 << collInfo1.
mAttack;
216 u32 attInteract2 = collInfo2.mVsDamage;
217 u32 attCatMask2 = 1 << collInfo2.
mAttack;
221 (catInteract1 & catMask2 & BIT_FLAG(CC_KIND_PLAYER_ATTACK))
223 && (attCatMask2 & attInteract1) == 0
226 (catInteract2 & catMask1 & BIT_FLAG(CC_KIND_PLAYER_ATTACK))
228 && (attCatMask1 & attInteract2) == 0
240 if (!(collInfo2.
mStatus & CC_STATUS_NO_PASS_INFO)) {
242 if (attInteract1 & attCatMask2) {
245 if (attCatMask1 & attInteract2) {
246 c1->
mAttSent |= attInteract2 & attCatMask1;
249 if (!(collInfo1.
mStatus & CC_STATUS_NO_PASS_INFO)) {
251 if (attInteract1 & attCatMask2) {
252 c2->
mAttSent |= attInteract1 & attCatMask2;
254 if (attCatMask1 & attInteract2) {
260 if (!(collInfo2.
mStatus & CC_STATUS_NO_PASS_INFO) && collInfo1.
mCallback !=
nullptr) {
263 if (!(collInfo1.
mStatus & CC_STATUS_NO_PASS_INFO) && collInfo2.
mCallback !=
nullptr) {
272 for (
dCc_c *c1 =
mEntryN; c1 !=
nullptr; c1 = c1->mpNext) {
273 for (
dCc_c *c2 = c1->mpNext; c2 !=
nullptr; c2 = c2->mpNext) {
284 float xDist = pos1.x - pos2.x;
285 float collSizeX = ci1.mSize.x + ci2.mSize.x;
286 float yDist = pos1.y - pos2.y;
287 float collSizeY = ci1.mSize.y + ci2.mSize.y;
289 if (std::fabs(xDist) < collSizeX && std::fabs(yDist) < collSizeY) {
294 if ((ci1.
mStatus & CC_STATUS_NO_REVISION || ci2.
mStatus & CC_STATUS_NO_REVISION)
295 && ci1.
mKind != CC_KIND_GOAL_POLE && ci2.
mKind != CC_KIND_GOAL_POLE) {
302 float offsetX = (collSizeX - std::fabs(xDist)) / 2;
307 float offsetY = (collSizeY - std::fabs(yDist)) / 2;
342 p1.
incX(dBg_c::m_bg_p->mLoopOffset);
344 p2.
incX(dBg_c::m_bg_p->mLoopOffset);
361 float collSizeRadius = (collSizeX + collSizeY) / 2;
364 if (distVec.length() <= collSizeRadius) {
366 float dist = collSizeRadius - distVec.length();
367 s16 ang =
cM::atan2s(distVec.y, std::fabs(distVec.x));
370 float offsetX = dist * nw4r::math::CosIdx(ang);
371 float offsetY = -dist * nw4r::math::SinIdx(ang);
396#define DIR2SCALE(dir) (1.0f - dir * 2.0f)
399 dCc_c *boxCc, *circleCc;
401 if (c1->
mShape == CC_SHAPE_BOX) {
412 float circleRadius = circleCc->
mCcData.mSize.x;
416 float closerEdgeX[] = {
420 float closerEdgeY[] = {
425 if (closerEdgeY[ABOVE] < circlePos.y && circlePos.y < closerEdgeY[BELOW]) {
427 float colliderXDist = DIR2SCALE(boxSideX) * (circlePos.x - closerEdgeX[boxSideX]);
428 if (colliderXDist < circleRadius) {
431 float circleOffsetX = DIR2SCALE(boxSideX) * (circleRadius - colliderXDist) / 2;
444 if (closerEdgeX[RIGHT] < circlePos.x && circlePos.x < closerEdgeX[LEFT]) {
446 float smthA = DIR2SCALE(boxSideY) * (circlePos.y - closerEdgeY[boxSideY]);
447 if (smthA < circleRadius) {
451 float circleOffsetY = DIR2SCALE(boxSideY) * (circleRadius - smthA) / 2;
466 mVec2_c closerCorner(closerEdgeX[boxSideX], closerEdgeY[boxSideY]);
467 mVec2_c distVec = circlePos - closerCorner;
468 float distance = distVec.normalise();
469 if (distance < circleRadius) {
470 float offsetBy = (circleRadius - distance) / 2;
486enum LINE_CHECK_RESULT_e {
494inline float ratioX(
mVec2_c diff,
float v) {
495 return v * diff.y / diff.x;
498inline float ratioY(
mVec2_c diff,
float v) {
499 return v * diff.x / diff.y;
502int dCc_c::_lineCheckUD(
mVec2_c p1,
mVec2_c p2,
float x,
float y) {
503 if (p1.x > x || p2.x < x) {
507 float scaled = ratioX(p2 - p1, x - p1.x);
508 if (scaled + p1.y < y) {
526 float collSizeX = ccTrp->
mCcData.mSize.x + ccBox->
mCcData.mSize.x;
528 if (std::fabs(trpCenter.x - boxCenter.x) >= collSizeX) {
542 if (trpCorner1.y < boxBottom && trpCorner3.y < boxBottom) {
545 if (trpCorner2.y > boxTop && trpCorner4.y > boxTop) {
549 if (!(boxLeft <= trpCorner1.x) || !(trpCorner3.x <= boxRight)) {
550 if (_lineCheckUD(trpCorner1, trpCorner3, boxLeft, boxBottom) != THREE
551 && _lineCheckUD(trpCorner1, trpCorner3, boxRight, boxBottom) != THREE) {
555 if (_lineCheckUD(trpCorner2, trpCorner4, boxLeft, boxTop) != TWO
556 && _lineCheckUD(trpCorner2, trpCorner4, boxRight, boxTop) != TWO) {
574int dCc_c::_lineCheckLR(
mVec2_c p1,
mVec2_c p2,
float x,
float y) {
575 if (p1.y < y || p2.y > y) {
579 float scaled = ratioY(p1 - p2, y - p2.y);
580 if (scaled + p2.x < x) {
598 float heightSum = ccTrp->
mCcData.mSize.y + ccBox->
mCcData.mSize.y;
600 if (std::fabs(p1.y - p2.y) >= heightSum) {
614 if (trpCorner1.x > boxRight && trpCorner3.x > boxRight) {
617 if (trpCorner2.x < boxLeft && trpCorner4.x < boxLeft) {
621 if (!(boxBottom <= trpCorner3.y) || !(trpCorner1.y <= boxTop)) {
622 if (_lineCheckLR(trpCorner1, trpCorner3, boxRight, boxTop) != ZERO
623 && _lineCheckLR(trpCorner1, trpCorner3, boxRight, boxBottom) != ZERO) {
627 if (_lineCheckLR(trpCorner2, trpCorner4, boxLeft, boxTop) != ONE
628 && _lineCheckLR(trpCorner2, trpCorner4, boxLeft, boxBottom) != ONE) {
The minimum required implementation for a stage actor.
Collider ("Collision Check") class - handles collisions between actors.
void set(dActor_c *actor, sCcDatNewF *collInfo)
Registers an owner actor to this collider and sets the collider data.
mVec2_c getCenterVec()
Gets the center of the collider as a vector.
static bool _hitCheckSquare(dCc_c *c1, dCc_c *c2, mVec2_c pos1, mVec2_c pos2)
A hit check function for rectangular colliders. Used in _hitCheckNormal and _hitCheckLoop.
bool mIsLinked
Whether this collider has been placed in the collider list.
static bool checkCollision(dCc_c *c1, dCc_c *c2, int active)
Checks for collisions between two colliders.
static bool _hitCheckDaikeiUD_R(dCc_c *ccBox, dCc_c *ccTrp)
Check a rectangular collider against a trapezoid-shaped collider for collisions.
dActor_c * mpOwner
The actor this collider belongs to.
float getUnderPos()
Gets the Y position of the bottom of the collider.
static bool _hitCheckLoop(dCc_c *c1, dCc_c *c2)
Check two rectangular colliders against each other for collisions with stage looping.
float getTopPos()
Gets the Y position of the top of the collider.
static dCc_c * mEntryN
The first collider in the list.
u16 isHitAtDmg(u16 mask) const
Gets the result of an attack hit check.
u8 mInfo
Info flags for this collider. See CC_INFO_e.
dCc_c * mpPrev
The previous collider in the list.
void clear()
Clear the data related to previous collisions.
float getCenterPosY()
Gets the Y position of the center of the collider.
float mCollOffsetY[8]
The Y offset for a collision.
void entry()
Places this collider in the collider list.
u16 mCollidedWith
The categories of the previously collided with colliders.
u8 mShape
The shape of the collider. See CC_SHAPE_e .
u16 mAttSent
The attack types sent by this collider in the previous collisions.
u16 isHit(u16 mask) const
Gets the result of a hit check.
static hitCheck _hitCheck[4][4]
The hit check function for each combination of collider shapes.
u16 mAttReceived
The attack types received by this collider in the previous collisions.
u8 mLayer
The layer this collider is on.
float getCenterPosX()
Gets the X position of the center of the collider.
static bool _hitCheckCircle(dCc_c *c1, dCc_c *c2)
Check two circle colliders against each other for collisions.
float getLeftPos()
Gets the X position of the left side of the collider.
mVec2_c mCollPos
The position where the last collision occurred.
float getRightPos()
Gets the X position of the right side of the collider.
static bool _hitCheckDaikeiLR_R(dCc_c *ccBox, dCc_c *ccTrp)
Check a rectangular collider against a trapezoid-shaped collider for collisions.
virtual ~dCc_c()
Destroys the collider.
static void execute()
Check all colliders against each other for collisions.
dActor_c * mFriendActor
A second actor that this collider will not collide with.
void release()
Removes this collider from the collider list.
sCcDatNewF mCcData
The collision data of this collider.
float mCollOffsetX[8]
The X offset for a collision.
static bool _hitCheckDaikeiLR(dCc_c *ccTrp, dCc_c *ccBox)
Check a trapezoid-shaped collider against a rectangular collider for collisions.
u8 mAmiLine
The non-collide mask for this collider.
static bool _hitCheckBoxCircle(dCc_c *c1, dCc_c *c2)
Check a rectangular and a circle collider against each other for collisions.
static void reset()
Clears the collider list.
dCc_c * mpNext
The next collider in the list.
dCc_c()
Constructs a new collider.
static dCc_c * mEntryB
The last collider in the list.
static bool _hitCheckNormal(dCc_c *c1, dCc_c *c2)
Check two rectangular colliders against each other for collisions without stage looping.
static bool _hitCheckDaikeiUD(dCc_c *ccTrp, dCc_c *ccBox)
Check a trapezoid-shaped collider against a rectangular collider for collisions.
bool isInside(dCc_c *other)
Checks if this collider is inside another collider.
A two-dimensional floating point vector.
void incX(float x)
Increments the X coordinate.
static const T::GlobalData_t mData
s16 atan2s(float sin, float cos)
Converts a sine and a cosine to an angle in units.
A structure that contains information about a collider.
void(* mCallback)(dCc_c *self, dCc_c *target)
The callback to execute when a collision occurs.
u8 mKind
The type of this collider. See CC_KIND_e.
u8 mAttack
The attack type of this collider. See CC_ATTACK_e.
u16 mStatus
Status flags for this collider. See CC_STATUS_FLAG_e.
mVec2_POD_c mOffset
The offset of the collider.
u32 mVsKind
Which attack types this collider should be able to receive. This is a bitfield with the bits enumerat...