CharacterSprite Viewer
キャラクターチップ(歩行グラフィック)を取り込んで表示する、簡易ビューワーです。
各パラメータをもとに、カーソルキーで操作できるキャラクタースプライトを生成します。
各コンポーネントの役割
-importボタン キャラクターチップの読み込み
-元画像の表示倍率を変更
-透過色を指定するピッカー(元画像にマウスを乗せると、マウス位置にある色がピックアップされるので、透過させたい色のところでクリックで決定)
-アニメーション列の分割数
-方向行を、プリセットまたは個別に指定
-フレームレートの変更
-キャラクターの移動量の変更
まとめ
http://d.hatena.ne.jp/nenjiru/20110914/charachip_viewer
/**
* Copyright nenjiru ( http://wonderfl.net/user/nenjiru )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/gZyx
*/
package
{
import com.bit101.components.ComboBox;
import com.bit101.components.NumericStepper;
import com.bit101.components.PushButton;
import com.bit101.components.Style;
import flash.display.Bitmap;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.net.FileFilter;
import flash.net.FileReference;
import flash.net.URLRequest;
import flash.system.LoaderContext;
[SWF(frameRate="60", width="465", height="465")]
/**
* キャラクタースプライト簡易ビューワー
*
* @author nenjiru
*/
public class CharacterSpriteViewer extends Sprite
{
private static const URL:String = "http://assets.wonderfl.net/images/related_images/c/c7/c7e1/c7e1afcd9030542ec89c8639ee2acc9d529d0cea";
private static const PRESET_A:Vector.<String> = Vector.<String>(["front", "left", "right", "back"]);
private static const PRESET_B:Vector.<String> = Vector.<String>(["back", "right", "front", "left"]);
private var rowIndex:Vector.<String>;
private var source:Bitmap;
private var canvas:GridCanvas;
private var character:Player;
private var colStepper:NumericStepper;
private var rowPreset:ComboBox;
private var rowSelector:Vector.<RowSelectButton>;
private var zoom1:PushButton;
private var zoom2:PushButton;
private var colorChip:ColorChip;
private var colorMonitor:ColorMonitor;
private var frameRate:NumSlider;
private var speedRate:NumSlider;
public function CharacterSpriteViewer():void
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
//Style.BUTTON_DOWN = 0xBCBCBC;
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaded);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, trace);
loader.load(new URLRequest(URL), new LoaderContext(true));
var file:FileReference = new FileReference();
file.addEventListener(Event.COMPLETE, function (event:Event):void
{
loader.loadBytes((event.currentTarget as FileReference).data);
});
file.addEventListener(Event.SELECT, function (event:Event):void
{
file.load();
});
var importButton:PushButton = new PushButton(this, 5, 5, "import");
importButton.setSize(70, 16);
importButton.addEventListener(MouseEvent.CLICK, function ():void
{
file.browse([new FileFilter("Image", "*.jpg;*.jpeg;*.gif;*.png")]);
});
init();
}
/**
* コンポーネント系の初期化
*/
private function init():void
{
zoom1 = new PushButton(this, 81, 5, "x1");
zoom1.toggle = true;
zoom1.setSize(30, 16);
zoom1.addEventListener(MouseEvent.CLICK, function (e:MouseEvent):void
{
source.scaleX = source.scaleY = 1;
canvasUpdate();
zoom2.selected = false;
});
zoom2 = new PushButton(this, 110, 5, "x2");
zoom2.toggle = true;
zoom2.setSize(30, 16);
zoom2.addEventListener(MouseEvent.CLICK, function (e:MouseEvent):void
{
source.scaleX = source.scaleY = 2;
canvasUpdate();
zoom1.selected = false;
});
colorChip = addChild(new ColorChip()) as ColorChip;
colorMonitor = addChild(new ColorMonitor()) as ColorMonitor;
colorMonitor.addEventListener(Event.CHANGE, colorHandler);
colorMonitor.x = 74;
colorMonitor.y = 35;
colStepper = new NumericStepper(this, 5, 56);
colStepper.setSize(60, 16);
colStepper.minimum = 1;
colStepper.addEventListener(Event.CHANGE, colStepHandler);
rowSelector = Vector.<RowSelectButton>([
new RowSelectButton(this, 5, 80, rowSelectHandler),
new RowSelectButton(this, 5, 100, rowSelectHandler),
new RowSelectButton(this, 5, 120, rowSelectHandler),
new RowSelectButton(this, 5, 140, rowSelectHandler)
]);
rowPreset = new ComboBox(this, 70, 56, "PRESET A", ["PRESET A", "PRESET B"]);
rowPreset.setSize(70, 16);
rowPreset.addEventListener(Event.SELECT, rowPresetHandler);
rowPreset.numVisibleItems = 2;
frameRate = addChild(new NumSlider("FPS ", 1, 60)) as NumSlider;
frameRate.addEventListener(Event.CHANGE, frameRateHandler);
frameRate.x = 30;
frameRate.y = 165;
speedRate = addChild(new NumSlider("SPEED ", 1, 10)) as NumSlider;
speedRate.addEventListener(Event.CHANGE, speedRateHandler);
speedRate.x = 30;
speedRate.y = 180;
canvas = addChild(new GridCanvas()) as GridCanvas;
canvas.x = 150;
canvas.y = 5;
canvas.addEventListener(MouseEvent.MOUSE_OVER, colorPickerEnable);
canvas.addEventListener(MouseEvent.MOUSE_OUT, colorPickerEnable);
canvas.addEventListener(MouseEvent.MOUSE_MOVE, colorPickerHandler);
canvas.addEventListener(MouseEvent.MOUSE_DOWN, getMaskColor);
}
/**
* 画像の読み込み完了
*/
private function loaded(event:Event):void
{
var loaderInfo:LoaderInfo = event.target as LoaderInfo;
colStepper.value = 3;
colorMonitor.value = 0xFF99CC33;
frameRate.value = 12;
speedRate.value = 4;
source = loaderInfo.content as Bitmap;
canvas.setBitmap(source);
canvasUpdate();
zoom2.selected = true;
zoom2.dispatchEvent(new MouseEvent(MouseEvent.CLICK));
colStepper.maximum = source.width / 4;
rowPreset.selectedIndex = 0;
}
/**
* グリッドと塗りを更新
*/
private function canvasUpdate():void
{
canvas.drawGrid(source.width, source.height, 4, colStepper.value);
}
/**
* キャラクターの生成
*/
private function createCharacter():void
{
var posX:Number, posY:Number;
if (character)
{
character.stop();
stage.removeEventListener(KeyboardEvent.KEY_DOWN, character.keyDownHandler);
stage.removeEventListener(KeyboardEvent.KEY_UP, character.keyUpHandler);
removeChild(character);
posX = character.x;
posY = character.y;
}
var chip:CharacterBitmap = new CharacterBitmap(source.bitmapData, 4, colStepper.value, colorMonitor.value);
character = new Player(chip, frameRate.value, rowIndex, speedRate.value);
stage.addEventListener(KeyboardEvent.KEY_DOWN, character.keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, character.keyUpHandler);
character.x = posX || (465 - character.width) >> 1;
character.y = posY || (465 - character.height) >> 1;
character.start();
addChild(character);
}
/**
* 列変更
*/
private function colStepHandler(event:Event):void
{
canvasUpdate();
createCharacter();
}
/**
* 行プリセット
*/
private function rowPresetHandler(event:Event):void
{
switch (rowPreset.selectedIndex)
{
case 0:
rowIndex = PRESET_A;
rowSelector[0].selectIndex = 0;
rowSelector[1].selectIndex = 1;
rowSelector[2].selectIndex = 2;
rowSelector[3].selectIndex = 3;
break;
case 1:
rowIndex = PRESET_B;
rowSelector[0].selectIndex = 3;
rowSelector[1].selectIndex = 1;
rowSelector[2].selectIndex = 2;
rowSelector[3].selectIndex = 0;
break;
}
createCharacter();
}
/**
* 行設定のトグル変更
*/
private function rowSelectHandler(target:RowSelectButton):void
{
var index:Array = [];
for (var i:int = 0, n:int = rowSelector.length; i < n; i++)
{
if (target !== rowSelector[i] && target.selectIndex === rowSelector[i].selectIndex)
{
rowSelector[i].selectIndex = target.changeBeforeIndex;
}
index.push(rowSelector[i].selectLabel);
}
rowIndex = Vector.<String>(index);
createCharacter();
}
/**
* スライダーハンドラ
*/
private function frameRateHandler(event:Event):void
{
character.frameRate = frameRate.value;
}
/**
* スライダーハンドラ
*/
private function speedRateHandler(event:Event):void
{
character.speed = speedRate.value;
}
/**
* 透過色変更
*/
private function colorHandler(event:Event):void
{
createCharacter();
}
/**
* カラーピッカー表示切り替え
*/
private function colorPickerEnable(event:MouseEvent):void
{
if (event.type == MouseEvent.MOUSE_OVER)
{
stage.addChild(colorChip);
}
else
{
stage.removeChild(colorChip);
}
}
/**
* カラーピッカー
*/
private function colorPickerHandler(event:MouseEvent):void
{
colorChip.x = stage.mouseX + 16;
colorChip.y = stage.mouseY;
colorChip.color = source.bitmapData.getPixel32(event.localX / source.scaleX, event.localY / source.scaleY);
}
/**
* 透過色を決定
*/
private function getMaskColor(event:MouseEvent):void
{
colorMonitor.value = colorChip.color;
createCharacter();
}
}
}
import com.bit101.components.HSlider;
import com.bit101.components.InputText;
import com.bit101.components.Label;
import com.bit101.components.PushButton;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObjectContainer;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.FocusEvent;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.ui.Keyboard;
/**
* グリッドキャンバス
*/
class GridCanvas extends Sprite
{
private var _grid:Shape;
private var _pallet:BitmapData;
public function GridCanvas()
{
_grid = addChild(new Shape()) as Shape;
_pallet = new BitmapData(16, 16);
_pallet.fillRect(new Rectangle(0, 0, 8, 8), 0xFFCCCCCC);
_pallet.fillRect(new Rectangle(8, 8, 8, 8), 0xFFCCCCCC);
}
public function setBitmap(target:Bitmap):void
{
if (numChildren > 1)
{
removeChildAt(0);
}
addChildAt(target, 0);
}
public function drawGrid(width:int, height:int, row:int, col:int):void
{
graphics.clear();
graphics.beginBitmapFill(_pallet);
graphics.drawRect(0, 0, width, height);
graphics.endFill();
_grid.graphics.clear();
_grid.graphics.lineStyle(0, 0x4AFFFF);
verticalLine(col + 1, height, --width / col);
horizontalLine(row + 1, width, --height / row);
}
private function verticalLine(col:int, canvasHeight:int, equalWidth:Number):void
{
for (var i:int = 0; i < col; i++)
{
_grid.graphics.moveTo(equalWidth * i, 0);
_grid.graphics.lineTo(equalWidth * i, canvasHeight);
}
}
private function horizontalLine(row:int, canvasWidth:int, equalHeight:Number):void
{
for (var i:int = 0; i < row; i++)
{
_grid.graphics.moveTo(0, equalHeight * i);
_grid.graphics.lineTo(canvasWidth, equalHeight * i);
}
}
}
/**
* スライダー
*/
class NumSlider extends Sprite
{
private var _label:String;
private var _field:Label;
private var _slider:HSlider;
public function set value(value:int):void
{
_slider.value = value;
updateLabel();
}
public function get value():int
{
return int(_slider.value);
}
public function NumSlider(labeling:String, min:Number, max:Number)
{
_label = labeling;
_field = new Label(this, 0, 0);
_slider = new HSlider(this, 50, 5);
_slider.addEventListener(Event.CHANGE, sliderHandler);
_slider.setSize(60, 10);
_slider.setSliderParams(min, max, 0);
}
private function sliderHandler(event:Event):void
{
updateLabel();
dispatchEvent(new Event(Event.CHANGE));
}
private function updateLabel():void
{
_field.text = _label + String(value);
}
}
/**
* カラーチップ
*/
class ColorChip extends Sprite
{
private var _fill:uint;
private var _chip:BitmapData;
public function get color():uint
{
return _fill;
}
public function set color(value:uint):void
{
_fill = value;
graphics.clear();
graphics.lineStyle(0, (value === 0xFF999999) ? 0x0 : 0x999999);
graphics.drawRect(0, 0, 15, 15);
_chip.fillRect(_chip.rect, value);
}
public function ColorChip()
{
_chip = new BitmapData(14, 14, true, 0x0);
var colorChip:Bitmap = new Bitmap(_chip);
colorChip.x = colorChip.y = 1;
addChild(colorChip);
}
}
/**
* カラーピッカー
*/
class ColorMonitor extends Sprite
{
private var _color:uint;
private var _tmpValue:String;
private var _chip:ColorChip;
private var _label:InputText;
public function get value():uint
{
return _color;
}
public function set value(value:uint):void
{
_color = value;
_chip.color = _color;
_label.text = value.toString(16).substring(2).toUpperCase() || "------";
}
public function ColorMonitor()
{
graphics.beginFill(0xCCCCCC);
graphics.drawRect(0, 0, 8, 8);
graphics.drawRect(8, 8, 8, 8);
graphics.lineStyle(0, 0x999999);
graphics.drawRect(0, 0, 15, 15);
graphics.endFill();
_chip = addChild(new ColorChip()) as ColorChip;
_label = new InputText(this, 16, 0, "------", changeHandler);
_label.addEventListener(FocusEvent.FOCUS_IN, focusInHandler);
_label.addEventListener(FocusEvent.FOCUS_OUT, focusOutHandler);
_label.setSize(50, 16);
_label.restrict = "0123456789ABCDEF";
_label.maxChars = 6;
addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
}
private function changeHandler(event:Event):void
{
event.stopImmediatePropagation();
}
private function focusInHandler(event:Event):void
{
_tmpValue = _label.text;
}
private function focusOutHandler(event:Event):void
{
if (_label.text.length !== 6)
{
_label.text = _tmpValue;
}
else if (_label.text !== _tmpValue)
{
value = uint("0xFF" + _label.text);
dispatchEvent(new Event(Event.CHANGE));
}
}
private function keyDownHandler(event:KeyboardEvent):void
{
if (event.keyCode === Keyboard.ENTER)
{
stage.focus = stage;
}
}
}
/**
* 行編集ボタン
*/
class RowSelectButton extends Sprite
{
private var _selectedIndex:int;
private var _beforeIndex:int;
private var _callbackHandler:Function;
public function get selectIndex():int
{
return _selectedIndex;
}
public function set selectIndex(value:int):void
{
_setIndex(value);
}
public function get selectLabel():String
{
return (getChildAt(_selectedIndex) as PushButton).label.toLowerCase();
}
public function get changeBeforeIndex():int
{
return _beforeIndex;
}
public function RowSelectButton(parent:DisplayObjectContainer, x:Number, y:Number, callbackHandler:Function)
{
parent.addChild(this);
this.x = x;
this.y = y;
_callbackHandler = callbackHandler;
var front:PushButton = new PushButton(this, 0, 0, "Front", _onClickHandler);
front.setSize(35, 16);
front.toggle = true;
front.selected = true;
var left:PushButton = new PushButton(this, 34, 0,"Left", _onClickHandler);
left.setSize(35, 16);
left.toggle = true;
var right:PushButton = new PushButton(this, 68, 0, "Right", _onClickHandler);
right.setSize(34, 16);
right.toggle = true;
var back:PushButton = new PushButton(this, 101, 0, "Back", _onClickHandler);
back.setSize(34, 16);
back.toggle = true;
graphics.beginFill(0xBCBCBC);
graphics.drawRect(0, 0, 135, 16);
graphics.endFill();
}
private function _onClickHandler(event:MouseEvent):void
{
var index:int = getChildIndex(event.target as PushButton);
if (_selectedIndex === index)
{
(getChildAt(index) as PushButton).selected = true;
}
else
{
_setIndex(index);
_callbackHandler(this);
}
}
private function _setIndex(index:int):void
{
_beforeIndex = _selectedIndex;
_selectedIndex = index;
(getChildAt(_beforeIndex) as PushButton).selected = false;
(getChildAt(_beforeIndex) as PushButton).getChildAt(1).alpha = 1;
(getChildAt(_selectedIndex) as PushButton).selected = true;
(getChildAt(_selectedIndex) as PushButton).getChildAt(1).alpha = 0;
}
}
/**
* キャラクター表示
*/
class CharacterBitmap extends Bitmap
{
private var _row:int;
private var _pattern:int;
private var _col:int;
private var _frame:int;
private var _width:int;
private var _height:int;
private var _point:Point;
private var _crop:Rectangle;
private var _source:BitmapData;
public function get frame():int
{
return _frame;
}
public function set frame(value:int):void
{
if (0 <= value)
{
_frame = value;
}
}
public function get pattern():int
{
return _pattern;
}
public function set pattern(value:int):void
{
if (0 <= value && _row > value)
{
_pattern = value;
}
}
public function CharacterBitmap(source:BitmapData, row:int, col:int, maskColor:uint = 0)
{
_row = row;
_col = col;
_width = source.width / col >> 0;
_height = source.height / row >> 0;
_point = new Point();
_crop = new Rectangle(0, 0, _width, _height);
_source = new BitmapData(source.width, source.height, true, 0);
_source.draw(source);
_source.threshold(_source, _source.rect, _point, "==", maskColor, 0, 0xFFFFFF);
bitmapData = new BitmapData(_width, _height);
bitmapData.copyPixels(_source, _crop, _point);
}
public function update():void
{
_crop.x = (_frame++ % _col) * _width;
_crop.y = _pattern * _height;
bitmapData.copyPixels(_source, _crop, _point);
}
}
/**
* キャラクタースプライト
*/
class CharacterSprite extends Sprite
{
protected var _frameRate:Number;
protected var _frameSpan:Number;
protected var _updateTarget:Number;
protected var _front:int;
protected var _left:int;
protected var _right:int;
protected var _back:int;
protected var _source:CharacterBitmap;
public function get frameRate():Number
{
return _frameRate;
}
public function set frameRate(value:Number):void
{
_frameRate = value;
_frameSpan = 1000 / _frameRate;
_updateTarget = 0;
_source.frame = 0;
}
public function CharacterSprite(source:CharacterBitmap, frameRate:Number, direction:Vector.<String>)
{
_source = addChild(source) as CharacterBitmap;
_front = direction.indexOf("front");
_left = direction.indexOf("left");
_right = direction.indexOf("right");
_back = direction.indexOf("back");
this.frameRate = frameRate;
}
public function start():void
{
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
public function stop():void
{
removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
protected function enterFrameHandler(event:Event):void
{
var now:Number = new Date().getTime();
if (now > _updateTarget)
{
_updateTarget = now + _frameSpan;
_source.update();
}
}
}
/**
* キー操作できるキャラクター
*/
class Player extends CharacterSprite
{
public var speed:int;
private var _right_key:Boolean;
private var _left_key:Boolean;
private var _up_key:Boolean;
private var _down_key:Boolean;
public function Player(source:CharacterBitmap, frameRate:Number, direction:Vector.<String>, speed:int)
{
this.speed = speed;
super(source, frameRate, direction);
}
public function keyDownHandler(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case Keyboard.RIGHT:
_right_key = true;
_source.pattern = _right;
break;
case Keyboard.LEFT:
_left_key = true;
_source.pattern = _left;
break;
case Keyboard.UP:
_up_key = true;
_source.pattern = _back;
break;
case Keyboard.DOWN:
_down_key = true;
_source.pattern = _front;
break;
}
}
public function keyUpHandler(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case Keyboard.RIGHT:
_right_key = false;
break;
case Keyboard.LEFT:
_left_key = false;
break;
case Keyboard.UP:
_up_key = false;
break;
case Keyboard.DOWN:
_down_key = false;
break;
}
if (_up_key) _source.pattern = _back;
if (_right_key) _source.pattern = _right;
if (_down_key) _source.pattern = _front;
if (_left_key) _source.pattern = _left;
}
override protected function enterFrameHandler(event:Event):void
{
if (_left_key) x -= speed;
if (_right_key) x += speed;
if (_up_key) y -= speed;
if (_down_key) y += speed;
super.enterFrameHandler(event);
}
}