Complete lyra game
This commit is contained in:
parent
6ef7becac7
commit
7a473693b8
|
@ -1,353 +0,0 @@
|
|||
"""
|
||||
ATL Text Tags Ren'Py Module
|
||||
2021 Daniel Westfall <SoDaRa2595@gmail.com>
|
||||
|
||||
http://twitter.com/sodara9
|
||||
I'd appreciate being given credit if you do end up using it! :D Would really
|
||||
make my day to know I helped some people out!
|
||||
Really hope this can help the community create some really neat ways to spice
|
||||
up their dialogue!
|
||||
http://opensource.org/licenses/mit-license.php
|
||||
Forum Post: https://lemmasoft.renai.us/forums/viewtopic.php?f=51&t=60527&sid=75b4eb1aa5212a33cbfe9b0354e5376b
|
||||
Github: https://github.com/SoDaRa/Kinetic-Text-Tags
|
||||
itch.io: https://wattson.itch.io/kinetic-text-tags
|
||||
"""
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
# General Notes:
|
||||
# I have not tested every transform property and such some may not work as indended
|
||||
# Most common ones work fine such as pos and offset.
|
||||
# I can't imagine this being an issue for most of them. However I imagine that
|
||||
# anchor, xanchor, yanchor, fit and events may not have the indended effect.
|
||||
|
||||
# Tranforms used for ATLText must take up time if they repeat
|
||||
# The following will cause an error:
|
||||
# transform random_pos(range):
|
||||
# xpos (random.random() * range)
|
||||
# ypos (random.random() * range)
|
||||
# # If there were a pause 0.01 here, it'd be fine. w/o it, renpy flags this as an infinite loop.
|
||||
# repeat
|
||||
|
||||
# Sadly, repeating a section a limited number of times does not work.
|
||||
# As an example:
|
||||
# transform text_rotate_3d(time=1.5):
|
||||
# matrixanchor (0.5,0.5)
|
||||
# matrixtransform RotateMatrix(0,0,0) * OffsetMatrix(0,0,100)
|
||||
# linear time matrixtransform RotateMatrix(180,0,180) * OffsetMatrix(0,0,100)
|
||||
# linear time matrixtransform RotateMatrix(360,0,360) * OffsetMatrix(0,0,100)
|
||||
# matrixtransform RotateMatrix(0,0,0) * OffsetMatrix(0,0,100)
|
||||
# repeat 3
|
||||
# matrixtransform RotateMatrix(0,0,0) * OffsetMatrix(0,0,100)
|
||||
# linear time matrixtransform RotateMatrix(180,0,180) * OffsetMatrix(0,0,50)
|
||||
# linear time matrixtransform RotateMatrix(360,0,360) * OffsetMatrix(0,0,0)
|
||||
# The 'repeat 3' will be skipped and instead just fall through into the next section.
|
||||
# Thus, repeated sections must be included manually. Which sucks but idk a way
|
||||
# around it right now.
|
||||
# Thankfully, infinite repeats work without issue.
|
||||
|
||||
# Using matrixtransform and zpos is possible. However, standard text is applied on
|
||||
# the screens layer. Using:
|
||||
# camera screens:
|
||||
# perspective True
|
||||
# Will enable that layer to use the 3D stage.
|
||||
# HOWEVER!!!
|
||||
# Doing so will prevent the user from being able to interact with any buttons
|
||||
# on that layer. Therefore, it is advised that if you want to use the 3D stage
|
||||
# for text transforms, you have it be handled on a layer.
|
||||
# Below is an example of how to implement this.
|
||||
|
||||
# While making this I frequently had the source code up for things
|
||||
# Relevant bits to look over were:
|
||||
# defaultstore.rpy for how At() works
|
||||
# display/motion.py for how various kinda of movement are handled
|
||||
# display/transform.py for the TransformState, Tranform and ATLTransform classes
|
||||
# atl.py for ATLTransformBase class, which handles a lot of functions for ATLTransform
|
||||
# display/accelerator.pyx for how Tranform handles rendering.
|
||||
transform bounce:
|
||||
ease 0.5 yoffset 10 matrixcolor TintMatrix("#f00")
|
||||
ease 0.5 yoffset -10 matrixcolor TintMatrix("#00f")
|
||||
repeat
|
||||
transform bounce_text(yoff):
|
||||
ease 0.5 ypos yoff
|
||||
ease 0.5 ypos -yoff
|
||||
repeat
|
||||
transform rotate_text(speed):
|
||||
linear speed rotate 180
|
||||
linear speed rotate 360
|
||||
rotate 0
|
||||
repeat
|
||||
transform drop_text(letter, time):
|
||||
contains:
|
||||
letter
|
||||
contains:
|
||||
letter
|
||||
yoffset 0 alpha 1
|
||||
easeout_circ time yoffset 50 alpha 0
|
||||
letter
|
||||
repeat
|
||||
transform fade_in_text(time=0.5, distance=20):
|
||||
alpha 0 xoffset distance
|
||||
ease time alpha 1 xoffset 0
|
||||
|
||||
# Doing the following will help with using 3D stage transforms on say screen text
|
||||
# Defining the new layer below the screens layer to allow it to go behind anything on the screens layer
|
||||
# define config.layers = [ 'master', 'transient', 'threeD_text', 'screens', 'overlay' ]
|
||||
# Tell the character to use our new layer to display the screen.
|
||||
# define e_3d = Character("Eileen3D", show_layer="threeD_text")
|
||||
# And before using the character, be sure to do:
|
||||
# camera threeD_text:
|
||||
# perspective True
|
||||
# And the 3D stage things should work.
|
||||
# You can also make this layer the default for showing the say screen by doing.
|
||||
# define config.say_layer = "threeD_text"
|
||||
# Also remember you can override elements of a character for a line, such as with:
|
||||
# "Here's a narration line with an override to {atl=-0.1, text_rotate_3d}allow for 3D Text.{/atl}" (show_layer="threeD_text")
|
||||
transform text_rotate_3d(time=1.5):
|
||||
matrixanchor (0.5,0.5)
|
||||
matrixtransform RotateMatrix(0,0,0) * OffsetMatrix(0,0,100)
|
||||
linear time matrixtransform RotateMatrix(180,0,0) * OffsetMatrix(0,0,100)
|
||||
linear time matrixtransform RotateMatrix(360,0,0) * OffsetMatrix(0,0,100)
|
||||
matrixtransform RotateMatrix(0,0,0) * OffsetMatrix(0,0,100)
|
||||
repeat
|
||||
|
||||
init python:
|
||||
class ATLText(renpy.Displayable):
|
||||
def __init__(self, child, transforms, offset=0, hold=False,**kwargs):
|
||||
super(ATLText, self).__init__(**kwargs)
|
||||
self.child = At(child, *transforms)
|
||||
self.offset = offset
|
||||
self.hold = hold
|
||||
# If your ATL uses 2+ contains for a character to be used twice, then
|
||||
# a fixed is made to contain them. During rendering, this can lead
|
||||
# to a render that is far larger than the actual character's render.
|
||||
# To combat this, I'm having it check the original Text's render size
|
||||
# so we can use that instead. This shouldn't have many consequences,
|
||||
# but if you observe something weird, maybe try removing the below and
|
||||
# using the child render's size in the render function
|
||||
child_render = renpy.render(child, 0, 0, 0, 0)
|
||||
self.width, self.height = child_render.get_size()
|
||||
# Because of how renpy handles transforms on screens in 7.4.7, we
|
||||
# have to update the internals of the transform to get the appropriate
|
||||
# time on it. Otherwise our offset won't have the correct effect.
|
||||
# If you're using Renpy 7.4.6 or below and this causes issues, you
|
||||
# can remove this bit.
|
||||
if config.atl_start_on_show:
|
||||
renpy.render(self.child, 0, 0, 0, 0)
|
||||
|
||||
def render(self, width, height, st, at):
|
||||
# Apply the time offset.
|
||||
st = st + self.offset
|
||||
at = at + self.offset
|
||||
if self.hold:
|
||||
st = max(st, 0)
|
||||
at = max(at, 0)
|
||||
|
||||
# Get child render and our output render
|
||||
child_render = renpy.render(self.child, width, height, st, at)
|
||||
# self.width, self.height = child_render.get_size()
|
||||
render = renpy.Render(self.width, self.height)
|
||||
|
||||
# Next section is to figure out the offset applied to the blit
|
||||
# Get_Placement returns a tuple containing:
|
||||
# xpos, ypos, xanchor, yanchor, xoffset, yoffset, subpixel
|
||||
child_pos = self.child.state.get_placement()
|
||||
# Sometimes the output of get_placement has some None values in there.
|
||||
# So use this to get safe output.
|
||||
def none_to_float(param):
|
||||
if param is None:
|
||||
return 0.0
|
||||
return param
|
||||
child_xpos = none_to_float(child_pos[0]) + none_to_float(child_pos[4])
|
||||
child_ypos = none_to_float(child_pos[1]) + none_to_float(child_pos[5])
|
||||
|
||||
render.blit(child_render, (child_xpos,child_ypos))
|
||||
renpy.redraw(self, 0)
|
||||
return render
|
||||
|
||||
def visit(self):
|
||||
return [ self.child ]
|
||||
|
||||
# Allows one to use one or more ATL transforms to define a movement for text.
|
||||
# Arguments are separated by ',' and transform parameters are separated by '~'
|
||||
# The offset and hold arguments are optional.
|
||||
# Arguments:
|
||||
# offset: (float/'#'/'-#') The time offset between two characters (in seconds).
|
||||
# If #, then it use's the user's cps setting as the offset
|
||||
# If -#, does the above but treats it as negative.
|
||||
# See Notes for details on negative offsets
|
||||
# hold: ('#') Tells the displayable to hold the value at 0 if time is negative.
|
||||
# Is ignored if offset is positive.
|
||||
# See Notes on negative offsets for more details.
|
||||
# transform_name: (string) The name of a defined transform.
|
||||
# Will throw an error if doesn't exist
|
||||
# param: (float/string/'#') A parameter for the transform. Must be ordered by position.
|
||||
# All numbers will be interpreted as floats. Strings should evaluate to a displayable, a global variable OR
|
||||
# optionally, can be left as '#' in order to use the current character as a displayable parameter.
|
||||
# (No current support for keyword args)
|
||||
# Notes:
|
||||
# - Transforms are applied using an At() displayable and are added in the same order.
|
||||
#
|
||||
# - If a negative offset is supplied, we have to be careful of what time
|
||||
# we supply to the ATL's render function. If we give it a negtive number, it
|
||||
# will treat that value as it's new 0 seconds. So if we feed it -2 seconds
|
||||
# to start, then when it reaches -1.8 seconds, it'll treat that as 0.2 seconds.
|
||||
# This has the effect of syncronizing every letter, which isn't what we want.
|
||||
#
|
||||
# - To combat this, if a negative offset is given I instead push the first
|
||||
# letter forward in time. That way each subsequent character can approach
|
||||
# zero with the negative offset.
|
||||
# So, for example, if we have 6 characters and the offset is to be -0.2 seconds,
|
||||
# then the 1st character will start at 1.0 seconds, 2nd will start at 0.8,
|
||||
# and so on until the 6th character starts at 0 seconds.
|
||||
#
|
||||
# - However, this may not always be the ideal setup for all transforms,
|
||||
# such as fades. An alternative is then to hold the time at 0 until it becomes
|
||||
# positive. Which is what the 'hold' argument applies.
|
||||
# Re-using the example from before, every character starts at 0 seconds,
|
||||
# The 1st character will start to move immediately, but the 2nd character
|
||||
# will wait 0.2 seconds before starting. The 3rd waits 0.4, 4th waits 0.6,
|
||||
# until the 6th character waits 1.0 seconds before starting.
|
||||
#
|
||||
# Examples:
|
||||
# {atl=[offset],[hold],[transform_name]~[param]~...),...}Text{/atl}
|
||||
# {atl=0.1, rotate_text~0.5, bounce_text~10}Text{/atl}
|
||||
# {atl=drop_text~#~0.5}Text{/atl}
|
||||
# {atl=-#,#,fade_in_text~1.0~-100}Text{/atl}
|
||||
def atl_tag(tag, argument, contents):
|
||||
new_list = []
|
||||
# Split the argument into a list of transforms and their parameters
|
||||
arg_list = argument.split(',')
|
||||
atl_list = []
|
||||
time_offset = 0
|
||||
hold = False
|
||||
# Check for an offset
|
||||
# See if we want to use the current cps settings
|
||||
if arg_list[0] == "#" or arg_list[0] == "-#":
|
||||
if preferences.text_cps is not 0:
|
||||
time_offset = (1.0 / preferences.text_cps)
|
||||
if arg_list[0] == "-#":
|
||||
time_offset = time_offset * -1.0
|
||||
arg_list.pop(0)
|
||||
# Attempt checking if the first parameter is a float.
|
||||
else:
|
||||
try:
|
||||
time_offset = float(arg_list[0])
|
||||
arg_list.pop(0)
|
||||
except:
|
||||
time_offset = 0
|
||||
if arg_list[0] == "#":
|
||||
hold = True
|
||||
arg_list.pop(0)
|
||||
# Go through the arguments for transforms.
|
||||
# Returns False if it finds a "#" in the params without text set
|
||||
# Otherwise returns a list of transforms
|
||||
def arg_handler(arg_list, text=None):
|
||||
return_list = []
|
||||
for arg in arg_list:
|
||||
if '~' in arg:
|
||||
txt_param_list = arg.split('~')
|
||||
arg = txt_param_list[0].strip()
|
||||
# Remove the name of the transform from the parameters list
|
||||
txt_param_list.pop(0)
|
||||
param_list = []
|
||||
for i in range(len(txt_param_list)):
|
||||
param = None
|
||||
txt_param_list[i] = txt_param_list[i].strip()
|
||||
# If a #, then we'll have to do some special stuff later
|
||||
if txt_param_list[i] == "#":
|
||||
if text == None: # If we weren't supplied a way to handle this, return
|
||||
return False
|
||||
param_list.append(text)
|
||||
continue
|
||||
# Attempt a float
|
||||
try:
|
||||
param = float(txt_param_list[i])
|
||||
except ValueError:
|
||||
param = None
|
||||
# Attempt a global variable
|
||||
if param == None and txt_param_list[i] in globals():
|
||||
param = globals()[txt_param_list[i]]
|
||||
# Attempt a displayable
|
||||
elif param == None:
|
||||
param = renpy.displayable(txt_param_list[i])
|
||||
param_list.append(param)
|
||||
return_list.append(globals()[arg](*param_list))
|
||||
else:
|
||||
arg = arg.strip()
|
||||
return_list.append(globals()[arg])
|
||||
return return_list
|
||||
|
||||
# Setup char_index
|
||||
char_index = 0
|
||||
count_back = False # Used to know if we count forwards or backwards
|
||||
# If offset is negative and we aren't holding time at zero, count
|
||||
# the number of characters so char_index can count down to 0.
|
||||
if time_offset < 0 and not hold:
|
||||
for kind,text in contents:
|
||||
if kind == renpy.TEXT_TEXT:
|
||||
char_index += len(text)
|
||||
# Handles adding images into text. Remove if you don't want this behavior
|
||||
elif kind == renpy.TEXT_TAG:
|
||||
if text.find("image") != -1:
|
||||
char_index += 1
|
||||
time_offset = time_offset * -1.0
|
||||
count_back = True
|
||||
atl_list = arg_handler(arg_list) # Attempt to get a list of atl functions
|
||||
# Usual kinetic-text-tag text handling
|
||||
my_style = DispTextStyle()
|
||||
for kind,text in contents:
|
||||
if kind == renpy.TEXT_TEXT:
|
||||
for char in text:
|
||||
char_text = Text(my_style.apply_style(char))
|
||||
if atl_list == False:
|
||||
# If we got a false earlier, then we know we want to call
|
||||
# one of the transforms with the text character as a parameter
|
||||
# so we generate the atl_list necessary for each character.
|
||||
new_atl_list = arg_handler(arg_list, char_text)
|
||||
char_disp = ATLText(char_text, new_atl_list, char_index * time_offset, hold)
|
||||
else:
|
||||
char_disp = ATLText(char_text, atl_list, char_index * time_offset, hold)
|
||||
new_list.append((renpy.TEXT_DISPLAYABLE, char_disp))
|
||||
if count_back:
|
||||
char_index -= 1
|
||||
else:
|
||||
char_index += 1
|
||||
elif kind == renpy.TEXT_TAG:
|
||||
# Handles adding images into text. Remove if you don't want this behavior
|
||||
if text.find("image") != -1:
|
||||
tag, _, value = text.partition("=")
|
||||
my_img = renpy.displayable(value)
|
||||
if atl_list == False:
|
||||
new_atl_list = arg_handler(arg_list, my_img)
|
||||
img_disp = ATLText(my_img, new_atl_list, char_index * time_offset, hold)
|
||||
else:
|
||||
img_disp = ATLText(my_img, atl_list, char_index * time_offset, hold)
|
||||
new_list.append((renpy.TEXT_DISPLAYABLE, img_disp))
|
||||
if count_back:
|
||||
char_index -= 1
|
||||
else:
|
||||
char_index += 1
|
||||
elif not my_style.add_tags(text):
|
||||
new_list.append((kind, text))
|
||||
else:
|
||||
new_list.append((kind,text))
|
||||
return new_list
|
||||
|
||||
config.custom_text_tags["atl"] = atl_tag
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 56 KiB |
Binary file not shown.
After Width: | Height: | Size: 523 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.7 MiB After Width: | Height: | Size: 1.6 MiB |
|
@ -1,841 +0,0 @@
|
|||
"""
|
||||
Kinetic Text Tags Ren'Py Module
|
||||
2021 Daniel Westfall <SoDaRa2595@gmail.com>
|
||||
|
||||
http://twitter.com/sodara9
|
||||
I'd appreciate being given credit if you do end up using it! :D Would really
|
||||
make my day to know I helped some people out!
|
||||
Really hope this can help the community create some really neat ways to spice
|
||||
up their dialogue!
|
||||
http://opensource.org/licenses/mit-license.php
|
||||
Github: https://github.com/SoDaRa/Kinetic-Text-Tags
|
||||
itch.io: https://wattson.itch.io/kinetic-text-tags
|
||||
Forum Post: https://lemmasoft.renai.us/forums/viewtopic.php?f=51&t=60527&sid=75b4eb1aa5212a33cbfe9b0354e5376b
|
||||
"""
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
### UPDATE ###
|
||||
# With the new ATL text tag, a handful of effects I've made have become redundant.
|
||||
# Namely the bounce (bt), fadein (fi) and rotation (rotat) effects.
|
||||
# However, I'll leave them in here for posterity and in case someone would like
|
||||
# to reuse some of the code for whatever purpose.
|
||||
# Plus the bounce and fadein may be faster to type for some. And I'd probably
|
||||
# break some code if I did. Though feel free to remove them if you find them
|
||||
# to be clutter.
|
||||
|
||||
##### Our preference to disable the chaos text #####
|
||||
default preferences.chaos_on = False # You can change this to be gui.chaos_text or persistent.chaos_text if you'd prefer.
|
||||
|
||||
init python:
|
||||
import random
|
||||
import math
|
||||
|
||||
# This will maintain what styles we want to apply and help us apply them
|
||||
class DispTextStyle():
|
||||
# Notes:
|
||||
# - "" denotes a style tag. Since it's usually {=user_style} and we partition
|
||||
# it over the '=', it ends up being an empty string
|
||||
# - If you want to add your own tags to the list, I recommend adding them
|
||||
# before the ""
|
||||
# - Self-closing tags should not be added here and should be handled
|
||||
# in the text tag function.
|
||||
custom_tags = ["omega", "bt", "fi", "sc", "rotat", "chaos", "move"]
|
||||
accepted_tags = ["", "b", "s", "u", "i", "color", "alpha", "font", "size", "outlinecolor", "plain", 'cps']
|
||||
custom_cancel_tags = ["/" + tag for tag in custom_tags]
|
||||
cancel_tags = ["/" + tag for tag in accepted_tags]
|
||||
def __init__(self):
|
||||
self.tags = {}
|
||||
|
||||
# For setting style properties. Returns false if it accepted none of the tags
|
||||
def add_tags(self, char):
|
||||
tag, _, value = char.partition("=") # Separate the tag and its info
|
||||
# Add tag to dictionary if we accept it
|
||||
if tag in self.accepted_tags or tag in self.custom_tags:
|
||||
if value == "":
|
||||
self.tags[tag] = True
|
||||
else:
|
||||
self.tags[tag] = value
|
||||
return True
|
||||
# Remove mark tag as cleared if should no longer apply it
|
||||
if tag in self.cancel_tags or tag in self.custom_cancel_tags:
|
||||
tag = tag.replace("/", "")
|
||||
self.tags.pop(tag)
|
||||
return True
|
||||
return False # If we got any other tag, tell the function to let it pass
|
||||
|
||||
# Applies all style properties to the string
|
||||
def apply_style(self, char):
|
||||
new_string = ""
|
||||
# Go through and apply all the tags
|
||||
new_string += self.start_tags()
|
||||
# Add the character in the middle
|
||||
new_string += char
|
||||
# Now close all the tags we opened
|
||||
new_string += self.end_tags()
|
||||
return new_string
|
||||
|
||||
# Spits out start tags. Primarily used for SwapText
|
||||
def start_tags(self):
|
||||
new_string = ""
|
||||
# Go through the custom tags
|
||||
for tag in self.custom_tags:
|
||||
if tag in self.tags:
|
||||
if self.tags[tag] == True:
|
||||
new_string += "{" + tag + "}"
|
||||
else:
|
||||
new_string += "{" + tag + "=" +self.tags[tag] + "}"
|
||||
# Go through the standard tags
|
||||
for tag in self.accepted_tags:
|
||||
if tag in self.tags:
|
||||
if self.tags[tag] == True:
|
||||
new_string += "{" + tag + "}"
|
||||
else:
|
||||
new_string += "{" + tag + "=" +self.tags[tag] + "}"
|
||||
return new_string
|
||||
|
||||
# Spits out ending tags. Primarily used for SwapText
|
||||
def end_tags(self):
|
||||
new_string = ""
|
||||
# The only tags we are required to end are any custom text tags.
|
||||
# And should also end them in the reverse order they were applied.
|
||||
reversed_cancels = [tag for tag in self.custom_cancel_tags]
|
||||
reversed_cancels.reverse()
|
||||
for tag in reversed_cancels:
|
||||
temp = tag.replace("/", "")
|
||||
if temp in self.tags:
|
||||
new_string += "{" + tag + "}"
|
||||
return new_string
|
||||
|
||||
|
||||
### TEXT WRAPPER CLASSES ###
|
||||
# Basic text displacement demonstration
|
||||
class BounceText(renpy.Displayable):
|
||||
def __init__(self, child, char_offset, amp=20, period=4.0, speed = 1.0, **kwargs):
|
||||
|
||||
# Pass additional properties on to the renpy.Displayable
|
||||
# constructor.
|
||||
super(BounceText, self).__init__(**kwargs) # REMEMBER TO RENAME HERE TO YOUR CLASS
|
||||
|
||||
# For all of my classes, I assume I am being passed a displayable
|
||||
# of class Text. If you might not, I recommend going with the default of
|
||||
# self.child = renpy.displayable(child)
|
||||
self.child = child
|
||||
self.amp = amp # The amplitude of the sine wave
|
||||
self.char_offset = char_offset # The offset into the sine wave
|
||||
self.period = period # Affects the distance between peaks in the wave.
|
||||
self.speed = speed # Affects how fast our wave moves as a function of time.
|
||||
|
||||
def render(self, width, height, st, at):
|
||||
# Where the current offset is calculated
|
||||
# (self.char_offset * -.1) makes it look like the left side is leading
|
||||
# We use st to allow this to change over time
|
||||
curr_height = math.sin(self.period*((st * self.speed)+(float(self.char_offset) * -.1))) * float(self.amp)
|
||||
|
||||
#### A Transform can be used for several effects ####
|
||||
# t = Transform(child=self.child, alpha = curr_height)
|
||||
|
||||
# Create a render from the child.
|
||||
# Replace self.child with t to include an alpha or zoom transform
|
||||
child_render = renpy.render(self.child, width, height, st, at)
|
||||
|
||||
self.width, self.height = child_render.get_size()
|
||||
render = renpy.Render(self.width, self.height)
|
||||
|
||||
# This will position our child's render. Replacing our need for an offset Transform
|
||||
render.subpixel_blit(child_render, (0, curr_height))
|
||||
|
||||
renpy.redraw(self, 0) # This lets it know to redraw this indefinitely
|
||||
return render
|
||||
|
||||
def event(self, ev, x, y, st):
|
||||
return self.child.event(ev, x, y, st)
|
||||
|
||||
def visit(self):
|
||||
return [ self.child ]
|
||||
|
||||
# Simple fade in. Helps show some ideas for timing
|
||||
# May want to modify to allow it to skip to the end if the user clicks.
|
||||
# Otherwise plays for the full time given.
|
||||
class FadeInText(renpy.Displayable):
|
||||
def __init__(self, child, char_num, fade_time, slide_distance=100, **kwargs):
|
||||
super(FadeInText, self).__init__(**kwargs)
|
||||
|
||||
# The child.
|
||||
self.child = child
|
||||
self.fade_time = fade_time
|
||||
self.display_time = .01
|
||||
self.slide_distance = slide_distance
|
||||
# This is to get seconds per character on screen for later
|
||||
# Allowing this effect to scale with the player's desired text speed
|
||||
cps = 0.0
|
||||
if preferences.text_cps is not 0: # Avoid division by 0.0
|
||||
cps = (1.0 / preferences.text_cps)
|
||||
self.time_offset = char_num * cps # How long to wait before doing things
|
||||
|
||||
def render(self, width, height, st, at):
|
||||
curr_alpha = 0.0
|
||||
xoff = 5.0
|
||||
if st > self.time_offset:
|
||||
adjust_st = st - self.time_offset # Adjust for time delay
|
||||
curr_alpha = adjust_st/self.fade_time
|
||||
xoff = max(self.slide_distance - ((adjust_st/self.fade_time) * self.slide_distance), 0)
|
||||
# Example of using transform to adjust alpha
|
||||
t = Transform(child=self.child, alpha = curr_alpha)
|
||||
child_render = renpy.render(t, width, height, st, at)
|
||||
|
||||
self.width, self.height = child_render.get_size()
|
||||
render = renpy.Render(self.width, self.height)
|
||||
render.subpixel_blit(child_render, (xoff, 0))
|
||||
# Stop redrawing when the animation is finished.
|
||||
if st <= self.fade_time + self.time_offset:
|
||||
renpy.redraw(self, 0)
|
||||
return render
|
||||
|
||||
def visit(self):
|
||||
return [ self.child ]
|
||||
|
||||
# Simple random motion effect
|
||||
class ScareText(renpy.Displayable):
|
||||
def __init__(self, child, square=2, **kwargs):
|
||||
super(ScareText, self).__init__(**kwargs)
|
||||
|
||||
self.child = child
|
||||
|
||||
self.square = square # The size of the square it will wobble within.
|
||||
# Include more variables if you'd like to have more control over the positioning.
|
||||
|
||||
def render(self, width, height, st, at):
|
||||
# Randomly move the offset of the text's render.
|
||||
xoff = (random.random()-.5) * float(self.square)
|
||||
yoff = (random.random()-.5) * float(self.square)
|
||||
|
||||
child_render = renpy.render(self.child, width, height, st, at)
|
||||
self.width, self.height = child_render.get_size()
|
||||
render = renpy.Render(self.width, self.height)
|
||||
|
||||
render.subpixel_blit(child_render, (xoff, yoff))
|
||||
renpy.redraw(self, 0)
|
||||
return render
|
||||
|
||||
def visit(self):
|
||||
return [ self.child ]
|
||||
|
||||
# Demonstration of changing text styles on the fly
|
||||
# Could also predefine some styles and swap between those as well!
|
||||
# Also for this effect in particular, I ---HIGHLY--- advise building in some way to disable it
|
||||
# as it can be pretty harsh on the eyes.
|
||||
# An example of how you can make this a preference option is included below.
|
||||
class ChaosText(renpy.Displayable):
|
||||
# Some may want to have this list be more of a global variable than baked into the class.
|
||||
font_list = ["FOT-PopJoyStd-B.otf", "GrenzeGotisch-VariableFont_wght.ttf", "Pacifico-Regular.ttf", "RobotoSlab-ExtraBold.ttf",\
|
||||
"RobotoSlab-Medium.ttf", "SyneTactile-Regular.ttf", "TurretRoad-Bold.ttf", "TurretRoad-ExtraBold.ttf", "TurretRoad-ExtraLight.ttf", \
|
||||
"TurretRoad-Light.ttf", "TurretRoad-Medium.ttf", "TurretRoad-Regular.ttf"]
|
||||
#Just a list so we can pull any hex value randomly
|
||||
color_choice = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"]
|
||||
def __init__(self, orig_text, **kwargs):
|
||||
|
||||
super(ChaosText, self).__init__(**kwargs) #REMEMBER TO RENAME HERE TO YOUR CLASS
|
||||
|
||||
# Create our child
|
||||
self.child = renpy.text.text.Text(orig_text)
|
||||
self.orig_text = orig_text
|
||||
self.last_style = None # This will be used for renders if the user wants to stop chaos text
|
||||
|
||||
def render(self, width, height, st, at):
|
||||
if not preferences.chaos_on: # This preference is defined near the top of this file. And can be set in the preferences screen (see line 783-787 in screens.rpy)
|
||||
if self.last_style is not None: # If this is our first render, then should do that first
|
||||
# Rest of this is just a repeat of what's below.
|
||||
self.child.set_text(self.last_style.apply_style(self.orig_text))
|
||||
child_render = renpy.render(self.child, width, height, st, at)
|
||||
self.width, self.height = child_render.get_size()
|
||||
render = renpy.Render(self.width, self.height)
|
||||
render.subpixel_blit(child_render, (0, 0))
|
||||
return render
|
||||
|
||||
# We'll create a new text style for this render
|
||||
new_style = DispTextStyle()
|
||||
new_color = ""
|
||||
# Create a random color using hex values
|
||||
for i in range(0,6):
|
||||
new_color += renpy.random.choice(self.color_choice)
|
||||
new_color = "#" + new_color
|
||||
new_style.add_tags("color=" + str(new_color))
|
||||
# Random size
|
||||
rand_size = renpy.random.randint(0,50)
|
||||
new_style.add_tags("size="+str(rand_size))
|
||||
# Random font
|
||||
rand_font = renpy.random.choice(self.font_list)
|
||||
new_style.add_tags("font="+rand_font)
|
||||
#Apply our style to our Text child
|
||||
self.child.set_text(new_style.apply_style(self.orig_text))
|
||||
# Create a render from the child.
|
||||
child_render = renpy.render(self.child, width, height, st, at)
|
||||
self.width, self.height = child_render.get_size()
|
||||
render = renpy.Render(self.width, self.height)
|
||||
render.subpixel_blit(child_render, (0, 0))
|
||||
renpy.redraw(self,0)
|
||||
|
||||
self.last_style = new_style # Save the current style for if the user wishes to turn off the Chaos tag
|
||||
return render
|
||||
|
||||
def visit(self):
|
||||
return [ self.child ]
|
||||
|
||||
# Demonstration of using a Transform on the text and applying rotation
|
||||
class RotateText(renpy.Displayable):
|
||||
def __init__(self, child, speed=300, **kwargs):
|
||||
super(RotateText, self).__init__(**kwargs)
|
||||
|
||||
self.child = child
|
||||
|
||||
self.speed = speed # The speed of our rotation
|
||||
|
||||
def render(self, width, height, st, at):
|
||||
|
||||
theta = math.radians(st * float(self.speed))
|
||||
t = Transform(child=self.child, rotate=st*float(self.speed))
|
||||
child_render = renpy.render(t, width, height/2, st, at)
|
||||
|
||||
self.width, self.height = child_render.get_size()
|
||||
render = renpy.Render(self.width, self.height/2)
|
||||
|
||||
# Problem with using a Transform though is that each character will be padded
|
||||
# Because the rotation may make it wider or taller depending on the character and angle.
|
||||
# How best to tackle this though may vary depending on how you'd like to implement it.
|
||||
render.blit(child_render, (0,0))
|
||||
renpy.redraw(self, 0)
|
||||
return render
|
||||
|
||||
def visit(self):
|
||||
return [ self.child ]
|
||||
|
||||
# The following is an alternative version of rotate that allows for rotation in the x and y axis
|
||||
# Functionally equivalent to using a Transform and flipping it using ATL xzoom and yzoom constrained between 0 and 1
|
||||
# Using a Transform might be better in some cases, but I'll leave this here for anyone who'd prefer to work with angles
|
||||
# for this kind of effect.
|
||||
# Other matrix functions of note include
|
||||
# renpy.display.matrix.perspective(w,h,n,p,f)
|
||||
# renpy.display.matrix.screen_projection(w,h) < Renpy space to OpenGL viewport
|
||||
# renpy.display.matrix.texture_projection(w,h) < Renpy space to OpenGL render-to-texture
|
||||
# You can look up more about them in the renpy\display\matrix_functions.pyx file
|
||||
# Credit to the FancyText module creator yukinogatari for the idea.
|
||||
# FancyText module can be found at https://lemmasoft.renai.us/forums/viewtopic.php?f=51&t=59587
|
||||
"""
|
||||
class RotateText(renpy.Displayable):
|
||||
def __init__(self, child, speed=100, **kwargs):
|
||||
super(RotateText, self).__init__(**kwargs)
|
||||
|
||||
self.child = child
|
||||
self.speed = speed # The speed of our rotation
|
||||
|
||||
def render(self, width, height, st, at):
|
||||
angle = st * self.speed
|
||||
# Which parameter you put the 'angle' into will affect which axis the render rotates on.
|
||||
# Try moving it around and seeing what happens.
|
||||
rotation_m = renpy.display.matrix.rotate(angle,0,0)
|
||||
|
||||
child_render = renpy.render(self.child, width, height, st, at)
|
||||
c_width, c_height = child_render.get_size()
|
||||
# This applies the rotation to our child's render.
|
||||
child_render.reverse = rotation_m
|
||||
|
||||
self.width, self.height = child_render.get_size()
|
||||
render = renpy.Render(self.width, self.height)
|
||||
|
||||
# Math nerds might realize I'm not offsetting the transform.
|
||||
# While renpy.display.matrix.offset(x,y,z) is a thing, it won't change much
|
||||
# The real place to apply the offset is in your final blit. Which is what we'll calculate here
|
||||
|
||||
# Rotations on x axis
|
||||
theta2 = math.radians(st * float(self.speed) + 180)
|
||||
c = math.cos(theta2) + 1.0
|
||||
xoff = 0
|
||||
yoff = c * self.height
|
||||
if yoff > self.height:
|
||||
yoff = self.height
|
||||
|
||||
render.subpixel_blit(child_render, (xoff,yoff))
|
||||
renpy.redraw(self, 0)
|
||||
return render
|
||||
|
||||
def visit(self):
|
||||
return [ self.child ]
|
||||
"""
|
||||
|
||||
# Simple text swap effect
|
||||
# It can be prone to having letters out of place when part of a larger string
|
||||
# I recommended you pass it the entire line to avoid this issue.
|
||||
# Can also just define every line it'll need in advance and just tell it which
|
||||
# ones to swap to to be extra sneaky. Then the text won't be in your script at all!
|
||||
class SwapText(renpy.Displayable):
|
||||
def __init__(self, start_tags, text1, text2, end_tags, swap_time, **kwargs):
|
||||
super(SwapText, self).__init__(**kwargs)
|
||||
#Style tags we'll need as well as the text
|
||||
self.start_tags = start_tags
|
||||
self.text1 = text1
|
||||
self.text2 = text2
|
||||
self.end_tags = end_tags
|
||||
# How long between swapping text
|
||||
self.s_time = swap_time
|
||||
# An internal timer to keep track of when to swap
|
||||
self.timer = 0.0
|
||||
# Determines if we swap to text1 or text2 next
|
||||
self.swap_to_1 = False
|
||||
self.child = Text(start_tags + text1 + end_tags)
|
||||
self.st = 0.0
|
||||
|
||||
|
||||
def render(self, width, height, st, at):
|
||||
delta = st - self.st # How long since last update
|
||||
self.timer += delta
|
||||
if self.timer > self.s_time:
|
||||
# If time to swap, determine which one to swap to.
|
||||
if self.swap_to_1:
|
||||
self.child.set_text(self.start_tags + self.text1 + self.end_tags)
|
||||
self.swap_to_1 = False
|
||||
self.timer = 0.0
|
||||
else:
|
||||
self.child.set_text(self.start_tags + self.text2 + self.end_tags)
|
||||
self.swap_to_1 = True
|
||||
self.timer = 0.0
|
||||
|
||||
child_render = renpy.render(self.child, width, height, st, at)
|
||||
self.width, self.height = child_render.get_size()
|
||||
render = renpy.Render(self.width, self.height)
|
||||
render.subpixel_blit(child_render, (0,0))
|
||||
renpy.redraw(self, 0)
|
||||
|
||||
self.st = st # So we can check how long since last update
|
||||
return render
|
||||
|
||||
def visit(self):
|
||||
return [ self.child ]
|
||||
|
||||
# An example of text that moves and reacts to the mouse.
|
||||
# Sidenote: The position the mouse is distorted if the screen is resized.
|
||||
# I did try to find a way to counteract this, but didn't have much luck.
|
||||
# Seems to only happen on the x component though. No clue why.
|
||||
# If anyone can pinpoint the issue, please let me know and I'll be happy to fix it.
|
||||
class MoveText(renpy.Displayable):
|
||||
def __init__(self, child, **kwargs):
|
||||
super(MoveText, self).__init__(**kwargs)
|
||||
self.affect_distance = 150
|
||||
self.child = child
|
||||
self.mouse_pos = (1000,1000)
|
||||
self.pos = (0,0)
|
||||
|
||||
def render(self, width, height, st, at):
|
||||
child_render = renpy.render(self.child, width, height, st, at)
|
||||
self.width, self.height = child_render.get_size()
|
||||
render = renpy.Render(self.width, self.height)
|
||||
# x and y we get in the event function are relative to the top left corner of the displayable initially.
|
||||
# So we'll want to update it to reflect the actual position of our text
|
||||
trans_x = self.mouse_pos[0] - self.pos[0] - (self.width / 2)
|
||||
trans_y = self.mouse_pos[1] - self.pos[1] - (self.height / 2)
|
||||
|
||||
vl = math.hypot(trans_x,trans_y)
|
||||
xpos, ypos = self.pos
|
||||
# Can skip calculation if vector length is further than our specified effect distance
|
||||
if vl < self.affect_distance:
|
||||
distance = 3.0 * (self.affect_distance-vl) / self.affect_distance
|
||||
xpos -= distance * trans_x / vl
|
||||
ypos -= distance * trans_y / vl
|
||||
self.pos = (xpos, ypos) # Preserve the new pos
|
||||
# Use our child's position as determined by the event function
|
||||
render.subpixel_blit(child_render, (xpos, ypos))
|
||||
renpy.redraw(self, 0)
|
||||
return render
|
||||
|
||||
def event(self, ev, x, y, st):
|
||||
self.mouse_pos = (x,y)
|
||||
# Pass the event to our child.
|
||||
return self.child.event(ev, x, y, st)
|
||||
|
||||
def visit(self):
|
||||
return [ self.child ]
|
||||
|
||||
|
||||
### CUSTOM TAG FUNCTIONS ###
|
||||
# Letters move in a sine wave.
|
||||
# Arguments are separated by dashes.
|
||||
# Arguments:
|
||||
# 'a': (int) The amplitude (height) of the text's sine wave motion. How high and low it'll go from it's default position in pixels.
|
||||
# 'p': (float) The period of the wave. Distance between peaks in the wave.
|
||||
# 's': (float) The speed of the wave. How fast it moves with time.
|
||||
# Example: {bt=[height]}Text{/bt}
|
||||
# Example: {bt=h5-p2.0-s0.5}Text{/bt}
|
||||
# If a lone number is given, it is treated as the amplitude only to ensure backwards compatibility
|
||||
# Example: {bt=10}Text{/bt}
|
||||
def bounce_tag(tag, argument, contents):
|
||||
new_list = [ ] # The list we will be appending our displayables into
|
||||
amp, period, speed = 20, 4.0, 1.0
|
||||
if argument == "": # If the argument received is blank, insert a default value
|
||||
amp = 20
|
||||
else:
|
||||
argument = argument.split('-')
|
||||
if len(argument) == 1 and argument[0][0].isdigit(): # Default behavior to ensure backward compatibility
|
||||
amp = int(argument[0])
|
||||
else:
|
||||
for arg in argument:
|
||||
if arg[0] == 'a':
|
||||
amp = int(arg[1:])
|
||||
elif arg[0] == 'p':
|
||||
period = float(arg[1:])
|
||||
elif arg[0] == 's':
|
||||
speed = float(arg[1:])
|
||||
|
||||
char_offset = 0 # Since we want our text to move in a wave,
|
||||
# we want to let each character know where it is in the wave.
|
||||
# So they move in harmony. Otherwise they rise and fall all together.
|
||||
my_style = DispTextStyle() # This will keep track of what tags and styling to add to each letter
|
||||
for kind,text in contents:
|
||||
if kind == renpy.TEXT_TEXT:
|
||||
for char in text: # Extract every character from the string
|
||||
char_text = Text(my_style.apply_style(char)) # Create a Text displayable with our styles applied
|
||||
char_disp = BounceText(char_text, char_offset, amp=amp, period=period, speed=speed) # Put the Text into the Wrapper
|
||||
new_list.append((renpy.TEXT_DISPLAYABLE, char_disp)) # Add it back in as a displayable
|
||||
char_offset += 1
|
||||
elif kind == renpy.TEXT_TAG:
|
||||
if text.find("image") != -1:
|
||||
tag, _, value = text.partition("=")
|
||||
my_img = renpy.displayable(value)
|
||||
img_disp = BounceText(my_img, char_offset, amp=amp, period=period, speed=speed)
|
||||
new_list.append((renpy.TEXT_DISPLAYABLE, img_disp))
|
||||
char_offset += 1
|
||||
elif not my_style.add_tags(text):
|
||||
new_list.append((kind, text))
|
||||
# I honestly never got around to testing this. Not often the text
|
||||
# already has a displayable in it. Let me know if it breaks though.
|
||||
elif kind == renpy.TEXT_DISPLAYABLE:
|
||||
char_disp = BounceText(text, char_offset, amp=amp, period=period, speed=speed)
|
||||
new_list.append((renpy.TEXT_DISPLAYABLE, char_disp))
|
||||
char_offset += 1
|
||||
else: # Don't touch any other type of content
|
||||
new_list.append((kind,text))
|
||||
|
||||
return new_list
|
||||
|
||||
# Letters will start off to the right & invisible. And will then move left while increasing their opacity. Good for meditation and calm text.
|
||||
# offset: (int) Offset within the line. Needed to help time start of fade-in with other slow text characters.
|
||||
# time: (float) How long in seconds the animation lasts.
|
||||
# distance: (int) How many pixels the fade in occurs across
|
||||
# Example: {fi=[offset]-[time]-[distance]}Text{/fi}
|
||||
def fade_in_tag(tag, argument, contents):
|
||||
new_list = [ ]
|
||||
my_index, fade_time, slide_distance = 0, 5.0, 100
|
||||
if argument != "":
|
||||
argument = argument.split('-')
|
||||
if len(argument) > 0:
|
||||
my_index = int(argument[0])
|
||||
if len(argument) > 1:
|
||||
fade_time = float(argument[1])
|
||||
if len(argument) > 2:
|
||||
slide_distance = int(argument[2])
|
||||
my_style = DispTextStyle()
|
||||
for kind,text in contents:
|
||||
if kind == renpy.TEXT_TEXT:
|
||||
for char in text:
|
||||
if char == ' ':
|
||||
new_list.append((renpy.TEXT_TEXT, ' ')) # Skips blank space since looks weird counting it
|
||||
continue
|
||||
char_text = Text(my_style.apply_style(char))
|
||||
char_disp = FadeInText(char_text, my_index, fade_time, slide_distance)
|
||||
new_list.append((renpy.TEXT_DISPLAYABLE, char_disp))
|
||||
my_index += 1
|
||||
elif kind == renpy.TEXT_TAG:
|
||||
if text.find("image") != -1:
|
||||
tag, _, value = text.partition("=")
|
||||
my_img = renpy.displayable(value)
|
||||
img_disp = FadeInText(my_img, my_index, fade_time, slide_distance)
|
||||
new_list.append((renpy.TEXT_DISPLAYABLE, img_disp))
|
||||
my_index += 1
|
||||
elif not my_style.add_tags(text):
|
||||
new_list.append((kind, text))
|
||||
else:
|
||||
new_list.append((kind,text))
|
||||
return new_list
|
||||
|
||||
# Letters change position every frame randomly. Good for very angry or quivering dialogue.
|
||||
# range: (int) Letters are confined to a square around their default location. Range determines length of the sides of that square.
|
||||
# Higher values will make it very chaotic while smaller values will make it quite minimal.
|
||||
# Example: {sc=[range]}Text{/sc}
|
||||
def scare_tag(tag, argument, contents):
|
||||
new_list = [ ]
|
||||
if argument == "":
|
||||
argument = 5
|
||||
my_style = DispTextStyle()
|
||||
for kind,text in contents:
|
||||
if kind == renpy.TEXT_TEXT:
|
||||
for char in text:
|
||||
char_text = Text(my_style.apply_style(char))
|
||||
char_disp = ScareText(char_text, argument)
|
||||
new_list.append((renpy.TEXT_DISPLAYABLE, char_disp))
|
||||
elif kind == renpy.TEXT_TAG:
|
||||
if text.find("image") != -1:
|
||||
tag, _, value = text.partition("=")
|
||||
my_img = renpy.displayable(value)
|
||||
img_disp = ScareText(my_img, argument)
|
||||
new_list.append((renpy.TEXT_DISPLAYABLE, img_disp))
|
||||
elif not my_style.add_tags(text):
|
||||
new_list.append((kind, text))
|
||||
else:
|
||||
new_list.append((kind,text))
|
||||
|
||||
return new_list
|
||||
|
||||
# Letters change their font, color and size every frame.
|
||||
# Example: {chaos}Text{/chaos}
|
||||
# Honestly more a demonstration of what can be done than useful in it's own right.
|
||||
# If you create tags this chaotic, please include a way to turn it off for people with epilepsy.
|
||||
def chaos_tag(tag, argument, contents):
|
||||
new_list = [ ]
|
||||
my_style = DispTextStyle()
|
||||
for kind,text in contents:
|
||||
if kind == renpy.TEXT_TEXT:
|
||||
for char in text:
|
||||
char_disp = ChaosText(my_style.apply_style(char))
|
||||
new_list.append((renpy.TEXT_DISPLAYABLE, char_disp))
|
||||
elif kind == renpy.TEXT_TAG:
|
||||
if not my_style.add_tags(text):
|
||||
new_list.append((kind, text))
|
||||
else:
|
||||
new_list.append((kind,text))
|
||||
|
||||
return new_list
|
||||
|
||||
# Letters rotate in place. Good for stylized intros or UI
|
||||
# Speed: (int) How fast the rotation will be.
|
||||
# Example: {rotat=[speed]}Text{/rotat}
|
||||
def rotate_tag(tag, argument, contents):
|
||||
new_list = [ ]
|
||||
# Argument here will reprsent the desired speed of the rotation.
|
||||
if argument == "":
|
||||
argument = 400
|
||||
else:
|
||||
argument = int(argument)
|
||||
my_style = DispTextStyle()
|
||||
for kind,text in contents:
|
||||
if kind == renpy.TEXT_TEXT:
|
||||
for char in text:
|
||||
char_text = Text(my_style.apply_style(char))
|
||||
char_disp = RotateText(char_text, argument)
|
||||
new_list.append((renpy.TEXT_DISPLAYABLE, char_disp))
|
||||
elif kind == renpy.TEXT_TAG:
|
||||
if text.find("image") != -1:
|
||||
tag, _, value = text.partition("=")
|
||||
my_img = renpy.displayable(value)
|
||||
img_disp = RotateText(my_img, argument)
|
||||
new_list.append((renpy.TEXT_DISPLAYABLE, img_disp))
|
||||
elif not my_style.add_tags(text):
|
||||
new_list.append((kind, text))
|
||||
else:
|
||||
new_list.append((kind,text))
|
||||
|
||||
return new_list
|
||||
|
||||
# Causes letters to change between two strings every couple of seconds.
|
||||
# text1: (String) First set of characters to display. Should be equal to the length of the characters we're replacing
|
||||
# text2: (String) Second set of characters to display. Should be equal to the length of text1
|
||||
# swap_time: (int) Length of time between character swap
|
||||
# Arguments are separated by '@'. Length of strings should not exceed length of text they are replacing.
|
||||
# Example: {swap=Text@Four@0.5}Text{}
|
||||
# This is a pretty static way of doing it mostly made to demonstrate the concept.
|
||||
# Included for others to build upon for their needs.
|
||||
def swap_tag(tag, argument, contents):
|
||||
new_list = [ ]
|
||||
if argument == "":
|
||||
return contents
|
||||
text1, _, argument = argument.partition("@")
|
||||
text2, _, argument = argument.partition("@")
|
||||
if len(text1) != len(text2):
|
||||
new_list.append((renpy.TEXT_TEXT, "ERROR!"))
|
||||
swap_time = float(argument)
|
||||
|
||||
my_style = DispTextStyle()
|
||||
for kind,text in contents:
|
||||
if kind == renpy.TEXT_TEXT:
|
||||
# This one replaces the whole text rather than extracting over letters
|
||||
# That way it can take up this whole block with its own Text displayable
|
||||
char_disp = SwapText(my_style.start_tags(), text1, text2, my_style.end_tags(), swap_time)
|
||||
new_list.append((renpy.TEXT_DISPLAYABLE, char_disp))
|
||||
elif kind == renpy.TEXT_TAG:
|
||||
if not my_style.add_tags(text):
|
||||
new_list.append((kind, text))
|
||||
else:
|
||||
new_list.append((kind,text))
|
||||
return new_list
|
||||
|
||||
# Makes it so the text within moves away from the mouse. More example of what can be done than useful
|
||||
# Example: {move}Text{/move}
|
||||
def move_tag(tag, argument, contents):
|
||||
new_list = [ ]
|
||||
my_style = DispTextStyle()
|
||||
for kind,text in contents:
|
||||
if kind == renpy.TEXT_TEXT:
|
||||
for char in text:
|
||||
char_text = Text(my_style.apply_style(char))
|
||||
char_disp = MoveText(char_text)
|
||||
new_list.append((renpy.TEXT_DISPLAYABLE, char_disp))
|
||||
elif kind == renpy.TEXT_TAG:
|
||||
if text.find("image") != -1:
|
||||
tag, _, value = text.partition("=")
|
||||
my_img = renpy.displayable(value)
|
||||
img_disp = MoveText(my_img)
|
||||
new_list.append((renpy.TEXT_DISPLAYABLE, img_disp))
|
||||
elif not my_style.add_tags(text):
|
||||
new_list.append((kind, text))
|
||||
else:
|
||||
new_list.append((kind,text))
|
||||
return new_list
|
||||
|
||||
# Some text effects won't allow for a paragraph break if applied to a whole line
|
||||
# Which can cause your text to just continue straight off the screen.
|
||||
# To amend this, you can insert the {para} tag.
|
||||
# This will let the Text displayable holding us know when to wrap.
|
||||
# Can also use \n in most cases. But leaving this for people who may already be using it
|
||||
# or for cases where \n doesn't work.
|
||||
def paragraph_tag(tag, argument):
|
||||
return [(renpy.TEXT_PARAGRAPH, "")]
|
||||
|
||||
# This tag is made to automatically wrap several Classes inside one another
|
||||
# This is to reduce strain on the render pipeline and memory from nested classes
|
||||
# Notes:
|
||||
# GradientText and GlitchText are omitted because they were made after the 1.0 release.
|
||||
# SwapText and MoveText are omitted for possible issues.
|
||||
# SwapText because is not included in this due to it replacing whole sections rather than
|
||||
# individual letters. Would be better to embed an Omega inside a SwapText.
|
||||
# MoveText because of potential issues of having things like BounceText affect
|
||||
# affecting the position of the letter visually.
|
||||
# Would be better to have an event call attached to one of those so it can account
|
||||
# for the transformations of other tags
|
||||
# Argument Notes (all tag args accept same arguments as original tag):
|
||||
# BT: BounceText
|
||||
# SC: ScareText
|
||||
# FI: FadeInText
|
||||
# ROT: RotateText
|
||||
# CH: ChaosText
|
||||
# All tag arguments are seperated by @.
|
||||
# Example: {omega=BT=[bt_arg]@SC=[sc_arg]@FI=[fi_arg1]-[fi_arg2]@ROT=[rot_arg]@CH}Text{/omega}
|
||||
def omega_tag(tag, argument, contents):
|
||||
new_list = [ ]
|
||||
if argument == "": # This tag must have arguments
|
||||
return contents
|
||||
# Variable for each of our tags. None if it takes one argument.
|
||||
# Boolean if 0 or many arguments.
|
||||
bt_tag = None
|
||||
sc_tag = None
|
||||
fi_tag = False
|
||||
rot_tag = None
|
||||
chao_tag = False
|
||||
fi_arg_1 = None
|
||||
fi_arg_2 = None
|
||||
|
||||
args = [ ]
|
||||
arg_count = argument.count('@') # Count how many partitions we will need to make
|
||||
for x in range(arg_count): # Extract all the tags and arguments with them
|
||||
new_arg, _, argument = argument.partition('@')
|
||||
args.append(new_arg)
|
||||
args.append(argument)
|
||||
# Determine what tags we'll need to apply and the arguments associated with them
|
||||
for arg in args:
|
||||
tag, _, value = arg.partition('=')
|
||||
if tag == "BT":
|
||||
if value is not "":
|
||||
bt_tag = value
|
||||
else:
|
||||
bt_tag = 10
|
||||
elif tag == "SC":
|
||||
if value is not "":
|
||||
bt_tag = value
|
||||
else:
|
||||
bt_tag = 5
|
||||
# Multiargument tag example. Be sure to use different partitions for these
|
||||
elif tag == "FI":
|
||||
fi_tag = True
|
||||
str1, _, str2 = value.partition('-')
|
||||
fi_arg_1 = int(str1)
|
||||
fi_arg_2 = float(str2)
|
||||
elif tag == "ROT":
|
||||
rot_tag = value
|
||||
elif tag == "CH":
|
||||
chao_tag = True
|
||||
|
||||
my_style = DispTextStyle()
|
||||
my_index = 0 # Some Classes will need an index
|
||||
for kind,text in contents:
|
||||
if kind == renpy.TEXT_TEXT:
|
||||
for char in text:
|
||||
# Apply base Wrappers to letter
|
||||
if chao_tag:
|
||||
char_disp = ChaosText(my_style.apply_style(char))
|
||||
else:
|
||||
char_disp = Text(my_style.apply_style(char))
|
||||
# Apply further Wraps
|
||||
# Be sure to consider if the order will be important to you
|
||||
if bt_tag is not None:
|
||||
char_disp = BounceText(char_disp, my_index, bt_tag)
|
||||
if sc_tag is not None:
|
||||
char_disp = ScareText(char_disp, sc_tag)
|
||||
if fi_tag:
|
||||
char_disp = FadeInText(char_disp, my_index + fi_arg_1, fi_arg_2)
|
||||
if rot_tag is not None:
|
||||
char_disp = RotateText(char_disp, rot_tag)
|
||||
new_list.append((renpy.TEXT_DISPLAYABLE, char_disp))
|
||||
elif kind == renpy.TEXT_TAG:
|
||||
if not my_style.add_tags(text):
|
||||
new_list.append((kind, text))
|
||||
else:
|
||||
new_list.append((kind,text))
|
||||
|
||||
return new_list
|
||||
|
||||
"""
|
||||
# Template tag function to copy off of.
|
||||
def TEMPLATE_tag(tag, argument, contents):
|
||||
new_list = [ ]
|
||||
if argument == "":
|
||||
argument = 5
|
||||
my_style = DispTextStyle()
|
||||
for kind,text in contents:
|
||||
if kind == renpy.TEXT_TEXT:
|
||||
for char in text:
|
||||
char_text = Text(my_style.apply_style(char))
|
||||
char_disp = TEMPLATEText(char_text, argument)
|
||||
new_list.append((renpy.TEXT_DISPLAYABLE, char_disp))
|
||||
elif kind == renpy.TEXT_TAG:
|
||||
if not my_style.add_tags(text):
|
||||
new_list.append((kind, text))
|
||||
else:
|
||||
new_list.append((kind,text))
|
||||
return new_list
|
||||
"""
|
||||
|
||||
# Define our new text tags
|
||||
config.custom_text_tags["bt"] = bounce_tag
|
||||
config.custom_text_tags["fi"] = fade_in_tag
|
||||
config.custom_text_tags["sc"] = scare_tag
|
||||
config.custom_text_tags["rotat"] = rotate_tag
|
||||
config.custom_text_tags["chaos"] = chaos_tag
|
||||
config.custom_text_tags["swap"] = swap_tag
|
||||
config.custom_text_tags["move"] = move_tag
|
||||
config.custom_text_tags["omega"] = omega_tag
|
||||
config.self_closing_custom_text_tags["para"] = paragraph_tag
|
||||
# Template tag function
|
||||
#config.custom_text_tags[""] = _tag
|
|
@ -12,7 +12,7 @@
|
|||
##
|
||||
## The _() surrounding the string marks it as eligible for translation.
|
||||
|
||||
define config.name = _("sexo_space_lady_game")
|
||||
define config.name = _("A Star in her Eyes")
|
||||
|
||||
|
||||
## Determines if the title given above is shown on the main menu screen. Set
|
||||
|
@ -30,6 +30,10 @@ define config.version = "1.0"
|
|||
## triple-quotes, and leave a blank line between paragraphs.
|
||||
|
||||
define gui.about = _p("""
|
||||
A game made by Cavemanon, an upcoming indie game team comprised of many members from around the world. Currently developing {color=#f1a5d8}Exit 665{/color}, {color=#f1a5d8}I Wani Hug that Gator!{/color}, and potentially more!
|
||||
|
||||
You can find out about most recent updates and developments at our {a=https://twitter.com/Cavemanon}twitter{/a}.
|
||||
|
||||
""")
|
||||
|
||||
|
||||
|
@ -37,7 +41,7 @@ define gui.about = _p("""
|
|||
## distribution. This must be ASCII-only, and must not contain spaces, colons,
|
||||
## or semicolons.
|
||||
|
||||
define build.name = "sexo_space_lady_game"
|
||||
define build.name = "A_Star_in_her_Eyes"
|
||||
|
||||
|
||||
## Sounds and music ############################################################
|
||||
|
@ -48,7 +52,7 @@ define build.name = "sexo_space_lady_game"
|
|||
|
||||
define config.has_sound = True
|
||||
define config.has_music = True
|
||||
define config.has_voice = True
|
||||
define config.has_voice = False
|
||||
|
||||
|
||||
## To allow the user to play a test sound on the sound or voice channel,
|
||||
|
@ -120,7 +124,7 @@ define config.window_hide_transition = Dissolve(.2)
|
|||
## 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
|
||||
default preferences.text_cps = 50
|
||||
|
||||
|
||||
## The default auto-forward delay. Larger numbers lead to longer waits, with 0
|
||||
|
|
1228
game/script.rpy
1228
game/script.rpy
File diff suppressed because it is too large
Load Diff
|
@ -1 +0,0 @@
|
|||
hello
|
Loading…
Reference in New Issue