// forked from kazy's forked from: BOUNDING BALLS package { import flash.display.Sprite; import flash.events.Event; import funnel.*; [SWF(backgroundColor="0x000000")] /** * Main * メインクラス. * * 09.12.06 ロクナナワークショップイベント用 製作中 */ public class Main extends Sprite { private var balls:Array; //ボールの数 private var numBalls:Number = 300; private var bounce:Number = -0.5; private var spring:Number = 0.05; private var gravityX:Number = 0.1; private var gravityY:Number = 0.9; private var fioSystem:Fio; private var fio:IOModule; // 加速度センサのx軸を接続したアナログピン private var xAxisPin:Pin; // 加速度センサのy軸を接続したアナログピン private var yAxisPin:Pin; /** * コンストラクタ. */ public function Main() { var config:Configuration = Fio.FIRMATA; // 必要ないアナログ入力をすべて出力にセットする config.setDigitalPinMode(17, OUT); // A3 config.setDigitalPinMode(18, OUT); // A4 config.setDigitalPinMode(19, OUT); // A5 config.setDigitalPinMode(20, OUT); // A6 config.setDigitalPinMode(21, OUT); // A7 fioSystem = new Fio([1], config); fio = fioSystem.ioModule(1); xAxisPin = fio.analogPin(0); yAxisPin = fio.analogPin(1); // 2つの軸のそれぞれにフィルタをセット xAxisPin.addFilter(new Convolution(Convolution.MOVING_AVERAGE)); xAxisPin.addFilter(new Scaler(0.30, 0.70, -0.7, 0.7)); yAxisPin.addFilter(new Convolution(Convolution.MOVING_AVERAGE)); yAxisPin.addFilter(new Scaler(0.30, 0.70, -0.7, 0.7)); init(); } /** * 初期化. */ private function init():void { balls = new Array(); for (var i:uint = 0; i < numBalls; i++) { //ボール生成 var ball:Ball = new Ball(Math.random() * 10 + 2, Math.random() * 0xff0000); //初期位置 ball.x = Math.random() * stage.stageWidth; ball.y = Math.random() * stage.stageHeight; //ボール初速度 ball.vx = Math.random() * 6 - 3; ball.vy = Math.random() * 6 - 3; //表示 addChild(ball); //配列追加 balls.push(ball); } //ENTER_FRAMEイベントをリスナーに追加 addEventListener(Event.ENTER_FRAME, onEnterFrame); } private function onEnterFrame(event:Event):void { // 重力の方向をセット gravityX = -yAxisPin.value; gravityY = -xAxisPin.value; trace(xAxisPin.value); for (var i:uint = 0; i < numBalls - 1; i++) { //対象のボール var ball0:Ball = balls[i]; for (var j:uint = i + 1; j < numBalls; j++) { //被対象のボール var ball1:Ball = balls[j]; //両ボール座標の相対距離 var dx:Number = ball1.x - ball0.x; var dy:Number = ball1.y - ball0.y; //3平方の定理から直線距離を出す var dist:Number = Math.sqrt(dx * dx + dy * dy); //両ボールの半径の合計を最小距離に var minDist:Number = ball0.radius + ball1.radius; //最小距離より縮まった場合 if (dist < minDist) { //x座標系の最小距離 var tx:Number = ball0.x + dx / dist * minDist; //y座標系の最小距離 var ty:Number = ball0.y + dy / dist * minDist; //加速度 var ax:Number = (tx - ball1.x) * spring; var ay:Number = (ty - ball1.y) * spring; //それぞれ反対側へ反発 ball0.vx -= ax; ball0.vy -= ay; ball1.vx += ax; ball1.vy += ay; } } } for (i = 0; i < numBalls; i++) { //基本の動き var ball:Ball = balls[i]; move(ball); } } /** * 基本の動き. */ private function move(ball:Ball):void { //重力 ball.vx += gravityX; ball.vy += gravityY; //加速 ball.x += ball.vx; ball.y += ball.vy; //壁で半分減速してはね返る if (ball.x + ball.radius > stage.stageWidth) { ball.x = stage.stageWidth - ball.radius; ball.vx *= bounce; } else if (ball.x - ball.radius < 0) { ball.x = ball.radius; ball.vx *= bounce; } if (ball.y + ball.radius > stage.stageHeight) { ball.y = stage.stageHeight - ball.radius; ball.vy *= bounce; } else if (ball.y - ball.radius < 0) { ball.y = ball.radius; ball.vy *= bounce; } } } } /** * Ball * ボール生成クラス. */ class Ball extends flash.display.Sprite { public var radius:Number; private var color:uint; public var vx:Number = 0; public var vy:Number = 0; /** * コンストラクタ. */ public function Ball(radius:Number=40, color:uint=0x990033) { this.radius = radius; this.color = color; init(); } /** * 初期化. */ public function init():void { graphics.beginFill(color); graphics.drawCircle(0, 0, radius); graphics.endFill(); } } BOUNDING BALLS WITH ACCELERATION SENSOR