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
Beispiel #2
0
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