ASL Example: Cutscenes

Overcat
17 Dec 2006, 13:00
Hey folks. Been a while.

I thought I'd post a little cutscene code example. Cutscenes are non-interactive events that serve to advance the plot. They occur in many games, graphical or no.

I'm posting this for three reasons:

1) To contribute to the understanding of newcomers
2) To get feedback from you guys on making the example even better
3) To inspire more code examples from the community

Okay. The code is in a .lib file called fae_Cutscenes.lib, and is as follows:

!library
!asl-version <391>

define type <Cutscene>

action <Played> {

set string <Self; $thisobject$>
property <#Self#; Played>

set numeric <tn1; #(Self):Elements#>
'NOTE: This procedure is not included this example, but I advance my game time after a cutscene
do <AdvanceTime(%tn1%)>
}

end define

define room <Cutscenes>

alias <Cutscenes>

define object <CUTSCENE_01>

type <Cutscene>
properties <Elements = 16>
properties <Element_1 = "|cgYou've finally come out of hibernation,"|cb says Boslow, your boss. He sets himself down in his chair abruptly. Rogor, his body guard, lets out a snort.>
properties <Element_1_delay = 5>
properties <Element_2 = "|cgHad a long one last night,|cb" you croak.>
properties <Element_2_delay = 2>
properties <Element_3 = |cg"So I heard,|cb" says Boslow.>
properties <Element_3_delay = 2>
properties <Element_4 = You walk over to the desk, rubbing your eyes. You feel a hundred years old. Blinking, you look down at Boslow. |cl|iFull of energy, the frick.|xi|cb He's seventy-five, a full ten years on you, and he still gets up before sunrise every morning.>
properties <Element_4_delay = 6>
properties <Element_5 = |cg"What kind of botheration were you into?|cb" Boslow leans back in his chair.>
properties <Element_5_delay = 3>
properties <Element_6 = Rogor, from his position at the stairs: "|cgClimbing the cathouse again?|cb">
properties <Element_6_delay = 3>
properties <Element_7 = You flash him a quick look. He shifts his left leg, looks down the staircase. You let your eyes linger on the floor a few more seconds, unwilling to tell Boslow of the emperor's threat. |i|clI don't wanna' cause him any needless worry.|cb|xi. After a moment, you, with his wife in mind: "|cgHow's Katja?|cb">
properties <Element_7_delay = 9>
properties <Element_8 = "|cgAh, she's fine,|cb" Boslow replies, leaning back towards his desk. "|cgTrina's got her going to the country this aft. They're picking plumbs.|cb">
properties <Element_8_delay = 3>
properties <Element_9 = You nod absently.>
properties <Element_9_delay = 2>
properties <Element_10 = "|cgWe got a long day ahead of us,|cb" Boslow wraps his knuckles on a stack of papers in front of him.>
properties <Element_10_delay = 2>
properties <Element_11 = |i|clTell me about it.|xi|cb>
properties <Element_11_delay = 2>
properties <Element_12 = "|cgAnd I want to catch the opening of the arena tonight. The fae are finally doing something good for us humans,|cb" he says, almost incredulously. "|cgI imagine you want to be there too, considering.|cb" He looks to the stairs: "|cgYou going, Rogor?|cb">
properties <Element_12_delay = 6>
properties <Element_13 = "|cgCan't.|cb" He shrugs. |i|clThe punk ain't old enough to remember.|cb|xi>
properties <Element_13_delay = 2>
properties <Element_14 = "|cgYeah,|cb" you breathe. "|cgI'll be there.|cb">
properties <Element_14_delay = 2>
properties <Element_15 = "|cgGood.|cb" Boslow claps his hands. "|cgLet's get this day started!|cb">
properties <Element_15_delay = 2>
properties <Element_16 = You feel kinda' sick. You swallow it down, clench your jaw, and give your neck a few quick cracks.>
properties <Element_16_delay = 4>

end define

end define

'parameter1 = cutscene to run
define procedure <RunCutscene>

set string <s; $parameter(1)$>
set numeric <n; #(s):Elements#>
set numeric <n2; 0>
set string <s2; >
set numeric <nloop; 0>

msg <|n|b|cr***********************|xb|cb>

for <nloop; 1; %n%; 1> {

set string <s2; $objectproperty(#s#; Element_%nloop%)$>
set numeric <n2; $objectproperty(#s#; Element_%nloop%_delay)$>
if ( %n2% > 32 ) then { set numeric <n2; 32> }
if not property <game; fastscroll> then {
set numeric <n2; %n2% * 1000>
}
msg <>
msg < #s2#>
pause <%n2%>

}
msg <>
msg <|b|cr***********************|xb|cb|n>

doaction <#s#; Played>

end define


To use this, copy and paste the code into a new library file. Include it in your main ASL file with the !include line (you can find the correct usage of !include in the ASL Reference).

A cutscene is comprised of elements, or lines of text, and an associated delay for each element. The longer the lines of text, the longer the delay should be. Edit the numbered elements and their delays to create your own unique cutscene. Then change the line

properties <Elements = 16>


to the number of elements that you have created. Delete any extraneous elements, if any, from the example above. Also change the name of the cutscene to whatever you want. Mine is called CUTSCENE_01, though you may want to use something more descriptive.

To run your cutscene, add the code

do <RunCutscene(CutsceneName)>


wherever you want the cutscene to run. (Perhaps when you first enter a room.)

So. If there is any way to improve this, add new functionality, or whatever, lemme' know. I'm always interested in learning better ways to code.

Elexxorine
18 Dec 2006, 11:12
Man, I was actually wondering if you'd died or something, you haven't been around for ages. Glad to see you're not. Cool cut scene thing, with my cut scenes I usually give each one a procedure, with each bit of text having a 'press any key', as multipalyer games can't use pause, something I'm going to bug Alex about, don't worry. Some nice coding there. Well done.

paul_one
18 Dec 2006, 11:48
Just a comment...

Would it not make more sense just to have one "cutscene" object - with multiple actions, named "one" "two" "three" etc?

.. These actions would just be scripts, which could also have events - or move the character about - or anything... Instead of being limited to only a few actions.
(it is called by "doaction <cutscene; 001>")

Also the fact that not everyone reads at the same rate, and more traditionally I recall the "press any button" used over timing.

.. Not to say this isn't fair coding... I just wondered why put all the effort into re-inventing the wheel - only leaving out the gears and tyres.

Freak
18 Dec 2006, 13:59
It seems to me that a cutscene declared with this method would take more work and be more error-prone than directly coding it.

Overcat
18 Dec 2006, 22:51

Man, I was actually wondering if you'd died or something, you haven't been around for ages.



Not dead. Just taking care of business.

Also the fact that not everyone reads at the same rate, and more traditionally I recall the "press any button" used over timing.



Hmm, I think I like that better, too.

Would it not make more sense just to have one "cutscene" object - with multiple actions, named "one" "two" "three" etc?

.. These actions would just be scripts, which could also have events - or move the character about - or anything... Instead of being limited to only a few actions.
(it is called by "doaction <cutscene; 001>")



You could do it that way. How would it make more sense, though? Less objects hanging around? As for wanting to fire off some extra script events, I guess I could just add a hook in at the end of the RunCutscene procedure:

if action <#s#; OnPlayed> then {
doaction <#s#; OnPlayed>
}


Instead of having the events take place after each line of dialogue (like moving the player about), I would just describe them, and trust the player to believe it's actually happening. Then at the end I'd script all the practical effects of the events.

It seems to me that a cutscene declared with this method would take more work and be more error-prone than directly coding it.



Really? How so... :oops:

Okay, so I've dropped my drawers and showed a pair of my faulty knickers...the rest of you get to it. :lol:

paul_one
19 Dec 2006, 00:22
To look down your post, you can't exactly follow the flow of writing, and the effor in both following, and typing it out, is a bit more than just "msg <#text#>
pause <1000>
msg <#text2#>"...etc

Infact, the only extra ability will be the "super-scroll" feature - which is easily done away with by putting in key-waits after every 10 lines or so.. (I wish Quest had an automatic one after a full 'screen' of text).

How would it make more sense, though? Less objects hanging around?

It is more KISS-oriented.
It is an 'action' from a cut-scene object, which can be cleanly followed through, and interaction taken at various points.

There are some instances where having calculations/certain random events would be fruitful.. Card-playing, or values to be entered.

Could I ask why you went for the route you did?

Overcat
19 Dec 2006, 10:30

To look down your post, you can't exactly follow the flow of writing, and the effor in both following, and typing it out, is a bit more than just "msg <#text#>
pause <1000>
msg <#text2#>"...etc



Yeah, that's true. Never thought of that. It's a bit more typing, isn't it?

Could I ask why you went for the route you did?



Yeah. I suppose it's because I'm addicted to the idea of looping through objects with 'for each' to check their states and alter them. I figured, why not make everything objects - including each cutscene. Just in case. That's why they're in a Cutscenes room. But perhaps I'll never need to loop through them.