Yes!
Viewport nodes are a good option, but you can actually just extend get_viewport().get_texture().get_data()
to include .get_rect( -Rect2- )
, where "Rect2" is the region that you specify (beforehand).
Rect2(x: float, y: float, width: float, height: float)
So just for example:
var region = Rect2(83, 225, 480, 296) # change the values around to suit your actual scene
var image = get_viewport().get_texture().get_data().get_rect(region)
image.flip_y()
image.save_png("screenshot.png")
Also in your screenshots you have a little thumbnail of the screenshot and you can do that in various ways, but I have a basic example if you're looking for inspiration:
# do this in the main (or visible) scene
sprite = Sprite.new()
var texture = ImageTexture.new()
texture.create_from_image(image, 1)
sprite.set_texture(texture)
sprite.position = Vector2(700, 200)
sprite.scale = Vector2(0.3, 0.3)
$Node.add_child(sprite)
Just in order to test all that code I made a quick little scene with your screenshots (the thumbnail was actually generated in the scene):

The flash and fade effects were also extras I added but pretty easy to do as well (animate the modulate property of a white box and the thumbnail).
Your game looks really nice, by the way. I like it!
Good luck!