forked from: forked from: 万有引力のお勉強
万有引力のお勉強
書籍「FLASH LAB」のsatelliteという項目を
自分なりに租借してAS3で組みなおしてみました。
惑星がひとつだったり、出現の仕方がちょっと違いますが、
まぁ(面倒だったので)アレンジ的な感じで。
真ん中の惑星(?)はドラッグ可能です。
なんか軌道が変わりまくってるから、多分計算が違うのかなぁ・・・。
ついでにZ軸もつけてみました。
FP10になって焦点距離とか考えなくてよくなったのは
うれしいですね。ここら辺もうちょっと勉強しないと
損かなと実感。
衛星の最大移動距離が惑星より小さいと
惑星の中から衛星が出てきて不恰好な状態に・・・。
あとは全体的に不恰好なんで、エフェクトとか模様とか
付けてみたい気がします。
(5/2 6:47 単純な間違いをしてたと思って治したら更に悪化・・・
Z軸の計算間違ってるっぽい気が・・・)
// forked from runouw's forked from: 万有引力のお勉強
// forked from Hiiragi's 万有引力のお勉強
package
{
/* 万有引力のお勉強
*
* 書籍「FLASH LAB」のsatelliteという項目を
* 自分なりに租借してAS3で組みなおしてみました。
* 惑星がひとつだったり、出現の仕方がちょっと違いますが、
* まぁ(面倒だったので)アレンジ的な感じで。
*
* 真ん中の惑星(?)はドラッグ可能です。
* なんか軌道が変わりまくってるから、多分計算が違うのかなぁ・・・。
*
* ついでにZ軸もつけてみました。
* FP10になって焦点距離とか考えなくてよくなったのは
* うれしいですね。ここら辺もうちょっと勉強しないと
* 損かなと実感。
*
* 衛星の最大移動距離が惑星より小さいと
* 惑星の中から衛星が出てきて不恰好な状態に・・・。
*
* あとは全体的に不恰好なんで、エフェクトとか模様とか
* 付けてみたい気がします。
*
* (5/2 6:47 単純な間違いをしてたと思って治したら更に悪化・・・
* Z軸の計算間違ってるっぽい気が・・・)
*/
import flash.display.Sprite;
import flash.events.Event;
import com.flashdynamix.utils.SWFProfiler
import flash.events.MouseEvent;
[SWF(width=465,height=465,frameRate=30,backgroundColor=0x000000)]
public class Main extends Sprite
{
private var targetPlanet:planet = new planet(0x0000FF, 20);
private var satelliteNum:uint = 50;
private var satelliteArray:Vector.<planet> = new Vector.<planet>;
private const MG:Number = 1;
private const TIME:Number = 0.5;
private var maxSpeed:Number = 20;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
SWFProfiler.init(this);
targetPlanet.x = stage.stageWidth / 2;
targetPlanet.y = stage.stageHeight / 2;
targetPlanet.z = 0;
targetPlanet.name = "targetPlanet";
targetPlanet.addEventListener(MouseEvent.MOUSE_DOWN, onPlanetMouseDown);
targetPlanet.addEventListener(MouseEvent.MOUSE_UP, onPlanetMouseUp);
satelliteArray.push(targetPlanet);
this.addChild(targetPlanet);
var cp_x:Number = stage.stageWidth / 2;
var cp_y:Number = stage.stageHeight / 2;
for (var i:uint = 0; i < satelliteNum; i++) {
//var p:planet = new planet(0xFF6600, 3);
var p:planet = new planet(Math.random()*0xAAAAAA+0x555555, 3);
p.x = cp_x + Math.random() * 100 - 50;
p.y = cp_y + Math.random() * 100 - 50;
this.addChild(p);
satelliteArray.push(p);
}
this.addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
}
private function onPlanetMouseUp(e:MouseEvent):void
{
var p:planet = e.target as planet;
p.stopDrag();
}
private function onPlanetMouseDown(e:MouseEvent):void
{
var p:planet = e.target as planet;
p.startDrag();
}
private function onEnterFrameHandler(e:Event):void
{
//satelliteArray.forEach(movePlanet);
for each(var p:planet in satelliteArray){
for each(var s:planet in satelliteArray){
if(p!==s){
// planets now have a gravitational pull on each other
movePlanet(p,s)
}
}
if(p.name != "targetPlanet"){
p.x += p.vx*TIME;
p.y += p.vy*TIME;
p.z += p.vz*TIME;
}
}
//zSort
satelliteArray.sort(function(x:planet, y:planet):Number { return y.z - x.z; } );
var num:uint = satelliteArray.length;
for (var i:uint = 0; i < num; i++) {
this.setChildIndex(satelliteArray[i], i);
}
}
private function movePlanet(item:planet, targetPlanet:planet):void
{
if (item.name != "targetPlanet") {
var dx:Number = targetPlanet.x - item.x;
var dy:Number = targetPlanet.y - item.y;
var dz:Number = targetPlanet.z - item.z;
// using a faster alternative than trig...
//var radXY:Number = Math.atan2(dy, dx);
//var radYZ:Number = Math.atan2(dy, dz);
//var distanceXY:Number = dx * dx + dy * dy;
//var distanceYZ:Number = dy * dy + dz * dz;
//var aXY:Number = MG / (distanceXY + 4000);
//var aYZ:Number = MG / (distanceYZ + 4000);
//var aYZ:Number = MG / (distanceXY + 4000);
//var aXY_x:Number = aXY * Math.cos(radXY);
//var aXY_y:Number = aXY * Math.sin(radXY);
//var aXY_y:Number = aXY * Math.sin(radYZ);
//var aYZ_z:Number = aYZ * Math.cos(radYZ);
var d:Number = Math.sqrt(dx * dx + dy * dy + dz * dz);
var g:Number = MG/(d); // should be d*d*d
if (targetPlanet.name == "targetPlanet") {
g *= 5;
}
item.vx += (dx/d)*g*TIME;
item.vy += (dy/d)*g*TIME;
item.vz += (dz/d)*g*TIME;
//limiter
if (item.vx > maxSpeed) {
item.vx = maxSpeed;
} else if (item.vx < -maxSpeed) {
item.vx = -maxSpeed;
}
if (item.vy > maxSpeed) {
item.vy = maxSpeed;
} else if (item.vy < -maxSpeed) {
item.vy = -maxSpeed;
}
}
}
}
}
import flash.display.Sprite;
internal class planet extends Sprite{
private var _vx:Number = Math.random() * 20 - 10;
private var _vy:Number = Math.random() * 20 - 10;
private var _vz:Number = Math.random() * 20 - 10;
public function planet(color:uint,size:uint) {
this.graphics.beginFill(color);
this.graphics.drawCircle(0, 0, size);
this.graphics.endFill();
}
public function get vx():Number {
return _vx;
}
public function set vx(arg1:Number):void {
_vx = arg1;
}
public function get vy():Number {
return _vy;
}
public function set vy(arg1:Number):void {
_vy = arg1;
}
public function get vz():Number {
return _vz;
}
public function set vz(arg1:Number):void {
_vz = arg1;
}
}