Ren'Py Image maps - create an interactive main screen

Mad King

The 'landlord'
Donor
Game Developer
Feb 2, 2018
910
3,768
Hi mates,

How can I create a main screen where the players can interact with different elements to activate the content. This type of feature has been used in many games, an the most known is MILF City. Basically you have a screen with different image maps. For example, a house where the user can navigate between the rooms and interact with elements and unlock scenes in the process.

I just need something to start from.

Thank you in advance
 
Last edited:

Porcus Dev

Engaged Member
Game Developer
Oct 12, 2017
2,582
4,681
Imagemaps I think it has become a bit old, although you can use it, but it has its limitations, I recommend you an imagebuttons...

And as for how to start, you can try this:

Code:
screen house_navigation:
    add "nav/house_corridor.webp"  ## this is the background
    imagebutton auto "nav/door1_%s.webp" xpos 100 ypos 140 focus_mask True action Hide("house_navigation), Jump("Room1") #Door button to jump to "Room1" label
    imagebutton auto "nav/door2_%s.webp" xpos 700 ypos 140 focus_mask True action Hide("house_navigation), Jump("Room2") #Door button to jump to "Room2" label
For this example you need 5 images, "house_corridor" for the background, and two images for every imagebutton.
In the examples, images for imagebuttons are inside a folder called "nav" inside the "images" folder; and you need one for idle state, called in this case "door1_idle.webp" (use your preferred format, just keep in main that you need transparency, so use webp or png, not jpg), and another image for the same imagebutton for the hover state, called in this case "door1_hover.webp".
The remaining two images for the other imagebutton would be "door2_idle.webp" and "door2_hover.webp".

For images in "hover" state the best thing is to create some kind of highlight with some image editor, so that the player when passing over notices that he/she can click there.

And to use this code in the game, here's an example:
Code:
label start:
    "This is the corridor upstairs, and you can visit the rooms..."
    "Try it"

    show screen house_navigation

label Room1:
    "This is the room of..."
    "It's pretty, huh? Now let's go back to the corridor"
    show screen house_navigation   

label Room2:
    "This is the room of..."
    "It's pretty, huh? Now let's go back to the corridor"
    show screen house_navigation
 
  • Like
  • Love
Reactions: zger and Mad King

Rich

Old Fart
Modder
Respected User
Donor
Game Developer
Jun 25, 2017
2,439
6,847
To add a few tidbits to what @mgomez0077 wrote:
  1. If you're going to display your "pick what to do next" screen via "show screen" and have it "Jump" to the appropriate spot to handle what you clicked on, you'll want to make sure that the screen is set to be modal. Otherwise, Ren'py will show your screen, but then move right on to the next statement in the code, and clicks on the screen will also be interpreted as "move to the next bit of dialog." Not what you'll want, in all probability.
  2. The alternate approach is to use "call screen" instead, which implicitly makes the screen modal. The particular paradigm I strongly prefer is to "call screen" and have anything you click on Return() a value. Then, right after the "call screen", I put the appropriate "and what do I do next" logic.
I tend to use #2 if I'm working on a "sandbox" type game, because I basically set up a "game loop" that "call"s out to various bits and pieces of logic, where each "call" returns back to the game loop with "what to do next." "What to do next" might be "call the dialog at this label" or "change the player to be at this location" (which then might either return "display the navigation map for the current location" or "call this label because there's an event that happens when you enter that location")

Doing this requires you to set up some "structure" (locations, actions, etc.) for your game, but once you get the basic plumbing in place, it's very straightforward to add more locations, events, etc., etc., etc. It turns out that there usually aren't all that many "what to do next" options in the game loop if you set up the proper abstractions. Otherwise, as your game grows you're probably going to find yourself repeating a lot of code over and over again, and possibly missing a few places when an update is required. Which leads to "the event triggers if you come from here, but not if you come from there" type bugs.

Just my $0.02.
 

Mad King

The 'landlord'
Donor
Game Developer
Feb 2, 2018
910
3,768
@mgomez0077 and @Rich, thank you a lot for stepping out and help me. As @Rich gave the example, I want to tend for a sandbox game that will generate actions regarding the progress of the player. Can I ask if you have an example or a source I can get the info from? Never tried this before and I am in the dark as a blind man.
 

Porcus Dev

Engaged Member
Game Developer
Oct 12, 2017
2,582
4,681
Maybe I'm wrong because I tend to use instead of , but I think my example code adapted to the call command would be like this, using :
Code:
screen house_navigation:
    add "nav/house_corridor.webp"  ## this is the background
    imagebutton auto "nav/door1_%s.webp" xpos 100 ypos 140 focus_mask True action Call("Room1") #Door button to jump to "Room1" label
    imagebutton auto "nav/door2_%s.webp" xpos 700 ypos 140 focus_mask True action Call("Room2") #Door button to jump to "Room2" label
Code:
label start:
    scene houser_corridor   #I forgot to put this in my previous example... this will show the image of the corridor :-p
    "This is the corridor upstairs, and you can visit the rooms..."
    "Try it"

    call screen house_navigation

label Room1:
    "This is the room of..."
    "It's pretty, huh? Now let's go back to the corridor"
    return   #It will return you to the previous call; if you don't come from a call command it will return you to the main menu.

label Room2:
    "This is the room of..."
    "It's pretty, huh? Now let's go back to the corridor"
    return
 
  • Love
Reactions: Mad King

Mad King

The 'landlord'
Donor
Game Developer
Feb 2, 2018
910
3,768
Maybe I'm wrong because I tend to use instead of , but I think my example code adapted to the call command would be like this, using :
Code:
screen house_navigation:
    add "nav/house_corridor.webp"  ## this is the background
    imagebutton auto "nav/door1_%s.webp" xpos 100 ypos 140 focus_mask True action Call("Room1") #Door button to jump to "Room1" label
    imagebutton auto "nav/door2_%s.webp" xpos 700 ypos 140 focus_mask True action Call("Room2") #Door button to jump to "Room2" label
Code:
label start:
    scene houser_corridor   #I forgot to put this in my previous example... this will show the image of the corridor :-p
    "This is the corridor upstairs, and you can visit the rooms..."
    "Try it"

    call screen house_navigation

label Room1:
    "This is the room of..."
    "It's pretty, huh? Now let's go back to the corridor"
    return   #It will return you to the previous call; if you don't come from a call command it will return you to the main menu.

label Room2:
    "This is the room of..."
    "It's pretty, huh? Now let's go back to the corridor"
    return

Thank you! You have been of great help. I will give it a try
 
  • Like
Reactions: Porcus Dev

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
9,944
14,546
Maybe I'm wrong because I tend to use instead of , but I think my example code adapted to the call command would be like this, using :
Code:
    [...] action Call("Room1") #Door button to jump to "Room1" label
I know it's confusing, but called screens and called labels are two different mechanisms that absolutely don't react in the same way. So you don't need to call the labels from a called screen. You can still jump to labels like in your initial example, and you don't need to return from the labels you jumped to from the screen.

The problem of something like show screen navigation is double. There's the problem pointed by @Rich , and there's also the fact that the player can quit the actual flow at anytime.
Take this by example :
Code:
label blabla:
    show screen navigation
    mc "Hello sis."
    menu:
        "compliment her":
            mc "you look really good today."
            sis "thanks."
            $ sis_like += 1
        "Say nothing":
            pass
Like the player can quit the actual flow at anytime, he can by example do it right after the mc said that she look good. So, he'll have made the right choice, but he will not have the point for it, because he never reached this part.
Obviously, the fix for this particular example is to give the point before everything else, but it's still a flaw in the design to let the player quit in the middle of the action.

If the problem is that the navigation bar isn't always visible and it somehow break the design of the User Interface, you can use something like this :

[Note, I use textbutton for the example, because it simplify it. But obviously the exact same works with imagemap and imagebutton.]
Python:
# Flag to control the display of the navigation bar in the UI.
default disableNav = False

# The navigation bar when active.
screen myNav():
    # Ensure that it will always be on top of the UI.
    zorder 1
    # Add the navigation bar.
    use myNavButtons( True )

# The User Interface.
screen myUI():
    # Whatever is needed in the UI.
    vbox:
        hbox:
            text "Monday"
            null width 5
            text "noon"

    # Add the navigation bar, unless it's disabled.
    if disableNav is False:
        use myNavButtons()

# The navigation bar, inactive by default.
screen myNavButtons( active=False):

    vbox:
        yalign 0.5
        textbutton "Go here":
            # Add the action only if the bar is active.
            if active is True:
                action Jump( "here" )

        textbutton "Go there":
            if active is True:
                action Jump( "there" )
            #  An alternative is to have this when the bar 
            # is not active. But as you see the button still
            # react, what can be confusing.
            else:
                action NullAction()

label start:
    # The UI is always to show.
    show screen myUI
    "welcome to  my example."
    # But the navigation bar is active only now.
    call screen myNav

label here:

    "I'm here."
    "The navigation bar is still visible."
    "But it don't works."
    "Now it will works again."
    # Active the navigation bar again.
    call screen myNav
    "back here."

label there:
    "I'm there."
    #  Temporarily remove the navigation bar, and it only,
    # the User Interface is still visible.
    $ disableNav = True
    "But for this scene we need to get ride of the navigation bar."
    "Ok, now we can have it back."
    # Ok, the navigation bar can appear again.
    $ disableNav = False
    "END"
The "myUI" screen will always be visible and include the navigation bar by default. But the button are effectively active only when you call the "myNav" screen.
Plus, like the navigation bar is inside it's own screen, added by , you don't have to define the buttons twice, which will limit the risk of bugs.
 

Mad King

The 'landlord'
Donor
Game Developer
Feb 2, 2018
910
3,768
I know it's confusing, but called screens and called labels are two different mechanisms that absolutely don't react in the same way. So you don't need to call the labels from a called screen. You can still jump to labels like in your initial example, and you don't need to return from the labels you jumped to from the screen.

The problem of something like show screen navigation is double. There's the problem pointed by @Rich , and there's also the fact that the player can quit the actual flow at anytime.
Take this by example :
Code:
label blabla:
    show screen navigation
    mc "Hello sis."
    menu:
        "compliment her":
            mc "you look really good today."
            sis "thanks."
            $ sis_like += 1
        "Say nothing":
            pass
Like the player can quit the actual flow at anytime, he can by example do it right after the mc said that she look good. So, he'll have made the right choice, but he will not have the point for it, because he never reached this part.
Obviously, the fix for this particular example is to give the point before everything else, but it's still a flaw in the design to let the player quit in the middle of the action.

If the problem is that the navigation bar isn't always visible and it somehow break the design of the User Interface, you can use something like this :

[Note, I use textbutton for the example, because it simplify it. But obviously the exact same works with imagemap and imagebutton.]
Python:
# Flag to control the display of the navigation bar in the UI.
default disableNav = False

# The navigation bar when active.
screen myNav():
    # Ensure that it will always be on top of the UI.
    zorder 1
    # Add the navigation bar.
    use myNavButtons( True )

# The User Interface.
screen myUI():
    # Whatever is needed in the UI.
    vbox:
        hbox:
            text "Monday"
            null width 5
            text "noon"

    # Add the navigation bar, unless it's disabled.
    if disableNav is False:
        use myNavButtons()

# The navigation bar, inactive by default.
screen myNavButtons( active=False):

    vbox:
        yalign 0.5
        textbutton "Go here":
            # Add the action only if the bar is active.
            if active is True:
                action Jump( "here" )

        textbutton "Go there":
            if active is True:
                action Jump( "there" )
            #  An alternative is to have this when the bar
            # is not active. But as you see the button still
            # react, what can be confusing.
            else:
                action NullAction()

label start:
    # The UI is always to show.
    show screen myUI
    "welcome to  my example."
    # But the navigation bar is active only now.
    call screen myNav

label here:

    "I'm here."
    "The navigation bar is still visible."
    "But it don't works."
    "Now it will works again."
    # Active the navigation bar again.
    call screen myNav
    "back here."

label there:
    "I'm there."
    #  Temporarily remove the navigation bar, and it only,
    # the User Interface is still visible.
    $ disableNav = True
    "But for this scene we need to get ride of the navigation bar."
    "Ok, now we can have it back."
    # Ok, the navigation bar can appear again.
    $ disableNav = False
    "END"
The "myUI" screen will always be visible and include the navigation bar by default. But the button are effectively active only when you call the "myNav" screen.
Plus, like the navigation bar is inside it's own screen, added by , you don't have to define the buttons twice, which will limit the risk of bugs.
Hi mates,

Sorry for the late reply, I am doing a run to see if I can get this through and I will return with feedback. Thank you for the help guys
 

Mad King

The 'landlord'
Donor
Game Developer
Feb 2, 2018
910
3,768
I finished the test and did some renders to have an idea of how the world will look like and it worked. Thank you all for your great help in this matter.
 

lancelotdulak

Active Member
Nov 7, 2018
556
549
Can i suggest you try out unity? Yes its' over powered. YES youre capable of learning its basics quickly. It sounds like youre going to want something more advanced than python rather soon..... (and theres nothing wrong with python)
 

Mad King

The 'landlord'
Donor
Game Developer
Feb 2, 2018
910
3,768
Can i suggest you try out unity? Yes its' over powered. YES youre capable of learning its basics quickly. It sounds like youre going to want something more advanced than python rather soon..... (and theres nothing wrong with python)
It is a good point. I will take a look to see how well I can adjust to it
 
  • Like
Reactions: lancelotdulak

Allzamye

Newbie
Dec 25, 2018
54
20
how to add click-able button in this image part 1,2.How to do it when I click position 1 or 2 , then another label start and there I can show text +scene image.Can anyone help me for it?
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
9,944
14,546
Can anyone help me for it?
The whole thread answer to your question. Add an , position it at the right place, then use its action property to either or to the label you want. Then, repeat for the second button.
 

Allzamye

Newbie
Dec 25, 2018
54
20
The whole thread answer to your question. Add an , position it at the right place, then use its action property to either or to the label you want. Then, repeat for the second button.
can you give some example of coding.?
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
9,944
14,546
can you give some example of coding.?
I can, but what will they have, that the examples gave in this thread don't already have ?
If there's a particular point, or something else, you don't understand, I'll be glad to answer ; and if it's not me, it will be someone else. But actually you're asking for what is already present in the thread. Take the time to read it, look at the code gave in the comments, everything you need is here.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,546
2,160
can you give some example of coding.?
As with all these things, it's not an unusual question.

If you read through this thread and don't see an answer you are happy with... maybe try this other thread too.
It talks about how to do a point-and-click type adventure game in RenPy... which seems close enough to the pictures you've added. It talked about imagebutton instead of imagemap
https://f95zone.to/threads/finding-...-to-create-a-point-click-game-on-renpy.25325/

If you want to use rectangles.. then use then use imagemap.
If you want to use irregular shapes, rather than pure rectangles... then use imagebutton.

If you try using imagebutton instead, then start with a full sized image, then remove all the bits from it that aren't your clickable areas to create hotspots as separate images.
For each clickable area, you'd have 2 images. An "idle" version and a "hover" version. They can be the same, but often the hover image is highlighted somehow (brighter, different color, fluorescent border, etc)... so when you hover the mouse over it... the player notices.
The secret is that any pixel that isn't pure transparency within the idle or hover images is clickable.

In your case, I'd guess you would end up with 5 images... a base image, 2x images for the couch and 2x images for the wall sconce. Each clickable area would have an label associated with it... again 1 for the couch and 1 for the wall sconce.
 

badcock

Member
Jun 2, 2018
131
650
Can i suggest you try out unity? Yes its' over powered. YES youre capable of learning its basics quickly. It sounds like youre going to want something more advanced than python rather soon..... (and theres nothing wrong with python)
Suggestions on Unity plugins to use for Visual Novels? I started with Unity, but found the multiple plugins (Fungus, Localized Dialogs & Cutscenes, Vinoma, etc.) I tried to be clunky and lacking one feature that I needed (i.e. imagebuttons/hotspots or an inventory system).

I switched to Renpy because of easier screen presentation. I would prefer working in C# and Unity as I believe it will allow more complexity behind the screens.