[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)