Drawing a line on a screen

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
User avatar
thelastsecret
Regular
Posts: 115
Joined: Tue Mar 01, 2022 1:32 pm
Completed: The Last Secret
Projects: Sweet Science – The Girls from Silversee Castle
itch: thelastsecret
Discord: TheLastSecret #5266
Contact:

Drawing a line on a screen

#1 Post by thelastsecret »

I have a (supposedly) modest task: I want to draw a line on a screen between two points (connecting image buttons, but I have their coordinates).
I have tried to understand how a canvas works, but I'm not even sure that would work on a screen, and I really couldn't get a handle on the whole thing. I'm too dumb for that I am afraid...
I have also tried to draw it by hand by adding a small square and then rotating and stretching it, but I ultimately failed as well.
Is there an easy solution? I just need something like "draw a line from x1,y1 to x2,y2" within a screen.
I would be super thankful for your help! :)

P.S.: Here's my failed attempt to draw the line by hand:

Code: Select all

$theta=math.atan((cy[1]-cy[0])/(cx[0]-cx[1]))
$lengthofline=math.sqrt((cy[1]-cy[0])**2+(cx[0]-cx[1])**2)
add "images/others/point.png":
xanchor 0
yanchor 0
xpos cx[0]
ypos cy[0]
rotate theta
xzoom lengthofline
(EDIT: Simplified the example)

User avatar
Andredron
Miko-Class Veteran
Posts: 700
Joined: Thu Dec 28, 2017 2:37 pm
Location: Russia
Contact:

Re: Drawing a line on a screen

#2 Post by Andredron »

thelastsecret wrote: Tue Dec 06, 2022 6:50 am I have a (supposedly) modest task: I want to draw a line on a screen between two points (connecting image buttons, but I have their coordinates).
I have tried to understand how a canvas works, but I'm not even sure that would work on a screen, and I really couldn't get a handle on the whole thing. I'm too dumb for that I am afraid...
I have also tried to draw it by hand by adding a small square and then rotating and stretching it, but I ultimately failed as well.
Is there an easy solution? I just need something like "draw a line from x1,y1 to x2,y2" within a screen.
I would be super thankful for your help! :)

P.S.: Here's my failed attempt to draw the line by hand:

Code: Select all

$theta=math.atan((cy[1]-cy[0])/(cx[0]-cx[1]))
$lengthofline=math.sqrt((cy[1]-cy[0])**2+(cx[0]-cx[1])**2)
add "images/others/point.png":
xanchor 0
yanchor 0
xpos cx[0]
ypos cy[0]
rotate theta
xzoom lengthofline
(EDIT: Simplified the example)
viewtopic.php?f=8&t=57541

User avatar
_ticlock_
Miko-Class Veteran
Posts: 910
Joined: Mon Oct 26, 2020 5:41 pm
Contact:

Re: Drawing a line on a screen

#3 Post by _ticlock_ »

thelastsecret wrote: Tue Dec 06, 2022 6:50 am
Another example, that uses canvas:
viewtopic.php?t=17142#p224718

User avatar
_ticlock_
Miko-Class Veteran
Posts: 910
Joined: Mon Oct 26, 2020 5:41 pm
Contact:

Re: Drawing a line on a screen

#4 Post by _ticlock_ »

thelastsecret wrote: Tue Dec 06, 2022 11:39 pm Thank you for the links. I can't say that I understand all of that, I'm just not good with object-oriented programming. After trying out a bit and not getting any further, I think I just skip that and use numbers instead of lines to mark the path. That's more feasible.
Here is a simple example:

Code: Select all

init python:
    class LineDisplayable(renpy.Displayable):

        def __init__(self, lines, color = "#000", width = 1, **kwargs):
            super(LineDisplayable, self).__init__(**kwargs)
            self.lines = lines
            self.color = color
            self.width = width

        def render(self, width, height, st, at):
            render = renpy.Render(width, height)
            canvas = render.canvas()
            for line in self.lines:
                canvas.line(self.color, line[0], line[1], width = self.width)
            return render
If you have points like this:

Code: Select all

default line1 = [(0,0), (100,100)]
default line2 = [(100,100), (200,300)]
default line3 = [(300,300), (300,300)]
default lines = [line1,line2,line3]
Then you can use LineDisplayable in a screen:

Code: Select all

screen some_screen(lines):
    add LineDisplayable(lines, color="#f00", width=2)

Code: Select all

label start:
    show screen some_screen(lines)
    pause
Or you can use LineDisplayable with show expression statements:

Code: Select all

label start:
    show expression LineDisplayable(lines, color = "f0f", width = 5) as shown_lines
    pause
    hide shown_lines # to hide

User avatar
thelastsecret
Regular
Posts: 115
Joined: Tue Mar 01, 2022 1:32 pm
Completed: The Last Secret
Projects: Sweet Science – The Girls from Silversee Castle
itch: thelastsecret
Discord: TheLastSecret #5266
Contact:

Re: Drawing a line on a screen

#5 Post by thelastsecret »

Oh, thank you so much, that looks a bit more comprehensible for my small brain. :)
I'm just done with adding the numbers, but additional lines would be better, so I'll give it a shot!

User avatar
thelastsecret
Regular
Posts: 115
Joined: Tue Mar 01, 2022 1:32 pm
Completed: The Last Secret
Projects: Sweet Science – The Girls from Silversee Castle
itch: thelastsecret
Discord: TheLastSecret #5266
Contact:

Re: Drawing a line on a screen

#6 Post by thelastsecret »

It works fantastic! Thank you so much. That made even for an OOI (object-oriented idiot) like me everything usable. I still don't get what the Python code is actually doing, but who cares as long as it does what it should. :D

User avatar
m_from_space
Miko-Class Veteran
Posts: 939
Joined: Sun Feb 21, 2021 3:36 am
Contact:

Re: Drawing a line on a screen

#7 Post by m_from_space »

thelastsecret wrote: Wed Dec 07, 2022 2:42 am It works fantastic! Thank you so much. That made even for an OOI (object-oriented idiot) like me everything usable. I still don't get what the Python code is actually doing, but who cares as long as it does what it should. :D
The python code creates a class for a user-defined Displayable (a Renpy specific object) that you then can add or manipulate like any image after its creation. The class itself just uses specific functions like render() that specify what the Displayable is actually showing. In this case it uses the function canvas(), which relates to the pygame.draw functions, that allow you to draw circles, lines etc.

If you wish your line to be "antialiased", which means it looks smoother and doesn't have this staircase effect, you can replace the following line:

Code: Select all

canvas.line(self.color, line[0], line[1], width = self.width)
with

Code: Select all

canvas.aaline(self.color, line[0], line[1])
Note: You can only draw 1 pixel wide lines when using antialiasing, so width has no effect anymore.

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot]