Frogatto and Scripted Cutscenes
Moderator: Forum Moderators
Frogatto and Scripted Cutscenes
I should probably make a blog post on our site ( www.frogatto.com ) to cover this, but I'm posting it here. One of the biggest unpleasant surprises I've had in developing frogatto is how time-consuming it is to make a game that seamlessly integrates "normal simulation by the engine" with "pre-scripted action".
It seems like it should be really easy; like you should just be able to tell the engine "okay, have the character walk in, and do X" - but if you're doing anything less than an absolutely hermetically-sealed cutscene, with no connection to the actual game, there are always chances for unexpected state in the actual game to screw with your cutscene.
For a simple example, let's say you're in a FPS which lets NPCs die; like halo does, and one of the NPCs is supposed to speak a line. What do you do if they're dead? That's usually pretty easy. But the problem is that there are a LOT of these what-ifs. It's not that they're individually hard to deal with, it's that there are just so damned many of them. Ex: What do you do if that NPC has run several screens away? What do you do if that NPC puts him camera-wise behind a wall? What do you do if that NPC is actively involved in a fight? What do you do if that NPC is unable to pathfind to his intended location? Etc.
Quoted article snippet that made me think of posting this:
http://www.gamespot.com/features/makeunreal/index2.html
It seems like it should be really easy; like you should just be able to tell the engine "okay, have the character walk in, and do X" - but if you're doing anything less than an absolutely hermetically-sealed cutscene, with no connection to the actual game, there are always chances for unexpected state in the actual game to screw with your cutscene.
For a simple example, let's say you're in a FPS which lets NPCs die; like halo does, and one of the NPCs is supposed to speak a line. What do you do if they're dead? That's usually pretty easy. But the problem is that there are a LOT of these what-ifs. It's not that they're individually hard to deal with, it's that there are just so damned many of them. Ex: What do you do if that NPC has run several screens away? What do you do if that NPC puts him camera-wise behind a wall? What do you do if that NPC is actively involved in a fight? What do you do if that NPC is unable to pathfind to his intended location? Etc.
Quoted article snippet that made me think of posting this:
http://www.gamespot.com/features/makeunreal/index2.html
Anyone have any thoughts on the subject?Finally, the game's technical innovations took longer than expected to complete, particularly the scripted, in-game cut-scenes that would eventually produce Unreal's spookiest moments. These dramatic interludes - such as the early level scene where the lights suddenly cut out, the music changes, and Skaarj warriors leap from the darkness and attack the bewildered player - are what truly separates Unreal from its competition. "[This type of] drama is really tough to do," says Bleszinski, "because you have to account for all the possibilities. For instance, if a Nali Alien is scripted to get killed by a Skaarj, you must account for all the possibilities - what if the player goes and stands between them, or what if he kills the Nali before the Skaarj gets to him? I think everyone underestimates how difficult it is to program those elements into a game."

Play Frogatto & Friends - a finished, open-source adventure game!
- Cloud
- Art Contributor
- Posts: 502
- Joined: December 17th, 2008, 7:43 pm
- Location: The land of pixels
- Contact:
Re: Frogatto and Scripted Cutscenes
Take all of the following with a pinch of salt. I've only just completed my first year of CS, so I'm sure there's a lot of people more equipped to answer the question. However, I do like working stuff like this out; so I can't resist. Also because of the CS degree, I have my head stuck in the Object Oriented sand (I'm assuming it's C++, of which I know very little currently). I've also never written anything as large or complex as what you're talking about either and though I have coded games, they're things like glorified hangman.
My first port of call would be inheritance. Something you're able to plug in any sort of character, be it the PC or an NPC, and method associated with all kinds of character. Then you begin to specalise; until you've worked your way down to the lowest point of every branch. Then you would do a similar thing with the checking methods - have something that you can plug the highest level thing into a method and begin to call lower methods as an when needed.
To give an example - say we want to check if the player can interact with an NPC
As I've found with programming so far; setting up everything is alway more complex than the actual algorithm which runs everything. Catching errors is another big thing, I usually just try to think of all possibilities that a method could take and try to error handle from there onwards. Admittedly for my that's more like sanatising inputs rather than checking a load of clauses, but the principal is the same.
And yes I'm aware I probably make everything a couple of hundered times more complex than they should be - believe it or not, but it's the way I simplify everything (it does help to have JavaDoc (or at least proper comments) and auto-completion).
My first port of call would be inheritance. Something you're able to plug in any sort of character, be it the PC or an NPC, and method associated with all kinds of character. Then you begin to specalise; until you've worked your way down to the lowest point of every branch. Then you would do a similar thing with the checking methods - have something that you can plug the highest level thing into a method and begin to call lower methods as an when needed.
To give an example - say we want to check if the player can interact with an NPC
Code: Select all
if player.canInteractWith(npc)
{
player.interactWith(npc);
}
else
{
//Wait until the npc is free or just skip the even
}
abstract class Character
{
abstract boolean canInteract();
boolean attemptToMoveCloserTo(Character c)
{
if this.canMoveCloserTo(c)
{
this.MoveCloserTo(c);
if Tools.distanceBetween(this, c) > Tools.INTERACTABLE_DISTANCE
{
this.attemptToMoveCloserTo(c);
}
else
{
return true;
}
}
else
{
return false;
}
}
boolean isAlive()
{
//You get the picture
}
}
class Player
extends Character
{
boolean canInteract()
{
if this.isAlive() && ... //player meets all player criteria for interaction
{
return true;
}
else
{
return false;
}
}
boolean canInteractWith(Character c)
{
if this.canInteract() && c.canInteract()
{
return this.isWithinInteractableDistanceWith(c)
}
else
{
//other possible error handling.
return false;
}
}
boolean isWithinInteractableDistanceWith(Character c)
{
if Tools.distanceBetween(this, c) > Tools.INTERACTABLE_DISTANCE
{
c.attemptToMoveCloserTo(this);
}
else
{
return true;
}
}
}
class NPC
extends Character
{
boolean canInteract()
{
if this.isAlive
}
//Hopefully you've got the picture by now, otherwise I'm not going to be able to help you.
}
And yes I'm aware I probably make everything a couple of hundered times more complex than they should be - believe it or not, but it's the way I simplify everything (it does help to have JavaDoc (or at least proper comments) and auto-completion).
Softly/SoftlySplinter on IRC. Will be lurking around more these days
Mainline Animations|The Væringjar
Art for these mead-sodden, bearded mushroom-junkies by Girgistian!
Mainline Animations|The Væringjar
Art for these mead-sodden, bearded mushroom-junkies by Girgistian!
Re: Frogatto and Scripted Cutscenes
Artificial Intelligence, Distributed Computing, and Simulation
All three are topics that you could study for your whole life, though.
Back to the point about object oriented approach, I think you may be onto a good approach, but let's rethink what the objects are. From a generic story-teller's point of view, I don't think characters are the atomic unit in this case, but rather "plot points." Think of a plot point as something that when it manifests will spur the player onwards to a new development. It may be appropriate to only use a particular character to say something, or maybe anybody standing who's holding a particular sword, or who got hit too many times in the last battle, etc. If nobody around fills the role, maybe a note left on the ground catches the hero's attention instead (depending on how urgent this particular plot development is).
All three are topics that you could study for your whole life, though.

Back to the point about object oriented approach, I think you may be onto a good approach, but let's rethink what the objects are. From a generic story-teller's point of view, I don't think characters are the atomic unit in this case, but rather "plot points." Think of a plot point as something that when it manifests will spur the player onwards to a new development. It may be appropriate to only use a particular character to say something, or maybe anybody standing who's holding a particular sword, or who got hit too many times in the last battle, etc. If nobody around fills the role, maybe a note left on the ground catches the hero's attention instead (depending on how urgent this particular plot development is).
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."
- Sgt. Groovy
- Art Contributor
- Posts: 1471
- Joined: May 22nd, 2006, 9:15 pm
- Location: Helsinki
Re: Frogatto and Scripted Cutscenes
I think this kind of problems should have been thought through before one even starts coding. That is, if one runs into problems of player actions causing hangups for prewritten plotline, then one is probably trying to force a narrative concept on a game concept where it doesn't really fit into.
For an open-ended game world, where the player has lot of freedom to influence the world state, a linear narrative is a bad choice. If you want to make it work, you need so much if..elseif..switch..finally thicket that your narrative won't be all that linear, it will a pain to design and even more pain to testplay. If your gameworld is a living and evolving thing, then the story has to evolve with it. Instead of prewritten sequence of events, you should have agents with a set of goals they are trying to promote. If certain goals are very important for the narrative, then there should be redundancy of independent agents to make sure at least one of them succeeds. There can still be prewritten events, but they should be those kind that are not dependent of the world state (an earthquake, changing of seasons, etc.)
For an open-ended game world, where the player has lot of freedom to influence the world state, a linear narrative is a bad choice. If you want to make it work, you need so much if..elseif..switch..finally thicket that your narrative won't be all that linear, it will a pain to design and even more pain to testplay. If your gameworld is a living and evolving thing, then the story has to evolve with it. Instead of prewritten sequence of events, you should have agents with a set of goals they are trying to promote. If certain goals are very important for the narrative, then there should be redundancy of independent agents to make sure at least one of them succeeds. There can still be prewritten events, but they should be those kind that are not dependent of the world state (an earthquake, changing of seasons, etc.)
Tiedäthän kuinka pelataan.
Tiedäthän, vihtahousua vastaan.
Tiedäthän, solmu kravatin, se kantaa niin synnit
kuin syntien tekijätkin.
Tiedäthän, vihtahousua vastaan.
Tiedäthän, solmu kravatin, se kantaa niin synnit
kuin syntien tekijätkin.
Re: Frogatto and Scripted Cutscenes
What I notice for most games is that scripted events occur at the most predictable opportunities. I don't ever recall Unreal being spooky. But I am vividly reminded of a scene from Doom3 where everything goes into red cut scene where creepy stuff happens - then when everything seems calm the ceiling falls down in front of you and an imp is clawing at your face.
Essentially your goal would be to minimize possibilities by employing different strategies:
- Don't give dialogue, or script actions for npcs that can die. Employ new npcs for game progression (common tactic)
- Make critical npcs invincible (oblivion style, knock a guy out 1 million times, he wont die) or exclude them from the normal game logic (they only exist in the scripted events)
- Like wesnoth, if any character that has dialogue dies, its game over
- Restrict npc movement to certain areas (safe areas - towns where no enemies spawn)
Essentially your goal would be to minimize possibilities by employing different strategies:
- Don't give dialogue, or script actions for npcs that can die. Employ new npcs for game progression (common tactic)
- Make critical npcs invincible (oblivion style, knock a guy out 1 million times, he wont die) or exclude them from the normal game logic (they only exist in the scripted events)
- Like wesnoth, if any character that has dialogue dies, its game over
- Restrict npc movement to certain areas (safe areas - towns where no enemies spawn)
Re: Frogatto and Scripted Cutscenes
What we ended up doing in frogatto, when we had harmable actors doing lines, was exploiting the separation of the game into levels.
For example, when you'd enter a boss level, before any state alteration would happen, the boss would immediately deliver their lines, and during this time, the player's controls would be locked. We also hacked together some very non-intelligent "move to X" scripts, to force the player to walk to a specific position before a cutscene happens.
It's not as nice/flexible as it could be, but it's pretty much on par with what they had in e.g. chrono trigger or seiken densetsu 3 (and other such SNES-era games).
One of the biggest things I found was that cutscene locations, in order to be amenable to this sort of stuff, had to have fairly simple setups, since frogatto really has no pathfinding algorithm to speak of. You couldn't have solid objects in the way. But that said - cave story did pretty much exactly the same thing. If you look at any boss battle, or any pre-scripted scene in that game, all of them tend to happen in what are, collisionwise, big square rooms.
It would be really cool to have some pathfinding algorithm, but that's... dangerous john-romero-type fluff that can easily blow a project's scope into the stratosphere. (I'm specifically referring to the ridiculously over-engineered pathfinding they had to provide for your in-game buddies in Daikatana, so they could correctly follow the player around. Getting that to work right was one of many reasons their project took years longer than intended.)
For example, when you'd enter a boss level, before any state alteration would happen, the boss would immediately deliver their lines, and during this time, the player's controls would be locked. We also hacked together some very non-intelligent "move to X" scripts, to force the player to walk to a specific position before a cutscene happens.
It's not as nice/flexible as it could be, but it's pretty much on par with what they had in e.g. chrono trigger or seiken densetsu 3 (and other such SNES-era games).
One of the biggest things I found was that cutscene locations, in order to be amenable to this sort of stuff, had to have fairly simple setups, since frogatto really has no pathfinding algorithm to speak of. You couldn't have solid objects in the way. But that said - cave story did pretty much exactly the same thing. If you look at any boss battle, or any pre-scripted scene in that game, all of them tend to happen in what are, collisionwise, big square rooms.
It would be really cool to have some pathfinding algorithm, but that's... dangerous john-romero-type fluff that can easily blow a project's scope into the stratosphere. (I'm specifically referring to the ridiculously over-engineered pathfinding they had to provide for your in-game buddies in Daikatana, so they could correctly follow the player around. Getting that to work right was one of many reasons their project took years longer than intended.)
Play Frogatto & Friends - a finished, open-source adventure game!
Re: Frogatto and Scripted Cutscenes
For all of the cases, one could imagine a graph or tree showing the flow of the plot. What ends up happening is an exponential explosion in the number of states, especially redundant states with slightly different information. Nobody wants to look at it, and no computer can navigate it.
Super Mario RPG is a brilliant example of cut scenes. Mario is the king of charades. A very big part of making that game fun was they figured out how and when to do cut scenes well.
It's very difficult to balance fun, yet complex gameplay with a meaningful, yet variable plot.
I wonder what they did for Knights of the old republic and #2. Seems like a fairly complicated series of plot choices.
Fallout 2 is another example of amazing plot choices in a variable world. I think just about everyone can be killed.
Super Mario RPG is a brilliant example of cut scenes. Mario is the king of charades. A very big part of making that game fun was they figured out how and when to do cut scenes well.
It's very difficult to balance fun, yet complex gameplay with a meaningful, yet variable plot.
I wonder what they did for Knights of the old republic and #2. Seems like a fairly complicated series of plot choices.
Fallout 2 is another example of amazing plot choices in a variable world. I think just about everyone can be killed.
-
- Posts: 45
- Joined: September 25th, 2007, 5:37 pm
Re: Frogatto and Scripted Cutscenes
First of all one advice: Do _not_ try to create a sort of world simulation where the game behavior emerges as the combination of the behavior of independant agents who try to promote some goals. I have often seen such a system proposed and never (not even partially) succesfully implemented. Its (almost) impossible to control such a system and (almost) impossible to get it right so, that it really seems *alive*
That means - a lot of if's. In Summoning Wars, we have a similar problem. We want that our system adapt to multiplayer game, in other words, if you play a game with three players, they all should participate in ingame dialogs and cutscenes. In addition, dialogs should be slightly different depending on the classes of the players. All in all enough to create some mindsplitting complexity. Some of the strategies we used:
1. Insert and Abstraction layer between Units and spoken text. In our game speaker roles are assigned to players (or npcs or monsters that can speak text) and text is then spoken by speaker roles. An example: In a dialog an arbitrary player should make a snide remark. Then you could define the role *remarkmaker* and assign it to a random player. The text is then assign to *remarkmaker*. An important point is, that a unit can speak several roles. So if you have few players, each one will speak multiple roles, whereas for many players the dialog is distributed to all players. The same thing works if you have three peasant and one of them should complain about whatever. In addition in our system a text is not spoken if there is nobody assigned for that role. That makes debugging a bit harder, but saves _a lot_ of ifs. You need some helper functions for selecting the right speakers for roles, but most complicated selections and ifs (what to do if unit X is dead?) can be hidden in these functions, that must be written once.
The same strategie can be applied not only for spoken text, but also for some other actions.
2. Define Fallback points and reset game state to these if bad things happen. For instance in our game tutorial three players can easily block out the guardians, so that they never reach their scripted destination area. They are just teleported to the right point in this case. This is done during the next cutscene, when the camera *looks* somewhere else
. These things happen rarely, no player has complained about this so far and it saves to care with to much what-ifs. This is the most easiest method of joining story threads to avoid exponential explosion. Im some cases there are more elegant strategies
3. Define as much of the environment as possible. The easiest case is the already proposed rectangular game. For scripted actions allow to assign a chain of actions (walk to 1, walk to 2, walk to 3, do action X). By this way no overpowered pathfinding is required. Again, you need to detect if one of the actions fails (for instance lcation 2 is blocked) and try to react accordingly. In our system, automaticall the next command is started. So if you set a chain of command where only the last one is really important, you only have to listen if the last one is succesful. In _most_ cases everything will work fine, but it will also continue to work, if some animation of gesture or whatever in the middle was missed.
3.
That means - a lot of if's. In Summoning Wars, we have a similar problem. We want that our system adapt to multiplayer game, in other words, if you play a game with three players, they all should participate in ingame dialogs and cutscenes. In addition, dialogs should be slightly different depending on the classes of the players. All in all enough to create some mindsplitting complexity. Some of the strategies we used:
1. Insert and Abstraction layer between Units and spoken text. In our game speaker roles are assigned to players (or npcs or monsters that can speak text) and text is then spoken by speaker roles. An example: In a dialog an arbitrary player should make a snide remark. Then you could define the role *remarkmaker* and assign it to a random player. The text is then assign to *remarkmaker*. An important point is, that a unit can speak several roles. So if you have few players, each one will speak multiple roles, whereas for many players the dialog is distributed to all players. The same thing works if you have three peasant and one of them should complain about whatever. In addition in our system a text is not spoken if there is nobody assigned for that role. That makes debugging a bit harder, but saves _a lot_ of ifs. You need some helper functions for selecting the right speakers for roles, but most complicated selections and ifs (what to do if unit X is dead?) can be hidden in these functions, that must be written once.
The same strategie can be applied not only for spoken text, but also for some other actions.
2. Define Fallback points and reset game state to these if bad things happen. For instance in our game tutorial three players can easily block out the guardians, so that they never reach their scripted destination area. They are just teleported to the right point in this case. This is done during the next cutscene, when the camera *looks* somewhere else

3. Define as much of the environment as possible. The easiest case is the already proposed rectangular game. For scripted actions allow to assign a chain of actions (walk to 1, walk to 2, walk to 3, do action X). By this way no overpowered pathfinding is required. Again, you need to detect if one of the actions fails (for instance lcation 2 is blocked) and try to react accordingly. In our system, automaticall the next command is started. So if you set a chain of command where only the last one is really important, you only have to listen if the last one is succesful. In _most_ cases everything will work fine, but it will also continue to work, if some animation of gesture or whatever in the middle was missed.
3.