Collision detection - LearnOpenGL
文章推薦指數: 80 %
Because the ball is a circle-like object, an AABB is probably not the best choice for the ball's collision shape. The collision code thinks the ball is a ...
Ifyou'rerunningAdBlock,pleaseconsiderwhitelistingthissiteifyou'dliketosupportLearnOpenGL;andnoworries,Iwon'tbemadifyoudon't:)
IntroductionGettingstartedOpenGLCreatingawindowHelloWindowHelloTriangleShadersTexturesTransformationsCoordinateSystemsCameraReviewLightingColorsBasicLightingMaterialsLightingmapsLightcastersMultiplelightsReviewModelLoadingAssimpMeshModelAdvancedOpenGLDepthtestingStenciltestingBlendingFacecullingFramebuffersCubemapsAdvancedDataAdvancedGLSLGeometryShaderInstancingAntiAliasingAdvancedLightingAdvancedLightingGammaCorrectionShadowsShadowMappingPointShadowsNormalMappingParallaxMappingHDRBloomDeferredShadingSSAOPBRTheoryLightingIBLDiffuseirradianceSpecularIBLInPracticeDebuggingTextRendering2DGameBreakoutSettingupRenderingSpritesLevelsCollisionsBallCollisiondetectionCollisionresolutionParticlesPostprocessingPowerupsAudioRendertextFinalthoughtsGuestArticlesHowtopublish2020OITIntroductionWeightedBlendedSkeletalAnimation2021CSMSceneSceneGraphFrustumCullingTessellationHeightmapTessellationDSA2022ComputeShadersIntroductionPhys.BasedBloomCoderepositoryTranslationsAbout
BTC
1CLGKgmBSuYJ1nnvDGAepVTKNNDpUjfpRa
ETH/ERC20
0x1de59bd9e52521a46309474f8372531533bd7c43
Collisiondetection
In-Practice/2D-Game/Collisions/Collision-detection
Whentryingtodetermineifacollisionoccursbetweentwoobjects,wegenerallydonotusethevertexdataoftheobjectsthemselvessincetheseobjectsoftenhavecomplicatedshapes;thisinturnmakesthecollisiondetectioncomplicated.Forthisreason,itisacommonpracticetousemoresimpleshapes(thatusuallyhaveanicemathematicaldefinition)forcollisiondetectionthatweoverlayontopoftheoriginalobject.Wethencheckforcollisionsbasedonthesesimpleshapes;thismakesthecodeeasierandsavesalotofperformance.Afewexamplesofsuchcollisionshapesarecircles,spheres,rectangles,andboxes;thesearealotsimplertoworkwithcomparedtoarbitrarymesheswithhundredsoftriangles.
Whilethesimpleshapesdogiveuseasierandmoreefficientcollisiondetectionalgorithms,theyshareacommondisadvantageinthattheseshapesusuallydonotfullysurroundtheobject.Theeffectisthatacollisionmaybedetectedthatdidn'treallycollidewiththeactualobject;oneshouldalwayskeepinmindthattheseshapesarejustapproximationsoftherealshapes.
AABB-AABBcollisions
AABBstandsforaxis-alignedboundingbox,arectangularcollisionshapealignedtothebaseaxesofthescene,whichin2Dalignstothexandyaxis.Beingaxis-alignedmeanstherectangularboxhasnorotationanditsedgesareparalleltothebaseaxesofthescene(e.g.leftandrightedgeareparalleltotheyaxis).Thefactthattheseboxesarealwaysalignedtotheaxesofthescenemakescalculationseasier.HerewesurroundtheballobjectwithanAABB:
AlmostalltheobjectsinBreakoutarerectangularbasedobjects,soitmakesperfectsensetouseaxisalignedboundingboxesfordetectingcollisions.Thisisexactlywhatwe'regoingtodo.
Axisalignedboundingboxescanbedefinedinseveralways.OneofthemistodefineanAABBbyatop-leftandabottom-rightposition.TheGameObjectclassthatwedefinedalreadycontainsatop-leftposition(itsPositionvector),andwecaneasilycalculateitsbottom-rightpositionbyaddingitssizetothetop-leftpositionvector(Position+Size).Effectively,eachGameObjectcontainsanAABBthatwecanuseforcollisions.
Sohowdowecheckforcollisions?Acollisionoccurswhentwocollisionshapesentereachother'sregionse.g.theshapethatdeterminesthefirstobjectisinsomewayinsidetheshapeofthesecondobject.ForAABBsthisisquiteeasytodetermineduetothefactthatthey'realignedtothescene'saxes:wecheckforeachaxisifthetwoobject'edgesonthataxisoverlap.Sowecheckifthehorizontaledgesoverlap,andiftheverticaledgesoverlapofbothobjects.Ifboththehorizontalandverticaledgesoverlapwehaveacollision.
Translatingthisconcepttocodeisrelativelystraightforward.Wecheckforoverlaponbothaxesandifso,returnacollision:
boolCheckCollision(GameObject&one,GameObject&two)//AABB-AABBcollision
{
//collisionx-axis?
boolcollisionX=one.Position.x+one.Size.x>=two.Position.x&&
two.Position.x+two.Size.x>=one.Position.x;
//collisiony-axis?
boolcollisionY=one.Position.y+one.Size.y>=two.Position.y&&
two.Position.y+two.Size.y>=one.Position.y;
//collisiononlyifonbothaxes
returncollisionX&&collisionY;
}
Wecheckiftherightsideofthefirstobjectisgreaterthantheleftsideofthesecondobjectandifthesecondobject'srightsideisgreaterthanthefirstobject'sleftside;similarlyfortheverticalaxis.Ifyouhavetroublevisualizingthis,trytodrawtheedges/rectanglesonpaperanddeterminethisforyourself.
TokeepthecollisioncodeabitmoreorganizedweaddanextrafunctiontotheGameclass:
classGame
{
public:
[...]
voidDoCollisions();
};
WithinDoCollisions,wecheckforcollisionsbetweentheballobjectandeachbrickofthelevel.Ifwedetectacollision,wesetthebrick'sDestroyedpropertytotrue,whichinstantlystopsthelevelfromrenderingthisbrick:
voidGame::DoCollisions()
{
for(GameObject&box:this->Levels[this->Level].Bricks)
{
if(!box.Destroyed)
{
if(CheckCollision(*Ball,box))
{
if(!box.IsSolid)
box.Destroyed=true;
}
}
}
}
Thenwealsoneedtoupdatethegame'sUpdatefunction:
voidGame::Update(floatdt)
{
//updateobjects
Ball->Move(dt,this->Width);
//checkforcollisions
this->DoCollisions();
}
Ifwerunthecodenow,theballshoulddetectcollisionswitheachofthebricksandifthebrickisnotsolid,thebrickisdestroyed.Ifyourunthegamenowit'lllooksomethinglikethis:
Whilethecollisiondetectiondoeswork,it'snotveryprecisesincetheball'srectangularcollisionshapecollideswithmostofthebrickswithouttheballdirectlytouchingthem.Let'sseeifwecanfigureoutamoreprecisecollisiondetectiontechnique.
AABB-Circlecollisiondetection
Becausetheballisacircle-likeobject,anAABBisprobablynotthebestchoicefortheball'scollisionshape.Thecollisioncodethinkstheballisarectangularbox,sotheballoftencollideswithabrickeventhoughtheballspriteitselfisn'tyettouchingthebrick.
ItmakesmuchmoresensetorepresenttheballwithacirclecollisionshapeinsteadofanAABB.ForthisreasonweincludedaRadiusvariablewithintheballobject.Todefineacirclecollisionshape,allweneedisapositionvectorandaradius.
ThisdoesmeanwehavetoupdatethedetectionalgorithmsinceitcurrentlyonlyworksbetweentwoAABBs.Detectingcollisionsbetweenacircleandarectangleisabitmorecomplicated,butthetrickisasfollows:wefindthepointontheAABBthatisclosesttothecircle,andifthedistancefromthecircletothispointislessthanitsradius,wehaveacollision.
Thedifficultpartisgettingthisclosestpoint\(\color{red}{\bar{P}}\)ontheAABB.ThefollowingimageshowshowwecancalculatethispointforanyarbitraryAABBandcircle:
Wefirstneedtogetthedifferencevectorbetweentheball'scenter\(\color{blue}{\bar{C}}\)andtheAABB'scenter\(\color{green}{\bar{B}}\)toobtain\(\color{purple}{\bar{D}}\).Whatwethenneedtodoisclampthisvector\(\color{purple}{\bar{D}}\)totheAABB'shalf-extents\(\color{orange}{{w}}\)and\(\color{teal}{\bar{h}}\)andadditto\(\color{green}{\bar{B}}\).Thehalf-extentsofarectanglearethedistancesbetweentherectangle'scenteranditsedges:itssizedividedbytwo.ThisreturnsapositionvectorthatisalwayslocatedsomewhereattheedgeoftheAABB(unlessthecircle'scenterisinsidetheAABB).
Aclampoperationclampsavaluetoavaluewithinagivenrange.Thisisoftenexpressedas:
floatclamp(floatvalue,floatmin,floatmax){
returnstd::max(min,std::min(max,value));
}
Forexample,avalueof42.0fisclampedto6.0fwitharangeof3.0fto6.0f,andavalueof4.20fwouldbeclampedto4.20f.
Clampinga2Dvectormeansweclampbothitsxanditsycomponentwithinthegivenrange.
Thisclampedvector\(\color{red}{\bar{P}}\)isthentheclosestpointfromtheAABBtothecircle.Whatwethenneedtodoiscalculateanewdifferencevector\(\color{purple}{\bar{D'}}\)thatisthedifferencebetweenthecircle'scenter\(\color{blue}{\bar{C}}\)andthevector\(\color{red}{\bar{P}}\).
Nowthatwehavethevector\(\color{purple}{\bar{D'}}\),wecancompareitslengthtotheradiusofthecircle.Ifthelengthof\(\color{purple}{\bar{D'}}\)islessthanthecircle'sradius,wehaveacollision.
Thisisallexpressedincodeasfollows:
boolCheckCollision(BallObject&one,GameObject&two)//AABB-Circlecollision
{
//getcenterpointcirclefirst
glm::vec2center(one.Position+one.Radius);
//calculateAABBinfo(center,half-extents)
glm::vec2aabb_half_extents(two.Size.x/2.0f,two.Size.y/2.0f);
glm::vec2aabb_center(
two.Position.x+aabb_half_extents.x,
two.Position.y+aabb_half_extents.y
);
//getdifferencevectorbetweenbothcenters
glm::vec2difference=center-aabb_center;
glm::vec2clamped=glm::clamp(difference,-aabb_half_extents,aabb_half_extents);
//addclampedvaluetoAABB_centerandwegetthevalueofboxclosesttocircle
glm::vec2closest=aabb_center+clamped;
//retrievevectorbetweencentercircleandclosestpointAABBandcheckiflength<=radius
difference=closest-center;
returnglm::length(difference)
延伸文章資訊
- 1A Primer on AABB Collision Resolution - Deen Games
AABB (Axis Aligned Bounding Boxes) means two non-rotated boxes, that are aligned on one axis. · C...
- 22D collision detection - Game development - MDN Web Docs
One of the simpler forms of collision detection is between two rectangles that are axis aligned —...
- 3AABB Collision Detection Tutorial - TutorialEdge.net
AABB Collision Detection or "Axis-Aligned Bounding Box" Collision detection as it stands for is t...
- 4Using Swept AABB to detect and process collision
AABB stands for Axis-Aligned Bounding Box, it is an algorithm to detect collision between a recta...
- 5Simple AABB vs AABB collision detection - Studio Freya
What is AABB? An AABB is an axis aligned bounding box. AABB vs AABB is a box vs box or bounding b...