- Jun 2, 2018
- 1,716
- 9,218
I've been working on this for a few days now and feel like I'm going around in circles. Some outside perspective would be really helpful.
Here is the quick gist of the issue. I'd like to implement blinks all through the project I'm working on. This has turned out to be very straight forward using ATL:
The problem is, this code isn't very compact, is hugely repetitive (do not repeat yourself), and feels like I should be able to create a factory to generate it. Additionally, since every character model (using layeredimage) and every full screen image (mostly using layeredimage as well) needs this code it is littered everywhere, and it just feels... bad.
After much googling, I found a helpful post on this site that pointed me towards DynamicDisplayable as a possible option, and damn did it get me close. Now the blink code looks more like this:
Much more compact and when I get to scene work, it is WAY easier to implement for each image.
Just, one, tiny, little, hardly worth mentioning but absolutely a pretty big issue, thing. The images don't dissolve, they just hard switch. And when dealing with blinks, this looks awful, taking away any immersion the blinks otherwise added.
Here is the sub class I'm working with (based on the DynamicBlink code in this post)
And the code does work, it just doesn't dissolve. I tried returning a Dissolve object at the end of get_current_blink_image, but that doesn't work (throwing an error that Dissolve is not a Displayable, even though it looks like it should be?)
After spending (I have no idea how many hours) a lot of time looking at the renpy engine classes for DynamicDisplayable and Dissolve, I just can't figure out how to get them to work with each other. I think I might ultimately be going about this from the wrong end. Maybe I just need to write a whole new implementation of something like DynamicDissolveable or something... Or, I'm looking at the wrong class entirely
Anyhow, thanks for any input anyone can share! Worst case I just stick with ATL, which works, but is a bit ugly (and no one but me will ever care).
Here is the quick gist of the issue. I'd like to implement blinks all through the project I'm working on. This has turned out to be very straight forward using ATL:
Python:
image morty_main_blink_open:
"chars/morty/main/blank.png"
choice:
5
choice:
4
choice:
3
choice:
2
"chars/morty/main/l/1.png" with Dissolve(0.1)
0.1
"chars/morty/main/l/0.png" with Dissolve(0.1)
0.1
"chars/morty/main/l/1.png" with Dissolve(0.1)
0.1
repeat
After much googling, I found a helpful post on this site that pointed me towards DynamicDisplayable as a possible option, and damn did it get me close. Now the blink code looks more like this:
Code:
image morty_main_blink_open = DynamicBlink("chars/morty/main/blank.png", ["1.png", "0.png"], ["chars", "morty", "main", "l"])
Just, one, tiny, little, hardly worth mentioning but absolutely a pretty big issue, thing. The images don't dissolve, they just hard switch. And when dealing with blinks, this looks awful, taking away any immersion the blinks otherwise added.
Here is the sub class I'm working with (based on the DynamicBlink code in this post)
Python:
class DynamicBlink(renpy.display.layout.DynamicDisplayable):
def __init__(self, first_image, images, dir_list, **kwargs):
self.closing = True
self.used_images = [first_image]
self.dir_setup(images, dir_list)
self.current_image_index = 0
self.image_count = len(images) - 1
self.current_image = images[0]
self.blink_timer = -1.0
kwargs.update( { '_predict_function' : self.predict_images } )
super(DynamicBlink, self).__init__( self.get_current_blink_image )
def get_current_blink_image(self, timer, at):
if timer < 1.0 and self.blink_timer > 6.0:
self.get_new_random_time(timer)
if self.closing == True:
if timer > self.blink_timer:
self.current_image_index += 1
self.current_image = self.used_images[self.current_image_index]
self.blink_timer = timer + 0.1
if self.current_image_index == self.image_count:
self.closing = False
self.blink_timer = timer + 0.1
else:
if timer > self.blink_timer:
self.current_image_index -= 1
self.current_image = self.used_images[self.current_image_index]
self.blink_timer = timer + 0.1
if self.current_image_index == 0:
self.closing = True
self.get_new_random_time(timer)
return self.current_image, 0
def dir_setup(self, images, dir_list):
for i in images:
img = ""
for n in dir_list:
img += n + "/"
img += i
self.used_images.append(img)
def get_new_random_time(self, timer):
self.blink_timer = timer + 2.0 + ( renpy.python.rng.random() * 3.0 )
def predict_images(self):
return self.used_images
After spending (I have no idea how many hours) a lot of time looking at the renpy engine classes for DynamicDisplayable and Dissolve, I just can't figure out how to get them to work with each other. I think I might ultimately be going about this from the wrong end. Maybe I just need to write a whole new implementation of something like DynamicDissolveable or something... Or, I'm looking at the wrong class entirely
Anyhow, thanks for any input anyone can share! Worst case I just stick with ATL, which works, but is a bit ugly (and no one but me will ever care).