怪盗福笑い
MediaRSSを使って福笑い
「村(tag)の村人の顔が怪盗福笑いに奪われた」という設定で
強引にゲームっぽくしてみました。
右上の検索バーでtagを指定すると,他の村(tag)を探せます。
ちなみにスクリーンショットの村人達は"mobile"村にいました。(2010.08.29)
効果音とBGMが欲しい...
コードは,,,汚くてすいません。
既知のバグ:
最初の読み込み時に95%sで止まることがある。
顔認識するときにJPEGのエンコード処理でタイムアウトエラーが発生する場合がある。
/**
* Copyright geko ( http://wonderfl.net/user/geko )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/ekEn
*/
// MediaRSSを使って福笑い
// 「村(tag)の村人の顔が怪盗福笑いに奪われた」という設定で
// 強引にゲームっぽくしてみました。
// 右上の検索バーでtagを指定すると,他の村(tag)を探せます。
// ちなみにスクリーンショットの村人達は"mobile"村にいました。(2010.08.29)
//
// 効果音とBGMが欲しい...
// コードは,,,汚くてすいません。
//
// 既知のバグ:
// 最初の読み込み時に95%sで止まることがある。
// 顔認識するときにJPEGのエンコード処理でタイムアウトエラーが発生する場合がある。
package {
import flash.display.*;
import flash.events.*;
import flash.net.*;
import flash.system.*;
import caurina.transitions.Tweener;
[SWF(width=465, height=465, backgroundColor=0x333333)]
public class MakeAFace extends Sprite{
static public const ThanksMessages:Array = [["村人:ありがとう。\nイカしたオレの顔が戻ったよ。", "村人:これで明日の合コンに行けそうだ!\n助かった。本当にありがとう。"],
["村人:おぉ,どうも。助かったよ。", "村人:それじゃ。"],
["村人:ふぁ〜,よく寝た。\n・・・\n・・・\nあれ,勇者さんだ?何かあったのかい?", "村人:なんだか忙しいみたいだけど,勇者さんもたまには僕みたいに休んだ方がいいよ。\nそれじゃ僕は帰って寝直すよ。"],
["村人:おぉ,私の顔が帰ってきた!\nありがとう,ありがとう!!", "村人:一時は人生をあきらめかけていたんだけど,なんとかやっていく勇気が沸いてきたよ。"],
["???:うぁっはっはっはっはっ!!\n私が ”怪盗福笑い” だ!", "村人:なーんちゃって,うそだよーん。\n助けてくれてありがとさーん。"]];
public var itemsPanel:ItemsPanel;
public var setUpPanel:SetUpPanel;
public var canvas:MakeFaceCanvas;
public var message:MessagePanel;
public var menuBar:MenuBar;
public var webAPI:WebAPI = new WebAPI();
public var target:Loader;
public var sp:Sprite = new Sprite();
public function MakeAFace(){
//Wonderfl.capture_delay(30);
Wonderfl.disable_capture();
this.graphics.beginFill(0x333333);
this.graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight);
this.graphics.endFill();
sp.graphics.beginFill(0,0);
sp.graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight);
sp.graphics.endFill();
init();
}
private function init():void{
itemsPanel = new ItemsPanel(this);
setUpPanel = new SetUpPanel(this);
message = new MessagePanel(stage);
itemsPanel.addEventListener(Event.COMPLETE, setUpComplete);
itemsPanel.addEventListener(ProgressEvent.PROGRESS, progress);
webAPI.addEventListener(Event.COMPLETE, detectFaceComplete);
message.addEventListener(Event.COMPLETE, setUpComplete);
itemsPanel.search("close up face");
message.inputMessages("???:おぉ勇者よ,目覚めたか。わしは ”じいちゃん” じゃ。","じぃ:大変じゃ。お主がのんびり寝取る間に, ”怪盗福笑い” に村の者の顔が奪われてしまったのじゃ。","じぃ:勇者よ,今こそ立ち上がるときじゃ!\n ”福笑い” に立ち向かい,村の者の顔を取り戻してくるのじゃ!!\n\n\n※要は福笑いです。");
}
public function setUpComplete(event:Event):void{
event.target.removeEventListener(Event.COMPLETE, setUpComplete);
if((event.target == message ? itemsPanel : message).hasEventListener(Event.COMPLETE)) return;
Tweener.addTween(setUpPanel, {alpha:0, time:0.8, onComplete:function comps():void{
(setUpPanel.parent as DisplayObjectContainer).removeChild(setUpPanel);
setUpPanel = null;
}});
menuBar = new MenuBar(stage.stageWidth, 25);
stage.addChild(menuBar);
itemsPanel.addEventListener("find", findVillage);
itemsPanel.addEventListener("none", findVillage);
itemsPanel.addEventListener("selectedTop", menuChange);
itemsPanel.addEventListener("selectedVillage", menuChange);
itemsPanel.addEventListener("selectedVillager", menuChange);
itemsPanel.addEventListener(Event.SELECT, selected);
menuBar.addEventListener("search", search);
menuBar.topBt.addEventListener(MouseEvent.CLICK, itemChange);
menuBar.villageBt.addEventListener(MouseEvent.CLICK, itemChange);
menuBar.villagerBt.addEventListener(MouseEvent.CLICK, itemChange);
}
private function progress(event:ProgressEvent):void{
if(setUpPanel) setUpPanel.value = event.bytesLoaded/event.bytesTotal;
}
//----
//flickerのtag検索
//検索開始
private function search(event:Event):void{
itemsPanel.search(menuBar.tag);
message.inputMessages("じぃ: \""+menuBar.tag+"\" 村...あったかのぅ...");
addChild(sp);
}
//発見
private function findVillage(event:Event):void{
switch(event.type){
case "find":
message.inputMessages("じぃ:勇者よ,見つけたぞ!\nどうやら \""+menuBar.tag+"\" 村はあるようじゃの。");
if(menuBar.topBt.selected) itemsPanel.showPanel("top");
break;
case "none": message.inputMessages("じぃ:勇者よ,残念ながら \""+menuBar.tag+"\" 村は既に存在しないようじゃ。"); break;
}
removeChild(sp);
}
//-----
//メニューとパネルの変更
//メニューの変更
private function menuChange(event:Event):void{
switch(event.type){
case "selectedTop": menuBar.change("top",[]); break;
case "selectedVillage": menuBar.change("village", [itemsPanel.selectedVillage.name]); break;
case "selectedVillager": menuBar.change("villager", [itemsPanel.selectedVillage.name, itemsPanel.selectedVillager.name]); break;
}
}
//パネルの変更
private function itemChange(event:MouseEvent):void{
switch(event.currentTarget){
case menuBar.topBt: itemsPanel.showPanel("top"); break;
case menuBar.villageBt: itemsPanel.showPanel("village"); break;
case menuBar.villagerBt: itemsPanel.showPanel("villager"); break;
}
}
//-----
//顔認識
//村人の選択
private function selected(event:Event):void{
message.inputMessages("じぃ:お〜い, \""+itemsPanel.selectedVillager.name+"\" さ〜ん\nどこにおられますか〜?");
target = new Loader();
target.load(new URLRequest(itemsPanel.selectedVillager.url), new LoaderContext(true));
target.contentLoaderInfo.addEventListener(Event.COMPLETE, function complete(event:Event):void{
target.contentLoaderInfo.removeEventListener(Event.COMPLETE, complete);
var bmd:BitmapData = new BitmapData(target.width, target.height);
bmd.draw(target);
webAPI.detectFace(bmd);
});
addChild(sp);
}
//顔認識完了
private function detectFaceComplete(event:Event):void{
var xml:XML = XML(webAPI.data);
var faces:Array = [];
removeChild(sp);
//顔が見つかった
if(xml.face.hasOwnProperty("features")){
message.inputMessages("じぃ:おぉ,あそこに \""+itemsPanel.selectedVillager.name+"\" さんがおりますぞ。","村人:た,助けてください!\n私の顔が奪われてしまった!!");
for each(var _xml:XML in xml.face){
if(!_xml.hasOwnProperty("features")) continue;
var face:FacialPath = new FacialPath(_xml.features);
faces.push(face);
}
}
//顔が見つからなかった
else{
message.inputMessages("じぃ:おぉ,あそこに \""+itemsPanel.selectedVillager.name+"\" さんがおりますぞ。", "じぃ:どうやらこの者は顔を奪われていないようじゃ。");
message.addEventListener(Event.COMPLETE, function complete(event:Event):void{
message.removeEventListener(Event.COMPLETE, complete);
itemsPanel.showPanel("village");
});
}
itemsPanel.showPanel("villager");
itemsPanel.canvas.newFace(target, faces);
itemsPanel.canvas.addEventListener("comps", function complete(event:Event):void{
itemsPanel.canvas.removeEventListener(Event.COMPLETE, complete);
message.inputMessages(ThanksMessages[Math.round(Math.random()*(ThanksMessages.length-1))]);
message.addEventListener(Event.COMPLETE, function complete(event:Event):void{
message.removeEventListener(Event.COMPLETE, complete);
itemsPanel.canvas.remove(1,0);
});
});
itemsPanel.canvas.addEventListener("remove", function removed(event:Event):void{
itemsPanel.canvas.removeEventListener(Event.REMOVED, removed);
itemsPanel.showPanel("village");
});
}
}
}
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.net.*;
import flash.system.*;
import flash.text.*;
import flash.utils.*;
import caurina.transitions.Tweener;
import caurina.transitions.properties.ColorShortcuts;
import com.adobe.images.*;
///////////////////////////////////////////
///////////// MainPanel /////////////
///////////////////////////////////////////
//----------
//メインパネル
class ItemsPanel extends Sprite{
public function ItemsPanel(parent:DisplayObjectContainer){
parent.addChild(this);
addChild(villageContainer);
addChild(villagersContainer);
canvas = new MakeFaceCanvas(this);
villagersContainer.x = 465;
canvas.x = 930;
mediaRSS.addEventListener("find", findVillage);
mediaRSS.addEventListener("none", noneVillage);
}
public function search(tag:String):void{
this.tag = tag
mediaRSS.search(this.tag);
}
private function findVillage(event:Event):void{
var village:Village = new Village();
village.title = tag;
for each(var item:Object in mediaRSS.items){
village.addVillager(item);
}
villages.push(village);
villageContainer.addChild(village);
village.x = 85*((villages.length-1)%5)+20;
village.y = 100*(Math.floor((villages.length-1)/5))+40;
village.addEventListener(MouseEvent.DOUBLE_CLICK, selected);
village.addEventListener(ProgressEvent.PROGRESS, function progress(event:ProgressEvent):void{
dispatchEvent(event);
});
village.addEventListener(Event.COMPLETE, function complete(event:Event):void{
dispatchEvent(event);
});
selectedVillage = village;
dispatchEvent(event);
}
private function noneVillage(event:Event):void{
dispatchEvent(event);
}
private function selected(event:Event):void{
switch(event.type){
case MouseEvent.DOUBLE_CLICK:
selectedVillage = event.currentTarget as Village;
showPanel("village");
break;
case Event.SELECT:
selectedVillager = selectedVillage.villager;
dispatchEvent(event);
break;
}
}
public function showPanel(target:String):void{
if(villagersContainer.numChildren) {
villagersContainer.getChildAt(0).removeEventListener(Event.SELECT, selected);
villagersContainer.removeChild(villagersContainer.getChildAt(0));
}
villagersContainer.addChild(selectedVillage.villagersContainer);
villagersContainer.getChildAt(0).addEventListener(Event.SELECT, selected);
Tweener.addTween(this, {x: target == "top" ? 0 : target == "village" ? -465 : -930, time:0.8});
dispatchEvent(new Event(target == "top" ? "selectedTop" : target == "village" ? "selectedVillage" : "selectedVillager"));
}
public var mediaRSS:MediaRSS = new MediaRSS();
public var tag:String;
public var villages:Vector.<Village> = new Vector.<Village>();
public var canvas:MakeFaceCanvas;
public var selectedVillage:Village;
public var selectedVillager:Villager;
public var villageContainer:Sprite = new Sprite();
public var villagersContainer:Sprite = new Sprite();
}
//----------
//福笑い用キャンバス
class MakeFaceCanvas extends Sprite{
private var bmp:Bitmap = new Bitmap(null,"never");
private var container:Sprite = new Sprite();
public function MakeFaceCanvas(parent:DisplayObjectContainer) {
parent.addChildAt(this,0);
ColorShortcuts.init();
init();
}
private function init():void{
this.addChild(bmp);
this.addChild(container);
bmp.bitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0xFFFFFF);
}
public function newFace(source:Loader, facialPaths:Array):void{
if(bmp.bitmapData) bmp.bitmapData.dispose();
while(container.numChildren){
var target:Sprite = container.getChildAt(0) as Sprite;
container.removeChild(target);
target = null;
}
if(!facialPaths) return;
var mtrx:Matrix = new Matrix();
scale = Math.min(stage.stageWidth/source.content.width, stage.stageHeight/source.content.height);
dx = (stage.stageWidth-source.content.width*scale)/2;
dy = (stage.stageHeight-source.content.height*scale)/2;
var bmd:BitmapData = new BitmapData(source.content.width*scale, source.content.height*scale, false);
mtrx.scale(scale, scale);
bmd.draw(source, mtrx);
bmp.bitmapData = bmd;
bmp.x = op.x = dx;
bmp.y = op.y = dy;
trace(facialPaths.length);
for each(var facialPath:FacialPath in facialPaths){
var F:Sprite = new Sprite();
var M:Sprite = new Sprite();
var N:Sprite = new Sprite();
var BR:Sprite = new Sprite();
var BL:Sprite = new Sprite();
var ER:Sprite = new Sprite();
var EL:Sprite = new Sprite();
container.addChild(F);
container.addChild(M);
container.addChild(N);
container.addChild(BR);
container.addChild(BL);
container.addChild(ER);
container.addChild(EL);
drawPath(F, facialPath._facePath, 2, 0x000000, 0xFFFFFF);
drawPath(F, facialPath._mousePath, null, null, 0xDDDDDD);
drawPath(F, facialPath._nosePath, null, null, 0xDDDDDD);
drawPath(F, facialPath._rightEyePath, null, null, 0xDDDDDD);
drawPath(F, facialPath._leftEyePath, null, null, 0xDDDDDD);
drawPath(F, facialPath._rightBrowPath, null, null, 0xDDDDDD);
drawPath(F, facialPath._leftBrowPath, null, null, 0xDDDDDD);
drawPath(M, facialPath._mousePath, 1, 0x666666, 0xDD0000, true);
drawPath(N, facialPath._nosePath, 1, 0x666666, 0xFFFFFF, true);
drawPath(ER, facialPath._rightEyePath, 1, 0x666666, 0x000000, true);
drawPath(EL, facialPath._leftEyePath, 1, 0x666666, 0x000000, true);
drawPath(BR, facialPath._rightBrowPath, 1, 0x666666, 0x996600, true);
drawPath(BL, facialPath._leftBrowPath, 1, 0x666666, 0x996600, true);
}
comps = 0;
for(var i:uint = 0; i < container.numChildren; i++){
var parts:Sprite = container.getChildAt(i) as Sprite;
if(i % 7 == 0) {
comps++;
container.addChildAt(parts,0);
continue;
}
parts.addEventListener(MouseEvent.MOUSE_DOWN, drag);
parts.addEventListener(MouseEvent.MOUSE_UP, drag);
}
}
private function drawPath(sp:Sprite, path:GraphicsPath, thickness:Object = null, lineColor:Object = null, fillColor:Object = null, shuffle:Boolean = false):void{
if(shuffle){
var minX:Number = path.data[0]*scale;
var minY:Number = path.data[1]*scale;
var maxX:Number = minX;
var maxY:Number = minY;
for(var i:uint = 2; i < path.data.length; i++){
var data:Number = path.data[i]*scale;
if(i%2 == 0){
minX = Math.min(minX, data);
maxX = Math.max(maxX, data);
}
else {
minY = Math.min(minY, data);
maxY = Math.max(maxY, data);
}
}
sp.graphics.beginFill(0xFFFFFF,0);
sp.graphics.drawRect(minX/scale-5, minY/scale-5, (maxX-minX)/scale+10, (maxY-minY)/scale+10);
sp.graphics.endFill();
sp.x = -minX+Math.random()*((stage.stageWidth-maxX)-10);
sp.y = -minY+30+Math.random()*((stage.stageHeight-maxY)-10);
}
else{
sp.x = dx;
sp.y = dy;
}
sp.graphics.lineStyle(Number(thickness), uint(lineColor), thickness ? 1 : 0);
if(fillColor != null) sp.graphics.beginFill(uint(fillColor));
sp.graphics.drawPath(path.commands, path.data);
if(fillColor != null) sp.graphics.endFill();
sp.scaleX = sp.scaleY = scale;
}
private function drag(event:MouseEvent):void{
var target:Sprite = event.currentTarget as Sprite;
switch(event.type){
case MouseEvent.MOUSE_DOWN:
container.addChild(target);
target.startDrag();
break;
case MouseEvent.MOUSE_UP:
target.stopDrag();
var mp:Point = new Point(target.x, target.y);
if(Point.distance(op, mp) < 8){
target.removeEventListener(MouseEvent.MOUSE_DOWN, drag);
target.removeEventListener(MouseEvent.MOUSE_UP, drag);
target.x = dx;
target.y = dy;
Tweener.addTween(bmp, {_brightness:0.5, time:0.1, onComplete:function _complete():void{
Tweener.addTween(bmp, {_brightness:0, time:0.3});
if(++comps == container.numChildren) {
Tweener.addTween(container, {alpha:0, time:2.5, onComplete:complete,onCompleteParams:["comps"]});
return;
}
}});
dispatchEvent(new Event("set"));
}
break;
}
event.updateAfterEvent();
}
private function complete(type:String):void{
switch(type){
case "comps":
while(container.numChildren){
var target:Sprite = container.getChildAt(0) as Sprite;
container.removeChild(target);
target = null;
}
container.alpha = 1;
break;
case "remove":
bmp.bitmapData.dispose();
this.alpha = 1;
break;
}
dispatchEvent(new Event(type));
}
public function remove(_time:Number, _delay:Number):void{
Tweener.addTween(this, {alpha:0, time:_time, delay:_delay,onComplete:complete,onCompleteParams:["remove"]});
}
public var scale:Number = 1;
public var dx:Number = 0;
public var dy:Number = 0;
public var op:Point = new Point();
public var comps:uint = 0;
}
//----------
//パネルアイコン
class Icon extends Sprite{
internal var interval:uint = 0;
internal var icon:Sprite = new Sprite();
internal var container:Sprite = new Sprite();
internal var _mask:Sprite = new Sprite();
internal var txt:TextField = new TextField();
internal var format:TextFormat = new TextFormat("Arial", 10, 0x666666, null, null, null, null, null, "center");
internal var filterA:GlowFilter = new GlowFilter(0xFFFFFF, 0.8, 10, 10, 1, 3, true);
internal var filterB:GlowFilter = new GlowFilter(0x333333, 0.75, 8, 8, 2, 3);
internal var filterC:GlowFilter = new GlowFilter(0x333333, 0.5, 3, 3, 2, 3);
private var rollOver:Boolean = false;
public function Icon() {
container.mask = _mask;
_mask.graphics.beginFill(0x000000);
_mask.graphics.drawRoundRect(0, 0, 75, 75, 10);
_mask.graphics.endFill();
txt.defaultTextFormat = format;
txt.y = 75;
txt.width = 75;
txt.height = 16;
txt.wordWrap = true;
txt.mouseEnabled = false;
addChild(txt);
addChild(icon);
icon.alpha = 0.6;
icon.addChild(container);
icon.addChild(_mask);
icon.addEventListener(MouseEvent.CLICK, click);
icon.addEventListener(MouseEvent.ROLL_OVER, function rollOver(event:MouseEvent):void{
icon.alpha = 1;
icon.filters = [filterA];
txt.textColor = 0xDDDDDD;
rollOver = true;
title = name;
});
icon.addEventListener(MouseEvent.ROLL_OUT, function rollOver(event:MouseEvent):void{
icon.alpha = 0.6;
icon.filters = [];
txt.textColor = 0x666666;
rollOver = false;
title = name;
});
}
private function click(event:MouseEvent):void{
if(getTimer()-interval < 250) dispatchEvent(new MouseEvent(MouseEvent.DOUBLE_CLICK));
interval = getTimer();
}
public function set title(str:String):void{
this.name = str;
if(str.length > 8 && !rollOver) str = str.slice(0,8)+"...";
txt.text = str;
}
public function get title():String{
return txt.text;
}
}
//----------
//村
class Village extends Icon{
public function Village() {
super();
}
public function addVillager(obj:Object):void{
var villager:Villager = new Villager();
villager.title = obj.title;
villager.url = obj.contentURL;
villager.load(obj.thumbnailURL);
villagers.push(villager);
villager.addEventListener(ProgressEvent.PROGRESS, progress);
villager.addEventListener(Event.COMPLETE, complete);
}
private function progress(event:ProgressEvent):void{
var bytesLoaded:Number = 0;
var bytesTotal:Number = villagers.length;
for each(var villager:Villager in villagers){
if(villager.bytesLoaded) bytesLoaded += villager.bytesLoaded/villager.bytesTotal;
}
dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS, false, false, bytesLoaded, bytesTotal));
}
private function complete(event:Event):void{
event.target.removeEventListener(Event.COMPLETE, complete);
event.target.removeEventListener(ProgressEvent.PROGRESS, progress);
var target:Villager = event.target as Villager;
if(++comps >= villagers.length) dispatchEvent(event);
if(comps == 1){
var bmd:BitmapData = new BitmapData(event.target.width, event.target.height, true, 0x00FFFFFF);
bmd.draw(target.loader);
container.addChild(new Bitmap(bmd));
}
var index:uint = villagers.indexOf(target);
villagersContainer.addChild(target);
target.x = 85*(index%5)+20;
target.y = 100*(Math.floor(index/5))+40;
target.addEventListener(MouseEvent.DOUBLE_CLICK, function doubleClick(event:MouseEvent):void{
villager = event.currentTarget as Villager;
villagersContainer.dispatchEvent(new Event(Event.SELECT));
});
}
public var comps:uint = 0;
public var villagers:Vector.<Villager> = new Vector.<Villager>();
public var villagersContainer:Sprite = new Sprite();
public var villager:Villager;
}
//----------
//村人
class Villager extends Icon{
public function Villager() {
super();
}
public function load(url:String):void{
loader = new Loader();
loader.load(new URLRequest(url), new LoaderContext(true));
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, function progress(event:ProgressEvent):void{
bytesLoaded = event.bytesLoaded;
bytesTotal = event.bytesTotal;
dispatchEvent(event);
});
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function complete(event:Event):void{
event.target.removeEventListener(Event.COMPLETE, complete);
dispatchEvent(event);
});
container.addChild(loader);
}
public var loader:Loader;
public var url:String;
public var bytesLoaded:Number;
public var bytesTotal:Number;
}
///////////////////////////////////////////
///////////// MenuBar /////////////
///////////////////////////////////////////
//----------
//MenuBar本体
class MenuBar extends Sprite{
private var searchPanel:SearchPanel;
public function MenuBar(width:Number, height:Number) {
this.graphics.beginFill(0x000000, 0.8);
this.graphics.drawRect(0, 0, width, height);
this.graphics.endFill();
searchPanel = new SearchPanel(100, 18);
addChild(searchPanel);
searchPanel.x = 330;
searchPanel.bt.addEventListener(MouseEvent.CLICK, function click(event:MouseEvent):void{
tag = searchPanel.text;
if(tag) dispatchEvent(new Event("search"));
});
topBt.x = 5;
topBt.y = villageBt.y = villagerBt.y = 2.5;
topBt.selected = false;
topBt.label = "村リスト";
addChild(topBt);
}
public function change(target:String, title:Array):void{
switch(target){
case "top":
if(villageBt.parent) removeChild(villageBt);
if(villagerBt.parent) removeChild(villagerBt);
topBt.selected = false;
topBt.label = "村リスト";
break;
case "village":
if(villagerBt.parent) removeChild(villagerBt);
villageBt.x = topBt.x + topBt.width - 10;
villageBt.selected = false;
villageBt.label = " "+title[0];
topBt.selected = true;
topBt.label = "村リスト";
addChild(villageBt);
addChild(topBt);
break;
case "villager":
villageBt.x = topBt.x + topBt.width - 10;
villageBt.selected = true;
villageBt.label = " "+title[0];
villagerBt.x = villageBt.x + villageBt.width - 10;
villagerBt.selected = false;
villagerBt.label = " "+title[1];
topBt.selected = true;
topBt.label = "村リスト";
addChild(villagerBt);
addChild(villageBt);
addChild(topBt);
break;
}
}
public var tag:String;
public var topBt:BreadcrumbList = new BreadcrumbList();
public var villageBt:BreadcrumbList = new BreadcrumbList();
public var villagerBt:BreadcrumbList = new BreadcrumbList();
}
//----------
//パン屑リスト
class BreadcrumbList extends Sprite{
static private const DefaultColor:uint = 0xCCCCCC;
static private const ClickColor:uint = 0x666666;
private var container:Sprite = new Sprite();
private var txt:TextField = new TextField();
private var format:TextFormat = new TextFormat("Arial", 9, null, true);
private var _selected:Boolean = false;
public function BreadcrumbList() {
txt.defaultTextFormat = format;
txt.textColor = DefaultColor;
txt.mouseEnabled = false;
txt.x = 3;
txt.y = 3;
addChild(container);
addChild(txt);
container.addEventListener(MouseEvent.MOUSE_DOWN, function mouseDown(event:MouseEvent):void{
txt.textColor = ClickColor;
container.filters = [new GlowFilter(0x888888, 0.4, 8, 8, 1, 3, true)];
});
container.addEventListener(MouseEvent.MOUSE_UP, function mouseUp(event:MouseEvent):void{
txt.textColor = DefaultColor;
container.filters = [new GlowFilter(0xDDDDDD, 0.4, 8, 8, 1, 3, true)];
});
container.addEventListener(MouseEvent.ROLL_OVER, function rollOver(event:MouseEvent):void{
txt.textColor = DefaultColor;
container.filters = [new GlowFilter(0xDDDDDD, 0.4, 8, 8, 1, 3, true)];
});
container.addEventListener(MouseEvent.ROLL_OUT, function rollOut(event:MouseEvent):void{
txt.textColor = ClickColor;
container.filters = [];
});
}
public function set label(str:String):void{
if(str.length > 20) str = str.slice(0, 18) + "...";
txt.text = str;
txt.width = txt.textWidth+5;
txt.height = txt.textHeight+5;
container.graphics.clear();
container.graphics.lineStyle(1,0x333333);
container.graphics.beginFill(0x000000);
container.graphics.lineTo(txt.width+3, 0);
container.graphics.lineTo(txt.width+15, 10);
container.graphics.lineTo(txt.width+3, 20);
container.graphics.lineTo(0, 20);
container.graphics.endFill();
}
public function set selected(val:Boolean):void{
_selected = val;
container.mouseEnabled = val;
txt.textColor = !val ? DefaultColor : ClickColor;
}
public function get selected():Boolean{
return _selected;
}
}
//----------
//検索バー
class SearchPanel extends Sprite{
static private const DefaultMessage:String = "他の村を探す";
static private const DefaultColor:uint = 0x666666;
static private const InputColor:uint = 0xAAAAAA;
static private const EnabledColor:uint = 0x000000;
private var txt:TextField = new TextField();
private var format:TextFormat = new TextFormat("Arial", 9);
private var icon:Shape = new Shape();
public function SearchPanel(width:Number, height:Number) {
txt.defaultTextFormat = format;
txt.textColor = DefaultColor;
txt.background = true;
txt.backgroundColor = 0x333333;
txt.text = DefaultMessage;
txt.width = width;
txt.height = txt.textHeight+5;
txt.type = "input";
txt.filters = [new GlowFilter(0x000000, 0.6, 6, 6, 1, 3, true)];
txt.y = 5;
bt.x = width+4;
bt.y = 2.5;
icon.x = 35/2;
icon.y = 25/2;
icon.rotation = -45;
buttonSkin("mouseUp");
addChild(txt);
addChild(bt);
bt.addChild(icon);
txt.addEventListener(MouseEvent.CLICK, input);
bt.addEventListener(MouseEvent.MOUSE_DOWN, function mouseDown(event:MouseEvent):void{
bt.filters = [new GlowFilter(0x888888, 0.4, 8, 8, 1, 3, true)];
buttonSkin(event.type);
});
bt.addEventListener(MouseEvent.MOUSE_UP, function mouseUp(event:MouseEvent):void{
bt.filters = [new GlowFilter(0xDDDDDD, 0.4, 8, 8, 1, 3, true)];
buttonSkin(event.type);
});
bt.addEventListener(MouseEvent.ROLL_OVER, function rollOver(event:MouseEvent):void{
bt.filters = [new GlowFilter(0xDDDDDD, 0.4, 8, 8, 1, 3, true)];
});
bt.addEventListener(MouseEvent.ROLL_OUT, function rollOut(event:MouseEvent):void{
bt.filters = [];
buttonSkin(event.type);
});
}
private function input(event:MouseEvent):void{
txt.textColor = InputColor;
stage.addEventListener(MouseEvent.CLICK, function click(event:MouseEvent):void{
if(event.target == txt) return;
txt.textColor = DefaultColor;
stage.removeEventListener(MouseEvent.CLICK, click);
if(!txt.text) txt.text = DefaultMessage;
});
txt.text = text;
}
private function buttonSkin(type:String):void{
var iconColor:uint;
switch(type){
case MouseEvent.MOUSE_DOWN:
iconColor = 0x333333;
break;
case MouseEvent.ROLL_OUT:
case MouseEvent.MOUSE_UP:
iconColor = 0x666666;
break;
}
bt.graphics.clear();
bt.graphics.beginFill(0x000000);
bt.graphics.drawRect(0, 0, 30, 20);
bt.graphics.endFill();
icon.graphics.clear();
icon.graphics.lineStyle(1.5, iconColor);
icon.graphics.drawCircle(0, -4.5, 4);
icon.graphics.moveTo(-0.5, -0.5);
icon.graphics.lineTo(-0.5, 4);
}
public var bt:Sprite = new Sprite();
public function get text():String{
return txt.text == DefaultMessage ? "" : txt.text;
}
}
///////////////////////////////////////////
/////////// その他Panel ///////////
///////////////////////////////////////////
//----------
//セットアップパネル
class SetUpPanel extends Sprite{
static private const LABEL:String = "Make a Face";
private var container:Sprite = new Sprite();
private var loadedContainer:Sprite = new Sprite();
private var maskSprite:Sprite = new Sprite();
private var normalLabel:TextField = new TextField();
private var loadedLabel:TextField = new TextField();
private var txt:TextField = new TextField();
private var format:TextFormat = new TextFormat("Arial", 30, null, true, null, null, null, null, "center");
public function SetUpPanel(parent:DisplayObjectContainer) {
parent.addChild(this);
init();
}
private function init():void{
this.graphics.beginFill(0x000000);
this.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
this.graphics.endFill();
normalLabel.defaultTextFormat = loadedLabel.defaultTextFormat = format;
normalLabel.textColor = 0x545454;
loadedLabel.textColor = 0xDDDDDD;
normalLabel.text = loadedLabel.text = LABEL;
normalLabel.width = loadedLabel.width = normalLabel.textWidth+5;
normalLabel.height = loadedLabel.height = normalLabel.textHeight;
normalLabel.mouseEnabled = loadedLabel.mouseEnabled = false;
format.size = 14;
txt.defaultTextFormat = format;
txt.textColor = 0xAAAAAA;
txt.text = "0%";
txt.x = loadedLabel.x;
txt.y = loadedLabel.height+3;
txt.width = loadedLabel.width;
txt.height = txt.textHeight+3;
txt.mouseEnabled = false;
loadedContainer.mask = maskSprite;
maskSprite.y = loadedLabel.height-3;
addChild(container);
container.addChild(normalLabel);
container.addChild(txt);
container.addChild(loadedContainer);
loadedContainer.addChild(loadedLabel);
loadedContainer.addChild(maskSprite);
container.x = (stage.stageWidth-container.width)/2;
container.y = (stage.stageHeight-container.height)/2;
}
public function set value(val:Number):void{
val = Math.min(val, 1);
maskSprite.graphics.clear();
maskSprite.graphics.beginFill(0xFFFFFF,0.4);
maskSprite.graphics.drawRect(0, -val*(maskSprite.y-7), loadedLabel.width, val*(maskSprite.y-7));
maskSprite.graphics.endFill();
txt.text = String(Math.round(val*100)+"%");
}
public function get value():Number{
return maskSprite.height/maskSprite.y;
}
}
//----------
//メッセージパネル
class MessagePanel extends Sprite{
private var txt:TextField = new TextField();
private var format:TextFormat = new TextFormat("Arial", 20, 0xDDDDDD, true);
private var flipIcon:Shape = new Shape();
private var message:Array;
private var timer:Timer = new Timer(100);
private var _parent:DisplayObjectContainer;
public function MessagePanel(parent:DisplayObjectContainer) {
_parent = parent;
init();
}
private function init():void{
this.graphics.beginFill(0x000000, 0);
this.graphics.drawRect(0, 0, 465, 465);
this.graphics.endFill();
this.graphics.lineStyle(5, 0xDDDDDD);
this.graphics.beginFill(0x000000);
this.graphics.drawRoundRect(0, 315, 465, 150, 10);
this.graphics.endFill();
flipIcon.graphics.beginFill(0xDDDDDD);
flipIcon.graphics.lineTo(10, -15);
flipIcon.graphics.lineTo(-10, -15);
flipIcon.graphics.endFill();
flipIcon.x = 440;
flipIcon.y = 460;
txt.defaultTextFormat = format;
txt.x = 20;
txt.y = 335;
txt.width = 425;
txt.height = 120;
txt.mouseEnabled = false;
txt.wordWrap = true;
addChild(txt);
this.addEventListener(MouseEvent.CLICK, click);
timer.addEventListener(TimerEvent.TIMER, textAnimation);
}
public function inputMessages(...messages):void{
txt.text = "";
this.messages = this.message = [];
_parent.addChild(this);
if(messages[0] is Array){
this.messages = messages[0].concat();
}
else {
this.messages = messages.concat();
}
message = this.messages.shift().toString().split("");
timer.start();
}
private function textAnimation(event:TimerEvent):void{
if(message.length){
txt.appendText(message.shift());
}else{
timer.stop();
flipAnimation();
}
}
private function click(event:MouseEvent):void{
if(message.length){
while(message.length){
txt.appendText(message.shift());
}
}else if(messages.length){
txt.text = "";
message = messages.shift().toString().split("");
timer.start();
}else{
dispatchEvent(new Event(Event.COMPLETE));
timer.stop();
_parent.removeChild(this);
}
}
private function flipAnimation():void{
if(timer.running) {
if(flipIcon.parent) removeChild(flipIcon);
return;
}
if(this.parent){
addChild(flipIcon);
Tweener.addTween(flipIcon, {y:flipIcon.y == 462 ? 460 : 462, time:0.2, delay:0.1, onComplete:flipAnimation});
}
}
public var messages:Array;
}
///////////////////////////////////////////
///////////// Web関連 /////////////
///////////////////////////////////////////
//----------
//MediaRSS
class MediaRSS extends EventDispatcher{
private var feed:String = "http://api.flickr.com/services/feeds/photos_public.gne?format=rss_200&tags=";
private var media:Namespace = new Namespace("http://search.yahoo.com/mrss/");
public function MediaRSS() {}
private function mediaRSSReader():void{
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, function load(event:Event):void {
urlLoader.removeEventListener(Event.COMPLETE, load);
setContentsInfo(XML(urlLoader.data));
});
urlLoader.load(new URLRequest(feed+tag));
}
private function setContentsInfo(rss:XML):void{
//タグが見つからなかった場合
if(!rss..item[0]) {
dispatchEvent(new Event("none"));
return;
}
for each(var xml:XML in rss..item){
var item:Object = new Object();
item.contentURL = xml.media::content.@url;
item.title = xml.media::title;
item.tags = xml.media::category.split(" ");
item.thumbnailURL = xml.media::thumbnail.@url;
items.push(item);
}
dispatchEvent(new Event("find"));
}
//検索
public function search(tag:String = ""):void{
if(tag) this.tag = tag;
items = new Vector.<Object>();
mediaRSSReader();
}
//格納変数
public var items:Vector.<Object>;
//public var contents:Array;
//検索タグ
public var tag:String = "";
//public var comps:uint = 0;
}
//----------
//WebAPI
class WebAPI extends EventDispatcher{
public static var URL:String = "http://detectface.com/api/detect";
public function WebAPI(){}
public function detectFace(source:BitmapData):void{
//画像の準備
var jpegEncoder:JPGEncoder = new JPGEncoder(40);
var data:ByteArray = jpegEncoder.encode(source);
var request:URLRequest = new URLRequest(URL);
request.data = data;
request.method = URLRequestMethod.POST;
request.contentType = "image/jpeg";
loaded = true;
var loader:URLLoader = new URLLoader(request);
loader.addEventListener(Event.COMPLETE, complete);
loader.addEventListener(IOErrorEvent.IO_ERROR, ioError);
}
private function ioError(event:IOErrorEvent):void{
loaded = false;
dispatchEvent(event);
}
private function complete(event:Event):void{
data = event.target.data;
loaded = false;
dispatchEvent(event);
}
public var data:*;
public var loaded:Boolean = false;
}
//----------
//顔認識>>GraphicsPath変換
class FacialPath {
public function FacialPath(faceInfo:XMLList = null) {
if(faceInfo) getFacialPath(faceInfo);
}
public function getFacialPath(faceInfo:XMLList):void{
_facePath = getPath(faceInfo, 10, "F");
_mousePath = getPath(faceInfo, 9, "M");
_nosePath = getPath(faceInfo, 4, "N", true);
_rightEyePath = getPath(faceInfo, 6, "ER");
_leftEyePath = getPath(faceInfo, 6, "EL");
_rightBrowPath = getPath(faceInfo, 6, "BR");
_leftBrowPath = getPath(faceInfo, 6, "BL");
}
//パスの計算
static private function getPath(faceInfo:XMLList, count:uint, id:String, curve:Boolean = false):GraphicsPath{
var path:GraphicsPath = new GraphicsPath();
var positive:Boolean;
for(var i:uint = 1; i <= count; i++){
var point:XMLList = faceInfo.point.(@id.toString() === String(id+i));
if(i == 1){
path.moveTo(point.@x,point.@y);
}
else{
if(curve){
positive = (path.data[path.data.length-2]-point.@x)*(path.data[path.data.length-1]-point.@y) > 0 ? true : false;
path.curveTo(positive ? path.data[path.data.length-2] : point.@x,
positive ? point.@y : path.data[path.data.length-1],
point.@x, point.@y);
}
else{
path.lineTo(point.@x, point.@y);
}
}
}
if(curve){
positive = (path.data[path.data.length-2]-path.data[0])*(path.data[path.data.length-1]-path.data[1]) > 0 ? true : false;
path.curveTo(positive ? path.data[path.data.length-2] : path.data[0],
positive ? path.data[1] : path.data[path.data.length-1],
path.data[0], path.data[1]);
}
else {
path.lineTo(path.data[0], path.data[1]);
}
return path;
}
//プロパティ
public var _facePath:GraphicsPath;
public var _mousePath:GraphicsPath;
public var _nosePath:GraphicsPath;
public var _rightEyePath:GraphicsPath;
public var _leftEyePath:GraphicsPath;
public var _rightBrowPath:GraphicsPath;
public var _leftBrowPath:GraphicsPath;
}