Saturday, 21 February 2015

TS2015 - Scenario Scripting in LUA Part 12 - Video

Apologies for the long time between articles!

In this article i'm going to show you how to incorporate videos in to your scenarios, done correctly they can really elevate your scenarios to a completely different level.

The overall API for playing videos is almost identical to the API for playing sounds - so if you haven't yet read the previous blog post on the subject then now would be a great time to do that.

At the top of your LUA script file you're going to want to drop in some definitions, just to make the rest of the script a bit easier to read:

FULLSCREEN = 0
FRONT_AND_CENTER = 1
CALL = 2

FALSE = 0
TRUE = 1

NO_CONTROLS = 0
PLAYPAUSE = 1
STOP = 2
SEEK = 4

Note: You may already have FALSE and TRUE defined, in which case there's no need to duplicate them here.

The calls to handle videos are as follows:

Start a video playing:
SysCall("ScenarioManager:PlayVideoMessage", "2013_startup.ogv", FRONT_AND_CENTER, FALSE, NO_CONTROLS,0)

Check to see if a video is playing:
SysCall("ScenarioManager:IsVideoMessagePlaying", "2013_startup.ogv")

Stop a video from playing:
SysCall("ScenarioManager:StopVideoMessage", "2013_startup.ogv")

Let's put it in a small example to provide some context:

function OnEvent(event)
  _G["OnEvent" .. event]();
end

function OnEventStart()
  SysCall("ScenarioManager:PlayVideoMessage", "2013_startup.ogv", FULLSCREEN, FALSE, NO_CONTROLS,0)
end

Here, i'm defining a trigger event "Start" (which should be initiated from a Trigger instruction in the scenario definition) and this will play a video, full screen.

Just as with audio, the call to play a video will return immediately and let the video carry on playing in the background, that's the main reason for the "IsVideoMessagePlaying" and "StopVideoMessage" calls.  I'll show them in action in a moment.

Parameters

There are a number of parameters to the PlayVideoMessage function that are interesting.

After the Filename, the next one tells the game how and where you want the video displayed.  The options are Fullscreen (0), Front and Center (1), and Video Call (2).  I've defined some constants above so that it's easier to see what it is doing rather than passing plain numbers in (never do that, trust me!).

Full Screen puts the video full screen, just as it says it will.  It will also include an X in the top right that allows the player to abort playback of the video if they wish.  In the screenshot below you can see it has completely filled the game screen.

Full Screen Playback
Front and Center gives you a video playback which does not fill the screen and therefore allows some context from within the game to still be seen, but it is meant to still command the users attention fully and is of sufficient size it can still contain some detail.
Front and Center Playback
Finally, Video Call is intended to show in the top left corner somewhat like if you had a video call going on with someone.  You could use this for giving brief snippets of information, perhaps a news bulletin about something that's just happened (based on the players action) or something similar.
Video Call Playback


The next option is either TRUE (1) or FALSE (0) and this tells the game whether to pause in-game action or leave it running.  If you're going to get in the way of the user such as a full screen video then I'd suggest pausing the game is a good idea.  If it's a video call, then you probably don't want to pause it so that it feels more like something that is happening as part of the game play.

The next option tells the game what kinds of controls to put on the video, do you want them to be able to pause it? skip to a particular bit? or stop it?  There are four constants defined for this in my example.  NO_CONTROLS (0) means show nothing, and is used in all the above three screenshot examples.  PLAYPAUSE (1), STOP (2) and SEEK (4) add the relevant controls that you would expect.  If you want to add more than one control, simply add them together like this:

SysCall("ScenarioManager:PlayVideoMessage", "2013_startup.ogv", FRONT_AND_CENTER, FALSE, (PLAYPAUSE+STOP+SEEK),0)

This would give you something like this::

Front and Center with all controls enabled along the bottom of the video
The final parameter is always a zero.

Format

The format of the video is an Ogg Vorbis ".ogv" video.  You will need to create your video and export it in some format using your preferred editing tool and then if it won't export to Ogv then you'll need to use an additional step to convert it.  As a reference example, the 2013_startup.ogv used as part of the start-up sequence of the game is in the correct format.  You can use this to confirm you're calling the video correctly and it is working, and then drop your own video in afterwards.  You can find this video in the data\videos folder.

I use FFMpeg2Theora to do my conversions, available here, once installed you can run it with this command line to get the right format:

ffmpeg2theora-0.29.exe myvideo.mp4 -vcodec libtheora -acodec libvorbis -v 10

Here i've used an mp4 video because that's what I exported from my video editing suite, the result will go out as myvideo.ogv .

The number at the end is the quality level, 10 is the maximum and reducing it can make a huge difference to the file size - as well as a huge difference to the quality.  You will likely find that you can drop it down one or two settings before you even notice a difference and then it will drop off quickly.  Find that right setting for your video that means you can get the file size down as far as possible while still remaining good quality.

Place the videos in the localised language folder, the same as the audio files.  So this would be in the "en" folder for English users, for example.

Bigger Example

So here's a bigger example showing how you can use conditions to work out when to continue with the scenario.

function OnEvent(event)
  _G["OnEvent" .. event]();
end

function TestCondition(condition)
  _G["TestCondition" .. condition]();
end

function OnEventStart()
  videoPlaying = SysCall("ScenarioManager:IsVideoMessagePlaying", "2013_startup.ogv")
  if (videoPlaying == TRUE) then
    SysCall("ScenarioManager:StopVideoMessage", "2013_startup.ogv")
  end
  SysCall("ScenarioManager:PlayVideoMessage", "2013_startup.ogv", FULLSCREEN, FALSE, NO_CONTROLS,0)
  SysCall("ScenarioManager:BeginConditionCheck", "HasItStoppedYet")
end

function OnEventNextStep()
  SysCall("ScenarioManager:ShowInfoMessageExt", "Get moving", "moving.html", 10, MSG_TOP + MSG_TOP, MSG_SMALL, TRUE);
end

function TestConditionHasItStoppedYet()
  videoPlaying = SysCall("ScenarioManager:IsVideoMessagePlaying", "2013_startup.ogv")
  if (videoPlaying == FALSE) then
    OnEventNextStep()
  end
end

This example is somewhat contrived to try and fit a few different things in to a small space but it should give you the "snippets" to do what you want to do.

In the scenario instructions we're triggering "Start", which ultimately calls OnEventStart().
In OnEventStart() we find out if the video is currently playing and if so, we stop it.  It's highly unlikely that would be the case here, but normally you might find a place where there's a chance a video is already playing and now as a result of a more gameplay based event you need to play a video so the first thing you do is make sure that nothing else is playing first.
We then kick off playing our video, and then finally start a condition check called HasItStoppedYet.

The game will now play the video, and while the user is enjoying this video the game will now be calling TestConditionHasItStoppedYet over and over again, each time it will find out if the video is currently playing.  At some point this is going to return FALSE because our video finally finished playing and when this happens we manually trigger another event NextStep.

When OnEventNextStep runs, it displays a message to the user, presumably saying "right, now get moving".  Had you just tried to put the message box up, it would have appeared over or simply interrupted the video.  In this way, you remain fully in control of when things are presented to the user.











1 comment:

  1. I read your whole article, it's really interesting and helpful thanks for sharing. PNR status
    Train running status

    ReplyDelete