Should I be using imagemaps or imagebutton for an interactive flowchart (zooming, mouse navigation, etc)

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.
Post Reply
Message
Author
MisterPinetree
Newbie
Posts: 5
Joined: Mon Apr 22, 2024 10:25 pm
Contact:

Should I be using imagemaps or imagebutton for an interactive flowchart (zooming, mouse navigation, etc)

#1 Post by MisterPinetree »

I'm trying to make a flowchart with a couple of basic features:
- When you click on a node, it zooms in on that node and neighboring nodes
- When you click on the node again, you jump into a story segment

I've been using an imagemap so far, because it seems to better support zooming in and when the hotspots move.

Code: Select all

    def zoom_in():
        renpy.show_screen("flowchart", zoomed_in=True)
        renpy.restart_interaction()

transform imap_small():
    zoom 1.0
    
transform imap_zoom(t=0.5):
    zoom 1.0
    linear t zoom 2.0


screen flowchart(zoomed_in=False):

    default select_node = None
    default zoomed_node = nodes[0]

    default imap_size = imap_zoom if zoomed_in else imap_small
    default hotspot_size = 80 if zoomed_in else 40
    
    frame:
        xysize (config.screen_width, config.screen_height)
        # this is just a blue background
        add "bg_flowchart"
        vbox:
            align (0.5, 0.5)
            viewport id "repaired_flowchart": 
                xalign 0.5
                yalign 0.5
                arrowkeys True
                xysize(900, 2000)
                xinitial 0.5

                for node in nodes:
                    add node.get_icon() pos (node.get_coordinates(zoomed_in)) size (40, 40) at imap_size
                    
                imagemap:
                    at imap_size
                    ground "flowchart/images/flowchart_repaired_no_true.png"
                    idle Solid("#FF09", xysize=(config.screen_width, config.screen_height)) 
                    hover Solid("#F009", xysize=(config.screen_width, config.screen_height))

                    for node in nodes:
                        hotspot (node.get_x(zoomed_in), node.get_y(zoomed_in), hotspot_size, hotspot_size):
                            action [Function(zoom_in), SetVariable("select_node", node)]
                            hover_sound "sound/confirm-beep.mp3"
And here's my node class and some select nodes:

Code: Select all

class Status(Enum):
        UNREAD = "unread"
        NOVEL = "novel"
        ESCAPE = "escape"
        END = "end"
        LOCKED = "locked"

    class Node:
        def __init__(self, coordinates, label, name, description, is_accessible, status=None, icon=None):
            self.coordinates = coordinates
            self.label = label
            self.name = name
            self.description = description
            self.is_accessible = is_accessible
            self.status = status
            self.icon = icon

        def set_is_accessible(self, is_accessible):
            self.is_accessible = is_accessible

        def get_is_accessible(self):
            if self.label is None or self.status is Status.END or self.status is Status.LOCKED:
                return False
            return True

        def get_coordinates(self, is_zoomed):
            return (self.get_x(is_zoomed), self.get_y(is_zoomed))
	
        def get_x(self, is_zoomed):
            if is_zoomed:
                return self.coordinates[0] * 2
            return self.coordinates[0]
            
        def get_y(self, is_zoomed):
            if is_zoomed:
                return self.coordinates[1] * 2
            return self.coordinates[1]

        def get_icon(self):
            if self.icon:
                return self.icon
            if self.status is Status.UNREAD:
                return 'flowchart/images/nodes/unread.png'
            elif self.status is Status.NOVEL:
                return 'flowchart/images/nodes/novel.png'
            elif self.status is Status.ESCAPE:
                return 'flowchart/images/nodes/escape.png'
            return None

    nodes = [
        Node((400, 0), "start", "Fragment 0 ~ Scene 1", "Beginning", True, Status.NOVEL),
        Node((400, 80), "frag0_s2_start", "Fragment 0 ~ Scene 2", "Meeting Everyone", frag0_s1_complete, Status.UNREAD),
        Node((400, 160), "frag0_s3_start", "Fragment 0 ~ Scene 3", "Rules of the Game", frag0_s2_complete, Status.UNREAD),
        Node((400, 240), None, "End of Prologue", None, frag0_complete, Status.END, "flowchart/images/nodes/badend.png"),
        ]
I got the zoom to work in that the nodes will still map to the ground image, but my current bug is that:

1. I always zoom in on the same place of the flowchart
2. The hotspots no longer work when the image

This is my flowchart, ground image, and a gif of the bug
flowchart_repaired_no_true.png
(156.44 KiB) Not downloaded yet
Screenshot 2024-04-22 at 11.09.58 PM.png
(2.08 MiB) Not downloaded yet
Screen Recording 2024-04-24 at 7.05.40 PM.gif
(15.57 MiB) Not downloaded yet

philat
Eileen-Class Veteran
Posts: 1953
Joined: Wed Dec 04, 2013 12:33 pm
Contact:

Re: Should I be using imagemaps or imagebutton for an interactive flowchart (zooming, mouse navigation, etc)

#2 Post by philat »

Note that I am not particularly offering advice on how to best approach this, because that's a complicated question that I am ill equipped to deal with without your assets or your design goals. Simply to answer your specific question: the way you do it now the hotspots would be in a different place, because the imagemap itself is zoomed. In other words, if your hotspot is supposed to be at (400, 80, 40, 40) normally, you should leave it at that and ren'py will zoom it for you when you blow the imagemap up. If you manually change it to (800, 160, 80, 80), it will visually end up at (1600, 320, 160, 160).

MisterPinetree
Newbie
Posts: 5
Joined: Mon Apr 22, 2024 10:25 pm
Contact:

Re: Should I be using imagemaps or imagebutton for an interactive flowchart (zooming, mouse navigation, etc)

#3 Post by MisterPinetree »

I believe that's what I'm doing with this code:

Code: Select all

def get_coordinates(self, is_zoomed):
            return (self.get_x(is_zoomed), self.get_y(is_zoomed))
	
        def get_x(self, is_zoomed):
            if is_zoomed:
                return self.coordinates[0] * 2
            return self.coordinates[0]
            
        def get_y(self, is_zoomed):
            if is_zoomed:
                return self.coordinates[1] * 2
            return self.coordinates[1]

...

for node in nodes:
         hotspot (node.get_x(zoomed_in), node.get_y(zoomed_in), hotspot_size, hotspot_size):
But when I have time later I'll try with some hard-coded coordinates

User avatar
Ocelot
Lemma-Class Veteran
Posts: 2498
Joined: Tue Aug 23, 2016 10:35 am
Github: MiiNiPaa
Discord: MiiNiPaa#4384
Contact:

Re: Should I be using imagemaps or imagebutton for an interactive flowchart (zooming, mouse navigation, etc)

#4 Post by Ocelot »

And that is exactly the problem. If you are applying zoom to the displayable with children, they would be zoomed automatically. All children are already drawn before zoom is applied and are transformed together with the displayable.
See this: https://drive.google.com/file/d/1bOui-S ... sp=sharing
All those rotations and zooms did not requre me to change anything in element positioning. Only thing I did to accomodate changes in map was to "unrotate" icons so they would appear straight on the map (because by default they followed map rotation).
< < insert Rick Cook quote here > >

MisterPinetree
Newbie
Posts: 5
Joined: Mon Apr 22, 2024 10:25 pm
Contact:

Re: Should I be using imagemaps or imagebutton for an interactive flowchart (zooming, mouse navigation, etc)

#5 Post by MisterPinetree »

Got it, I misunderstood the OP. So I apply zoom to the images, but not the hotspots themselves. That seems unintuitive, but maybe I just need to flip my thinking around.

It's working much better now--just need to make sure I'm zooming in on an actual node on the map now. Also really cool map you got there, I love that effect!

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], RVNSN, Semrush [Bot]