Сделал проверку на нулевую длину для связей:

Код AS3:
package gerich.verlet
{
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main extends Sprite{
private var pt:Array = new Array();
private var joints:Array = new Array();
private var particles:Sprite = new Sprite();
private var canvas:Shape = new Shape();
private var grav:Number = 500;
private var timeSqr:Number;
// ========================================================== //
public function Main():void{
stage.frameRate = 40;
timeSqr=1/stage.frameRate;timeSqr*=timeSqr;
addChild(canvas);
addChild(particles);
pt.push(new Particle(270,150,true));
for (var j:int=0;j<30;j++)
{
pt.push(new Particle(270,150));
joints.push(new RangeJoint(pt[j], pt[j+1], 8, 20));
}
for (var i in pt){
particles.addChild(pt[i]);
}
addEventListener(Event.ENTER_FRAME, checkJoints);
addEventListener(Event.ENTER_FRAME, ptMouse);
}
// ========================================================== //
private function checkJoints(event:Event):void{
var dx:Number;
var dy:Number;
canvas.graphics.clear();
// Gravity
for (var i in pt){
dx = (pt[i].xx - pt[i].old_x);
dy = (pt[i].yy - pt[i].old_y);
pt[i].old_x = pt[i].xx;
pt[i].old_y = pt[i].yy;
pt[i].xx += dx;
pt[i].yy += (dy+grav*timeSqr);
}
// Joints
for (var z:int=0; z<30; z++){
for (var i in joints){
joints[i].Apply();
}
for (var i in pt){
pt[i].xx=Math.max(pt[i].xx,0);
pt[i].xx=Math.min(pt[i].xx,stage.stageWidth);
pt[i].yy=Math.max(pt[i].yy,0);
pt[i].yy=Math.min(pt[i].yy,stage.stageHeight);
}
}
for (var i in pt){
pt[i].x = pt[i].xx;
pt[i].y = pt[i].yy;
}
// Lines
for (var i in joints){
joints[i].Draw(canvas);
}
}
// ========================================================== //
private function ptMouse(event:Event):void{
for (var i in pt){
if(pt[i].isMouse){
pt[i].x=mouseX;
pt[i].y=mouseY;
pt[i].xx=mouseX;
pt[i].yy=mouseY;
}
}
canvas.graphics.clear();
// Lines
for (var i in joints){
joints[i].Draw(canvas);
}
}
}
}
// ***** [ Particle Class ] ***************************************** //
import flash.display.Sprite;
internal class Particle extends Sprite{
public var old_x:Number;
public var old_y:Number;
public var xx:Number;
public var yy:Number;
public var isMouse:Boolean;
// ========================================================== //
public function Particle(_x:int, _y:int, _isMouse:Boolean=false):void{
x = _x;
y = _y;
xx = _x;
yy = _y;
old_x = _x;
old_y = _y;
isMouse=_isMouse;
graphics.lineStyle(1, 0x000000);
graphics.beginFill(0xFFD22B);
graphics.drawCircle(0,0,5);
graphics.endFill();
}
// ========================================================== //
}
import flash.display.Shape;
internal class Joint{
public var p1:Particle;
public var p2:Particle;
public var len:Number;
// ========================================================== //
public function Joint(_p1:Particle, _p2:Particle, _len:Number):void{
p1=_p1;
p2=_p2;
len=_len;
}
// ========================================================== //
public function Draw(canvas:Shape):void{
canvas.graphics.lineStyle(1,0x000000);
canvas.graphics.moveTo(p1.x, p1.y);
canvas.graphics.lineTo(p2.x, p2.y);
}
// ========================================================== //
public function Apply():void{
var dx:Number;
var dy:Number;
var d_len:Number;
var diff:Number;
dx = p2.xx-p1.xx;
dy = p2.yy-p1.yy;
d_len = Math.sqrt(dx*dx + dy*dy);
if(d_len==0){
dx=Math.random();
dy=Math.random();
d_len = Math.sqrt(dx*dx + dy*dy);
}
diff = (d_len-len)/d_len;
dx *= 0.5*diff;
dy *= 0.5*diff;
if(!p2.isMouse){
p2.xx -= dx;
p2.yy -= dy;
}
if(!p1.isMouse){
p1.xx += dx;
p1.yy += dy;
}
}
// ========================================================== //
}
internal class WeakJoint extends Joint
{
// ========================================================== //
public function WeakJoint(_p1:Particle, _p2:Particle, _len:Number):void{
super(_p1,_p2,_len);
}
// ========================================================== //
override public function Apply():void{
var dx:Number;
var dy:Number;
var d_len:Number;
var diff:Number;
dx = p2.xx-p1.xx;
dy = p2.yy-p1.yy;
d_len = Math.sqrt(dx*dx + dy*dy);
if(d_len==0){
dx=Math.random();
dy=Math.random();
d_len = Math.sqrt(dx*dx + dy*dy);
}
if(d_len>len){
diff = (d_len-len)/d_len;
dx *= diff;
dy *= diff;
if(!p2.isMouse){
p2.xx -= dx;
p2.yy -= dy;
}
if(!p1.isMouse){
p1.xx += dx;
p1.yy += dy;
}
}
}
// ========================================================== //
}
internal class RangeJoint extends Joint
{
public var lenmax:Number;
public var lenmin:Number;
// ========================================================== //
public function RangeJoint(_p1:Particle, _p2:Particle, _lenmin:Number, _lenmax:Number):void
{
lenmax=_lenmax;
lenmin=_lenmin;
super(_p1,_p2,_lenmax);
}
// ========================================================== //
override public function Apply():void
{
var dx:Number;
var dy:Number;
var d_len:Number;
var diff:Number;
dx = p2.xx-p1.xx;
dy = p2.yy-p1.yy;
d_len = Math.sqrt(dx*dx + dy*dy);
if(d_len==0){
dx=Math.random();
dy=Math.random();
d_len = Math.sqrt(dx*dx + dy*dy);
}
if((d_len>lenmax)||(d_len<lenmin)){
if(d_len>lenmax)
diff = (d_len-lenmax)/d_len;
if(d_len<lenmin)
diff = (d_len-lenmin)/d_len;
dx *= diff;
dy *= diff;
if(!p2.isMouse){
p2.xx -= dx;
p2.yy -= dy;
}
if(!p1.isMouse){
p1.xx += dx;
p1.yy += dy;
}
}
}
// ========================================================== //
}
Добавлено через 12 часов 1 минуту
Вопрос ко всем, а как реализовать трение о поверхность(границы нашего квадрата). Как я понимаю, если частица "проникла" в другой объект, то надо добавить силу трения, направленную в противоположную сторону скорости.. но как это сделать? Есть ли у кого хорошие статейки по теме?