バネを円状につないだ
ActionScript3.0アニメーション読んでます。
バネの勉強しなおしってことで。
1つのボールが両隣&向いのボールとバネで繋がれてます。
/**
* Copyright sakef ( http://wonderfl.net/user/sakef )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/q3Kp
*/
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.DropShadowFilter;
[SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="40")]
public class Main extends Sprite
{
private static const RADIUS:Number = 80;
private static const RADIUS_BALL:Number = 13;
private static const BALL_NUM:int = 8;
private var len_side:Number;
private var len_opp:Number;
private var balls:Vector.<Ball>;
private var drag_ball:int;
private var prev_mouseX:Number;
private var prev_mouseY:Number;
public function Main()
{
// 初期化
balls = new Vector.<Ball>(BALL_NUM, true);
for(var i:int=0, theta:Number=0 ; i<BALL_NUM ; i++, theta += 360/BALL_NUM)
{
balls[i] = addChild(new Ball(Math.cos(theta*Math.PI/180)*80 + 100, Math.sin(theta*Math.PI/180)*80 + 100, i, RADIUS_BALL)) as Ball;
balls[i].addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
balls[i].buttonMode = true;
}
// 隣接してるボールとの距離
len_side = Math.sqrt((balls[0].x - balls[1].x)*(balls[0].x - balls[1].x) + (balls[0].y - balls[1].y)*(balls[0].y - balls[1].y));
// 向かいのボールとの距離
len_opp = RADIUS * 2;
prev_mouseX = mouseX;
prev_mouseY = mouseY;
drag_ball = -1;
filters = [new DropShadowFilter(4,45,0x777777)];
addEventListener(Event.ENTER_FRAME, onFrame);
}
// マウスアップ時に実行する関数
private function onMouseUp(e:MouseEvent):void
{
balls[drag_ball].addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
stage.removeEventListener(MouseEvent.MOUSE_UP , onMouseUp);
drag_ball = -1;
}
// マウスダウン時に実行する関数
private function onMouseDown(e:MouseEvent):void
{
var ball:Ball = (e.target as Ball);
drag_ball = ball.id;
ball.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
stage.addEventListener(MouseEvent.MOUSE_UP , onMouseUp);
}
// 計算
private function onFrame(e:Event):void
{
var i:int, j:int;
graphics.clear();
graphics.lineStyle(6,0xFF0000);
graphics.beginFill(0xFFFF00,1);
// ドラッグ中のBallを計算
if(drag_ball != -1)
{
var d:Ball = balls[drag_ball];
d.dx = mouseX - prev_mouseX;
d.dy = mouseY - prev_mouseY;
d.x = mouseX;
d.y = mouseY;
}
prev_mouseX = mouseX;
prev_mouseY = mouseY;
// 向い同士のボールを使って座標計算
var half:int = BALL_NUM * 0.5;
for(i=0 ; i<half ; i++)
{
j = i+half;
if(i != drag_ball) moveBallSpring(balls[i], balls[j], len_opp);
if(j != drag_ball) moveBallSpring(balls[j], balls[i], len_opp);
}
//隣同士のボールを使って座標計算
var ball:Ball = balls[0];
var last:Ball = balls[BALL_NUM-1];
var startCx:Number=(ball.x + last.x) * 0.5;
var startCy:Number=(ball.y + last.y) * 0.5;
graphics.moveTo(startCx, startCy);
for(i=0 ; i<BALL_NUM ; i++)
{
j = (i+1)%BALL_NUM;
ball = balls[i];
var next:Ball=balls[j];
var cx:Number=(ball.x + next.x) * 0.5;
var cy:Number=(ball.y + next.y) * 0.5;
if(i < BALL_NUM-1) graphics.curveTo(ball.x, ball.y, cx, cy);
if(i != drag_ball) moveBallSpring(ball, next, len_side);
if(j != drag_ball) moveBallSpring(next, ball, len_side);
}
graphics.curveTo(last.x, last.y, startCx, startCy);
graphics.endFill();
// 壁とのあたり判定
for(i=0;i<BALL_NUM;i++)
{
ball = balls[i];
if(ball.id != drag_ball)
{
if(ball.x < RADIUS_BALL)
{
ball.x = RADIUS_BALL;
ball.dx *= -1;
}
if(ball.y < RADIUS_BALL)
{
ball.y = RADIUS_BALL;
ball.dy *= -1;
}
if(ball.x > stage.stageWidth-RADIUS_BALL)
{
ball.x = stage.stageWidth-RADIUS_BALL;
ball.dx *= -1;
}
if(ball.y > stage.stageHeight-RADIUS_BALL)
{
ball.y = stage.stageHeight-RADIUS_BALL;
ball.dy *= -1;
}
}
}
}
// ボールの位置を計算する (バネの動き)
private function moveBallSpring(ball:Ball, target:Ball, length:Number):void
{
var theta:Number = Math.atan2(target.y - ball.y, target.x - ball.x);
ball.dx += ((target.x - Math.cos(theta) * length) - ball.x) * 0.1;
ball.dy += ((target.y - Math.sin(theta) * length) - ball.y) * 0.1;
ball.x += ball.dx;
ball.y += ball.dy;
ball.dx *= 0.95;
ball.dy *= 0.95;
}
}
}
// ボールクラス
import flash.display.Sprite;
class Ball extends Sprite
{
public var dx:Number;
public var dy:Number;
public var id:int;
public function Ball(x:Number, y:Number, id:int, radius:Number)
{
this.x = x;
this.y = y;
this.id = id;
dx = dy = 0;
graphics.beginFill(0xffffff,1);
graphics.lineStyle(radius*0.5,0x00ff00);
graphics.drawCircle(0,0, radius);
graphics.endFill();
}
}