Happy Tiger Year 2010
小さい頃に、遊びませんでしたか?クレヨンで塗りつぶした
絵を、上から釘で削って絵を描く手法。あれを再現してみました。
/**
* Copyright utabi ( http://wonderfl.net/user/utabi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/1nCF
*/
// forked from nengafl's nengafl
//
// 小さい頃に、遊びませんでしたか?クレヨンで塗りつぶした
// 絵を、上から釘で削って絵を描く手法。あれを再現してみました。
//
package {
import flash.display.GradientType;
import flash.display.SpreadMethod;
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.display.StageScaleMode;
import flash.display.StageAlign;
import flash.display.BlendMode;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.events.*;
import flash.geom.Point;
import flash.geom.ColorTransform;
import flash.ui.Mouse;
import flash.geom.Matrix;
import flash.text.TextField;
[SWF(width=465, height=465, frameRate=30, backgroundColor=0xffffff)]
public class DocumentClass extends Sprite {
private var backGround:ImageClip;
private var board:MovieClip;
private var blackMC:ImageClip;
private var buttonsMC:MovieClip;
private var material_eraser:ImageClip;
private var material_nail:ImageClip;
private var material_palm:ImageClip;
private var material_thumb:ImageClip;
private var cursorMC:MovieClip;
private var eraser:ImageClip;
private var nail:ImageClip;
private var palm:ImageClip;
private var thumb:ImageClip;
private var hittestObject:Sprite;
private var messages:MovieClip;
private var m1:ImageClip;
private var m2:ImageClip;
private var drawSprite:Sprite;
private var drawSpriteA:Sprite;
private var drawSpriteB:Sprite;
private var drawSpriteC:Sprite;
private var buttons:Array = [];
private var cursors:Array = [];
private var drawingIsEnable:Boolean=false;
private var drawingMaterial:String="nail";
private var bmd:BitmapData;
private var bmdSmall:BitmapData;
private var bm:Bitmap;
private var palmAX:int=-13,palmBX:int=17,palmCX:int=33;
private var palmAY:int=6,palmBY:int=-7,palmCY:int=-6;
private var selectedCT:ColorTransform=new ColorTransform(1,1,1,1,0,-50,-205,0);
private var attentionCT:ColorTransform=new ColorTransform(1,1,1,1,0,-255,-255,0);
private var normalCT:ColorTransform=new ColorTransform(1,1,1,1,0,0,0,0);
private var mSmall:Matrix = new Matrix();
private var scratchRatio:Number = 0;
private var isErasedHalf:Boolean = false;
public function DocumentClass() {
stage.scaleMode = StageScaleMode.NO_SCALE;
backGround = new ImageClip();
backGround.loaderVisible = false;
backGround.visible = false;
backGround.load("http://pokeal.com/happy-tiger-year/wonderfl/tiger.jpg");
addChild(backGround);
board = new MovieClip();
board.blendMode = BlendMode.MULTIPLY;
addChild(board);
blackMC = new ImageClip();
blackMC.imageStyle = {width:465,height:465};
blackMC.load("http://pokeal.com/happy-tiger-year/wonderfl/black.jpg");
board.addChild(blackMC);
blackMC.addEventListener(ImageClip.READY_TO_DISPLAY,function(e:Event):void{backGround.visible = true;});
buttonsMC = new MovieClip();
addChild(buttonsMC);
buttonsMC.x = 270;
buttonsMC.y = 410;
material_eraser = new ImageClip();
material_eraser.visible = false;
material_eraser.load("http://pokeal.com/happy-tiger-year/wonderfl/eraser_small.png");
buttonsMC.addChild(material_eraser);
material_nail = new ImageClip();
material_nail.load("http://pokeal.com/happy-tiger-year/wonderfl/nail_small.png");
buttonsMC.addChild(material_nail);
material_nail.x = 60;
material_palm = new ImageClip();
material_palm.load("http://pokeal.com/happy-tiger-year/wonderfl/palm_small.png");
buttonsMC.addChild(material_palm);
material_palm.x = 100;
material_palm.y = -3;
material_thumb = new ImageClip();
material_thumb.load("http://pokeal.com/happy-tiger-year/wonderfl/thumb_small.png");
buttonsMC.addChild(material_thumb);
material_thumb.x = 150;
material_thumb.y = -2;
buttons = [material_nail, material_palm, material_thumb, material_eraser];
cursorMC = new MovieClip();
addChild(cursorMC);
hittestObject = new Sprite();
hittestObject.graphics.beginFill(0,0);
hittestObject.graphics.drawRect(0,0,1,1);
hittestObject.graphics.endFill();
cursorMC.addChild(hittestObject);
eraser = new ImageClip();
eraser.load("http://pokeal.com/happy-tiger-year/wonderfl/eraser.png");
cursorMC.addChild(eraser);
eraser.x = -100;
eraser.y = -100;
nail = new ImageClip();
nail.load("http://pokeal.com/happy-tiger-year/wonderfl/nail.png");
cursorMC.addChild(nail);
nail.x = -1;
nail.y = -118;
palm = new ImageClip();
palm.load("http://pokeal.com/happy-tiger-year/wonderfl/palm.png");
cursorMC.addChild(palm);
palm.x = -17;
palm.y = -10;
thumb = new ImageClip();
thumb.load("http://pokeal.com/happy-tiger-year/wonderfl/thumb.png");
cursorMC.addChild(thumb);
thumb.x = -30;
thumb.y = -30;
cursors = [nail, palm, thumb, eraser];
messages = new MovieClip();
addChild(messages);
messages.x = 15;
messages.y = 415;
m1 = new ImageClip();
m1.visible = false;
m1.load("http://pokeal.com/happy-tiger-year/wonderfl/message01.png");
messages.addChild(m1);
m2 = new ImageClip();
m2.visible = false;
m2.load("http://pokeal.com/happy-tiger-year/wonderfl/message02.png");
messages.addChild(m2);
mSmall.scale(1/10,1/10);
bmdSmall = new BitmapData(465/10,465/10,true,0xff000000);
bmd=new BitmapData(465,465,true,0);
bm=new Bitmap(bmd,"auto",true);
board.addChild(bm);
onClickNail();
addEventListener(MouseEvent.MOUSE_DOWN,enable);
addEventListener(MouseEvent.MOUSE_MOVE,drawing);
addEventListener(MouseEvent.MOUSE_UP,disable);
//addEventListener(Event.ENTER_FRAME,onEnterFrames);
material_nail.addEventListener(MouseEvent.CLICK,onClickNail);
material_palm.addEventListener(MouseEvent.CLICK,onClickPalm);
material_thumb.addEventListener(MouseEvent.CLICK,onClickThumb);
material_eraser.addEventListener(MouseEvent.CLICK,onClickEraser);
}
private function enable(e:MouseEvent):void {
drawingIsEnable=true;
drawSprite = new Sprite();
drawSprite.graphics.moveTo(board.mouseX,board.mouseY);
board.addChild(drawSprite);
if (drawingMaterial=="palm") {
drawSpriteA = new Sprite();
drawSpriteB = new Sprite();
drawSpriteC = new Sprite();
board.addChild(drawSpriteA);
board.addChild(drawSpriteB);
board.addChild(drawSpriteC);
drawSpriteA.graphics.moveTo(board.mouseX+palmAX,board.mouseY+palmAY);
drawSpriteB.graphics.moveTo(board.mouseX+palmBX,board.mouseY+palmBY);
drawSpriteC.graphics.moveTo(board.mouseX+palmCX,board.mouseY+palmCY);
}
switch (drawingMaterial) {
case "nail" :
drawSprite.graphics.lineStyle(1,0xffffff,1);
break;
case "palm" :
drawSprite.graphics.lineStyle(2,0xffffff);
drawSpriteA.graphics.lineStyle(2,0xffffff);
drawSpriteB.graphics.lineStyle(2,0xffffff);
drawSpriteC.graphics.lineStyle(2,0xffffff);
break;
case "thumb" :
drawSprite.graphics.lineStyle(40,0xffffff,0.1);
break;
case "eraser" :
drawSprite.graphics.lineStyle(200,0xffffff,1);
break;
}
}
private function drawing(e:MouseEvent):void {
if (drawingIsEnable) {
switch (drawingMaterial) {
case "nail" :
drawSprite.graphics.lineTo(board.mouseX,board.mouseY);
break;
case "palm" :
drawSprite.graphics.lineTo(board.mouseX,board.mouseY);
drawSpriteA.graphics.lineTo(board.mouseX+palmAX,board.mouseY+palmAY);
drawSpriteB.graphics.lineTo(board.mouseX+palmBX,board.mouseY+palmBY);
drawSpriteC.graphics.lineTo(board.mouseX+palmCX,board.mouseY+palmCY);
break;
case "thumb" :
drawSprite.graphics.lineStyle(40,0xffffff,0.1); //ここにこれを入れてやることで、「塗り続けるとどんどん濃くなる」が表現できる
drawSprite.graphics.lineTo(board.mouseX,board.mouseY);
break;
case "eraser" :
drawSprite.graphics.lineTo(board.mouseX,board.mouseY);
break;
}
}
cursorMC.x=mouseX;
cursorMC.y=mouseY;
//カーソルの基準点がbuttonsMC内なら、通常カーソルに。buttonsMC外なら特殊カーソルに。
if (hittestObject.hitTestObject(buttonsMC) && !drawingIsEnable) {
Mouse.show();
cursorMC.visible=false;
} else {
Mouse.hide();
cursorMC.visible=true;
}
}
private function disable(e:MouseEvent):void {
drawingIsEnable=false;
//動作を軽くするために、BitmapDataに変換して入れ替える
bmd.draw(drawSprite,null,null,BlendMode.NORMAL,null,true);
board.removeChild(drawSprite);
if (drawingMaterial=="palm") {
bmd.draw(drawSpriteA,null,null,BlendMode.NORMAL,null,true);
bmd.draw(drawSpriteB,null,null,BlendMode.NORMAL,null,true);
bmd.draw(drawSpriteC,null,null,BlendMode.NORMAL,null,true);
board.removeChild(drawSpriteA);
board.removeChild(drawSpriteB);
board.removeChild(drawSpriteC);
}
ckeckScratch();
}
private function onClickNail(e:MouseEvent = undefined):void {
drawingMaterial="nail";
buttonIsSelected(material_nail);
cursorIsChanged(nail);
}
private function onClickPalm(e:MouseEvent):void {
drawingMaterial="palm";
buttonIsSelected(material_palm);
cursorIsChanged(palm);
}
private function onClickThumb(e:MouseEvent):void {
drawingMaterial="thumb";
buttonIsSelected(material_thumb);
cursorIsChanged(thumb);
}
private function onClickEraser(e:MouseEvent):void {
drawingMaterial="eraser";
buttonIsSelected(material_eraser);
cursorIsChanged(eraser);
}
private function buttonIsSelected(mc:MovieClip):void{
//ボタンの色をかえる。選択されていないものは、もとに戻す
for (var i:int = 0; i < buttons.length; i++){
if (mc == buttons[i]){
mc.transform.colorTransform=selectedCT;
} else {
buttons[i].transform.colorTransform=normalCT;
}
}
}
private function cursorIsChanged(mc:MovieClip):void{
//カーソルをかえる
for (var i:int = 0; i < cursors.length; i++){
if (mc == cursors[i]){
mc.visible=true;
} else {
cursors[i].visible = false;
}
}
}
private function onEnterFrames(e:Event):void {
}
private function ckeckScratch():void {
// 描画率を計算する。すべてのピクセルをfor文でまわすと時間がかかるので、一度画像を縮小してから計算する。
var numWhite:int = 0;
bmdSmall.draw(bmd,mSmall);
for (var y:int = 0; y < bmdSmall.height ; y ++){
for (var x:int = 0; x < bmdSmall.width ; x ++){
if(bmdSmall.getPixel(x,y) > 0){
//黒でないピクセルを合計
numWhite ++;
}
}
}
scratchRatio = numWhite/(bmdSmall.height*bmdSmall.width);
//trace(scratchRatio);
if(0.1 < scratchRatio && scratchRatio < 0.8){
//10%以上描いたら、何かが出る
m1.visible = true;
if(!material_eraser.visible) {
//最初だけわかりやすく、色をつける
material_eraser.transform.colorTransform=attentionCT;
}
material_eraser.visible = true;
} else if (scratchRatio >= 0.8){
//80%以上描いたら、何かが出る
m1.visible = false;
m2.visible = true;
}
}
}
}
////////////////////////////////////////////
// ここから下は ImageClip Class
////////////////////////////////////////////
// ImageClipクラスだけで別に投稿してます
// http://wonderfl.net/code/b5e4a53e5ea9cf4a188ef30313a7d6d327144c10
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.ProgressEvent;
import flash.events.IOErrorEvent;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.Shape;
import flash.text.TextField;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import caurina.transitions.Tweener;
class ImageClip extends MovieClip {
public static const READY_TO_DISPLAY:String = "ready_to_display";
private var _imageStyle:Object = new Object();
private var _loaderStyle:Object = new Object();
private var imgLoader:Loader;
private var tmpLoader:Loader;
private var imageMask:Shape;
private var req:URLRequest;
private var donut:Donut;
private var bmp:Bitmap;
private var imageType:String;
private var areaWidth:Number;
private var areaHeight:Number;
private var bg:Shape;
private var bgColor:int;
private var bgAlpha:Number;
private var bgVisible:Boolean;
private var padding:Number;
private var _loaderVisible:Boolean = true;
//private var _imageVisible:Boolean = true;
public function ImageClip() {
super();
}
private function init():void{
_imageStyle.type ? imageType = _imageStyle.type : imageType = "original";
_imageStyle.width ? areaWidth = _imageStyle.width : areaWidth = 100;
_imageStyle.height ? areaHeight = _imageStyle.height : areaHeight = 100;
_imageStyle.bgColor ? bgColor = _imageStyle.bgColor : bgColor = 0;
_imageStyle.bgAlpha ? bgAlpha = _imageStyle.bgAlpha : bgAlpha = 1;
_imageStyle.padding ? padding = _imageStyle.padding : padding = 0;
_imageStyle.bgVisible ? bgVisible = _imageStyle.bgVisible : bgVisible = false;
if(!_imageStyle.width && !_imageStyle.height){
_loaderVisible = false;
}
if(bgVisible){
bg = new Shape();
bg.graphics.beginFill(bgColor,bgAlpha);
bg.graphics.drawRect(0,0,areaWidth,areaHeight);
bg.graphics.endFill();
addChild(bg);
}
imageMask = new Shape();
imageMask.graphics.beginFill(0,1);
imageMask.graphics.drawRect(0,0,areaWidth - (padding*2), areaHeight - (padding*2));
imageMask.x = padding;
imageMask.y = padding;
imgLoader = new Loader();
imgLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, imageOnProgress);
imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,imageOnLoaded);
imgLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, imageIOError);
if(_loaderVisible){
donut = new Donut(_loaderStyle, areaWidth, areaHeight);
addChild(donut);
}
}
private function imageOnProgress(event:ProgressEvent):void {
if(_loaderVisible){
var ratio:Number = event.bytesLoaded/event.bytesTotal;
donut.loadedRatio = ratio;
}
}
private function imageIOError(event:Event):void {
imgLoader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, imageOnProgress);
imgLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE,imageOnLoaded);
imgLoader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, imageIOError);
if(_loaderVisible){
donut.removeEventListener(Donut.TWEEN_COMPLETE, displayImage);
donut.kill();
removeChild(donut);
}
// エラー表示
var errorBGColor:int;
var errorLineColor:int;
_loaderStyle.bgColor ? errorBGColor = _loaderStyle.bgColor : errorBGColor = 0x333333;
_loaderStyle.color ? errorLineColor = _loaderStyle.color : errorLineColor = 0xaaaaaa;
var errorBox:Sprite = new Sprite();
errorBox.graphics.beginFill(errorBGColor,1);
errorBox.graphics.drawRect(0,0,areaWidth,areaHeight);
errorBox.graphics.endFill();
errorBox.graphics.lineStyle(1,errorLineColor,1);
errorBox.graphics.lineTo(areaWidth,areaHeight);
errorBox.graphics.moveTo(0,areaHeight);
errorBox.graphics.lineTo(areaWidth,0);
addChild(imageMask);
errorBox.mask = imageMask;
addChild(errorBox);
this.alpha = .2;
trace(event);
// TODO // クロスドメイン無しのアラートは可能か?
}
private function imageOnLoaded(event:Event):void {
imgLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE,imageOnLoaded);
imgLoader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, imageOnProgress);
imgLoader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, imageIOError);
tmpLoader = new Loader();
tmpLoader.contentLoaderInfo.addEventListener(Event.INIT, tmpOnLoaded);
tmpLoader.loadBytes(imgLoader.contentLoaderInfo.bytes);
}
private function tmpOnLoaded(event:Event):void {
tmpLoader.contentLoaderInfo.removeEventListener(Event.INIT, tmpOnLoaded);
var loader:Loader = event.currentTarget.loader;
var bd:BitmapData = new BitmapData(loader.content.width, loader.content.height, true, 0x00ffffff);
bd.draw(loader.content);
bmp = new Bitmap(bd);
bmp.smoothing = true;
if(_loaderVisible){
donut.swapContent = bmp;
donut.addEventListener(Donut.TWEEN_COMPLETE, function(e:Event):void{
dispatchEvent(new Event(READY_TO_DISPLAY))
});
} else {
dispatchEvent(new Event(READY_TO_DISPLAY));
}
displayImage();
}
private function displayImage(event:Event = undefined):void {
if(_loaderVisible){
donut.removeEventListener(Donut.TWEEN_COMPLETE, displayImage);
}
var areaAspectRatio:Number = areaWidth/areaHeight;
var bmpAspectRatio:Number = bmp.width/bmp.height;
var bmpRatioIsHigher:Boolean = ((bmpAspectRatio - areaAspectRatio) >= 0);
switch (imageType){
case "original":
break;
case "fit":
bmp.width = areaWidth - (padding*2);
bmp.height = areaHeight - (padding*2);
bmp.x = padding;
bmp.y = padding;
break;
case "auto":
bmpRatioIsHigher ? adjustHeightFirst() : adjustWidthFirst();
addChild(imageMask);
bmp.mask = imageMask;
break;
case "show all":
bmpRatioIsHigher ? adjustWidthFirst() : adjustHeightFirst();
break;
case "trim center":
bmp.y = (areaHeight - bmp.height)/2;
bmp.x = (areaWidth - bmp.width)/2;
addChild(imageMask);
bmp.mask = imageMask;
break;
}
addChild(bmp);
function adjustWidthFirst():void{
bmp.width = areaWidth - (padding*2);
bmp.height = bmp.width/bmpAspectRatio;
bmp.x = padding;
bmp.y = (areaHeight - bmp.height)/2;
}
function adjustHeightFirst():void{
bmp.height = areaHeight - (padding*2);
bmp.width = bmp.height*bmpAspectRatio;
bmp.x = (areaWidth - bmp.width)/2;
bmp.y = padding;
}
}
public function load(url:String):void {
init();
req = new URLRequest(url);
imgLoader.load(req,new LoaderContext(true));
}
public function set imageStyle(o:Object):void {
_imageStyle = o;
}
/*public function set imageVisible(b:Boolean):void {
_imageVisible = b;
}*/
public function set loaderStyle(o:Object):void {
_loaderStyle = o;
}
public function set loaderVisible(b:Boolean):void {
_loaderVisible = b;
}
}
////////////////////////////////
// Donut Class
////////////////////////////////
// ImageClipクラスとセットで使う。ドーナツを描くためのクラス。
import flash.display.Shape;
import flash.display.Bitmap;
import frocessing.display.*;
import flash.events.EventDispatcher;
class Donut extends F5MovieClip2DBmp {
private var bg:Shape;
private var _style:Object = new Object();
private var _loadedRatio:Number = 0;
private var _radius:Number;
private var _weight:Number;
private var _color:int;
private var _bgColor:int;
private var lastRadian:Number = 0;
private var acceleration:Number = 8;
private var isLoadedEnough:Boolean = false;
private var _swapContent:Bitmap;
public static const TWEEN_COMPLETE:String = "load_complete";
public function Donut(style:Object, areaWidth:Number, areaHeight:Number):void {
super();
if(style) { _style = style };
_style.radius ? _radius = _style.radius : _radius = 15;
_style.weight ? _weight = _style.weight : _weight = 5;
_style.color ? _color = _style.color : _color = 0xaaaaaa;
_style.bgColor ? _bgColor = _style.bgColor : _bgColor = 0x666666;
this.x = (areaWidth/2)-_radius-1;
this.y = (areaHeight/2)-_radius-1;
}
public function setup():void {
bg = new Shape();
bg.graphics.beginFill(_bgColor,1);
bg.graphics.drawCircle(_radius+1,_radius+1,_radius);
bg.graphics.drawCircle(_radius+1,_radius+1,_radius-_weight);
bg.graphics.endFill();
addChild(bg);
size(_radius*2+2,_radius*2+2);
background(255,0);
fill(_color);
stroke(0,0);
}
public function draw():void {
background(255,0);
translate(_radius+1,_radius+1);
var targetRadian:Number = Math.PI*2/(360/_loadedRatio);
var amount:Number = lastRadian+(targetRadian - lastRadian)/acceleration;
if(amount < 6.283185307179583){
beginShape();
moveTo(0,-_radius);
arcTo(0, 0, _radius, _radius, 0, amount, -Math.PI/2);
arcTo(0, 0, _radius-_weight, _radius-_weight, amount, 0, -Math.PI/2);
endShape();
}
lastRadian = amount;
if(amount >= 3.14){
acceleration = 4
}
if(amount >= 6.26){
this.alpha -= .1;
if(!isLoadedEnough){
isLoadedEnough = true;
}
if(isLoadedEnough && _swapContent){
_swapContent.alpha = 1-this.alpha;
}
if(this.alpha <= 0){
dispatchEvent(new Event(TWEEN_COMPLETE));
noLoop();
}
}
}
public function set loadedRatio(n:Number):void{
_loadedRatio = n*360;
}
public function set swapContent(bmp:Bitmap):void{
_swapContent = bmp;
_swapContent.alpha = 0;
}
public function kill():void{
noLoop();
}
}