Ren'Py Issue with lagging and saving.

7GC

Newbie
Game Developer
Nov 5, 2018
57
315
Hi,

this is my first game and Iv been getting report of game lagging and unable to save after a point. And for some the game crashes.
The game is made on Renpy.
Would like someone to have a look at the code to identify the problem.
Thanks
7GC
 

rayminator

Engaged Member
Respected User
Sep 26, 2018
3,130
3,194
we need more info like the error message what they are getting when the game crashes
 

7GC

Newbie
Game Developer
Nov 5, 2018
57
315
I'm sorry, but an uncaught exception occurred.

While loading <'Image' u'images/127.png'>:
File "game/script.rpy", line 1097, in script
menu:
File "game/script.rpy", line 1097, in script
menu:
error: Out of memory

-- Full Traceback ------------------------------------------------------------

Full traceback:
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\bootstrap.py", line 316, in bootstrap
renpy.main.main()
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\main.py", line 578, in main
run(restart)
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\main.py", line 143, in run
renpy.execution.run_context(True)
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\execution.py", line 908, in run_context
context.run()
File "game/script.rpy", line 1097, in script
menu:
File "game/script.rpy", line 1097, in script
menu:
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\ast.py", line 1628, in execute
choice = renpy.exports.menu(choices, self.set, args, kwargs, item_arguments)
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\exports.py", line 990, in menu
rv = renpy.store.menu(new_items)
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\exports.py", line 1226, in display_menu
rv = renpy.ui.interact(mouse='menu', type=type, roll_forward=roll_forward)
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\ui.py", line 297, in interact
rv = renpy.game.interface.interact(roll_forward=roll_forward, **kwargs)
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\display\core.py", line 2702, in interact
repeat, rv = self.interact_core(preloads=preloads, trans_pause=trans_pause, **kwargs)
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\display\core.py", line 3194, in interact_core
self.draw_screen(root_widget, fullscreen_video, (not fullscreen_video) or video_frame_drawn)
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\display\core.py", line 2094, in draw_screen
renpy.config.screen_height,
File "renpy/display/render.pyx", line 490, in renpy.display.render.render_screen (gen\renpy.display.render.c:6805)
rv = render(root, width, height, st, st)
File "renpy/display/render.pyx", line 259, in renpy.display.render.render (gen\renpy.display.render.c:3520)
rv = d.render(widtho, heighto, st, at)
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\display\layout.py", line 722, in render
surf = render(child, width, height, cst, cat)
File "renpy/display/render.pyx", line 166, in renpy.display.render.render (gen\renpy.display.render.c:4075)
cpdef render(d, object widtho, object heighto, double st, double at):
File "renpy/display/render.pyx", line 259, in renpy.display.render.render (gen\renpy.display.render.c:3520)
rv = d.render(widtho, heighto, st, at)
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\display\layout.py", line 722, in render
surf = render(child, width, height, cst, cat)
File "renpy/display/render.pyx", line 166, in renpy.display.render.render (gen\renpy.display.render.c:4075)
cpdef render(d, object widtho, object heighto, double st, double at):
File "renpy/display/render.pyx", line 259, in renpy.display.render.render (gen\renpy.display.render.c:3520)
rv = d.render(widtho, heighto, st, at)
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\display\layout.py", line 722, in render
surf = render(child, width, height, cst, cat)
File "renpy/display/render.pyx", line 166, in renpy.display.render.render (gen\renpy.display.render.c:4075)
cpdef render(d, object widtho, object heighto, double st, double at):
File "renpy/display/render.pyx", line 259, in renpy.display.render.render (gen\renpy.display.render.c:3520)
rv = d.render(widtho, heighto, st, at)
File "accelerator.pyx", line 110, in renpy.display.accelerator.transform_render
File "renpy/display/render.pyx", line 259, in renpy.display.render.render (gen\renpy.display.render.c:3520)
rv = d.render(widtho, heighto, st, at)
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\display\image.py", line 500, in render
return wrap_render(self.target, width, height, st, at)
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\display\image.py", line 306, in wrap_render
rend = render(child, w, h, st, at)
File "renpy/display/render.pyx", line 166, in renpy.display.render.render (gen\renpy.display.render.c:4075)
cpdef render(d, object widtho, object heighto, double st, double at):
File "renpy/display/render.pyx", line 259, in renpy.display.render.render (gen\renpy.display.render.c:3520)
rv = d.render(widtho, heighto, st, at)
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\display\im.py", line 583, in render
return cache.get(self, render=True)
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\display\im.py", line 266, in get
surf = image.load()
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\display\im.py", line 628, in load
surf = renpy.display.pgrender.load_image(renpy.loader.load(self.filename), self.filename)
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\display\pgrender.py", line 164, in load_image
rv = copy_surface_unscaled(surf)
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\display\pgrender.py", line 129, in copy_surface
rv = surface_unscaled(surf.get_size(), alpha)
File "A:\Downloads\NOT TOUCHED YET\1 NOT REALLY TOUCHEDL\StayWithClaire-1.0-pc\renpy\display\pgrender.py", line 118, in surface
surf = Surface((width + 4, height + 4), 0, sample)
File "src/pygame_sdl2/surface.pyx", line 164, in pygame_sdl2.surface.Surface.__init__
error: Out of memory

Windows-8-6.2.9200
Ren'Py 7.3.5.606
Stay With Claire 1.0
Sun Sep 13 21:20:01 2020
 

7GC

Newbie
Game Developer
Nov 5, 2018
57
315
when im running the game, it doesnt seem to crash.
But iv got few reports on comments..
Also people are complaining about game being laggy
 

mickydoo

Fudged it again.
Game Developer
Jan 5, 2018
2,446
3,557
Your images are huge, at a guess maybe it's people on laptops or shitty pc's running out of memory. They should be .jpg's or webp's if you want to preserve transparency as a .png does.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,607
2,256
Yeah. Okay. Got it... or at least I think I do.

You're showing all the pictures with show image "{filename}"

There are two ways of changing the background image as the game plays. show and scene.

... as the name implies... shows an image. Nice and simple.
... clears the current screen layers and then shows the named image.

... now your problem. show merely adds an image to the current scene. If you've displayed image1, image2... thru image10... you now have 10 separated (quite large) images shown on the screen... except you can only see the top one, while RenPy has to keep track of all of them.

In the case of your game... since the reported error is happening at image 127... and your game has nearly 230 images totalling 700MB already... I'd have to guess the game is using about 350MB of memory on a computer that perhaps has maybe 8MB to 32MB of active memory. There's your slowdown... there's your "out of memory" error.

Normally (and I use that word very hesitantly), any time you use show - you'd follow that up by using a corresponding hide later. There is a better way, involving naming the images a specific way... but I doubt you're ready for that (hardly anyone does it that way anymore).

The answer is to swap all your show image statements for scene statements. As stated above, scene clears the current game workspace (removes all displayables from the game layer). It is effectively a "hide all + show image" combined.

A couple of notes:

scene does not strictly need double quotes around the image's name. scene 1 will work just fine.
scene works best (imo) when combined with with dissolve or with fade used as a transition. So scene 1 with fade or scene 1 with dissolve

Completely unrelated... but you're also not your menu: statements correctly.
They should remain on the same level of indentation as the other statements.
It's not critical... and due to a quirk of RenPy - it will work. But it's a bad habit and it could cause issues with other statements if you don't understand why python/renpy indents code like it does.

You don't have permission to view the spoiler content. Log in or register now.

To add to the list... a personal pet peeve. Spell checking.
You don't have permission to view the spoiler content. Log in or register now.


Next... You still occasionally refer to your MC as "Tom". I guess it was before you learned to use a variable for the MC's name instead.
Variables (any variable) can be included in the dialogue by putting the variable name within square brackets ( [] ). Because it's a character, you can use either [t] or [name]. [t] is quicker to type and is a good habit, as it means you can do it with other character names too - which is handy if you ever want to give the player the choice of naming the other NPC's too.


Versioning... I also note a common theme in the game thread is the version numbering. The game is up to version 0.3, yet the download is named 0.2 and the game itself still thinks it is version 1.0.
So I'll draw your attention to define config.version = "1.0" in the options.rpy file. If you change that to whatever version you are currently working on... like 0.4 now I assume... that will take care of everything else for you. The distribution filenames will be correct at the very least.


Next... There are some very long lines of dialogue in the code that are split over two lines. That's fine btw. But I'm wondering if you actually wanted the newline itself to be part of the dialogue, or whether you are just doing it to make it easier for you to edit on your computer's monitor. If you actually wanted to split the text within the game, there are two ways. First you can use what is called an (think "special character"). The escape code for "newline" is \n. Therefore "Line 1\nLine 2" would appear on two separate lines. The alternative (and my preferred choice) is a RenPy text-tag - which is a paragraph tag, with zero wait time. So "Line 1{p=0}Line 2" would do the same thing, but is easier to read in my opinion.


Anyway. To make life easier for you... Please find attached a copy of your 0.3 script.rpy file - updated with correct indentation of the menu statements, all those show image replaced with scene {...} with dissolve and Tom's name removed and replaced with [t] to use his character definition instead to show his name. Download it... don't download it - it's all the same to me. (Just remember to backup your current script.rpy before doing anything else - just in case I'm some sort of arsehole).


One final IMPORTANT note. Never, ever delete your .rpyc files - even if you (or I) have changed the code significantly. It'll always completely break previous saved games. There's some technical shit reasons as to why - but rather than explain it... I'll simply say "don't delete them... ever". Honestly, you probably wouldn't have - but this is a "just in case" warning.
 
Last edited:

Bearded_NoPants

Skin as brittle and thin as dry rice paper
Donor
Jan 12, 2020
1,230
1,451
Your images are huge, at a guess maybe it's people on laptops or shitty pc's running out of memory. They should be .jpg's or webp's if you want to preserve transparency as a .png does.
That's my issue with the game. Not only do I play it on a laptop but it's a shitty laptop
 

7GC

Newbie
Game Developer
Nov 5, 2018
57
315
Wow, Thank you soo much....

This explains alot and its a great help. Thank you so much for taking out the time and explaining in such detail.
Also thanks for the script edit..
 

7GC

Newbie
Game Developer
Nov 5, 2018
57
315
A token of appreciation , unseen teaser image of new characters.
Not as much as you have worked , but just a little token from my side..

thank you
keep safe
teaser tandn.png
 

7GC

Newbie
Game Developer
Nov 5, 2018
57
315
Also are you aware how to add stats/variables like :

(MC)Dominant: the more dominant the more commanding actions the MC can take and future submissive options will not be available to the player
(MC)Submissive: The more submissive the more things will not be in the MC's control and future dominate options will not be available.
(Claire)Perversion: the more perverse Claire is the more sexual actions will be available to the MC. for example if shes a little perverted she's dress more modest and only go as far as a blowjob. but the more perverted she is the more revealing she will dress and you could fuck her in the ass and cum on her face in public
(Haley)Exhibitionism: this is just an example but the more of an exhibitionist Haley is the more risky the actions you can make her do.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,607
2,256
Probably something like:

Python:
define t = Character("Tom")

default tom_dom = 0
default tom_sub = 0
default claire_perv = 0
default haley_exhib = 0

label start:

    menu:
        "[t] picks dom action":
            $ tom_dom += 1
            c "Oh, how manly."

        "[t] picks sub action":
            $ tom_sub += 1
            c "That's a good boy."

label story_continues:

    if tom_dom >= 1:
        jump tom_dom_route

    if tom_sub >= 1:
        jump tom_sub_route

    jump tom_neutral_route # Not that a neutral route would be needed in this example

# blah, blah, more code.

default is a sort of "create variable and assign the initial value". There are others ways to do it... this is the better way.

$ is basically "do python command". Don't ask me why you need to invoke python to set variables... it just "is".

$ tom_dom += 1 adds 1 to the variable tom_dom.
... though you could also write it as $ tom_dom = tom_dom + 1. += is just a shorthand version.

Alternatively there's also -= which would subtract a number.

There are lots of alternative . += and -= are just the most commonly used in RenPy games.


For the checks...
  • == is an "equal to" check
  • > is a "greater than" check
  • < is a "less than" check
  • >= is a "greater than or equal to" check
  • <= is a "less than or equal to" check
  • != is a "not equal to" check
These can be combined with for and, or or not.

if tom_dom >= 6 and tom_sub <= 2:
-or-
if tom_dom >= 6 or haley_exhib >= 4:

if: statements don't need to only do jump. That's where python's indented code comes in. It can be a single line for a jump, or a dozen lines of dialogue or anything else you can think of.

Finally, there's a "do something or otherwise do something else" variation for using if: statements.

Python:
    if tom_dom >= 4:
        jump tom_dom_route
    else:
        jump tom_sub_route
(there is also something called elif:, but honestly - you're not at that stage yet).

You might want to consider a single variable for Tom's dom/sub status. Where dom actions do += 1 and sub actions do -= 1 instead. Depends on your game of course and how you want to structure future actions/events.

I've called my variables things like tom_dom largely out of habit and experience. The secret is to make variable (and label) names short enough to be easily typed over and over again, but long enough to still be recognizable for what they are. I also tend to separate "parts" of a variable name out with underscores to make it easier to recognize. I could just as easily used tomdom, tom_domination or tomdomination - though I hope you can see why they wouldn't be my first choices for naming styles.

If in doubt... forget variables. It's so easy to try to adopt too many new concepts to quickly. It's okay to write a kinetic novel, with largely no choices and no variables. Better that, than getting into troubles by getting out of your depth too quickly.
 
Last edited:
  • Like
Reactions: Baka_Energy_studios

Bearded_NoPants

Skin as brittle and thin as dry rice paper
Donor
Jan 12, 2020
1,230
1,451
Probably something like:

Python:
define t = Character("Tom")

default tom_dom = 0
default tom_sub = 0
default claire_perv = 0
default haley_exhib = 0

label start:

    menu:
        "[t] picks dom action":
            $ tom_dom += 1
            c "Oh, how manly."

        "[t] picks sub action":
            $ tom_sub += 1
            c "That's a good boy."

label story_continues:

    if tom_dom >= 1:
        jump tom_dom_route

    if tom_sub >= 1:
        jump tom_sub_route

    jump tom_neutral_route # Not that a neutral route would be needed in this example

# blah, blah, more code.

default is a sort of "create variable and assign the initial value". There are others ways to do it... this is the better way.

$ is basically "do python command". Don't ask me why you need to invoke python to set variables... it just "is".

$ tom_dom += 1 adds 1 to the variable tom_dom.
... though you could also write it as $ tom_dom = tom_dom + 1. += is just a shorthand version.

Alternatively there's also -= which would subtract a number.

There are lots of alternative . += and -= are just the most commonly used in RenPy games.


For the ...
  • == is an "equal to" check
  • > is a "greater than" check
  • < is a "less than" check
  • >= is a "greater than or equal to" check
  • <= is a "less than or equal to" check
  • != is a "not equal to" check
These can be combined with for and, or or not.

if tom_dom >= 6 and tom_sub <= 2:
-or-
if tom_dom >= 6 or haley_exhib >= 4:

Finally, there's a "do something or otherwise do something else" variation for using if: statements.

Python:
    if tom_dom >= 4:
        jump tom_dom_route
    else:
        jump tom_sub_route
(there is also something called elif:, but honestly - you're not at that stage yet).

You might want to consider a single variable for Tom's dom/sub status. Where dom actions do += 1 and sub actions do -= 1 instead. Depends on your game of course and how you want to structure future actions/events.

I've called my variables things like tom_dom largely out of habit and experience. The secret is to make variable (and label) names short enough to be easily typed over and over again, but long enough to still be recognizable for what they are. I also tend to separate "parts" of a variable name out with underscores to make it easier to recognize. I could just as easily used tomdom, tom_domination or tomdomination - though I hope you can see why they wouldn't be my first choices for naming styles.

If in doubt... forget variables. It's so easy to try to adopt too many new concepts to quickly. It's okay to write a kinetic novel, with largely no choices and no variables. Better that, than getting into troubles by getting out of your depth too quickly.
JESUS! you Devs are something. I was curious how 7GC was fixing his issue but this...
head on fire.gif
I am in awe as this stuff is beyond me
 

7GC

Newbie
Game Developer
Nov 5, 2018
57
315
Regardless both of you have been a great help and this game will be credited with both of you. As long as the game is being developed all is good