Adobe
製品
Acrobat
Creative Cloud
Creative Suite
Digital Marketing Suite
Digital Publishing Suite
Elements
Photoshop
Touch Apps
その他の製品一覧
ソリューション
デジタルマーケティング
デジタルメディア
教育
金融機関
Web Experience Management
その他のソリューション
ラーニング サポート ダウンロード 会社情報
ご購入
アドビストア 安心のサポート& サービス
アカデミックストア 学生、教職員、個人向け
アドビライセンスストア 中小企業向け
ボリュームライセンスについて 企業、教育機関、官公庁向け
販売パートナー
キャンペーン情報
検索
 
情報 サインイン
ようこそ、 さん カート 注文状況 マイアカウント
マイアカウント
注文状況
アカウント情報の変更
コミュニケーションの設定を変更
サインアウト
サインインの目的 お客様のアカウントや体験版ダウンロード、製品の拡張機能、コミュニティエリアへのアクセスなどを管理するため
Adobe
製品 セクション ご購入   検索  
ソリューション 会社情報
サポート ラーニング
サインイン サインアウト 注文状況 マイアカウント
先行予約の提供開始予定日Date. 商品が発送されるまで、クレジットカードには課金されません。提供開始の予定日は変更される場合があります。 先行予約の提供開始予定日Date. ダウンロードの準備が整うまで、クレジットカードには課金されません。提供開始の予定日は変更される場合があります。
個数:
ご購入には学生・教職員個人版の購入資格の確認が必要です。
小計
カートの中身を見る
Adobe Developer Connection / Flashデベロッパーセンター /

Firework.jp :「自分で花火を作って、打ち上げる」花火大会の仕組み

著者 小松弘昌氏

小松弘昌氏
  • 株式会社イージェーワークス

Content

  • ユーザーが花火をデザインし、自分だけの花火大会を演出する
  • 花火玉のデザインから色情報を配列にして収集する
  • 色情報から粒子データへ拡張する
  • 花火の動きを再現する
  • 花火玉を登録する

作成日

11 September 2008

ページ ツール

Facebookでシェア
Twitterでツイート
LinkedInでシェア
ブックマーク
印刷

タグ

必要ソフトウェア

ユーザーレベル

上級

必要な製品

  • Flash Professional CS3 (Download trial)

ユーザーが花火をデザインし、自分だけの花火大会を演出する

Webだからこそ体験できるコンテンツは何か? それを突き詰めた結果生まれたのが「Firework.jp」です。ユーザー自身が花火をデザインし、自分だけの花火大会を演出する。現実の世界では、とうてい実現できない話も、Webだからこそ実現できる、そんな思いからこの企画が採用されました。

Firework.jpでは、まず「花火玉を作る」画面(図1)で自分だけの花火をデザインします。カラーピッカーから好きな色を選択し、花火玉の上でドラッグしながら「火薬」に色を塗っていきます。デザインしたら、「出来上がりを確認」ボタンをクリックして、花火の打ち上がり具合を確認し、花火玉を保存します。そして、保存した花火玉で自分だけの花火大会を作ったり、みんなの花火大会にエントリーすることができます。

図1
図1 「花火玉を作る」画面。画面左は、自分がデザイン・保存した花火玉です(最高10個まで)。画面右は、現在編集中の花火玉です。「出来上がりを確認」ボタンをクリックすると、編集中の花火玉が左へスライドして、花火が打ち上がった状態を確認できます

花火玉をデザインした後は、画面左下の「あなたの花火大会を作る」メニューから自分の花火玉と好きな会場を選び、「出来上がりを確認」ボタンをクリックしてエントリー(保存)すると、自分だけの花火大会へ登録することができます(図2)。他にも、みんなの花火大会に参加すると、いろんな人が作った花火と共演することができます。

図2 自分の花火大会では、自分が決めた順番に次々と花火が打ち上がります
図2 自分の花火大会では、自分が決めた順番に次々と花火が打ち上がります

花火を作ったり、登録したり、打ち上げたりと、自分で好きなように花火大会を演出することができるのがFirework.jpの醍醐味です。それでは、どのようにして自分でデザインした花火を打ち上げているのか、その考え方と構造を解説していきます。

花火玉のデザインから色情報を配列にして収集する

ユーザーは「花火玉を作る」画面で花火玉の各「火薬」に色を塗ります。これを元に花火を再現していくわけですが、まず最初の工程として、火薬の色情報を配列として収集します。この時、取得する配列内の順番は火薬の位置によって決められます。

「花火玉を作る」画面にある花火玉の火薬は、スクリプトで生成・配置されており、中心から徐々に半径を拡張するように円を描きながら火薬の位置を決めています。このスクリプトでは、最初の円周で6つの火薬を等幅に配置し、半径を5つずつ増やしながら円を拡張し、次の円周で12個、18個、24個…と火薬の数を6ずつ増やしていきます。このように生成された火薬(MovieClip)の順番に沿って配列へ追加しています(図3)。

図3 花火玉の火薬の位置で配列の順番が決まっています
図3 花火玉の火薬の位置で配列の順番が決まっています

以下は、花火玉を生成するスクリプトです。

// HALF_SIZE : 花火玉全体の半径 // DEFAULT_COLOR : 塗りがないときの星の色 // selected_color : 選択中のRGBカラー private function starCreate():void {               var renge_length:uint = 5; var renge_margin:Number = ( HALF_SIZE  - 10 ) * 2 / ( renge_length * 2 - 1 ); var renge:Number; var angle_length:uint; var angle_margin:Number; var angle:Number; var star_mc:Sprite; var rad:Number; var half:Number = renge_margin / 2; var color:uint = DEFAULT_COLOR;               renge = 0;               // 円周を増幅 for ( var i:int = 0; i < renge_length; i++ ) {                             angle_length = ( i == 0 ) ? 1 : 6 * i; angle_margin = 360 / angle_length; angle = 90;                             // 円周の玉数を増幅 for ( var k:int = 0; k < angle_length; k++ ) {                                           // 花火の星を作る rad = angle * PI; star_mc = new Sprite(); star_mc.graphics.beginFill( color ); star_mc.graphics.drawCircle( 0 , 0 , half ); star_mc.graphics.endFill(); star_mc.x = Math.cos( rad ) * renge; star_mc.y = Math.sin( rad ) * renge; star_mc.buttonMode = true; star_mc.addEventListener( MouseEvent.MOUSE_DOWN , starClick ); star_mc.addEventListener( MouseEvent.ROLL_OVER , starOver ); star_mc.addEventListener( MouseEvent.ROLL_OUT , starOut ); container_mc.addChild( star_mc );                                           // 配列に追加 star_arr.push( star_mc );                                           // 角度を足す angle += angle_margin;                                           }                             // 半径を足す renge += renge_margin;                             }               // ボタンオーバーのときのライン overline_mc = new Sprite(); overline_mc.graphics.lineStyle( 2 , 0x999999 ); overline_mc.graphics.drawCircle( 0 , 0 , half ); overline_mc.mouseEnabled = false;               } // ボタンクリック private function starClick( event:MouseEvent ):void { var target:Sprite = event.target as Sprite; setStarColor( target , selected_color ); } // ボタンオーバー - ドラッグしながら色を塗る処理 private function starOver( event:MouseEvent ):void { var target:Sprite = event.target as Sprite; if ( event.buttonDown ) { setStarColor( target , selected_color ); } overline_mc.x = target.x + HALF_SIZE; overline_mc.y = target.y + HALF_SIZE; addChild( overline_mc ); } // ボタンアウト private function starOut( event:MouseEvent ):void { if ( contains( overline_mc ) ) removeChild( overline_mc ); } // 星にカラーを適応 private function setStarColor( star_mc:Sprite , color:String ):void { var color_trans:ColorTransform = new ColorTransform(); color_trans.color = ( color != null ) ? Number( "0x" + color ) : DEFAULT_COLOR; star_mc.transform.colorTransform = color_trans; }

また、getter/setterメソッドによって、図4のように61個の色情報が入出力されます。

getter/setterメソッドとは、プロパティの値を設定したり返したりするための専用メソッドで、クラス内にはメソッドとして定義しますが、クラスの外側からはプロパティとしてアクセスすることができます。

この場合のサンプルでは、「data」というgetter/setteメソッドを定義しています。dataプロパティを読み取ると、色情報の配列を返し、逆に色情報の配列をdataプロパティに指定すると花火玉の火薬の色が適応されます。

図4 dataプロパティによって花火玉の火薬の色を設定したり返したりします
図4 dataプロパティによって花火玉の火薬の色を設定したり返したりします

以下は、花火玉の配列を入出力するスクリプトです。

// color_arr : カラー情報の配列 // 入力 public function set datas( color_arr:* ):void { var len:int = star_arr.length; var star_mc:Sprite; var color_str:String; var data:Object; for ( var i:int = 0; i < len; i++ ) { star_mc = star_arr[ i ]; if ( color_arr != null ) { data = color_arr[ i ]; color_str = data.color; setStarColor( star_mc , color_str ); } else { setStarColor( star_mc , null ); } } } // 出力 public function get datas():Array { var color_arr:Array = new Array(); var len:int = star_arr.length; var star_mc:Sprite; var color:uint; var color_str:String; var data:Object; for ( var i:int = 0; i < len; i++ ) { data = new Object(); star_mc = star_arr[ i ]; color = star_mc.transform.colorTransform.color; color_str = ( color != DEFAULT_COLOR ) ? ( "000000" + color.toString( 16 ) ).substr( -6 , 6 ) : null; data.color = color_str; color_arr[ i ] = data; } return color_arr; }

色情報から粒子データへ拡張する

花火玉から色情報の配列を受け取ったら、花火の打ち上がりを演出するための「粒子」データ(位置、移動距離、持続エネルギー)へと変換していきます。

色は、物理エンジンによって描画されるため、数値化して取得します。

位置は、火花のxとyの座標になりますが、初期設定として花火が拡散する時の中心の位置を指定します。花火の中心位置は打ち上がるときのタイミングによって変わってくるので、値を任意に変更できるようにメソッドの引数として設定できるようにしておきます。

移動距離は、配列の順番によってルール付けされています。その情報から粒子の速さ(半径の長さ)と方向(角度)を取得し、取得された半径と角度からx軸方向とy軸方向 の移動距離を計算していきます(図5)。

図5 配列の順番から、粒子の速さ(半径の長さ)と方向(角度)を導きだしています。更にそこから、vx(x軸の移動距離)とvy(y軸の移動距離)を計算しています
図5 配列の順番から、粒子の速さ(半径の長さ)と方向(角度)を導きだしています。更にそこから、vx(x軸の移動距離)とvy(y軸の移動距離)を計算しています

色情報から粒子データへ拡張する内容をまとめると、図7のようになります。

図7 火薬のデータは、color x y vx vy energyのパラメータに拡張されます。
図7 火薬のデータは、color x y vx vy energyのパラメータに拡張されます。

以下は、色情報を粒子データに変換するスクリプトです。

// color_arr : カラー情報の配列 // x : パーティクルのX座標 // y : パーティクルのY座標 // n : 星データからパーティクルに拡張する配列量の倍率 // radius : 拡散する距離の基準値 static public function encode( color_arr:Array = null , x:Number = 0 , y:Number = 0 , n:uint = 1 , radius:Number = 14 ):Array { if ( color_arr == null ) { return null; } var renge_length:uint = 5; var renge_margin:Number = radius / ( renge_length * 2 - 1 ); var renge:Number; var angle_length:uint; var angle_margin:Number; var angle:Number; // カラー情報 var star_obj:Object; var id:int = 0; // 火花データ var particle_arr:Array; var particle_obj:Object; var p_angle:Number; var p_renge:Number; var rad:Number; particle_arr = new Array(); renge = 0; // 円周を増幅 for ( var i:int = 0; i < renge_length; i++ ) { angle_length = ( i == 0 ) ? 1 : 6 * i; angle_margin = 360 / angle_length; angle = 90; // 円周の玉数を増幅 for ( var k:int = 0; k < angle_length; k++ ) { // カラー情報の配列からオブジェクトを取得 star_obj = color_arr[ id ]; if ( star_obj.color != null ) { // 火花データを拡張 particle_obj = new Object(); p_angle = angle + Math.random() * ( angle_margin || 0 ); p_renge = renge + Math.random() * ( renge_margin || 0 ); rad = p_angle * PI; particle_obj.x = x; particle_obj.y = y; particle_obj.vx = Math.cos( rad ) * p_renge; particle_obj.vy = Math.sin( rad ) * p_renge; particle_obj.energy = 5 + 10 * Math.random(); particle_obj.color = Number( "0x" + star_obj.color ); if ( star_obj.bright ) particle_obj.bright = star_obj.bright || 3; if ( star_obj.graviton ) particle_obj.graviton = star_obj.graviton || 0.05; particle_arr.push( particle_obj ); } id++; // 角度を足す angle += angle_margin; } // 半径を足す renge += renge_margin; } return particle_arr; }

花火の動きを再現する

実際の花火を見ると、発火して火花が発光した後、時間と共に爆発エネルギーが減衰し、やがて空気中で消えていくという特徴があります。この花火の動きをシミュレーションするために、座標に移動距離を加算しながら、移動距離の値にエネルギー消費量を乗算、y軸方向の移動距離に重力の値を加算するという物理エンジンを生成しました。これを図にしたのが、図8です。火花の移動距離にエネルギー消費量(ここでは0.95)を乗算することで、徐々に花火(粒子)が拡散する勢いを減らしています。

図8 x軸方向に0.95を乗算して火花(粒子)の移動距離を徐々に減らしていきます
図8 x軸方向に0.95を乗算して火花(粒子)の移動距離を徐々に減らしていきます

このとき、花火玉の火薬から取得した色と位置を元に、粒子データの位置・移動距離・持続エネルギー・色情報を生成しているため、ユーザーが意図した通りの花火の形で演出することができるのです。

また、拡散した花火の粒子データを描画する処理ですが、粒子データごとにMovieClipインスタンスを生成する方法だと非常に処理が重くなるので、1つのインスタンスの中にそれぞれ点描画するという方法を採用しています。

火花(粒子)が夜空で消えるときの余韻を演出するために、別のMovieClipインスタンスに火花の残像を表現するためのビットマップデータ作成し、さらに時間によって徐々に残像を消し込むために半透明の黒いビットマップデータを作成し、それを重ね塗りするようにします。

// width : ステージの横サイズ // height : ステージの縦サイズ // display_mc : 火花の残像を表現するためのインスタンス display_bmd = new BitmapData( width , height , true, 0x00000000 ); aftereffect_bmd = new BitmapData( width , height, true, 0x1D000000 ); display_mc.addChild( new Bitmap( display_bmd ) );

また、花火のぼかした感じを表現するために、描画用のインスタンスにグローフィルタを適応し、明度を若干上げています。

// draw_mc : 花火の粒子を点描画するためのインスタンス // フィルター作成 var f_color:Number = 0xFFFFFF; var f_alpha:Number = 0.8; var f_blurX:Number = 30; var f_blurY:Number = 30; var f_strength:Number = 1; var f_quality:Number = 1; var f_inner:Boolean = false; var f_knockout:Boolean = false; var filters:GlowFilter = new GlowFilter( f_color , f_alpha , f_blurX , f_blurY , f_strength , f_quality ); draw_mc.filters = [ filters ];   // 明度を上げる ( new Transform( draw_mc ) ).colorTransform = new ColorTransform( 0.5 , 0.5 , 0.5 , 1 , 128 , 128 , 128 , 0 );

火花を描画するとき、毎フレームごとに粒子データから取得した移動距離の値によって座標を計算します。その計算された情報に沿って描画用のMovieClip(draw_mc)に点描画していきます。
更に、毎回 点描画される度に 残像用のビットマップデータ(display_bmd)に重ねて描画しつつ、半透明の黒いビットマップデータ(aftereffect_bmd)を重ね塗りすることによって火花を徐々に消していきます。この黒いビットマップデータ(aftereffect_bmd)の透明度を変更することによって、火花が消える間隔を遅めたり速めたりできます。

このとき、背景画像レイヤー(back_mc)を最背面に置いてしまうと一つの問題が生じます。それは、残像用のビットマップデータ(diplay_bmd)に半透明の黒いビットマップデータ(aftereffect_bmd)を重ね塗りするのですが、全体を徐々に真っ黒にするため、下にあるレイヤーが見えなくなってしまいます。この問題を解決するために、背景画像レイヤー(back_mc)を一番上に置いてMovieClipのblendModeプロパティをBlendMode.SCREENに指定します。そうすることによって、表示オブジェクトの色の補数 (逆)と背景色の補数が乗算されるため、表示オブジェクトの黒い領域が削除されるので、その下にあるグラフィック(花火)が表示されるようになります(図9)。

図9 back_mc.blendMode = BlendMode.SCREENと指定します図9 back_mc.blendMode = BlendMode.SCREENと指定します
図9 back_mc.blendMode = BlendMode.SCREENと指定します

以下は、粒子の演算に関するスクリプトです。

// ENERGY_CONSUMED : エネルギー消費量(0.95) // draw_mc : 点描画するステージ // display_bmd :残像用のビットマップデータ // aftereffect_bmd :半透明の黒いビットマップデータ public function draw():void { var particle:Object; draw_mc.graphics.clear(); draw_mc.graphics.lineStyle( 3 , 0xFFFFFF , 50 ); for ( var i:int = 0; i < particle_arr.length; i++ ) { // 粒子データ particle = particle_arr[ i ]; // 一定以下のエネルギー量をもつ粒子データを削除する if ( particle.energy < 0.1 ) { particle_arr.splice( i , 1 ); continue; } // 粒子データの重力値と明度 var graviton:Number = ( particle.graviton != undefined ) ? particle.graviton : 0.05; var bright:int = ( particle.bright != undefined ) ? particle.bright : 3; with ( particle ) { x += vx; y += vy; //時間が経つごとに粒子のエネルギーを減少させる energy *= ENERGY_CONSUMED; vx *= ENERGY_CONSUMED; vy *= ENERGY_CONSUMED; //重力 vy += graviton; // カラーを適応する draw_mc.graphics.lineStyle( bright , color || 0xFFFFFF , 50 ); } // 粒子データを点描画する draw_mc.graphics.moveTo( particle.x , particle.y ); draw_mc.graphics.lineTo( particle.x+0.5 , particle.y+0.5 ); } //余韻を表現する display_bmd.draw( aftereffect_bmd ); display_bmd.draw( draw_mc ); }

ActionScript 3.0で開発を採用する理由として、このときの粒子の点描画処理を快適に表現するという意図が前提にあります。

花火玉を登録する

「花火玉を作る」画面で生成された火薬の情報は、自分の花火としてサーバに登録できます。そのとき、大量の花火玉データをサーバと転送する際、XMLでデータを受け取るよりもJSON形式にしたほうがデータ情報量は減ると考えました。また、配列からJSON形式のデータへ変換するときに、ActionScript 3.0用ライブラリである「as3corelib」のJSONクラスを利用しています。

JSONクラスを活用し、encodeで文字列にしたものを繰り返しdecodeすることによって、元のオブジェクトの変更せずに花火情報を複製することができます。これを利用して、スターマインで繰り返し花火を打ち上げる処理を表現しています。

以上で、Firework.jpの仕組みの解説は終了です。

Firework.jpは、2009年4月31日まで開催しています。
夏の思い出に浸るもよし、作品を眺めて癒されるもよし。
自分だけの夜空を、あなたのセンスで彩ってみてください。

製品

  • Acrobat
  • Creative Cloud
  • Creative Suite
  • Digital Marketing Suite
  • Digital Publishing Suite
  • Elements
  • モバイルアプリ
  • Photoshop
  • Touch Apps

ソリューション

  • デジタルマーケティング
  • コンテンツオーサリング
  • Web Experience Management

業種別ソリューション

  • 教育
  • 金融機関

サポート

  • ヘルプ&サポート
  • 注文と返品
  • ダウンロードに関するヘルプ
  • ユーザー登録に関するヘルプ

ラーニング

  • ADC: Adobe Developer Center
  • Adobe TV
  • Design Magazine
  • Photoshop Magazine
  • Focus In

ご購入方法

  • アドビストア
  • アカデミックストア
  • アドビライセンスストア
  • ボリュームライセンスについて
  • 販売パートナー
  • キャンペーン情報

ダウンロード

  • Adobe Reader
  • Adobe Flash Player
  • Adobe AIR
  • Adobe Shockwave Player

会社情報

  • プレスルーム
  • パートナープログラム
  • 企業の社会的責任(英語)
  • 採用情報
  • 投資家の皆様へ(英語)
  • イベント&セミナー
  • Legal(英語)
  • セキュリティ
  • お問い合わせ
国・地域および言語の選択 日本(変更)
国・地域および言語の選択 閉じる

North America

Europe, Middle East and Africa

Asia Pacific

  • Canada - English
  • Canada - Français
  • Latinoamérica
  • México
  • United States

South America

  • Brasil
  • Africa - English
  • Österreich - Deutsch
  • Belgium - English
  • Belgique - Français
  • België - Nederlands
  • България
  • Hrvatska
  • Česká republika
  • Danmark
  • Eastern Europe - English
  • Eesti
  • Suomi
  • France
  • Deutschland
  • Magyarország
  • Ireland
  • Israel - English
  • ישראל - עברית
  • Italia
  • Latvija
  • Lietuva
  • Luxembourg - Deutsch
  • Luxembourg - English
  • Luxembourg - Français
  • الشرق الأوسط وشمال أفريقيا - اللغة العربية
  • Middle East and North Africa - English
  • Moyen-Orient et Afrique du Nord - Français
  • Nederland
  • Norge
  • Polska
  • Portugal
  • România
  • Россия
  • Srbija
  • Slovensko
  • Slovenija
  • España
  • Sverige
  • Schweiz - Deutsch
  • Suisse - Français
  • Svizzera - Italiano
  • Türkiye
  • Україна
  • United Kingdom
  • Australia
  • 中国
  • 中國香港特別行政區
  • Hong Kong S.A.R. of China
  • India - English
  • 日本
  • 한국
  • New Zealand
  • 台灣

Southeast Asia

  • Includes Indonesia, Malaysia, Philippines, Singapore, Thailand, and Vietnam - English

Copyright © 2012 Adobe Systems Incorporated. All rights reserved.

利用条件 | プライバシーポリシーとCookie (更新)

Reviewed by TRUSTe: site privacy statement