ドット絵エディタ(マップエディタメーカー)
---------------------------------------------------------------------------------------
* マップエディタを作成できます。
* ---------------------------------------------------------------------------------------
* [操作方法]
* 操作はマウスのみです。
* ---------------------------------------------------------------------------------------
* [マニュアル]
* ・右下のマップチップのリストから、クリックでマップチップを選択できます。
* ・選択中のマップチップは右上の枠内に表示されます。
* ・左上のマップをクリックすると、選択中のマップチップを配置できます。
* (ドラッグ操作で、連続で配置することもできます)
* ・マップが画面内に収まらない大きさなら上下左右のスライダーでスライドできます。
*
* ・exportボタンで現在のマップをテキストフィールドに出力することができます。
* ・importボタンは逆にテキストフィールドのテキストを読み込んでマップに反映させます。
*
* (テキストフィールドがかなり小さいので、コピペする場合は
* windowsなら、テキストフィールドを右クリック[すべて選択]、[コピー]が楽です。)
* ---------------------------------------------------------------------------------------
* [いじりどころ]
* MapContextクラス(もっと適切なクラス名募集)をいじると、
* マップのサイズを変更したり、他のマップチップ画像を読み込んだり、
* 他のテキスト形式での入出力が可能になります。
*
* [例]
* ワンダフルワールド用マップエディタ
* http://wonderfl.net/code/f64230007f5ccfb1709e1327287d6da3e5840e5f
* ワンダフルクエスト用マップエディタ
* http://wonderfl.ne
/**
* Copyright o8que ( http://wonderfl.net/user/o8que )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/61OW
*/
// forked from nengafl's nengafl
/* ---------------------------------------------------------------------------------------
* マップエディタを作成できます。
* ---------------------------------------------------------------------------------------
* [操作方法]
* 操作はマウスのみです。
* ---------------------------------------------------------------------------------------
* [マニュアル]
* ・右下のマップチップのリストから、クリックでマップチップを選択できます。
* ・選択中のマップチップは右上の枠内に表示されます。
* ・左上のマップをクリックすると、選択中のマップチップを配置できます。
* (ドラッグ操作で、連続で配置することもできます)
* ・マップが画面内に収まらない大きさなら上下左右のスライダーでスライドできます。
*
* ・exportボタンで現在のマップをテキストフィールドに出力することができます。
* ・importボタンは逆にテキストフィールドのテキストを読み込んでマップに反映させます。
*
* (テキストフィールドがかなり小さいので、コピペする場合は
* windowsなら、テキストフィールドを右クリック[すべて選択]、[コピー]が楽です。)
* ---------------------------------------------------------------------------------------
* [いじりどころ]
* MapContextクラス(もっと適切なクラス名募集)をいじると、
* マップのサイズを変更したり、他のマップチップ画像を読み込んだり、
* 他のテキスト形式での入出力が可能になります。
*
* [例]
* ワンダフルワールド用マップエディタ
* http://wonderfl.net/code/f64230007f5ccfb1709e1327287d6da3e5840e5f
* ワンダフルクエスト用マップエディタ
* http://wonderfl.net/code/17c6b454fff55993f110f45b897cae6b83d82780
* ---------------------------------------------------------------------------------------
*
* サンプルとして、シンプルなドット絵エディタっぽい感じにしてます。
*
* [ビギナー向け(?)いじりどころ]
* ・MapContextのGRID_SIZE, GRID_COLS, GRID_ROWS(293~295行目)の値をいじると、
* キャンバスのサイズを変更できます。
* ・MapContext.load()内の変数sample(310行目)をいじると、パレットの色を追加・変更できます。
* ・MapContext.DEFAULT_MAPDATA(296行目)の値を、exportで出力したテキストで置き換えると、
* 自分が作ったドット絵を初期の配置にすることができます。
*
* ---------------------------------------------------------------------------------------
* [修正]
* 1/26 : MapContextのGRID_COLS, GRID_ROWSの値だけを変えると、コンパイルエラーになっていた問題を修正しました。
*/
package {
import com.bit101.components.HSlider;
import com.bit101.components.PushButton;
import com.bit101.components.Text;
import com.bit101.components.VSlider;
import flash.display.DisplayObject;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
[SWF(frameRate=10)]
public class LevelEditor extends Sprite {
private var _selectedChipType:int; // 選択中のマップチップの種類を保持する
private var _isMouseDownOnMap:Boolean; // (マップ上で)マウス左ボタンが押されているか
private var _mapModel:Array; // マップモデル
// 各コンポーネントの参照
private var _map:Sprite;
private var _mapScrollTop:HSlider;
private var _mapScrollBottom:HSlider;
private var _mapScrollLeft:VSlider;
private var _mapScrollRight:VSlider;
private var _IOTextField:Text;
private var _importButton:PushButton;
private var _exportButton:PushButton;
private var _selectedChip:MapChip;
private var _chipList:Sprite;
private var _chipListSlider:VSlider;
public function LevelEditor() {
graphics.beginFill(0x000000);
graphics.drawRect(0, 0, 465, 465);
graphics.endFill();
MapContext.instance.addEventListener(Event.COMPLETE, initialize);
MapContext.instance.load();
}
private function initialize(e:Event):void {
MapContext.instance.removeEventListener(Event.COMPLETE, initialize);
initializeData();
initializeMap();
initializeSelectedChip();
initializeChipList();
initializeComponents();
MapContext.instance.setReference(_mapModel, _IOTextField);
}
private function initializeData():void {
_selectedChipType = 0;
_isMouseDownOnMap = false;
}
// マップを作成する
private function initializeMap():void {
_map = new Sprite();
_mapModel = [];
for (var row:int = 0; row < MapContext.GRID_ROWS; row++) {
_mapModel[row] = [];
for (var col:int = 0; col < MapContext.GRID_COLS; col++) {
var mapChip:MapChip;
if (MapContext.DEFAULT_MAPDATA[row] == undefined || MapContext.DEFAULT_MAPDATA[row][col] == undefined) {
mapChip = new MapChip(0);
}else {
mapChip = new MapChip(MapContext.DEFAULT_MAPDATA[row][col]);
}
mapChip.x = MapContext.GRID_SIZE * col;
mapChip.y = MapContext.GRID_SIZE * row;
_map.addChild(mapChip);
_mapModel[row][col] = mapChip;
}
}
addDisplayWindow(_map, 20, 20, 350, 350);
// マップ上でのマウスイベントリスナの登録
_map.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownMap);
_map.addEventListener(MouseEvent.MOUSE_UP, mouseUpMap);
_map.addEventListener(MouseEvent.ROLL_OUT, mouseUpMap);
_map.addEventListener(MouseEvent.MOUSE_OVER, mouseOverMap);
_map.addEventListener(MouseEvent.MOUSE_OUT, mouseOutMap);
}
// 選択中のマップチップの画像を表示する枠を作成する
private function initializeSelectedChip():void {
_selectedChip = new MapChip(_selectedChipType);
_selectedChip.x = _selectedChip.y = int((50 - MapContext.GRID_SIZE) / 2);
addDisplayWindow(_selectedChip, 395, 5, 50, 50);
}
// マップチップのリストを作成する
private function initializeChipList():void {
_chipList = new Sprite();
var chipNum:int = MapChip.images.length;
var chipPosX:int = int((50 - MapContext.GRID_SIZE) / 2);
for (var num:int = 0; num < chipNum; num++) {
var mapChip:MapChip = new MapChip(num);
mapChip.x = chipPosX;
mapChip.y = MapContext.GRID_SIZE * num;
_chipList.addChild(mapChip);
}
addDisplayWindow(_chipList, 395, 60, 50, 400);
// マップチップのリスト上でのマウスイベントリスナの登録
_chipList.addEventListener(MouseEvent.CLICK, mouseClickChipList);
_chipList.addEventListener(MouseEvent.MOUSE_OVER, mouseOverChipList);
_chipList.addEventListener(MouseEvent.MOUSE_OUT, mouseOutChipList);
}
// 引数で指定したDisplayObject用の窓を作成して、表示リストに追加する
private function addDisplayWindow(displayObject:DisplayObject, posx:int, posy:int, width:int, height:int):void {
// マスクで表示範囲を制限する
var maskShape:Shape = new Shape();
maskShape.graphics.beginFill(0xffffff);
maskShape.graphics.drawRect(0, 0, width, height);
maskShape.graphics.endFill();
displayObject.mask = maskShape;
// 位置を調整するコンテナを作成し表示させる
var container:Sprite = new Sprite();
container.x = posx;
container.y = posy;
container.addChild(displayObject);
container.addChild(maskShape);
addChild(container);
}
// 画面に配置するコンポーネントを作成する
private function initializeComponents():void {
// マップのスクロール用スライダー作成
_mapScrollTop = new HSlider(this, 20, 5, scrollMapHorizontal);
_mapScrollBottom = new HSlider(this, 20, 375, scrollMapHorizontal);
_mapScrollLeft = new VSlider(this, 5, 20, scrollMapVertical);
_mapScrollRight = new VSlider(this, 375, 20, scrollMapVertical);
_mapScrollTop.width = _mapScrollBottom.width =
_mapScrollLeft.height = _mapScrollRight.height = 350;
_mapScrollTop.maximum = _mapScrollBottom.maximum = Math.max(MapContext.MAP_WIDTH - 350, 0);
_mapScrollLeft.value = _mapScrollRight.value =
_mapScrollLeft.maximum = _mapScrollRight.maximum = Math.max(MapContext.MAP_HEIGHT - 350, 0);
// 入出力用テキストフィールド・インポートボタン・エクスポートボタン作成
_IOTextField = new Text(this, 10, 395, "");
_IOTextField.width = 370;
_IOTextField.height = 35;
_importButton = new PushButton(this, 10, 435, "import", MapContext.instance.importMapData);
_exportButton = new PushButton(this, 280, 435, "export", MapContext.instance.exportMapData);
// 選択中のマップチップの表示用の枠作成
graphics.beginFill(0x999999);
graphics.drawRect(394, 4, 52, 52);
graphics.endFill();
graphics.beginFill(0x000000);
graphics.drawRect(395, 5, 50, 50);
graphics.endFill();
// マップチップのリスト用スライダー作成
_chipListSlider = new VSlider(this, 450, 60, slideChipList);
_chipListSlider.height = 400;
_chipListSlider.maximum = Math.max((MapContext.GRID_SIZE * MapChip.images.length) - 400, 0);
_chipListSlider.value = _chipListSlider.maximum;
}
private function mouseDownMap(e:MouseEvent):void {
_isMouseDownOnMap = true;
MapChip(e.target).type = _selectedChipType;
}
private function mouseUpMap(e:MouseEvent):void {
_isMouseDownOnMap = false;
}
private function mouseOverMap(e:MouseEvent):void {
MapChip(e.target).showFrame();
if (_isMouseDownOnMap) {
MapChip(e.target).type = _selectedChipType;
}
}
private function mouseOutMap(e:MouseEvent):void {
MapChip(e.target).hideFrame();
}
private function mouseClickChipList(e:MouseEvent):void {
_selectedChipType = MapChip(e.target).type;
_selectedChip.type = _selectedChipType;
}
private function mouseOverChipList(e:MouseEvent):void {
MapChip(e.target).showFrame();
}
private function mouseOutChipList(e:MouseEvent):void {
MapChip(e.target).hideFrame();
}
private function scrollMapHorizontal(e:Event):void {
_mapScrollTop.value = _mapScrollBottom.value = HSlider(e.target).value;
_map.x = -(int(_mapScrollTop.value));
}
private function scrollMapVertical(e:Event):void {
_mapScrollLeft.value = _mapScrollRight.value = VSlider(e.target).value;
_map.y = -(_mapScrollLeft.maximum - int(_mapScrollLeft.value));
}
private function slideChipList(e:Event):void {
_chipList.y = -(_chipListSlider.maximum - int(_chipListSlider.value));
}
}
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Shape;
import flash.display.Sprite;
class MapChip extends Sprite {
public static var images:Array = []; // BitmapDataの配列
private var _type:int;
private var _image:Bitmap;
private var _frame:Shape;
public function get type():int { return _type; }
public function set type(t:int):void {
if (t != _type) {
_type = t;
_image.bitmapData = images[_type];
}
}
public function MapChip(type:int) {
_type = type;
_image = new Bitmap(images[_type]);
_frame = new Shape();
addChild(_image);
addChild(_frame);
hideFrame();
}
// 枠をハイライト表示させる
public function showFrame():void {
_frame.graphics.clear();
_frame.graphics.lineStyle(1, 0xffff00);
_frame.graphics.drawRect(0, 0, MapContext.GRID_SIZE - 0.5, MapContext.GRID_SIZE - 0.5);
}
// 枠をぼんやり見える程度にする
public function hideFrame():void {
_frame.graphics.clear();
_frame.graphics.lineStyle(1, 0x000000, 0.5);
_frame.graphics.drawRect(0, 0, MapContext.GRID_SIZE - 0.5, MapContext.GRID_SIZE - 0.5);
}
}
import com.bit101.components.Text;
import flash.display.BitmapData;
import flash.events.Event;
import flash.events.EventDispatcher;
class MapContext extends EventDispatcher {
public static const GRID_SIZE:int = 35; // グリッドの大きさ
public static const GRID_COLS:int = 10; // グリッドの横の数
public static const GRID_ROWS:int = 10; // グリッドの縦の数
// 初期のマップ配置
public static const DEFAULT_MAPDATA:Array =
[[1,1,1,8,8,8,8,1,1,1],
[1,1,8,8,8,8,8,8,1,1],
[1,8,8,0,8,8,0,8,8,1],
[8,8,8,0,8,8,0,8,8,8],
[8,8,8,8,8,8,8,8,8,8],
[8,8,8,8,8,8,8,8,8,8],
[8,8,5,5,5,5,5,5,8,8],
[1,8,8,5,5,5,5,8,8,1],
[1,1,8,8,8,8,8,8,1,1],
[1,1,1,8,8,8,8,1,1,1]];
// マップチップ画像(BitmapDataオブジェクト)の読み込み
public function load():void {
var sample:Array = [
0x333333, 0x666666, 0x999999, 0xcccccc, 0xffffff, 0xff0000,
0x00ff00, 0x0000ff, 0xffff00, 0xff00ff, 0x00ffff
];
var sampleNum:int = int(sample.length);
for (var i:int = 0; i < sampleNum; i++) {
MapChip.images.push(new BitmapData(MapContext.GRID_SIZE, MapContext.GRID_SIZE, false, sample[i]));
}
// 読み込み完了イベント送出
dispatchEvent(new Event(Event.COMPLETE));
}
// インポート(読み込み)ボタンの処理
public function importMapData(e:Event):void {
var mapData:Array = _IOTextFieldReference.text.match(/\d+/g);
for (var row:int = 0; row < MapContext.GRID_ROWS; row++) {
for (var col:int = 0; col < MapContext.GRID_COLS; col++) {
// マップ上の各マップチップの種類を変更する
MapChip(_mapModelReference[row][col]).type = mapData[(row * MapContext.GRID_COLS) + col];
}
}
}
// エクスポート(書き出し)ボタンの処理
public function exportMapData(e:Event):void {
var mapDataText:String = "[";
for (var row:int = 0; row < MapContext.GRID_ROWS; row++) {
mapDataText += "[";
for (var col:int = 0; col < MapContext.GRID_COLS; col++) {
mapDataText += MapChip(_mapModelReference[row][col]).type.toString();
if (col < MapContext.GRID_COLS - 1) { mapDataText += ","; }
}
mapDataText += "]";
if (row < MapContext.GRID_ROWS - 1) { mapDataText += ",\n"; }
}
mapDataText += "];";
// テキストフィールドに出力する
_IOTextFieldReference.text = mapDataText;
}
/* ここから上をいじる */
/********************************************************************************/
public static const MAP_WIDTH:int = MapContext.GRID_SIZE * MapContext.GRID_COLS;
public static const MAP_HEIGHT:int = MapContext.GRID_SIZE * MapContext.GRID_ROWS;
private static var _instance:MapContext = null;
private var _mapModelReference:Array; // マップモデルの参照
private var _IOTextFieldReference:Text; // テキスト表示エリアの参照
public static function get instance():MapContext {
if (MapContext._instance == null) {
MapContext._instance = new MapContext(new SingletonEnforcer());
}
return MapContext._instance;
}
public function MapContext(enforcer:SingletonEnforcer) {
}
public function setReference(mapModel:Array, textField:Text):void {
_mapModelReference = mapModel;
_IOTextFieldReference = textField;
}
}
class SingletonEnforcer {}