Skip to main content

On Sale: GamesAssetsToolsTabletopComics
Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Wattson

74
Posts
650
Followers
111
Following
A member registered Jun 24, 2019 · View creator page →

Creator of

Recent community posts

If your audience is furry and gay, you can consider linking my Bluesky (https://bsky.app/profile/wattson.bsky.social). But if you don't think ppl would want to see how much I repost on there, you can just say Wattson or use my name in the files, depending on what works best for you.

Sorry for being slow on the reply. If you still need help with this, I managed to fix this by changing the "none_to_float" function around line 173 to

def none_to_float(param):
                if param is None:
                    return 0.0
                if isinstance(param, position):
                    return param.relative
                return param

Think that should help make it not crash anymore.

Oh yeah I think before it was 'h' for height but I changed it to 'a' for amplitude to be more in line with the others. I'll try to have that fixed next time I work on it. Thanks for letting me know!

I should be upfront that I am friends with many of the developers, and some of my code is used in the game, though I had little to no direct involvement. So to be fair, I will mention any problems I have, even if nitpicky. 

That said, this is still one of the best quality VNs I've played in a while. A full course meal in a very digestible size. There is room to expand, but for a game made in a month, I'm happy with it, leaving me wanting more. The level of polish of what it there more than makes up for any shortcomings. 

The story is a fun murder mystery with a cast I would consider large for the limitations. Twelve speaking characters is a lot to flesh out in a 2-3 hour story while weaving in clues and hints. I might critique that it would be nice to get more from some of the characters, but it likely would have made it harder to keep track of all the elements within the limitations. Though the main cast of the living feel well developed enough to carry it, and the number of characters makes it a good popcorn read with friends. The path to the true ending has one complication that I feel could be smoothed out, but the steps to it are not difficult to reach otherwise. The balance of comedy and horror walks a fine line, having dark subject matter kept digestible with a deft attention to the tone. Characters who have done awful things are fun to watch bounce off Maxwell, who keeps a level head through it all. 

All of the visuals are fantastic. Each sprite feels unique and has plenty of fun expressions to elevate their lines. Backgrounds are high quality, though the storage room and attic bg are a bit too similar imo. Also feels like maybe one or two more CGs were desired but likely were cut, though I'm glad the CGs that are there leave great impact and were worth prioritizing. The UI is very clear with plenty of style and polish. I'm especially impressed that the textbox manages to make lines bordering on a paragraph feel readable, even though lines that long are rare (which is a good thing).

All of the music is fantastic and perfectly fits the mood. The inclusion of a fully original soundtrack really elevates each scene. The sound design is also deserving of praise, with meaty thuds and every step appropriate to the room. Sorry, I'm not very articulate with sound stuff, but all of it is a cut above even VNs made with more time and budget.

I'm not sure why a game jam would have a voice acting category. The inclusion of sounds for the text appearing though is always fitting, and I will consider it close enough. The UI sounds can be a tad loud by default, but easy enough to turn them down to your preference. None of it was beneath the standard of the rest of the experience.

Cinematography is fantastic as always from Domn. His skill he's wielded upon Crypid Crush is in full effect to make scenes fun and bouncy when appropriate, and spooky and mysterious when needed. I especially enjoy the zoom in on the character introductions, which looks fantastic. The scene transitions are also very fun to see, and I appreciated their style. Only nitpick is some transitions between selecting someone to talk to or a topic and a dissolve into the conversation, where it feels odd the characters shift a small amount, even with the dissolve to smooth between them. Though fixing them would be an effort that is better spent after the jam is concluded.

Outside of the normal ratings, I have some small critiques, though most of them would be better saved for the post-jam version. I've seen one person have an issue with navigating between the rooms. I would recommend a map to select between scenes, even if some rooms are locked, better to just see all options than using the choice screen that is limited. Fixing choice menus to grey out previously selected options will be a nice QoL move. And the handful of typos and times a tooltip clips the UI were never major issues that held back the overall experience. 

That all said, the project is a fantastic piece of spooky fun that I think makes for a fun read for the season. I look forward to recommending it every year for a fun, spooky romp. The passion and love put into every piece is on full display, and I'm left only wanting more from these characters and the world. Let's all hope the creators can come together to make more of this exceptional story and world.

I should be upfront that I am friends with many of the developers, and some of my code is used in the game, though I had little to no direct involvement. So to be fair, I will mention any problems I have, even if nitpicky. 

That said, this is still one of the best quality VNs I've played in a while. A full course meal in a very digestible size. There is room to expand, but for a game made in a month, I'm happy with it, leaving me wanting more. The level of polish of what it there more than makes up for any shortcomings. 

The story is a fun murder mystery with a cast I would consider large for the limitations. Twelve speaking characters is a lot to flesh out in a 2-3 hour story while weaving in clues and hints. I might critique that it would be nice to get more from some of the characters, but it likely would have made it harder to keep track of all the elements within the limitations. Though the main cast of the living feel well developed enough to carry it, and the number of characters makes it a good popcorn read with friends. The path to the true ending has one complication that I feel could be smoothed out, but the steps to it are not difficult to reach otherwise. The balance of comedy and horror walks a fine line, having dark subject matter kept digestible with a deft attention to the tone. Characters who have done awful things are fun to watch bounce off Maxwell, who keeps a level head through it all. 

All of the visuals are fantastic. Each sprite feels unique and has plenty of fun expressions to elevate their lines. Backgrounds are high quality, though the storage room and attic bg are a bit too similar imo. Also feels like maybe one or two more CGs were desired but likely were cut, though I'm glad the CGs that are there leave great impact and were worth prioritizing. The UI is very clear with plenty of style and polish. I'm especially impressed that the textbox manages to make lines bordering on a paragraph feel readable, even though lines that long are rare (which is a good thing).

All of the music is fantastic and perfectly fits the mood. The inclusion of a fully original soundtrack really elevates each scene. The sound design is also deserving of praise, with meaty thuds and every step appropriate to the room. Sorry, I'm not very articulate with sound stuff, but all of it is a cut above even VNs made with more time and budget.

I'm not sure why a game jam would have a voice acting category. The inclusion of sounds for the text appearing though is always fitting, and I will consider it close enough. The UI sounds can be a tad loud by default, but easy enough to turn them down to preference. None of it was beneath the standard of the rest of the experience.

Cinematography is fantastic as always from Domn. His skill he's wielded upon Crypid Crush is in full effect to make scenes fun and bouncy when appropriate, and spooky and mysterious when needed. I especially enjoy the zoom in on the character introductions, which looks fantastic. The scene transitions are also very fun to see, and I appreciated their style. Only nitpick is some transitions between selecting someone to talk to or a topic and a dissolve into the conversation, where it feels odd the characters shift a small amount, even with the dissolve to smooth between them. Though fixing them would be an effort that is better spent after the jam is concluded.

Outside of the normal ratings, I have some small critiques, though most of them would be better saved for the post-jam version. I've seen one person have an issue with navigating between the rooms. I would recommend a map to select between scenes, even if some rooms are locked, better to just see all options than using the choice screen that is limited. Fixing choice menus to grey out previously selected options will be a nice QoL move. And the handful of typos and times a tooltip clips the UI were never major issues that held back the overall experience. 

That all said, the project is a fantastic piece of spooky fun that I think makes for a fun read for the season. I look forward to recommending it every year for a fun, spooky romp. The passion and love put into every piece is on full display, and I'm left only wanting more from these characters and the world. Let's all hope the creators can come together to make more of this exceptional story and world.

You can use it commercially. I'd appreciate a thanks in the credits if you can but I'm not too worried about it. Just hope it helps!

Yeah if you want to do this with individual images, you'll have to do something like.

image eileen happy = At('eileen_happy', sprite_highlight('eileen'))
image eileen sad = At('eileen_sad', sprite_highlight('eileen'))
# Or, if you'd want an ATL example 
image eileen happy: 
    'eileen_happy' 
    function SpriteFocus('eileen')

It's definitely more cumbersome but I don't have a lot of good ways of working around this. Hope this helps though.

Main way to do this would be to define your character like 

define both = Character('Both', callback=name_callback, cb_name=['char1', 'char2'])

Hope that helps!

I probably should put out a patch but think if you fix my DispTextStyle code on line 72 to be

self.tags[tag] = value

and update whatever tag you're using by replacing a

char_text = Text(my_style.apply_style(char))

with

if "" in my_style.tags:  
    char_text = Text(my_style.apply_style(char), style=my_style.tags[""])
else:
    char_text = Text(my_style.apply_style(char))

You should see some improvement. Hope that helps.

I didn't originally add a speed setting to the ScareText admittedly but it wouldn't be hard to add if you wanted. To just slow it down, all you need to do is to change the renpy.redraw(self, 0) in the render function to be something like renpy.redraw(self, 1./30) or something. The '0' tells renpy to redraw this element every frame, so if you have a high frame rate, it'll update very quickly. Putting a fraction there tells it to wait until [fraction] has passed.

You can't really tell it to every 5 frames sadly because, if the frame rate is high, 5 frames might not be a lot anyway. So what you really want is a rate. You can play around with what speed you want but you can try .1 or .05 if you want. Or if you just want division, just do 1./12 for a twelth of a second (I recommend adding the '.' because it tells python to do floating point division instead of integer).

For adding it as a parameter though, you can add that by doing something like.

def scare_tag(tag, argument, contents):
        new_list = [ ]
        if argument == "":
            shake = 5
            speed = 1./30
        elif '-' in arguemnt:
            shake, _, speed = argument.split('-')
            shake = int(shake)
            speed = float(speed
        else:
            shake = 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 = ScareText(char_text, shake, speed)
                    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

for the tag and then

class ScareText(renpy.Displayable):
        def __init__(self, child, shake=2, speed=1./30, **kwargs):
            super(ScareText, self).__init__(**kwargs)
            self.child = child
            self.shake = shake # The size of the square it will wobble within.
            self.speed = speed
            # 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.shake)
            yoff = (random.random()-.5) * float(self.shake)
            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, self.speed)
            return render
        def visit(self):
            return [ self.child ]

for the class. I haven't tested that code myself so you might need to fix it if I missed a bug but I think it's good to learn how to debug stuff. Hope this helps and you're able to get it to work how you want it to!

You'll need to just combine them together. I'm currently at a con but I could make an example when I get back. 

You can see examples of their use in the script.rpy

(2 edits)

The problem is that you put everything inside the _() function. So you need to move the first ')'

define sa = Character(_('Sasha', callback = name_callback, cb_name = "Sasha"), color="#efe49c")

It should be:

define sa = Character(_('Sasha'), callback = name_callback, cb_name = "Sasha", color="#efe49c")

I think you copied it from my script.rpy file which was just examples. You can remove the {=test_style} from inside the tag.

You are free to modify it but yeah most of them don't put much of a delay on the effects. And the looping is just because they keep updating themselves as renpy calls them. I imagine you're looking to modify the SwapText though and you're free to modify that to how you want it to work. It uses it's swap_to_1 variable to keep track of which character it should be. So probably just need to treat the current timer variable it has to be a delay instead and remove the logic for switching back. Might need to add more code in there too if you want more than just the letter swap. Hopefully that helps though.

I never wrote down a cheat sheet but you can rename them to what is easiest for you to remember yourself if you want. Nothing wrong with making it easier for yourself.

I've never had it flat out refuse to work. My best guess would be maybe your sprites are sharing names that are used to look up which to highlight. Having two sprites referring to the same one can often make it act screwy. Could be something else. but without more information about what's going on, that's my best guess.

Weirddd.... Could try regenerating the rpyc file. That or you could just move most of the code from one to the other.

I've never tested it with that but I'm down to work with you to try and find a fix. I'll try and see about it this week but if you wanna chat on discord or something so can maybe help me know your setup to better help.

Yeah, the kinetic text tags are a displayable being shown as part of an overall text displayable, but that text displayable doesn't know to pass it's style information down to the kinetic text tag's text. My solution to this was defining a style with all the properties you want, and then using the {=style} tag (https://www.renpy.org/doc/html/text.html#style-text-tags) INSIDE the kinetic text tag to carry that information in. While going through the text it's given, my text tags will try to keep track of other tags inside it and apply them to their text. So you'd want to do something like 

style narr_text_style:
    color "#fff"
    outlines [(2, "#000000")]
    size 1900
    font "fonts/DisgustingBehavior-AZrA.ttf"
"{sc=10}{=narr_text_style}{outlines}No! You just don't want me to be happy!{/sc}"

Not sure the style tag applies all of that attributes, especially outlines, or if that will necessarily work entirely. Though that's the general way I made it work.

While looking into this though I did learn that renpy now has some of this stuff built in. https://www.renpy.org/doc/html/textshaders.html So if it's not working it might be worth using their jitter instead.

Sorry, I can't say I tested it very extensively in NVL mode. I'll try to make a note to look into it more later. I have some guesses as to what the issue might be. I know Renpy likes to reset the whole textbox in ADV mode whenever it updates, so maybe it does something similar in NVL mode. If true, then the time being given to the displayables would be reset and not a lot I could do about that outside of awkwardly storing timers in globals in a way that'd be really messy. Though given your description, it that might not be the case and could be something else. I'll try to look into it when I have time but been busy lately.

I'll say I'm not entirely sure what you're asking, From the sounds of it, you're asking to have the shake and gradient tags moved to their own files. You are free to remove those sections are put them in their own .rpy file if you like, but I'm not sure how that will help you. If you're wondering how to use them, you just do "{sc}Some text{/sc}" for the scare tag, and the gradient tag is a bit harder, though I believe I provided some examples and reference for it in the comments of gradient_tags.rpy. Hopefully that helps but if you need more help feel free to ask!

By default I haven't added something like that yet. But it can be easily patched in by modifying 

if isinstance(sprite_focus, list):
    is_talking = char_name in sprite_focus
else:
    is_talking = char_name == sprite_focus

then passing a list of names for the cb_name I believe.

Like it cycles through multiple fonts before settling on one or each letter is a different random font?

Mostly just would be having it so the letters keep some kind timer, randomly going through characters until the timer hits zero and then just shows the actual letter. Though if you do need me to do it I'll note it down and let you know when I can get to it later.

(1 edit)

No, I've never directly made an effect like that, but with my setup, it wouldn't be hard to make one if you know what you want and have some coding experience. Could maybe make one if you need though, but currently busy with another project so can't promise anything for a bit if you need it right now.

Sorry about that. Yeah I've had that issue sometimes crop up. Usually though it's when I'm having another auto talking solution going on as well. If I ever find a solution to that though I'll be sure to let you know.

If I had to guess I would presume it's because when the scene starts, the character hasn't been speaking, so the speaking_char is probably either None or someone else. Then when the line starts, the character is then set as the speaking_char, so he lights up to normal. If you want them to start off already focused, you can manually set the speaking char by doing:

$ speaking_char = "guard1"

either before the transition or sometime during it. Which would then have the sprite start off in the talking state.

Hopefully that helps. But if it's some other issue, let me know and I'd be happy to help correct it.

You can probably have the glitch go slower but changing the redraw time. Maybe something like 1./30 instead of 0 if you just want it at 30 fps or just .2 or something if you need it slower. It'll be the renpy.redraw(self,[new number here]) bit.

I'd need to know more about your project to know what might be the issue.

Ah so you got it fixed?

You'd probably need to add a flag to each text tag function or class to tell it to do more default behavior. Will need to make it a persistent or preference variable as well so it is always accessible.

Sorry for the late reply. But yeah you need to have the base kinetic_text_tags.rpy in there as well since it contains the DispTextStyle class which helps the text tag function handle other text tags. That or you can copy it from there into that file if it's the only thing you need.

Hi. Sorry for the late reply. I tried replicating the issue on my end, but doing the same setup (or at least what I can suppose from your comment) yielded results that looked correct to me. My best guess for the issue is that something about how you defined the sprites is causing renpy to reset the anim_time value, which would cause the sprite_highlight function to snap to the highlighted value. Which maybe you're confusing for the .2 seconds given .2 is pretty fast. Though I could be wrong. This is just my best guess given the information.

I tested with NVL and that didn't seem to make much of a difference. If you'd want to show me your code so I could test it and see what the issue might be, I'd be happy to take a look when I have time. (My username on discord is wattson if you need to reach out). But yeah I'm not entirely sure what the problem might be beyond my guess. Hope this was helpful and a solution to your issue can be found!

Hi. Sorry for taking a bit to get back to you. But yeah I appreciate you wanting to edit it to be easier for non-programmers to read it. I will admit I did my best when writing the original code to try and make it approachable as I could. If you have ideas on how to make it more approachable, I'd be happy to take feedback and upload a modified version on here with credit to you for the help. But if you're not making significant changes to the functionality and just adding comments, I feel like it'd be best to just have one project up. Sent a friend request on discord so we can chat more about it. Thanks for your feedback.

- Wattson

Yes. But you'll also need to make changes to your layeredimage sprites to work with it in order for it to work. Instructions and examples on how to do it can be found in the example project.

1. You'll probably need to add the glitch tag to the DispTextStyle class as part of the custom tags. That way it'll try and add it to every letter more or less. 

2. Depends on what you want to do with the swap text. You'll probably want to update the SwapText class at least to take a list of texts to do. And then tell it to keep track of which one is being shown and increment it when you want it to go to the next one. But yeah the details from there are up to how you want to do it.

Sure I'll see what I can do about that. The main reason I split them up was originally to make it more modular. So if you didn't need every tag, you could pick and choose which you want, without it becoming a 1000+ line script file to go through. But given how many of my custom tags use the DispTextStyle class to handle other tags, probably makes sense to just lump them into one. So ppl just need to download one file even if they don't use all of them. I've just been pretty busy lately with my actual job and life stuff, so I'll see about when I get around to updating it. Probably when I have enough free time to work on another tool I've been meaning to release for a while.

Can you not use matrixcolor to accomplish the same thing?

The text's default position is going to be relative to where it would normally be placed on the screen. I don't know which specific tag is giving you problems, but I will guess it's the ATL tag. Depending on the values you give it, you may just be offsetting it too much and might want to bring them down closer to 0. Hard to know what exactly is the problem without more details, but hope you're able to get it fixed.