今回は創作活動の道中の様子を少し。
ゲーム作りともなると色々な開発用ツールが生み出されるのですが、
その中の1つを紹介してみたいと思います。
本来はゲーム制作を目的としたpygameというpythonモジュールですが、
これが割と内容のあるものでして、ビットマップのピクセル編集や音声のサンプルデータ編集もいくらか行う事ができます。(音声まわりはまだ触ってません)
単純な画像編集は普段PILを使いますが、編集内容によってはpygameを持ち出す事も多いです。
そこで、ゲーム演出に重要なアニメーションエフェクトについてはpygameで制作環境を作成する事にしました。
今回はその環境を使い、1つのサンプルが出来るまでの手順を紹介したいと思います。
1.GIMPたんで以下のような画像を描く
想定より大きめに描いておきます。
2.pythonで挙動を定義するコードを描きます。(当サンプルはちょうど100行ほどで書ける演出です)
ここでインポートしてるモジュールが主な成果物です。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
#-*- encoding: utf-8 -*- | |
#coding=utf-8 | |
from siraeffanim.EffectAnim_Engine import EffectAnim_Main | |
from siraeffanim.EffectAnim_Base import * | |
from siraeffanim.EffectAnim_Template import * | |
"""============================================================================ | |
依存値の簡易指定~~ | |
""" | |
#全体フレーム数。大きくするとエフェクト時間をゆったり引き延ばす。 | |
TOTALLENGTH = 50 | |
#出現オブジェ数 | |
OBJECTNUM = 32 | |
"""============================================================================ | |
テストエフェクト。 | |
エフェクトの総まとめ。 | |
各エフェクトセルの使用をここで定義する。 | |
""" | |
class EffectFrame_Test(EffectFrame): | |
def __init__(self, **kwargs ): | |
EffectFrame.__init__( self, kwargs , | |
sellSplitSize = (2,3) , #画像ファイルの切り取り数。縦横にそれぞれ何分割するかって値。 | |
CanvasSizeOfByScale = ( 2.5 , 2.5 ) | |
) | |
self.paraminit( TOTALLENGTH ) #エフェクトの長さ。 | |
#以下セルの定義。 | |
#指定順番がそのまま描画順番になるよ。 | |
#▼もやっ | |
self.AddSell( EffectFrameSell_Template_Simple( | |
param_SrcImageSellGridPos = ( 0 , 0 ) , | |
lamb_DrawScale = lambda p,x:( lamb_grad_Sin2Line( p , 1.0 ) * x ) , | |
lamb_DrawAlpha = lambda p,x:( lamb_grad_Sin2Line( p , 0.6 ) * x ) , | |
param_DrawScale = ( 1.6 , 1.6 ) | |
) ) | |
#▼中心ピカー! | |
self.AddSell( EffectFrameSell_Template_Simple( | |
param_SrcImageSellGridPos = ( 0 , 1 ) , | |
lamb_DrawScale = lambda p,x:( lamb_grad_Sin2Line( p , 0.6 ) * x ) , | |
lamb_DrawAlpha = lambda p,x:( lamb_grad_Sin2Line( p , 0.5 ) * x ) , | |
param_DrawScale = ( 1.0 , 1.0 ) | |
) ) | |
#▼衝撃シュパーン | |
self.AddSell( EffectFrameSell_Template_Simple( | |
param_SrcImageSellGridPos = ( 1 , 1 ) , | |
lamb_DrawScale = lambda p,x:( p * x ) , | |
lamb_DrawAlpha = lambda p,x:( lamb_grad_Sin2Line( p , 0.8 ) * x ) , | |
param_DrawScale = ( 6.0 , 2.0 ) , | |
lamb_SurfTransform = lambda surf:( pygame.transform.rotate( surf , 20.0 ) ) | |
) ) | |
#▼ピカピカぱーてぃこ~ | |
#中心ピカーにコレが重なってさらにピカーってなる。その後は小さくなってふわっと消える感じで。 | |
for i in range( OBJECTNUM ) : | |
#lambdaにそのまま書くと遅延評価されちゃうので、乱数含む値は一旦変数に。 | |
alphatime = ( random.randint(35,98)*0.01 ) | |
scale = ( random.randint(75,200)*0.01 ) | |
xpos = ( random.randint(0,180) - 90 )/2 #中心から最終的に行く位置 | |
ypos = ( random.randint(0,180) - 90 )/2 | |
self.AddSell( EffectFrameSell_Template_Simple( | |
param_SrcImageSellGridPos = ( 1 , 0 ) , | |
lamb_DrawPos = ( lambda p,x: p * x + sin( ( p + x*0.37 ) * PI * 2 ) * 5 , lambda p,x: p * x ) , | |
lamb_DrawScale = lambda p,x:( ( 1.0 - p ) * x * ( 0.5 + ( sin( ( p * x )* 5 ) + 1 )/4 ) ) , | |
lamb_DrawAlpha = lambda p,x:( lamb_grad_Sin2Line( p , x ) / 2 ) , | |
param_DrawPos = ( xpos , ypos ) , | |
param_DrawScale = ( scale , scale ) , | |
param_DrawAlpha = alphatime , | |
Blend = BLEND_ADD | |
) ) | |
"""============================================================================ | |
実行コード。 | |
ファイルの指定や描画サイズの決定はここで。 | |
""" | |
if __name__ == '__main__': | |
getImagePathList = [ | |
os.path.abspath("Effanimmap_Fire1.png").decode('shift-jis'), | |
os.path.abspath("Effanimmap_EffHelper.png").decode('shift-jis'), | |
] | |
drawEffectFrames = ( #1度に複数のエフェクトを同時描画も可能 | |
EffectFrame_Test( | |
imagepathlist = getImagePathList , #エフェクトイメージファイルのリストを指定 | |
drawRect = DrawRect( (0,0) , (400,400) ) #描画位置、サイズを指定。 | |
) | |
, ) | |
EffectAnim_Main( drawEffectFrames , CanvasSize = (400,400) ) #実行開始。 |
3.以上のpyを実行するとテスト画面が現れる。
このウィンドウからエクスポートフォームを開き、
フレームスキップやセルサイズの設定をしてフレームアニメとして吐く事ができます。
以下、吐いたもの。(128*128セル設定(全長3200*128)で吐いたものを縮小しました)
非常に小さくなりました。一応ぬるぬる動いていい感じなのです。
一応この工程で"特定色を透明度にする"という操作を行っています。
感想
AviUtlの拡張編集でも同じような事はできる事に気づき、存在意義が疑わしくなってきました。もう黒歴史ですか。
結局今回のプラクティスで実践できたメリットというと・・・
1. ループなどを含めた値変化を利用してアニメーション定義が可能
→ 何千個といったパーティクルを簡単に定義、描画できる
(もっと他の値に依存させれば活用の幅が広がる??)
2. フレームアニメの自動抽出。
くらいのものでしょうか。
スクリプティングについても、パーティクルの拡散を表す式など、
もっと可読性が上がるような構造化、マクロの用意など、課題が残ります。
成果物のモジュールの公開については、
まだ完成度が至ってない事、そして公開時の心得(ライセンスなど)について僕自身知らない事が多すぎる事があり、ひとまず未定とさせて頂きます。