Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F621465
CollisionSystem.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
10 KB
Referenced Files
None
Subscribers
None
CollisionSystem.cpp
View Options
//
// Created by Ido Mozes on 11/07/2019.
//
#include
"CollisionSystem.h"
inline
float
getLeft
(
EntityP
&
entity
)
{
return
entity
->
getComponent
<
Position
>
()
->
value
.
X
-
entity
->
getComponent
<
Range
>
()
->
value
;
}
int
binarySearch
(
Entities
&
layer
,
float
left
,
int
low
,
int
high
)
{
if
(
high
<=
low
)
return
left
>
getLeft
(
layer
[
low
])
?
(
low
+
1
)
:
low
;
int
mid
=
(
low
+
high
)
/
2
;
if
(
left
==
getLeft
(
layer
[
mid
]))
return
mid
+
1
;
if
(
left
>
getLeft
(
layer
[
mid
]))
return
binarySearch
(
layer
,
left
,
mid
+
1
,
high
);
return
binarySearch
(
layer
,
left
,
low
,
mid
-
1
);
}
int
binarySearch
(
std
::
vector
<
std
::
tuple
<
EntityP
,
EntityP
,
float
>>
collided
,
float
distance
,
int
low
,
int
high
)
{
if
(
high
<=
low
)
return
distance
>
std
::
get
<
2
>
(
collided
[
low
])
?
(
low
+
1
)
:
low
;
int
mid
=
(
low
+
high
)
/
2
;
if
(
distance
==
std
::
get
<
2
>
(
collided
[
mid
]))
return
mid
+
1
;
if
(
distance
>
std
::
get
<
2
>
(
collided
[
mid
]))
return
binarySearch
(
collided
,
distance
,
mid
+
1
,
high
);
return
binarySearch
(
collided
,
distance
,
low
,
mid
-
1
);
}
void
insertionSort
(
Entities
&
layer
)
{
// can be optimized with binary search instead of comparison to every item
for
(
int
i
=
1
,
j
=
0
;
i
<
layer
.
size
();
j
=
i
++
)
{
auto
&
entity
=
layer
[
i
];
EntityP
entityP
(
entity
);
auto
&
previousEntity
=
layer
[
i
-
1
];
auto
[
position
,
range
]
=
entity
->
getComponents
<
Position
,
Range
>
().
value
();
float
entityLeft
=
position
.
value
.
X
-
range
.
value
;
if
(
entityLeft
>=
getLeft
(
layer
[
j
]))
continue
;
int
loc
=
binarySearch
(
layer
,
entityLeft
,
0
,
j
);
while
(
j
>=
loc
)
{
layer
[
j
+
1
]
=
layer
[
j
];
--
j
;
}
if
(
j
!=
i
-
1
)
{
layer
[
j
+
1
]
=
entityP
;
}
}
}
void
CollisionSystem::update
(
Entities
*
layers
,
GameData
&
gameData
)
{
if
(
!
gameData
.
levelRunning
)
return
;
Entities
&
bloonsLayer
=
layers
[
BLOONS_LAYER
];
Entities
&
shotsLayer
=
layers
[
SHOTS_LAYER
];
insertionSort
(
bloonsLayer
);
insertionSort
(
shotsLayer
);
std
::
vector
<
std
::
tuple
<
EntityP
,
EntityP
,
float
>>
collided
;
int
bloonIndex
=
0
;
for
(
auto
&
shot
:
shotsLayer
)
{
switch
(
shot
->
getComponent
<
Kind
>
()
->
value
)
{
case
GOO_SPLASH
:
case
BOMB_EXPLOSION
:
case
MISSILE_EXPLOSION
:
case
ENHANCED_BOMB_EXPLOSION
:
case
MOAB_MAULER_EXPLOSION
:
case
MOAB_ASSASSIN_EXPLOSION
:
case
MOAB_ELIMINATOR_EXPLOSION
:
shot
->
addComponent
<
RemoveEntityEvent
>
();
break
;
}
int
collidedIndex
=
collided
.
size
();
auto
[
shotPosition
,
poppedBloons
]
=
shot
->
getComponents
<
Position
,
PoppedBloons
>
().
value
();
auto
[
shotX
,
shotY
]
=
shotPosition
.
value
;
auto
shotRange
=
shot
->
getComponent
<
Range
>
()
->
value
;
float
shotLeft
=
shotX
-
shotRange
;
float
shotRight
=
shotX
+
shotRange
;
float
shotTop
=
shotY
-
shotRange
;
float
shotBottom
=
shotY
+
shotRange
;
for
(
int
i
=
bloonIndex
;
i
<
bloonsLayer
.
size
();
++
i
)
{
auto
&
bloon
=
bloonsLayer
[
i
];
auto
bloonPosition
=
bloon
->
getComponent
<
Position
>
()
->
value
;
auto
[
bloonX
,
bloonY
]
=
bloonPosition
;
auto
bloonRange
=
bloon
->
getComponent
<
Range
>
()
->
value
;
float
bloonLeft
=
bloonX
-
bloonRange
;
float
bloonRight
=
bloonX
+
bloonRange
;
float
bloonTop
=
bloonY
-
bloonRange
;
float
bloonBottom
=
bloonY
+
bloonRange
;
if
(
bloonRight
<
shotLeft
)
{
bloonIndex
++
;
continue
;
}
if
(
shotRight
<
bloonLeft
)
break
;
if
(
shotBottom
>=
bloonTop
and
shotTop
<=
bloonBottom
and
!
poppedBloons
.
value
.
count
(
bloon
.
get
()))
{
poppedBloons
.
value
.
emplace
(
bloon
.
get
());
float
distance
=
twoPointsDistance
(
shotPosition
.
value
,
bloonPosition
);
if
(
collidedIndex
==
collided
.
size
())
collided
.
emplace_back
(
shot
,
bloon
,
distance
);
else
{
int
index
=
binarySearch
(
collided
,
distance
,
collidedIndex
,
collided
.
size
()
-
1
);
if
(
index
<
collided
.
size
())
collided
.
emplace
(
collided
.
begin
()
+
index
,
shot
,
bloon
,
distance
);
else
collided
.
emplace_back
(
shot
,
bloon
,
distance
);
}
}
}
}
for
(
auto
[
shot
,
bloon
,
_
]
:
collided
)
{
auto
[
pierce
,
damage
,
kind
,
position
]
=
shot
->
getComponents
<
Pierce
,
Damage
,
Kind
,
Position
>
().
value
();
if
(
bloon
->
getComponent
<
Camo
>
()
and
!
shot
->
getComponent
<
Camo
>
())
continue
;
int
bloonKind
=
bloon
->
getComponent
<
Kind
>
()
->
value
;
if
(
pierce
.
value
>
0
)
{
switch
(
kind
.
value
)
{
case
LASER
:
if
(
bloonKind
!=
PURPLE_BLOON
and
bloonKind
!=
LEAD_BLOON
)
bloon
->
addComponent
<
DamageEvent
>
(
damage
.
value
,
shot
);
break
;
case
PLASMA
:
if
(
bloonKind
!=
PURPLE_BLOON
)
bloon
->
addComponent
<
DamageEvent
>
(
damage
.
value
,
shot
);
break
;
case
SUN
:
case
HOT_TACK
:
case
ENHANCED_TACK
:
bloon
->
addComponent
<
DamageEvent
>
(
damage
.
value
,
shot
);
break
;
case
DART
:
case
TACK
:
case
BLADE
:
case
SPIKE
:
if
(
bloonKind
!=
LEAD_BLOON
)
bloon
->
addComponent
<
DamageEvent
>
(
damage
.
value
,
shot
);
break
;
case
JUGGERNAUT
:
bloon
->
addComponent
<
DamageEvent
>
(
bloonKind
==
CERAMIC_BLOON
?
5
:
damage
.
value
,
shot
);
break
;
case
BOMB_EXPLOSION
:
case
MISSILE_EXPLOSION
:
case
ENHANCED_BOMB_EXPLOSION
:
case
MOAB_MAULER_EXPLOSION
:
case
MOAB_ASSASSIN_EXPLOSION
:
case
MOAB_ELIMINATOR_EXPLOSION
:
{
bool
breakFlag
=
false
;
switch
(
kind
.
value
)
{
case
BOMB_EXPLOSION
:
case
MISSILE_EXPLOSION
:
case
MOAB_MAULER_EXPLOSION
:
if
(
bloonKind
==
BLACK_BLOON
or
bloonKind
==
ZEBRA_BLOON
)
breakFlag
=
true
;
break
;
}
if
(
breakFlag
)
break
;
auto
shotGooP
=
shot
->
getComponent
<
Goo
>
();
if
(
shotGooP
and
(
bloonKind
<
MOAB
or
shot
->
getComponent
<
MoabClassAffecting
>
()))
bloon
->
addComponent
<
Goo
>
(
STUN
,
bloonKind
<
MOAB
?
shotGooP
->
ttl
:
45
,
0
,
true
);
int
_damage
=
damage
.
value
;
if
(
bloonKind
>=
MOAB
)
switch
(
kind
.
value
)
{
case
MOAB_MAULER_EXPLOSION
:
_damage
+=
15
;
break
;
case
MOAB_ASSASSIN_EXPLOSION
:
_damage
+=
20
;
break
;
case
MOAB_ELIMINATOR_EXPLOSION
:
_damage
+=
80
;
break
;
}
if
(
bloonKind
==
CERAMIC_BLOON
)
switch
(
kind
.
value
)
{
case
MOAB_ASSASSIN_EXPLOSION
:
case
MOAB_ELIMINATOR_EXPLOSION
:
_damage
=
24
;
break
;
}
bloon
->
addComponent
<
DamageEvent
>
(
_damage
,
shot
);
break
;
}
case
GOO_SPLASH
:
{
bloon
->
addComponent
<
DamageEvent
>
(
damage
.
value
,
shot
);
if
(
bloonKind
<
MOAB
and
!
bloon
->
getComponent
<
Goo
>
())
{
bloon
->
addComponent
<
Goo
>
(
*
shot
->
getComponent
<
Goo
>
());
auto
[
texture
,
surface
]
=
gameData
.
getTexture
(
getSurfaceName
(
bloon
));
auto
&
visibility
=
*
bloon
->
getComponent
<
Visibility
>
();
visibility
.
setDstRect
(
SDL_Rect
{
0
,
0
,
surface
->
w
/
3
,
0
});
visibility
.
reloadTexture
(
texture
,
surface
);
}
break
;
}
case
BOMB
:
case
ENHANCED_BOMB
:
case
MISSILE
:
case
MOAB_MAULER
:
case
MOAB_ASSASSIN
:
case
MOAB_ELIMINATOR
:
case
GOO_SHOT
:
if
(
shot
->
getComponent
<
RemoveEntityEvent
>
())
break
;
EntityP
explosion
(
new
Entity
());
explosion
->
addComponent
<
Position
>
(
position
.
value
.
X
,
position
.
value
.
Y
);
explosion
->
addComponent
<
Type
>
(
SHOT_T
);
switch
(
kind
.
value
)
{
case
BOMB
:
case
ENHANCED_BOMB
:
case
MISSILE
:
case
MOAB_MAULER
:
case
MOAB_ASSASSIN
:
case
MOAB_ELIMINATOR
:
explosion
->
addComponent
<
Kind
>
(
kind
.
value
+
1
);
if
(
auto
shotGooP
=
shot
->
getComponent
<
Goo
>
())
explosion
->
addComponent
<
Goo
>
(
*
shotGooP
);
break
;
case
GOO_SHOT
:
explosion
->
addComponent
<
Kind
>
(
GOO_SPLASH
);
explosion
->
addComponent
<
Goo
>
(
*
shot
->
getComponent
<
Goo
>
());
break
;
}
if
(
shot
->
getComponent
<
MoabClassAffecting
>
())
explosion
->
addComponent
<
MoabClassAffecting
>
();
explosion
->
addComponent
<
Pierce
>
(
pierce
);
explosion
->
addComponent
<
PoppedBloons
>
();
explosion
->
addComponent
<
Range
>
(
shot
->
getComponent
<
Spread
>
()
->
value
);
explosion
->
addComponents
(
damage
);
auto
[
texture
,
surface
]
=
gameData
.
getTexture
(
getSurfaceName
(
explosion
));
explosion
->
addComponent
<
Visibility
>
(
texture
,
surface
,
SDL_Rect
{
0
,
0
,
surface
->
w
/
2
});
layers
[
SHOTS_LAYER
].
emplace_back
(
explosion
);
shot
->
addComponent
<
RemoveEntityEvent
>
();
break
;
}
if
(
--
pierce
.
value
==
0
)
shot
->
addComponent
<
RemoveEntityEvent
>
();
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Sat, Nov 14, 7:09 PM (19 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
132445
Default Alt Text
CollisionSystem.cpp (10 KB)
Attached To
Mode
R74 BloonsTD
Attached
Detach File
Event Timeline