forked from: Twitter Friend Location
Twiiterでフォローしているユーザーの現在地に登録されている情報で
都道府県に、配置します。
都道府県が記載されていないユーザーは、表示されません。
とりあえず、1000人まではサーチできるようにしていますが。
多いとそれだけ処理時間が長くなります。
最初かっこよくカメラ動かそうかとも思いましたが、めんどくさいので止めたw
@narutohyper
/**
* Copyright tepe ( http://wonderfl.net/user/tepe )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/jmiS
*/
// forked from narutohyper's Twitter Friend Location
package {
/*
Twiiterでフォローしているユーザーの現在地に登録されている情報で
都道府県に、配置します。
都道府県が記載されていないユーザーは、表示されません。
とりあえず、1000人まではサーチできるようにしていますが。
多いとそれだけ処理時間が長くなります。
最初かっこよくカメラ動かそうかとも思いましたが、めんどくさいので止めたw
@narutohyper
*/
import alternativ5.engine3d.materials.FillMaterial;
import alternativ5.engine3d.materials.WireMaterial;
import alternativ5.engine3d.primitives.Box;
import alternativ5.engine3d.primitives.Sphere;
import alternativ5.engine3d.core.Object3D;
import alternativ5.engine3d.events.MouseEvent3D
import alternativ5.engine3d.controllers.WalkController
import alternativ5.engine3d.controllers.ObjectController
import alternativ5.types.Point3D;
import alternativ5.engine3d.core.Camera3D;
import alternativ5.utils.KeyboardUtils
import flash.display.*;
import flash.events.*;
import flash.net.*;
import flash.text.*;
import flash.system.*;
import caurina.transitions.Tweener;
[SWF(width = 465, height = 465, frameRate = 60,backgroundColor=0x000000)]
public class SimpleDemo extends Sprite {
private var prefectureArray:Array;
private var eye:Sphere
private var camera:Camera3D
public function SimpleDemo():void {
var template:BasicTemplate = new BasicTemplate();
addChild(template);
camera=template.camera
camera.z=500
//Controllerのインスタンスを作る
var walkController:WalkController=new WalkController(this.stage,template.camera)
walkController.lookAt(new Point3D(0,0,0));
//キーボードのキー(Keyboard.KEY)を関連付ける(Bind)する
walkController.mouseEnabled=false
walkController.bindKey(KeyboardUtils.PAGE_UP, ObjectController.ACTION_UP);
walkController.bindKey(KeyboardUtils.PAGE_DOWN, ObjectController.ACTION_DOWN);
walkController.bindKey(KeyboardUtils.E, ObjectController.ACTION_UP);
walkController.bindKey(KeyboardUtils.D, ObjectController.ACTION_DOWN);
walkController.bindKey(KeyboardUtils.W, ObjectController.ACTION_FORWARD);
walkController.bindKey(KeyboardUtils.UP, ObjectController.ACTION_FORWARD);
walkController.bindKey(KeyboardUtils.Z, ObjectController.ACTION_BACK);
walkController.bindKey(KeyboardUtils.DOWN, ObjectController.ACTION_BACK);
walkController.bindKey(KeyboardUtils.A, ObjectController.ACTION_YAW_LEFT);
walkController.bindKey(KeyboardUtils.LEFT, ObjectController.ACTION_YAW_LEFT);
walkController.bindKey(KeyboardUtils.S, ObjectController.ACTION_YAW_RIGHT);
walkController.bindKey(KeyboardUtils.RIGHT, ObjectController.ACTION_YAW_RIGHT);
walkController.bindKey(KeyboardUtils.SHIFT, ObjectController.ACTION_ACCELERATE);
//移動スピードを設定する
walkController.speed = 700;
//初期位置を設定する
walkController.coords=new Point3D(0,-4000,500);
var base:Object3D = new Object3D();
template.scene.root.addChild(base);
//base.rotationX = -70 * Math.PI / 180;
var areArray:Array=[
['北海道','hokkaido'],
['青森' ,'aomori'],
['秋田' ,'akita'],
['岩手' ,'iwate'],
['山形' ,'yamagata'],
['宮城' ,'miyagi'],
['福島' ,'fukushima'],
['茨城' ,'ibaragi'],
['千葉' ,'chiba'],
['栃木' ,'tochigi'],
['群馬' ,'gunma'],
['埼玉' ,'saitama'],
['東京' ,'tokyo'],
['神奈川','kanagawa'],
['新潟' ,'nigata'],
['山梨' ,'yamanashi'],
['長野' ,'nagano'],
['富山' ,'toyama'],
['石川' ,'ishikawa'],
['福井' ,'fukui'],
['静岡' ,'shizuoka'],
['愛知' ,'aichi'],
['岐阜' ,'gifu'],
['三重' ,'mie'],
['滋賀' ,'shiga'],
['奈良' ,'nara'],
['和歌山','wakayama'],
['京都' ,'kyoto'],
['大阪' ,'osaka'],
['兵庫' ,'hyougo'],
['鳥取' ,'tottori'],
['岡山' ,'okayama'],
['島根' ,'simane'],
['広島' ,'hiroshima'],
['山口' ,'yamaguchi'],
['香川' ,'kagawa'],
['愛媛' ,'ehime'],
['徳島' ,'tokushima'],
['高知' ,'kouchi'],
['福岡' ,'fukuoka'],
['大分' ,'oita'],
['宮崎' ,'miyazaki'],
['熊本' ,'kumamoto'],
['鹿児島','kagoshima'],
['佐賀' ,'saga'],
['長崎' ,'nagasaki'],
['沖縄' ,'okinawa']
]
prefectureArray=[];
prefectureArray.push(new prefecture(this,base, 0,0,'北海道',770,100,200,200));
prefectureArray.push(new prefecture(this,base, 1,0,'青森',720,250,100,60));
prefectureArray.push(new prefecture(this,base, 2,0,'秋田',695,320,50,80));
prefectureArray.push(new prefecture(this,base, 3,0,'岩手',745,320,50,80));
prefectureArray.push(new prefecture(this,base, 4,0,'山形',695,400,50,80));
prefectureArray.push(new prefecture(this,base, 5,0,'宮城',745,400,50,80));
prefectureArray.push(new prefecture(this,base, 6,0,'福島',720,470,100,60));
prefectureArray.push(new prefecture(this,base, 7,1,'茨城',745,535,50,70));
prefectureArray.push(new prefecture(this,base, 8,1,'千葉',745,625,50,110));
prefectureArray.push(new prefecture(this,base, 9,1,'栃木',695,520,50,40));
prefectureArray.push(new prefecture(this,base,10,1,'群馬',645,520,50,40));
prefectureArray.push(new prefecture(this,base,11,1,'埼玉',670,560,100,40));
prefectureArray.push(new prefecture(this,base,12,1,'東京',695,600,50,40));
prefectureArray.push(new prefecture(this,base,13,1,'神奈川',695,640,50,40));
prefectureArray.push(new prefecture(this,base,14,2,'新潟',620,470,100,60));
prefectureArray.push(new prefecture(this,base,15,2,'山梨',645,605,50,50));
prefectureArray.push(new prefecture(this,base,16,2,'長野',595,565,50,130));
prefectureArray.push(new prefecture(this,base,17,2,'富山',545,515,50,50));
prefectureArray.push(new prefecture(this,base,18,2,'石川',500,485,40,110));
prefectureArray.push(new prefecture(this,base,19,2,'福井',475,565,50,50));
prefectureArray.push(new prefecture(this,base,20,3,'静岡',635,665,70,70));
prefectureArray.push(new prefecture(this,base,21,3,'愛知',570,655,60,50));
prefectureArray.push(new prefecture(this,base,22,3,'岐阜',535,585,70,90));
prefectureArray.push(new prefecture(this,base,23,3,'三重',520,680,40,100));
prefectureArray.push(new prefecture(this,base,24,4,'滋賀',475,620,50,60));
prefectureArray.push(new prefecture(this,base,25,4,'奈良',475,680,50,60));
prefectureArray.push(new prefecture(this,base,26,4,'和歌山',455,740,90,60));
prefectureArray.push(new prefecture(this,base,27,4,'京都',430,595,40,70));
prefectureArray.push(new prefecture(this,base,28,4,'大阪',430,670,40,80));
prefectureArray.push(new prefecture(this,base,29,4,'兵庫',380,605,60,90));
prefectureArray.push(new prefecture(this,base,30,5,'鳥取',315,580,70,40));
prefectureArray.push(new prefecture(this,base,31,5,'岡山',315,625,70,50));
prefectureArray.push(new prefecture(this,base,32,5,'島根',245,580,70,40));
prefectureArray.push(new prefecture(this,base,33,5,'広島',245,625,70,50));
prefectureArray.push(new prefecture(this,base,34,5,'山口',180,615,60,70));
prefectureArray.push(new prefecture(this,base,35,6,'香川',340,700,80,40));
prefectureArray.push(new prefecture(this,base,33,6,'愛媛',260,700,80,40));
prefectureArray.push(new prefecture(this,base,37,6,'徳島',340,740,80,40));
prefectureArray.push(new prefecture(this,base,38,6,'高知',260,740,80,40));
prefectureArray.push(new prefecture(this,base,39,7,'福岡',145,685,90,50));
prefectureArray.push(new prefecture(this,base,40,7,'大分',170,740,40,60));
prefectureArray.push(new prefecture(this,base,41,7,'宮崎',170,805,40,70));
prefectureArray.push(new prefecture(this,base,42,7,'熊本',125,750,50,80));
prefectureArray.push(new prefecture(this,base,43,7,'鹿児島',125,820,50,60));
prefectureArray.push(new prefecture(this,base,44,7,'佐賀',80,685,40,50));
prefectureArray.push(new prefecture(this,base,45,7,'長崎',40,695,40,70));
prefectureArray.push(new prefecture(this,base,46,7,'沖縄',50,830,60,40));
var friendArray:Array=[]
var inputBox:TextField=new TextField()
inputBox.type=TextFieldType.INPUT
inputBox.width=200
inputBox.height=20
inputBox.x=10
inputBox.y=10
inputBox.selectable=true;
inputBox.mouseEnabled=true;
inputBox.background=true;
inputBox.backgroundColor=0xFFFFFF
inputBox.border
var format:TextFormat=new TextFormat();
format.color=0x000000
format.size=12;
format.font='_ゴシック';
inputBox.defaultTextFormat=format
inputBox.text='narutohyper'
addChild(inputBox)
//searchButton
var bt:Sprite=new Sprite()
bt.graphics.beginFill(0xCCCCCC,1)
bt.graphics.drawRect(0,0,100,20)
bt.x=220
bt.y=10
var label:TextField=new TextField()
label.autoSize=TextFieldAutoSize.CENTER
label.selectable=false;
label.mouseEnabled=false;
format=new TextFormat();
format.color=0x000000
format.size=12;
format.font='_ゴシック';
label.defaultTextFormat=format
label.text='search'
bt.addChild(label)
addChild(bt)
bt.addEventListener(MouseEvent.CLICK,init)
var guideBox:TextField=new TextField()
guideBox.autoSize=TextFieldAutoSize.LEFT
guideBox.width=400
guideBox.y=40
guideBox.selectable=true;
guideBox.mouseEnabled=true;
format=new TextFormat();
format.color=0xFFFFFF
format.size=12;
format.font='_等幅';
guideBox.defaultTextFormat=format
guideBox.text="TwitterIDを入力して、searchを押してください。\n";
guideBox.appendText(" W↑ E上 \n");
guideBox.appendText("←A S→ D下 \n");
guideBox.appendText(" Z↓ \n");
guideBox.appendText("十字キーでも操作できます。\n");
addChild(guideBox);
var dbg:TextField=new TextField()
//dbg.autoSize=TextFieldAutoSize.LEFT
dbg.width=400
dbg.y=120
dbg.selectable=true;
dbg.mouseEnabled=true;
dbg.multiline=true;
format=new TextFormat();
format.color=0xFFFFFF
format.size=12;
format.font='_ゴシック';
dbg.defaultTextFormat=format
addChild(dbg);
function init():void {
var userId:String=inputBox.text
var loader:URLLoader = new URLLoader();
var page:uint=1
var maxPage:uint=11
var next_cursor:Number=-1
for (var i:uint=0;i<prefectureArray.length;i++) {
prefectureArray[i].init()
}
dbg.text="";
loadXml()
function loadXml():void {
//Twitterのstatusesはcrossdomain許可されていない為、セキュリティエラーで取得できない
//とりあえず串で対応
Security.loadPolicyFile("http://marubayashi.net/crossdomain.xml");
var url:String="http://marubayashi.net/tips/crossdomain-proxy.php?url="+"http://twitter.com/statuses/friends/"+userId+".xml?cursor="+next_cursor
dbg.appendText("読み込み ");
new LoaderContext(true)
loader.load(new URLRequest(url));
loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurityError);
loader.addEventListener(Event.OPEN,onOpen);
loader.addEventListener(Event.COMPLETE,onComplete);
loader.addEventListener(IOErrorEvent.IO_ERROR, errorEvent);
}
function onSecurityError(e:SecurityErrorEvent):void {
dbg.appendText("\nsecurityErrorHandler: " + e);
dbg.appendText("\n");
}
function onOpen(e:Event):void {
dbg.appendText("開始\n");
}
function onComplete(e:Event):void {
dbg.appendText("終了\n");
loader.removeEventListener(Event.COMPLETE,onComplete );
loader.removeEventListener(IOErrorEvent.IO_ERROR, errorEvent);
next_cursor=XML(loader.data).next_cursor
var users:XMLList = XML(loader.data).users.user;
var pattern:RegExp
var matchId:int
var temp:uint
for each(var x:XML in users) {
matchId=-1;
for (var i:uint=0;i<areArray.length;i++) {
pattern = new RegExp(areArray[i][0]+'|'+areArray[i][1], "i");
if (pattern.exec(x.location)) {
matchId=i;
break;
}
}
if (matchId>=0) {
prefectureArray[matchId].addFriend(x.name,x.profile_image_url)
}
temp++
}
page++
if (maxPage>page && next_cursor) {
loadXml(userId)
} else {
dbg.text="";
//配置が終わったら、各県のキャラクターを分布させる
for (i=0;i<prefectureArray.length;i++) {
prefectureArray[i].setPosition()
}
}
}
function errorEvent(e:IOErrorEvent):void {
guideBox.appendText("ERROR"+e+"\n");
loader.removeEventListener(Event.COMPLETE,onComplete );
loader.removeEventListener(IOErrorEvent.IO_ERROR, errorEvent);
trace(e);
}
}
template.onPreRender = function():void {
//walkController.lookAt(eye.coords);
walkController.processInput()
//camera.coords=new Point3D(eye.x,eye.y-1000,1000)
}
}
}
}
import alternativ5.engine3d.primitives.Plane;
import alternativ5.engine3d.primitives.Cone;
import alternativ5.engine3d.core.Sprite3D;
import alternativ5.engine3d.materials.FillMaterial;
import alternativ5.engine3d.materials.TextureMaterial;
import alternativ5.engine3d.materials.SpriteTextureMaterial;
import alternativ5.types.Texture;
import alternativ5.engine3d.events.MouseEvent3D
import flash.display.*;
import flash.text.*;
import flash.net.*;
import flash.system.LoaderContext;
import flash.geom.Matrix;
import flash.utils.escapeMultiByte;
import jp.progression.casts.CastDocument;
import jp.progression.commands.lists.LoaderList;
import jp.progression.commands.lists.SerialList;
import jp.progression.commands.net.LoadBitmapData;
import jp.progression.commands.net.LoadURL;
import jp.progression.data.Resource;
import jp.progression.data.getResourceById;
class prefecture extends Object3D{
private var mainMc:SimpleDemo
private var id:uint
private var bmd:BitmapData
private var friendList:Array
private var friendSet:Object3D
private var width:Number
private var height:Number
private var colorArray:Array=[0xB0CFEA,0xFFB0B0,0xB0F1C0,0xDBB6FF,0xFFD3B0,0xD9FFB0,0xFFD8FF,0xFFFDB0]
private var prefectureName:String
private var cone:*
private var cone2:*
private var bmdCounter:uint=0
public function prefecture(_mainMc:SimpleDemo,_parentMc:Object3D,_id:uint,_areaid:uint,_name:String,_x:Number,_y:Number,_width:Number,_height:Number) {
mainMc=_mainMc
var s:uint=6
friendList=[]
prefectureName=_name
width=_width*s-4*s
height=_height*s-4*s
var base:Plane = new Plane(width,height);
base.cloneMaterialToAllSurfaces(new FillMaterial(colorArray[_areaid]));
this.addChild(base)
x=_x*s-850/2*s+50*s
y=-_y*s+850/2*s
_parentMc.addChild(this)
mainMc.addEventListener(Event.ENTER_FRAME, onEnterFrame);
function onEnterFrame(e:Event):void {
if (cone) {
cone.rotationZ+=1*Math.PI/180
}
if (cone2) {
cone2.rotationZ+=1*Math.PI/180
}
}
}
public function init():void {
if (cone) {
this.removeChild(cone);
cone=null;
}
if (cone2) {
this.removeChild(cone2);
cone2=null;
}
for (var i:uint = 0; i < friendList.length; i++) {
var res:Resource = getResourceById(friendList[i].filename);
if (res) {
res.dispose()
res=null
}
}
//2010/2/24メモリリーク修正
if(bmd) {
bmd.dispose()
}
friendList=[]
}
public function addFriend(_name:String,_filename:String):void {
friendList.push({name:_name,filename:_filename})
}
public function addFriendBmd(i:uint,f:BitmapData,_scale:Number):void {
bmd.draw(f,new Matrix(_scale,0,0,_scale,i%12*80,(bmd.height-80)-Math.floor(i/12)*80))
}
private static const LOADER_CONTEXT:LoaderContext = new LoaderContext(true);
public function setPosition():void {
var r:Number=0
var pol:uint=12
if (friendList.length==1 || friendList.length==2) {
cone=new Sprite3D();
bmd=new BitmapData(80*friendList.length,80,true,0x00000000)
cone.z=80/2;
addChild(cone)
cone.material=new SpriteTextureMaterial(new Texture(bmd),1,true);
} else if (friendList.length) {
pol=(friendList.length<12)? friendList.length:12
bmd=new BitmapData(80*pol,80*Math.ceil(friendList.length/pol),true,0x00000000)
r=80/(2*Math.sin(Math.PI/pol))
cone=new Cone(80*Math.ceil(friendList.length/pol),r,r,1,pol,false,true);
cone.z=80*Math.ceil(friendList.length/pol)/2*0.7;
cone.scaleX=cone.scaleY=cone.scaleZ=0.7
addChild(cone)
cone.setMaterialToSurface(new TextureMaterial(new Texture(bmd),1,false,true),'side');
cone2=new Cone(80*Math.ceil(friendList.length/pol),r,r,1,pol,true,false);
cone2.z=80*Math.ceil(friendList.length/pol)/2*0.7;
cone2.scaleX=cone2.scaleY=cone2.scaleZ=0.7
addChild(cone2)
cone2.setMaterialToSurface(new FillMaterial(0x666666),'side');
}
//画像の読み込み
new SerialList(null,
function():void {
var cmd:LoaderList = new LoaderList();
for (var i:uint = 0; i < friendList.length; i++) {
cmd.addCommand(
new LoadBitmapData(new URLRequest(friendList[i].filename),
{
context: new LoaderContext(true),
catchError: function(target:Object, error:Error):void {
target.executeComplete();
}
}
)
);
}
this.parent.insertCommand(cmd);
}
,
function():void {
for (var i:uint = 0; i < friendList.length; i++) {
var s:Number
var res:Resource = getResourceById(friendList[i].filename);
var bmd:BitmapData = res.toBitmapData();
if (bmd) {
if (bmd.width>bmd.height) {
s=80/bmd.width
} else {
s=80/bmd.height
}
addFriendBmd(i,bmd,s)
}
}
}
).execute();
}
}
import alternativ5.engine3d.controllers.CameraController;
import alternativ5.engine3d.core.Camera3D;
import alternativ5.engine3d.core.Object3D;
import alternativ5.engine3d.core.Scene3D;
import alternativ5.engine3d.display.View;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
/**
* BasicTemplate for Alternativa3D
* Alternativa3Dを扱いやすくするためのテンプレートです
* @author Yasu
*/
class BasicTemplate extends Sprite{
/**
* シーンインスタンスです。
*/
public var scene:Scene3D;
/**
* ビューインスタンスです。
*/
public var view:View;
/**
* カメラインスタンスです。
*/
public var camera:Camera3D;
/**
* カメラコントローラーです。
*/
public var cameraContoller:CameraController;
private var _viewWidth:int;
private var _viewHeight:int;
private var _scaleToStage:Boolean;
/**
* 新しい BasicTemplate インスタンスを作成します。
* @param viewWidth
* @param viewHeight
* @param scaleToStage
*/
public function BasicTemplate(viewWidth:int=640, viewHeight:int=480, scaleToStage:Boolean = true) {
_viewWidth = viewWidth;
_viewHeight = viewHeight;
_scaleToStage = scaleToStage;
// Creating scene
scene = new Scene3D();
scene.splitAnalysis = false; // not analysis for performance
scene.root = new Object3D();
// Adding camera
camera = new Camera3D();
camera.z = -1000;
scene.root.addChild(camera);
// camera contoller
cameraContoller = new CameraController(this);
cameraContoller.camera = camera;
// set view
view = new View();
view.camera = camera;
addChild(view);
// stage
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
/**
* 初期化されたときに実行されるイベントです。
* 初期化時に実行したい処理をオーバーライドして記述します。
*/
protected function atInit():void {}
/**
* 初期化されたときに実行されるイベントです。
* 初期化時に実行したい処理を記述します。
*/
private var _onInit:Function = function():void { };
public function get onInit():Function { return _onInit; }
public function set onInit(value:Function):void {
_onInit = value;
}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング前に実行したい処理をオーバーライドして記述します。
*/
protected function atPreRender():void {}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング前に実行したい処理を記述します。
*/
private var _onPreRender:Function = function():void{};
public function get onPreRender():Function { return _onPreRender; }
public function set onPreRender(value:Function):void {
_onPreRender = value;
}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング後に実行したい処理をオーバーライドして記述します。
*/
protected function atPostRender():void {
}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング後に実行したい処理を記述します。
*/
protected var _onPostRender:Function = function():void{};
public function get onPostRender():Function { return _onPostRender; }
public function set onPostRender(value:Function):void {
_onPostRender = value;
}
/**
* レンダリングを開始します。
*/
public function startRendering():void {
addEventListener(Event.ENTER_FRAME, onRenderTick);
}
/**
* レンダリングを停止します。
*/
public function stopRendering():void {
removeEventListener(Event.ENTER_FRAME, onRenderTick);
}
/**
* シングルレンダリング(レンダリングを一回だけ)を実行します。
*/
public function singleRender():void {
onRenderTick();
}
/**
* @private
*/
private function init(e:Event = null):void {
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.quality = StageQuality.HIGH;
// resize
stage.addEventListener(Event.RESIZE, onResize);
onResize(null);
// render
startRendering();
atInit();
_onInit();
}
/**
* @private
*/
private function onRenderTick(e:Event = null):void {
atPostRender();
_onPostRender();
scene.calculate();
atPreRender();
_onPreRender();
}
/**
* @private
*/
private function onResize(event:Event = null):void {
if (_scaleToStage) {
view.width = stage.stageWidth;
view.height = stage.stageHeight;
}else {
view.width = _viewWidth;
view.height = _viewHeight;
}
}
}