This is my second algorithm and I will try to make it as simple for you to understand how it works.
Visual picture of the valid points where the direction of collision is calculated at
It works by splitting a square into 4 sides and then by determining if an edge is within a side (which is a triangle). Then collision can respond by using collision direction as a tool to reduce velocity in the y axis or x.
class Collisions():
def Detect(me, ent):
me_Pos = Vector.Add(me.GetPos(), [me.GetVelocity()[0], -me.GetVelocity()[1]])
ent_pos = Vector.Add(ent.GetPos(), [ent.GetVelocity()[0], -ent.GetVelocity()[1]])
y_max, y_min, x_max, x_min = me_Pos[1] + (me.Entity.h * 0.5), me_Pos[1] - (me.Entity.h * 0.5), me_Pos[0] + (me.Entity.w * 0.5), me_Pos[0] - (me.Entity.w * 0.5)
y_max2, y_min2, x_min2, x_max2 = ent_pos[1] + (ent.Entity.h / 2), ent_pos[1] - (ent.Entity.h / 2), ent_pos[0] - (ent.Entity.w/2), ent_pos[0] + (ent.Entity.w/2)
isColliding = ((x_max >= x_min2 and x_max <= x_max2) or (x_min <= x_max2 and x_min >= x_min2)) and ((y_min <= y_max2 and y_min >= y_min) or (y_max <= y_max2 and y_max >= y_min2))
y_range = Math.Clamp((abs(me_Pos[0] - ent_pos[0])) / (0.5 * ent.Entity.w) * ent.Entity.h, 0, ent.Entity.h) * 0.5
y_range_2 = (y_range*0.5)
left = (x_max >= x_min2 and x_max <= ent_pos[0]) and ((y_min <= ent_pos[1]+y_range and y_min >= ent_pos[1]-y_range) or (y_max <= ent_pos[1]+y_range and y_max >= ent_pos[1]-y_range))
right = (x_min <= x_max2 and x_min >= ent_pos[0]) and ((y_min <= ent_pos[1]+y_range and y_min >= ent_pos[1]-y_range) or (y_max <= ent_pos[1]+y_range and y_max >= ent_pos[1]-y_range))
top = ((x_max >= x_min2 and x_max <= x_max2) or (x_min <= x_max2 and x_min >= x_min2)) and ((y_min <= y_max2 and y_min >= ent_pos[1] + y_range_2) or (y_max <= y_max2 and y_max >= ent_pos[1] + y_range_2))
bottom = ((x_max >= x_min2 and x_max <= x_max2) or (x_min <= x_max2 and x_min >= x_min2)) and ((y_max >= y_min2 and y_max <= ent_pos[1] - y_range_2) or (y_min >= y_min2 and y_min <= ent_pos[1] - y_range_2))
Collisions.Response(me, ent, [isColliding, left, right, top, bottom])
return isColliding, left, right, top, bottom
def Response(me, ent, physdata):
isColliding, left, right, top, bottom = physdata[0], physdata[1], physdata[2], physdata[3], physdata[4]
if left == True:
me.SetVelocity([me.GetVelocity()[0] * -0.2, me.GetVelocity()[1]])
if right == True:
me.SetVelocity([me.GetVelocity()[0] * -0.2, me.GetVelocity()[1]])
if top == True:
me.SetVelocity([me.GetVelocity()[0], me.GetVelocity()[1] * -0.2])
if bottom == True:
me.SetVelocity([me.GetVelocity()[0], me.GetVelocity()[1] * -0.2])
me_Pos = me.GetPos()
ent_Pos = ent.GetPos()
y_max, y_min, x_max, x_min = me_Pos[1] + (me.Entity.h * 0.5), me_Pos[1] - (me.Entity.h * 0.5), me_Pos[0] + (me.Entity.w * 0.5), me_Pos[0] - (me.Entity.w * 0.5)
for x in [x_max, x_min]:
for y in [y_max, y_min]:
colliding, byDistance = util.isInSphere([x,y], ent.GetPos(), ent.Entity.w * 0.5 )
if colliding:
me.Entity.move_ip(Vector.Multiply(Vector.Normalize(Vector.Sub(me.GetRealPos(),ent.GetRealPos())), 1+byDistance))
Collisions.Stuck_Response(me, ent)
def Stuck_Response(me,ent):
if Vector.Distance(me.GetRealPos(), ent.GetRealPos()) < me.Entity.w * 0.7:
me.Entity.move_ip(random.randint(1,2), random.randint(1,2))
me.Entity.move_ip(Vector.Sub(me.GetRealPos(), ent.GetRealPos()))
def Translate(table):
for k, v in enumerate(table):
for k2, v2 in enumerate(table):
ent_one = table[k]
ent_two = table[k2]
if ent_one != ent_two:
Collisions.Detect(ent_one, ent_two)