Вот, собственно, вопрос, как бороться? Изза того, что синусы и косинусы считаются недостаточно точно, определение места коллизии тоже получается очень приблизительным.
Пример прилагается:

Код AS3:
package com.ayumilove.map
{
//{imports
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.Dictionary;
//}
/**
* Surface class.
* @author wvxvw
* @langVersion 3.0
* @playerVersion 10.0.12.36
*/
public class Surface
{
//--------------------------------------------------------------------------
//
// Public properties
//
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//
// Protected properties
//
//--------------------------------------------------------------------------
protected var _right:Point;
protected var _left:Point;
protected var _top:Point;
protected var _bottom:Point;
protected var _angle:Number;
protected var _cos:Number;
protected var _sin:Number;
protected var _tan:Number;
protected var _atan:Number;
protected var _acos:Number;
protected var _asin:Number;
protected var _lineRect:Rectangle;
//--------------------------------------------------------------------------
//
// Private properties
//
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
public function Surface(left:Point, right:Point)
{
super();
_left = left.clone();
_right = right.clone();
var tempTop:Number = Math.min(_right.y, _left.y);
var tempLeft:Number = Math.min(_right.x, _left.x);
var tempBottom:Number = Math.max(_right.y, _left.y);
var tempRight:Number = Math.max(_right.x, _left.x);
_top = new Point(tempLeft, tempTop);
_bottom = new Point(tempRight, tempBottom);
var x:Number = tempBottom - tempTop;
var y:Number = tempRight - tempLeft;
_angle = Math.atan2(x, y);
_cos = Math.cos(_angle);
_sin = Math.sin(_angle);
_tan = Math.tan(_angle);
_tan = Math.atan(_angle);
_acos = Math.acos(_angle);
_asin = Math.asin(_angle);
trace(_asin, _acos, _atan, _tan, _sin, _cos);
trace(_angle * 180 / Math.PI);
_lineRect = new Rectangle();
_lineRect.top = tempTop;
_lineRect.left = tempLeft;
_lineRect.bottom = tempBottom;
_lineRect.right = tempRight;
}
//--------------------------------------------------------------------------
//
// Public methods
//
//--------------------------------------------------------------------------
public function right():Point { return _right.clone(); }
public function left():Point { return _left.clone(); }
public function top():Point { return _top.clone(); }
public function bottom():Point { return _bottom.clone(); }
public function angle():Number { return _angle; }
public function lineRect():Rectangle { return _lineRect.clone(); }
public function intersects(rect:Rectangle):Boolean
{
if (!rect.intersects(_lineRect)) return false;
var cornerPoints:Dictionary = new Dictionary();
cornerPoints[new Point(rect.top, rect.left)] = 1;
cornerPoints[new Point(rect.top, rect.right)] = 2;
cornerPoints[new Point(rect.bottom, rect.left)] = 3;
cornerPoints[new Point(rect.bottom, rect.right)] = 4;
var lineTop:Point = top();
var h:Number;
var w:Number;
var d:Number;
var p:Point;
for (var po:Object in cornerPoints)
{
p = po as Point;
w = Math.max(lineTop.x, p.x) - Math.min(lineTop.x, p.x);
h = Math.max(lineTop.y, p.y) - Math.min(lineTop.y, p.y);
d = Math.sqrt(h * h + w * w);
p.x = lineTop.x + _cos * d;
p.y = lineTop.y + _sin * d;
if (rect.containsPoint(p)) return true;
}
return false;
}
public function collisionPoints(rect:Rectangle):Array
{
var topY:Number = Math.max(top().y, rect.top);
var bottomY:Number = Math.min(bottom().y, rect.bottom);
var d1:Number = (topY - top().y) / _sin;
var d2:Number = (bottomY - top().y) / _sin;
var topX:Number = top().x + d1 * _cos;
var bottomX:Number = top().x + d2 * _cos;
var p1:Point = new Point(topX, topY);
var p2:Point = new Point(bottomX, bottomY);
if (!rect.containsPoint(p1))
{
p1.x = rect.left;
d1 = (p1.x - top().x) / _cos;
p1.y = top().y + d1 * _sin;
}
var p2Clone:Point = p2.clone();
p2Clone.x = p2.x - 1;
p2Clone.y = p2.y - 1;
if (!rect.containsPoint(p2Clone))
{
p2.x = rect.right;
d1 = (p2.x - top().x) / _cos;
p2.y = top().y + d1 * _sin;
}
return [p1, p2];
}
//--------------------------------------------------------------------------
//
// Protected methods
//
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//
// Private methods
//
//--------------------------------------------------------------------------
}
}
EDIT: Упс, прошу прощения, неправильно посчитал
