Drawing in Ren'Py
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.
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.
- Kinmoku
- Miko-Class Veteran
- Posts: 591
- Joined: Mon Aug 11, 2014 9:39 am
- Completed: One Night Stand
- Projects: VIDEOVERSE
- Tumblr: gamesbykinmoku
- itch: kinmoku
- Location: Germany
- Contact:
Drawing in Ren'Py
Okay, this is a big question. I don't think I've seen it done in a Ren'Py game before but I'm sure it's possible –somehow– with python...
Can a player draw a picture in Ren'Py? I want to add a feature where the player can draw and submit/ wipe clean a simple black and white drawing. The idea is that the drawing will be crude/ funny, and purely there just for a bit of fun, hence I'm not too concerned about people using a mouse.
If it's possible, then I think I'll bring in a programmer to do this for me (as I'm terrible at it myself!).
I thought it's best to ask first, to know if it's even a possibility, before getting someone involved!
Can a player draw a picture in Ren'Py? I want to add a feature where the player can draw and submit/ wipe clean a simple black and white drawing. The idea is that the drawing will be crude/ funny, and purely there just for a bit of fun, hence I'm not too concerned about people using a mouse.
If it's possible, then I think I'll bring in a programmer to do this for me (as I'm terrible at it myself!).
I thought it's best to ask first, to know if it's even a possibility, before getting someone involved!
- Per K Grok
- Miko-Class Veteran
- Posts: 882
- Joined: Fri May 18, 2018 1:02 am
- Completed: the Ghost Pilot, Sea of Lost Ships, Bubbles and the Pterodactyls, Defenders of Adacan Part 1-3, the Phantom Flyer
- itch: per-k-grok
- Location: Sverige
- Contact:
Re: Drawing in Ren'Py
There is something called renpy.render.canvas https://www.renpy.org/doc/html/udd.html ... der.canvas
on which you should be able to use some draw functions. I have not got that work myself yet though.
on which you should be able to use some draw functions. I have not got that work myself yet though.
- Imperf3kt
- Lemma-Class Veteran
- Posts: 3794
- Joined: Mon Dec 14, 2015 5:05 am
- itch: Imperf3kt
- Location: Your monitor
- Contact:
Re: Drawing in Ren'Py
This was asked once before and the conclusion at that time was that it was not possible in any feasible way.
A recent thread prompted me to conside building a grid, made up of 1*1 solids. Upon mouseover (perhaps, only when holding down a key), any hovered grid section would swap colors.
It might work, it might not. I expect, if it does work, it would be fairly GPU intensive.
A recent thread prompted me to conside building a grid, made up of 1*1 solids. Upon mouseover (perhaps, only when holding down a key), any hovered grid section would swap colors.
It might work, it might not. I expect, if it does work, it would be fairly GPU intensive.
Warning: May contain trace amounts of gratuitous plot.
pro·gram·mer (noun) An organism capable of converting caffeine into code.
Current project: GGD Mentor
Twitter
pro·gram·mer (noun) An organism capable of converting caffeine into code.
Current project: GGD Mentor
- MaydohMaydoh
- Regular
- Posts: 165
- Joined: Mon Jul 09, 2018 5:49 am
- Projects: Fuwa Fuwa Panic
- Tumblr: maydohmaydoh
- Location: The Satellite of Love
- Contact:
Re: Drawing in Ren'Py
It's a good idea in theory, but I agree, feels like it would lag due to the 1000s of buttons on screen. A window size of 1280* 720 would have 921600 buttons... You could increase the size of each to 2*2, to half the amount of buttons but who knows.Imperf3kt wrote: ↑Tue Aug 14, 2018 7:26 pm This was asked once before and the conclusion at that time was that it was not possible in any feasible way.
A recent thread prompted me to conside building a grid, made up of 1*1 solids. Upon mouseover (perhaps, only when holding down a key), any hovered grid section would swap colors.
It might work, it might not. I expect, if it does work, it would be fairly GPU intensive.
I'm going to try it out at some point and see how it goes.
- Kinmoku
- Miko-Class Veteran
- Posts: 591
- Joined: Mon Aug 11, 2014 9:39 am
- Completed: One Night Stand
- Projects: VIDEOVERSE
- Tumblr: gamesbykinmoku
- itch: kinmoku
- Location: Germany
- Contact:
Re: Drawing in Ren'Py
Hmm okay, good to know. My idea was to have the draw area a lot smaller (probably around 700 x 400), although it still maybe too big.
If I get chance, I may try it out and see how it runs on a lower-end device. I still really want to do it as I think it'd add quite a charming little feature to my game
If anyone else tries it in the meantime, please comment back on this thread so I know how it goes
If I get chance, I may try it out and see how it runs on a lower-end device. I still really want to do it as I think it'd add quite a charming little feature to my game
If anyone else tries it in the meantime, please comment back on this thread so I know how it goes
- MaydohMaydoh
- Regular
- Posts: 165
- Joined: Mon Jul 09, 2018 5:49 am
- Projects: Fuwa Fuwa Panic
- Tumblr: maydohmaydoh
- Location: The Satellite of Love
- Contact:
Re: Drawing in Ren'Py
So I gave it a go and it is pretty laggy. Max size I could do before it lagged unbearably on my PC was 40x40. 50x50 was bad and once you start getting towards 100x100 and beyond, it lagged so bad I kept getting has stopped responding messages.
One issue is that if you hover over a button and click, it won't change. You need to get a new hover event to change a button. Only way to do it is to change the button_select keymap to mousedown_1 and add SetDict(lDraw, i-1, True) to the action because for some reason changing
to
will only change the last button in the bottom right corner, no matter where you click. But I'm sure I'm just missing something and it's relatively simple to fix.
I also messed about and made a color version.
And have some picture I drew for you all.
End result, it probably won't run on low end devices.
Code: Select all
init python:
def fSetVal(max):
l = []
for i in range(max):
l.append(False)
return l
screen drawing():
tag menu
predict False
default rows = 40
default cols = 40
default lDraw = fSetVal(cols * rows, False)
default tPixelSize = (10, 10)
default bDraw = False
default bErase = False
grid cols rows:
for i in range(cols * rows):
button xysize (tPixelSize):
action NullAction()
hovered [ If(bDraw, SetDict(lDraw, i-1, True)), If(bErase, SetDict(lDraw, i-1, False)) ]
if lDraw[i-1]:
background '#000000'
else:
background '#FFFFFF'
key 'mousedown_1' action SetScreenVariable('bDraw', True)
key 'mouseup_1' action SetScreenVariable('bDraw', False)
key 'mousedown_3' action SetScreenVariable('bErase', True)
key 'mouseup_3' action SetScreenVariable('bErase', False)
Code: Select all
key 'mousedown_1' action SetScreenVariable('bDraw', True)
Code: Select all
key 'mousedown_1' action [ SetScreenVariable('bDraw', True), SetDict(lDraw, i-1, True) ]
I also messed about and made a color version.
Code: Select all
init python:
def fSetValColors(max, value):
l = []
for i in range(max):
l.append(value)
return l
screen drawing_color():
tag menu
predict False
default rows = 40
default cols = 40
default lDraw = fSetValColors(cols * rows, '#FFFFFF')
default tPixelSize = (10, 10)
default bDraw = False
default bErase = False
default color_list = [ '#FFFFFF', '#000000', '#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#00FFFF', '#FF00FF' ]
default draw_color = color_list[1]
vbox:
grid cols rows:
for i in range(cols * rows):
button xysize (tPixelSize):
action NullAction()
hovered [ If(bDraw, SetDict(lDraw, i-1, draw_color)), If(bErase, SetDict(lDraw, i-1, color_list[0])) ]
background lDraw[i-1]
key 'mousedown_1' action SetScreenVariable('bDraw', True)
key 'mouseup_1' action SetScreenVariable('bDraw', False)
key 'mousedown_3' action SetScreenVariable('bErase', True)
key 'mouseup_3' action SetScreenVariable('bErase', False)
grid 4 2:
for i in range(len(color_list)):
button xysize (20, 20):
action SetScreenVariable('draw_color', color_list[i])
background color_list[i]
text draw_color color '#FFFFFF'
End result, it probably won't run on low end devices.
- Kinmoku
- Miko-Class Veteran
- Posts: 591
- Joined: Mon Aug 11, 2014 9:39 am
- Completed: One Night Stand
- Projects: VIDEOVERSE
- Tumblr: gamesbykinmoku
- itch: kinmoku
- Location: Germany
- Contact:
Re: Drawing in Ren'Py
Thanks for letting us know! I love the little pixel arts you didMaydohMaydoh wrote: ↑Wed Aug 15, 2018 5:02 pm So I gave it a go and it is pretty laggy. Max size I could do before it lagged unbearably on my PC was 40x40. 50x50 was bad and once you start getting towards 100x100 and beyond, it lagged so bad I kept getting has stopped responding messages.One issue is that if you hover over a button and click, it won't change. You need to get a new hover event to change a button. Only way to do it is to change the button_select keymap to mousedown_1 and add SetDict(lDraw, i-1, True) to the action because for some reason changingCode: Select all
init python: def fSetVal(max): l = [] for i in range(max): l.append(False) return l screen drawing(): tag menu predict False default rows = 40 default cols = 40 default lDraw = fSetVal(cols * rows, False) default tPixelSize = (10, 10) default bDraw = False default bErase = False grid cols rows: for i in range(cols * rows): button xysize (tPixelSize): action NullAction() hovered [ If(bDraw, SetDict(lDraw, i-1, True)), If(bErase, SetDict(lDraw, i-1, False)) ] if lDraw[i-1]: background '#000000' else: background '#FFFFFF' key 'mousedown_1' action SetScreenVariable('bDraw', True) key 'mouseup_1' action SetScreenVariable('bDraw', False) key 'mousedown_3' action SetScreenVariable('bErase', True) key 'mouseup_3' action SetScreenVariable('bErase', False)
toCode: Select all
key 'mousedown_1' action SetScreenVariable('bDraw', True)
will only change the last button in the bottom right corner, no matter where you click. But I'm sure I'm just missing something and it's relatively simple to fix.Code: Select all
key 'mousedown_1' action [ SetScreenVariable('bDraw', True), SetDict(lDraw, i-1, True) ]
I also messed about and made a color version.And have some picture I drew for you all.Code: Select all
init python: def fSetValColors(max, value): l = [] for i in range(max): l.append(value) return l screen drawing_color(): tag menu predict False default rows = 40 default cols = 40 default lDraw = fSetValColors(cols * rows, '#FFFFFF') default tPixelSize = (10, 10) default bDraw = False default bErase = False default color_list = [ '#FFFFFF', '#000000', '#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#00FFFF', '#FF00FF' ] default draw_color = color_list[1] vbox: grid cols rows: for i in range(cols * rows): button xysize (tPixelSize): action NullAction() hovered [ If(bDraw, SetDict(lDraw, i-1, draw_color)), If(bErase, SetDict(lDraw, i-1, color_list[0])) ] background lDraw[i-1] key 'mousedown_1' action SetScreenVariable('bDraw', True) key 'mouseup_1' action SetScreenVariable('bDraw', False) key 'mousedown_3' action SetScreenVariable('bErase', True) key 'mouseup_3' action SetScreenVariable('bErase', False) grid 4 2: for i in range(len(color_list)): button xysize (20, 20): action SetScreenVariable('draw_color', color_list[i]) background color_list[i] text draw_color color '#FFFFFF'
End result, it probably won't run on low end devices.
It's a shame the lag was too much, I'd have really liked to try this for my game
I can't figure another way around it, apart from having a character creator-like screen for the drawings... But that would require more work from me and be nowhere near as fun. I think I'll drop the idea and try something else.
- MaydohMaydoh
- Regular
- Posts: 165
- Joined: Mon Jul 09, 2018 5:49 am
- Projects: Fuwa Fuwa Panic
- Tumblr: maydohmaydoh
- Location: The Satellite of Love
- Contact:
Re: Drawing in Ren'Py
This thread got me interested in trying to make a drawing function, so like was mentioned before, I tried making a UDD. It works a lot better than the button method but it's still far from perfect. Never used UDD before as never needed it so it's probably a bit messy but here it is.
Have to define the displayable list as global to allow for color and size changes as when you click a button the screen updates, resetting the UDD. I suppose you could set it as a screen variable and pass it as an argument to the UDD so it resets when you leave and return to the screen.
One big issue is that when you move the cursor too fast, it can't keep up with the mouse tracking and you end up with spaces between each pixel but not sure that can be fixed.
If you change it a bit and have it display an image of a circle instead of a solid block of color, you could get a "cheap" antialiasing effect, using matrix color to change the color etc. but I haven't tried it yet.
But the code is there if anyone wants to use or improve it.
Sample screen to show UDD with buttons to change color/size and clear the canvas:
And of course, here's your complimentary snail pic.
Code: Select all
lDraw_Pos = [] ## List of displayable colors positions
class Draw(renpy.Displayable):
def __init__(self, color, size, width, height):
super(Draw, self).__init__()
self.col = color ## Brush color
self.size = size ## Brush size tuple
self.canvas_w = width ## Width of drawing space
self.canvas_h = height ## Height of drawing space
self.drawing = False
self.erasing = False
self.pos = (0, 0) ## Cursor position tuple
def render(self, width, height, st, at):
global lDraw_Pos
## Create drawing space
canvas = renpy.Render(self.canvas_w, self.canvas_h)
canvas.canvas().rect('#FFF', (0, 0, self.canvas_w, self.canvas_h))
## Set brush location
x, y = self.pos
w, h = self.size
x -= w / 2
y -= h / 2
## Prevent brush from leaving drawing space
if x < 0:
x = 0
elif x > self.canvas_w - w:
x = self.canvas_w - w
if y < 0:
y = 0
elif y > self.canvas_h - h:
y = self.canvas_h - h
## Create brushes
t_brush = Transform(child=Solid(self.col), size=self.size)
brush = renpy.render(t_brush, width, height, st, at)
t_eraser = Transform(child=Solid('#FFF'), size=self.size)
eraser = renpy.render(t_eraser, width, height, st, at)
## Add displayables to lists
if self.drawing and (brush, (x, y)) not in lDraw_Pos:
lDraw_Pos.append( (brush, (x, y)) )
elif self.erasing and (eraser, (x, y)) not in lDraw_Pos:
lDraw_Pos.append( (eraser, (x, y)) )
## Add the list of displayables to the drawing space
for v in lDraw_Pos:
canvas.blit(v[0], v[1])
return canvas
def event(self, ev, x, y, st):
# Set variable to true when key is pressed and set to false when released to create a pseudo key hold
if renpy.map_event(ev, 'mousedown_1'):
## Start drawing
self.drawing = True
elif renpy.map_event(ev, 'mouseup_1'):
## Stop drawing
self.drawing = False
if renpy.map_event(ev, 'mousedown_3'):
## Start erasing
self.erasing = True
elif renpy.map_event(ev, 'mouseup_3'):
## Stop erasing
self.erasing = False
renpy.redraw(self, 0.0)
## Get cursor position
self.pos = (x, y)
One big issue is that when you move the cursor too fast, it can't keep up with the mouse tracking and you end up with spaces between each pixel but not sure that can be fixed.
If you change it a bit and have it display an image of a circle instead of a solid block of color, you could get a "cheap" antialiasing effect, using matrix color to change the color etc. but I haven't tried it yet.
But the code is there if anyone wants to use or improve it.
Sample screen to show UDD with buttons to change color/size and clear the canvas:
Code: Select all
screen canvas():
tag menu
default color_list = [ '#FFFFFF', '#000000', '#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#00FFFF', '#FF00FF' ]
default draw_color = '#000000'
default brush_size = (2, 2)
vbox:
add Draw(draw_color, brush_size, 500, 500)
grid 4 2:
for v in color_list:
button xysize (20, 20):
action SetScreenVariable('draw_color', v)
background v
hbox:
textbutton "Size 2" action SetScreenVariable('brush_size', (2, 2))
textbutton "Size 4" action SetScreenVariable('brush_size', (4, 4))
textbutton "Size 10" action SetScreenVariable('brush_size', (10, 10))
textbutton "Clear Canvas" action SetVariable('lDraw_Pos', []) selected False
-
- Regular
- Posts: 111
- Joined: Fri Oct 11, 2013 12:46 am
- Contact:
Re: Drawing in Ren'Py
Here's an quick example that won't melt your CPU. Won't leave spaces between pixels if you draw quickly, either.
https://github.com/jsfehler/renpy-freehand-draw
https://github.com/jsfehler/renpy-freehand-draw
- Imperf3kt
- Lemma-Class Veteran
- Posts: 3794
- Joined: Mon Dec 14, 2015 5:05 am
- itch: Imperf3kt
- Location: Your monitor
- Contact:
Re: Drawing in Ren'Py
Found the thread I was referencing.
viewtopic.php?f=8&t=47773
Although what we currently have seems to work well enough.
Warning: May contain trace amounts of gratuitous plot.
pro·gram·mer (noun) An organism capable of converting caffeine into code.
Current project: GGD Mentor
Twitter
pro·gram·mer (noun) An organism capable of converting caffeine into code.
Current project: GGD Mentor
-
- Regular
- Posts: 111
- Joined: Fri Oct 11, 2013 12:46 am
- Contact:
Re: Drawing in Ren'Py
I've added the ability to draw straight lines so that it's easier to draw Gundams. I know how important that is to the kids. Go forth, and draw the polygonal shapes of your dreams.
- Attachments
-
- freehand.png (11.7 KiB) Viewed 6809 times
- ComputerArt.Club
- Veteran
- Posts: 427
- Joined: Mon May 22, 2017 8:12 am
- Completed: Famous Fables, BoPoMoFo: Learn Chinese, Santa's workshop, Cat's Bath, Computer Art Club
- Location: Taiwan
- Contact:
Re: Drawing in Ren'Py
Wow! This looks awesome!
Facebook:
Renpy Creators and Enthusiasts Facebook Group
My latest game:
Famous Fables: Read, Learn and Play - Android App for teaching children to read
Creative Commons stuff:
Shape transitions,
100+ 360° photos of Japan,
- MaydohMaydoh
- Regular
- Posts: 165
- Joined: Mon Jul 09, 2018 5:49 am
- Projects: Fuwa Fuwa Panic
- Tumblr: maydohmaydoh
- Location: The Satellite of Love
- Contact:
Re: Drawing in Ren'Py
Also just to add, adding a new method that pops the last child from the list and you've got yourself an undo button and putting the removed child into a new list, you now also have a redo button.
Code: Select all
def undo(self):
self.old_children.append(self.children.pop())
renpy.redraw(self, 0)
def redo(self):
self.children.append(self.old_children.pop())
renpy.redraw(self, 0)
- Imperf3kt
- Lemma-Class Veteran
- Posts: 3794
- Joined: Mon Dec 14, 2015 5:05 am
- itch: Imperf3kt
- Location: Your monitor
- Contact:
Re: Drawing in Ren'Py
I like where this is going!
The big question is: can you draw an Eileen with it?
Just kidding, I wonder if there's any way to use the generated image.
The big question is: can you draw an Eileen with it?
Just kidding, I wonder if there's any way to use the generated image.
Warning: May contain trace amounts of gratuitous plot.
pro·gram·mer (noun) An organism capable of converting caffeine into code.
Current project: GGD Mentor
Twitter
pro·gram·mer (noun) An organism capable of converting caffeine into code.
Current project: GGD Mentor
Re: Drawing in Ren'Py
This drawing-thingy looks worth to be in a cookbook - as a stand alone feature and as useful sample of UDD..
Who is online
Users browsing this forum: Majestic-12 [Bot]