Ren'Py Taking the devil from the horns - Day night cycle plus calendar

Deleted member 416612

The 'landlord'
Donor
Game Developer
Feb 2, 2018
923
3,925
Hi mates,

As you are the spring of hope and I am half retarded, I came to one of my biggest features that I want to implement.

I want to implement in the game, a day-night cycle and a calendar.
What that mean?! The user can go into a location and click on an object, for example, the bed, and choose to nap/sleep or something like that until the night from the current day or until tomorrow (daylight).
If he/she chooses to progress to the next day, that will mean that it will advance a day in the calendar.
As a side note, I was thinking to activate the free-roaming screens according to the day/night option.

What is the best option to approach this?

Cheers
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,964
16,209
If he/she chooses to progress to the next day, that will mean that it will advance a day in the calendar.
For the calendar part, there's many options in this thread, plus this option.


As a side note, I was thinking to activate the free-roaming screens according to the day/night option.
I'm not sure to understand what you mean by this. Do you want to have locations available only at a particular time of the day ?
Code:
# whatever which one you choose.
default calendar = MyCalendar()

screen whatever:
    # Available only before 10 AM
    # Assume that XXX.hour is where the actual 'hour' is stored.
    if calendar.hour < 10:
        imagebutton:
             auto "thisButton_%s"
             action Jump( "there" )
    else:
        # Else, display a "not available" version.
        add "thisButton_DISABLED"
    imagebutton:
         auto "thatButton_%s"
         action Jump( "here" )

Or do you want the background to change according of the period of the day ? By example darker at dawn and dusk, with candles at night, and things like that ?

For this, your calendar object need to have something like this :
Python:
    class MyCalendar( ... ):
        [...]

        @property
        def lighting( self ): 
            # Before 6 AM it's night.
            # Assume that self.hour is where the actual 'hour' is stored.
            if    self.hour < 6: return "night"
            # Between 6 AM and 8 AM it's dawn.
            elif self.hour < 8: return "dawn"
            # Between 8 AM and 8 PM it's day.
            elif self.hour < 20: return "day"
            # Between 8 PM and 10 PM it's dawn...
            # well in fact dusk, but the lighting is near
            # and it's one image less to generate.
            elif self.hour < 22: return "dawn"
            # After 10 PM, it's night.
            else: return "night"
Then you use it like this :
Python:
# whatever which one
default calendar = MyCalendar()

label whatever:
    # Build the name of the image according to the lighting.
    # If it's before 6 AM, the image used will be "my_beautiful_CG_night",
    # if it's 5 PM, the image used will be "my_beautiful_CG_day",
    # and so on.
    show expression "my_beautiful_CG_{}".format( calendar.lighting )
    [...]
    # Same than above, because it also works with /scene/.
    scene expression "my_beautiful_CG_{}".format( calendar.lighting )

screen whatever:
    # Same than above, but with /add/ you can build the name directly.
    add "my_beautiful_CG_{}".format( calendar.lighting )
This while having those files in your images directory :
  • my_beautiful_CG_night.jpg
  • my_beautiful_CG_dawn.jpg
  • my_beautiful_CG_day.jpg
Unlike the auto "mybutton_%s" property of an imagebutton, there's no securities here ; the three variations need to exist.
 

Deleted member 416612

The 'landlord'
Donor
Game Developer
Feb 2, 2018
923
3,925
For the calendar part, there's many options in this thread, plus this option.




I'm not sure to understand what you mean by this. Do you want to have locations available only at a particular time of the day ?
Code:
# whatever which one you choose.
default calendar = MyCalendar()

screen whatever:
    # Available only before 10 AM
    # Assume that XXX.hour is where the actual 'hour' is stored.
    if calendar.hour < 10:
        imagebutton:
             auto "thisButton_%s"
             action Jump( "there" )
    else:
        # Else, display a "not available" version.
        add "thisButton_DISABLED"
    imagebutton:
         auto "thatButton_%s"
         action Jump( "here" )

Or do you want the background to change according of the period of the day ? By example darker at dawn and dusk, with candles at night, and things like that ?

For this, your calendar object need to have something like this :
Python:
    class MyCalendar( ... ):
        [...]

        @property
        def lighting( self ):
            # Before 6 AM it's night.
            # Assume that self.hour is where the actual 'hour' is stored.
            if    self.hour < 6: return "night"
            # Between 6 AM and 8 AM it's dawn.
            elif self.hour < 8: return "dawn"
            # Between 8 AM and 8 PM it's day.
            elif self.hour < 20: return "day"
            # Between 8 PM and 10 PM it's dawn...
            # well in fact dusk, but the lighting is near
            # and it's one image less to generate.
            elif self.hour < 22: return "dawn"
            # After 10 PM, it's night.
            else: return "night"
Then you use it like this :
Python:
# whatever which one
default calendar = MyCalendar()

label whatever:
    # Build the name of the image according to the lighting.
    # If it's before 6 AM, the image used will be "my_beautiful_CG_night",
    # if it's 5 PM, the image used will be "my_beautiful_CG_day",
    # and so on.
    show expression "my_beautiful_CG_{}".format( calendar.lighting )
    [...]
    # Same than above, because it also works with /scene/.
    scene expression "my_beautiful_CG_{}".format( calendar.lighting )

screen whatever:
    # Same than above, but with /add/ you can build the name directly.
    add "my_beautiful_CG_{}".format( calendar.lighting )
This while having those files in your images directory :
  • my_beautiful_CG_night.jpg
  • my_beautiful_CG_dawn.jpg
  • my_beautiful_CG_day.jpg
Unlike the auto "mybutton_%s" property of an imagebutton, there's no securities here ; the three variations need to exist.


Related to the free roaming, it was about changing backgrounds accordingly with the night/day option the user will choose.
For the interface, the user will have to choose, from a button, to progress to the night of the current day or to progress to the next day/night. I don't think I will add time, only day, month and year for the players to progress.

I have a question as I've read it in your example anne O'nymous related to variables. If I implement this feature now, players that have old save games will be impacted in a way?

I want to thank you both for your help and I am grateful that you are helping me with this feature.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,964
16,209
I have a question as I've read it in your example anne O'nymous related to variables. If I implement this feature now, players that have old save games will be impacted in a way?
Er... It depend of the way you do it.
The obvious problem is the addition of the "calendar" object. But for this a simple
Code:
default calendar = MyCalendar()
will do it.

If you add this only to parts that aren't wrote yet (well, at least not on the last released update), the problems stop here.
But if you add this to parts already present in previous update, then there's a second problem, which is more of a concern. Simply because you have no way to know what day it should be ; have the player saved during what is Friday the 13th for new players, or have he saved during what is Wednesday the 24th ?

From my point of view, the best options is to trick the player with an empty period of times.
First you set the date for players using a save file :
Python:
label after_load:
   # /month/ or something else. As for the value, /None/
   # or whatever you'll use as default value. 
   # The goal is to be sure that it's a never used calendar...
   if calendar.month == None:
        # ...then to set a believable default date.
        calendar.day = "Tuesday"
        calendar.dayOfMonth = 1
        calendar.month = "March"
Then you add something like this, more or less at the start of the next update [Note: It's a really cheap example] :
MC goes for a walk in the forest.
"Oh, look", say the MC, "what a beautiful bird."
"Boom !", say the tree that the MC hit really hard because he wasn't looking.
[place here a beautiful screen saying "Few days of unconsciousness later..."]
[Force the date to now be Monday the 14th March]
MC finally wake up and return home.
Mother "What the fuck ? Where were you all this time ?"
Sister "Alright, this time it's sure, I'll kill you !"
MC "What can I say ? The bird was really beautiful, and the tree a real asshole."


Count more or less the number of days from the start to this event, add 1 or 2, and go for it, using the result as date for the MC awakening.
99% of the new players will have a coherent result. The other 1% will perhaps go back in time of few days, but probably don't even notice it. As for the players using a previously saved file, they'll fallback on the right track and, starting now, will have the same date than anyone else.

What matter isn't how the players are tricked, but that you have a reason to pass one or two days in one second. It's what will synchronize the date for all the players, a blank "days passing" screen, a forced date, and it's good.
 

Deleted member 416612

The 'landlord'
Donor
Game Developer
Feb 2, 2018
923
3,925
Er... It depend of the way you do it.
The obvious problem is the addition of the "calendar" object. But for this a simple
Code:
default calendar = MyCalendar()
will do it.

If you add this only to parts that aren't wrote yet (well, at least not on the last released update), the problems stop here.
But if you add this to parts already present in previous update, then there's a second problem, which is more of a concern. Simply because you have no way to know what day it should be ; have the player saved during what is Friday the 13th for new players, or have he saved during what is Wednesday the 24th ?

From my point of view, the best options is to trick the player with an empty period of times.
First you set the date for players using a save file :
Python:
label after_load:
   # /month/ or something else. As for the value, /None/
   # or whatever you'll use as default value.
   # The goal is to be sure that it's a never used calendar...
   if calendar.month == None:
        # ...then to set a believable default date.
        calendar.day = "Tuesday"
        calendar.dayOfMonth = 1
        calendar.month = "March"
Then you add something like this, more or less at the start of the next update [Note: It's a really cheap example] :
MC goes for a walk in the forest.
"Oh, look", say the MC, "what a beautiful bird."
"Boom !", say the tree that the MC hit really hard because he wasn't looking.
[place here a beautiful screen saying "Few days of unconsciousness later..."]
[Force the date to now be Monday the 14th March]
MC finally wake up and return home.
Mother "What the fuck ? Where were you all this time ?"
Sister "Alright, this time it's sure, I'll kill you !"
MC "What can I say ? The bird was really beautiful, and the tree a real asshole."


Count more or less the number of days from the start to this event, add 1 or 2, and go for it, using the result as date for the MC awakening.
99% of the new players will have a coherent result. The other 1% will perhaps go back in time of few days, but probably don't even notice it. As for the players using a previously saved file, they'll fallback on the right track and, starting now, will have the same date than anyone else.

What matter isn't how the players are tricked, but that you have a reason to pass one or two days in one second. It's what will synchronize the date for all the players, a blank "days passing" screen, a forced date, and it's good.

Thank you for your help, mate. You are a coding angel. I will put at good used what you've shown me. Fingers crossed and I will return with feedback.
 
  • Like
Reactions: anne O'nymous