The Animation Question!

Just getting into the artwork and animation side of things on my game and was wondering:

Is it possible to get animations to play (mpeg etc) on passage opening? If it is, can I take it a step further and have animations play on clicking


PLAY OPENING COMBAT ANIMATION HERE

<span id='dice-outcome'></span>
<span id='dice-button'><<button 'Handgun Test!'>>
    <<set $roll to random(0, 100)>>
    <<if $roll gt $pcStats.McGuffin>>
    <<replace '#dice-outcome'>>
    You rolled $roll!<br><br>You get hit!
PLAY ANIMATION HERE FOR BEING HIT
    <<replace '#dice-button'>><</replace>> /% remove button %/
    <</replace>><</if>>
    <<if $roll lte $pcStats.McGuffin>> 
        <<replace '#dice-outcome'>>
            Your rolled $roll!<br><br>You hit it!
PLAY ANIMATION HERE HITTING OPPONENT!
        <</replace>><</if>>
    <<replace '#dice-button'>><</replace>> /% remove button %/
<</button>>
</span>

<</if>>

So my big question here is, is it possible to get two our of three possible animations to play? One on passage opening and one depending on what the button / random roll is?

Answers greatly requested.

Here’s a script that will do something like that. It’s not quite what you need but it’s workable.

It’s probably easier to use a GIF than a video if the animation is short. I think you can create non-looping GIFs when you encode them.

You will need to combine this with your code. Basically, you only really need to link an image (with the standard html img tag) and use the replace function that you are already using. Images are treated more or like text so your original script is almost doing what you need already.

<span id="dice-roll"> <img src="https://media.tenor.com/i_L5KauoCcoAAAAj/dice.gif"></span>

<<button "Handgun Test!">>
  <<set $roll to random(1,3)>>
  <<if $roll eq 1>>
    <<replace "#dice-roll">><span id="dice-roll"> <img src="https://miro.medium.com/max/640/1*5i3bBsz_bMcGQ-UgDMCzQA.png"></span>
  <</replace>>
  <<elseif $roll eq 2>>
    <<replace "#dice-roll">><span id="dice-roll"> <img src="https://miro.medium.com/max/640/1*dqZhjZbsbEBDXzKQPAagXw.png"></span><</replace>>
  <<elseif $roll eq 3>>
    <<replace "#dice-roll">><span id="dice-roll"> <img src="https://miro.medium.com/max/640/1*DrPdeWaJON0XbtmiEZc3jw.png"></span><</replace>>
  <</if>>
<</button>>
1 Like

Quick answer: Yes, sort of.

I suspect more skilled users of SugarCube may have more comprehensive answers than mine, though.

You don’t mention whether you are using twine, tweego or some other software to produce your story.

I use tweego (instead of twine) to compile Sugarcube2 into html.
If tweego finds an image file in the same folder with the .tw file that it’s compiling, it’ll encode that image into a passage in the html file in base64 format. An animated GIF is considered an image. Any video format can be converted into an animated GIF using the command-line utility ffmpeg.

That image passage can then be shown in-line by using Sugarcube’s img construct

[img[imagename]]

where “imagename” should be replaced by the name of the image passage, which is the same as the name of the image file but without the extension (file type).

Many people are prejudiced against in-line base64 encoding since it bloats the html file substantially when compared to using separate image files. It has the advantage, though, that only a single .html file needs to be provided to the game’s player (or story’s reader).

Below is twee3 code which can be compiled by tweego, but without the actual images. I think it does what you seem to want.

:: StoryData
{
        "ifid": "D976ED06-E2F6-4184-920F-F98BD6A678CA"
}

:: Start
!! Start

Example of an in-line video:

/* my_video_1 is an animated gif which is in the same folder as this .tw file. */

[img[my_video_1]]

Example of hiding an animated gif:
/*
  The macro "hideit" is a way of using the "toggleclass" macro to hide and reveal
  an included passage; adapted by me from code originally provdied by HiEv.
*/
<<hideit  "video2" "Show video 2 for me" "Hide video 2 (below)"   "Hide video 2 (above)" >>

:: video2
!! This passage contains video_2
/* my_video_2 is an animated gif which is in the same folder as this .tw file. */
/* Note: I used the command-line program ffmpeg to convert video files
   from mp4 to animated gif
*/   

/*
   tweego automatically compiles images (including animated gifs)
   into passages which have the same names as the images.
   For details, see the documentation for tweego.
 */
   
[img[my_video_2]]

:: StoryInit


:: StoryTitle
test_video

:: StoryAuthor
by Selden

:: Story Stylesheet [stylesheet]

/*-------------------------------------------------------*/
/* make it possible to hide/show spans & divs */

.hide { display: none; }


:: Story JavaScript [script]

/*..........................................................*/
/* macro hideit */

/* "hideit" macro to hide a block of text
   and change the text of the link which does the reveal/hide
   adapted from code provided by HiEv

   1 required arg: the name of the passage to hide/show
   3 optional args: initial show, replacement hide, final hide

Example usages:

<<hideit "passagename">>

<<hideit "passagename" "showpassage" "hidepassage (below)" "hidepassage (above)" >>

 */

Macro.add("hideit", {
    handler: function() {
    /* initialize a variable so can
       automatically increment (make unique) two class ids */

        if (!setup.hideit_count) setup.hideit_count = 0;
        var hideit_id1 = "hideit_" + setup.hideit_count;
        setup.hideit_count += 1;
        var hideit_id2 = "hideit_" + setup.hideit_count;
        setup.hideit_count += 1;

/* args are 0-based */
/* only 1 arg is required: name of passage to be included */
/* Allow up to 3 optional args for displayed names of links */
/* if an optional arg is a space (" ") then that link becomes unavailable */

       var hideit_a1 = "Show details. ";
       var hideit_a2 = "Hide details. ";
       var hideit_a3 = "Hide details. ";

       if (this.args[1]) var hideit_a1 = this.args[1];
       if (this.args[2]) var hideit_a2 = this.args[2] + " ";
       if (this.args[3]) var hideit_a3 = this.args[3];

/* initially just "Show details" is visible
   selecting it
   1. makes "Show details" link invisible   
   2. makes "Hide details" link visible instead
   3. makes "Hidden text" visible
   4. makes "Hide details" link visible on last line
 */
        var output =
                   '<span id="' + hideit_id1 + '">' +
   		   '<<link "' + hideit_a1 + '">> ' +
		   '<<toggleclass "#' + hideit_id1 + '" "hide">>' +
		   '<<toggleclass "#' + hideit_id2 + '" "hide">>' +
		   '<</link>> </span>' +
                   '<span id="' + hideit_id2 + '" class="hide">' +
   		   '<<link "' + hideit_a2 + '">> ' +
		   '<<toggleclass "#' + hideit_id1 + '" "hide">>' +
		   '<<toggleclass "#' + hideit_id2 + '" "hide">>' +
		   '<</link>>' +
		   '<<include "' + this.args[0] + '">>' +
   		   '<<link " ' + hideit_a3 + '">> ' +
		   '<<toggleclass "#' + hideit_id1 + '" "hide">>' +
		   '<<toggleclass "#' + hideit_id2 + '" "hide">>' +
		   '<</link>>' +
		   '</span>' ;

        $(this.output).wiki(output);

    }

} );

/*********************************************/




:: End
!! This is the End

Goto [[Start]]
1 Like

Thanks for that, I am using Twine.

1 Like

Cheers, I’ll see what I can do with that.
I’ll probably convert it using handbrake or something.

2 Likes

When using Twine, you have to use in-line HTML and access an external image or video file. For example, to display an mp4 video file which is in the same folder as the published story’s HTML file, you’d could use

<video width="320" height="240" controls autoplay loop> <source src="my_video_1.mp4" type="video/mp4"> </video>

An annoyance is that, by default, Edge and Chrome ignore the “autoplay” directive and have to have that option enabled in the browser’s own settings. Otherwise the person reading the story has to start the video manually. In contrast, Firefox seems to respect the video’s “autoplay” directive.

Also, the video has to be relatively short. Larger files (more than 2MB?) generate an error and don’t display.

To implement the “hideit” macro, the line of text

.hide { display: none; }

should go in Twine’s Story passage named “# Stylesheet”, while all of the code defining the macro (after :: Story JavaScript [script] and before :: End) goes in Twine’s Story passage named “{} JavaScript”.

Thanks for that. Also, does the Brave Browser have auto-play enabled? Assuming popup blockers are turned-off?

If that video doesn’t include an audio track then you should be able to ask it to autoplay by including the correct attribute to the <video> HTML element you are using to display it.

If that video does include an audio track then you can only autoplay it on any Passage other than the first Passage your project displays to the end-user, because the Security system of modern web-browsers don’t allow the auto-playing of audio (video or sound files) until after the end-user has interacted with the web-page.

1 Like

My personal experience suggests that the video Autoplay functionality is somewhat more subtle.

On my Win10 22H2 v 19045.2364 computer it doesn’t seem to matter whether or not an audio track is present. Videos don’t play the first time they’re seen in a Story’s Start passage when the Story is being rendered by a chromium-based browser.

Neither the MP4 videos that I used in my tests nor the AVIs from which they were derived (using ffmpeg v2022-12-19) have any audio tracks. I am sure of this for several reasons: The program which created the AVIs (Celestia v1.6.1) has no audio capability. MediaInfo v22.12 lists no audio tracks although it does list a video track. In addition, the “Properties → Details” tab of Windows 10’s RMB context menu shows only the names of possible Audio characteristics All three of those audio data fields (bit rate, channels and audio sample rate) are blank.

Even so, those videos don’t autoplay under either Edge v108.0.1462.76 or Chrome v108.0.5359.126 when they’re first seen in the Start passage, so long as the Start passage is the only one that’s been seen. However, they DO autoplay when they’re viewed in other passages (i.e. in the ones visible after following links). They also autoplay in the Start passage after one returns to it from another passage. In contrast, Firefox v108.0.2 does immediately autoplay the videos which are in the Start passage the very first time they’re seen.

In other words, there’ll be less confusion if no videos are included in the Start passage.

Re: audio tracks, I don’t know if the embedded audio track makes a difference, but if you mute the file within the html tag it should work.

Try this:

<video autoplay muted loop>
  <source src="https://samplelib.com/lib/preview/mp4/sample-5s.mp4" type="video/mp4">
</video>

It seems like that is how the browser’s security options decide whether to allow autoplay or not. I don’t know if it’s guaranteed to be this way in the future.

Like you say, it’s better to just not have a video in the Start passage.

If the video is visible when the browser first opens the Start passage, then “muted” does allow the video to play. If, however, the video in the Start passage is hidden from view (e.g. by using the “hideit” macro) then it does NOT play when it is revealed.
Once I fixed a typo, the previously hidden video did play. sigh

I used Chrome v108 with Twine v2.5.1 and SugarCube v2.36.1 for this test.

1 Like