Below you will find the final scripts and the overall final look of the game. I have added a clip of the gameplay as well as some screenshots and the link to the game!
━━━━━━∙⋆⋅⋆∙━━━━━━━━━━∙⋆⋅⋆∙━━━━━━
Game clips and Screenshots


























Annotated Final Scripts
Main Script
# The script of the game goes in this file.
# Declare characters used by this game. The color argument colorizes the
# name of the character.
# The game starts here.
image violet think = "violet think.png"
# Declare an image that can be used in scenes (e.g., character expression)
define e = Character ("Violet")
# Define a character with their display name and (optionally) a custom textbox or style
define y = Character("Yami") # Normal Yami
# Define a character with their display name and (optionally) a custom textbox or style
define y_alt = Character("Yami", screen="alt_say") # Custom textbox version
# Define a character with their display name and (optionally) a custom textbox or style
define m = Character(None, what_italic=True)
# Define a character with their display name and (optionally) a custom textbox or style
default affection = 0.5
# Set a default value for a variable (affection) that tracks relationship status or progress
screen choice(items):
# Define a custom screen for presenting choices to the player
vbox:
# Vertical layout box to stack UI elements (buttons in this case)
style_prefix "choice"
xalign 0.95 # Align to the right side of the screen
yalign 0.5 # Vertically center
spacing 15
for i in items:
button:
# Each choice is rendered as a button with its own action
action i.action
xsize 650 # Smaller width for each button
# Each choice is rendered as a button with its own action
text i.caption style "choice_text"
# Set the label of the button using the defined text style
style choice_text:
# Define the text style for choice buttons
size 30
color "#FFFFFF"
screen affection_bar():
# Create a custom screen that visually displays the affection value as a vertical bar
$ total_height = 600
$ bar_width = 900
$ fill_height = int(total_height * affection)
# Calculate the fill height of the affection bar based on the affection value
fixed:
# 'fixed' layout used to manually control placement of child elements
xpos -250
ypos 100
add "bar_bg.png" size (bar_width, total_height)
add "bar_fill.png" at Transform(anchor=(0.0, 1.0)):
size (bar_width, fill_height)
xpos 0
ypos total_height
label start:
show bg start
show violet think
m "You find yourself walking aimlessly in a sparse forest, the sun rays dancing around onto the lush blades of grass and the strong aroma of an assortment of wildflowers infiltrates your nose."
m "As you wander further into the forest, a tall, slender figure emerges from the trees and extends a welcoming hand out to you."
m "You could immediately feel the warmth that radiated from his smile. His attire displays an impression of importance and regality, a red velvet cape follows his shadow."
m "He approaches you with such gentle poise and introduces himself as your-"
hide violet think
show violet head sleep onlayer over_screens
"Violet" "Prince Charming..."
hide violet head sleep onlayer over_screens
play sound "audio/phone alarmm.mp3" volume 0.8
scene bg bedroom
show violet head sleep onlayer over_screens
"Violet" "AGH!"
play music "audio/bedroom music.mp3" volume 0.5 fadein 1.0
hide violet head sleep onlayer over_screens
m "You spring up from bed, half awake and notice that you have 2 missed calls and an ongoing call from your friend Elijah."
show phone call
show violet head sleep onlayer over_screens
"Violet" "G-Good morning! Sorry I’m almost there Eli! Aha..."
hide violet head sleep onlayer over_screens
m "You leap out of the comfort of your sheets and stumble towards your dresser."
"Elijah" "Girl, I know damn well you just woke up now. You really need to fix that sleep schedule because passing out at 3AM can’t be that good for you."
show violet head sleep onlayer over_screens
"Violet" "This is the last time I promise! Sortaaaaa… I was finishing up the 5th to last episode of this romance series about a princess locked away and escaping to find her prince. Just 5 more episodes to go and I can go back to doing whatever again!"
hide violet head sleep onlayer over_screens
"Elijah" "That’s another fat lie, you’re gonna click on another series and start this cycle again."
show violet head sleep onlayer over_screens
"Violet" "Hehe-"
hide violet head sleep onlayer over_screens
"Elijah" "Anyways, what are you wearing for today?"
hide phone call
label choices:
"What are you wearing today?"
menu:
"Casual- I’m wearing my green shirt and a miniskirt.":
jump choices1_a
"Doll yourself up- I’m gonna attempt to look nice today, I have a new dress I wanna try on but I think it’s a bit too short…":
jump choices1_b
label choices1_a:
"You feel cute and comfortable in this outfit."
jump choices1_common
label choices1_b:
"You feel confident, but weary about this outfit."
jump choices1_common
label choices1_common:
m "Just as you open the door, you can’t help but have a bad feeling about today."
stop music fadeout 1.5
label start_2:
call screen mapScreen
label myScreens_2:
screen mapScreen:
add "bg map.png"
#room2
imagebutton:
# Declare an image that can be used in scenes (e.g., character expression)
xpos 630
ypos 200
xysize (246, 215)
idle "cafe_idle.png"
hover "cafe_hover.png"
action Jump ("room2")
label room1:
scene bg bedroom
"Welcome to Violet's bedroom!"
label room2:
scene bg cafe exterior
with fade
play music "audio/outside cafe.mp3" volume 1 fadein 0.5
m "Hopefully Eli isn’t here already, I really need to start going to bed earlier."
m "You look around at the beautiful scenery around you, the smell of cakes and pastries fills the air..."
m "Ugh, I can’t wait to see Eli, it's been ages, and the thought of those cakes right now is irresistible..."
play sound "audio/exit.mp3" volume 0.5
scene bg cafe interior
with fade
stop sound
play music "audio/soft cafe music.mp3" volume 0.5 fadein 1.5
m "A few minutes go by as you sit and stare at the hot chocolate in front of you going cold. You try to distract yourself from the fact that Elijah is late once again…"
m "Looking around you see all the yummy pastries just waiting on the side, wishing they were in your belly right now, some cute little jellyfish lights which look so magical and…"
play sound "audio/phone buzzing.mp3" volume 0.8
show violet head onlayer over_screens
"Violet" "AGH! Oh, um..."
hide violet head onlayer over_screens
m "You blush, hoping no one just heard you letting out that yelp. You look down to see messages from Elijah."
label start_3:
call screen phoneScreen
label myScreens:
screen phoneScreen:
add "phone home.png"
#texts
imagebutton:
# Declare an image that can be used in scenes (e.g., character expression)
xpos 800
ypos 750
xysize (246, 215)
idle "text_idle.png"
hover "text_hover.png"
action Jump ("texts")
label texts:
show phone blank
show text one
show text two
show text three
show text four
show text five
play sound "audio/sigh.mp3" volume 0.6
show violet head onlayer over_screens
"Violet" "Why, Eli???"
hide violet head onlayer over_screens
m "As you debate whether or not to leave the cafe you hear a voice."
play sound "audio/footsteps.mp3" volume 0.8
label start_4:
hide phone blank
hide text one
hide text two
hide text three
hide text four
hide text five
show yami standing
show screen affection_bar
# Create a custom screen that visually displays the affection value as a vertical bar
"???" "You must be the famous Violet."
"You look up from your phone to be met with this random stranger smirking at you."
show violet head onlayer over_screens
"Violet" "Ugh, yes, sorry, who are you?"
hide violet head onlayer over_screens
show yami head onlayer over_screens
"???" "Name’s Yami."
hide yami head onlayer over_screens
show yami neutral
show coffee single
m "Before you can say anything more, Yami sits down in front of you, placing his coffee down and looking up at you... You can already feel the intensity from his gaze."
show yami neutral
show coffee single
show violet head onlayer over_screens
"Violet" "Well, nice to meet you Yami. Sorry, I was not prepared for this at all."
hide violet head onlayer over_screens
show yami head onlayer over_screens
"Yami" "Don’t worry about that. We’re here now, that’s all that matters."
hide yami head onlayer over_screens
show violet head onlayer over_screens
"Violet" "Yeah. Anyways, as you know my name is Vio-"
hide violet head onlayer over_screens
show yami mad
show yami head onlayer over_screens
"Yami" "I was standing here alone for 10 minutes, I was worried I was going to be stood up! Can you imagine how embarrassing that would’ve been for me?"
"Yami" "So, how are you?"
hide yami head onlayer over_screens
show yami happy
"Yami lets out a light chuckle."
m "Did he just interrupt me? Rude, but okay, maybe it’s just first date nerves."
label choices_2:
menu:
"Good, now that you’re here.":
jump choices2_a
"I’m good, thank you, you?":
jump choices2_b
"Well, I have been better but I’m fine.":
jump choices2_c
label choices2_a:
show yami smirk
$ affection += 0.0625
jump choices2_common
label choices2_b:
show yami distracted
$ affection += 0
jump choices2_common
label choices2_c:
show yami mad
$ affection -= 0.0625
jump choices2_common
label choices2_common:
show yami head onlayer over_screens
"Yami" "I’ve had a bit of a morning, you know when you look this good you have all these agencies trying to book you."
hide yami head onlayer over_screens
show yami neutral
label start_5:
"He looks at you waiting for a response, but before you can even say a word he continues."
show yami head onlayer over_screens
"Yami" "I mean you probably wouldn’t know, but that’s okay, we all start somewhere."
hide yami head onlayer over_screens
show yami happy
m "You frown, annoyed by the comment. You decide to dismiss the comment and try to keep a straight face, but you’ll keep this in mind when he next says anything."
show yami head onlayer over_screens
"Yami" "I’m joking, pretty lady, just relax."
hide yami head onlayer over_screens
show yami neutral
label choices_3:
menu:
"Awhh, so you do think I’m pretty.":
jump choices3_a
"I’m all relaxed, don’t you worry.":
jump choices3_b
"Oh, so now you think I’m pretty? Funny way of showing it.":
jump choices3_c
label choices3_a:
show yami happy
$ affection += 0.0625
jump choices3_common
label choices3_b:
show yami neutral
$ affection += 0
jump choices3_common
label choices3_c:
show yami mad
$ affection -= 0.0625
jump choices3_common
label choices3_common:
show yami head onlayer over_screens
"Yami" "So what do you think of me?"
hide yami head onlayer over_screens
m "Oh god, is he really asking me this?"
label choices_4:
menu:
"I’m not surprised you’re a model, look at you.":
jump choices4_a
"You seem very nice.":
jump choices4_b
"Don’t think you need me to inflate your ego anymore.":
jump choices4_c
label choices4_a:
show yami smirk
$ affection += 0.0625
jump choices4_common
label choices4_b:
show yami happy
$ affection += 0
jump choices4_common
label choices4_c:
show yami mad
$ affection -= 0.0625
jump choices4_common
label choices4_common:
m "You take a closer look at Yami, his long, sweeping eyelashes complimenting his androgynous features. There's a subtle elegance in each flick of his lashes framing his slender eyes, yet a glint of undying certitude emanates."
label start_6:
m "The dappled light filters through the seashell-peppered drapes, casting a soft glow on his golden brown stylishly cut layers."
m "You take a quick glance at his attire and notice that he's decked out in designer brands, each piece adding to his powerful presence."
m "It's like you're living two completely different worlds. His looks are otherworldly, almost mesmerising. It’s no wonder he’s a model, but there's one thing that you can't get over-"
show yami head onlayer over_screens
"Yami" "Like what you see? I don't blame you, if I could make money off my looks, I would- oh wait, I do!"
hide yami head onlayer over_screens
show yami smirk
m "He's totally full of himself!"
m "All of a sudden, the waiter brings over the yummiest cake and places it down in front of you. You look at Yami wondering if he had ordered as a little gift, but he looks at you just as confused. The waiter catches onto the confused expressions."
label start_11:
call screen dessertScreen
label myScreens_3:
screen dessertScreen:
add "dessert blank.png"
#desserthint
imagebutton:
# Declare an image that can be used in scenes (e.g., character expression)
xpos 0
ypos 0
idle "dessert_idle.png"
hover "dessert_hover.png"
action Jump ("desserthint")
label desserthint:
"1/4 hints unlocked!"
label start_10:
show yami neutral
show waiter head onlayer over_screens
"Waiter" "Sorry, I think there’s been a mix-up."
hide dessert idle
hide waiter head onlayer over_screens
m "The waiter picks up the cake and takes it off."
show violet head onlayer over_screens
"Violet" "That was odd, aha-"
hide violet head onlayer over_screens
show yami head onlayer over_screens
"Yami" "You should have said it was yours."
hide yami head onlayer over_screens
show yami smirk
show violet head onlayer over_screens
"Violet" "I could never, that was someone else’s ord-"
hide violet head onlayer over_screens
show yami head onlayer over_screens
"Yami" "I would have."
hide yami head onlayer over_screens
show yami happy
m "It goes silent for a second as this is the SECOND time he’s interrupted you."
play sound "audio/sigh.mp3" volume 0.6
show yami neutral
show yami head onlayer over_screens
"Yami" "Have I done something?"
hide yami head onlayer over_screens
show violet head onlayer over_screens
"Violet" "No, no, don’t worry..."
hide violet head onlayer over_screens
show yami distracted
show yami head onlayer over_screens
"Yami" "Hm, okay, I didn’t think so."
hide yami head onlayer over_screens
show yami neutral
m "Wow, I didn’t think he could get anymore ignorant but wait, he just did. The urge to roll my eyes is unbearable right now."
show yami happy
show yami head onlayer over_screens
"Yami" "You’ll never guess what I got asked to do this week."
hide yami head onlayer over_screens
show violet head onlayer over_screens
"Violet" "Um, wha-"
hide violet head onlayer over_screens
show yami head onlayer over_screens
"Yami" "I got asked to model for IMG models, pretty impressive, am I right?"
hide yami head onlayer over_screens
show yami smirk
m "Ugh, is he only going to talk about himself on this date..."
label choices_5:
menu:
"That’s amazing, clearly you’re a hot shot.":
jump choices5_a
"Oh, that’s cool! Well done.":
jump choices5_b
"I guess so.":
jump choices5_c
label choices5_a:
show yami smirk
$ affection += 0.0625
jump choices5_common
label choices5_b:
show yami happy
$ affection += 0
jump choices5_common
label choices5_c:
show yami mad
$ affection -= 0.0625
jump choices5_common
label choices5_common:
show violet head onlayer over_screens
"Violet" "I actually really like fashion, maybe you could give me some tips?"
show yami happy
hide violet head onlayer over_screens
label start_7:
show yami head onlayer over_screens
"Yami" "I thought you’d never ask."
show yami smirk
"Yami" "To be honest though, some people just get fashion and, well, others just don't…"
show yami neutral
"Yami" "But, I guess if I had to give you some tips, it would be to figure out your own colour palette, whether you're cold, warm or neutral tones, always helps."
"Yami" "And then there’s a whole other route of finding out what season you are, in colour terms of course."
hide yami head onlayer over_screens
m "Hmm, so he can actually be helpful... If only he was like this the whole time..."
show violet head onlayer over_screens
"Violet" "Well, thank you very much, mister top model."
hide violet head onlayer over_screens
show yami smirk
show yami head onlayer over_screens
"Yami" "What can I say, I’m an all-rounder."
hide yami head onlayer over_screens
show yami neutral
play sound "audio/sigh.mp3" volume 0.6
show violet head onlayer over_screens
"Violet" "I feel like I’ve gotten to know about you, soo... How about I tell you a little about me?"
hide violet head onlayer over_screens
show yami head onlayer over_screens
"Yami" "I guess..."
hide yami head onlayer over_screens
show violet head onlayer over_screens
"Violet" "Well, I loveeee, and I mean LOVE, watching classic romance films."
hide violet head
show yami distracted
show yami head onlayer over_screens
"Yami" "Oh yeah?"
hide yami head onlayer over_screens
m "Wow, okay, last time I ever talk about myself, geez-"
show violet head onlayer over_screens
"Violet" "Anyway... What do you like to watch?"
hide violet head onlayer over_screens
show yami neutral
show yami head onlayer over_screens
"Yami" "Oh, I don’t like to waste my time watching films, I’d much rather be starring in them, you know, because I’m a model, I could easily land myself an acting role."
hide yami head onlayer over_screens
show yami smirk
label choices_6:
menu:
"I could definitely see you in a romance film, the hot, sexy model.":
jump choices6_a
"I’m sure you’d do great!":
jump choices6_b
"You know not everything has to involve you, right?":
jump choices6_c
label choices6_a:
show yami smirk
$ affection += 0.0625
jump choices6_common
label choices6_b:
show yami happy
$ affection += 0
jump choices6_common
label choices6_c:
show yami mad
$ affection -= 0.0625
jump choices6_common
label choices6_common:
show violet head onlayer over_screens
"Violet" "Sooo, what you drinking? It looks nice."
hide violet head onlayer over_screens
label start_8:
show yami smirk
show yami head onlayer over_screens
"Yami" "It’s a latte with sugar-free vanilla. Sophisticated, but have to watch the calories. Can’t be ruining a hot bod like mine."
show yami neutral
"Yami" "What about yours? It looks like something a kid would order... And all that sugar..."
hide yami head onlayer over_screens
label choices_7:
menu:
"Yeah, I guess you’re right. I never thought about it like that.":
jump choices7_a
"Oh, I always get a hot chocolate.":
jump choices7_b
"Lighten up a bit, it’s only a hot chocolate with whipped cream and marshmallows, geez-":
jump choices7_c
label choices7_a:
show yami happy
$ affection += 0.0625
jump choices7_common
label choices7_b:
show yami neutral
$ affection += 0
jump choices7_common
label choices7_c:
show yami mad
$ affection -= 0.0625
jump choices7_common
label choices7_common:
m "At this point I don’t even know why HE, let alone myself, agreed to go on this date…"
show yami smirk
label start_9:
show yami head onlayer over_screens
"Yami" "You know, I don’t normally do this but you’re actually quite pretty, you’d definitely look good on the side of me."
hide yami head onlayer over_screens
m "Oh... I was not expecting that, but also on the side? So he can just disregard me when he’s done??"
m "But why did that lowkey give me butterflies...?"
m "You begin to enter daydream land where he would sweep you off your feet and off into the sunset…"
show yami neutral
show yami head onlayer over_screens
"Yami" "Earth to miss princess over there?"
hide yami head onlayer over_screens
m "You snap back into reality and feel yourself blushing a nice shade of rouge..."
show violet head onlayer over_screens
"Violet" "Oh my God, sorry, aha..."
hide violet head onlayer over_screens
show yami mad
show yami head onlayer over_screens
"Yami" "I mean, you should be sorry, you're over there in daydream land when you have a literal god in front of you, money is time, sweetheart, and I’m on a tight schedule."
hide yami head onlayer over_screens
m "Well, that didn’t last very long, did it…"
label start_12:
scene bg evil cafe
show yami glitch
show screen affection_bartwo
# Create a custom screen that visually displays the affection value as a vertical bar
with hpunch
hide screen affection_bar
# Create a custom screen that visually displays the affection value as a vertical bar
play sound "audio/glitch cut.mp3" volume 0.8
play music "audio/scary.mp3" volume 0.8 fadein 1.0
$ y_alt = Character("Yami", screen="alt_say", what_style="alt_say_dialogue", who_style="alt_say_label")
show yami evil head onlayer over_screens
y_alt "You know you should be careful with people like me, you really shouldn’t be meeting with random strangers you don’t know"
hide yami evil head onlayer over_screens
stop sound
label choices_9:
menu:
"Oh, you play too much, aha, you're a big softy, really.":
jump choices9_a
"Um... Aha, I don't think that you should say that on a first date...":
jump choices9_b
"What the hell? Who do you think you are talking to me like that!":
jump choices9_c
label choices9_a:
show yami happy
$ affection += 0.0625
jump choices9_common
label choices9_b:
show yami neutral
$ affection += 0
jump choices9_common
label choices9_c:
show yami mad
$ affection -= 0.0625
jump choices9_common
label choices9_common:
hide screen affection_bartwo
# Create a custom screen that visually displays the affection value as a vertical bar
show screen affection_bar
# Create a custom screen that visually displays the affection value as a vertical bar
show bg cafe interior
with fade
play music "audio/soft cafe music.mp3" volume 0.5 fadein 1.5
m "WHAT ON EARTH WAS THAT?!!!"
show yami neutral
"Yami..." "Is something the matter, beautiful?"
m "No way, is he acting like nothing just happened? I literally saw that with my own two eyes."
m "Your eyes dart around the room to see if anyone else witnessed what you just did but alas nothing, just couples enjoying their cakes and drinks."
m "I really need to start going to bed earlier."
"Violet." "Uh- oh... no, nothing, don’t worry, just lack of sleep."
show yami smirk
"yami" "No worries, maybe we should wrap this up?"
"Violet" "Yeah, maybe that would be for the best."
"Yami" "Violet, before you go… I have something to ask you."
m "Oh god, not another thing, just let me goooo-"
"Violet" "Yes, Yami?"
"Yami" "I was thinking, me, you, another date?"
show yami smirk
label choices_10:
menu:
"I mean, sure, why not, it couldn't hurt to do so.":
jump choices10_a
"It's going to have to be a no... you were just not it.":
jump choices10_b
label choices10_a:
show yami happy
"See you next time then, Violet."
hide yami happy
with fade
play sound "audio/exit.mp3" volume 0.5
hide screen affection_bar
# Create a custom screen that visually displays the affection value as a vertical bar
scene bg bad ending
with slideleft
stop sound
m "After your second date with Yami you are left absolutely drained, physically and mentally. You decided it’s way better to rot in bed watching rom coms than trying to be in one yourself!"
hide screen affection_bar
# Create a custom screen that visually displays the affection value as a vertical bar
jump credits
label choices10_b:
show yami mad
with vpunch
hide yami mad
with dissolve
play sound "audio/exit.mp3" volume 0.5
hide screen affection_bar
# Create a custom screen that visually displays the affection value as a vertical bar
scene bg good ending
with slideleft
stop sound
"After your date with Yami you couldn’t shake the weird occurrence that happened and so your first protocol was to of course debrief Eli."
jump credits
label credits:
$ quick_menu = False
window hide
$ credits_speed = 7.0
scene bg pink
show credits image
# Declare an image that can be used in scenes (e.g., character expression)
$ renpy.pause(credits_speed + 2.0)
return
Screens Script
################################################################################
## Initialization
################################################################################
init offset = -1
################################################################################
## Styles
################################################################################
init python:
def hide_all_heads():
renpy.hide("yami head")
renpy.hide("violet head")
renpy.hide("waiter head")
transform hide_all:
alpha 0.0
style default:
properties gui.text_properties()
language gui.language
style input:
properties gui.text_properties("input", accent=True)
adjust_spacing False
style hyperlink_text:
properties gui.text_properties("hyperlink", accent=True)
hover_underline True
style gui_text:
properties gui.text_properties("interface")
style button:
properties gui.button_properties("button")
style button_text is gui_text:
properties gui.text_properties("button")
yalign 0.5
style label_text is gui_text:
properties gui.text_properties("label", accent=True)
style prompt_text is gui_text:
properties gui.text_properties("prompt")
style bar:
ysize gui.bar_size
left_bar Frame("gui/bar/left.png", gui.bar_borders, tile=gui.bar_tile)
right_bar Frame("gui/bar/right.png", gui.bar_borders, tile=gui.bar_tile)
style vbar:
xsize gui.bar_size
top_bar Frame("gui/bar/top.png", gui.vbar_borders, tile=gui.bar_tile)
bottom_bar Frame("gui/bar/bottom.png", gui.vbar_borders, tile=gui.bar_tile)
style scrollbar:
ysize gui.scrollbar_size
base_bar Frame("gui/scrollbar/horizontal_[prefix_]bar.png", gui.scrollbar_borders, tile=gui.scrollbar_tile)
thumb Frame("gui/scrollbar/horizontal_[prefix_]thumb.png", gui.scrollbar_borders, tile=gui.scrollbar_tile)
style vscrollbar:
xsize gui.scrollbar_size
base_bar Frame("gui/scrollbar/vertical_[prefix_]bar.png", gui.vscrollbar_borders, tile=gui.scrollbar_tile)
thumb Frame("gui/scrollbar/vertical_[prefix_]thumb.png", gui.vscrollbar_borders, tile=gui.scrollbar_tile)
style slider:
ysize gui.slider_size
base_bar Frame("gui/slider/horizontal_[prefix_]bar.png", gui.slider_borders, tile=gui.slider_tile)
thumb "gui/slider/horizontal_[prefix_]thumb.png"
style vslider:
xsize gui.slider_size
base_bar Frame("gui/slider/vertical_[prefix_]bar.png", gui.vslider_borders, tile=gui.slider_tile)
thumb "gui/slider/vertical_[prefix_]thumb.png"
style frame:
padding gui.frame_borders.padding
background Frame("gui/frame.png", gui.frame_borders, tile=gui.frame_tile)
################################################################################
## In-game screens
################################################################################
## Say screen ##################################################################
##
## The say screen is used to display dialogue to the player. It takes two
## parameters, who and what, which are the name of the speaking character and
## the text to be displayed, respectively. (The who parameter can be None if no
## name is given.)
##
## This screen must create a text displayable with id "what", as Ren'Py uses
## this to manage text display. It can also create displayables with id "who"
## and id "window" to apply style properties.
##
## https://www.renpy.org/doc/html/screen_special.html#say
screen say(who, what):
window:
id "window"
if who is not None:
window:
id "namebox"
style "namebox"
text who id "who"
text what id "what"
screen alt_say(who, what):
fixed:
add "gui/textbox_two.png"
# ✅ Side image inside fixed
if not renpy.variant("small"):
add SideImage() xalign 0.0 yalign 1.0
vbox:
xalign 0.55 # Adjust until it fits your box
yalign 0.8
spacing 5
if who:
text who id "who" style "alt_say_label" xalign 0.0 xoffset 210 yoffset 30
text what id "what" style "alt_say_dialogue" xalign 0.0
init -1:
style alt_say_label is say_label
style alt_say_label:
color "#808080"
size 45
init -1:
style alt_say_dialogue is say_dialogue
style alt_say_dialogue:
color "#000000"
size 40
## Make the namebox available for styling through the Character object.
init python:
config.character_id_prefixes.append('namebox')
style window is default
style say_label is default
style say_dialogue is default
style say_thought is say_dialogue
style namebox is default
style namebox_label is say_label
style window:
xalign 0.5
xfill True
yalign gui.textbox_yalign
ysize gui.textbox_height
background Image("gui/textbox.png", xalign=0.5, yalign=1.0)
style namebox:
xpos 685
xanchor gui.name_xalign
xsize gui.namebox_width
ypos -35
ysize gui.namebox_height
background Frame("gui/namebox.png", gui.namebox_borders, tile=gui.namebox_tile, xalign=gui.name_xalign)
padding gui.namebox_borders.padding
style say_label:
properties gui.text_properties("name", accent=True)
xalign gui.name_xalign
yalign 0.5
style say_dialogue:
properties gui.text_properties("dialogue")
xpos 500
xsize 1000
ypos 50
adjust_spacing False
## Input screen ################################################################
##
## This screen is used to display renpy.input. The prompt parameter is used to
## pass a text prompt in.
##
## This screen must create an input displayable with id "input" to accept the
## various input parameters.
##
## https://www.renpy.org/doc/html/screen_special.html#input
screen input(prompt):
style_prefix "input"
window:
vbox:
xanchor gui.dialogue_text_xalign
xpos gui.dialogue_xpos
xsize gui.dialogue_width
ypos gui.dialogue_ypos
text prompt style "input_prompt"
input id "input"
style input_prompt is default
style input_prompt:
xalign gui.dialogue_text_xalign
properties gui.text_properties("input_prompt")
style input:
xalign gui.dialogue_text_xalign
xmaximum gui.dialogue_width
## Choice screen ###############################################################
##
## This screen is used to display the in-game choices presented by the menu
## statement. The one parameter, items, is a list of objects, each with caption
## and action fields.
##
## https://www.renpy.org/doc/html/screen_special.html#choice
screen choice(items):
style_prefix "choice"
vbox:
for i in items:
textbutton i.caption action i.action
style choice_vbox is vbox
style choice_button is button
style choice_button_text is button_text
style choice_vbox:
xalign 0.5
ypos 405
yanchor 0.5
spacing gui.choice_spacing
style choice_button is default:
properties gui.button_properties("choice_button")
style choice_button_text is default:
properties gui.text_properties("choice_button")
## Quick Menu screen ###########################################################
##
## The quick menu is displayed in-game to provide easy access to the out-of-game
## menus.
screen quick_menu():
## Ensure this appears on top of other screens.
zorder 100
if quick_menu:
hbox:
style_prefix "quick"
xalign 0.5
yalign 1.0
textbutton _("Back") action Rollback()
textbutton _("History") action ShowMenu('history')
textbutton _("Skip") action Skip() alternate Skip(fast=True, confirm=True)
textbutton _("Auto") action Preference("auto-forward", "toggle")
textbutton _("Save") action ShowMenu('save')
textbutton _("Q.Save") action QuickSave()
textbutton _("Q.Load") action QuickLoad()
textbutton _("Prefs") action ShowMenu('preferences')
## This code ensures that the quick_menu screen is displayed in-game, whenever
## the player has not explicitly hidden the interface.
init python:
config.overlay_screens.append("quick_menu")
default quick_menu = True
style quick_button is default
style quick_button_text is button_text
style quick_button:
properties gui.button_properties("quick_button")
style quick_button_text:
properties gui.text_properties("quick_button")
################################################################################
## Main and Game Menu Screens
################################################################################
## Navigation screen ###########################################################
##
## This screen is included in the main and game menus, and provides navigation
## to other menus, and to start the game.
screen navigation():
vbox:
style_prefix "navigation"
xpos gui.navigation_xpos
yalign 0.5
spacing gui.navigation_spacing
if main_menu:
textbutton _("Start") action Start()
else:
textbutton _("History") action ShowMenu("history")
textbutton _("Save") action ShowMenu("save")
textbutton _("Load") action ShowMenu("load")
textbutton _("Preferences") action ShowMenu("preferences")
if _in_replay:
textbutton _("End Replay") action EndReplay(confirm=True)
elif not main_menu:
textbutton _("Main Menu") action MainMenu()
textbutton _("About") action ShowMenu("about")
if renpy.variant("pc") or (renpy.variant("web") and not renpy.variant("mobile")):
## Help isn't necessary or relevant to mobile devices.
textbutton _("Help") action ShowMenu("help")
if renpy.variant("pc"):
## The quit button is banned on iOS and unnecessary on Android and
## Web.
textbutton _("Quit") action Quit(confirm=not main_menu)
style navigation_button is gui_button
style navigation_button_text is gui_button_text
style navigation_button:
size_group "navigation"
properties gui.button_properties("navigation_button")
style navigation_button_text:
properties gui.text_properties("navigation_button")
## Main Menu screen ############################################################
##
## Used to display the main menu when Ren'Py starts.
##
## https://www.renpy.org/doc/html/screen_special.html#main-menu
screen main_menu():
## This ensures that any other menu screen is replaced.
tag menu
add gui.main_menu_background
## This empty frame darkens the main menu.
frame:
style "main_menu_frame"
## The use statement includes another screen inside this one. The actual
## contents of the main menu are in the navigation screen.
use navigation
if gui.show_name:
vbox:
style "main_menu_vbox"
text "[config.name!t]":
style "main_menu_title"
text "[config.version]":
style "main_menu_version"
style main_menu_frame is empty
style main_menu_vbox is vbox
style main_menu_text is gui_text
style main_menu_title is main_menu_text
style main_menu_version is main_menu_text
style main_menu_frame:
xsize 420
yfill True
background "gui/overlay/main_menu.png"
style main_menu_vbox:
xalign 1.0
xoffset -30
xmaximum 1200
yalign 1.0
yoffset -30
style main_menu_text:
properties gui.text_properties("main_menu", accent=True)
style main_menu_title:
properties gui.text_properties("title")
style main_menu_version:
properties gui.text_properties("version")
## Game Menu screen ############################################################
##
## This lays out the basic common structure of a game menu screen. It's called
## with the screen title, and displays the background, title, and navigation.
##
## The scroll parameter can be None, or one of "viewport" or "vpgrid".
## This screen is intended to be used with one or more children, which are
## transcluded (placed) inside it.
screen game_menu(title, scroll=None, yinitial=0.0, spacing=0):
style_prefix "game_menu"
if main_menu:
add gui.main_menu_background
else:
add gui.game_menu_background
frame:
style "game_menu_outer_frame"
hbox:
## Reserve space for the navigation section.
frame:
style "game_menu_navigation_frame"
frame:
style "game_menu_content_frame"
if scroll == "viewport":
viewport:
yinitial yinitial
scrollbars "vertical"
mousewheel True
draggable True
pagekeys True
side_yfill True
vbox:
spacing spacing
transclude
elif scroll == "vpgrid":
vpgrid:
cols 1
yinitial yinitial
scrollbars "vertical"
mousewheel True
draggable True
pagekeys True
side_yfill True
spacing spacing
transclude
else:
transclude
use navigation
textbutton _("Return"):
style "return_button"
action Return()
label title
if main_menu:
key "game_menu" action ShowMenu("main_menu")
style game_menu_outer_frame is empty
style game_menu_navigation_frame is empty
style game_menu_content_frame is empty
style game_menu_viewport is gui_viewport
style game_menu_side is gui_side
style game_menu_scrollbar is gui_vscrollbar
style game_menu_label is gui_label
style game_menu_label_text is gui_label_text
style return_button is navigation_button
style return_button_text is navigation_button_text
style game_menu_outer_frame:
bottom_padding 45
top_padding 180
background "gui/overlay/game_menu.png"
style game_menu_navigation_frame:
xsize 420
yfill True
style game_menu_content_frame:
left_margin 60
right_margin 30
top_margin 15
style game_menu_viewport:
xsize 1380
style game_menu_vscrollbar:
unscrollable gui.unscrollable
style game_menu_side:
spacing 15
style game_menu_label:
xpos 75
ysize 180
style game_menu_label_text:
size gui.title_text_size
color gui.accent_color
yalign 0.5
style return_button:
xpos gui.navigation_xpos
yalign 1.0
yoffset -45
## About screen ################################################################
##
## This screen gives credit and copyright information about the game and Ren'Py.
##
## There's nothing special about this screen, and hence it also serves as an
## example of how to make a custom screen.
screen about():
tag menu
## This use statement includes the game_menu screen inside this one. The
## vbox child is then included inside the viewport inside the game_menu
## screen.
use game_menu(_("About"), scroll="viewport"):
style_prefix "about"
vbox:
label "[config.name!t]"
text _("Version [config.version!t]\n")
## gui.about is usually set in options.rpy.
if gui.about:
text "[gui.about!t]\n"
text _("Made with {a=https://www.renpy.org/}Ren'Py{/a} [renpy.version_only].\n\n[renpy.license!t]")
style about_label is gui_label
style about_label_text is gui_label_text
style about_text is gui_text
style about_label_text:
size gui.label_text_size
## Load and Save screens #######################################################
##
## These screens are responsible for letting the player save the game and load
## it again. Since they share nearly everything in common, both are implemented
## in terms of a third screen, file_slots.
##
## https://www.renpy.org/doc/html/screen_special.html#save https://
## www.renpy.org/doc/html/screen_special.html#load
screen save():
tag menu
use file_slots(_("Save"))
screen load():
tag menu
use file_slots(_("Load"))
screen file_slots(title):
default page_name_value = FilePageNameInputValue(pattern=_("Page {}"), auto=_("Automatic saves"), quick=_("Quick saves"))
use game_menu(title):
fixed:
## This ensures the input will get the enter event before any of the
## buttons do.
order_reverse True
## The page name, which can be edited by clicking on a button.
button:
style "page_label"
key_events True
xalign 0.5
action page_name_value.Toggle()
input:
style "page_label_text"
value page_name_value
## The grid of file slots.
grid gui.file_slot_cols gui.file_slot_rows:
style_prefix "slot"
xalign 0.5
yalign 0.5
spacing gui.slot_spacing
for i in range(gui.file_slot_cols * gui.file_slot_rows):
$ slot = i + 1
button:
action FileAction(slot)
has vbox
add FileScreenshot(slot) xalign 0.5
text FileTime(slot, format=_("{#file_time}%A, %B %d %Y, %H:%M"), empty=_("empty slot")):
style "slot_time_text"
text FileSaveName(slot):
style "slot_name_text"
key "save_delete" action FileDelete(slot)
## Buttons to access other pages.
vbox:
style_prefix "page"
xalign 0.5
yalign 1.0
hbox:
xalign 0.5
spacing gui.page_spacing
textbutton _("<") action FilePagePrevious()
key "save_page_prev" action FilePagePrevious()
if config.has_autosave:
textbutton _("{#auto_page}A") action FilePage("auto")
if config.has_quicksave:
textbutton _("{#quick_page}Q") action FilePage("quick")
## range(1, 10) gives the numbers from 1 to 9.
for page in range(1, 10):
textbutton "[page]" action FilePage(page)
textbutton _(">") action FilePageNext()
key "save_page_next" action FilePageNext()
if config.has_sync:
if CurrentScreenName() == "save":
textbutton _("Upload Sync"):
action UploadSync()
xalign 0.5
else:
textbutton _("Download Sync"):
action DownloadSync()
xalign 0.5
style page_label is gui_label
style page_label_text is gui_label_text
style page_button is gui_button
style page_button_text is gui_button_text
style slot_button is gui_button
style slot_button_text is gui_button_text
style slot_time_text is slot_button_text
style slot_name_text is slot_button_text
style page_label:
xpadding 75
ypadding 5
style page_label_text:
textalign 0.5
layout "subtitle"
hover_color gui.hover_color
style page_button:
properties gui.button_properties("page_button")
style page_button_text:
properties gui.text_properties("page_button")
style slot_button:
properties gui.button_properties("slot_button")
style slot_button_text:
properties gui.text_properties("slot_button")
## Preferences screen ##########################################################
##
## The preferences screen allows the player to configure the game to better suit
## themselves.
##
## https://www.renpy.org/doc/html/screen_special.html#preferences
screen preferences():
tag menu
use game_menu(_("Preferences"), scroll="viewport"):
vbox:
hbox:
box_wrap True
if renpy.variant("pc") or renpy.variant("web"):
vbox:
style_prefix "radio"
label _("Display")
textbutton _("Window") action Preference("display", "window")
textbutton _("Fullscreen") action Preference("display", "fullscreen")
vbox:
style_prefix "check"
label _("Skip")
textbutton _("Unseen Text") action Preference("skip", "toggle")
textbutton _("After Choices") action Preference("after choices", "toggle")
textbutton _("Transitions") action InvertSelected(Preference("transitions", "toggle"))
## Additional vboxes of type "radio_pref" or "check_pref" can be
## added here, to add additional creator-defined preferences.
null height (4 * gui.pref_spacing)
hbox:
style_prefix "slider"
box_wrap True
vbox:
label _("Text Speed")
bar value Preference("text speed")
label _("Auto-Forward Time")
bar value Preference("auto-forward time")
vbox:
if config.has_music:
label _("Music Volume")
hbox:
bar value Preference("music volume")
if config.has_sound:
label _("Sound Volume")
hbox:
bar value Preference("sound volume")
if config.sample_sound:
textbutton _("Test") action Play("sound", config.sample_sound)
if config.has_voice:
label _("Voice Volume")
hbox:
bar value Preference("voice volume")
if config.sample_voice:
textbutton _("Test") action Play("voice", config.sample_voice)
if config.has_music or config.has_sound or config.has_voice:
null height gui.pref_spacing
textbutton _("Mute All"):
action Preference("all mute", "toggle")
style "mute_all_button"
style pref_label is gui_label
style pref_label_text is gui_label_text
style pref_vbox is vbox
style radio_label is pref_label
style radio_label_text is pref_label_text
style radio_button is gui_button
style radio_button_text is gui_button_text
style radio_vbox is pref_vbox
style check_label is pref_label
style check_label_text is pref_label_text
style check_button is gui_button
style check_button_text is gui_button_text
style check_vbox is pref_vbox
style slider_label is pref_label
style slider_label_text is pref_label_text
style slider_slider is gui_slider
style slider_button is gui_button
style slider_button_text is gui_button_text
style slider_pref_vbox is pref_vbox
style mute_all_button is check_button
style mute_all_button_text is check_button_text
style pref_label:
top_margin gui.pref_spacing
bottom_margin 3
style pref_label_text:
yalign 1.0
style pref_vbox:
xsize 338
style radio_vbox:
spacing gui.pref_button_spacing
style radio_button:
properties gui.button_properties("radio_button")
foreground "gui/button/radio_[prefix_]foreground.png"
style radio_button_text:
properties gui.text_properties("radio_button")
style check_vbox:
spacing gui.pref_button_spacing
style check_button:
properties gui.button_properties("check_button")
foreground "gui/button/check_[prefix_]foreground.png"
style check_button_text:
properties gui.text_properties("check_button")
style slider_slider:
xsize 525
style slider_button:
properties gui.button_properties("slider_button")
yalign 0.5
left_margin 15
style slider_button_text:
properties gui.text_properties("slider_button")
style slider_vbox:
xsize 675
## History screen ##############################################################
##
## This is a screen that displays the dialogue history to the player. While
## there isn't anything special about this screen, it does have to access the
## dialogue history stored in _history_list.
##
## https://www.renpy.org/doc/html/history.html
screen history():
tag menu
## Avoid predicting this screen, as it can be very large.
predict False
use game_menu(_("History"), scroll=("vpgrid" if gui.history_height else "viewport"), yinitial=1.0, spacing=gui.history_spacing):
style_prefix "history"
for h in _history_list:
window:
## This lays things out properly if history_height is None.
has fixed:
yfit True
if h.who:
label h.who:
style "history_name"
substitute False
## Take the color of the who text from the Character, if
## set.
if "color" in h.who_args:
text_color h.who_args["color"]
$ what = renpy.filter_text_tags(h.what, allow=gui.history_allow_tags)
text what:
substitute False
if not _history_list:
label _("The dialogue history is empty.")
## This determines what tags are allowed to be displayed on the history screen.
define gui.history_allow_tags = { "alt", "noalt", "rt", "rb", "art" }
style history_window is empty
style history_name is gui_label
style history_name_text is gui_label_text
style history_text is gui_text
style history_label is gui_label
style history_label_text is gui_label_text
style history_window:
xfill True
ysize gui.history_height
style history_name:
xpos gui.history_name_xpos
xanchor gui.history_name_xalign
ypos gui.history_name_ypos
xsize gui.history_name_width
style history_name_text:
min_width gui.history_name_width
textalign gui.history_name_xalign
style history_text:
xpos gui.history_text_xpos
ypos gui.history_text_ypos
xanchor gui.history_text_xalign
xsize gui.history_text_width
min_width gui.history_text_width
textalign gui.history_text_xalign
layout ("subtitle" if gui.history_text_xalign else "tex")
style history_label:
xfill True
style history_label_text:
xalign 0.5
## Help screen #################################################################
##
## A screen that gives information about key and mouse bindings. It uses other
## screens (keyboard_help, mouse_help, and gamepad_help) to display the actual
## help.
screen help():
tag menu
default device = "keyboard"
use game_menu(_("Help"), scroll="viewport"):
style_prefix "help"
vbox:
spacing 23
hbox:
textbutton _("Keyboard") action SetScreenVariable("device", "keyboard")
textbutton _("Mouse") action SetScreenVariable("device", "mouse")
if GamepadExists():
textbutton _("Gamepad") action SetScreenVariable("device", "gamepad")
if device == "keyboard":
use keyboard_help
elif device == "mouse":
use mouse_help
elif device == "gamepad":
use gamepad_help
screen keyboard_help():
hbox:
label _("Enter")
text _("Advances dialogue and activates the interface.")
hbox:
label _("Space")
text _("Advances dialogue without selecting choices.")
hbox:
label _("Arrow Keys")
text _("Navigate the interface.")
hbox:
label _("Escape")
text _("Accesses the game menu.")
hbox:
label _("Ctrl")
text _("Skips dialogue while held down.")
hbox:
label _("Tab")
text _("Toggles dialogue skipping.")
hbox:
label _("Page Up")
text _("Rolls back to earlier dialogue.")
hbox:
label _("Page Down")
text _("Rolls forward to later dialogue.")
hbox:
label "H"
text _("Hides the user interface.")
hbox:
label "S"
text _("Takes a screenshot.")
hbox:
label "V"
text _("Toggles assistive {a=https://www.renpy.org/l/voicing}self-voicing{/a}.")
hbox:
label "Shift+A"
text _("Opens the accessibility menu.")
screen mouse_help():
hbox:
label _("Left Click")
text _("Advances dialogue and activates the interface.")
hbox:
label _("Middle Click")
text _("Hides the user interface.")
hbox:
label _("Right Click")
text _("Accesses the game menu.")
hbox:
label _("Mouse Wheel Up")
text _("Rolls back to earlier dialogue.")
hbox:
label _("Mouse Wheel Down")
text _("Rolls forward to later dialogue.")
screen gamepad_help():
hbox:
label _("Right Trigger\nA/Bottom Button")
text _("Advances dialogue and activates the interface.")
hbox:
label _("Left Trigger\nLeft Shoulder")
text _("Rolls back to earlier dialogue.")
hbox:
label _("Right Shoulder")
text _("Rolls forward to later dialogue.")
hbox:
label _("D-Pad, Sticks")
text _("Navigate the interface.")
hbox:
label _("Start, Guide, B/Right Button")
text _("Accesses the game menu.")
hbox:
label _("Y/Top Button")
text _("Hides the user interface.")
textbutton _("Calibrate") action GamepadCalibrate()
style help_button is gui_button
style help_button_text is gui_button_text
style help_label is gui_label
style help_label_text is gui_label_text
style help_text is gui_text
style help_button:
properties gui.button_properties("help_button")
xmargin 12
style help_button_text:
properties gui.text_properties("help_button")
style help_label:
xsize 375
right_padding 30
style help_label_text:
size gui.text_size
xalign 1.0
textalign 1.0
################################################################################
## Additional screens
################################################################################
## Confirm screen ##############################################################
##
## The confirm screen is called when Ren'Py wants to ask the player a yes or no
## question.
##
## https://www.renpy.org/doc/html/screen_special.html#confirm
screen confirm(message, yes_action, no_action):
## Ensure other screens do not get input while this screen is displayed.
modal True
zorder 200
style_prefix "confirm"
add "gui/overlay/confirm.png"
frame:
vbox:
xalign .5
yalign .5
spacing 45
label _(message):
style "confirm_prompt"
xalign 0.5
hbox:
xalign 0.5
spacing 150
textbutton _("Yes") action yes_action
textbutton _("No") action no_action
## Right-click and escape answer "no".
key "game_menu" action no_action
style confirm_frame is gui_frame
style confirm_prompt is gui_prompt
style confirm_prompt_text is gui_prompt_text
style confirm_button is gui_medium_button
style confirm_button_text is gui_medium_button_text
style confirm_frame:
background Frame([ "gui/confirm_frame.png", "gui/frame.png"], gui.confirm_frame_borders, tile=gui.frame_tile)
padding gui.confirm_frame_borders.padding
xalign .5
yalign .5
style confirm_prompt_text:
textalign 0.5
layout "subtitle"
style confirm_button:
properties gui.button_properties("confirm_button")
style confirm_button_text:
properties gui.text_properties("confirm_button")
## Skip indicator screen #######################################################
##
## The skip_indicator screen is displayed to indicate that skipping is in
## progress.
##
## https://www.renpy.org/doc/html/screen_special.html#skip-indicator
screen skip_indicator():
zorder 100
style_prefix "skip"
frame:
hbox:
spacing 9
text _("Skipping")
text "▸" at delayed_blink(0.0, 1.0) style "skip_triangle"
text "▸" at delayed_blink(0.2, 1.0) style "skip_triangle"
text "▸" at delayed_blink(0.4, 1.0) style "skip_triangle"
## This transform is used to blink the arrows one after another.
transform delayed_blink(delay, cycle):
alpha .5
pause delay
block:
linear .2 alpha 1.0
pause .2
linear .2 alpha 0.5
pause (cycle - .4)
repeat
style skip_frame is empty
style skip_text is gui_text
style skip_triangle is skip_text
style skip_frame:
ypos gui.skip_ypos
background Frame("gui/skip.png", gui.skip_frame_borders, tile=gui.frame_tile)
padding gui.skip_frame_borders.padding
style skip_text:
size gui.notify_text_size
style skip_triangle:
## We have to use a font that has the BLACK RIGHT-POINTING SMALL TRIANGLE
## glyph in it.
font "DejaVuSans.ttf"
## Notify screen ###############################################################
##
## The notify screen is used to show the player a message. (For example, when
## the game is quicksaved or a screenshot has been taken.)
##
## https://www.renpy.org/doc/html/screen_special.html#notify-screen
screen notify(message):
zorder 100
style_prefix "notify"
frame at notify_appear:
text "[message!tq]"
timer 3.25 action Hide('notify')
transform notify_appear:
on show:
alpha 0
linear .25 alpha 1.0
on hide:
linear .5 alpha 0.0
style notify_frame is empty
style notify_text is gui_text
style notify_frame:
ypos gui.notify_ypos
background Frame("gui/notify.png", gui.notify_frame_borders, tile=gui.frame_tile)
padding gui.notify_frame_borders.padding
style notify_text:
properties gui.text_properties("notify")
## NVL screen ##################################################################
##
## This screen is used for NVL-mode dialogue and menus.
##
## https://www.renpy.org/doc/html/screen_special.html#nvl
screen nvl(dialogue, items=None):
window:
style "nvl_window"
has vbox:
spacing gui.nvl_spacing
## Displays dialogue in either a vpgrid or the vbox.
if gui.nvl_height:
vpgrid:
cols 1
yinitial 1.0
use nvl_dialogue(dialogue)
else:
use nvl_dialogue(dialogue)
## Displays the menu, if given. The menu may be displayed incorrectly if
## config.narrator_menu is set to True.
for i in items:
textbutton i.caption:
action i.action
style "nvl_button"
add SideImage() xalign 0.0 yalign 1.0
screen nvl_dialogue(dialogue):
for d in dialogue:
window:
id d.window_id
fixed:
yfit gui.nvl_height is None
if d.who is not None:
text d.who:
id d.who_id
text d.what:
id d.what_id
## This controls the maximum number of NVL-mode entries that can be displayed at
## once.
define config.nvl_list_length = gui.nvl_list_length
style nvl_window is default
style nvl_entry is default
style nvl_label is say_label
style nvl_dialogue is say_dialogue
style nvl_button is button
style nvl_button_text is button_text
style nvl_window:
xfill True
yfill True
background "gui/nvl.png"
padding gui.nvl_borders.padding
style nvl_entry:
xfill True
ysize gui.nvl_height
style nvl_label:
xpos gui.nvl_name_xpos
xanchor gui.nvl_name_xalign
ypos gui.nvl_name_ypos
yanchor 0.0
xsize gui.nvl_name_width
min_width gui.nvl_name_width
textalign gui.nvl_name_xalign
style nvl_dialogue:
xpos gui.nvl_text_xpos
xanchor gui.nvl_text_xalign
ypos gui.nvl_text_ypos
xsize gui.nvl_text_width
min_width gui.nvl_text_width
textalign gui.nvl_text_xalign
layout ("subtitle" if gui.nvl_text_xalign else "tex")
style nvl_thought:
xpos gui.nvl_thought_xpos
xanchor gui.nvl_thought_xalign
ypos gui.nvl_thought_ypos
xsize gui.nvl_thought_width
min_width gui.nvl_thought_width
textalign gui.nvl_thought_xalign
layout ("subtitle" if gui.nvl_text_xalign else "tex")
style nvl_button:
properties gui.button_properties("nvl_button")
xpos gui.nvl_button_xpos
xanchor gui.nvl_button_xalign
style nvl_button_text:
properties gui.text_properties("nvl_button")
## Bubble screen ###############################################################
##
## The bubble screen is used to display dialogue to the player when using speech
## bubbles. The bubble screen takes the same parameters as the say screen, must
## create a displayable with the id of "what", and can create displayables with
## the "namebox", "who", and "window" ids.
##
## https://www.renpy.org/doc/html/bubble.html#bubble-screen
screen bubble(who, what):
style_prefix "bubble"
window:
id "window"
if who is not None:
window:
id "namebox"
style "bubble_namebox"
text who:
id "who"
text what:
id "what"
style bubble_window is empty
style bubble_namebox is empty
style bubble_who is default
style bubble_what is default
style bubble_window:
xpadding 30
top_padding 5
bottom_padding 5
style bubble_namebox:
xalign 0.5
style bubble_who:
xalign 0.5
textalign 0.5
color "#000"
style bubble_what:
align (0.5, 0.5)
text_align 0.5
layout "subtitle"
color "#000"
define bubble.frame = Frame("gui/bubble.png", 55, 55, 55, 95)
define bubble.thoughtframe = Frame("gui/thoughtbubble.png", 55, 55, 55, 55)
define bubble.properties = {
"bottom_left" : {
"window_background" : Transform(bubble.frame, xzoom=1, yzoom=1),
"window_bottom_padding" : 27,
},
"bottom_right" : {
"window_background" : Transform(bubble.frame, xzoom=-1, yzoom=1),
"window_bottom_padding" : 27,
},
"top_left" : {
"window_background" : Transform(bubble.frame, xzoom=1, yzoom=-1),
"window_top_padding" : 27,
},
"top_right" : {
"window_background" : Transform(bubble.frame, xzoom=-1, yzoom=-1),
"window_top_padding" : 27,
},
"thought" : {
"window_background" : bubble.thoughtframe,
}
}
define bubble.expand_area = {
"bottom_left" : (0, 0, 0, 22),
"bottom_right" : (0, 0, 0, 22),
"top_left" : (0, 22, 0, 0),
"top_right" : (0, 22, 0, 0),
"thought" : (0, 0, 0, 0),
}
################################################################################
## Mobile Variants
################################################################################
style pref_vbox:
variant "medium"
xsize 675
## Since a mouse may not be present, we replace the quick menu with a version
## that uses fewer and bigger buttons that are easier to touch.
screen quick_menu():
variant "touch"
zorder 100
if quick_menu:
hbox:
style_prefix "quick"
xalign 0.5
yalign 1.0
textbutton _("Back") action Rollback()
textbutton _("Skip") action Skip() alternate Skip(fast=True, confirm=True)
textbutton _("Auto") action Preference("auto-forward", "toggle")
textbutton _("Menu") action ShowMenu()
style window:
variant "small"
background "gui/phone/textbox.png"
style radio_button:
variant "small"
foreground "gui/phone/button/radio_[prefix_]foreground.png"
style check_button:
variant "small"
foreground "gui/phone/button/check_[prefix_]foreground.png"
style nvl_window:
variant "small"
background "gui/phone/nvl.png"
style main_menu_frame:
variant "small"
background "gui/phone/overlay/main_menu.png"
style game_menu_outer_frame:
variant "small"
background "gui/phone/overlay/game_menu.png"
style game_menu_navigation_frame:
variant "small"
xsize 510
style game_menu_content_frame:
variant "small"
top_margin 0
style pref_vbox:
variant "small"
xsize 600
style bar:
variant "small"
ysize gui.bar_size
left_bar Frame("gui/phone/bar/left.png", gui.bar_borders, tile=gui.bar_tile)
right_bar Frame("gui/phone/bar/right.png", gui.bar_borders, tile=gui.bar_tile)
style vbar:
variant "small"
xsize gui.bar_size
top_bar Frame("gui/phone/bar/top.png", gui.vbar_borders, tile=gui.bar_tile)
bottom_bar Frame("gui/phone/bar/bottom.png", gui.vbar_borders, tile=gui.bar_tile)
style scrollbar:
variant "small"
ysize gui.scrollbar_size
base_bar Frame("gui/phone/scrollbar/horizontal_[prefix_]bar.png", gui.scrollbar_borders, tile=gui.scrollbar_tile)
thumb Frame("gui/phone/scrollbar/horizontal_[prefix_]thumb.png", gui.scrollbar_borders, tile=gui.scrollbar_tile)
style vscrollbar:
variant "small"
xsize gui.scrollbar_size
base_bar Frame("gui/phone/scrollbar/vertical_[prefix_]bar.png", gui.vscrollbar_borders, tile=gui.scrollbar_tile)
thumb Frame("gui/phone/scrollbar/vertical_[prefix_]thumb.png", gui.vscrollbar_borders, tile=gui.scrollbar_tile)
style slider:
variant "small"
ysize gui.slider_size
base_bar Frame("gui/phone/slider/horizontal_[prefix_]bar.png", gui.slider_borders, tile=gui.slider_tile)
thumb "gui/phone/slider/horizontal_[prefix_]thumb.png"
style vslider:
variant "small"
xsize gui.slider_size
base_bar Frame("gui/phone/slider/vertical_[prefix_]bar.png", gui.vslider_borders, tile=gui.slider_tile)
thumb "gui/phone/slider/vertical_[prefix_]thumb.png"
style slider_vbox:
variant "small"
xsize None
style slider_slider:
variant "small"
xsize 900
style alt_say_label is say_label
style alt_say_label:
color "#808080"
style alt_say_dialogue is say_dialogue
style alt_say_dialogue:
color "#000000"
screen affection_bartwo():
frame:
xalign 0.5
yalign 0.1
has vbox
text "Affection Level" xalign 0.5
bar value VariableValue("affection", 0, 100) style "affection_bartwo"
style affection_bar:
xmaximum 400
ymaximum 30
screen affection_bartwo():
frame:
style "affection_frame"
align ( 0.615, 0.8)
has vbox
text "Affection Level" xalign 0.5
# Show the custom heart overlay image above the bar
add "images/vertical_heart.png" xalign 0.5
# Vertical affection bar
bar value VariableValue("affection", 0, 100) style "affection_bar"
style affection_bar is bar:
xmaximum 30
ymaximum 300
style affection_frame is frame
style affection_frame:
padding (10, 10)
background None
Options Script
## This file contains options that can be changed to customize your game.
##
## Lines beginning with two '#' marks are comments, and you shouldn't uncomment
## them. Lines beginning with a single '#' mark are commented-out code, and you
## may want to uncomment them when appropriate.
## Basics ######################################################################
## A human-readable name of the game. This is used to set the default window
## title, and shows up in the interface and error reports.
##
## The _() surrounding the string marks it as eligible for translation.
define config.name = _("playtest 2")
define config.layers = [ 'master', 'transient', 'screens', 'over_screens', 'overlay' ]
## Determines if the title given above is shown on the main menu screen. Set
## this to False to hide the title.
define gui.show_name = True
## The version of the game.
define config.version = "1.0"
## Text that is placed on the game's about screen. Place the text between the
## triple-quotes, and leave a blank line between paragraphs.
define gui.about = _p("""
""")
## A short name for the game used for executables and directories in the built
## distribution. This must be ASCII-only, and must not contain spaces, colons,
## or semicolons.
define build.name = "playtest2"
## Sounds and music ############################################################
## These three variables control, among other things, which mixers are shown
## to the player by default. Setting one of these to False will hide the
## appropriate mixer.
define config.has_sound = True
define config.has_music = True
define config.has_voice = True
## To allow the user to play a test sound on the sound or voice channel,
## uncomment a line below and use it to set a sample sound to play.
# define config.sample_sound = "sample-sound.ogg"
# define config.sample_voice = "sample-voice.ogg"
## Uncomment the following line to set an audio file that will be played while
## the player is at the main menu. This file will continue playing into the
## game, until it is stopped or another file is played.
# define config.main_menu_music = "main-menu-theme.ogg"
## Transitions #################################################################
##
## These variables set transitions that are used when certain events occur.
## Each variable should be set to a transition, or None to indicate that no
## transition should be used.
## Entering or exiting the game menu.
define config.enter_transition = dissolve
define config.exit_transition = dissolve
## Between screens of the game menu.
define config.intra_transition = dissolve
## A transition that is used after a game has been loaded.
define config.after_load_transition = None
## Used when entering the main menu after the game has ended.
define config.end_game_transition = None
## A variable to set the transition used when the game starts does not exist.
## Instead, use a with statement after showing the initial scene.
## Window management ###########################################################
##
## This controls when the dialogue window is displayed. If "show", it is always
## displayed. If "hide", it is only displayed when dialogue is present. If
## "auto", the window is hidden before scene statements and shown again once
## dialogue is displayed.
##
## After the game has started, this can be changed with the "window show",
## "window hide", and "window auto" statements.
define config.window = "auto"
## Transitions used to show and hide the dialogue window
define config.window_show_transition = Dissolve(.2)
define config.window_hide_transition = Dissolve(.2)
## Preference defaults #########################################################
## Controls the default text speed. The default, 0, is infinite, while any other
## number is the number of characters per second to type out.
default preferences.text_cps = 0
## The default auto-forward delay. Larger numbers lead to longer waits, with 0
## to 30 being the valid range.
default preferences.afm_time = 15
## Save directory ##############################################################
##
## Controls the platform-specific place Ren'Py will place the save files for
## this game. The save files will be placed in:
##
## Windows: %APPDATA\RenPy\<config.save_directory>
##
## Macintosh: $HOME/Library/RenPy/<config.save_directory>
##
## Linux: $HOME/.renpy/<config.save_directory>
##
## This generally should not be changed, and if it is, should always be a
## literal string, not an expression.
define config.save_directory = "playtest2-1743073636"
## Icon ########################################################################
##
## The icon displayed on the taskbar or dock.
define config.window_icon = "gui/window_icon.png"
## Build configuration #########################################################
##
## This section controls how Ren'Py turns your project into distribution files.
init python:
## The following functions take file patterns. File patterns are case-
## insensitive, and matched against the path relative to the base directory,
## with and without a leading /. If multiple patterns match, the first is
## used.
##
## In a pattern:
##
## / is the directory separator.
##
## * matches all characters, except the directory separator.
##
## ** matches all characters, including the directory separator.
##
## For example, "*.txt" matches txt files in the base directory, "game/
## **.ogg" matches ogg files in the game directory or any of its
## subdirectories, and "**.psd" matches psd files anywhere in the project.
## Classify files as None to exclude them from the built distributions.
build.classify('**~', None)
build.classify('**.bak', None)
build.classify('**/.**', None)
build.classify('**/#**', None)
build.classify('**/thumbs.db', None)
## To archive files, classify them as 'archive'.
# build.classify('game/**.png', 'archive')
# build.classify('game/**.jpg', 'archive')
## Files matching documentation patterns are duplicated in a mac app build,
## so they appear in both the app and the zip file.
build.documentation('*.html')
build.documentation('*.txt')
## A Google Play license key is required to perform in-app purchases. It can be
## found in the Google Play developer console, under "Monetize" > "Monetization
## Setup" > "Licensing".
# define build.google_play_key = "..."
## The username and project name associated with an itch.io project, separated
## by a slash.
# define build.itch_project = "renpytom/test-project"