Home > Archives > 2008-10-21
2008-10-21
グニャグニャするネットを作る
- 2008-10-21 (火)
- flash
以前作ったのの続き。
前回のは位置が固定されていて動かせなかったけど、どうにかして動かせるようにしました。
まだ未完ですが、勢いでUPします。
今回はパラメーターを弄れるようにスライダーを付けていて、左からfriction(摩擦 : 0.1~0.98)、spring(バネの係数 : 0.1~1)、_POWER_COEFFICIENT(各点にかかる力を求めるための定数。自分でやっといて良く理解していない : 5~300)です。
スライダーのソース、使い方は書籍『ActionScriptアニメーション』のものを使わせて貰いました。色だけ変えてあります。
Ballクラスにtensionってパラメーターを追加し、マウスとの距離によって変え、バネ運動の際にその値を反映させています。
以下は問題点。
- 未だにネット部分だけにあたり判定を付けるのが出来てない。
- なのでスライダーを弄ってもネットが動く。
- 前回も書いたけど、多分この方法は間違ってる気がする。ちゃんと点どうしが連結されていない。
- 各値をかなり低くすると、動作がおかしい点がある。
要改善。次は回転させようと思います。
んで、僕は何がやりたいのかと言うと、
The Magic Carpet — Manuel’s Coding Blogとか、THE ECO ZOO | ECODA!DOBUTSUENの引っ張れる旗みたいなのを作りたいのです。
といっても3Dにしたい訳ではなく、どういう風に座標を管理しているのか、等の仕組みが知りたい。
同じように、確かFlash8が出たあたり、fladdictさんがグネグネするコーラの缶のデモを作られていた。そこのURLはもう無い(ドメインが違う)し、はっきりとは覚えていないんだけど、テクスチャも貼られていた。そういったのを作りたいのです。
メインとなるソースだけ載せてみます。
package
{
import flash.display.Sprite;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import org.miniapp.customFigure.Ball;
[SWF(backgroundColor="0x000000", width="800", height="800", frameRate="60")]
public class Net extends Sprite
{
private static const _SPRING:Number = 0.5;
private static const _FRICTION:Number = 0.5;
private static const _COLUM:uint = 20
private static const _ROW:uint = 20;
private static const _NUM_BALLS:uint = _COLUM * _ROW;
private static const _DIFF_X:uint = 20;
private static const _DIFF_Y:uint = 20;
private static const _START_X:uint = 200;
private static const _START_Y:uint = 200;
private static const _BALL_RADIUS:uint = 4;
//TODO 名前も数値も適当。ちゃんとしたい。
private static const _POWER_COEFFICIENT:uint = 50;
/**
* コンストラクタ
*/
public function Net()
{
if (stage)
init();
else
addEventListener(Event.ADDED_TO_STAGE, init);
}
private var _mousePressX:Number;
private var _mousePressY:Number;
private var _isDragging:Boolean = false;
private var _lastMouseX:Number;
private var _lastMouseY:Number;
private var _balls:Array/* of Ball */
private var _horizontalBallArray:Array/* of Array */
private var _verticalBallsArray:Array/* of Array */
private var _frictionSlider:SimpleSlider;
private var _springSlider:SimpleSlider;
private var _powerCoefficientSlider:SimpleSlider;
private function init():void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.scaleMode = StageScaleMode.NO_SCALE;
_frictionSlider = new SimpleSlider(0.1, 0.98, _FRICTION);
_frictionSlider.x = 10;
_frictionSlider.y = 10;
addChild(_frictionSlider);
_springSlider = new SimpleSlider(0.1, 1, _SPRING);
_springSlider.x = 30;
_springSlider.y = 10;
addChild(_springSlider);
_powerCoefficientSlider = new SimpleSlider(5, 300, _POWER_COEFFICIENT);
_powerCoefficientSlider.x = 50;
_powerCoefficientSlider.y = 10;
addChild(_powerCoefficientSlider);
_balls = [];
//ボールを繋ぐ線を描くため、縦、横に分けて配列に入れて纏める。
//縦に並ぶボールを入れた配列をまとめる配列
_horizontalBallArray = [];
//横に並ぶボールを入れた配列をまとめる配列
_verticalBallsArray = [];
for (var i:uint = 0; i < _COLUM; i++)
{
//縦に並ぶボールを管理する配列を作る
var horizontalBalls:Array/* of Ball */ = [];
_horizontalBallArray.push(horizontalBalls);
}
//ボール生成、配置
for (i = 0; i < _ROW; i++)
{
//横に並ぶボールを管理する配列を作る
var verticalBalls:Array/* of Ball */ = [];
for (var j:uint = 0; j < _COLUM; j++)
{
var ball:Ball = new Ball(_BALL_RADIUS, 0xFFFFFF);
ball.x = ball.defaultX = _START_X + _DIFF_X * j;
ball.y = ball.defaultY = _START_Y + _DIFF_Y * i;
_balls.push(ball);
//縦に並ぶボールを入れる
(_horizontalBallArray[j] as Array).push(ball);
//横に並ぶボールを入れる
verticalBalls.push(ball);
//ball.cacheAsBitmap = true;
//addChild(ball);
}
_verticalBallsArray.push(verticalBalls);
}
drawLine();
stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
}
/**
* ボール同士を線で繋ぐ
*/
private function drawLine():void
{
graphics.clear();
graphics.lineStyle(1, 0xFFFFFF);
//縦のラインを引く
for (var i:uint = 0; i < _COLUM; i++)
{
var horizontalBalls:Array = _horizontalBallArray[i] as Array;
var firstBall:Ball = Ball(horizontalBalls[0]);
graphics.moveTo(firstBall.x, firstBall.y);
for (var j:uint = 1; j < _COLUM; j++)
{
var ball:Ball = Ball(horizontalBalls[j]);
graphics.lineTo(ball.x, ball.y);
}
}
//横のラインを引く
for (i = 0; i < _ROW; i++)
{
var verticalBalls:Array = _verticalBallsArray[i] as Array;
firstBall = Ball(verticalBalls[0]);
graphics.moveTo(firstBall.x, firstBall.y);
for (j = 1; j < _ROW; j++)
{
ball = Ball(verticalBalls[j]);
graphics.lineTo(ball.x, ball.y);
}
}
}
/**
* バネ運動させる
* @param ball バネ運動させるボール
* @param targetPoint 目標位置
*/
private function springTo(ball:Ball, targetX:Number, targetY:Number):void
{
ball.vx += (targetX - ball.x) * _springSlider.value * ball.tension;
ball.vy += (targetY - ball.y) * _springSlider.value * ball.tension;
ball.vx *= _frictionSlider.value;
ball.vy *= _frictionSlider.value;
ball.x += ball.vx;
ball.y += ball.vy;
}
private function enterFrameHandler(e:Event):void
{
if (_isDragging)
{
//マウスが移動した距離を調べる
var dxMouse:Number = mouseX - _lastMouseX;
var dyMouse:Number = mouseY - _lastMouseY;
}
for (var i:uint = 0; i < _NUM_BALLS; i++)
{
var ball:Ball = Ball(_balls[i]);
if (_isDragging)
{
//マウスが押された地点とボールの距離を調べる
var dx:Number = mouseX - ball.x;
var dy:Number = mouseY - ball.y;
var distance:Number = Math.sqrt(dx * dx + dy * dy);
//マウスとボールの位置からボールにかかる力を算出
//マウスから近いボールほど引っ張られる力が大きくなる
var tension:Number = _powerCoefficientSlider.value / ( _powerCoefficientSlider.value + distance);
ball.tension = tension;
//目的地を算出
var toX:Number = ball.defaultX + dxMouse;
var toY:Number = ball.defaultY + dyMouse;
}
else
{
toX = ball.defaultX;
toY = ball.defaultY;
}
springTo(ball, toX, toY);
ball.defaultX = toX;
ball.defaultY = toY;
}
drawLine();
//マウス位置を記憶
_lastMouseX = mouseX;
_lastMouseY = mouseY;
}
private function mouseDownHandler(e:MouseEvent):void
{
_isDragging = true;
_mousePressX = mouseX;
_mousePressY = mouseY;
}
private function mouseUpHandler(e:MouseEvent):void
{
_isDragging = false;
}
}
}
- Comments: 0
- Trackbacks (Close): 0
Home > Archives > 2008-10-21
