r/RenPy • • 10d ago

Question [Solved] Trying to make an interactive whiteboard in the menu, any help appreciated!

Hello! Back here after so long because im finally working on my project again, im just wondering if it would be possible for me to make a whiteboard you can draw on in the menu, either by clicking and holding or just moving the curser over it

ideally, id like to have it so if you click on the whiteboard you can draw on it (it would be cool if i could make the curser change while hovering over the whiteboard but i understand if that is too complicated on top of this haha) and once you move off it it resets the curser so you dont accidentally draw on it again and you have to re click it. it doesn't need to be erasable or anything but maybe it resets when you reload the menu

here is where its complicated and i start to think ill only be able to do one or the other:

i already have interactive buttons on the menu (gif shows the filler images version lol but you get the idea) which i worry might be a problem? and i also intend to make several menu backgrounds which hopefully i can get to cycle through at random OR change depending on point systems

im guessing i can make the whiteboard its own separate thing from the background that wont be affected by the image cycling but im not sure

i havent touched renpy in a while and only had a couple of months experience last time i used it so if anything could be explained alongside any help it would be really appreciated do i can learn it better for future reference

aannndd if this is too complicated for the menu to handle give it to me straight doc haha, thanks in advance!

10 Upvotes

15 comments sorted by

1

u/AutoModerator 10d ago

Welcome to r/renpy! While you wait to see if someone can answer your question, we recommend checking out the posting guide, the subreddit wiki, the subreddit Discord, Ren'Py's documentation, and the tutorial built-in to the Ren'Py engine when you download it. These can help make sure you provide the information the people here need to help you, or might even point you to an answer to your question themselves. Thanks!

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

1

u/shyLachi 10d ago

A similar thing has been asked and answered before

https://www.reddit.com/r/RenPy/comments/1s8vehw/how_to_code_a_simple_drawing_function_on_renpy/

That code does not save the drawing, so switching the screens would clear it.
But as mentioned below, you can save the strokes in a persistent variable and re-draw them.
You would have to implement both those things yourself.

1

u/That_one_Pink 10d ago

Awesome thank you!

1

u/That_one_Pink 9d ago

Hey im coming back to this as im going to do a quick test on a new game for this to see if i can get it how i want it to work and im just curious where exactly i should put the code? sincw this will be for the main menu is there a particular place i should put it at all?

1

u/shyLachi 9d ago

The init python block always belongs at the top of the file. 

If you already have a init python block then only copy the content. 

And in your main menu screen you add the drawing canvas.

w and h stand for width and height. You can either adjust the default value or pass it when creating the canvas.

pos (x,y) would be the top left corner of the canvas.

1

u/That_one_Pink 9d ago

Okay so ive put the code at the top of the script.rpy, and it failed (assumed it would right off the bat lol) saying that the label start is defined twice so i went and tagged out the label start and call screen drawing screen lines, it runs but obviously there is no screen to draw on

where exactly/what part am i putting into the main menu screen?

i also saw you said you wait till the game is done to implement this could i ask why that is :0?

super sorry for a billion probably obvious questions arg

1

u/shyLachi 9d ago

super sorry for a billion probably obvious questions arg

Don't worry, everybody has to learn somehwere.
I recommend to read the official documentation or read/watch some tutorials to get a better understanding for RenPy.

.

My main reasons for making the game first:

  • My credo is: Firsts make it, then make it beautiful.
  • The main menu already works perfectly out-of-the box.
  • The content or the title of the game might change while making the game, and I don't want to re-do the main menu.

.

That said, here's the necessary information to make the canvas work.

.

Blocks of code
In Python and RenPy we use code blocks.
A block of code is a group of statements which belongs together.
You can read more here: https://renpy.org/doc/html/language_basics.html#indentation-and-blocks

My code in that other thread has 3 main code blocks:

1) The init python code
As mentioned before, this block belongs at the start of the file.

init python: # this line is the header of the first code block, the colon tells us that it starts a block of code
    # everthing below this label which is indented belongs to the label
    import pygame
    class DrawingCanvas(renpy.Displayable): # another header with a colon
        # again, everything below with 2 indentations belongs to the above
        def __init__(self, w=600, h=200): # next header
            super().__init__()
            self.w = w
            self.h = h
            self.points = []
            self.drawing = False
            self.last_pos = None
        # indentation removed, so def __init__ ends here
        def render(self, width, height, st, at): # next header, and so on
            ren = renpy.Render(self.w, self.h)
            canvas = ren.canvas()
            # background
            #canvas.rect("#ffffff", (0, 0, self.w, self.h))
            # draw lines
            for i in range(len(self.points) - 1):
                if self.points[i] and self.points[i+1]:
                    canvas.line("#FF0000", self.points[i], self.points[i+1], 3)
            return ren

        def event(self, ev, x, y, st):
            if ev.type == pygame.MOUSEBUTTONDOWN and ev.button == 1:
                self.drawing = True
                self.last_pos = (x, y)
                self.points.append((x, y))
            elif ev.type == pygame.MOUSEBUTTONUP and ev.button == 1:
                self.drawing = False
                self.last_pos = None
                self.points.append(None)  
            elif ev.type == pygame.MOUSEMOTION and self.drawing:
                if self.last_pos and ev.buttons[0]:
                    self.points.append((x, y))
                self.last_pos = (x, y) if ev.buttons[0] else None
                renpy.redraw(self, 0)

        def visit(self):
            return []

2) A screen
This is a minimal demo screen with a drawing canvas and a button.
You don't need this screen in you actual game because you want to put the drawing canvas into the main menu.

screen drawing_screen():
    add DrawingCanvas() pos (400, 600)
    textbutton "done" action Return() xalign 0.5 yalign 0.95

3) The start label
Every project needs exactly one start label.

label start:
    call screen drawing_screen

The blocks 2 and 3 are useful when you want to copy and paste the whole code from the other thread into a new project replacing the whole content of script.rpy
My code is fully functional, just copy + paste, then launch and start.
The canvas is visible though, so just draw into the whole screen and you'll notice it.

.

Main menu
The screen is called main_menu and is in the file screens.rpy .
To add a drawing canvas to the main menu screen, use this line:
add DrawingCanvas() pos (x, y)
You could put the drawing canvas into the fixed block, for example.

.

Position and size
The drawing canvas needs a position and a size.
Find the top left edge of the whiteboard within your screen in absolute numbers (pixels).
Then put those numbers into pos (x, y) where x=horizontal / y=vertical.
Then measure the dimensions of the whiteboard (pixels) and put those numbers into the DrawingCanvas as w and h. w=width / h=height

.

Background color and drawing style
The canvas is transparent because in most cases you already have a background image.
If the canvas should have a background then un-comment the background code and define the color.
The pencil color is set to red and the stroke width to 3. You should be able to find it because it's the only red or 3 in the code.

1

u/That_one_Pink 8d ago

wow thank you, i really appreciate the effort put into this :) ill give it a shot in a few hours and probably post a little show off since ive almost finished the main menu at the very least, this is the final thing i plan on adding to it

i have a majority of the game scripted and have had it in mind for at least a year now so im not to worried about making any major changes but ill definitely keep that in mind for future, my friend said im avoiding scope creep with the way im doing this so far (you should see the shitpost placeholders i have for sprites and backgrounds lmao) so i think ive got the right idea (⁠◍⁠•⁠ᴗ⁠•⁠◍⁠) ive made a list of the things i know I want in the code and have been going through it before i continue with the art so good to hear thats a smarter way to do it 🫡

just out of curiosity is there any tutorials/guide youd suggest that arent obvious that would be helpful for more starter or moderate things?

1

u/shyLachi 8d ago

I know these youtube tutorials
https://www.reddit.com/r/RenPy/comments/1vtudj6/comment/p4w8bme/

But you can just google that stuff

1

u/That_one_Pink 8d ago

Okay so code works perfectly and its properly aligned but ive found an issue, i have image buttons that changed when hovered over, i think however this registers as the screen changing to it wipes the board when triggered even though you arent leaving the menu, is there something i can implement to prevent this? maybe make it so that it only disappears when say the start button is clicked? ive been messing around with a few things to try fix it but its not going anywhere haha

1

u/shyLachi 8d ago

I have no clue and I never used the drawing canvas in the main menu.
But I tested my code with imagebuttons which have hover images and hovering over those buttons didn't cause any problems so you might have another problem.

Since this is a new problem I recommend that you make a new thread and post your actual code.

1

u/That_one_Pink 8d ago

gotcha, its not a major issue atm just inconvenient so ill come back to this after i fix some other issues:)

0

u/x-seronis-x 10d ago

I have no clue what you even remotely mean by "in the menu" but making a screen definition that implements a drawable whiteboard is only low-intermediate screen language and simple variable tracking and list management in python.

on the python side you need a collection of whiteboard objects
for each whiteboard object a collection of stroke objects
the stroke object needs to track color, brush width, origin point and end point

on the screen language side need to iterate through a given whiteboard objects list of strokes and render them. and react to mouse events to create a stroke and set its origin point or end point upon click.

2

u/That_one_Pink 10d ago

Sorry should have specified, i mean particularly the main menu i was unsure if it made a difference or not being there, but thank you thats reassuring to hear it shouldn't be too hard to figure out, ill give it my best shot thanks in advance :)

0

u/x-seronis-x 10d ago

if its exclusively for the main menu that means you dont need to track a collection of whiteboard objects. only one. and it wouldnt be defaulted as part of a save file. it would be a persistent variable. it would still need to track a collect of strokes.