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.
I'm having a little trouble with FileTakeScreenshot. I'm using the freehand_draw discussed in this thread: viewtopic.php?f=8&t=51370&p=494175#p494175 and I want to take a screenshot of the drawing and show it back to the player.
v "Let me see what you drew!"
nvl clear
window hide
show screen pixelart
But FileTakeScreenshot() doesn't work. FileCurrentScreenshot() does, but it doesn't take the screenshot at the right moment.
Looking on the forums, I've seen a few people with this issue and I'm not sure if they resolved it, if at all. It seems like it should be possible now, though? Any ideas?
Last edited by Kinmoku on Tue May 12, 2020 6:08 am, edited 2 times in total.
I am making a photo album right now where the user can take their own screenshots and it will catalogue them, and here is the code I used. . You do need to have the photos variable initialized with "photos = []" in with your other variables.
init python:
import os
from datetime import datetime
PHOTO_DIRECTORY = config.gamedir + "/Photos/"
def take_picture():
# Make the directory if needed
if(os.path.isdir(PHOTO_DIRECTORY) == False):
os.mkdir(self.directory)
# Setup the filename
now = datetime.now().strftime("%Y%m%d-%H%M%S")
filename = "Screenshot-" + str(now) + ".png"
# Take the screenshot
result = renpy.screenshot(PHOTO_DIRECTORY + filename)
renpy.transition(Fade(0,0,0.5,color=(255,255,255,255)))
if (result):
photos.append(filename)
renpy.notify("Screenshot Saved! " + filename)
else:
renpy.notify("Could not take screenshot! " + filename)
return
label photo:
# Hide the dialogue window for the picture
window hide
$ renpy.pause(0.3)
$ take_picture()
# Re-show the dialogue window and continue
window auto
return
When you want to take a picture, you can use the screen action
qirien wrote: ↑Mon Apr 20, 2020 3:14 pm
I am making a photo album right now where the user can take their own screenshots and it will catalogue them, and here is the code I used. . You do need to have the photos variable initialized with "photos = []" in with your other variables.
I plan on showing many photos throughout the game so your code sounds like the kind of thing I'm after However, I pasted it in and I get the error:
I'm sorry, but an uncaught exception occurred.
While running game code:
File "game/script.rpy", line 184, in script
$ take_picture()
File "game/script.rpy", line 184, in <module>
$ take_picture()
File "game/script.rpy", line 41, in take_picture
os.mkdir(self.directory)
NameError: global name 'self' is not defined
-- Full Traceback ------------------------------------------------------------
Full traceback:
File "game/script.rpy", line 184, in script
$ take_picture()
File "/Applications/renpy-6.99.11-sdk/renpy/ast.py", line 914, in execute
renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store)
File "/Applications/renpy-6.99.11-sdk/renpy/python.py", line 2028, in py_exec_bytecode
exec bytecode in globals, locals
File "game/script.rpy", line 184, in <module>
$ take_picture()
File "game/script.rpy", line 41, in take_picture
os.mkdir(self.directory)
NameError: global name 'self' is not defined
It seems to be "$ take_picture()" is not defined... I'm not good at python so I don't fully understand, but could there be some missing parts to the code?
-- Full Traceback ------------------------------------------------------------
Full traceback:
File "game/script.rpy", line 184, in script
$ take_picture()
File "/Applications/renpy-6.99.11-sdk/renpy/ast.py", line 914, in execute
renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store)
File "/Applications/renpy-6.99.11-sdk/renpy/python.py", line 2028, in py_exec_bytecode
exec bytecode in globals, locals
File "game/script.rpy", line 184, in <module>
$ take_picture()
File "game/script.rpy", line 41, in take_picture
os.mkdir(self.directory)
NameError: global name 'self' is not defined
hell_oh_world wrote: ↑Tue Apr 21, 2020 8:01 am
should be...
CODE: SELECT ALL
os.mkdir(PHOTO_DIRECTORY)
Thanks This fixed it. I also added "define photos = []" to script.rpy.
I am still having an issue, though. Because I want to take a photo of the drawing (freehand_draw), the screen needs to stay open as the photo code works. I changed "call screen freehand_draw" to "show screen freehand_draw", added "modal True", and the screen stays open but doesn't take_picture. Here's my code:
v "Have a go!"
show screen freehand_draw
e "Er..."
v "Let me see!"
nvl clear
window hide
call screen photo_album # this works
# etc
label photo:
# Hide the dialogue window for the picture
#window hide
e "test 1"
$ renpy.pause(0.2)
$ take_picture()
e "test 2"
hide screen freehand_draw
# Re-show the dialogue window and continue
#window auto
return
"test 1" will display but the photo will not take and "test 2" doesn't appear, suggesting the take_picture code doesn't like using show screen. Is there a way I can get it to take a screenshot of freehand_draw before it closes?
hell_oh_world wrote: ↑Tue Apr 21, 2020 8:01 am
should be...
CODE: SELECT ALL
os.mkdir(PHOTO_DIRECTORY)
Thanks This fixed it. I also added "define photos = []" to script.rpy.
I am still having an issue, though. Because I want to take a photo of the drawing (freehand_draw), the screen needs to stay open as the photo code works. I changed "call screen freehand_draw" to "show screen freehand_draw", added "modal True", and the screen stays open but doesn't take_picture. Here's my code:
v "Have a go!"
show screen freehand_draw
e "Er..."
v "Let me see!"
nvl clear
window hide
call screen photo_album # this works
# etc
label photo:
# Hide the dialogue window for the picture
#window hide
e "test 1"
$ renpy.pause(0.2)
$ take_picture()
e "test 2"
hide screen freehand_draw
# Re-show the dialogue window and continue
#window auto
return
"test 1" will display but the photo will not take and "test 2" doesn't appear, suggesting the take_picture code doesn't like using show screen. Is there a way I can get it to take a screenshot of freehand_draw before it closes?
u might need to replace the done action with the take_picture function
also why are you trying to show the canvas? doesn't that will cause the user to proceed to the next dialogues freely while drawing? i mean, when they're drawing things, the user must not be able to proceed to the next statements, that's the purpose of call right? I don't have much experience with calls, sorry.
Note: i suggest making the action button first with no return action, then show the photo or what... and from my previous post before, try also setting a delay before returning or hiding the canvas, better to be safe than sorry though, its in my previous post.
hell_oh_world wrote: ↑Tue Apr 21, 2020 9:43 am
u might need to replace the done action with the take_picture function
CODE: SELECT ALL
textbutton "Done" action Function(take_picture)
Awesome Works like a charm!
hell_oh_world wrote: ↑Tue Apr 21, 2020 9:43 am
also why are you trying to show the canvas? doesn't that will cause the user to proceed to the next dialogues freely while drawing? i mean, when they're drawing things, the user must not be able to proceed to the next statements, that's the purpose of call right? I don't have much experience with calls, sorry.
Calling the screen meant it left it when the button was pressed, so the screenshot never took the photo of the artwork. Your code fixed this though
hell_oh_world wrote: ↑Tue Apr 21, 2020 9:43 am
Note: i suggest making the action button first with no return action, then show the photo or what... and from my previous post before, try also setting a delay before returning or hiding the canvas, better to be safe than sorry though, its in my previous post.
You make a great point. I was going to add this once I got it working.
My final code is below. I just have one question about how I can change take_picture to include my desired screenshot crop "define config.screenshot_crop = (0, 0, 800, 360)" ?
define photos = []
# PHOTOS
init python:
import os
from datetime import datetime
PHOTO_DIRECTORY = config.gamedir + "/Photos/"
def take_picture():
# Make the directory if needed
if(os.path.isdir(PHOTO_DIRECTORY) == False):
os.mkdir(PHOTO_DIRECTORY)
# Setup the filename
now = datetime.now().strftime("%Y%m%d-%H%M%S")
filename = "Screenshot-" + str(now) + ".png"
# Take the screenshot
result = renpy.screenshot(PHOTO_DIRECTORY + filename)
renpy.transition(Fade(0,0,0.5,color=(255,255,255,255)))
if (result):
photos.append(filename)
renpy.notify("Screenshot Saved! " + filename)
else:
renpy.notify("Could not take screenshot! " + filename)
return
init -10:
# A thumbnail version of a full screen image
transform thumbnail:
zoom 0.28
label start:
v "Have a go!"
call screen freehand_draw
e "Er..."
v "Let me see!"
nvl clear
window hide
call screen photo_album
I don't see a way to pass a screenshot size/crop area to renpy.screenshot. You could try config.screenshot_crop, but it might just be for screenshots for saved games, which are taken with FileTakeScreenshot. I think you can get the screenshot it takes with FileCurrentScreenshot, which returns a Displayable, which you could then write out with python file code.
This is similar to the method used by this cell phone emulationcode, so you might take a look at that if you need just a certain part of the screen.
Or, you could have the screenshot be full size and just crop it when you show it in the gallery with a transform like this. Use "at crop_drawing" in your gallery when displaying an image:
hell_oh_world wrote: ↑Tue Apr 21, 2020 9:43 am
u might need to replace the done action with the take_picture function
CODE: SELECT ALL
textbutton "Done" action Function(take_picture)
Awesome Works like a charm!
hell_oh_world wrote: ↑Tue Apr 21, 2020 9:43 am
also why are you trying to show the canvas? doesn't that will cause the user to proceed to the next dialogues freely while drawing? i mean, when they're drawing things, the user must not be able to proceed to the next statements, that's the purpose of call right? I don't have much experience with calls, sorry.
Calling the screen meant it left it when the button was pressed, so the screenshot never took the photo of the artwork. Your code fixed this though
hell_oh_world wrote: ↑Tue Apr 21, 2020 9:43 am
Note: i suggest making the action button first with no return action, then show the photo or what... and from my previous post before, try also setting a delay before returning or hiding the canvas, better to be safe than sorry though, its in my previous post.
You make a great point. I was going to add this once I got it working.
My final code is below. I just have one question about how I can change take_picture to include my desired screenshot crop "define config.screenshot_crop = (0, 0, 800, 360)" ?
i dunno how are you showing or retaining the shot image, so i modified it a bit...
default last_screenshot = "" # takes note of the recent screenshot
init python:
import os
from datetime import datetime
PHOTO_DIRECTORY = config.gamedir + "/Photos/"
def take_picture():
# Make the directory if needed
if(os.path.isdir(PHOTO_DIRECTORY) == False):
os.mkdir(PHOTO_DIRECTORY)
# Setup the filename
now = datetime.now().strftime("%Y%m%d-%H%M%S")
filename = "Screenshot-" + str(now) + ".png"
store.last_screenshot = filename # store the last screenshot name
# Take the screenshot
result = renpy.screenshot(PHOTO_DIRECTORY + filename)
renpy.transition(Fade(0,0,0.5,color=(255,255,255,255)))
if (result):
photos.append(filename)
renpy.notify("Screenshot Saved! " + filename)
else:
renpy.notify("Could not take screenshot! " + filename)
return
screen the_shot(image, crop=None):
default the_image = image if not crop else Crop(crop, image)
add the_image
label sample:
## Some codes before showing...
show screen the_shot(last_screenshot, (0, 0, 800, 360)) # show / call the screen together with the image name and an optional crop value...
qirien wrote: ↑Tue Apr 21, 2020 11:18 am
This is similar to the method used by this cell phone emulationcode, so you might take a look at that if you need just a certain part of the screen.
This post is awesome! I'll check over it in more detail soon.
As you've both suggested, Crop is the best solution here. However, it doesn't display correctly if the window is fullscreen or smaller. I'm not sure what the solution is to that
Anyway, I have changed the filename code to the below:
init python:
import os
#from datetime import datetime
PHOTO_DIRECTORY = config.gamedir + "/photos/"
def take_picture():
# Make the directory if needed
if(os.path.isdir(PHOTO_DIRECTORY) == False):
os.mkdir(PHOTO_DIRECTORY)
# Take the screenshot
result = renpy.screenshot(PHOTO_DIRECTORY + filename)
renpy.transition(Fade(0,0,0.5,color=(255,255,255,255)))
photos.append(filename)
return
image photo_first = "photos/screenshot-first.png"
label start:
v "Have a go!"
$ filename = "screenshot-first.png"
call screen freehand_draw
e "Er..."
v "Let me see!"
nvl clear
show photo_first at crop_drawing
pause
hide photo_first
It worked the first time I tested, but when I try again, it shows my drawing from a previous test. I guess when the game loaded, it loaded the previous image. How can I refresh it? Sorry for so many questions! I'm learning a lot today lol
The problem with statically declaring your image is that images get cached - Ren'Py loads them once and then keeps them around and doesn't reload them unless you haven't used them for a long time. This is also the reason that you can't declare images after your code starts. So you need to show your image in a way that will reload it from disk... which is why I ended up using imagebutton where you give it, not an image, but a filename. This will make sure it loads it every time.
qirien wrote: ↑Tue Apr 21, 2020 1:13 pm
The problem with statically declaring your image is that images get cached - Ren'Py loads them once and then keeps them around and doesn't reload them unless you haven't used them for a long time. This is also the reason that you can't declare images after your code starts. So you need to show your image in a way that will reload it from disk... which is why I ended up using imagebutton where you give it, not an image, but a filename. This will make sure it loads it every time.
Ah, very smart! So I can use imagebutton or something and add Nullaction to it Cool.
I'm still unsure about the game window size and ensuring the crop is the same each time. Is there a way for screenshots to be taken at 100% size, regardless of whether the window is actually 50%, fullscreen etc?
Ugh... you're right. It works fine at the default window size, but in full screen it doesn't work at all...
BUT, I think once again transforms will be our friend! I changed the thumbnail transform and added another one for full screen:
# A thumbnail version of a full screen image
transform thumbnail:
#zoom 0.22 #doesn't work if full screen
size (282,159)
# Display something the size of our screen
transform full_screen:
size (1280,720) #Change to whatever the resolution of your game is
When we display the images, use "at full_screen" like this:
Even though when you run at full screen it's larger than 1280x720, Ren'Py still considers whatever resolution your game is at to be "full screen". So you can tell it to use absolute pixel sizes and it will just scale them up if people are running it at a higher resolution.