見出し画像

非プログラマのRen'Pyノート:演出とかアニメーション 〜screen編〜

プログラムの知識はない個人開発者が推しツール「Ren'Py」(以下renpy)のTIPSなどを細々書いています本シリーズ、今回はscreenをscreenごとアニメーションさせたり、addするimageをアニメーションさせる方法についてまとめました。

本稿は「renpyで色々なことができるのはうっすらわかってきた。ところでscreenを動かしたいのだが……」という方向けの限定的な内容です。内容がやや中〜上級者向け? のため、つまり、非プログラマの私により解説が不十分なまま進行しますことご容赦ください。

renpyとはつまりどんなツールなのか? 触ったことはないけど興味はある。という方はこちらをご覧ください。

そもそもrenpyのScreenとは何なのか?

マニュアルを読んでも何のことやらわからない私のために記しておきますと、ざっくり

-概念的には「レイヤー」のようなもの?
-元々say、コンフィグスクリーンなどがあり、自前でも作れる
-役割上、かなり手前(立ち絵の前など)に表示される
-基本hideしない限り消えない
-labelほど自由には使えず、書けるスクリプトに制限がある

……みたいな理解でおります。

難しいことを理解できてなくてもコピペーでそれっぽく動けばそれでいいのです。という私のために、アーカイブも兼ねてscreenをアニメーションする方法を残します。

renpy勢の皆様におかれましてはコピペーでどんどんご利用ください。利用報告などは特に必要ありませんが、よろしければrenpyでこんなことができるよとSNSで広めていただければ幸いです。


at transform で直書き

これが一番分かりやすいかな? と思う方法です。汎用性は低いかもですが、1screenにつき1アニメならこれで十分です。

##カウンタ増減########################################################
screen ex():#ただのtext show ではカウンタ減りしない?
    text "{size=62}{color=#fff}Ex.[ex_now]{/color}{/size}":
        at transform:
            alpha 0.0
            align (0.5, 0.4) 
            linear 0.3 ypos 0.34 alpha 1.0

これはtextに使っていますが、imagebuttonやframeにも使えます。厳密にいうとscreenを動かしてるわけじゃないんですが、同じサイズのbackground がないフレームを置くと実質スクリーンが動いてるっぽくできます。

ちなみに……本稿では at trans と at transform があって、違いがよく分かっていませんが何か分かりましたら追記します。

showとhideを指定し、at で含める

まず、Transformで動きを決めます。 その際、on show & on hide と設定すると、show screen と hide screen に自動で付与されます。

これはメニュー画面をスマホにして、斜め下に置いてぴよっと回転して出てくる仕様にしたもの。

screen phone():
    zorder 101

    frame:
        at phone_anm #電話の動き

        anchor(0.5, 0.36)
        xpos 0.9 #transformの方が優勢になるので注意
        xsize 500 ysize 899 #これを消すと回転軸もはちゃめちゃになる
        background "iphone.png"

        vbox:
            xalign 0.5
            ypos 0.25
            
            text "[tsuki][hiduke]日":#ローカライズ注意
                size 64
                color "#fff"
                xalign 0.5

            text "[youbi]曜日 [asahiruyoru]":#ローカライズ注意
                size 42
                color "#fff"
                xalign 0.5


transform phone_anm: #電話の動き
    on show:#これサンプル置いといてね〜
        ypos 0.9 rotate 10 #rotate 90
    on hide:#左に滑りつつ消えます
        linear 0.2 xpos 0.5 alpha 0.0

これで、label start: 以下で、表示したいときは

show screen phone()

表示したものを消すときは

hide screen phone

でtransform 通り動く……はず、なのですが、私が動かしてみた範囲だと、on hideにpauseを入れても、末尾であった場合無視され次の動作に移ってしまうので、hide screen 〜 の後に任意の秒数入れないと待ってもらえないようです。


アニメーションの種類が多い時は (trans) で

screenの最後についている謎の()、これはどうも何かを代入する時に使うようです。

上記で紹介した方法の場合、動きの種類が複数あるなら if で分ける必要があります。これでも良いのですが、変数を入れて処理すると今度は表示したあと消したりという手間が必要になってきます。

じゃあscreen内でフラグを倒せばいいんじゃない? と私も思ってたんですが、screen内での変数の取得はこれまたややこしいそうですので、おすすめではありません。

そこで、()に代入することで解決するパターンも共有します。

transform moveup:
   yalign 1.2
   linear 0.3 yalign 0.5 

screen phone(trans):#
    zorder 101

    frame:
        at trans
        anchor(0.5, 0.36)
        xpos 0.9 
        xsize 500 
        background "iphone.png"

label start:
    show screen phone(moveup)
    "表示されたかな"

多分trans以外にもこのように()に変数を入れることでscreen(に入れたframe内)に代入できてどうにかなるものがあるっぽいとうっすらわかってはきたのですが、解説できるほど詳しくないので割愛します!

時間経過で消したい場合は timer を利用

消すことがアニメーションに含まれるかというと微妙ですが、チュートリアル表示などにとっても便利なので共有します。

screen hintdayo():#ヒントウィンドウ
    timer 1.5 action Hide("hintdayo")#=1.5秒でhintodayo screenが消える

    add "hogehoge":#画像などお好みで
        ypos 0.5

    frame:
        xsize 480
        xpos 0.18
        ypos 0.75
        xalign 0.5

        text "ヒントだよ〜"

いや便利……便利だわ……。

手抜き雑TIPSとして「screenをshowしたら音を鳴らしたい」場合、自分はtimer 0.01 action Play〜 とかで鳴らしたりしてます。

また、modal Trueを使うけど、そのscreen自体を手動で消す手段がない、という時にも使っています。

そんなケースある?と思われるかも知れませんが、screenで表示せざるをえないギミックの上に、さらにレイヤー乗っけてカットイン表示する。みたいなケースです。ただのimageでも表示はできますが、そうすると下にあるギミックに干渉できてしまうので、 modal Trueにしたscreenを表示するのしか思いつきませんでした。

imageで登録したものをadd で含める

これはスクリーンそのものを動かしたいというより、スクリーンに含まれる画像を個別にアニメーションさせたいケースなどに有効です。以下リンクにも山盛りサンプルがありますが念の為引用します。

## Main Menu(メインメニュー)スクリーン #####################################################
##
## Ren'Py が起動した時に表示されるメインメニューを表示するスクリーンです。
##
## https://ja.renpy.org/doc/html/screen_special.html#main-menu

image bg_title:#タイトル背景をカメラ移動してます
    "images/opening.jpg"
    alpha 0.0
    ypos 0.0
    linear 1.0 ypos -160 alpha 1.0

image neko_ato:#猫の場所
    "images/title02_neko.png"
    align (1.0, 1.08)
    alpha 0.0
    pause 0.3
    linear 0.5 alpha 1.0

image title_anm:#タイトルをフェードインしてます
    "images/title02_line.png"
    zoom 0.8
    alpha 0.0
    align (0.98, 0.98)
    #xanchor 0.5 
    linear 0.3 alpha 1.0 zoom 0.8    

screen main_menu():

    ## 次のコードは、同じタグを持つ他のメニュースクリーンが表示された時にスクリ
    ## ーンを置換します。
    tag menu

    #add gui.main_menu_background #以下オリジナルに差し替えています
    add "bg_title"
    add "title_anm"
    add "neko_ato"

    ## 次の空のフレームは gui/overlay/main_menu.png を表示してメインメニューを暗
    ## くしています。
    frame:
        #style "main_menu_frame"
        background "images/black_frame.png" #差し替えました


screen表示時に音を鳴らす……?

screen phone():
    $ renpy.play("audio/phonecall.mp3") 

これで鳴る……には鳴るんですけど、自分がやるとゲーム開始時に全部鳴ってしまいます?? screen内で音を鳴らすのは色々調べてみたんですが、タイマーやボタン+アクション等でやるケース以外は「今んとこない」という認識でいます。

続々と集まる知見

試してみて動作確認できたらまた追記しますが、戦闘力高めな皆様のおかげでできそうな空気が漂ってまいりました!

番外編:image内で音を再生する

screen内でアニメーションする場合、外部からは干渉できないため、途中で音を再生したいときはどうしようもない? のかと探してみたところpythonで強引に音再生の機能をimageに仕込む方法が見つかりましたので共有します。

ただこれ多分やや無理やりっぽいのだろうなと思います。

init -1 python:
    def play_effect(trans, st, at):#()内がなんなのかビタイチわからん
        renpy.play("effect.mp3", channel="sound")
    def stop_effect(trans, st, at):
        stop.sound.renpy(channel="sound", fadeout=1.5)


image hoge_anim:
    "images/hoge1.png"
    function play_effect
    0.7
    "images/hoge2.png"
    function play_effect
    0.7
    "images/hoge3.png"
    function stop_effect
    0.7

これで、上述のadd などでhoge_animをaddすればOKです。

音のチャンネルは、soundを指定すると効果音が重なったとき消し去っちゃうので、audioにしておくと良いか? と思いきや、停止する方法がない? みたいなので、めっちゃ詳しい人以外にはおすすめではありません。

この記事が参加している募集

ゲームの作り方

この記事が気に入ったらサポートをしてみませんか?