Ren'Py Any way to make a x-ray power

Alt-0069

Member
Aug 27, 2017
106
131
Les gars Hy je veux savoir s'il est possible de créer une puissance de rayons X sur renpy (pour voir throught vêtements) de caractère en couches ...

Would to make disapear the clothes inside a shape (as a circle) is it possible ?
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,364
15,281
Would to make disapear the clothes inside a shape (as a circle) is it possible ?
Yeah it should be possible, but it wouldn't be something trivial to do.

It's a 2x2 layers system, with the clothed CG, the unclothed CG, and two masks..
Keeping only the unmasked part of the unclothed CG is something easy. You put the CG on the background, then add the mask on top of it, with the circle being at 100% transparency.
Doing the opposite, keeping only the masked part of the clothed CG, is not more complicated. You follow the same process, but with the opposite mask ; it's the circle that is at 100% opacity.
It's when it's time to merge the twos images that it become tricky. They now lost their transparency and therefore one will hide the other.
Perhaps having one on the mask acting as a green screen, and using a matrix to change the alpha channel according to the green channel. It would restore the transparency, making it full on the green part. But it would also make it partial on the rest of the image ; what wouldn't necessarily give a bad effect.

But turning all this into some code is something else.
Should it be a pure custom displayable, or should it be done with the Animation and Transformation Language ? It's probably possible with the twos, but one would surely be faster and I'm not sure which one.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
Yeah. I was imagining two layers.

Lower layer = Unclothed
Upper layer = Clothed

Then use something to apply a transparency mask to the top layer, likely a circle centered on the mouse position.

Alternatively, the lower layer being clothed and then upper layer being 100% transparent, except where the circular mask overlays it - where it shows only the circle part of the hidden upper layer.

But how to track the cursor and how to apply a dynamic mask to the upper layer (be it to hide or unhide part of an image)... both are beyond my current knowledge.

A quick search of the RenPy official forums found this post that claims to do it...

I haven't tested it though.

In disappointing news... The Girl with X-Ray Eyes features no X-Ray vision mechanics and has very questionable coding.
 

Alt-0069

Member
Aug 27, 2017
106
131
Ohh thank you very much I will try it later.
Sorry for the first part of the message the auto translation of Google sucks
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,364
15,281
But how to track the cursor and how to apply a dynamic mask to the upper layer (be it to hide or unhide part of an image)... both are beyond my current knowledge.
For the cursor it's not too difficult.
Ren'Py have a function and PyGame few functions for this as well. In top of that, if the custom displayable is created inside a screen, the event method will get called when the mouse move, and get its coordinates.
It's a little trick to make this works at first, because PyGame don't limit to the game window, while Ren'py partly depend of the interactions. Some trial/error process is generally needed to adapt to the particular case.

If you want to explore this, here's one of the helper I use when modding, it display the mouse position each time Ren'py come to refresh the screen:
Code:
init Python:
    class AONMousePos(renpy.Displayable):
        x = 0
        y = 0

        def __init__(self, **kwargs):
            super(AONMousePos, self).__init__(**kwargs)

        def event(self, ev, x, y, st):
            if (x < 0 or y < 0): return None
            import pygame_sdl2 as pygame
            if ev.type != pygame.MOUSEMOTION: return None
            self.x = x
            self.y = y
            renpy.redraw(self, 0)

        def render(self, width, height, st, at):
            rv = renpy.Render(width, height)
            rv.blit( renpy.render(Text( "X: {}\nY: {}".format( int( self.x ), int( self.y ) ), size=20, color="#fff", outlines=[ (1, "#000", 0, 0 ) ]), width, height, st, at), (0, 0))
            return rv

    config.overlay_screens.append( "AONMousePos" )


screen AONMousePos():
    zorder 1000
    vbox:
        xalign 0.0 yalign 0.0
        add AONMousePos()
It's not totally smooth like this because it don't focus on the movement, but on the position.
BUT I used the same for an attempt of custom displayable I made for fun, and where the code was this time designed to effectively track the movement, and there it was smooth.

For a displayable, something like:
Code:
init python:
    def trackMouse():
        store.mouseX, store.mouseY = renpy.get_mouse_pos()

image test:
    THE_IMAGE_TO_DISPLAY
    repeat:
        function trackMouse
        pos( mouseX, mouseY )
should be enough to make the sprite move accordingly to the mouse.

Just adapt the content of trackMouse to the situation you want. Here it place the top left corner of the sprite where the mouse is. For placing the center of the image you need to add half the width to X, and half the height to Y.



While I'm back here, the algorithm for the X-Ray made through ATL should be near to this:
Python:
# Build the masked clothed image, with a hole where the X-Ray apply.
image clothedLayer:
    contains:
        THE_CLOTHED_IMAGE
    contains:
        ITS_MASK
        # Get the mouse position
        function trackMouse
        # Move the mask accordingly to this position.
        pos( mouseX, mouseY )

# Build the masked unclothed image, with the hole filled by the image.
image unclothedLayer:
    contains:
        THE_UNCLOTHED_IMAGE
    contains:
        ITS_MASK
        # Get the mouse position
        function trackMouse
        # Move the mask accordingly to this position.
        pos( mouseX, mouseY )

# The tricky part, restore the transparency for the clothedLayer image
image transparentClothedLayer:
    # ???? Using a matrix to turn the green channel into the alpha channel ????

# Finally join the two.
image joinedLayers:
   contains:
        unclothedLayer
   contains:
        transparentClothedLayer


label whatever:
    show joinedLayers
It should be possible to benefit from text interpolation and make this code works with any images :
Code:
image clothedLayer:
    contains:
        "[clothedImageFQ]"
    contains:
        ITS_MASK
        function trackMouse
        pos( mouseX, mouseY )

image unclothedLayer:
    contains:
        ["unclothedImageFQ"]
    contains:
        ITS_MASK
        function trackMouse
        pos( mouseX, mouseY )


label whatever:
    $ clothedImageFQ = "images/effect/clothed/scene 001.jpg"
    $ unclothedImageFQ = "images/effect/unclothed/scene 001.jpg"