PhotoshopをjavaScriptでコントロールしてみた

By | 2017年5月24日

脱出ゲームを作っています

最近はBlenderの学習ついでにスマホアプリで人気カテゴリとなっている「脱出ゲーム」を作っています。勉強をしながらの制作なので時間がかかっていますがプログラムを組む段階にきました。

カテゴリ分析:脱出ゲーム
大きなカテゴリには「ファン」がついています。ここではファンの定義を「能動的に検索してアプリを探す方」とします。

Cocos2d-xは脱出ゲームには不向き?

開発プラットホームはこれまでの弾幕ゲームと同じCocos2d-xを利用する予定なのですが、これはUnityのSceneビューに相当するものが無く直感的にオブジェクトを配置することができません
cocos2d-xの利点は完全なオープンソースで処理のチューニングがしやすいこと(つまり弾幕ゲームに丁度良い)。
参考リンク:Unity初心者が幸せになれるシーンにオブジェクトを配置する時に使える18のTips

とはいえオブジェクトの配置を機械化してしまえば、この短所は消え工数も短縮することができます。ということで今回はPhotoshopで作成したレイアウトからプログラムに必要な座標などを書き出すことに挑戦しました。今回は脱出ゲームなので実際にオブジェクトを配置する必要は無いのでRect情報の読込だけを行っています。

Photoshop側の準備

脱出ゲームではタップされた位置によって処理を振り分けていきます、そのために領域(Rect型)にIDを紐付けたデータが必要になります。ということでPhotoshop側では下図のように反応領域ごとにレイヤー(半透明の赤)を作成しレイヤー名にIDを設定しました。

IDだけだと分かりにくいので以下のようにプログラムで利用しない編集上の名称とIDを「:(コロン)」で区切ったレイヤー名を設定しています。例→lamp:2 lampは混乱しないための名称で2の方がプログラムで利用するIDです。そしてこのレイヤーは1つのレイヤーセットにまとめられています(下図では0_areaとなっています)。

jsx

javaScriptの記述

Adobe公式には日本語でのフォローは無いようですがCS2〜CCまでの情報が公開されています
参考 → Adobe Photoshop Scripting

また以下のサイトが非常に参考になりました。
参考 → PhotoshopのGenerator機能で出力されたレイヤーおよび…

でもって私が書いたスクリプトは以下の通り。


var targetLayerSetName;
var targetLayerSet;

//---------操作するpsdファイルは開いておく必要があります
if(documents.length<=0){
    alert( "スクリプトを実行したいpsdデータを開いておいてください。" );
} else {
    main();
}
 

function main(){
	//---------ダイアログで文字入力も可能です
	targetLayerSetName = prompt("レイヤーセット名を入力してください","0_area");
	if (targetLayerSetName){
		getTargetLayerSet(activeDocument);
		var csvText = makeStrData(targetLayerSet);
		makeSCVfile(csvText);
	}
}
//---------再帰処理なので目的のフォルダが深い階層にあってもOK
function getTargetLayerSet(layerObj){
	var layerSetNum = layerObj.layerSets.length;
	for (var i=0; i<layerSetNum; i++){
		var focusLayerSet = layerObj.layerSets[i];
		if(focusLayerSet.name==targetLayerSetName){
			targetLayerSet = focusLayerSet;
		}else{	
			getTargetLayerSet(focusLayerSet)
		}
	}
}

//---------レイヤーのバウンドボックスをRectに変換します
function makeStrData(targetLayerSet){
	var csvText = "name,id,x,y,w,h";//--------CSVの見出し
	var layerNum = targetLayerSet.artLayers.length;
	
	for (var j=0; j<layerNum; j++){
		var layerObj = targetLayerSet.artLayers[j];
		var layerNameArray = layerObj.name.split(":");
		var layerName =  layerNameArray[0];
		var layerID =  layerNameArray[1];
		var layerBounds =layerObj.bounds;
		var x = parseInt(layerBounds[0]);
		var y = parseInt(layerBounds[1]);
		var w = parseInt(layerBounds[2])-x;
		var h = parseInt(layerBounds[3])-y;
		
		y = 1136 -y-h;//----cocos2dの座標系に合わせる
		var lineStr = layerName+","+layerID+","+x+","+y+","+w+","+h;
		csvText += "\n"+lineStr;
	}
	return csvText;
}

//---------CSVを書き出します
function makeSCVfile(csvText){
	var fileName = activeDocument.path + "/" + targetLayerSetName + ".csv";
	var file = new File(fileName);
	file.saveDlg("保存するファイル名を入れてください");
	
	var openFlg = file.open("w");
	if(openFlg) {
		file.write(csvText);
		file.close();
	} else {
		alert("ファイルが開けませんでした。");
	}
}

注意事項

今回は位置情報を書き出すことしかしていませんが、この仕組みはレイヤー毎に個別にWeb書き出しなども可能で非常に高機能です。というかリファレンスを見るとファイルを確認無しで削除することも可能なことが確認できます。なので不用意に他人の作成したコードを実行するのは危険だな…という印象も受けました。

動画

最後に実際に機能しているところを動画で撮ってみました。最後はデバッグ用に読み込んだ情報を元にスプライトを生成し、位置情報が正しく読み込めているかを確認しています。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

Time limit is exhausted. Please reload the CAPTCHA.