def createEdges(): lst = list() for tabw in slmap.walls: x = tabw[0] * CELL_SIZE y = tabw[1] * CELL_SIZE typ = tabw[2] * CELL_SIZE p1 = Vector(persoX, persoY) p2 = Vector(x + CELL_SIZE/2, y + CELL_SIZE/2) distToChar = p1.distance(p2) if distToChar > SIGHT_RANGE: continue view = p2 - p1 edges = list() for i in xrange(0,4): if i == 0 and typ not in [2,3,4,7,8,9,11,15]: p1 = Vector(x, y) # DOWN p2 = Vector(x+CELL_SIZE, y) elif i == 1 and typ not in [1,3,5,7,8,10,11,14]: p1 = Vector(x+CELL_SIZE, y) # RIGHT p2 = Vector(x+CELL_SIZE, y+CELL_SIZE) elif i == 2 and typ not in [2,5,6,7,9,10,11,13]: p1 = Vector(x+CELL_SIZE, y+CELL_SIZE) # UP p2 = Vector(x, y+CELL_SIZE) elif i == 3 and typ not in [1,4,6,8,9,10,11,12]: p1 = Vector(x, y+CELL_SIZE) # LEFT p2 = Vector(x, y) dire = p2 - p1 norm = Vector(-dire[1], dire[0]) if norm.dot(view) > 0: edge = Edge(p1, p2, distToChar) lst.append(edge) return lst
class Circle: def __init__(self, pos, radius): self.pos = Vector(*pos) self.r = radius def get_bbox(self): return self.pos.x - self.r, self.pos.y - self.r, self.pos.x + self.r, self.pos.y + self.r def get_y_at(self, x): # solution of y^2 - 2 * self.pos.y * y + self.pos.y^2 + (x - self.pos.x)^2 - self.r^2 = 0 # quadratic equation a = 1 b = -2 * self.pos.y c = self.pos.y**2 + (x - self.pos.x)**2 - self.r**2 has_sol, s1, s2 = self.solve_quadratic(a, b, c) if not has_sol: return False, 0, 0 return True, s1, s2 def collide_point(self, point): return self.pos.distance(point) <= self.r def collide_line(self, v1, v2): # based on https://stackoverflow.com/questions/40970478/python-3-5-2-distance-from-a-point-to-a-line x_diff = v2.x - v1.x y_diff = v2.y - v1.y num = abs(y_diff * self.pos.x - x_diff * self.pos.y + v2.x * v1.y - v2.y * v1.x) den = v2.distance(v1) return (num / den) <= self.r def collide_line_segment(self, v1, v2): if self.collide_point(v1) or self.collide_point(v2): return True # based on https://codereview.stackexchange.com/questions/86421/line-segment-to-circle-collision-algorithm # rewrite the segment as v1 + t*dir dir = v2 - v1 # at^2 + bt + c a = dir.dot(dir) b = 2 * dir.dot(v1 - self.pos) c = v1.dot(v1) + self.pos.dot( self.pos) - 2 * v1.dot(self.pos) - self.r**2 has_sol, t1, t2 = self.solve_quadratic(a, b, c) if not has_sol: return False return 0 <= t1 <= 1 or 0 <= t2 <= 1 def collide_rect(self, rectangle): # any rectangle vertex inside the circle (either whole rectangle inside or side collision) for vertex in rectangle.get_vertexes(): if self.collide_point(vertex): return True # all rect vertexes outside, try side collision for side in rectangle.get_sides(): if self.collide_line_segment(side[0], side[1]): return True @staticmethod def solve_quadratic(a, b, c): disc = b**2 - 4 * a * c if disc < 0: return False, 0, 0 sqrt_disc = math.sqrt(disc) t1 = (-b + sqrt_disc) / (2 * a) t2 = (-b - sqrt_disc) / (2 * a) return True, t1, t2