背景
AndroidとiOS向けに「NAMAKO02F」という棒人間だけの格闘ゲームを配布しています。
棒人間だけ〜といっても格闘技の名前を冠したそれぞれのキャラクター達は、その名の通りのアクションをするので十分個性的なのではないかなと思ってます。
今、次回アップデート時に4キャラほど増やしたいと思っているのですが、ちょっとこれが大変。
現バーションは以前から書き溜めてあったものを使ったのですが、これから絵を新しく描くとなると時間がかかるし、今は忙しくてそんな暇がない、リリースがいつになるやらと。
今まではたとえばハイキック1つとってもキャラごとに魂込めて別々に描いてきました。
そこに「たとえ棒人間でも」と個性を持たせようとしていたのですが、作りたいものをいつまで経っても作れないことにバカバカしさを感じ始めていて・・・
「もう棒人間だし誰も気にしないだろうしいいんじゃねえかな」と考え直し(笑)、元からある絵をつなぎ合わせてゲームで使いやすいように加工することにしました。
やるべきこと
- 1個が256x256の絵を、横縦4x3で敷き詰めた1024x768の画像を12枚に切り分ける。
- 切り分けた256x256の絵を、再び横縦4x3で自由に別の並びで繋ぎ直す。
- 上記条件以外の絵のサイズや枚数や配置でプログラムが動くようにする。
条件
上記のような、ゲームのキャラクターモーションを1枚の画像内に等間隔に並べて使う場合に限定されます。
使用言語
Python、なんとなく使ってみたいだけ。
画像処理は便利なのでPillow(PIL)を使います。
使い方
GUI部分を作るのがかったるいのでコンソールからコマンド叩けばOK。
ディレクトリ構成
- src(画像切り出しの元画像ディレクトリ)
- dst(画像切り出しの出力先ディレクトリ=画像繋ぎ直しの元画像ディレクトリ)
- recreate(画像繋ぎ直しの出力先ディレクトリ)
- cutout.py(画像切り出しプログラム)
- recreate.py(画像繋ぎ直しプログラム)
インストール
Pythonについてはググってください。
画像処理ライブラリのPillowは
pip install pillow
でOK。
プログラムの機能なんてのはね、とりあえず使ってみるってくらいならば、なんとなく使えていればそれでいいのです(真顔)
切り出しプログラム
import sys
from PIL import Image
# 指定した画像を切り分けるプログラム
args = sys.argv
filename = args[1]
src_width = int(args[2]) #切り取り元画像の横サイズ
src_height = int(args[3]) #切り取り元画像の縦サイズ
dst_width = int(args[4]) #切り出しの横サイズ
dst_height = int(args[5]) #切り出しの縦サイズ
# 元画像読み込み
im = Image.open("src/"+filename)
# カット
count = 0 #切り取った数
num_x = src_width//dst_width #横方向のサイズ
num_y = src_height//dst_height #縦方向のサイズ
# 1個ずつ切り出して保存
for y in range(num_y):
for x in range(num_x):
im_crop = im.crop((x*dst_width,y*dst_height,(x+1)*dst_width,(y+1)*dst_height))
im_crop.save("dst/"+filename.replace(".", "_"+str(count)+"."),quality=95)
count +=1
上記の12枚のモーションを一つにまとめた画像ファイルを対象に、
python cutout.py karate01_01.png 1024 768 256 256
第一パラメータが元画像ファイル名、第二,三パラメータが元画像の縦横サイズ、第四,五パラメータが切り出す各々の画像の縦横サイズとなります。
コマンドを叩きますと、
このようにdstディレクトリ以下に12枚のモーションが個別に切り出されました。
ね、簡単でしょ。
繋ぎ直しプログラム
import sys
from PIL import Image
# 指定した複数の画像をつなぎ直すプログラム
args = sys.argv
filename = args[1] #出力先ファイル名
num_horizontal = int(args[2]) #繋ぎ合わせる際、横にいくつ並べるか
num_vertical = int(args[3]) #繋ぎ合わせる際、縦にいくつ並べるか
# 素材画像をパラメータから取得(全て同じ縦横サイズであることが前提)
source = []
for count in range(4,len(args)):
source.append(Image.open("dst/"+args[count]))
# 繋ぎ合わせる画像のサイズを取得しておく
w = source[0].width
h = source[0].height
# 同じサイズの画像を作成
canvas = Image.new('RGBA', (w * num_horizontal, h * num_vertical), (0, 0, 0, 0))
# 第4パラメータからセットした画像を繋いでいく
for y in range(0,num_vertical):
for x in range(0,num_horizontal):
canvas.paste(source[y*num_horizontal+x], (w * x, h * y))
canvas.save("recreate/"+filename,'PNG')
では、dstにある切り出された画像を逆順で繋ぎ合わせてみましょう。
コマンドは以下の通り。
python recreate.py karate_reareate.png 4 3 karate01_01_11.png karate01_01_10.png karate01_01_9.png karate01_01_8.png karate01_01_7.png karate01_01_6.png karate01_01_5.png karate01_01_4.png karate01_01_3.png karate01_01_2.png karate01_01_1.png karate01_01_0.png
工夫もクソもなく、クソ長いですね(笑)
第一パラメータは出力するファイル名、第二,三パラメータが縦横にそれぞれ連結したい画像の個数(エクセルシートを想像してください)、あとのパラメータは連結させたい画像ファイル名です。
このコマンドの場合、1段目から横4つに並べて、次の段へいってまた横4つに並べて……という繰り返しで画像を連結して、256×256ピクセルの画像が横4列・縦3行で並んでいる画像を出力しています。
ちゃんと逆順になっていますね。
Finderじゃわかりにくいので、ペイントソフトでも確認します。
PNGの透過もちゃんとできているようです。
応用
例えば、パラメータを変えることで、
-1個が100x100の絵を横縦8x8で敷き詰めた800x800のゲーム用の画像を、64枚に切り分ける。
-切り分けた100x100の絵を、再び横縦8x8で自由に並べ替えて繋ぎ直す。
という使い方もできます。
3Dが簡単に使える昨今、こういう画像の使い方をする人が今時、どれだけいるのか謎ではありますけれど(^^;
終わりに、というか昔話
昔はPhotoshop Elements(若い人は知らないだろうな…)とかで1個1個手作業で格闘ゲームのキャラモーションをくっつけていたのですが、プログラム使った方が正確で早く作れたでしょう。
あの苦労はなんだったのだろうか(笑)(→でも楽しくはあった)
当時であればLL言語というとPerlがあって、画像編集ができるライブラリは……何があっただろうなー?
色々できることがあって、その情報がキャッチしやすい昨今は素晴らしいなとアラフォーのおじさんは思いました。