Visual Novel Tips and Tricks with Gabmag #2

Hello again everyone!

Today I have another blog post answering some of your questions from our CuriousCat. Thank you all again for sending in these questions, and you can still send in more if you need help with anything.

Let’s get straight into the first question.

I read your last blog and I'm not too sure how layeredimages and sprites work, especially side images (of a character who would show up in the lower left hand corner). Could you explain? Thanks!

Thank you for the question! I’d be happy to go over the multiple ways you can program your sprite, as well as how side images work. 

First of all, lets start with sprites. There’s a couple of ways you can program them, depending on how space savvy you need to be.

Using Whole Images

If you don’t have many characters, and space isn’t an issue, you can use WHOLE sprites in your game. This means each different expression includes the whole sprite (the body, the hair, etc.) compared to having it broken up into parts.

This is the easier way of doing things, but the amount of space it uses can quickly add up if you have a lot of different sprite variations.

First of all, inside your images folder you can make another folder, called “sprites”. If you want to be extra neat, inside that folder you could dedicate another folder per character. In this example, we’ll make a folder inside of “sprites” called “John”.

 

As you can see above, we have three sprites in John’s folder. 

In this case, they are full body sprites, a bigger size than the game will need. If you want to save extra space, and you won’t use the full body at any point in time, you can use a different program (like photoshop) to crop and resize the image.

Next, we will create a new .rpy file called “sprites”. Save it in your game folder. This is just to keep things neat. You could also put it at the top of your script.rpy folder, before label start.

If you’ve already cropped and scaled them to the correct size, then this is the code you will need to add them in:

######## John Sprite ########
image john confident = "sprites/John/John_Confident.png"
image john embarrassed = "sprites/John/John_Embarrassed.png"
image john flirty = "sprites/John/John_Flirty.png"
 

If you’re using full body, larger sprites, this is the code we’ll need. Please note that you will need to mess with the numbers a lot depending on what size canvas your sprite is on:

######## John Sprite ########
image john confident:
    im.Crop("sprites/John/John_Confident.png", (0, 0, 1000, 1200)) # crops the image (x, y, width, height)
    zoom 0.8

image john embarrassed:
    im.Crop("sprites/John/John_Embarrassed.png", (0, 0, 1000, 1200)) # crops the image (x, y, width, height)
    zoom 0.8
    
image john flirty:
    im.Crop("sprites/John/John_Flirty.png", (0, 0, 1000, 1200)) # crops the image (x, y, width, height)
    zoom 0.8
 

To make the above to work, play around with the zoom until you get a scale you would like to work with.

You will also need to play around with the (0, 0, 1000, 1200). Leave the first two at zero. The third number (the width) should be large enough to show the whole sprite sideways.

The last number (height) is the most important one. This is where your sprite will be cut off. Try it first at 1200 and work out if you want to show more or less. If you want to show less of the sprite, make the number smaller. If you want them to be taller/the crop to be further down, make the number bigger.

Then, it’s as simple as “show john flirty” to show your sprite!

Using LayeredImage

LayeredImages might be a little daunting at first, but once you’ve done a couple of them, you’ll see how simple they really are.

This is easiest to do if your artist gives you the PSD and puts the base body, hair and expressions on different layers.

Here’s what we’ll use in this example:

 

As you can see, we have the base body (a single outfit, but it also works if you have multiple), two expressions, one hairstyle plus a bonus clothing item, a cloak. 

First of all, we’ll save them all into a folder in our game files. This will be “images/sprites/raen”.

With the files prepared, we can now begin programming. As above, I will first go through the code you will use if you have ALREADY cropped the images to the correct size (not using full body sprites).

##### RAEN Sprites #####

layeredimage raen: # names the layeredimage sprite raen

    always:
        "sprites/raen/raen_base.png" # ALWAYS show Raen's body

    group face: # Here we put all the sprite expressions
        attribute neu:
            "sprites/raen/raen_neutral.png"
        attribute smi:
            "sprites/raen/raen_smile.png"

    group hair: # Here we put his hair - because it's under the "face", it will show on top of the expressions.
        attribute hair default: # We set it to default so it will always show. You can put other hairstyles here, too.
            "sprites/raen/raen_hair.png"

    group cloak: # Here we put the cloak accessory. It is NOT set to default or always, so it will only show when we tell it to.
        attribute cloak:
            "sprites/raen/raen_cloak.png" 

Then, we call it the same as normal. Here’s a few different combinations we could have.

label start:
    show raen neu # shows Raen's neutral expression
    show raen smi cloak # show Raen's smiling expression, plus his cloak
    show raen smi -cloak # removes the cloak
 

If you’re using full body sprites, bigger than the size of the screen, here is the code you will need. Note again that you WILL need to play with the numbers to fit them to your sprite size.

##### RAEN Sprites #####
layeredimage raen:

    always:
        zoom 0.63
        im.Crop("sprites/raen/raen_base.png", (0, 0, 1000, 1400))

    group face:
        zoom 0.63
        attribute neu:
            im.Crop("sprites/raen/raen_neutral.png", (0, 0, 1000, 1400))
        attribute smi:
            im.Crop("sprites/raen/raen_smile.png", (0, 0, 1000, 1400))

    group hair:
        attribute hair default:
            zoom 0.63
            im.Crop("sprites/raen/raen_hair.png", (0, 0, 1000, 1400))

    group cloak:
        attribute cloak:
            zoom 0.63
            im.Crop("sprites/raen/raen_cloak.png", (0, 0, 1000, 1400)) 

As you can see, the only change we’ve made is to add a “zoom” and to crop the image to only show half body/down to thigh.

Using LayeredImages, you can also further split up your sprites. Instead of having entire expressions, you could split them down to eyes, mouth, eyebrows, etc. and have any number of combinations! 

You can also add any number of extra items. Different outfits, different arm placements, different hairstyles – the sky is the limit.

Side Images

If you’ve gotten this far, don’t worry – side images are very easy! 

Firstly, we need to declare which side image belongs to which character. We do this in the character declarations, like this:

 

define r = Character("Raen", image="raen") 

Now, the character Raen will be linked to the side image raen, which we will set up now, like this:

# Raen Side Images

image side raen neu = "raen neu"
image side raen smi = "raen smi"
 

As you can see, this sets his side image to use his sprite declarations we did in the previous step. You need one side image per expression.

Then, all you need to do to show the side image is:

label start:
    r neu "This is me speaking." 

Ta da! Raen’s little face will now be showing in the corner of the screen. We just use the letter we defined his character as (r) and the expression we want (neu).

Now, there is probably a couple of other settings you’ll want to change, so I’ll go over them too.

Firstly, if you want to change the position of the side image (move them further up, further down, left/right, etc) we will want to change or delete a line in “screens.rpy”.

In this case, we will delete it, as we want to choose the position of EACH characters side image individually.

Firstly, here is the code you will want to remove:

if not renpy.variant("small"):
        add SideImage() xalign 0.0 yalign 1.0 

Simply delete or hash out the part that says “xalign 0.0 yalign 1.0”. Alternatively, you can adjust these numbers if you want every sprite at the exact same location. 

One reason you may not want this is if you have characters of varying heights, and you want all of their side images to be the same height.

If you’ve chosen to delete this number instead of altering it, next we will make a small change to our side image declarations:

# Raen Side Images

image side raen neu = Transform("raen neu", yalign = 3.0, xalign = -0.10)
image side raen smi = Transform("raen smi", yalign = 3.0, xalign = -0.10) 

Again, you will need to play with these numbers.

The other setting I wanted to bring up was the option to turn OFF side images for characters that already have a sprite on screen. If you want side images to show for every character whether they are on the screen or not, then you can ignore this.

If you want to turn it off, then this is the code you need to add (you can put it in options.rpy, or somewhere else!):

 

define config.side_image_only_not_showing = True 

Phew, I think that’s everything on side images! If you have any further questions or you need help, feel free to send me a message.

Whats the most difficult part about making a game with NSFW?

This is a hard question! I think mostly this will be my opinion on what I’ve found difficult in my experience.

Firstly, I have to state that I am new to writing NSFW, and this was the first struggle. In fact, I didn’t even read fanfiction, so I had to do a lot of research into NSFW writing, and even now I’m still slowly improving.

The next thing I found difficult was deciding how many NSFW scenes there should be per route. When I started The Divine Speaker and I was new to visual novel development, I thought the more I could put in, the better. I was thinking of 3-5 per route without even batting an eyelid. Only when I came to planning these scenes did I see how huge of a task this was. 

The Divine Speaker is a story-centric game. It doesn’t focus on the relationships alone, so I didn’t want to overwhelm the routes with so many sex scenes that we lost sight of the story and characters. That’s definitely something you want to keep in mind – is there more sex than story? Maybe that’s what you want, and that’s fine, but a balance is always good.

In the end, there is 3 sex scenes per route, plus 2 secret sex scenes in the game, making a total of 11. I never want to write so many again, and this is nothing compared to some other games! On the other hand, I am now a lot more confident in them than before, so I guess practice makes perfect.

Next, I didn’t want to make sex scenes for the sake of having them. I wanted them to be connected to the story, to mean something. I think I managed to achieve this, although it was definitely difficult at times, and some scenes are more connected than others.

Lastly, unrelated to writing, your artist definitely has to be good with posing, angles and drawing the act. Make sure to confirm with your artist before hiring if they’re okay with NSFW.

For someone making a NSFW game, I still struggle to read back my writing because of embarrassment, so maybe I’m not the best person to ask, hahaha!

How do you achieve the choices where you can pick multiple options, and the ones you already picked disappear?

Hey there! I’m glad you asked, because I find this a really interesting way of letting the player choose how much lore they want to consume. It feels very RPG-like! It is also great on subsequent playthroughs, since players can choose to skip the dialogue if they’ve already read it. 

Firstly, I’ll show you the code to do the following:

  • Show a menu with two options.
  • Once an option is chosen, hide it.
  • Once you’ve chosen AT LEAST one other option, an option to skip appears.

After, I’ll explain in detail how it works.

#### Looping Menu Code ####

define option1_unchosen = True 
define option2_unchosen = True
define skip_choices = False 
define choice_counter = 0

label choice_test:

    if choice_counter == 2: # If both menu options have been chosen, skip the menu and jump to after it.
        jump labelhere3 
        
    else:    # If there's at least one menu item to be picked, show the menu.
        menu:
            "Option 1 here" if option1_unchosen: # if option 1 hasn't been picked before, show this option.
                $ option1_unchosen = False 
                $ skip_choices = True
                $ choice_counter += 1
                jump labelhere1
            
            "Option 2 here." if option2_unchosen: # if option 2 hasn't been picked before, show this option.
                $ option1_unchosen = False
                $ skip_choices = True
                $ choice_counter += 1
                jump labelhere2
                
            "Skip the choices" if skip_choices: # If at least one other option has been chosen, show this option.
                jump labelhere3

label labelhere1:
    "You will get this text if you select option 1."
    jump choice_test # jump back to the menu

label labelhere2:
    "You will get this text if you select option 2"
    jump choice_test # jump back to the menu

label labelhere3:
    "You will get this text if you select 'skip the choices' OR if the counter reaches 2." 

It looks like a lot, but it’s very simple when you get into it.

Firstly, we need to define a number of variables. You need one “unchosen” variable per choice.

This variable changes to False once you select it, which then hides the option in the menu, stopping players from chosing the same choice more than once.

Next we make a “skip_choices” variable, which we set to False. Once you pick ANY other option in the menu, this will be set to True, letting players choose to skip the menu.

Lastly, we need a counter that counts every time an option in the menu is chosen. We need this because we don’t want the menu to show if there’s no other options to be chosen. 

Once we’ve finished with declaring the variables, we need to make a new label. In this example, it’s called choice_test. This is so we can jump back to the menu when needed.

Inside this label, we first put a little failsafe. “if choice_counter ==2”.

This means that if both options in the menu have been chosen, you will skip the menu and jump straight to labelhere3, where the game will continue. Otherwise, if it equals 0 or 1, it will show the menu.

If you choose to have more than two options, then you will need to adjust this number to match. 

Finally, we get to the menu. Only option 1 and 2 will show at first, and they only show as long as their respective variables = True. 

As you can see, once you select an option it will do the following:

  • Set the respective variable to False (stopping it from showing next time).
  • Set skip_choices to True (allowing the third option, “Skip the choices”, to show next time.)
  • Adds one point to the choice_counter. Once this reaches two, the menu will be skipped when returned to.
  • Jumps to a different label. At the end of that label, it will jump back to the menu.

And that’s how you do it! You can do this with any number of menu options. You just need to define a new variable per menu item, and change the number in choice_counter to match.

Feel free to copy the above code into your game to test it.

 

That’s all the questions I’ll be answering for now. I’m still taking more to answer in the future, which you can submit here! It can be on any topic to do with visual novel development, and I’ll try my best to answer.

 

 

Visual Novel Tips and Tricks with Gabmag #2
Scroll to top
Join Waitlist We will inform you when the product arrives in stock. Please leave your valid email address below.