Creating a 'text shuffling' effect?

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
User avatar
hachi-mitsu
Newbie
Posts: 18
Joined: Sun Sep 30, 2018 4:21 am
Projects: A (second) personal project!
Contact:

Creating a 'text shuffling' effect?

#1 Post by hachi-mitsu » Tue Sep 01, 2020 1:56 am

Hi there!

Before I start working heavily on my second project, I wanted to check prior if an effect like this is possible in Renpy, and what options I have available to pull it off, if it is possible. Because this type of feature would be pretty important to the story-telling, I really would like to be able to pull it off in some way, otherwise my story will kinda fall flat : P

I want to know if I can implement this kind of effect on external text.
http://geon.github.io/programming/2016/03/03/dsxyliea

When I say external text, I mean text that is not in the say window/textbox, but text on an image (specifically, a phone screen that is displayed at points during the story in the centre of the screen). So not menu text or anything like that. I posted an older topic asking about something similar in style, where my last VN used a notepad image that slid up at the centre of the screen, which I layered different transparent handwritten message pngs onto.

To do that notepad effect last time, it was really simple, I just defined the images and layered them for each message. I didn't utilise screens for it.

So here, I'm asking if it's possible for me to somehow implement coding that creates this organic shuffling effect on text during the game. Or would I need to do it pre-formatted on a gif image that when layered onto the phone screen, plays once and is synced to whatever the story is asking for at the time (extreme shuffling v. slowing down in shuffling).

I would like the ability for spontaneous shuffling of the text when the text is displayed, as well as perhaps different types of speeds/shuffle amounts (so for a simple message, I could slow the shuffling down to be very sparse).

I'm not sure if this is wishful thinking and too ambitious, or if this is something that is perfectly capable in Renpy. I would be very grateful if someone more experienced could let me know :) Thank you!

User avatar
hell_oh_world
Miko-Class Veteran
Posts: 558
Joined: Fri Jul 12, 2019 5:21 am
Projects: The Button Man
Organization: NILA
Github: hell-oh-world
Location: Philippines
Contact:

Re: Creating a 'text shuffling' effect?

#2 Post by hell_oh_world » Tue Sep 01, 2020 2:33 am

I think dynamic displayables should help.

Code: Select all

init python:
    def shuffleText(st, at, text, time_range=(0, 2), *args, **kwargs):
        texts = text.split()
        shuffled_texts = []
        for text in texts:
            text = list(text)
            renpy.random.shuffle(text)
            shuffled_texts.append("".join(text))

        time = renpy.random.choice(range(*time_range))
        
        return (Text(" ".join(shuffled_texts), *args, **kwargs), time)

screen something():
    add DynamicDisplayable(shuffleText, "Hello how are you?", align=(0.5, 0.5)) # not specifying the time_range would make the text shuffle randomly in 0 or 1 second. time_range (1, 5) shuffles 1 / 2 / 3 / 4 seconds

# The game starts here.
label start:
    call screen something
This sorta works. although the randomness affects all the words, if you want to make the randomness different per word you could try this approach I think.

Code: Select all

screen something():
    default text = "Hello how are you?"

    hbox:
        align (0.5, 0.25)
        spacing 5

        for t in text.split():
            add DynamicDisplayable(shuffleText, t)
lastly, probably wrap all of this in a function to make things easier.

Code: Select all

init python:
  def ShufflingText(text, time_range=(0, 2), *args, **kwargs):
    def shuffleText(st, at, text, time_range=(0, 2), *args, **kwargs):
        texts = text.split()
        shuffled_texts = []
        for text in texts:
            text = list(text)
            renpy.random.shuffle(text)
            shuffled_texts.append("".join(text))

        time = renpy.random.choice(range(*time_range))
        
        return (Text(" ".join(shuffled_texts), *args, **kwargs), time)

    return DynamicDisplayable(shuffleText, text, time_range, *args, **kwargs)

screen something:
  add ShufflingText("Who are you?", align=(0.5, 0.5))
then you can use it like...

Code: Select all

screen something():
  default text = """
    Dynamic displayables display a child displayable based on the state of the game. They do not take any properties, as their layout is controlled by the properties of the child displayable they return.

    Note that these dynamic displayables always display their current state. Because of this, a dynamic displayable will not participate in a transition. (Or more precisely, it will display the same thing in both the old and new states of the transition.)

    By design, dynamic displayables are intended to be used for things that change rarely and when an image define this way is off screen (Such as a character customization system), and not for things that change frequently, such as character emotions.
    """
  hbox:
      spacing 5
      align (0.5, 0.5)
      xsize 500
      box_wrap True
      for t in text.split():
          add ShufflingText(t, (1, 3)) # randomly shuffles within 1 / 2 seconds per word.
          
label start:
  call screen something
i don't know about dyslexia (the link that you sent), I kinda observed that the example only shuffles the in between characters, excluding the first and last letter of a word... so some modification to the function that I provide should do that, and here's what should the function look like.

Code: Select all

def ShufflingText(text, time_range=(0, 2), *args, **kwargs):
    def shuffleText(st, at, text, time_range=(0, 2), *args, **kwargs):
        texts = text.split()
        shuffled_texts = []
        for text in texts:
            shuffled_text = list(text[1:-1])
            renpy.random.shuffle(shuffled_text)
            shuffled_text = [text[0]] + shuffled_text + [text[-1]]
            shuffled_texts.append("".join(shuffled_text))

        time = renpy.random.choice(range(*time_range))
        
        return (Text(" ".join(shuffled_texts), *args, **kwargs), time)

    return DynamicDisplayable(shuffleText, text, time_range, *args, **kwargs)
the first few examples shuffle the whole words completely, while this one excludes the first and last characters of the word, like in the link that you shared.

User avatar
Imperf3kt
Lemma-Class Veteran
Posts: 3135
Joined: Mon Dec 14, 2015 5:05 am
Location: Your monitor
Contact:

Re: Creating a 'text shuffling' effect?

#3 Post by Imperf3kt » Tue Sep 01, 2020 2:59 am

Just some feedback, but I didn't notice the dyslexia example was actually shuffling letters around until I had read through half of it.
If you're aiming to simulate what it's like to be dyslexic, this may not work thanks to the hypothetical Typoglycemia effect.
It's speculated to be nothing more than a rumor but in my own experience, I have absolutely no trouble reading the given example. Others may experience similar, diminishing the effect you're presumably after.
Warning: May contain trace amounts of gratuitous plot.
pro·gram·mer (noun) An organism capable of converting caffeine into code.

Twitter
Imperf3kt Blackjack - a WIP blackjack game for Android made using Ren'Py
Free Android GUI - Updated occasionally

User avatar
hachi-mitsu
Newbie
Posts: 18
Joined: Sun Sep 30, 2018 4:21 am
Projects: A (second) personal project!
Contact:

Re: Creating a 'text shuffling' effect?

#4 Post by hachi-mitsu » Tue Sep 01, 2020 3:26 am

hell_oh_world wrote:
Tue Sep 01, 2020 2:33 am
I think dynamic displayables should help.

Code: Select all

def ShufflingText(text, time_range=(0, 2), *args, **kwargs):
    def shuffleText(st, at, text, time_range=(0, 2), *args, **kwargs):
        texts = text.split()
        shuffled_texts = []
        for text in texts:
            shuffled_text = list(text[1:-1])
            renpy.random.shuffle(shuffled_text)
            shuffled_text = [text[0]] + shuffled_text + [text[-1]]
            shuffled_texts.append("".join(shuffled_text))

        time = renpy.random.choice(range(*time_range))
        
        return (Text(" ".join(shuffled_texts), *args, **kwargs), time)

    return DynamicDisplayable(shuffleText, text, time_range, *args, **kwargs)
the first few examples shuffle the whole words completely, while this one excludes the first and last characters of the word, like in the link that you shared.
Oh wow, thank you very much for showing me how the coding would work! I was just after whether it was possible or not, so I'm really grateful! Thanks for taking the time to write it out for me and explain each step. I'll definitely refer to it then, though I haven't tested it, it does sound exactly like the effect I was hoping to create. I assume I would just have to position and bind the text to be within the phone screen displayable. Thank you once again!

Imperf3kt wrote:
Tue Sep 01, 2020 2:59 am
Just some feedback, but I didn't notice the dyslexia example was actually shuffling letters around until I had read through half of it.
If you're aiming to simulate what it's like to be dyslexic, this may not work thanks to the hypothetical Typoglycemia effect.
It's speculated to be nothing more than a rumor but in my own experience, I have absolutely no trouble reading the given example. Others may experience similar, diminishing the effect you're presumably after.
Hi there, thank you for the feedback! It's very interesting to hear about the different levels to where such a visual affects people (or not!). The Typoglycemia link really took me back to old internet chain mails :lol: But I understand your point. Luckily, I only really make these projects for myself, and share it with one or two friends in the end. I don't distribute it publicly, so I think it will be okay in my case. Though I'd definitely consider changing it based on your advice if I were making this a public/commercial VN. Thanks again for your reply : )

Post Reply

Who is online

Users browsing this forum: Alex