Verlet Triangle
/**
* Copyright fakestar0826 ( http://wonderfl.net/user/fakestar0826 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/sQYh
*/
// forked from fakestar0826's Verlet Method
package {
import flash.geom.Rectangle;
import flash.events.Event;
import flash.display.StageScaleMode;
import flash.display.StageAlign;
import flash.display.Sprite;
public class FlashTest extends Sprite {
private var _pointA:VerletPoint;
private var _pointB:VerletPoint;
private var _pointC:VerletPoint;
private var _stickA:VerletStick;
private var _stickB:VerletStick;
private var _stickC:VerletStick;
private var _stageRect:Rectangle;
public function FlashTest() {
// write as3 code here..
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
_stageRect = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
_pointA = new VerletPoint(100, 100);
_pointB = new VerletPoint(200, 100);
_pointC = new VerletPoint(150, 200);
_stickA = new VerletStick(_pointA, _pointB);
_stickB = new VerletStick(_pointB, _pointC);
_stickC = new VerletStick(_pointC, _pointA);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(e:Event):void
{
_pointA.y += 0.5;
_pointA.update();
_pointB.y += 0.5;
_pointB.update();
_pointC.y += 0.5;
_pointC.update();
//繰り返しを増やすと剛体に近づく。stickのupdateメソッドにより、点同士の斥力?が働くため
for(var i:int = 0;i < 1;i++)
{
_pointA.constrain(_stageRect);
_pointB.constrain(_stageRect);
_pointC.constrain(_stageRect);
_stickA.update();
_stickB.update();
_stickC.update();
}
graphics.clear();
_pointA.render(graphics);
_pointB.render(graphics);
_pointC.render(graphics);
_stickA.render(graphics);
_stickB.render(graphics);
_stickC.render(graphics);
}
}
}
import flash.display.Graphics;
import flash.geom.Rectangle;
class VerletPoint
{
public var x:Number;
public var y:Number;
private var _oldX:Number;
private var _oldY:Number;
public function VerletPoint(x:Number, y:Number)
{
setPosition(x, y);
}
public function update():void
{
var tempX:Number = x;
var tempY:Number = y;
x += vx;
y += vy;
_oldX = tempX;
_oldY = tempY;
}
public function setPosition(x:Number, y:Number):void
{
this.x = _oldX = x;
this.y = _oldY = y;
}
public function constrain(rect:Rectangle):void
{
x = Math.max(rect.left, Math.min(rect.right, x));
y = Math.max(rect.top, Math.min(rect.bottom, y));
}
public function set vx(value:Number):void
{
_oldX = x - value;
}
public function get vx():Number
{
return x - _oldX;
}
public function set vy(value:Number):void
{
_oldY = y - value;
}
public function get vy():Number
{
return y - _oldY;
}
public function render(g:Graphics):void
{
g.beginFill(0);
g.drawCircle(x, y, 4);
g.endFill();
}
}
class VerletStick
{
private var _pointA:VerletPoint;
private var _pointB:VerletPoint;
private var _length:Number;
public function VerletStick(pointA:VerletPoint, pointB:VerletPoint, length:Number = -1)
{
_pointA = pointA;
_pointB = pointB;
if(length == -1)
{
var dx:Number = _pointA.x - _pointB.x;
var dy:Number = _pointA.y - _pointB.y;
_length = Math.sqrt(dx * dx + dy * dy);
}
else
{
_length = length;
}
}
public function update():void
{
var dx:Number = _pointB.x - _pointA.x;
var dy:Number = _pointB.y - _pointA.y;
var dist:Number = Math.sqrt(dx * dx + dy * dy);
var diff:Number = _length - dist;
var offsetX:Number = (diff * dx / dist)/* it means diff * cos(θ)*/ / 2;
var offsetY:Number = (diff * dy / dist)/* it means diff * sin(θ)*/ / 2;
_pointA.x -= offsetX;
_pointA.y -= offsetY;
_pointB.x += offsetX;
_pointB.y += offsetY;
}
public function render(g:Graphics):void
{
g.lineStyle(0);
g.moveTo(_pointA.x, _pointA.y);
g.lineTo(_pointB.x, _pointB.y);
}
}