forked from: 【AS100本ノック】11回目:ろうそく
AS100本ノック
* 11回目のお題は「ろうそく」
* あなたなりの「ろうそく」を表現してください。
* --
* 昔の人は、ロウソクの明かりで本とか読んでたんだよなー
* こんな感じかなー。。。って怖っ!
* --
* クリックしてロウソクを配置してね。
/**
* Copyright mex_ichikawa ( http://wonderfl.net/user/mex_ichikawa )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/qLsC
*/
/**
* AS100本ノック
* 11回目のお題は「ろうそく」
* あなたなりの「ろうそく」を表現してください。
* --
* 昔の人は、ロウソクの明かりで本とか読んでたんだよなー
* こんな感じかなー。。。って怖っ!
* --
* クリックしてロウソクを配置してね。
*/
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.Event;
import flash.events.MouseEvent;
[SWF(width=465, height=465, backgroundColor=0xFFFFFF, frameRate=60)]
public class Candle extends Sprite
{
public static const STAGE_WIDTH:uint = 465;
public static const STAGE_HEIGHT:uint = 465;
private var _text:TextBook;
private var _effect:HaloEffect;
public function Candle()
{
init();
}
private function init():void
{
_text = new TextBook;
addChild(_text);
_effect = new HaloEffect;
_effect.blendMode = BlendMode.DARKEN;
addChild(_effect);
stage.addEventListener(MouseEvent.CLICK, mouseClickHandler);
}
private function mouseClickHandler(event:MouseEvent):void
{
_effect.addPoint(event.stageX, event.stageY);
addChild(new CandleClip(event.stageX, event.stageY));
addChild(new TeraFire(event.stageX, event.stageY));
_effect.render();
}
}
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.Event;
import flash.filters.BlurFilter;
import flash.filters.DisplacementMapFilter;
import flash.filters.DisplacementMapFilterMode;
import flash.filters.DropShadowFilter;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.text.engine.*;
import flashx.textLayout.container.ContainerController;
import flashx.textLayout.conversion.TextConverter;
import flashx.textLayout.edit.SelectionManager;
import flashx.textLayout.elements.*;
import flashx.textLayout.factory.TextFlowTextLineFactory;
import flashx.textLayout.formats.BlockProgression;
import flashx.textLayout.formats.Direction;
import frocessing.color.ColorHSV;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.core.easing.IEasing;
import org.libspark.betweenas3.easing.*;
import org.libspark.betweenas3.events.*;
import org.libspark.betweenas3.tweens.IObjectTween;
import org.libspark.betweenas3.tweens.ITween;
/**
* 表示テキスト
* [太宰治]
* http://www.aozora.gr.jp/cards/000035/card301.html
*/
class TextBook extends Sprite
{
private var _text:String = <><![CDATA[ はしがき
私は、その男の写真を三葉、見たことがある。
一葉は、その男の、幼年時代、とでも言うべきであろうか、十歳前後かと推定される頃の写真であって、その子供が大勢の女のひとに取りかこまれ、(それは、その子供の姉たち、妹たち、それから、従姉妹《いとこ》たちかと想像される)庭園の池のほとりに、荒い縞の袴《はかま》をはいて立ち、首を三十度ほど左に傾け、醜く笑っている写真である。醜く? けれども、鈍い人たち(つまり、美醜などに関心を持たぬ人たち)は、面白くも何とも無いような顔をして、
「可愛い坊ちゃんですね」
といい加減なお世辞を言っても、まんざら空《から》お世辞に聞えないくらいの、謂《い》わば通俗の「可愛らしさ」みたいな影もその子供の笑顔に無いわけではないのだが、しかし、いささかでも、美醜に就いての訓練を経て来たひとなら、ひとめ見てすぐ、
「なんて、いやな子供だ」
と頗《すこぶ》る不快そうに呟《つぶや》き、毛虫でも払いのける時のような手つきで、その写真をほうり投げるかも知れない。
まったく、その子供の笑顔は、よく見れば見るほど、何とも知れず、イヤな薄気味悪いものが感ぜられて来る。どだい、それは、笑顔でない。この子は、少しも笑ってはいないのだ。その証拠には、この子は、両方のこぶしを固く握って立っている。人間は、こぶしを固く握りながら笑えるものでは無いのである。猿だ。猿の笑顔だ。ただ、顔に醜い皺《しわ》を寄せているだけなのである。「皺くちゃ坊ちゃん」とでも言いたくなるくらいの、まことに奇妙な、そうして、どこかけがらわしく、へんにひとをムカムカさせる表情の写真であった。私はこれまで、こんな不思議な表情の子供を見た事が、いちども無かった。
第二葉の写真の顔は、これはまた、びっくりするくらいひどく変貌《へんぼう》していた。学生の姿である。高等学校時代の写真か、大学時代の写真か、はっきりしないけれども、とにかく、おそろしく美貌の学生である。しかし、これもまた、不思議にも、生きている人間の感じはしなかった。学生服を着て、胸のポケットから白いハンケチを覗《のぞ》かせ、籐椅子《とういす》に腰かけて足を組み、そうして、やはり、笑っている。こんどの笑顔は、皺くちゃの猿の笑いでなく、かなり巧みな微笑になってはいるが、しかし、人間の笑いと、どこやら違う。血の重さ、とでも言おうか、生命《いのち》の渋さ、とでも言おうか、そのような充実感は少しも無く、それこそ、鳥のようではなく、羽毛のように軽く、ただ白紙一枚、そうして、笑っている。つまり、一から十まで造り物の感じなのである。キザと言っても足りない。軽薄と言っても足りない。ニヤケと言っても足りない。おしゃれと言っても、もちろん足りない。しかも、よく見ていると、やはりこの美貌の学生にも、どこか怪談じみた気味悪いものが感ぜられて来るのである。私はこれまで、こんな不思議な美貌の青年を見た事が、いちども無かった。
もう一葉の写真は、最も奇怪なものである。まるでもう、としの頃がわからない。頭はいくぶん白髪のようである。それが、ひどく汚い部屋(部屋の壁が三箇所ほど崩れ落ちているのが、その写真にハッキリ写っている)の片隅で、小さい火鉢に両手をかざし、こんどは笑っていない。どんな表情も無い。謂わば、坐って火鉢に両手をかざしながら、自然に死んでいるような、まことにいまわしい、不吉なにおいのする写真であった。奇怪なのは、それだけでない。その写真には、わりに顔が大きく写っていたので、私は、つくづくその顔の構造を調べる事が出来たのであるが、額は平凡、額の皺も平凡、眉も平凡、眼も平凡、鼻も口も顎《あご》も、ああ、この顔には表情が無いばかりか、印象さえ無い。特徴が無いのだ。たとえば、私がこの写真を見て、眼をつぶる。既に私はこの顔を忘れている。部屋の壁や、小さい火鉢は思い出す事が出来るけれども、その部屋の主人公の顔の印象は、すっと霧消して、どうしても、何としても思い出せない。画にならない顔である。漫画にも何もならない顔である。眼をひらく。あ、こんな顔だったのか、思い出した、というようなよろこびさえ無い。極端な言い方をすれば、眼をひらいてその写真を再び見ても、思い出せない。そうして、ただもう不愉快、イライラして、つい眼をそむけたくなる。
所謂《いわゆる》「死相」というものにだって、もっと何か表情なり印象なりがあるものだろうに、人間のからだに駄馬の首でもくっつけたなら、こんな感じのものになるであろうか、とにかく、どこという事なく、見る者をして、ぞっとさせ、いやな気持にさせるのだ。私はこれまで、こんな不思議な男の顔を見た事が、やはり、いちども無かった。
]]></>;
private var _flow:TextFlow;
public function TextBook()
{
init();
}
private function init():void
{
_flow = new TextFlow;
_flow.fontFamily = 'ヒラギノ明朝 Pro W3, メイリオ, MS P明朝, _serif';
_flow.fontSize = 16;
_flow.color = 0x000000;
_flow.lineHeight = 22;
_flow.locale = "ja";
_flow.fontLookup = FontLookup.DEVICE;
_flow.direction = Direction.LTR;
_flow.blockProgression = BlockProgression.RL;
var p:ParagraphElement = new ParagraphElement();
var span:SpanElement = new SpanElement();
span.text = _text;
p.addChild(span);
_flow.addChild(p);
_flow.flowComposer.addController(new ContainerController(this, Candle.STAGE_WIDTH, Candle.STAGE_HEIGHT));
_flow.flowComposer.updateAllControllers();
}
}
/**
* 照明さん
* 重いよー
*/
class HaloEffect extends Bitmap
{
private var _haloSize:uint = 200;
private var _countScale:uint = 16;
private var _th:Vector.<uint>;
private var _p:Vector.<Point>;
private var _data:BitmapData;
private var _w:uint;
private var _h:uint;
private var _color:ColorHSV;
private var _tween:ITween;
public function HaloEffect()
{
init();
}
private function init():void
{
_p = new Vector.<Point>;
x = -Candle.STAGE_WIDTH*0.25;
y = -Candle.STAGE_HEIGHT*0.25;
_w = Candle.STAGE_WIDTH*1.5;
_h = Candle.STAGE_HEIGHT*1.5;
_color = new ColorHSV();
_color.h = 35;
_color.s = 0.5;
_color.v = 0;
_data = new BitmapData(_w, _h, true, _color.value | 0xFF<<24);
bitmapData = _data;
_th = _data.getVector(_data.rect);
filters = [new BlurFilter(_countScale, _countScale)];
_tween = BetweenAS3.serial(
BetweenAS3.tween(
this,
{scaleX: 1, scaleY: 1},
{scaleX: 0.99, scaleY: 0.99},
0.1
),
BetweenAS3.tween(
this,
{scaleX: 0.99, scaleY: 0.99},
{scaleX: 1, scaleY: 1},
0.1
)
);
_tween.stopOnComplete = false;
_tween.play();
}
public function addPoint(posX:uint, posY:uint):void
{
posX += Candle.STAGE_WIDTH*0.25;
posY += Candle.STAGE_HEIGHT*0.25;
_p.push(new Point(posX, posY));
}
public function render():void
{
// _data.lock();
var max:uint = _th.length;
var cp:Point = new Point();
var num:uint,dis:Number,p:Point,color:uint;
for(var i:uint=0; i<max; i+=_countScale)
{
cp.x = i%_w;
cp.y = int(i/_h);
num = 0;
for each(p in _p)
{
dis = Point.distance(p, cp);
if(_haloSize > dis)
{
num += _haloSize - dis;
}
}
_color.v = Math.min(num / _haloSize, 1);
color = _color.value | 0xFF<<24;
fillColors(color, i);
}
_data.setVector(_data.rect, _th);
// _data.unlock();
}
private function fillColors(color:uint, index:uint=0):void
{
var max:uint = Math.min(index + _countScale, _th.length);
for(var i:uint=index; i<max; i++)
{
_th[i] = color;
}
}
}
/**
* キャンドル描画
* ハードコード!
*/
class CandleClip extends Sprite
{
private var _g:Graphics;
private var _p:Point;
public function CandleClip(posX:Number, posY:Number)
{
_p = new Point(posX, posY);
init();
}
private function init():void
{
_g = graphics;
makeCandle();
}
private function makeCandle():void
{
//シン
_g.lineStyle(2, 0xFFFFFF);
_g.moveTo(_p.x, _p.y);
_g.lineTo(_p.x, _p.y+10);
//ロウ
_g.lineStyle(NaN, 0xFFFFFF);
var matr:Matrix = new Matrix();
matr.createGradientBox(14, 80, 0, _p.x-10, _p.y+10);
_g.beginGradientFill(
GradientType.LINEAR,
[0xFFFFFF, 0x888888],
[1,1],
[0x66, 0xFF],
matr
);
_g.drawRoundRect(_p.x-7, _p.y+10, 14, 80, 2);
_g.endFill();
//ロウソクタテ
_g.lineStyle(1, 0x333333);
matr = new Matrix();
matr.createGradientBox(30, Candle.STAGE_HEIGHT - (_p.y+90), 0, _p.x-15, _p.y+110);
_g.beginGradientFill(
GradientType.LINEAR,
[0x333333, 0x000000],
[1,1],
[0x77, 0xAA],
matr
);
_g.moveTo(_p.x-15, _p.y+90);
_g.lineTo(_p.x+15, _p.y+90);
_g.lineTo(_p.x+3, _p.y+95);
_g.lineTo(_p.x+3, Math.max(Candle.STAGE_HEIGHT, _p.y+115));
_g.lineTo(_p.x-3, Math.max(Candle.STAGE_HEIGHT, _p.y+115));
_g.lineTo(_p.x-3, _p.y+95);
_g.lineTo(_p.x-15, _p.y+90);
_g.endFill();
}
}
/**
* 炎エフェクト(TeraFire)
* http://www.trick7.com/blog/2008/07/27-205806.php
* http://www.libspark.org/svn/as3/TeraFire/src/com/trick7/effects/TeraFire.as
* ブログいつも拝見してますー
*/
class TeraFire extends Sprite{
//横方向ゆらぎ速度
public var phaseRateX:Number;
//縦方向ゆらぎ速度
public var phaseRateY:Number;
private var offsets:Array= [new Point(),new Point()];
private var seed:Number = Math.random();
private var fireW:Number;
private var fireH:Number;
//火の色
//private var fireColorIn:uint;
//private var fireColorOut:uint;
private var ball:Sprite;
private var gradientImage:BitmapData;
private var displaceImage:BitmapData;
//火の玉の中心の上下位置偏差(-1で上端、1で下端)
private var focalPointRatio:Number = 0.6;
//炎の揺らぎのせいで描画エリアをはみ出してしまうのを防ぐための余白幅
private const margin:int = 10;
private var rdm:Number;
//コンストラクタ
public function TeraFire(xPos:Number=0, yPos:Number=0, fireWidth:Number=20, fireHeight:Number=80){
fireW = fireWidth;
fireH = fireHeight;
phaseRateX = 0;
phaseRateY = 5;
var matrix:Matrix = new Matrix();
matrix.createGradientBox(fireW,fireH,Math.PI/2,-fireW/2,-fireH*(focalPointRatio+1)/2);
var colors:Array = [0xff9c00, 0xe25609, 0xe25609];
var alphas:Array = [1,1,0];
var ratios:Array = [20, 80, 220];
var home:Sprite = new Sprite();
ball = new Sprite();
//炎本体
ball.graphics.beginGradientFill(GradientType.RADIAL,colors, alphas, ratios, matrix,"pad","rgb",focalPointRatio);
ball.graphics.drawEllipse(-fireW/2,-fireH*(focalPointRatio+1)/2,fireW,fireH);
ball.graphics.endFill();
//余白確保用透明矩形
ball.graphics.beginFill(0x000000,0);
ball.graphics.drawRect(-fireW/2,0,fireW+margin,1);
ball.graphics.endFill();
addChild(home);
home.addChild(ball);
this.x = xPos -2.5;
this.y = yPos - 3;
addEventListener(Event.ENTER_FRAME,loop);
//ゆらぎ用のBitmap(ステージに貼付ける必要はないのでBitmapに貼る必要はない)
displaceImage = new BitmapData(fireW+margin,fireH,false,0xFFFFFFFF);
//火の芯付近の揺らぎを抑える用のグラデーション
var matrix2:Matrix = new Matrix();
matrix2.createGradientBox(fireW+margin,fireH,Math.PI/2,0,0);
var gradient_mc:Sprite = new Sprite;
gradient_mc.graphics.beginGradientFill(GradientType.LINEAR,[0x666666,0x666666], [0,1], [120,220], matrix2);
gradient_mc.graphics.drawRect(0,0,fireW+margin,fireH);//drawのターゲットなので生成位置にこだわる必要はない。
gradient_mc.graphics.endFill();
gradientImage = new BitmapData(fireW+margin,fireH,true,0x00FFFFFF);
gradientImage.draw(gradient_mc);//gradient_mcを消す必要は?
//同サイズの炎の揺らぎをランダム化
rdm = Math.floor(Math.random()*10);
}
private function loop(e:Event):void{
//もやもや画像を上スクロール移動させる
for(var i:int = 0; i < 2; ++i){
offsets[i].x += phaseRateX;
offsets[i].y += phaseRateY;
}
//もやもやした白黒画像を生成
displaceImage.perlinNoise(30+rdm, 60+rdm, 2, seed, false, false, 7, true, offsets);
//芯付近の揺らぎを抑える
displaceImage.copyPixels(gradientImage,gradientImage.rect,new Point(),null, null, true);
var dMap:DisplacementMapFilter = new DisplacementMapFilter(displaceImage, new Point(), 1, 1, 20, 10, DisplacementMapFilterMode.CLAMP);
ball.filters = [dMap];
}
}