Keeping everything together, instead of spread apart.

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
ISAWHIM
Veteran
Posts: 318
Joined: Sun Nov 06, 2016 5:34 pm
Contact:

Keeping everything together, instead of spread apart.

#1 Post by ISAWHIM »

I am trying to find a creative (or logical) way to keep all of my relevant code together, instead of the "common" way of spreading it out.

EG, This is the "common" way to code it...

#My Vars for "locations", with all attributes/images
# #1
# #2
# #3...
#My Vars for "characters", with all attributes/images
# #1
# #2
# #3...
#My Vars for "interactons", with all attributes/images
# #1, Etc...
#-------------
#Locations python code/functions
# #1, Etc...
#Characters python code/functions
# #1, Etc...
#Interactions python code/functions
# #1, Etc...
#-------------
#(The following isolated, because the "code" components are too tedious to manage/code/write, and/or the "flow" doesn't work {jumps/labels/returns} otherwise.)
#Location RenPy stuff (Dialogue and RenPy specific functions)
# #1, Etc...
#Character RenPy stuff (Dialogue and RenPy specific functions)
# #1, Etc...
#Interaction RenPy stuff (Dialogue and RenPy specific functions)
# #1, Etc...

=================================

What I am trying to do, in essence is this...

#Character #1 stuff...
# - Vars
# - Code
# - RenPy stuff

#Character #2 stuff...
# - Vars
# - Code
# - RenPy stuff

#Location #1 stuff...
# - Vars
# - Code
# - RenPy stuff

#Location #2 stuff...
etc...

#Interaction #1 stuff...
# - Vars
# - Code
# - RenPy stuff

#Interaction #2 stuff...
etc...

========================================

This way, I don't have to jump all over thousands of areas, looking for various components of each of the same exact things, but in various areas of "specific grouped code".

I just create a new "thing" (Character, Location, Interaction, Object, Asset, Whatever), and everything for that "thing", is all in one spot. Something that RenPy does not seem designed for, nor Python, as both prefer/demand the other style of "chop it up and spread it out all over the place", type of coding.

The closest I have gotten, is something like this... (This is not actual code, just a method.) This uses only the "Interactions" as an example, but it would extend to all things. (For me, the interactions are the largest and most demanding.)

The program would run through the whole set of code, for the game/novel. This sets the variables and skips the non-setup code and dialogue, until it hits the end. At the end, the "run" variable is set. Now, since all variables are set, it can run the code parts. However, it does not traverse the whole thing again, as code is only needed when each area/thing is needed. It "runs" in a game-loop, which actually resides at the end of all the code. (So if it, for some reason, jumps out of the loop, it just ends the game. As opposed to running through all the code, looking for an end.)

In the "game-loop", depending on the game-loop code... It jumps to various "locations" and "characters" and "interactions", triggering the Python code sections specific to those things, and the associated dialogues and RenPy things. (Which are all together, not spread-out, as they would normally be.)

# This is actually the end of something above...
# jump GameLoop
#
####(Interaction #1)####
# These sections only "seen" in the initial "pre-run", above label, for "tween" isolation.
# Vars specific to the interaction, setup
# label Interaction1:
####(The "code" part)####
# Code components, skipped unless "run" is set
####(The "RenPy" stuff)###
# Dialogue, etc... Skipped unless "run" is set
# jump GameLoop
#
####(Interaction #2)####
# Vars specific to the interaction, setup
# label Interaction2:
# etc...

================================

Is there some other way I could be doing this, to ease the split-personality style coding, common in most programming languages?

User avatar
ISAWHIM
Veteran
Posts: 318
Joined: Sun Nov 06, 2016 5:34 pm
Contact:

Re: Keeping everything together, instead of spread apart.

#2 Post by ISAWHIM »

Adding a NOTE:
- There will not be a "rollback" function and chances are quite possible that I will not be using the buggy save-game feature built-in to RenPy, as it fails to function with any updated content, in all my tests. (Where code changes, as opposed to being simply appended to existing content. Which is 99% of all updates in most games.) Save games will be a basic record of stats and a location, which is all that is honestly needed for any save-game. (As opposed to a "game-state" style save, which RenPy uses. Taking a snapshot of a previous version of a game, and expecting it to function in a new version, is NOT a possibility in this case.)

=================

My only OTHER alternative, is to make/program a pre-compiler, which would output the typical format, but manage it in groups. Thus, it would spit-out the files with all the classes and python variables at the top, followed by all the RenPy variables that depend on the above classes and python variables, followed by the python functions, then RenPy style functions, etc...

However, that, once again, requires a whole other layer of additional and unwanted programming, defeating the purpose of being simple or easy or fast. (Well, until that was programmed. Then it would be simple, easy and fast, minus additional development time.)

Also, it would require the "project" to be essentially duplicated. Since it would not be a reversible process. Once split-up, there would be no way to tell which things went with which groups. Not to mention the delays of having to pre-compile, so that RenPy could then compile into Python, before it ran. (Also, making errors irrelevant, since they would refer to the disjointed code, not the programmed code.)

Thus, my reasoning for wanting to do this, as easily as possible, using only RenPy hacks.

I considered using "init", but that just adds a whole additional set of over-complexity for something that should be automatic, but it isn't. Making it even more demanding and prone to errors and failure, without any easy way to edit, locate or fix things.

User avatar
sunwave
Regular
Posts: 45
Joined: Fri Apr 15, 2016 2:26 pm
Location: Netherlands
Contact:

Re: Keeping everything together, instead of spread apart.

#3 Post by sunwave »

If you want stuff to be initialized before the game actually starts, then can't you define the "pre-run" stuff in init blocks? As far as I know, I think you can put those anywhere (not inside a label) and they will run before the actual rest of the game runs. At least, if you need to define variables and characters and stuff. But because I'm not sure WHAT you want to do pre-run and what you want to do during-run I can't say if it will work or not. Especially because the "common" way does seem logical to me already. I cluster by "function of the code" and not "function in the story".

I am not sure what you're trying to achieve, though. Are you just trying to re-order the text so that related stuff is *visually* clustered (and easy to find and look up problems)? Then I have three solutions:
- Use init blocks for the pre-run stuff.
- Or use (convoluted) jumping around in the script (not recommended).
- Use if-statments wrapped around whole labels (sloppy, but slightly better than jumping around).

User avatar
ISAWHIM
Veteran
Posts: 318
Joined: Sun Nov 06, 2016 5:34 pm
Contact:

Re: Keeping everything together, instead of spread apart.

#4 Post by ISAWHIM »

Thanks SunWave, What you have described in your reply, is essentially where I am at now... (Jumping through ten hoops to stay within the lines on the road.)

The "init" things always seem to fail for me. Leading to things being undefined, or empty after loading a saved game. (I found some page that gave an oddball work-around to get the inits to actually function like inits, which involved forcing the values into RenPy variables.)

I'll have to double-check and see if some of my "inits" are nested in a block, but I don't think they are. (Honestly, that shouldn't matter, that is the point of typing "init"... to extract it and place it above all, no matter where it is. It only has one function, initialize. The point of it being typed, is that it is intended to put anywhere. Again, another "compilers job", not being done correctly.)

This is why I have the classes and variables between blocks, above the jump-labels. (Using jump, because calls and returns are the most oddball setup I have ever seen. It tags each call with an ID that you actually see in your code and messes everything-up if you alter them later. Like in updates or recompiling, which causes them to mismatch when loading a saved-game. Oddly, it is obviously done for "save game" purposes.)

Eg... (Back to the specific example, of one specific location. Imagine the following lines being the other locations...)

I have a "House" for "Bob" and one for "Sue"... Each have bedrooms and livingrooms, etc...

There is a class for houses and one for rooms, waaaay at the top of the list of locations, but the classes are not set there, they are set here, into RenPy/Python accessible values.

label House_Bob:
# Here is all the values for the class instance "House_Bob", telling the program that there is a house for Bob.
# Also, here is all the values for the room class of Bob's house... but the only "room" is "Entrance" for now...
# Here is a set of code, which fires when you enter Bob's house...
# Here is some {Conditional dialogue} that MAY happen, if you enter Bob's house...
label House_Bob_Livingroom:
# Here is all the values for the class instance "House_Bob_Livingroom", telling the program that this room exists and has certain attributes and functions. (appended class instance, to a list)
# Eg, Bob's computer, Bob's couch, Bob's desk...
# Here is the code for the livingroom...
# Here is the {conditional dialogue}, for the livingroom...
label Bob_Computer:
# NOTE: No "House" here... Due to below...
# Actually another asset type, this is a python function to that asset... Since this is about "Locations" and not "Items" or "Interactions".
# Here, so I can see and interact with it, from this location and (in code), I know it is setup in the house, without having to go to the list of assets.
# However, some items MAY also be listed here... Like something that is only in Bob's house, or a closet, within a room, in Bob's house, in the Livingroom.
label House_Bob_Kitchen:
# Here, back to actual rooms again...

For simplicity, all locations are in one section. Some have owners, some do not. Some are generic, some are specific. However, moving all the classes to all the other classes, and all the setup-values to all the other setup-values, and all the functions with all the other functions, would make it a pain in the ass to manage. I would have to keep flipping back and forth, and then apply similar groupings to each area, just to make in partly manageable.

This way, I just open the locations file... Since I am setting-up locations, and jump right to the location (which I visualize in reality as a physical location), and start coding. (Visualize, as in, x room is in y house, and holds z items.)

This also extends to characters. All images, sounds, associated locations, items, etc... are all with each character. (Again, coded as one normally visualizes.)

I don't want to go to the doctor to find what Bob's mood is, then have to go to the clothing store to figure-out what he is wearing, then have to run to the other side of town to the city-hall to figure-out if he owns a home, then run to home-depot to see if he purchased a bed for his bedroom, then have to go to the lecture-hall to hear him talk and eventually have to visit his therapist to interact with him... (Which is what spreading all the code around into non-associated arbitrary groupings is doing.)

I want to know everything about Bob, from his online profile on facebook, in one place.

I want to know everything about his house, just by looking at his ad on homes-and-gardens, in one place.

I want to see every item in the game, right on amazon, with full descriptions, in one place.

Just like I expect in real life... But in a more creepy way! ;)

Not sure if that makes sense to anyone other than me. lol. :P

{Actually, I identify each type of asset as a "l" = location, "c" = character, "i" = item, etc... Thus, it would be class instances lHouse_B and iComputer_B and cB, with "B" being Character("Bob"), which helps a little, when coding.}

User avatar
trooper6
Lemma-Class Veteran
Posts: 3712
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: Keeping everything together, instead of spread apart.

#5 Post by trooper6 »

First off. I don't know why you are using labels to define variables. That is going to cause you problems. Your variables should be defined using "default"

All you do is create a file called bob.rpy

Then you define your variables:

Code: Select all

default house_Bob = House(var1, var2, var3)
default blah blah
if you have any functions that are specific to bob put there there in your init python block.

But you seem to have a lot of thing in labels that just look like they should be classes and methods of classes.

You seem to be making this way more complicated than it needs to be.
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

User avatar
ISAWHIM
Veteran
Posts: 318
Joined: Sun Nov 06, 2016 5:34 pm
Contact:

Re: Keeping everything together, instead of spread apart.

#6 Post by ISAWHIM »

Making it complicated will make it easy to manage. Keeping it simple, makes it impossible to manage. I already have "easy" and "impossible", that takes no effort to do. (That is the "common" way.)

It is easy to build a dam with dirt and a spoon... but it is impossible to sustain it, if it ever gets completed.

It is complicated to use cement and trusses and machines to build a dam... but it is easy to sustain once completed.

I am using the labels as intended, jump points to enter components of the story. I am not jumping to initiate the classes. They are initiated at the top, then setup in each area that they are associated with. However, because you don't "jump" at the launch of the game, it must traverse the whole game to get the set values as RenPy variables, from those sections, before the game even knows there is a location to jump to. (The game knows there is a jump, because within the jump, is the variable that tells the game that it exists. As opposed to dissociating that code by moving that to the top, and out of the area it is associated with. Where all the other code for that area is also located.)

Everything always jumps back to the game-loop. I am not actually jumping around from spot to spot. The game-loop is determining which places to jump to, once it knows they exist and are needed, to get the RenPy display stuff and do the conditional checks for just those things. (As opposed to one massive if-then super-nested block or marathon of code, or thousands of functions more than I already have planned.)

Maybe I should have explained this part first...
1: The story/game is a free-roaming style of game.
2: There are many locations that characters travel to. (Well over 200 at the moment. 4 maps with 10 buildings each, having about 5 rooms in each building.)
3: They have schedules, which change, based on certain events. (School, Vacation, Work, Days-Off)
4: There are hundreds of "actions" that can be done, at various locations, with certain individuals.
5: At the moment, there are only five characters, including the protagonist. (More expected.)

So... Throwing all "classes" things into one location and all dialogue into another, with all code in another... Would make this horribly unmanageable. Like I said, I would be looking at code and having to "figure out" which dialogue it leads to... Then look at a class/variable, and have to "figure out" what it includes, or what the values are, and where they were... etc... I would be living in "Search", and pulling hair trying to remember what I called everything. (Not all things I name are normal names, due to obvious conflicts with unique names.)

My way, though it may seem abnormal, is actually more logical to manage. (For me.)

Yes, it is confusing to setup, which is why I am seeing if there is a better way. Doing the "split it up all over", is not a better way. That is the unmanageable way I am trying to avoid.

I am using individual files to assist the development, as you suggested with "Bob", but that still requires the use of labels to get there, and back to the game-loop, which manages the whole game. It is not a linear traversing story.

Eg, The game-loop runs at two levels. One for the DAY and one for the HOUR, nested, obviously. When there are no more hours left in a day, that returns back to setup the new day of events, by the hour. Each hour, (X, Y, Z) can be done. Which is determined by the code that looks at the schedules, picks events that can occur and makes them available for selection. These events happening at locations involving the characters who are doing "things". Thus, each label is jumped to, to setup the sum of all things, displayed as the "story".

- Bob is at Home, in the Bedroom, at the Bed, Reading a book.

- You see that he is "Home", but you have no idea what he is doing, until you go there. (Jump to Home_Bob, display RenPy Dialogue for his home.. Do you have to knock, or just enter with the key, are you expected?)

- You enter "Home_Bob", which jumps to where he is at, in his home... (Jump to Home_Bob_Bedroom, display RenPy Dialogue for him, in his bed... What is he doing there? Reading, Sleeping, Spanking one out?)

- You interrupt him reading, you have jumped to Bob_Reading(Home_Bob_Bedroom), the action function, and where he is doing it. (There was a stacked RenPy dialogue, for the Bedroom and now the conditional RenPy dialogue for the action "Bob_Reading".)

- Finally, you are at the actual interaction, as opposed to displayed dialogue. (He places his book down, talks to you about the story in it and you ask him to join you at the "Park_Picnic". Triggering the beginning of an event. This locks-out Bob's schedule and anyone who is also going. The rest of the characters continue the normal schedule they have.)

- Now, if Sue was in Bob's house, between you and Bob, along the way... You would have also run into her, with her actions available within Bob's house, which are not the same as the actions she has in her house. (Thus, the label-jump to see who is available to do what, in which location. That conditional RenPy dialogue is right in Bob's house, not Sue's house, or nested away in some long-ass chunk of disassociated code that I would have to find, if it even exists, if I even remember what it is called.)

So...

To gain the advantage of using RenPy's "easy" and "manageable" and "intuitive" story-dialogue and displays... I have to use the labels to jump-to, in order to keep from using the horrible Python-versions of that same code, to "display dialogue and scenes". But, I still need the Python code, for RenPy's shortfalls (Understandable, since it expects you to use Python for those things). Along with the Classes and Functions that I NEED all in the appropriate places. (Where they are actually used, not miles away in some other location of the code. Eg, not dissociated, where they might never be found again. Which also demands some kind of memorization of everything, which is impossible to do.)

With the abundance of common things, using memorable names is damn near impossible. Especially since RenPy is so "story word hungry" and greedy with the use of any form of those words in code. I can't use things like class attributes that have the name "label" or "pause" or "at" or "with" etc... even though they are attributes, and wouldn't interfere, it still breaks RenPy. Eg, Bob.with = ERROR-CAN'T-DO, because "with" is a function-initiator for "images at Position() with". Thus, I have to use more difficult words to remember, which are less intuitive. Like the use of "together" instead of "with"... Just to know who Bob is with. Okay, that one isn't that bad, but there are others too, even of my own doing. (Long story short... too much to memorize. It is like trying to memorize the entire Python library of functions. I am no savant. If I was, I wouldn't be using RenPy, I would be programming this in an actual lower-level language. Not a higher-level co-dependent scripting language. :P)

Plus, I want to show that RenPy can do this... With just RenPy's guts...

Once each section is setup, it is just a matter of Copy/Paste and changing the attributes. That is Waaaay easier than easter-egg hunts for snippets of code all over the place. Also trying to remember which chunk of code is in what files. Once setup, no old code changes. I just have to add more files, not edit older files. RenPy likes that more than editing existing things.

Eg, Add a new character = one new file... everything for them is there, except a place to live... That is another new file... Same with the actions they can do... I would not be editing any old code to expand for the content, throwing names and values into other disassociated groups. (Well, that isn't entirely true. If I have Donna with some special action in Bob's house, I have to edit Bob's house file too... But, I know where to find the houses, and just have to locate Bob's. If Donna doesn't exist later-on, then her code is irrelevant bloat. I can deal with that. I don't intend to remove people or locations or actions.)

It would be cool to put a whole chunk of RenPy code into a variable, but the only way to do that is to use the Python-versions of RenPy code, which is annoying to setup. renpy.Something(['FunkyFormatStuff', 'OddRequiredStuff']) as opposed to {bob "hello"} and {show bob} and {jump Home_Bob_Bedroom}. :P

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot]