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++) {
108 const static hitCheck hitCheckFuncTbl[3] = {
113 _hitCheck[0][0] = hitCheckFuncTbl[dScStage_c::m_loopType];
149 float _unused = (1.0f / 256.f);
150 if (
mShape == CC_SHAPE_CIRCLE) {
181 if ((c1->
mInfo & CC_NO_HIT) || (c2->
mInfo & CC_NO_HIT)) {
195 u32 catInteract1 = collInfo1.
mVsKind;
196 u32 catMask1 = 1 << collInfo1.
mKind;
199 u32 catInteract2 = collInfo2.
mVsKind;
200 u32 catMask2 = 1 << collInfo2.
mKind;
205 if ((catInteract1 & catMask2) && (catInteract2 & catMask1)) {
207 u32 attInteract1 = collInfo1.mVsDamage;
208 u32 attCatMask1 = 1 << collInfo1.
mAttack;
209 u32 attInteract2 = collInfo2.mVsDamage;
210 u32 attCatMask2 = 1 << collInfo2.
mAttack;
214 (catInteract1 & catMask2 & BIT_FLAG(CC_KIND_PLAYER_ATTACK))
216 && (attCatMask2 & attInteract1) == 0
219 (catInteract2 & catMask1 & BIT_FLAG(CC_KIND_PLAYER_ATTACK))
221 && (attCatMask1 & attInteract2) == 0
233 if (!(collInfo2.
mStatus & CC_STATUS_NO_PASS_INFO)) {
235 if (attInteract1 & attCatMask2) {
238 if (attCatMask1 & attInteract2) {
239 c1->
mAttSent |= attInteract2 & attCatMask1;
242 if (!(collInfo1.
mStatus & CC_STATUS_NO_PASS_INFO)) {
244 if (attInteract1 & attCatMask2) {
245 c2->
mAttSent |= attInteract1 & attCatMask2;
247 if (attCatMask1 & attInteract2) {
253 if (!(collInfo2.
mStatus & CC_STATUS_NO_PASS_INFO) && collInfo1.
mCallback !=
nullptr) {
256 if (!(collInfo1.
mStatus & CC_STATUS_NO_PASS_INFO) && collInfo2.
mCallback !=
nullptr) {
265 for (
dCc_c *c1 =
mEntryN; c1 !=
nullptr; c1 = c1->mpNext) {
266 for (
dCc_c *c2 = c1->mpNext; c2 !=
nullptr; c2 = c2->mpNext) {
277 float xDist = pos1.x - pos2.x;
278 float collSizeX = ci1.
mBase.mSize.x + ci2.
mBase.mSize.x;
279 float yDist = pos1.y - pos2.y;
280 float collSizeY = ci1.
mBase.mSize.y + ci2.
mBase.mSize.y;
282 if (std::fabs(xDist) < collSizeX && std::fabs(yDist) < collSizeY) {
287 if ((ci1.
mStatus & CC_STATUS_NO_REVISION || ci2.
mStatus & CC_STATUS_NO_REVISION)
288 && ci1.
mKind != CC_KIND_GOAL_POLE && ci2.
mKind != CC_KIND_GOAL_POLE) {
295 float offsetX = (collSizeX - std::fabs(xDist)) / 2;
300 float offsetY = (collSizeY - std::fabs(yDist)) / 2;
335 p1.
incX(dBg_c::m_bg_p->mLoopOffset);
337 p2.
incX(dBg_c::m_bg_p->mLoopOffset);
354 float collSizeRadius = (collSizeX + collSizeY) / 2;
357 if (distVec.length() <= collSizeRadius) {
359 float dist = collSizeRadius - distVec.length();
363 float offsetX = dist * ang.
cos();
364 float offsetY = -dist * ang.
sin();
389#define DIR2SCALE(dir) (1.0f - dir * 2.0f)
392 dCc_c *boxCc, *circleCc;
394 if (c1->
mShape == CC_SHAPE_BOX) {
409 float closerEdgeX[] = {
413 float closerEdgeY[] = {
418 if (closerEdgeY[ABOVE] < circlePos.y && circlePos.y < closerEdgeY[BELOW]) {
420 float colliderXDist = DIR2SCALE(boxSideX) * (circlePos.x - closerEdgeX[boxSideX]);
421 if (colliderXDist < circleRadius) {
424 float circleOffsetX = DIR2SCALE(boxSideX) * (circleRadius - colliderXDist) / 2;
437 if (closerEdgeX[RIGHT] < circlePos.x && circlePos.x < closerEdgeX[LEFT]) {
439 float smthA = DIR2SCALE(boxSideY) * (circlePos.y - closerEdgeY[boxSideY]);
440 if (smthA < circleRadius) {
444 float circleOffsetY = DIR2SCALE(boxSideY) * (circleRadius - smthA) / 2;
459 mVec2_c closerCorner(closerEdgeX[boxSideX], closerEdgeY[boxSideY]);
460 mVec2_c distVec = circlePos - closerCorner;
461 float distance = distVec.normalise();
462 if (distance < circleRadius) {
463 float offsetBy = (circleRadius - distance) / 2;
479enum LINE_CHECK_RESULT_e {
487inline float ratioX(
mVec2_c diff,
float v) {
488 return v * diff.y / diff.x;
491inline float ratioY(
mVec2_c diff,
float v) {
492 return v * diff.x / diff.y;
495int dCc_c::_lineCheckUD(
mVec2_c p1,
mVec2_c p2,
float x,
float y) {
496 if (p1.x > x || p2.x < x) {
500 float scaled = ratioX(p2 - p1, x - p1.x);
501 if (scaled + p1.y < y) {
521 if (std::fabs(trpCenter.x - boxCenter.x) >= collSizeX) {
535 if (trpCorner1.y < boxBottom && trpCorner3.y < boxBottom) {
538 if (trpCorner2.y > boxTop && trpCorner4.y > boxTop) {
542 if (!(boxLeft <= trpCorner1.x) || !(trpCorner3.x <= boxRight)) {
543 if (_lineCheckUD(trpCorner1, trpCorner3, boxLeft, boxBottom) != THREE
544 && _lineCheckUD(trpCorner1, trpCorner3, boxRight, boxBottom) != THREE) {
548 if (_lineCheckUD(trpCorner2, trpCorner4, boxLeft, boxTop) != TWO
549 && _lineCheckUD(trpCorner2, trpCorner4, boxRight, boxTop) != TWO) {
567int dCc_c::_lineCheckLR(
mVec2_c p1,
mVec2_c p2,
float x,
float y) {
568 if (p1.y < y || p2.y > y) {
572 float scaled = ratioY(p1 - p2, y - p2.y);
573 if (scaled + p2.x < x) {
593 if (std::fabs(p1.y - p2.y) >= heightSum) {
607 if (trpCorner1.x > boxRight && trpCorner3.x > boxRight) {
610 if (trpCorner2.x < boxLeft && trpCorner4.x < boxLeft) {
614 if (!(boxBottom <= trpCorner3.y) || !(trpCorner1.y <= boxTop)) {
615 if (_lineCheckLR(trpCorner1, trpCorner3, boxRight, boxTop) != ZERO
616 && _lineCheckLR(trpCorner1, trpCorner3, boxRight, boxBottom) != ZERO) {
620 if (_lineCheckLR(trpCorner2, trpCorner4, boxLeft, boxTop) != ONE
621 && _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.
void entry()
Places this collider in the collider list.
u16 mCollidedWith
The categories of the previously collided with colliders.
float mCollOffsetY[CC_KIND_COUNT]
The Y offset for a collision.
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 mCollOffsetX[CC_KIND_COUNT]
The X offset for a collision.
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.
void release()
Removes this collider from the collider list.
sCcDatNewF mCcData
The collision data of this collider.
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.
dActor_c * mpFriendActor
A second actor that this collider will not collide with.
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 one-dimensional short angle vector.
float cos() const
Computes the cosine of the angle.
float sin() const
Computes the sine of the angle.
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.
sCcDatNew mBase
Base collider data.
u16 mStatus
Status flags for this collider. See CC_STATUS_FLAG_e.
u32 mVsKind
Which attack types this collider should be able to receive. This is a bitfield with the bits enumerat...