Creating and implementing a cycling period/day system (Sugarcube 2)

0 votes
asked Aug 6 by Shaloamus (190 points)
Hey everyone, I just recently got started in Twine and I am making my second game. I want to implement a day system (seven days, specifically) with two different time periods per day ("Day" and "Night"), and have it loop by having the player sleep. I have been scouring the web for a way to do this, but I don't come from a programming background (quantitative thinking is not my strong suit either) and a lot of this is lost upon me. I understand it that such a system would be an array based either in Javascript or SoryInit, but I am not sure how to set up said array or implement it into the story itself as an action.

Sorry if this comes off as overly ignorant, once again I am not a programmer an am super new at this. So if anyone has the time, patience, and mercy to give me a step-by-step guide on how to get this done; it would really help! Thanks again!

1 Answer

+2 votes
answered Aug 7 by HiEv (11,760 points)

Actually, this is a really standard question.  See for example:

Help making a simple Clock and Calendar system, for sugarcube 2.21 in Twine 2.2.1

How to implement time and date?

[Sugarcube] How would I do this? Custom advancing time/countdown?

A couple things for a SugarCube game I'm looking for

The short version of all that is the easiest thing to do is to use the JavaScript Date object to keep track of the day, assuming you're using the standard Gregorian calendar.  So in your StoryInit passage you could set the starting date like this:

<<set $gameDate = new Date('December 17, 1995 03:24:00')>>

and then you could display the date using the .toLocaleString() function like this:

<<-$gameDate.toLocaleString("en-US", { weekday: 'long', month: 'short', day: 'numeric', year: 'numeric' } )>>

That would output something like "Wednesday, Dec. 17, 1995".  See the above link for other options you could set in that function to change how it displays the date and/or time.

To track the day/night cycle, just make another variable to track that.  For example, you would initialize it like this in your StoryInit passage:

<<set $gameTime = "Day">>

and then you can advance time using something like this:

<<if $gameTime == "Day">>
	<<set $gameTime = "Night">>
	<<set $gameTime = "Day">>
	<<set $gameDate.setDate($gameDate.getDate() + 1)>>

That would change day to night, and would also advance the date when going from night to day.

You could put that code inside of a widget if you want to be able to use that anywhere in your story.  (If you do create a widget, make sure you tag the passage it's in with "widget".  Also, tagging it with "nobr" will help prevent unnecessary blank lines.)

Hope that helps! smiley

commented Aug 7 by Shaloamus (190 points)
Thanks, that is a huge help! Is there any way I can change the dating parameters though? I want the game to only have seven days, and each day be labeled as such ("Day One", "Day Two", Day Three", etc.) when creating the date system. Is there a way to output that, or am I stuck with the regular calendar time?
commented Aug 7 by HiEv (11,760 points)

There are a couple of ways of doing that.  Creating your own variable (like $gameDay) to keep track of the game days, and advancing it by 1 when the day changes, would always work.  However, if the game will be 31 days or less you could just use the .getDate() function to get the game day.

You can also just use an array to convert the numbers to strings like this:

Day <<-["One", "Two", "Three", ...etc...][$gameDay - 1]>>

(You'll have to fill in the "...etc..." part yourself.)

That uses "[$gameDay - 1]" to get the element in the array (the part with the numbers in it) at that index (array indexes begin at zero).  For example, if $gameDay was set to 3, then the item at index 2 (3 - 1 = 2) would be "Three".

I'd convert that to a widget if you plan to display the game day in more than one passage.

Have fun! smiley

commented Aug 8 by Shaloamus (190 points)
Thanks man, I finally set one up! One last question though (I am so sorry for continually bugging you and/or anyone else with these dumb questions): Now that I have the two time metrics set up, how do I implement ways to change them in-game? Right Now I have both set up in a widget (connected to variables present in my StoryInit) like this:

<<set setup.PERIODS to ["Day", "Night"]>>
<<set setup.DAYS to ["Day One", "Day Two", "Day Three", "Day Four", "Day Five", "Day Six", "Day Seven"]>>

and two more widgets to change the time, looking like this:

<<widget "DaytoNight">>
    <<if $gameTime == setup.PERIODS[0]>>
        <<set $gameTime = setup.PERIODS[1]>>


<<widget "NextMorning">>
    <<if $gameTime == setup.PERIODS[1]>>
        <<set $gameTime = setup.PERIODS[0]>>
        <<set $gameDay = setup.DAYS[] += 1>>


How would I go about making options for the player to change those times? Specifically with "Wait" and "Sleep" buttons? I tried setting up a link like this:
<<link "DaytoNight">>
    [[Wait |living room]]

And the option shows up, but it tells me that elements of the link don't exist and nothing happens. Again, sorry for the continual badgering; you have been awesome so far!
commented Aug 8 by HiEv (11,760 points)
edited Aug 9 by HiEv

To advance the day you could use the code I gave you originally and add the $gameDay:

<<if $gameTime == "Day">>
	<<set $gameTime = "Night">>
	<<set $gameTime = "Day">>
	<<set $gameDate.setDate($gameDate.getDate() + 1)>>
	<<set $gameDay += 1>>

Also this part of your code:

<<set $gameDay = setup.DAYS[] += 1>>

isn't valid code.  You can't add 1 to an array with a missing index, which is what that code tries to do.  I assume you meant to do this:

<<set $gameDay += 1>>

You could then display the day like this:

<<-setup.DAYS[$gameDay - 1]>>

Though a shorter way of combining those two lines would be this:


because that would print the day based on the current value of $gameDay, and after that the "++" at the end would increment the value of $gameDay by 1 (a "post-increment"; as opposed to a "pre-increment" which, by putting the "++" in front of the variable, would increment the variable first, instead of last).

As for your <<link>> macro code, you're not quite using it correctly.  I think what you're trying to do is this:

<<link [[Wait|living room]]>>

That would show a link which says "Wait", and clicking it would first trigger your <<DaytoNight>> widget, and then it would take you to the "living room" passage.

Hopefully that answers your questions.

If you have any other questions, it's probably best to start a new question, since I don't always check back to see if there are new responses.

Have fun! smiley

Welcome to Twine Q&A, where you can ask questions and receive answers from other members of the community.

You can also find hints and information on Twine on the official wiki and the old forums archive.

See a spam question? Flag it instead of downvoting. A question flagged enough times will automatically be hidden while moderators review it.