这是我的第二个算法,我会尽量让你理解它是如何工作的。
Visual picture of the valid points where the direction of collision is calculated at
它的工作原理是将一个正方形分成4个边,然后确定边是否在一边(这是一个三角形)。然后碰撞可以通过使用碰撞方向作为降低y轴或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)