[SOLVED]Changing Sprites in-game

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.
Message
Author
User avatar
drbugs
Newbie
Posts: 13
Joined: Sat Nov 14, 2020 10:27 am
Contact:

[SOLVED]Changing Sprites in-game

#1 Post by drbugs » Sun Nov 15, 2020 6:50 pm

I'm making a game that combines some old visual novels I made along with a new game.
I'm planning on remaking all the sprites, but would love to have an option for players to change sprites at will during gameplay (For example, how you can change sprites in Umineko on Steam).
I know how to set it up so that you can choose old or new sprites from a menu when you start the game, but that will lock you into only one sprite choice, and I'd rather they have freedom to change on the fly. The only other thing I can think of is one that won't keep your place in the game, so that's not good either.
I tried to look at img layering but I'm not sure if that's exactly what I'm after (as the sprites are very different looking).

Hope this makes sense! Thanks in advance.
Last edited by drbugs on Wed Nov 25, 2020 4:19 pm, edited 1 time in total.

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

Re: Changing Sprites in-game

#2 Post by Imperf3kt » Sun Nov 15, 2020 7:24 pm

Maybe try using conditionswitch?
Warning: May contain trace amounts of gratuitous plot.
pro·gram·mer (noun) An organism capable of converting caffeine into code.

Current project: GGD Mentor
Free Android GUI - Updated occasionally
Twitter
Imperf3kt Blackjack - a WIP blackjack game for Android made using Ren'Py

User avatar
_ticlock_
Veteran
Posts: 391
Joined: Mon Oct 26, 2020 5:41 pm
Contact:

Re: Changing Sprites in-game

#3 Post by _ticlock_ » Mon Nov 16, 2020 12:51 am

Conditionswitch is really good. If you have too many sprites to choose from, then maybe DynamicDisplayable. Here is what I used for DynamicDisplayable to support the show and say statements with sprites. (For images with names eileen.png, eileen_happy.png etc.)

Code: Select all

define e = Character("Eileen", image="eileen")

init python:
    def update_npc(st, at, mood = ''):
        global eileen								
        return eileen + mood + '.png' , None   					

image eileen = DynamicDisplayable(update_npc, mood = '')
image eileen happy = DynamicDisplayable(update_npc, mood = '_happy')
image eileen sad = DynamicDisplayable(update_npc, mood = '_sad')

image side eileen = DynamicDisplayable(update_npc, mood = '_side')
...

label change sprite:
    ...
    $ eileen = "eileen"

User avatar
drbugs
Newbie
Posts: 13
Joined: Sat Nov 14, 2020 10:27 am
Contact:

Re: Changing Sprites in-game

#4 Post by drbugs » Wed Nov 18, 2020 1:21 am

Thank you for the suggestions!
Unfortunately, I'm not super ren'py savvy so I don't exactly understand how to apply them.
I read a little tutorial on conditionswitch, and it does sound good, but I don't know how to make it happen via a menu command.
It sounds like DynamicDisplayable would be what I need, as there's a lot of sprites to change, but unfortunately I don't really understand the code, sorry!

My main concern is how to change the sprite without it jumping to some different point in the script...

User avatar
_ticlock_
Veteran
Posts: 391
Joined: Mon Oct 26, 2020 5:41 pm
Contact:

Re: Changing Sprites in-game

#5 Post by _ticlock_ » Wed Nov 18, 2020 12:11 pm

ConditionSwitch:
Let's say you have a variable mc_sprite, that controls which sprite is chosen:

Code: Select all

image mc_image = ConditionSwitch(
        "mc_sprite == 1", "mc_sprite_001.png",
        "mc_sprite == 2", "mc_sprite_002.png",
        )
All you need to change the sprite from old one to new one is to change value of the mc_sprite. You can change this variable using textbutton or imagebutton:

Code: Select all

screen choose_mc_sprite:
    modal True
    vbox:
        imagebutton:
            idle 'mc_sprite_001.png'
            action [SetVariable('mc_sprite', 1), Hide("choose_mc_sprite")]
        imagebutton:
            idle 'mc_sprite_002.png'
            action [SetVariable('mc_sprite', 2), Hide("choose_mc_sprite")]
You can Show this screen from any game menu/screen:

Code: Select all

textbutton _("Choose mc sprite") action Show("choose_mc_sprite")
DynamicDisplayable:
Let's say you have a variable mc_sprite, that controls which sprite is chosen. For example, mc_sprite = "mc_sprite_001"

Code: Select all

init python:
    def update_mc_sprite(st, at):
        global mc_sprite								
        return mc_sprite + '.png' , None   					

image mc_image = DynamicDisplayable(update_mc_sprite)
Again to change the sprite we change mc_sprite:

Code: Select all

imagebutton:
    idle 'mc_sprite_002.png'
    action [SetVariable('mc_sprite', 'mc_sprite_002'), Hide("choose_mc_sprite")]
Sprite mood:
if you want to use a different mood you need to define images for different moods in a similar manner. In the case of DynamicDisplayable something like this:

Code: Select all

init python:
    def update_mc_sprite(st, at, mood = ''):
        global mc_sprite								
        return mc_sprite + mood+ '.png' , None   					

image mc_image = DynamicDisplayable(update_mc_sprite)
image mc_image happy = DynamicDisplayable(update_mc_sprite, mood = 'happy')
Hope, it makes more sense now :)

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

Re: Changing Sprites in-game

#6 Post by Imperf3kt » Wed Nov 18, 2020 2:51 pm

You can also set ConditionSwitch without using a screen by using python. For example,

Code: Select all

$ mc_sprite = "1"
Warning: May contain trace amounts of gratuitous plot.
pro·gram·mer (noun) An organism capable of converting caffeine into code.

Current project: GGD Mentor
Free Android GUI - Updated occasionally
Twitter
Imperf3kt Blackjack - a WIP blackjack game for Android made using Ren'Py

User avatar
drbugs
Newbie
Posts: 13
Joined: Sat Nov 14, 2020 10:27 am
Contact:

Re: Changing Sprites in-game

#7 Post by drbugs » Wed Nov 18, 2020 8:20 pm

So, I'm trying the condition switch because it makes the most sense to me (despite my attempts, I guess I unfortunately am not code-minded...), but when I try to swap sprites, I get this:

"I'm sorry, but an uncaught exception occurred.

While running game code:
File "game/6pm1 Script.rpy", line 140, in script
A "Oh."
File "renpy/common/00action_data.rpy", line 79, in get_selected
return __get_field(self.object, self.field, self.kind) == self.value
File "renpy/common/00action_data.rpy", line 39, in _m1_00action_data__get_field
raise NameError("The {} {} does not exist.".format(kind, name))
NameError: The variable mc_sprite does not exist."

I assume I have to add something in the 00action_data document but I don't really know what, nor do I want to randomly tinker with a renpy program file in case I break something...

User avatar
_ticlock_
Veteran
Posts: 391
Joined: Mon Oct 26, 2020 5:41 pm
Contact:

Re: Changing Sprites in-game

#8 Post by _ticlock_ » Wed Nov 18, 2020 10:53 pm

drbugs,

Sorry about that. You need to define mc_sprite for default value. Just add this line after label start:

Code: Select all

label start:
    $ mc_sprite = 1

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

Re: Changing Sprites in-game

#9 Post by Imperf3kt » Wed Nov 18, 2020 11:22 pm

_ticlock_ wrote:
Wed Nov 18, 2020 10:53 pm
drbugs,

Sorry about that. You need to define mc_sprite for default value. Just add this line after label start:

Code: Select all

label start:
    $ mc_sprite = 1
This is not the recommended way to default variables as it introduces errors when saving/loading games.

The suggested way to do it is to define the sprite with default outside any label / block.

Code: Select all

default mc_sprite = 1

label start:
    "stuff" 
Warning: May contain trace amounts of gratuitous plot.
pro·gram·mer (noun) An organism capable of converting caffeine into code.

Current project: GGD Mentor
Free Android GUI - Updated occasionally
Twitter
Imperf3kt Blackjack - a WIP blackjack game for Android made using Ren'Py

User avatar
_ticlock_
Veteran
Posts: 391
Joined: Mon Oct 26, 2020 5:41 pm
Contact:

Re: Changing Sprites in-game

#10 Post by _ticlock_ » Thu Nov 19, 2020 11:52 am

Imperf3kt wrote:
Wed Nov 18, 2020 11:22 pm
This is not the recommended way to default variables as it introduces errors when saving/loading games.

The suggested way to do it is to define the sprite with default outside any label / block.
Imperf3kt,

Thank you for the correction. I actually thought it gives almost the same result. Can you shortly explain (or just a link) why it introduces errors when saving/loading games (or other possible errors). Also, is it recommended to do with all variables or types of variables?

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

Re: Changing Sprites in-game

#11 Post by Imperf3kt » Thu Nov 19, 2020 2:47 pm

viewtopic.php?f=8&t=42245
This isn't the best link though.

Its to do with how renpy loads a saved game and when the variable is created.
Warning: May contain trace amounts of gratuitous plot.
pro·gram·mer (noun) An organism capable of converting caffeine into code.

Current project: GGD Mentor
Free Android GUI - Updated occasionally
Twitter
Imperf3kt Blackjack - a WIP blackjack game for Android made using Ren'Py

User avatar
_ticlock_
Veteran
Posts: 391
Joined: Mon Oct 26, 2020 5:41 pm
Contact:

Re: Changing Sprites in-game

#12 Post by _ticlock_ » Thu Nov 19, 2020 5:32 pm

Imperf3kt wrote:
Thu Nov 19, 2020 2:47 pm
viewtopic.php?f=8&t=42245
This isn't the best link though.

Its to do with how renpy loads a saved game and when the variable is created.
Imperf3kt,

Thank you for your reply. I checked the link and I am still a little confused. I understand that it is incorrect to define a variable in init python block since every time renpy does initialization it overwrites the stored value. But I still can't figure out why defining the variable after label start can create some problems.

I also looked at the link Default Statement. It says, that if the variable is not defined at game start or is not defined at game load the default points = 0 is equivalent to either of these:

Code: Select all

label start:
    $ points = 0

Code: Select all

label after_load:
    $ points = 0
So technically it seems if we define variable after label start we should not have any problems. When the game is saved the variable is stored, thus the variable should exist when the game is loaded.
The problem is possible if the game is updated and the new version defines a new variable after label start. So if we try to load the save file from the previous version we can catch the error: the variable does not exist.

Did you mean this error? Or, am I missing much more :oops:? I am trying to figure out if I should move all my variables to default statements to be safe.

PS: drbugs, sorry for flooding your post.

User avatar
drbugs
Newbie
Posts: 13
Joined: Sat Nov 14, 2020 10:27 am
Contact:

Re: Changing Sprites in-game

#13 Post by drbugs » Thu Nov 19, 2020 8:09 pm

_ticlock_ wrote:
Thu Nov 19, 2020 5:32 pm
PS: drbugs, sorry for flooding your post.
That's fine! It's educational for me too, so I don't mind!


@Imperf3kt
I'm sorry, but I still don't really understand how to implement the code you've posted. I don't really know much about using Python (though I'm planning on reading through some stuff when I get a chance).
If I'm using your one, would I use the following:

image mc_image = ConditionSwitch(
"mc_sprite == 1", "mc_sprite_001.png",
"mc_sprite == 2", "mc_sprite_002.png",
)

(^To define the images)

textbutton _("Choose mc sprite") action Show("choose_mc_sprite")

(^ To command the images to change)

then have this
default mc_sprite = 1
(or $ mc_sprite = "1"??)
(I guess to set which one it will default to showing?)

before the label for the game starts?

Also, if someone saves the game, quits and reloads, it'll remember the sprites were changed?

User avatar
RicharDann
Veteran
Posts: 284
Joined: Thu Aug 31, 2017 11:47 am
Contact:

Re: Changing Sprites in-game

#14 Post by RicharDann » Fri Nov 20, 2020 10:19 am

_ticlock_ wrote:
Thu Nov 19, 2020 5:32 pm
The problem is possible if the game is updated and the new version defines a new variable after label start. So if we try to load the save file from the previous version we can catch the error: the variable does not exist.

Did you mean this error? Or, am I missing much more :oops:? I am trying to figure out if I should move all my variables to default statements to be safe.
It is better to default all of your variables, mainly because of the reason you just mentioned. The point of default (as far as I know) is to organize variables across files and versions and make them compatible with all screens, save, load, rollback, etc. Suppose for example that you have a some kind of point system in your game, you need a variable called points to store the player's score and a screen where the points will be displayed. So you would use:

Code: Select all

screen some_screen():
    text "[points]"

label start:   
    $ points = 0

    show screen some_screen
This might work, but suppose you create a second game and want to use the same system. You would copy the screen code in the new game, but you also need to add $ points = 0 after label start in that new game. This may seem trivial, but suppose your system actually uses a lot of variables and objects you would have to copy. Label start would be flooded with variable initialization code before the actual game code. It is easier to create a separate rpy file, called for example score.rpy, and just put all the relevant variables defaulted in the same file, without having to modify the script only to add a call to the screen. This will help keep the code organized and reduce an extra step of copy pasting code. It's also useful if you want to send that code to other people, you just need to send the file and tell them all they need is to launch the screen, as the relevant variables will be there.

@drbugs,
drbugs wrote:
Thu Nov 19, 2020 8:09 pm
Also, if someone saves the game, quits and reloads, it'll remember the sprites were changed?
Yes, it should. Let me summarize how the code should look.

Code: Select all

#this is a variable that controls what sprite will be shown as the MC's sprite
default mc_sprite = 1

# this is a ConditionSwitch, it will change depending on what number the mc_sprite variable is
image mc_image = ConditionSwitch(
"mc_sprite == 1", "mc_sprite_001.png", # if mc_sprite equals 1, mc_sprite_001.png in your images folder will be shown
"mc_sprite == 2", "mc_sprite_002.png",
)

# this is the example screen _ticlock_ posted, clicking on either button will set the sprite to that image
screen choose_mc_sprite:
    modal True
    vbox:
        imagebutton:
            idle 'mc_sprite_001.png'
            action [SetVariable('mc_sprite', 1), Hide("choose_mc_sprite")]
        imagebutton:
            idle 'mc_sprite_002.png'
            action [SetVariable('mc_sprite', 2), Hide("choose_mc_sprite")]
label start:

    show mc_image # this will show the image. Since the default is 1, it should be showing mc_sprite_001.png
    
    pause #this is just to pause the game so you can see what image is showing
    
    $ mc_sprite = 2 # here we manually set the mc_sprite variable to 2, so ConditionSwitch should now change to mc_sprite_002.png
    
    pause
    
    # and if you want to change them from the screen, you can use:
    show screen choose_mc_sprite

I hope that all made sense.
The most important step is always the next one.

User avatar
_ticlock_
Veteran
Posts: 391
Joined: Mon Oct 26, 2020 5:41 pm
Contact:

Re: Changing Sprites in-game

#15 Post by _ticlock_ » Fri Nov 20, 2020 11:50 am

RicharDann,

Thank you for the detailed explanation. I really like the examples you provided!

Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot], Majestic-12 [Bot]