顯示具有 練習作品 標籤的文章。 顯示所有文章
顯示具有 練習作品 標籤的文章。 顯示所有文章


Flash P2P 研究

0 意見

Flash 10及AIR 1.5支援P2P連線,這種通訊技術叫做Real-Time Media Flow Protocol (RTMFP),跟FMS(Flash Media Service)的RTMP不同,RTMFP是架構在UDP層,允許點對點連線,使用者只需連到RTMFP-capable 伺服器即可,目前Adobe有提供免費的伺服器─Stratus,透過Stratus我們可簡單做出VOIP或電視電話的功能,當然也能運用在遊戲上。

2009-08-21_184655.png

比較兩種技術,RTMP是透過伺服器溝通,所有的訊息都需經過伺服器,而RTMFP只需透過伺服器建立連線,之後的訊息交換以兩台電腦為主,且Stratus允許本地及NAT連線,在一般網路環境都可正常運作。

Flash P2P遊戲:real time mill

Stratus:http://labs.adobe.com/technologies/stratus/

教學影片:http://www.flashrealtime.com/tuts/p2p-in-flash.html

教學網站:http://www.flashrealtime.com/basics-of-p2p-in-flash/

RTMFP FAQ:http://www.scribd.com/doc/3798516/Flash-Player-10-RTMFP-FAQ-070208



[練習] Google Map API

0 意見

2009-04-28_225438.jpg

最近在看Google Map API,寫個簡單範例練習,點選新增可增加Marker至正中心,Marker可拖曳,點擊列表可移動地圖到指定Marker

程式原始碼

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
xmlns:maps="com.google.maps.*"
creationComplete="main();"
width="900" height="500"
enabled="false"
backgroundColor="0xFFFFFF" >
<mx:Script>
<![CDATA[
import mx.controls.dataGridClasses.DataGridColumn;
import mx.effects.Glow;
import mx.events.ListEvent;
import mx.controls.Alert;
import mx.rpc.events.FaultEvent;
import mx.managers.FocusManager;
import mx.events.FlexEvent;
import mx.rpc.events.ResultEvent;
import mx.collections.ArrayCollection;
import mx.controls.ColorPicker;
import mx.controls.Button;
import com.google.maps.overlays.MarkerOptions;
import com.google.maps.overlays.Marker;
import com.google.maps.controls.OverviewMapControl;
import com.google.maps.controls.ScaleControl;
import com.google.maps.controls.MapTypeControl;
import com.google.maps.controls.PositionControl;
import com.google.maps.controls.ZoomControl;
import com.google.maps.MapType;
import com.google.maps.LatLng;
import com.google.maps.MapOptions;
import com.google.maps.MapEvent;

[Bindable]
private var currentLatlng:LatLng;

[Bindable]
private var currentMarkers:ArrayCollection = new ArrayCollection([]);

private static const TAIWAN_LATLNG:LatLng = new LatLng(23.793120080412926, 121.12177848815918);
private static const DEFAULT_TOOLTIP_MESSAGE:String = "請輸入提示名稱";

private var iconArr:Array = [];

private function main():void
{
cursorManager.setBusyCursor();
toolTipMsg.text = DEFAULT_TOOLTIP_MESSAGE;
}

/**
* map生成完畢,加入控制項
*/
private function mapReadyhandler(event:MapEvent):void
{
var map:Map = Map(event.currentTarget);

//取消地形模式,mapTypeControl不會顯示
myMap.removeMapType(MapType.PHYSICAL_MAP_TYPE);

map.addControl(new ZoomControl());
map.addControl(new PositionControl());
map.addControl(new MapTypeControl());
map.addControl(new ScaleControl());
map.addControl(new OverviewMapControl());

myMap.addEventListener(MouseEvent.MOUSE_UP, function():void{updatePos();});

updatePos();
this.enabled = true;
cursorManager.removeBusyCursor();
}

/**
* map生成時設定初值
*/
private function mapPreInitHandler(event:MapEvent):void
{
var mapOption:MapOptions = new MapOptions();
mapOption.zoom = 8;
mapOption.center = TAIWAN_LATLNG;
mapOption.mapType = MapType.NORMAL_MAP_TYPE;

myMap.setInitOptions(mapOption);
}

private function updatePos():void
{
currentLatlng = myMap.getCenter();
}

private function addMarkerHandler(event:MouseEvent):void
{
var markerOptions:MarkerOptions = new MarkerOptions();
var iconClass:Class = house2;
var icon:DisplayObject = new iconClass();

icon.scaleX = icon.scaleY = .5;

markerOptions.icon = icon;
markerOptions.iconAlignment = MarkerOptions.ALIGN_HORIZONTAL_CENTER;
markerOptions.iconOffset = new Point(icon.width * .5, -icon.height * .5);
markerOptions.tooltip = toolTipMsg.text;
markerOptions.hasShadow = true;
markerOptions.draggable = true;

var marker:Marker = new Marker(currentLatlng, markerOptions);
myMap.addOverlay(marker);

currentMarkers.addItem({tooltip:toolTipMsg.text, marker:marker});
}

private function removeMarkerHandler(event:MouseEvent):void
{
var selectedItem:Object = markerList.selectedItem;
myMap.removeOverlay(selectedItem.marker);

currentMarkers.removeItemAt(currentMarkers.getItemIndex(selectedItem));
}

private function markerListClickHandler(event:ListEvent):void
{
var obj:Object = markerList.selectedItem;
var marker:Marker = obj.marker as Marker;

myMap.panTo(marker.getLatLng());
}

]]>
</mx:Script>
<mx:Style source="assets/css/style.css"/>

<mx:Label id="titleLbl"
styleName="titleStyle"
x="10" y="10"
text="Flex Google Map"
filters="{[new DropShadowFilter(0)]}"/>
<mx:HRule x="0" y="47" width="100%"/>

<mx:DataGrid id="markerList"
dataProvider="{currentMarkers}"
itemClick="markerListClickHandler(event)"
x="10" y="151" width="271" height="334"
fontSize="12">
<mx:columns>
<mx:DataGridColumn headerText="提示文字" dataField="tooltip"/>
</mx:columns>
</mx:DataGrid>

<mx:Button id="addBtn"
x="174" y="119"
label="新增"
click="addMarkerHandler(event)" fontWeight="normal" fontSize="12"/>

<mx:Button id="removeBtn"
x="232" y="119"
label="刪除"
enabled="{markerList.selectedIndex != -1}"
click="removeMarkerHandler(event)"
fontWeight="normal" fontSize="12"/>

<mx:Label text="緯度:{currentLatlng.lat()}" x="10" y="57" fontSize="12" selectable="true" width="272"/>
<mx:Label text="經度:{currentLatlng.lng()}" x="10" y="85" fontSize="12" selectable="true" width="272"/>

<mx:Canvas x="290" y="57" width="600" height="433" backgroundColor="#FFFFFF">
<!-- language = null 時會取瀏覽器語系-->
<maps:Map id="myMap"
key="ABQIAAAAkOcVHiQqdmsV1CsmWiycyxTJiUO4stL7mkJ7l2ZLr3ZW-k6zdxQnI6k1A5AlNMwoBRFxHhmOwAektQ"
mapevent_mapready="mapReadyhandler(event)"
mapevent_mappreinitialize="mapPreInitHandler(event)"
language=""
right="10" left="10" top="10" bottom="10"/>
</mx:Canvas>

<mx:TextInput id="toolTipMsg"
enter="addMarkerHandler(null)"
focusIn="toolTipMsg.text = ''"
x="10" y="119" width="156"
fontSize="12"/> </mx:Application>


官方教學:http://code.google.com/intl/zh-TW/apis/maps/documentation/flash/intro.html

GoogleCode:http://code.google.com/intl/zh-TW/apis/maps/documentation/flash/



[練習]3D物理引擎 jiglibflash

0 意見

2009-04-19_011913.jpg

jiglibflash是為Flash 3D開發的物理引擎,支援常見的3D引擎,包括PV3D、Away3D,由於寫起來是直接使用3D座標,所以撰寫方便,也支援不規則模形的物件,比我之前看過的WOW引擎功能多很多,但缺點還是太吃CPU資源

package {
import flash.display.Bitmap;
import flash.events.Event;
import flash.events.MouseEvent;

import jiglib.math.JNumber3D;
import jiglib.physics.PhysicsSystem;
import jiglib.physics.RigidBody;
import jiglib.physics.constraint.JConstraintWorldPoint;
import jiglib.plugin.papervision3d.Papervision3DPhysics;

import org.papervision3d.core.geom.renderables.Vertex3D;
import org.papervision3d.core.math.Number3D;
import org.papervision3d.core.math.Plane3D;
import org.papervision3d.core.utils.Mouse3D;
import org.papervision3d.events.InteractiveScene3DEvent;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.materials.BitmapMaterial;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.view.BasicView;
import org.papervision3d.view.layer.ViewportLayer;
import org.papervision3d.view.layer.util.ViewportLayerSortMode;
       /**
* 
* @author GD
* 
*/     
[SWF (width = "950", height = "500", frameRate = "30", backgroundColor = "0xFFFFFF")]
public class Main extends BasicView
{
private static const WORLD_WIDTH:uint = 950;

private var physics:Papervision3DPhysics;
private var pointLight:PointLight3D;

private var mouse3D:Mouse3D;
private var currentBody:RigidBody;
private var planeToDragOn:Plane3D;
private var dragConstraint:JConstraintWorldPoint

[Embed (source = "assets/floor.jpg")]
private var floorAsset:Class;

public function Main()
{
super(950, 500, true, true);

initPV3D();
initJiglib();

createFloor();
createBox(5);

stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);                    
startRendering();
}

private function initJiglib():void
{
//創銉物理world並指定元件要加入的scene
physics = new Papervision3DPhysics(scene, 8);   
}

private function initPV3D():void
{
pointLight = new PointLight3D();
pointLight.y = 1000;
pointLight.z = -800;
viewport.containerSprite.sortMode = ViewportLayerSortMode.INDEX_SORT;

Mouse3D.enabled = true;
mouse3D = viewport.interactiveSceneManager.mouse3D;

camera.z = -1200;
camera.y = 300;
camera.rotationX = 45;
}

private function createFloor():void
{
var colorMat:ColorMaterial = new ColorMaterial(0xCCCCCC);
var imageMat:BitmapMaterial = new BitmapMaterial(Bitmap(new floorAsset()).bitmapData);
var listMat:MaterialsList = new MaterialsList({all:colorMat, top:imageMat});

//createCube會創建物理的body跟實際的pv3d元件(會自動加入至pv3d scene)
var floorBody:RigidBody = physics.createCube(listMat, 1600, 1200, 10);

var floor3D:DisplayObject3D = physics.getMesh(floorBody);

//fix
floorBody.movable = false;
floorBody.moveTo(new JNumber3D(0, -300, 0));
floorBody.restitution = .8;
floorBody.friction = .2;

//重調整layer層次
viewport.getChildLayer(floor3D).layerIndex = 1;
}

private function createBox(num:uint):void
{
//重調整layer層次,在floor前,內部照z軸排序
var modelLayer:ViewportLayer = new ViewportLayer(viewport, null);

modelLayer.sortMode = ViewportLayerSortMode.Z_SORT;
modelLayer.layerIndex = 2;
viewport.containerSprite.addLayer(modelLayer);  

var cubeWidth:uint = 150;
var cubeHeight:uint = 150;
var cubeDepth:uint = 150;

for (var i:uint; i < num; i++)
{
var ranX:Number = Math.random() * 1200 - 600;
var ranY:Number = Math.random() * 500 + 500;
var ranZ:Number = Math.random() * 800 - 400;

var flatMat:FlatShadeMaterial = new FlatShadeMaterial(pointLight, Math.random() * 0x1000000, 0x111111);
var listMat:MaterialsList = new MaterialsList({all:flatMat});

var cube:RigidBody = physics.createCube(listMat, cubeWidth, cubeDepth, cubeHeight);
var cube3D:DisplayObject3D = physics.getMesh(cube);

cube.moveTo(new JNumber3D(ranX, ranY, ranZ));
modelLayer.addDisplayObject3D(cube3D);

flatMat.interactive = true;     
cube3D.addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, mousePressHandler);
}
}

private function findBody(obj3D:DisplayObject3D):RigidBody
{
var bodys:Array = PhysicsSystem.getInstance().bodys;
var rigidBody:RigidBody;

for each (var body:RigidBody in bodys)
{
var skinObj:DisplayObject3D = physics.getMesh(body);
if (skinObj == obj3D)
{
rigidBody = body;
break;
}
}
return rigidBody;
}

private function mousePressHandler(event:InteractiveScene3DEvent):void
{
trace("press");
//創立constraint
var startPos:JNumber3D = new JNumber3D(mouse3D.x, mouse3D.y, mouse3D.z);
currentBody = findBody(event.displayObject3D);
planeToDragOn = new Plane3D(new Number3D(0, 0, -1), new Number3D(0, 0, -startPos.z));

var bodyPoint:JNumber3D = JNumber3D.sub(startPos, currentBody.currentState.position);
dragConstraint = new JConstraintWorldPoint(currentBody, bodyPoint, startPos);
PhysicsSystem.getInstance().addConstraint(dragConstraint);

stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
}

private function mouseUpHandler(evnet:MouseEvent):void
{
if (dragConstraint)
{
PhysicsSystem.getInstance().removeConstraint(dragConstraint);
dragConstraint = null;
currentBody.setActive();
stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
}
}

private function mouseMoveHandler(event:MouseEvent):void
{
var ray:Number3D = camera.unproject(viewport.containerSprite.mouseX, viewport.containerSprite.mouseY);
ray = Number3D.add(ray, new Number3D(camera.x, camera.y, camera.z));

var cameraVertex3D:Vertex3D = new Vertex3D(camera.x, camera.y, camera.z);
var rayVertex3D:Vertex3D = new Vertex3D(ray.x, ray.y, ray.z);
var intersectPoint:Vertex3D = planeToDragOn.getIntersectionLine(cameraVertex3D, rayVertex3D);

dragConstraint.worldPosition = new JNumber3D(intersectPoint.x, intersectPoint.y, intersectPoint.z);
}

override protected function onRenderTick(event:Event=null):void
{
physics.step();
super.onRenderTick(event);
}
}
}

jiglibflash google code:http://code.google.com/p/jiglibflash/



[練習]PV3D + BOX2D + IK

0 意見
2009-04-18_000509.jpg
Box2D是非常強力2D物理引擎,這次試著把之前的作品透過一些小技巧應用到PV3D,效果不錯,不過還蠻吃資源的
原始檔下載


[練習]PV3D人物互動

6 意見

最近都在看framework,偶爾也來練習一下PV3D,這次是練習DAEMC跟座標定位,寫了一個3D Game常見的人物互動,寫得更精緻點也能像遊戲一樣,有空再來研究

2009-04-13_232755.jpg

點擊地面移動人物,方向鍵可改變視角

模型來自http://www.tomtallian.com/

程式原始碼