Codes: Game Trailer (in RenPy!)

As someone with no video editing experience, looking at the requirement of making a trailer for YAGS, I was rather daunted by the prospect of figuring something out.

Enter RenPy, and ATL! A WIP version of the trailer can be viewed here. (Edit: Here now.)

I was able to create the entire game trailer in RenPy. The best part is that, because most of the sprites aren’t done yet, but the trailer is just RenPy code, I can easily fill in the final sprites later and re-record the video, without having to do serious updates. (At least, if I was doing this with video editing software, I imagine it would be a larger pain to swap images out.)

The best way to share this is probably to literally just paste the entire code used to create the trailer below. There are some notes and things I want to point out, after this huge block of text.

define quickwipeclear = CropMove(0.2, "wipeleft")
define quickwipe = CropMove(0.5, "wipeleft")
define quickwiperight = CropMove(0.5, "wiperight")
define quickwipeup = CropMove(0.5, "wipeup")

image welcomecollege = Text("Welcome to your Freshman year of college...", size=70)

image makefriends = Text("Meet people...", size=60)
image makefriendstwo = Text("(...and make friends...)", size=40)
image navigatecollege = Text("...navigate college life...", size=60)
image comeout = Text("...and come out...", size=60)
image comeoutfriends = Text("(...with a bit of help.)", size=40)

image makedec = Text("Make life-changing decisions!", size=40)
image playgames = Text("Play board games!", size=40)
image findbf = Text("Maybe even find a boyfriend?", size=40)

image comingsoon = Text("{color=#ffffff}Coming soon{/color}", size=60)
image myurl = Text("{color=#ffffff}https://yags-game.tumblr.com{/color}", size=40)

image adam grin = "images/adamgrin.png"
image nikhil crossed = "images/nikhilcrossed.png"

image adamchoice = "images/adamchoices.png"
image adamchoice choiceone = "images/adamchoices1.png"
image adamchoice choicetwo = "images/adamchoices2.png"
image adamchoice choicethree = "images/adamchoices3.png"

image gameschoice = "images/gamechoices.png"
image gameschoice choiceone = "images/gamechoices1.png"

image questionmark = Text("?", size=300)


transform questionm:
    xalign 0.5
    yalign 0.5
    alpha 0.0
    linear 1.0 alpha 1.0
    parallel:
        linear 4.0 alpha 0.2
        pause 1.0
        linear 0.5 alpha 0.0
    parallel:
        linear 5.5 zoom 5.0
transform campustransp:
    alpha 0.0
    pause 0.5
    linear 0.5 alpha 0.2
transform logoshow:
    zoom 20.0 xalign 0.5 yalign 0.5 alpha 0.0
    parallel:
        linear 0.5 alpha 1.0
    parallel:
        linear 0.5 zoom 0.8
    parallel:
        linear 0.5 rotate 2.0
    linear 0.2 zoom 1.3
    parallel:
        linear 0.3 rotate 0.0
    parallel:
        linear 0.3 zoom 1.0
    linear 0.2 zoom 1.1
    linear 0.2 zoom 1.0
transform whitefadeout:
    xalign 0.5
    yalign 0.5
    alpha 0.0
    linear 0.5 alpha 0.8
    linear 0.5 alpha 1.0
transform whitefadequick:
    xalign 0.5
    yalign 0.5
    alpha 0.0
    linear 0.5 alpha 1.0
transform subtextfadein:
    xalign 0.5
    yalign 0.3
    alpha 0.0
    pause 1.0
    linear 0.3 alpha 1.0
transform textfadein:
    xalign 0.5
    yalign 0.2
    alpha 0.0
    linear 0.3 alpha 1.0
transform adamcursor1:
    xalign 0.5
    yanchor 0.0
    ypos -50
    linear 1.0 ypos 350
transform adamcursor2:
    ypos 350
    parallel:
        linear 0.5 ypos 187
    parallel:
        linear 0.5 xoffset 50
transform adamcursor3:
    ypos 187
    parallel:
        linear 0.25 ypos 270
    parallel:
        linear 0.25 xoffset -20
transform gamescursor1:
    xalign 0.5
    yanchor 0.0
    ypos -50
    parallel:
        linear 0.7 ypos 226
    parallel:
        linear 0.7 xoffset 100
        
label start:
$ quick_menu = False
scene black
$ renpy.pause(2.0)
hide window
play music "theme.wav" noloop
show logo at logoshow
$ renpy.pause(1.5)
show campus behind logo with quickwipe
show logo with move:
    yoffset -100
show welcomecollege with dissolve:
    yanchor 1.0
    xalign 0.5
    ypos 550
$ renpy.pause(1.5)
show whitefill at whitefadeout
$ renpy.pause(0.5)
show white at whitefadequick
$ renpy.pause(1.7)
scene white
show makefriends at textfadein
show makefriendstwo at subtextfadein
show adam with moveinleft:
    yalign 1.0
    xanchor 0.5
    xpos 0.2
$ renpy.pause(1.0)
show juan with moveinright:
    yalign 1.0
    xanchor 0.5
    xpos 0.8
$ renpy.pause(1.0)
show frat behind adam with quickwiperight
$ renpy.pause(1.0)
show otherfrat behind adam with quickwipeup
$ renpy.pause(1.3)
scene white with quickwipeclear
show navigatecollege at textfadein
show james with moveinleft:
    yalign 1.0
    xanchor 0.5
    xpos 0.2
$ renpy.pause(1.0)
show dan with moveinright:
    yalign 1.0
    xanchor 0.5
    xpos 0.8
$ renpy.pause(1.0)
show halls behind james with quickwiperight
$ renpy.pause(1.0)
show otherqa behind james with quickwipeup
$ renpy.pause(1.3)
scene white with quickwipeclear
show comeout at textfadein
show comeoutfriends at subtextfadein
show jake with moveinleft:
    yalign 1.0
    xanchor 0.5
    xpos 0.2
$ renpy.pause(1.0)
show nikhil with moveinright:
    yalign 1.0
    xanchor 0.5
    xpos 0.8
$ renpy.pause(1.0)
show gamer behind jake with quickwiperight
$ renpy.pause(1.0)
show othergames behind jake with quickwipeup
$ renpy.pause(1.5)
scene theyard
show adam
show white:
    xalign 0.5
    yalign 0.5
    alpha 0.3
show makedec:
    xalign 0.5
    yalign 0.3
with quickwipeup
$ renpy.pause(1.0)
hide white
hide makedec
with dissolve
"You wonder if it's just his friendly demeanor, but somehow, the prompt makes you actually consider telling him. After all, you {i}do{/i} have to live with this guy for the next 9 months.{w=3.25}{nw}"
window hide
show cursor at adamcursor1
show adamchoice behind cursor:
    xalign 0.5
    yalign 0.5
$ renpy.pause(0.45)
show adamchoice choiceone:
    xalign 0.5
    yalign 0.5
$ renpy.pause(0.2)
show adamchoice choicetwo:
    xalign 0.5
    yalign 0.5
$ renpy.pause(0.2)
show adamchoice choicethree:
    xalign 0.5
    yalign 0.5
$ renpy.pause(0.7)
show cursor at adamcursor2
$ renpy.pause(0.2)
show adamchoice choicetwo
$ renpy.pause(0.2)
show adamchoice choiceone
$ renpy.pause(0.7)
show cursor at adamcursor3
$ renpy.pause(0.2)
show adamchoice choicetwo
$ renpy.pause(0.7)
hide adamchoice
hide cursor
show adam grin
"You hit yourself internally, vowing to take the next good opportunity to come out to him.{w=1.75}{nw}"
scene atrium
show jake:
    yalign 1.0
    xanchor 0.5
    xpos 0.2
show nikhil crossed:
    yalign 1.0
    xanchor 0.5
    xpos 0.8
show white:
    xalign 0.5
    yalign 0.5
    alpha 0.3
show playgames:
    xalign 0.5
    yalign 0.3
with quickwipe
$ renpy.pause(1.0)
hide white
hide playgames
with dissolve
nick "Ooo. Make a new city!{w=0.75}{nw}"
jake "No way. Finish that city. Guaranteed points. And a meeple back.{w=1.0}{nw}"
window hide
show cursor at gamescursor1
show gameschoice behind cursor
$ renpy.pause(0.6)
show gameschoice choiceone
$ renpy.pause(1.0)
hide cursor
hide gameschoice
show nikhil
nick "Going with the safe play? Both of you play it safe too often.{w=1.5}{nw}"
scene qaroom
show dan:
    yalign 1.0
    xalign 0.5
show white:
    xalign 0.5
    yalign 0.5
    alpha 0.3
show findbf:
    xalign 0.5
    yalign 0.3
with quickwipe
$ renpy.pause(1.0)
hide white
hide findbf
with dissolve
"Dan is there by himself, sitting on a couch when you arrive.{w=1.25}{nw}"
dan "Christopher!{w=1.0}{nw}"
hide window
show questionmark at questionm
$ renpy.pause(0.5)
hide dan
show james behind questionmark
$ renpy.pause(1.0)
hide james
show jake behind questionmark
$ renpy.pause(1.0)
hide jake
show nikhil behind questionmark
$ renpy.pause(1.0)
hide nikhil
show juan behind questionmark
$ renpy.pause(1.0)
hide juan
show adam behind questionmark
$ renpy.pause(1.2)
scene black with quickwipeup
show logo with dissolve:
    zoom 0.8
    xalign 0.5
    yalign 0.2
$ renpy.pause(1.8)
show comingsoon with dissolve:
    xalign 0.5
    yalign 0.6
$ renpy.pause(1.0)
show myurl with dissolve:
    xalign 0.5
    yalign 0.7
$ renpy.pause()
return

The most important timing thing is to automatically advance text without clicking. The combination of {w=number} and {nw} does that quite nicely.

The second weird thing is how to handle choice menus. Because there’s otherwise no good way to handle that, and you really don’t want the timing to be at the whim of you clicking at the right time, I cheated…

I put up a real choice menu, then took screenshots of the screen and with the mouse hovered over each option, in turn. I then removed the choice menu and showed these screenshots instead (with a fake cursor image hovering over them and moving around).

Everything else is fairly straightforward. We rely heavily on RenPy automatically creating displayable for items in the /images folder with the right names. Everything else is just making sure we synchronize to the music.

To actually record the trailer, we take advantage of Windows 10′s game bar. Hit Win+G while the game is started, then start recording. The extra click and pause at the beginning is so you can move your cursor out of the way before the actual trailer starts. After it’s recorded, you can trim it to size using Windows 10′s Photos program (right click the video, Open With, Photos).