[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [pygame] detecting reflection angle



alex wrote:
I have a moving dot and a bunch of  static walls which this dot collides
into. each wall is being represented as a line segment with its starting and
ending positions

can someone provide some code or pseudo-code solution for this problem?
awhile ago i wrote some code playing around with this. i've attached a simple but optimized module for dealing with line segments and circle collisions. the last function in the module is 'calcreflect'.

note, apon 'rereading' my calcreflect code, it appears i modified it so it only reflects vectors coming towards the plane normal. hence the funny "if" case. so it does not do 2-sided collisions against a segment. shouldn't be too hard to reenable the 2-sided collisions if thats what you need.

also, apon 'rereading' the normalize and length functions. i'm using sqrt(dot(vec,vec)) for length. this does not seem correct to me? i'd doublecheck that actually works. ?

btw, the "vectors" you use for this file are just Numeric.array objects with 3 float values.
#various vector and line functions, requires Numeric
from Numeric import *



class Segment:  
    "line segment"
    def __init__(self, pt1, pt2):
        self.pt1 = array(pt1, Float)
        self.pt2 = array(pt2, Float)
        self.dir = normalize(self.pt2 - self.pt1)
        self.dirlength = veclength(self.pt1 - self.pt2)
        self.dirlength2 = self.dirlength ** 2
        self.norm = normalize(array((self.dir[1],-self.dir[0])))
        self.dist = -dot(self.norm, pt1)

    def closest_point(self, pt):
        "closest point on segment to point"
        segpt = self.pt1
        t = dot(self.dir, pt - self.pt1)
        if t < 0.0: return self.pt1
        if t > self.dirlength: return self.pt2
        return self.pt1 + self.dir * t

    def closest_point_on_line(self, pt):
        "closest point on segment to point, pt must be on line"
        t = dot(self.dir, pt - self.pt1)
        if t < 0.0: return self.pt1
        if t > self.dirlength: return self.pt2
        return pt

    def pt_line_dist(self, pt):
        "distance from segment's line to point"
        return dot(self.norm, pt) + self.dist

    def ray_to_line(self, ray_pt, ray_norm):
        "distance from ray to segment's line"
        numer = dot(self.norm, ray_pt) + self.dist
        denom = dot(self.norm, ray_norm)
        if not denom: return 100000.0
        return -(numer / denom)



def normalize(vec):
    "return a vector with length 1"
    return vec / sqrt(dot(vec, vec))


def veclength(vec):
    "return the length of the vector"
    return sqrt(dot(vec,vec))


def pt_line_dist(line_pt, line_norm, pt):
    "distance from pt to line" #Segment has a faster one, since "d" is precalced
    line_d = -dot(line_norm, line_pt)
    return dot(line_norm, pt) + line_d


def ray_to_circle(ray_pt, ray_vec, circle_pt, radius):
    "distance from ray to circle, vec must be normalized"
    Q = circle_pt - ray_pt
    c = dot(Q, Q)  #length squared
    v = dot(Q, ray_vec)
    d = radius**2 - (c - v**2)
    if d < 0.0: return 10000.0
    return v - sqrt(d)


#unused for now
def my_dot(a, b): #just to remember, use Numeric's faster dot()
    return a[0]*b[0] + a[1]*b[1]


#unused for now
def calcreflect(velocity, planenorm): #velocity must be normalized
    component = dot(velocity, planenorm)
    if(component < 0.0):
        localnorm = planenorm
        component = -component
    else:
        localnorm = planenorm

    normproj = (localnorm * component) * 2.0
    return normalize(velocity + normproj)