2010年4月22日 星期四

AdobeFlashCS5試玩心得

感謝台灣Adobe提供的CS5 Beta版
呼,來分享一下FlashCS5的試用心得, 我是以手上的Beta版來做測試
正式版上市後, 可能會有些不同喔。
和CS3, CS4比較一下, 文字的排版換了。

歡迎頁, 最大的牛肉當然就是IPhone App了呀, 可惜, 已經, ......你懂的, (只能自己寫爽而不能上水果store)


新面版功能:Code snippets
之前就有類似的外掛面版, 而CS5把他整合進去, 看樣子是為了讓初學者好上手
找到你要的功能,點二下, 就會幫你產生對映的程式碼。


增強程式碼提示功能:
CS4之前的版本, 都只會提示預設的flash類別。
CS5只要路徑對,所有安裝的第三方類別都可以找的到, 這樣做就對了。


全新文字排版功能:簡單來說,是把Indesign的文字功能整個搬到flash裡。
文字可以下拉選擇新的TLT Text或是使用舊版的Classic Text
使用新版的TLT Text一定要搭配FlashPlayer10喔

之後文字就可以拉出許多的文字框, 但拉不好就感覺像在玩連連看(誤)

這個的正確功能指的是同一個動態文字, 能夠被放在不同的位置, 就能做出多欄位選取。

發佈成swf後, 就可以多選文字框, 太讚了,以後就不用一堆文字來排版,推




Deco Tool:
多了新的筆刷, 不過我很好奇, 這個功能在CS4就有, 請問有人用過嗎?



元件庫新增字型:CS4之前的版本, 新增字型會把所有的字崁入, 發佈後就暴K
CS5能讓你指定所需的文字。


Create New Symbo時, 多了Folder的選項, 呼, 這個功能不錯



除了存檔成.fla外, CS5還可以存成.xfl

xfl格式就長成這樣, 會有一推資料庫和一堆xml, 會把fla所有的元件影格都都變成文字格式
好處就是可以直接用筆記本更改
不過發佈還是要開flash呀, 而且經過我的測試, 那一堆xml, 你是不會想去看他的


下一篇來分享Catalyst CS5。

2010年4月21日 星期三

新案上線, 施羅德世界資源基金

施羅德世界資源基金




當然這次主要的技術, 是使用PV3D製作一個飛機的小遊戲。
使用鍵盤的上、下、左、右鍵或是WASD來控製
點擊滑鼠左鍵為俯視模式。
參考資源:
Papervision3DEssentials
裡面有介紹到飛機的控製還有切面的問題
而整個網站串接,是使用Progression4來製作

2010年4月16日 星期五

TweenMax MosaicPlugin

Flash製作Mosaic效果還滿常見的
但要給設計師們使用這樣的類別,好像不是那麼容易
就想到TweenMax有Plugin的概念, 讀了一下原理,就自己寫一個
這樣只要會使用TweenMax就可以使用這樣的效果。

線上Demo
需要再下載gs.TweenMax類別才能使用喔
完整程式碼

/**
/**
 * @author milkmidi
 * @see http://milkmidi.blogspot.com
 * @version 1.0.0
 * @date created 2010/04/16/
 */
package milkmidi.tweenmax.plugins {
 import flash.display.*; 
 import flash.geom.*; 
 import gs.plugins.TweenPlugin; 
 import gs.TweenLite;
 public class MosaicPlugin extends TweenPlugin {  
  public static const VERSION :Number = 1.0; 
  public static const API  :Number = 1.0; 
  private var _target  :Sprite;  
  private var _bitmap  :Bitmap;  
  private var _targetWidth:int;
  private var _targetHeight:int;
  private var _startValue :int = 0;
  private var _endValue :int = 20;
  private var _autoDestroy:Boolean = true;
  public function MosaicPlugin() {
   super();
   this.propName = "mosaic";
   this.overwriteProps = ["mosaic"];
   this.onComplete = onCompleteTween;
  }
  override public function onInitTween(pTarget:Object, pValue:*, $tween:TweenLite):Boolean {   
   if (!(pTarget is Sprite)) {
    trace("motionBlur tweens only work for DisplayObjects");
    return false;
   }
   _target = pTarget as Sprite;   
   _bitmap = _target.getChildByName("_mosaic_bitmap") as Bitmap;
   if (_bitmap == null) {    
    _bitmap = new Bitmap();
    _bitmap.name = "_mosaic_bitmap";
   }  
   if (typeof(pValue) != "object") {
    trace("parameter must be object");
    return false;
   }   
   _startValue = pValue.start;
   _endValue = pValue.end;   
   _autoDestroy = (pValue.autoDestroy == undefined) ? true: pValue.autoDestroy ;
   _target.addChild(_bitmap);   
   _targetWidth = _target.width;
   _targetHeight = _target.height;
   return true;
  }  
  public function onCompleteTween():void { 
   if (_autoDestroy==false) 
    return;   
   if(_target.contains(_bitmap))
    _target.removeChild(_bitmap);
   try {
    _bitmap.bitmapData.dispose();
   }catch (err:Error){}   
   _bitmap = null;   
  }
  override public function killProps($lookup:Object):void {
   super.killProps($lookup);
   _autoDestroy = true;
   onCompleteTween();
  }
  override public function get changeFactor():Number { return super.changeFactor; }  
  override public function set changeFactor(value:Number):void {
   super.changeFactor = value;   
   var _pixelSize:Number;      
   if (_startValue < _endValue) 
    _pixelSize = (value * _endValue) + 1 + _startValue;    
   else
    _pixelSize = ((1 - value) * _startValue) + 1 + _endValue;    
   _bitmap.bitmapData = new BitmapData(_targetWidth / _pixelSize, _targetHeight / _pixelSize, false);          
   var _matrix:Matrix = new Matrix();    
   _matrix.scale(1 / _pixelSize, 1 / _pixelSize); 
   _bitmap.visible = false;
   _bitmap.bitmapData.draw(_target, _matrix);    
   _bitmap.visible = true;
   _bitmap.width = _targetWidth;
   _bitmap.height = _targetHeight;
  } 
 }
 
}
測試用程式
/**
* @author milkmidi
* @see http://milkmidi.blogspot
* @version 1.0.1
* @date created 2010/04/15/
*/
package {
import flash.display.*; 
import flash.events.MouseEvent;
import gs.*
import gs.plugins.*;
import gs.easing.*; 
import milkmidi.tweenmax.plugins.MosaicPlugin;
public class MotionBlurPluginDemo extends Sprite {
[Embed(source='demo300x300.jpg')]
public static const Texture:Class;
public function MotionBlurPluginDemo() {
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;

var mc:Sprite = addChild(new Sprite()) as Sprite;
mc.addChild(  new Texture() );
addChild(mc);

TweenPlugin.activate([MosaicPlugin]);
//啟動 MosaicPlugin 
//之後就可以使用 mosaic 屬性
//mosaic 屬性現別必需要是Object, 
//可以使用的參數有 
/*
* start: 開啟的mosaic效果,  
* end:結束的mosaic效果, 
* autoDestroy: 當TweenMax完成時, 是否自動摧毀該效果, 預設值是true
*/ 

mc.addEventListener(MouseEvent.ROLL_OVER , function ():void {
TweenMax.to(mc, .8,
{ 
mosaic: { start:0, end:20 , autoDestroy:false }    
} ); 
});
mc.addEventListener(MouseEvent.ROLL_OUT , function ():void {
TweenMax.to(mc, .8,
{ 
mosaic: { start:20, end:0 }    
} ); 
});
}
}
}

2010年4月14日 星期三

米蘭數位2010實習夏令營,再度開跑囉!

你也有想不完的點子 ?對於設計總是有滿腔的熱血?想了解互動技術其中的奧秘?那你今年就不能再錯過米蘭實習夏令營!

擔心暑期太長跟不上時代的腳步嗎?米蘭實習夏令營又要開始囉!!
讓你每天都可以挑戰不同的實習課程,讓你能在學習中更快速的了解數位行銷。

想了解米蘭:http://medialand.com.tw/
快加入米蘭文化:http://medialand.com.tw/blog/default.asp
2.報名期間:4/14(三)~5/16(日) 00:00止
3.面試期間:5/17(一)~5/28(五) 19:30止,錄取通知:6/4(五)
4.實習時間:7/5(一)-8/27(五)
5.應徵文件:參與應徵者請務必提供以下內容

網站企劃實習 x 1名
你是點子開發製造機嗎?
有過人的幽默感嗎?
勇於思考又不怕創意被打槍,而且還有十足的熱血拼勁,
那你就快點來吧!米蘭需要你!
請發想一個超有idea的網路廣告吧!(不限形式)
總評比
創意 (30%) : 創意能不能清楚表達且讓人理解?
認知 (30%) : 平常對於網路生態的觀察和某程度的專業了解,還有你準備的資料
熱忱 (20% ) : 對於網路的熱血程度,能否為了它拋頭顱灑熱血!
反應能力(10%) : 臨場表現和清楚的表達能力
聯絡與收件窗口:Medica 電話:27390000轉170
medica @mail.medialand.com.tw 請標註:[應徵網站企劃實習]

媒體企劃實習 x 1名
對於各類媒體操作總是有說不完的想法嗎?
對於網路趨勢的敏銳度總是走在前端嗎?
對於新媒體新操作總是躍躍欲試嗎?
那就來挑戰這個對數字敏銳對媒體操作有想法,而對創意表現總有話要說的職位吧!!請發像一個網路操作事件吧!!
總評比
創意&想法 (30%) : 創意能不能清楚表達且讓人理解,是否對事情能有自我的想法
認知 (20%) : 平常對於網路生態的觀察和了解
熱忱 (30% ) : 對於網路的熱血程度,能否為了它拋頭顱灑熱血!
反應能力(10%) : 臨場表現和清楚的表達能力
聯絡與收件窗口:Lena  電話:27390000轉156
lena@mail.medialand.com.tw 請標註:[應徵媒體企劃實習]

設計實習 x 1名
你覺得自己是創意人嗎?
那就來米蘭表現你最有趣的一面!
自我介紹”5”分鐘,不可以用口述,
不管你是要跳舞、畫畫、唱歌、還是播影片…等等
請用最有創意的方式呈現你自己!
總評比
創意 (30%) :呈現的方式與內容(含作品)
技術 (30%) :呈現的質感
熱忱 (30% ):對於設計的用心與堅持
生活 (10% ):是否有在規劃自己的生活與未來
聯絡與收件窗口:Devin 電話:27390000轉177
devin @mail.medialand.com.tw 請標註:[應徵視覺設計實習]

互動程式設計實習 x 1名
對互動技術及 RIA 具有莫名的熱情與執著的你,與互動團隊一起討論及開發日新月異的新技術,並對此樂此不疲深陷其中的你!只要附上你個人作品,將有機會直接深入業界瞭解整個互動網站的開發流程!
總評比
創意 (25%) : 創意能不能清楚表達且讓人理解?
認知 (30%) : 平常對於網路生態的觀察和了解
熱忱 (35% ) : 對於網路的熱血程度,能否為了它拋頭顱灑熱血!
反應能力(10%) : 臨場表現和清楚的表達能力
聯絡與收件窗口:milkmidi 電話:27390000轉128
milkmidi@mail.medialand.com.tw 來信請標註: [應徵互動程式實習]


A.個人基本資料 (姓名、生日、聯絡方式、學經歷、並附上近期清晰照片乙張)
B.我的網路履歷表
i.使用網路的年資
ii.使用過哪些網站,其中最喜歡哪個網站?為什麼?
iii.你的個人平台(例如:Blog、Plurk、twitter、FunP、facebook、delicious、黑米…)
iv.你在虛擬的網路中,有哪些傲人的身分或成績?
(例如:線上遊戲團長或幹部、巴哈姆特Lv3等級以上、噗浪的Karma超高、擔任過批踢踢小天使或版主、在youtube或blog上的作品曾經被廣為傳閱…)
C.個人作品集(或作品網站、部落格)
★A與B:請用信或是word提供,內容就看你要寫多少來表現自己,因為每個人都不太一樣,企劃的字可能會比較多,而工程師說不定會寫一段程式碼給我們XD
★C:就按照自己想呈現的方式

以上資料請mail至各負責窗口。

原文連結:
http://medialand.com.tw/blog/article.asp?id=1208

milkmidiV4面版更新

這次主要是修正增加表籤問題,
之前的做法是在場景上放一個動態文字,然後在時間軸上寫code
當物件數量很多的時候,該表籤會出現一下下後才馬上消失,
這次改成組件式的方法,就不會發生這樣的問題。
只要需要開啟參數面版來打字。
使用方法如下:
點擊一個物件(MovieClip,Graphic或Button)


開啟面版,點擊面版上的La功能鍵


此時會進入該元件的輯編區, 同時將Label組件放在場景上

>

開啟參數面版, 就可以編輯文字啦


點這兒下載
其他功能可以參考之前發表的文章點這兒

2010年4月11日 星期日

新案上線, Absolut 校園創作競賽

創意絕對.絕對搖滾. 校園創作競賽



在這次的專案,有三個技術點想跟大家分享(如果有更好的方法,歡迎指教討論喔),
1. 自製網頁的ScrollBar
要寫一個ScrollBar不會很難, 但要配合隨視窗縮放的ScrollBar就不是那麼簡單。
在這兒我使用的是bit-101大叔的 minimalcomps 組件裡的VSlider。
該組件的特色,就是有個setSize的函式, 能讓你動態更改組件大小且不會變型。
基本用法如下:
new VSlider(要加入到那個容器裡, x座標, y座標, change偵聽函式);
決解ScrollBar的程式,再補上偵聽stage的Resize事件, 和偵聽stage的MouseWheel事件
完成(誤)
設計師當然不會用這樣的樣計樣式, 好在該特組件在建立元件時, 會執行addChildren函式
我們只要去override後,加入自己的元件,然後把對映的變數重新指過去就可以了
先在flash做好ScrollBar元件,並取好名稱
在這我不使用flash直接compile,因為太慢, 而是使用Embed把該swf裡的元件重新加進來。
再使用FlexSDK來做compile的動作。
自製ScrollBar的程式碼
/**
* @author milkmidi
* @see http://milkmidi.blogspot
* @version 1.0.1
* @date created 2010/03/24/
*/
package milkmidi.tutorials.absolut.cast {  
import com.bit101.components.VSlider; 
import flash.display.*; 
import flash.events.*;  
[Embed(source='../../../../../assets/Assets.swf',symbol="Scroll_mc")]
public class SliderMC extends VSlider{  
public var thumb_mc     :MovieClip;
public var track_mc     :MovieClip;
private var _addWheelListener:Boolean = false;
public function SliderMC(pParent:DisplayObjectContainer = null, pX:int = 0 , pY:int = 0, pChangeHandler:Function = null)  {      
super(pParent, pX, pY, pChangeHandler);     
}     
override protected function addChildren():void {      
_handle = thumb_mc;
_handle.buttonMode = true;
_handle.addEventListener(MouseEvent.MOUSE_DOWN, onDrag);    
}  
private function _mouseWheelHandler(e:MouseEvent):void {   
if(e.delta>0)
value += 15;
else
value -= 15;     
onSlide(e);   
}
override public function get value():Number { return super.value; }  
override public function set value(value:Number):void {   
super.value = value;
onSlide(null);
}  
public function get addWheelListener():Boolean { return _addWheelListener; }  
public function set addWheelListener(value:Boolean):void {
_addWheelListener = value;
if (_addWheelListener)
stage.addEventListener(MouseEvent.MOUSE_WHEEL , _mouseWheelHandler);   
else
stage.removeEventListener(MouseEvent.MOUSE_WHEEL , _mouseWheelHandler);      
}
override protected function drawBack():void {
track_mc.height = height;
}
override protected function drawHandle():void {   
positionHandle();
}  
} 
}
主程式測試碼
/**
* @author milkmidi
* @see http://milkmidi.blogspot
* @version 1.0.1
* @date created 2010/04/07/
*/
package  {  
import com.bit101.components.HBox;
import com.bit101.components.HSlider;
import com.bit101.components.VSlider;
import flash.display.*;  
import flash.events.Event;
import milkmidi.tutorials.absolut.cast.SliderMC;
public class A01SliderMCDemo extends Sprite {    

private var _scroll:SliderMC;
public function A01SliderMCDemo()  {   
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE , init);
}  

private function init(e:Event=null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);   
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.addEventListener(Event.RESIZE , _resizeHandler);
_scroll = new SliderMC(this, 0, 0, _slidrChangeHandler);
_scroll.addWheelListener = true;
_scroll.setSliderParams(0, 100, 50); 
_resizeHandler(null);   
//以下是測試用的
new VSlider(this, 0, 0, _slidrChangeHandler);
}

private function _resizeHandler(e:Event):void {
_scroll.x = stage.stageWidth - 40;
_scroll.setSize(200, stage.stageHeight);
}

private function _slidrChangeHandler(e:Event):void{
trace(e.currentTarget.value)
}
} 
}
2. 主視覺要隨視窗大小作定位
在這個案子裡,主視覺有二種模式, 一般模式(要完全罝中)
資訊打開模式(配合第一點的ScrollBar數值來作定位)
我想第一般模式很簡單, 直接對stage做Resize偵聽, 然後就完全置中
而第打開模式,其實也不難,反正ScrollBar裡的value預設就是0到100。
當ScollBar value 在0時, 主視覺物件的y軸也在0,
當ScrollBar value 在100時,主視覺物件的y軸就等於 (主視覺物件的高度-場景高*負1)
(keyVisual.height-stage.stageHeight*-1)
好了,公式出來了,剩下的應該不難。
package  {  

public class A02KeyVisualDemo extends A01SliderMCDemo{  

private var _keyVisual:KeyVisual_mc = new KeyVisual_mc();
public function A02KeyVisualDemo()  {   
addChild(_keyVisual);
}  
override protected function _onScrollChange(pValue:int):void {
pValue = 100 - pValue;
//因為VSlider拉到底是0, 跟我們需要的值是相反的, 所以要倒過來
var _rang:int = (_keyVisual.height - stage.stageHeight) * -1;   
_keyVisual.y = _rang * pValue / 100;         
}
} 
}
3. 效能問題
先直接看效能未優化版(僅供demo用, 活動資訊請以正式網址為主)
你可以看到整個網站在進場播放動畫時,是非常lag, 且整個網站的fps非常的低。
二者有非常明顯的差別(如果你的電腦配備超好的話,應該看不出來)
二個版本用的fla檔都是同一個。
先了解一下flash吃效能的幾個點。
flv:影片播放是很吃效能的,不管是外載還是匯入到flash裡,都非常吃效能,特別在大畫面時更明顯。
決解方法:用檔案k數來換, 把影片轉成序列圖檔
序列圖檔:能用jpg當然是最好的,但要有透明度的話,就一定要用PNG
在使用PNG時要特別注意, 假設你的圖片是600x400, 但真正有圖型的大小可能只有300x200, 其他的部份都是透明色塊, 請記得。打散他, 然後把用不到的透明色塊給delete掉, 這樣可以省下很多不必要的運算(經人體實驗是有效的)。
大畫面物件+多物件移動+序列圖檔:
就像這次的案子遇到的問題一樣,設計師做好美美的動畫,做完發現跑起來很lag,本來是想減少動畫量,但就少了一種感覺, 而我使用的方法就是 BitmapData
嘿嘿,想到了嗎
使用 BitmapData 類別,把該動畫所有的影格,事前畫成BitmapData, 在存在Array裡
當要播放動畫時,就去指定的Array裡把BitmapData拿出來。
這樣不管畫面上有多少物件,都視同只有一個BitmapData, 等到動畫播完時,在把Array裡的BitmapData Dispose掉,這樣動畫也順了,效能也有了。
但使用時還是需要注意幾個點:
一開始要把一個MovieClip裡的全部影格畫成BitmapData, 表示一瞬間會消耗大量的CPU,此時使用者的電腦可能會停頓一下,那可不可以改成邊播MovieClip邊畫呢,答案是這樣做的效能沒什麼差
所以我的作法是把整段動畫分階段去畫,一開始可能先畫20個影格,當動畫播到20個影格時,再去畫另外的20個影格
等到動畫全部播完後,再整個Dispose掉。

package milkmidi.display { 
import flash.display.*; 
import flash.events.Event;
import flash.geom.Matrix;
import flash.net.URLRequest;
import flash.utils.clearInterval;
import flash.utils.clearTimeout;
import flash.utils.setTimeout; 
public class BitmapDataSequence extends Sprite {
public static const END_FRAME:String = "endFrame";
private var _target   :MovieClip;
private var _targetWidth :int;
private var _targetHeight :int;  
private var _fps   :uint;
private var _totalFrames :uint;  
private var _bitmap   :Bitmap = new Bitmap();
private var _bmdArray  :Array = [];    
private var _frame   :int = 1;  
private var _inter   :int;
private var _drawMatrix  :Matrix;
private var _sequenceTime :Number;
public function BitmapDataSequence(pTargetMC:MovieClip, pWidth:Number = 320, pHeight:Number = 240, pFps:Number = 30):void {   
_fps = pFps;      
_targetWidth = pWidth;
_targetHeight = pHeight;   
_target = pTargetMC;         
_totalFrames = _target.totalFrames;
addChild(_bitmap);   
}
public function startSequence(pTime:Number = 0 ):void {   
_sequenceTime = pTime;
convert();   
}  
public function prevFrame():void {
_frame--; 
_frame = _frame < 1 ? 1 :_frame;   
showFrameBitmapData(_frame);   
}
public function nextFrame():void {
_frame++; 
_frame = _frame > _totalFrames  ? _totalFrames : _frame;   
showFrameBitmapData(_frame);
}
public function play():void {
showFrameBitmapData(_frame);   
if (_frame == _totalFrames) {    
dispatchEvent(new Event(END_FRAME));
}
_frame %= _totalFrames;      
_frame++;   
_inter = setTimeout(play, 1000 / _fps);      
}
public function stop():void {
clearTimeout(_inter);
}
public function gotoAndStop(pFrame:uint):void {   
stop();
_frame = pFrame;
showFrameBitmapData(_frame);
}
public function gotoAndPlay(pFrame:uint):void { 
stop();
_frame = pFrame;   
play();
}
private function convert():void {    
_target.gotoAndStop(_frame);   
var _mtr:Matrix = new Matrix();       
var _bmp:BitmapData = new BitmapData(_targetWidth, _targetHeight, true, 0x00000000);
_bmp.draw(_target, _drawMatrix);      
_bmdArray.push(_bmp);
_frame++;  
//trace(_frame, _bmdArray.length);
if (_frame > _totalFrames) {
stop();    
_frame = 1;    
showFrameBitmapData(1);
dispatchEvent(new Event(Event.COMPLETE));
return;
}   
if (_sequenceTime == 0)   
convert();
else
setTimeout( convert, _sequenceTime * 1000);
}  

private function showFrameBitmapData(pFrame:uint):void {
_bitmap.bitmapData = _bmdArray[pFrame - 1];    
}
public function get totalFrames():uint { return _totalFrames; }   
public function get currentFrame():uint { return _frame; }

public function get drawMatrix():Matrix { return _drawMatrix; }  
public function set drawMatrix(value:Matrix):void {
_drawMatrix = value;
}
public function destroy():void {
clearInterval(_inter);
for each (var _bmp:BitmapData in _bmdArray) {
_bmp.dispose();
}        
}
}

}
SourceCodeDownload