I'm trying to implement a character creation room, where the player can do the usual stuff (change haircut, clothes, colors, ...). I'd like, however to implement color changes as a dynamic recoloring of some the character image layers.
I'm nearly there, but I yet have to figure out how to manage to :
- dynamically modify a Composite image layer, and
- use this Composite to create a Character and use it for the rest of the game
What I've implemented is the character creation room (beautyparlor.rpy, see below), where the player can swap between haircut and clothes using hotspots of an imagemap (this works) and change skin tones using a slider (this works, but not as I'd like).
My screen has two Composite images : left one is added directly to the screen (skin tone updates fine), right one is a defined named variable ("girl") which is then added to the screen using its name (skin tone takes initial value, but doesn't update thereafter).
See screencap and code below :
Code: Select all
## file: beautyparlor.rpy
init:
default hairstyle = 1
default hairstyle_max = 5
default top_choice = 1
default top_choice_max = 5
default bottom_choice = 1
default bottom_choice_max = 3
init -1 python:
style.hue_bar = Style(style.bar)
style.hue_bar.thumb = "color_cursor.png"
style.hue_bar.hover_thumb = "color_cursor.png"
style.hue_bar.base_bar = Frame("color_hues.png")
style.hue_bar.hover_base_bar = Frame("color_hues.png")
init python:
import colorsys
class HSV(object):
def __init__(self):
self.hue = 0
self.saturation = 255
self.value = 255
@property
def hsv(self):
return self.hue, self.saturation, self.value
@property
def rgba(self):
# using HSV encoding allows to change RGB values with only one slider
# colorsys.hsv_to_rgb takes 3 floats in range [0.0, 1.0]
# and returns RGB values as 3 floats in range [0.0, 1.0]
rgb = colorsys.hsv_to_rgb(
float(self.hue)/255.0,
float(self.saturation)/255.0,
float(self.value)/255.0
)
# return RGBA values as 4 integers in range [0, 255]
return int(rgb[0]*255), int(rgb[1]*255), int(rgb[2]*255), 0
define skin = HSV()
# this image only gets skin color from the initial values defined in HSV.__init__
# they sadly won't be updated afterwards, although skin object values change
image girl = Composite(
(467, 946),
(0, 0), im.Twocolor("body/body.png", "#ffffff", skin.rgba),
(0, 0), "clothes/bottom[bottom_choice].png",
(0, 0), "clothes/top[top_choice].png",
(0, 0), "body/eyebrows.png",
(0, 0), "body/eyes.png",
(0, 0), "body/mouth.png",
(0, 0), "body/hair[hairstyle].png",
)
screen dress_character:
imagemap:
idle "dressup/idle.png"
hover "dressup/hover.png"
## Hairstyle
hotspot( 800,125, 100,100) action SetVariable("hairstyle", (hairstyle - 1) % hairstyle_max)
hotspot(1200,125, 100,100) action SetVariable("hairstyle", (hairstyle + 1) % hairstyle_max)
## Top
hotspot( 800,325, 100,100) action SetVariable("top_choice", (top_choice - 1) % top_choice_max)
hotspot(1200,325, 100,100) action SetVariable("top_choice", (top_choice + 1) % top_choice_max)
## Bottom
hotspot( 800,568, 100,100) action SetVariable("bottom_choice", (bottom_choice - 1) % bottom_choice_max)
hotspot(1200,568, 100,100) action SetVariable("bottom_choice", (bottom_choice + 1) % bottom_choice_max)
## Quit
hotspot(1107,9, 157,53) action Return()
vbox align(0.5, 0.8):
bar xalign 0.5 xmaximum 255 value FieldValue(skin, field='hue', style='hue_bar', range=255, step=1)
text ("{size=-5}HSV: %s"%str(skin.hsv)) align(0.5, 0.84)
text ("{size=-5}RGBA: %s"%str(skin.rgba)) align(0.5, 0.87)
# CHARACTER ON THE RIGHT
# this one I can (kind of) reuse later, but doesn't update well
add "girl":
pos(867, 86)
zoom 0.33
# CHARACTER ON THE LEFT
# this one updates fine, but I didn't find a way to reuse it
add Composite( (467, 946),
(0, 0), im.Twocolor("body/body.png", "#ffffff", skin.rgba),
(0, 0), "clothes/bottom[bottom_choice].png",
(0, 0), "clothes/top[top_choice].png",
(0, 0), "body/eyebrows.png",
(0, 0), "body/eyes.png",
(0, 0), "body/mouth.png",
(0, 0), "body/hair[hairstyle].png",
):
pos(50, 86)
zoom 0.33
- When I want to use the result afterwards, I cannot : I cannot use the Composite "on the left", even if it updates properly, because it is unnamed -plus, I'm not sure if Ren'Py allows to retrieve variables that are local to a screen (does it ?).
What I can do is use the Composite "on the right" (variable "girl" is found) to create a Character, but I get a placeholder instead of what I want.(solved)- The best I can do is to display the image "girl" directly on screen, and it displays more or less properly (although user-chosen skin color is not there, as seen before) ;
however, an image is not a Character ... So now I have to add this image on every screen where the "girl" character speaks, which is kind of a hassle.(solved)
Code: Select all
## file: script.py
label start:
define mc = Character("Girl", image='girl')
call screen dress_character
show girl:
pos(800, 0)
zoom 0.45
"Yes, that's what I look like ... But where is my skin tone ?"
show mc
mc "... And why doesn't my Character image display ?"
return
Thanks in advance !
obligatory kudos: To write what you see, xela's post and LunaLucid's template were of great help. Of course, "girl" image resources I used are Konnet's creations.
Thank you all !