Since you have stuff like hair, eyes and even skin colour in there (stuff that is unlikely to change for non-spy), and the fact that your variable name do not indicate that these customization is applicable to all character, it seems like you have just a single character with all these possible appearance, but only one will ever get used. In which case Ayutac's method is good enough, once all the technical issue are resolved (such as trying to use image statement after the game started). If you intended for these appearance to change and thus multiple of these can be seen, then as Ayutac mentioned in the edited post, do NOT use Ayutac's method. However, the idea is fine, and can be made to work.
Also, defining image have priority number 990, which LOW priority (but the number 990 is large though).
But first, to answer a few of your other question:
Renisca wrote:
So does that mean I have to insert this:
Code: Select all
image Character = ConditionSwitch(
"appearance == 'blackmeanlight'", "Character_blackmeanlight.png",
"appearance == ''blackmeanmedium'", "Character_blackmeanmedium.png",
...and so on 70 more times)
every time the character is going to be shown?
No. Your first statement use the image statement to declare a new displayable. The displayable is created by the ConditionSwitch function, and it is then associated with the tag "Character". The image statement is only allowed to run in an init block (if it is put outside all blocks, it's automatically assumed to be in an init block with priority 990). What this means is that, you are literally not allowed to declare the image again and again every time you try to show the image (attempting to do so will produce an error).
Now, what does ConditionSwitch do? It create a displayable. Note the term "displayable" rather than "image", which for Ren'Py means something that you can show on the screen and can be associated with an image tag using the image statement, but unlike "image" which is static, a displayable is allowed to act on its own. Images are a subspecies of the displayables, and using a string giving the filename of the image is a common way to make an image displayable. The ConditionSwitch is a displayable whose purpose is to show a different displayable, and it react to pretty much any interesting statement you can think of: say statement, menu statement, with statement, etc. Whenever one such statement is encountered, ConditionSwitch will go through the list of conditions again, until it get to one that is true or None, then it will pick the corresponding displayable, and make that it become the one to be shown.
ConditionSwitch does NOT simply return a displayable matching the condition among the one it was given. It is itself its own displayable, and it is just that it is made to look exactly like the displayable that match the condition. Hence it can react to all these statement. ConditionSwitch do NOT react to statement that change variable's value (so for example, if you change the value of
appearance, it won't realize that right away), but will react to the say or with or whatever statement that come afterward that have visual result, so that's just as good.
NOTE: "image" and "displayable" are usually interchangable, so people will say "image" even though "displayable" is the better choice, which I will also do because it's just shorter to write. There are times though where "image" really means image though.
Renisca wrote:
Already tried this but I must be doing something wrong. The images just aren't showing up, although the game still works.
Is there any way I can just do it once by associating it with my character image, like:
Code: Select all
define maincharacter = Character("[name]", image ="Character")
image Character = ConditionSwitch(
"appearance == 'blondebrownlight'", "Character_blondebrownlight.png",
"appearance == 'blondebrownmedium'", "Character_blondebrownmedium.png",
xalign =0.2, yalign =0.25)
You need to actually show the image for it to appear. You can't really expect Ren'Py to just display the sprite for you whenever that character speak, because: (a) it's just 1 extra line per scene to show the sprite, unless you want the character to disappear and reappear, which is less common in VN than having the sprite on the screen the whole time; (b) what if you want the character to speak offscreen; (c) how can Ren'Py know where to place the sprite?. So just use the show statement whenever you want the character to appear on the screen.
There is also something I think is not good style when you write your script. You're using the same word "Character" for both image tag and Ren'Py Character class name. Technically, everything still work out since name and image tag are different thing and is applicable in different context. But just like how people don't call a wardrobe a "frog" even though you can always tell from context which is which, it's also better if you don't share character name unnecessarily. That will easily cause confusion down the road. For example, you might attempt to use image tag to refer to the image at place where you need a name. If the same word isn't used for both tag and name, then Ren'Py will realize that it is an error and tell you so. If the word are shared, then Ren'Py will think you are trying to refer to something that isn't an image, and will lead to hours wasted trying to find what went wrong.
The image tag of a character is meant only for changing image already on the screen, and side image. Not showing image that isn't shown yet.
Also, I am not sure why you need the xalign and yalign argument. Why not use transformation instead? It's not like the character is going to stay stuck in that spot all the time right?
I don't recommend the image tag method in this particular situation, since it's more suitable for situation where the image is changing very frequently (such as a character changing expression), rather than something that is probably very rarely change. So simply add in a show statement whenever the character come into the scene (which you need to do whether you use image tag method or not). The image tag method is to use say statement with image attribute to display an image based on what is already on the screen and the new tag you gave, and change the side image too to match.
Renisca wrote:
I would make it a side image, but I also preloaded "mouth" images to overlay the faces and change the character's expression. Otherwise my character images don't have any mouths. So I need to have the faces on the screen so I can lay the mouth images on top, if that makes any sense. x)
Use LiveComposite for combining face and mouth. Use LiveCrop or Viewport to cut out a chunk of that for side image.
Now back to finding a more efficient method to your code. As Ayutac's method above, you can store the value in simply in 3 variables
haircolour,
eyescolour, and
skincolour. Assuming that you have a consistent naming scheme (e.g. black hair mean eye light skin are stored in file name "Character_blackmeanlight.png") then there are a number of thing you can do to shorten your code:
1. You can systematically declare all these image. Simply do something like this:
Code: Select all
init 990 python:
for hair in ["black","blond","red","brown","blue","green"]:
for eyes in ["mean","brown","green","gray"]:
for skin in ["light","medium","dark"]:
renpy.image(("character_%s%s%s"%(hair,eyes,skin),"Character_%s%s%s.png"%(hair,eyes,skin))
That go through all possible combination of these hair, eyes and skin colour and declare an image for each of them.
2. You have a simpler method than ConditionSwitch. Use DynamicDisplayable instead. For example:
Code: Select all
init 990:
python:
def create_appearance_from_hair_eyes_skin(hairvarname,eyesvarname,skinvarname):
def appearance(st,at,*args,**properties):
return Image("Character_%s%s%s.png"%(globals()[hairvarname],globals()[eyesvarname],globals()[skinvarname])),None
return ImageReference("character_%s%s%s"%(globals()[hairvarname],globals()[eyesvarname],globals()[skinvarname])),None
return appearance
image char=DynamicDisplayable(create_appearance_from_hair_eyes_skin("haircolour","eyescolour","skincolour"))
It doesn't have to be that complicated, but I am trying to make it somewhat more general, so that it work if you have multiple character that you can pick appearance from, and they are stored in different variable. Note that the 2nd return line will not run. I put it in there so that you can choose to use it instead of the 1st return line. This one require you to declare the image first, while the first one take stuff directly from the file.
3. Of course, once you do the previous suggestion, simply do
will now show the correct image based on the variable chosen, and you no longer need a long if statement. But if you want to do a show statement that show based on variable, you can do something like:
Code: Select all
$renpy.show("character_%s%s%s"%(haircolour,eyescolour,skincolour))
I hope this help.
