flash on 2011-3-15

by tepe
import com.google.maps.MapMouseEvent;
♥1 | Line 359 | Modified 2011-03-15 15:47:39 | MIT License
play

ActionScript3 source code

/**
 * Copyright tepe ( http://wonderfl.net/user/tepe )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/eVXO
 */

<?xml version="1.0" encoding="utf-8"?>
<!-- forked from Fake's forked from: forked from: Google Maps API test -->
<!-- forked from Fake's forked from: Google Maps API test -->
<!-- forked from Fake's Google Maps API test -->
<!--
RTMFPによるマルチプレイヤー対応版
色々と実装途中
Google Maps APIがproprietaryなので、GPLに変更出来ない。
テストコードからforkしてるので、ライセンスが変更出来ない。
自分のコードからforkしてるのにライセンスが変更出来ないのはおかしいんだけど…。

上記を踏まえた上で、
wonderfl上の表示では、All rights reserved になっていますが、ライセンスは CDDL にします。
I provide this code as CDDL.
English:
http://opensource.org/licenses/cddl1.php
日本語訳
http://sourceforge.jp/projects/opensource/wiki/licenses%2FCommon_Development_and_Distribution_License
FAQ(日本語)
http://hub.opensolaris.org/bin/view/Project+jp/licensing_faq
Copyright (c) 2010 Fake

以下、簡単にCDDLの説明:
CDDLは、コピーレフト的にはLGPLより更に弱いものとなってますので、
静的/動的に関わらずリンクされるライブラリに対してのソース公開を要求しません。
但し、本ソースコードに関してはコピーレフトとなりますので、ソースの公開が必要となります。
wonderfl内でのforkに関しては、自動的にソースが公開されますので、特に気にする必要はありません。

2010/11/05 Fake    クライアントのIPを元に初期位置を決めるようにした。
-->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<maps:Map xmlns:maps="com.google.maps.*" id="map" mapevent_mapready="onMapReady(event)" x="0" y="20" 
  width="100%" height="100%" key="ABQIAAAALF5oQPABFhnvOj2NwrgHKhSO5wqdqdHVqPB8sVJhBj86bhrVXRQGr4mbD7pCuDIQokA-caR3k3Xn1Q"/>
<mx:Script>
    <![CDATA[
   
    import com.google.maps.LatLng;
    import com.google.maps.Map;
    import com.google.maps.MapEvent;
    import com.google.maps.MapType;
    import com.google.maps.overlays.*;
    import com.google.maps.styles.*;
    import com.google.maps.InfoWindowOptions;
    import com.google.maps.MapAction;
    import com.google.maps.MapMouseEvent;
    import com.google.maps.services.*;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    import flash.utils.Timer;
    import flash.events.TimerEvent;
    import flash.events.NetStatusEvent;
    import flash.net.*;
    
    private var debugout:TextField;
    private var marker:Marker;
    private var myicon:Loader;
    private var mypt:Point;
    private var moveTarget:Point;
    private var MOVE_STEP:Number = 0.001;
    private var cmdline:TextField;
    private var balloon:TextField;
    private var iconurl:String;

    private var moveTimer:Timer;
    private var sendTimer:Timer;

    private var nodes:Object;
    private var gs:GroupSpecifier;
    private var nc:NetConnection;
    private var group:NetGroup;
    
    private var CMD_MOVE:String = "move";
    private var CMD_ICON:String = "icon";
    private var CMD_DISCO:String = "disco";

    private function onMapReady(event:Event):void {
        debugout = new TextField();
        debugout.x = 50;
        debugout.y = 50;
        debugout.autoSize = TextFieldAutoSize.LEFT;
        debugout.background = false;
        debugout.border = true;
        debugout.backgroundColor = 0x000000;
        debugout.textColor = 0x0000FF;
        //parent.addChild(debugout);
        debugout.text = "hoge";
        // init rtmfp group spec
        gs = new GroupSpecifier("net.wonderfl.fake.wonderflworld.test");
        gs.postingEnabled = true;
        gs.ipMulticastMemberUpdatesEnabled = true;
        gs.multicastEnabled = true;
        gs.objectReplicationEnabled = true;
        gs.routingEnabled = true;
        gs.serverChannelEnabled = true;
        // init rtmfp connection
        nc = new NetConnection();
        nc.addEventListener(NetStatusEvent.NET_STATUS, procNetStatus);
        nc.connect("rtmfp://p2p.rtmfp.net/445d9931dfac67103408ae5f-ad98e28e2386/");
        
        nodes = new Object();
    }
    private function initWorld(latlng:LatLng = null):void {
        if (latlng == null) {
            latlng = new LatLng(40.736072,-73.992062);
        }
        this.map.disableDragging();
        this.map.disableContinuousZoom();
        this.map.disableControlByKeyboard();
        this.map.disableScrollWheelZoom();
        this.map.setDoubleClickMode(MapAction.ACTION_NOTHING);
        this.map.setCenter(latlng, 14, MapType.NORMAL_MAP_TYPE);
        
        myicon = new Loader();
        myicon.contentLoaderInfo.addEventListener(Event.COMPLETE, onIconLoaded);
        myicon.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIconLoadError);
        iconurl = "http://maps.google.co.jp/mapfiles/ms/icons/red-dot.png";
        myicon.load(new URLRequest(iconurl), new LoaderContext(true));
        marker = new Marker(latlng, new MarkerOptions({
            icon : myicon
        }));
        this.map.addOverlay(marker);
        //marker.openInfoWindow(new InfoWindowOptions({content: "I am Omochi."}));
        
        cmdline = new TextField();
        cmdline.x = 0;
        cmdline.y = 0;
        cmdline.width = 200;
        cmdline.height = 20;
        cmdline.border = true;
        cmdline.type = TextFieldType.INPUT;
        cmdline.multiline = false;
        cmdline.maxChars = 140;
        cmdline.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDownCmdline);
        parent.addChild(cmdline);

        balloon = new TextField();
        balloon.border = true;
        balloon.background = true;
        balloon.backgroundColor = 0xFFFFFF;
        balloon.textColor = 0x000000;
        balloon.width = 200;
        balloon.height = 20;
        balloon.autoSize = TextFieldAutoSize.LEFT;
        balloon.wordWrap = true;
        balloon.text = "guest";
        var p:Point = map.fromLatLngToViewport(latlng);
        balloon.x = p.x - 100;
        balloon.y = p.x - 30;
        parent.addChild(balloon);
        
        this.map.addEventListener(MapMouseEvent.MOUSE_DOWN, onMouseClickMap);
        myicon.addEventListener(MouseEvent.CLICK, onMouseClick);
        
        mypt = new Point(latlng.lng(), latlng.lat());
        moveTarget = mypt.clone();
        
        moveTimer = new Timer(200, 0);
        moveTimer.addEventListener(TimerEvent.TIMER, procMoveTimer);
        moveTimer.start();
        
        sendTimer = new Timer(5000, 0);
        sendTimer.addEventListener(TimerEvent.TIMER, procSendTimer);
        sendTimer.start();
    }
    
    private function onIconLoaded(e:Event):void {
        var loader:Loader = e.target.loader;
        loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onIconLoaded);
        loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onIconLoadError);
        loader.width = 32;
        loader.height = 32;
    }

    private function onIconLoadError(e:Event):void {
        //marker.openInfoWindow(new InfoWindowOptions({content: "icon load error"}));
        var loader:Loader = e.target.loader;
        loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onIconLoaded);
        loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onIconLoadError);
        iconurl = "http://maps.google.co.jp/mapfiles/ms/icons/red-dot.png";
        loader.scaleX = 1.0;
        loader.scaleY = 1.0;
        loader.load(new URLRequest(iconurl), new LoaderContext(true));
    }

    private function onMouseClickMap(e:MapMouseEvent):void {
        moveTarget.x = e.latLng.lng();
        moveTarget.y = e.latLng.lat();
    }
    
    private function onMouseClick(e:MouseEvent):void {
        //marker.openInfoWindow(new InfoWindowOptions({content: e.toString()}));
    }
    
    private function procSendTimer(e:TimerEvent):void {
        group.post({
            cmd: CMD_MOVE,
            id: nc.nearID,
            point: mypt,
            label: balloon.text,
            iconurl: iconurl
        });
    }
    
    private function procMoveTimer(e:TimerEvent):void {
        var latlng:LatLng;
        var p:Point;
        // draw others
        for (var id:String in nodes) {
            if (id in nodes) {
                var node:Object = nodes[id];
                latlng = new LatLng(node.point.y, node.point.x);
                node.marker.setLatLng(latlng);
/*
                if (node.label && map.getLatLngBounds().containsLatLng(latlng)) {
                    //node.marker.openInfoWindow(new InfoWindowOptions({content: node.label}));
                } else {
                    //node.marker.closeInfoWindow();
                }
*/
                p = map.fromLatLngToViewport(latlng);
                node.balloon.x = p.x - 100;
                node.balloon.y = p.y - 30;
            }

        }
        
        // draw self
        if (moveTarget.equals(mypt)) {
            return;
        }
        if (Point.distance(moveTarget, mypt) <= MOVE_STEP) {
            mypt = moveTarget.clone();
        } else {
            p = moveTarget.subtract(mypt);
            p.normalize(MOVE_STEP);
            mypt.offset(p.x, p.y);
        }
        group.post({
            cmd: CMD_MOVE,
            id: nc.nearID,
            point: mypt,
            label: null,
            iconurl: iconurl
        });
        latlng = new LatLng(mypt.y, mypt.x);
        this.map.setCenter(latlng, 14, MapType.NORMAL_MAP_TYPE);
        marker.setLatLng(latlng);
        p = map.fromLatLngToViewport(latlng);
        balloon.x = p.x - 100;
        balloon.y = p.x - 30;
        //marker.openInfoWindow(new InfoWindowOptions({content: latlng.toString()}));
    }
    
    private function onKeyDownCmdline(e:KeyboardEvent):void {
        if (e.keyCode == Keyboard.ENTER && cmdline.text != "") {
            var r:RegExp = /^\/([a-z]+) +(.*)$/g;
            var res:Object = r.exec(cmdline.text);
            if (res == null) {
                group.post({
                    cmd: CMD_MOVE,
                    id: nc.nearID,
                    point: mypt,
                    label: cmdline.text
                });
                //marker.openInfoWindow(new InfoWindowOptions({content: cmdline.text}));
                balloon.text = cmdline.text;
                cmdline.text = "";
                return;
            }
            switch (res[1]) {
                case "icon":
                    myicon.contentLoaderInfo.addEventListener(Event.COMPLETE, onIconLoaded);
                    myicon.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIconLoadError);
                    iconurl = res[2];
                    myicon.load(new URLRequest(iconurl), new LoaderContext(true));
                    break;
                case "tp":
                    var ar:Array = res[2].split(/, */, 2);
                    var x:Number = parseFloat(ar[0]);
                    var y:Number = parseFloat(ar[1]);
                    if (isNaN(x) || isNaN(y)) {
                        var geoc:ClientGeocoder = new ClientGeocoder();
                        geoc.addEventListener(GeocodingEvent.GEOCODING_SUCCESS, onGeocodeSuccess);
                        geoc.geocode(res[2]);
                        break;
                    }
                    moveTarget.y = x;
                    moveTarget.x = y;
                    mypt = moveTarget.clone();
                    mypt.x += 0.0001
                    break;
/*
                case "move":
                    var geoc:ClientGeocoder = new ClientGeocoder();
                    geoc.addEventListener(GeocodingEvent.GEOCODING_SUCCESS, onGeocodeSuccess);
                    geoc.geocode(res[2]);
                    break;
*/
                default:
                    //marker.openInfoWindow(new InfoWindowOptions({content: "unknown command"}));
                    break;
            }

            cmdline.text = "";
        }
    }
    
    private function onGeocodeSuccess(e:GeocodingEvent):void {
        if (e.response.placemarks.length == 0) {
            return;
        }
        var latlng:LatLng = e.response.placemarks[0].point;
        //marker.openInfoWindow(new InfoWindowOptions({content: latlng.toString()}));
        moveTarget.y = latlng.lat();
        moveTarget.x = latlng.lng();
        mypt = moveTarget.clone();
        mypt.x += MOVE_STEP * 0.1;
    }

    private function procNetStatus(e:NetStatusEvent):void {
        //debugout.appendText(e.info.code + "\n");
        var node:Object;
        switch (e.info.code) {
            case "NetConnection.Connect.Success":
                group = new NetGroup(nc, gs.groupspecWithAuthorizations());
                group.addEventListener(NetStatusEvent.NET_STATUS, procNetStatus);
                break;
            case "NetGroup.Connect.Success":
                var urlloader:URLLoader = new URLLoader();
                urlloader.addEventListener(Event.COMPLETE, function (e:Event):void {
                    var xml:XML = new XML(e.target.data);
                    initWorld(new LatLng(parseFloat(xml.latitude), parseFloat(xml.longitude)));
                })
                urlloader.addEventListener(IOErrorEvent.IO_ERROR, function (e:Event):void {
                    initWorld();
                });
                urlloader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
                    initWorld();
                });
                urlloader.load(new URLRequest("http://www.onflex.org/geo/xml/"));
                break;
            case "NetGroup.Neighbor.Connect":
                break;
            case "NetGroup.Neighbor.Disconnect":
                // send notice to group when neighbor disconnected
                if (e.info.peerID in nodes) {
                    map.removeOverlay(nodes[e.info.peerID].marker);
                    parent.removeChild(nodes[e.info.peerID].balloon);
                    delete nodes[e.info.peerID];
                    group.post({
                        cmd: CMD_DISCO,
                        id: e.info.peerID
                    });
                }
                break;
            case "NetGroup.Posting.Notify":
                var obj:Object = e.info.message;
                switch (obj.cmd) {
                    case CMD_MOVE:
                        if (!(obj.id in nodes)) {
                            nodes[obj.id] = new Object();
                            node = nodes[obj.id];
                            node.icon = new Loader();
                            //node.icon.node = node;
                            node.iconurl = null;
                            node.marker = new Marker(new LatLng(obj.point.y, obj.point.x), new MarkerOptions({
                                strokeStyle: new StrokeStyle({color: 0x987654}),
                                fillStyle: new FillStyle({color: 0x223344, alpha: 0.8}),
                                radius: 12,
                                hasShadow: true
                            }));
                            map.addOverlay(node.marker);
                            node.point = new Point();
                            node.balloon = new TextField();
                            node.balloon.border = true;
                            node.balloon.background = true;
                            node.balloon.backgroundColor = 0xFFFFFF;
                            node.balloon.textColor = 0x000000;
                            node.balloon.width = 200;
                            node.balloon.height = 20;
                            node.balloon.autoSize = TextFieldAutoSize.LEFT;
                            node.balloon.wordWrap = true;
                            parent.addChild(node.balloon);
                            node.label = null;
                        }
                        node = nodes[obj.id];
                        node.point.x = obj.point.x;
                        node.point.y = obj.point.y;
                        if (obj.label != null) {
                            node.label = new String(obj.label);
                            node.balloon.text = new String(node.label);
                        }
                        if (obj.iconurl && obj.iconurl != node.iconurl) {
                            node.icon.contentLoaderInfo.addEventListener(Event.COMPLETE, onIconLoaded);
                            //node.icon.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIconLoadError);
                            node.iconurl = obj.iconurl;
                            node.icon.load(new URLRequest(node.iconurl), new LoaderContext(true));
                            node.marker.setOptions(new MarkerOptions({
                                icon : node.icon
                            }));
                        }
                        break;
                    case CMD_ICON:
                        break;
                    case CMD_DISCO:
                        if (obj.id in nodes) {
                            map.removeOverlay(nodes[obj.id].marker);
                            parent.removeChild(nodes[obj.id].balloon);
                            delete nodes[obj.id];
                        }
                        break;
                }
                break;
        }
    }

    ]]>
</mx:Script>
</mx:Application>