DSE Tutorial
by ShiraiJunichi
The Files
The Files
The executable file to start a dse game is named "run_dse.exe". It loads the game stored in the "dse" folder. Here's a quick rundown of the files within the "dse" folder:
Of these five files, only two of them need to be edited- main.rpy, and events.rpy.
main.rpy
There are six parts of the main.rpy file:
The init Block Here is where you'll put all your customizations- such as a frame image, text colors, config variables, etc. You can also include characters and images, but those may be more properly placed inside the "events.rpy" file. One thing you can put here that's unique to the DSE is the group of dp (day planner) variables. In order to set those, you'll need a basic understanding of how days are structured by the day planner. - Day structure Every day has a given number of periods. Each period is specified by a string (such as "Morning"). Each period of the day has a corresponding variable telling what action is being done at that part of the day, and a set of possible actions that variable could be. Here's the default values of the dp variables, as found in the day_planner.rpy file:
With these values, the first period of the day is "Morning". The variable that stores the action is morning_act. The possible values that morning_act can take is "class" and "cut". The strings 'Attend Class' and 'Cut Class' are what is displayed to the user when choosing the corresponding action. The start Block Here you put code you only want to run once- at the very beginning of the game. First thing it should do is initialize the event engine. It should also initialize the day variable to 0, create any Stat objects you plan on using and set which stats should be displayed by the day planner.
- Stat Objects The implementation of the Stat object is within the stats.rpy file. A stat object takes three parameters- name, current value, and max value. A stat object will automatically keep a statistic's value between 0 and the max value (inclusive). The day Block Code placed here will run at the beginning of every day. At the very least you'll want to increment the day variable by one. You may want to notify the user what day it is. And if you're using the GUI dayplanner you'll want to set all of your period variables to None, and call the day planner.
You may not want the player to have the exact same choices of what to do for every day of the game. You can change the choices available to the player by altering the dp_period_acts variable within this block. Note, however, that this code will be run at the beginning of each day- so simply altering the dp_period_acts variable will change it for every day. You'll need to condition it on some boolean expression, or incorporate variables into the constructor. IMPORTANT! If you plan on changing any of the dp variables at runtime, you'll need to move the dp variable declarations outside of the init block and place them somewhere else! Blocks for Each Period of the Day For organizational purposes, you should have a block for each period of the day, though it will still work if you don't. The convention is to label each block after the period it is for. So for the block governing the "Morning" period, you could name the label morning. Unless it's the first period in the day you'll want to check if you should skip this period (some events may require you to skip periods- but an event can't make you skip the first period of a day). Then you may wish to notify the user of what period it is. Then you'll want to set varibles so that they are current. Then you run events for the current period.
The last line ends in a "2" because it is the second period of the day. Change it for each period of the day accordingly. The night Block This block will run after all events of the day are finished- no events run during this period.
The night Block A callback called from the day planner. It can be used to show dialog and stats to the user when the day planner is shown. The following code does just that:
events.rpy
If you didn't declare your character objects, images, and transitions in the "main.rpy" file, you can declare them in an init block within the "events.rpy" file. It makes a bit of sense to put them within this file instead, because they will be used more here. Besides those declarations, this file is basically a series of init blocks creating event objects, and labeled blocks that correspond to those created events. Those labeled blocks will contain the code that should be run when their corresponding events are selected to run. After you learn how to create events, writing this file becomes a snap. Creating Event Objects Events must be declared within init blocks. This is the basic way of creating an event:
The first string is the name of the event. When this event is chosen to run, it will look for a label of the same name. The second string is an expression that will evaluate to a boolean. If it evaluates as false, this event can't run. You could use something like... "act == 'exercise' and strength >= 50". The event.depends("some_event") parameters will prevent this event from running unless the input event(s) ran yesterday, or before. You can include as many, or as few, depend statements as you want. The event.solo() parameter means that if one event has already ran during this period, this event won't run. However, it won't stop events from running after it, if they aren't solos. The event.once() parameter means that this event will only execute once during the entire game. And lastly, the priority parameter sets the priority of this event. The lower the number, the higher the priority. Higher priority events will execute before lower priority ones. If no priority is given, it defaults to 100. Note: if two events are both able to run and have the same priority, which one gets priority is undefined. Avoid this scenario! Writing Blocks for Events Writing blocks for events is just like regular Ren'Py code. However, there are three things I'd like to mention:
A More Subtle Use of the Day Planner
The use of the GUI part of the day planner is actually completely optional. By omiting use of the GUI, you can make the flow of your game much more transparent, but still take advantage of the event engine. Steps to separating from the day planner GUI:
You'll want to make sure that you've declared the act variable somewhere in your code (probably the start block) before you make any calls to run events- otherwise you'll run into some errors. To make up for disabling the day planner GUI, you'll need to have events themselves change the act variable. Most likely, one variable won't be sufficient to store all the information you need to choose which events should run. I suggest making multiple variables that are conditions for events and are changed by the running of certain events.
Using Arcs to Structure Your Game: Basic Theory
It can be a bit mind boggling trying to imagine a jumble of events coming together, and somehow forming a game. This can be demystified with the idea of an event arc- a series of events where each one is dependant upon the previous one. With an arc, you are guaranteed that all events in the arc will execute in the proper order. A simple game could have two or three arcs that are relatively independant of each other. Each of these arcs would start at the beginning, and end at the end. It would be easy for the developer to write the game one arc at a time. Such a game would be fairly linear. The example dse game bundled with ren'py is a good example of this type of game. A more complex (and better) game would contain arcs that are intertwined. Progress within one arc could affect progress within another one. Perhaps some arcs begin halfway through the game, and perhaps others will finish subtantially before the game is over. Programming this kind of game is much more difficult, as you'll want to program all arcs concurrently. But it will help if you can keep a picture in your mind of all these arcs, and how they fit together, and affect each other. You'll probably benefit from drawing a visual map of all the arcs in your game. Arc Behavior: Events and Outcomes An exploration of the different ways arcs behave can give ideas about how to intertwine the ars in your game. Here is a list of actions an arc can take: If an arc takes these actions based solely on decisions made in the day planner, or choices made in events within that arc, it is still relatively independant. To intertwine the arcs, you'll want the actions of one arc to affect another one. For example, when one arc spawns another one, that could trigger an entirely different arc to end prematurely. You can also use choices made in events from one arc affect other arcs, in order to help network the arcs together. The stronger you weave the arcs in your game, the more seamless your game will seem.
ShiraiJunichi is an up-and-coming ren'ai developer working on his first ren'ai game. "DSE Tutorial" © 2005 ShiraiJunichi. All rights reserved. |