【RPGツクールVX Ace】動くタイトル画面を作ろう!(画像編)【初心者向け】
本記事はVX Ace初心者の方、もしくはスクリプトがよくわからない方を対象に書いていきます。なので、分かりやすいように、だいぶざっくりとした説明をしていきます(悪くいえば大雑把?)。また、スクリプトの大まかな仕組みを理解して頂けるよう、ちょっと踏み込んだ話もしています。「そういうところは読み飛ばしたい!」という方は、青字の部分だけお読みください。
もし至らない点、こうするにはどうすればいいか、などのご質問がありましたらお気軽にコメントしてください。
【目次】
1.画像を動かそう!
2.画像を増やそう!
3.画像を編集しよう!
さて、改めてVX Aceのタイトル画面を見てみましょう。
デフォルトでは「暗転する」「カーソルを動かす」以外の動きがありません。
これはいわば真っ白なキャンバスのようなもので、実はスクリプトで改造しやすくするためにこのようなシンプルな形になっているのです(独自研究含む)。真っ白なまま使うのもいいですが、やはり、動画としてみたとき、それはやや地味に写るでしょう。
ということで早速動きをつけていきましょう!(スクリプトを見ながら読んでいくと分かりやすいと思います)
1.画像を動かそう!
まず初めにタイトル画面で画像を動かしていきましょう。ですがその前に、要となるdef updateというメソッドを見ていきましょう。このメソッド、クラスScene_Title(タイトル画面の画像、音楽などをつかさどるクラス)内にはないのですが、実はクラスScene_TitleのスーパークラスとなるクラスScene_Base内にちゃんと入っています。
「メソッドもクラスもスーパークラスもよく意味が分からない!」という方にざっくり説明すると、クラスの中にいくつかのメソッド(操作。実行するコード)とプロパティ(属性。オブジェクト固有のデータで、オブジェクトの性質や設定に関する情報)が入っていて、スーパークラスというのは、そのクラスのベースとなるクラスのことを指します。
def updateは1フレームごとに実行され、画面や入力情報をリフレッシュするメソッドで、大体の場合これがないとゲームがフリーズしてしまいます。では、なぜdef updateのないScene_Titleがフリーズしないのかといえば、前述したScene_Titleのベースとなるスーパークラスの中にdef updateがあるからです。Scene_Base内のdef updateがScene_Titleの中で使われているのです。
そして、def updateの中で何が行われているか見てみましょう。
def updateの下に「update_basic」という文章がありますが、これはdef update_basicを呼び出しているのです。
メソッド内で他のメソッドを呼び出す際には、defを取って後に続くメソッド名だけを書きます。
def updateは必ず1フレームごとに実行されるので、def update_basicもまた、必ず1フレームごとに実行されています。画像を動かすのに使うメソッドは、別にdef updateでもdef update_basicでもどちらでもよいのですが、今回はわざわざ行数が多いdef update_basicを使わずに、def updateのほうを使いましょう。
また、スーパークラスからメソッドを持ってくるとき、superをつかってメソッドの内容を省略することができます。例えば、
def update_basic
Graphics.update
Input.update
update_all_windows
end
をScene_Titleに持ってくるとき、確かにこれでもいいのですが、
def update_basic
super
end
とすると、この一行だけで上の三行と同じメソッドを実行します。
つまりこの場合、super = Graphics.update Input.update update_all_windowsということになるわけです。
覚えておいて損はないでしょう。
Scene_Titleに、Scene_Baseから持ってきたdef updateを貼り付けます。ただ、どこにでも貼り付けていいというわけではありません。実はメソッドやクラス、条件文を終わらせるときには必ずendをつけなければならないという決まりごとがあって、そのendの数が合わなかったり、変な場所でendが使われたりすると、エラーを吐き出してしまうからです。また、メソッド内でメソッドの定義(define)をすることできません(基本的にね)。
なので、どこがメソッド(クラス)とendとの間かわからない方は、上の画像の位置に挿入することをお勧めします(行数にして8行目)。
また、ifやwhenやtimesなどの条件文や繰り返し文の終わりの際にもendを使うため、単にdefとendの間だからといってやすやすと挿入できないので注意。
さて、やっと画像を動かしていくわけですが、まずは既存の、タイトルの遠景から動かしていきましょう。ここからはスクリプトウィンドウの右下にあるヘルプ(H)を押して、説明書を読みながら進めていくことをお勧めします。
Scene_Title内では、タイトルの遠景はインスタンス変数@sprite1の中にSpriteとして格納されています。説明書の検索(S)から「Sprite」と検索し、Spriteの頁を開いてください。
そこによると、スプライトのX座標はxで管理されているとあります(実はスプライトもクラスの一つで、xやyはそのクラス内のプロパティです)。
では、def updateを利用して、1フレームごとにスプライト@sprite1のxに+1していきましょう。
#(シャープ)は実行しない部分なので写さなくていいです。
それではゲームを起動してみましょう。
タイトル画面が動きました! +で右に、-で左に進み、xではなくyにしたときは、+で下に、-で上に進みます!
ただ、これだと遠景が行ったっきりで帰ってきません。背景が黒くなってしまいます。
「遠景をループさせたい……」という方にはこちら。まず、Scene_Title内にあるdef create_backgroundの、@sprite1 = Sprite.newという箇所を@sprite1 = Plane.newとし、そのすぐ下にあるcenter_sprite(@sprite1)という文章の頭に#(半角シャープ)をつけます。
次に、def updateの中にある、さっき書いた@sprite1.x+=1の.xという部分を、.oxに書き換えます。
プレーン(クラス)とは、ビットマップのパターンを画面全体に並べて表示する特殊なスプライトで、プレーンの中にはxとyというプロパティがなく、その代わりにoxとoyというプロパティ使います。ちなみにスプライトにもoxとoyというプロパティはありますが、そっちは一般的に画像を動かすのではなく、画像の原点をずらすときに使います。
スプライトとプレーンは二つとも同じObjectというスーパークラスを持ちますが、共有しないプロパティが多いで、説明書で確認するなど、注意してください。
そして、今遠景にしたことは近景にも同様に動作します。近景のスプライトを保管しているのはインスタンス変数@sprite2です。上の画像ではこのようにスクリプトを組んで動かしています。
それと、タイトルの文字は@foreground_spriteにスプライトとして保管されており、動かすことも可能です。
2.画像を増やそう!
さて、今まで既存の画像だけを動かしてきましたが、「遠景でも近景でもないもう一つの画像を表示したい!」という方もいると思います(多分)。
例えば上の画像のように。
「そんなの遠景や近景のどちらかに直接画像編集で貼り付ければいいじゃん!」と、お思いになるかも知れませんが、もしかしたら「遠景と近景を両方バラバラに動かして、真ん中に動かない画像を置きたい!」というときが来るかもしれません。そんなときのために、一緒に学びましょう。
実はこれ、簡単なお約束さえ覚えればさして難しい内容ではありません。
1・画像を表示する
2・画像を削除する
たったこれだけです。
では見ていきましょう。
1・画像を表示する
上の図の場合はこうなります。
#--------------------------------------------------------------------------
# ● 背景の作成
#--------------------------------------------------------------------------
def create_background
@sprite1 = Sprite.new
@sprite1.bitmap = Cache.title1($data_system.title1_name)
@sprite2 = Sprite.new
@sprite2.bitmap = Cache.title2($data_system.title2_name)
center_sprite(@sprite1)
center_sprite(@sprite2)
@sprite3 = Sprite.new
@sprite3.bitmap = Cache.battler("Angel",0)
@sprite3.z=@sprite1.z+1
@sprite2.z=@sprite3.z+1
center_sprite(@sprite3)
end
解説していくと、一行目の「@sprite3 = Sprite.new」が、「@sprite3に新しくスプライトのクラスを代入する」という意味です(ちなみに、sprite3の部分の変数名は別になんて名前を付けてもいいです)。
二行目の「@sprite3.bitmap = Cache.battler("Angel",0)」は、「@sprite3のビットマップに、Cacheというモジュールのbattlerというメソッドが返したビットマップを代入する」ということです。
勘のいい方はもう気付かれたと思いますが、これ実は遠景と近景を呼び出した時と全く同じです。
@sprite1 = Sprite.new
@sprite1.bitmap = Cache.title1($data_system.title1_name)
@sprite2 = Sprite.new
@sprite2.bitmap = Cache.title2($data_system.title2_name)←これ
この呼び出し方は全てのスプライトに共通します。ただ、Cacheから呼び出すのではなく、直接Bitmapのクラスで返すこともありますが、今のところこれはどうでもいい話です。
それと、メソッドを呼び出すのに引数(argument)が必要な場合があり、その際に引数を指定していないと「wrong number of arguments(指定した引数の数 for 実際に必要だった引数の数)」というエラーが出てきます。
スクリプトの上のほうにあるCacheを見てみると、● 戦闘グラフィックの取得 の引数はself.battler(filename, hue)とあるので二つであるということが分かります。他のCacheの引数はアニメーションを除いてすべて一つなので、油断していると結構間違えるので注意。
次に、@sprite3.z=@sprite1.z+1ですが、このzというのは画像表示の優先順位のことで、例えば、Aという画像とBというスプライトがあったとき、AもBもz軸の数字は等しく0ですが、後に作成されたスプライトのほうが手前に表示されますが、Aのz軸が1でもBより大きければ、AはBより手前に表示され、その逆もしかりです。
今回は、天使のキャラ(@sprite3)を近景(@sprite2)の後ろに表示するために、
@sprite3.z=@sprite1.z+1;@sprite2.z=@sprite3.z+1と書きました。
center_sprite(@sprite3)
これはScene_Titleの中だけのメソッドです。このメソッドの中では、かっこで指定された変数の中に入っているクラス:スプライトの、プロパティx(もしくはy)を参照する箇所があるので、プロパティにxとyがないクラス:プレーンにこれを使うとエラーが出ます。さっき、SpriteをPlaneに変える際に、center_spriteの先頭に#をつけるようにしたのはそのためです。
ちなみに、スプライトのクラスを代入する変数は、今回はインスタンス変数を使いましたが、別にローカル変数でもグローバル変数でもクラス変数でも構いません。変数の特性に関しては、説明書の「変数と定数」を参照してください。ちなみに、Scene系でスプライトやプレーンを表示するときは、もっぱらインスタンス変数が使われています。というか、特に理由のないとき以外はわざわざインスタンス変数以外の変数を使う必要はありません。
2・画像を削除する
スプライトやプレーン、ビットマップなどの画像類は、バグを防ぐために一度生成したら消さなければなりません。
では試しに、画像を消さないとどういうことになるのか見てみましょう。
こうなります。デン
「まあデザイン的にはこれでもアリかな……」って気もしますが、ダメなものはダメです。
こうならないためにも必ず画像を削除しましょう。
これもあまり難しい話ではないのでご安心を。
Scene_Title内にあるdef dispose_backgroundに、「
@sprite3.bitmap.dispose
@sprite3.dispose
」と付け加えるだけです。
これも、上にある
@sprite1.bitmap.dispose
@sprite1.dispose
@sprite2.bitmap.dispose
@sprite2.dispose
と同じです。
disposeとは英語で「削除する」を意味し、@sprite3.bitmap.disposeは、@sprite3.bitmap = Cache.battler("Angel",0)としたときに代入した「ビットマップ(Cache.battler("Angel",0))を削除する」という意味で、@sprite3.disposeは@sprite3 = Sprite.newのときに代入した「Spriteのクラスを削除する」という意味です。なお、この二行を逆にしてはいけません。
【悪い例】
@sprite3.dispose
@sprite3.bitmap.dispose
こうすると、@sprite3の中にあるスプライトのクラスが削除され、@sprite3の変数の中には何もないのに、bitmapというメソッドを呼び出し、削除しようとしていることになります。
とりあえず、今のうちは@sprite1と@sprite2の動きをならっているだけでいいでしょう。
削除すれば、ロード画面に天使が表示されることはなくなります。
3.画像を編集しよう!
さて、今のところスプライトに使ったメソッドはx、y、z、bitmap、disposeの5つだけですが、説明書のスプライトのページを見れば、まだまだたくさんメソッドがあることがわかります。簡単なものから見ていきましょう。
・disposed?
スプライトがすでに解放されている場合には真(true)を返します。主にif,unlessなどの条件文や、p などとともに使います。
例:
p "deleted" if @sprite3.disposed? => "deleted"
p @sprite3.disposed? => true
・flash(color, duration)
スプライトのフラッシュを開始します。duration はフラッシュにかけるフレーム数です。
color に nil を指定した場合は、フラッシュの時間分スプライト自体を消去します。
例:
def update
@sprite3.flash(Color.new(255,255,255),15)
update_basic
end
・width
スプライトの幅を取得します。src_rect.width と等価です。
例:
p @sprite3.width => 384
・height
スプライトの高さを取得します。src_rect.height と等価です。
例:
p @sprite3.height => 288
・x
画像x軸の座標です。
・y
画像y軸の座標です。
・z
画像z軸の座標です。数値が大きいほど手前に表示され、値が等しい場合は後に生成されたものが手前に表示されます。
・ox
画像x軸の原点。
・oy
画像y軸の原点。
・opacity
スプライトの不透明度です。0 ~ 255 の範囲で指定します。範囲外の値は自動で修正されます。
例:
@sprite3.opacity=0
・src_rect
ビットマップから転送される矩形 (Rect) です。Rectとは画像の大切な四要素(x,y,width,height)を含む四角形のクラス。
例:
p @sprite3.src_rect => (0, 0, 384, 288)
・viewport
スプライトが関連付けられているビューポート (Viewport) への参照です。 画面の一部にスプライトを表示し、他の部分にはみ出さないようにしたい場合に使用します(トリミング)。
また、SpriteやWindowのx、y、z軸、もしくは表示状態などを一括で管理したいときに使えます。アニメのセル板みたいに、複数あるSpriteを一枚に焼くものと考えてもらうとわかりやすいです。
例:
@viewport=Viewport.new(0,0,300,280)
@viewport.z=150
@sprite3.viewport=@viewport
個人的にあんまり好きじゃないです。
・visible
スプライトの可視状態です。trueのとき可視になります。
また、falseにすると、opacityに関係なく画像を透明にできます。
例:@sprite3.visible=false
・zoom_x
スプライトの X 方向拡大率です。1.0 で等倍になります。
・zoom_y
スプライトの Y 方向拡大率です。1.0 で等倍になります。
例:
@sprite3.zoom_x=4
@sprite3.zoom_y=2.5
・angle
スプライトの回転角度です。反時計回りを正とする 360 度系で指定します。回転描画には時間がかかりますので、多用は避けてください。
例:
def update
update_basic
@sprite3.angle+=1
end
・mirror
スプライトの左右反転フラグです。真のとき反転して描画されます。初期値は false です。
例:
@sprite3.mirror=true
・bush_opacity
・bush_depth
下の一部だけ半透明にします。透明度をbush_opacityで決められ、0で透明になる。bush_depthで、どれだけ下まで半透明にするか決められる。
例:
@sprite3.bush_depth =150
@sprite3.bush_opacity =120
・blend_type
スプライトの合成方法 (0:通常、1:加算、2:減算) です。
例:
@sprite3.blend_type=2#減算
・color
スプライトを特定の色に染めます。アルファで濃さを調整できます。
例:
@sprite3.color =Color.new(255,0,0,255)
・tone
スプライトの色調を変更します。
例:
@sprite3.tone=Tone.new(255,0,0)
・wave_amp
・wave_length
・wave_speed
・wace_phase
波形描画のための振幅、周期、速度、位相です。波形描画とは、スプライトを正弦波関数によりラインごとに横にずらして描画するもので、いわゆるラスタスクロールのような表現を行います。
wave_amp には波形の振幅を、wave_length には波形の周期を、それぞれピクセル数で指定します。
wave_speed は波形がアニメーションする速度を指定します。規定値は 360 で、値が大きいほど速くなります。
wave_phase はスプライトの一番上のラインでの位相を 360 度系の角度で指定します。これは update メソッドが呼ばれるごとに更新されます。波形描画を行うスプライト同士で同期を取る必要がある場合以外、特にこのプロパティを使用する必要はありません。
例:
def create_background
@sprite1 = Sprite.new
@sprite1.bitmap = Cache.title1($data_system.title1_name)
@sprite2 = Sprite.new
@sprite2.bitmap = Cache.title2($data_system.title2_name)
center_sprite(@sprite1)
center_sprite(@sprite2)
@sprite3 = Sprite.new
@sprite3.bitmap = Cache.battler("Angel",0)
center_sprite(@sprite3)
@sprite3.wave_amp=10
@sprite3.wave_length=15
@sprite3.wave_speed=360
@sprite3.wave_phase=200
end
def update
update_basic
@sprite3.update
end
こんなものほとんど使ったことがないです
さて、いかがだったでしょうか。なるべく簡潔でわかりやすいように、と書いてみたのですが、気付いたころには文字数が8800字を超えていました。実は、Bitmapクラスを利用してまた別の画像編集をすることができるのですが、それはまたの機会に書きたいと思います。
次回はタイトル画面に雨や雪、その他を降らせる方法を書いていきます。