Skill Flow Builderを使用したコンテンツの作成

Skill Flow Builderを使用したコンテンツの作成

Skill Flow Builderを使うと、デザイナーやゲームクリエイターは、コンテンツ、ロジック、画像、オーディオの構成にさまざまなオプションを使用できるようになります。

物語の流れを作成する

シーンを作成する

プレイヤーが初めてゲームを起動するときは、スキルはプレイヤーに応答し、プロンプトを出す必要があります。startシーンを作成し、初回起動時の動作を定義してください。以下の例は、Alexaに「すごいゲームにようこそ!」と言うように指示するstartシーンを表しています。

@start
    *say
        すごいゲームにようこそ!

どのシーンも必ず、新しい行で先頭に@を付けたシーン名から始めます。この例のシーン名は、startです。startなど一部のシーン名は予約されており、特殊な動作にのみ使用されます。

シーンにコンテンツを追加するには、シーンのプロパティを使います。プロパティには、シーン内でAlexaが読み上げるコンテンツを指定する*sayなどがあります。シーンのプロパティは、新しい行で先頭に*を付けたプロパティ名で指定します。

    *say
        すごいゲームにようこそ!

この文、すごいゲームにようこそ!は、*sayプロパティのコンテンツです。コンテンツは、先頭に*を付けた別のプロパティか、@を付けた別のシーンが始まるまで、複数行にわたって続けられます。インデントは任意です。

プレイヤーに選択肢を与える

以下は、プレイヤーが海賊になるか商人になるかを選択できるstartシーンの例です。

@start
    *say
        すごいゲームにようこそ!
        海賊と商人、どちらになりたいですか?
    *then
        hear 海賊になりたい, 海賊, 海賊になる {
            -> choose pirate
        }

        hear 商人になりたい, 商人, 商人になる {
            -> choose merchant
        }

シーンでは、*sayプロパティを使ってAlexaに「すごいゲームにようこそ! 海賊と商人、どちらになりたいですか?」を言わせ、*thenプロパティを使って次の指示を列挙しています。

        hear 海賊になりたい, 海賊, 海賊になる {
            -> choose pirate
        }

hear指示は、Alexaが特定の単語やフレーズを聞き取ったら特定のアクションを取るように指示しています。同じ意味の単語やフレーズをカンマで区切って指定できます。

この例では、Alexaが「海賊になりたい」、「海賊」、「海賊になる」を待機しています。Alexaがプレイヤーからこれらのフレーズのいずれかを聞き取ると、Alexaは{}の間に指定された指示を実行します。

プレイヤーが「海賊」と言うと、Alexaは-> choose pirateを実行します。つまり、Alexaに「choose pirate」シーンに遷移するよう指示しています。->指示の遷移はすぐに行われますが、シーン内の残りの指示は実行されません。

複数のシーンをつなげる

プレイヤーからのインプットがなくても、シーン間の遷移を行う場合もあります。次の例を考えてみましょう。

バージョン1:

@start
    *say
        すごいゲームにようこそ!
        海賊と商人、
        どちらになりたいですか?
    *then
        hear 海賊 {
            -> choose pirate
        }
        hear 商人 {
            -> choose merchant
        }

バージョン2:

@start
    *say
        すごいゲームにようこそ!
    *then
        -> choose your trade

@choose your trade
    *say
        海賊と商人、
        どちらになりたいですか?
    *then
        hear 海賊 {
            -> choose pirate
        }
        hear 商人 {
            -> choose merchant
        }

プレイヤーにとって、これらの例の結果はまったく同じです。しかし、次の理由からバージョン2のほうがより便利です。

  • ゲームが進んだときに、「すごいゲームにようこそ!」と言わなくても直接@choose your tradeの質問に遷移できます。
  • プレイヤーが何も答えず、Alexaが質問を繰り返さなければならない場合、Alexaは最後のシーンの質問だけを言うことができます。

ゲームロジックを実装する

if

    *then
        if not enraged {
            increase fear by 2
        }
        if fear is greater than 10 {
            -> fear warning
        }
        -> next room

状況を限定する場合には、ifを使用します。if文以下の指示は、if文に定義した状況に該当する場合(trueの場合)にのみ実行されます。

if文の形式は次のとおりです。

  • 指示を波括弧で囲む必要があります。
  • hear文の中でも使用できます。またhear文を含めることもできます。
  • 入れ子にできます。
  • 値の前に!を使用できます。!は「...ではない」ことを意味します。
  • サポートされる演算子は次のとおりです。
    • is
    • ==
    • is greater than
    • >
    • is greater than or equal
    • >=
    • is less than
    • <
    • is less than
    • <=
    • is not
    • !=
    • and
    • &&
    • or
    • ||
    • ()

プレイヤーの決定、インベントリー、進行状況を保存する

後で使えるように、プレイヤーに関する情報を保存しておきたい場合があります。たとえば、次のような情報です。

  • プレイヤーがパリに行ったこと
  • プレイヤーが魔法使いに話しかけたこと
  • プレイヤーが魔法使いに「いいえ」と答えたこと
  • プレイヤーが何でも開けられる鍵を見つけたこと

以下は、flag指示を使って情報を保存する方法の例です。

*then
    flag visitedParis
    flag talked_to_wizard
    flag toldWizardNo

同様に、プレイヤーの選択内容に基づいてフラグをセットすることもできます。

*then
    hear 鍵を拾って {
        flag skeletonkey
        -> escape room
    }

プレイヤーが「鍵を拾って」と言うと、skeletonkeyというフラグがセットされ、ゲームはescape roomというシーンに進みます。

フラグを解除するには、unflag指示を使います。たとえば、プレイヤーがあるシーンで何でも開けられる鍵を失くすと、以下を実行します。

    *then
        unflag skeletonkey

保存したプレイヤーの決定、インベントリー、進行状況を使って何らかのアクションを実行する

プレイヤーに関する情報を保存したら、その情報を使って何らかのアクションを実行するかどうかを判断します。

たとえば、プレイヤーは何でも開けられる鍵を持っていないと扉を開けられないとします。

@escape room
    *say
        あなたは今部屋の中にいます。
    *then
        if skeletonkey {
            -> open door
        }

        -> door locked

事前にskeletonkeyのフラグがセットされている場合、ゲームは自動でopen doorというシーンに進みます。事前にskeletonkeyのフラグが解除されているか、一度もセットされていない場合、ゲームは自動でdoor lockedというシーンに進みます。

if指示を使って、Alexaにif以降の文がtrueかfalseかをチェックするよう指示します。if文以降がtrueの場合(フラグがセットされているなど)、Alexaは{}の間に指定された指示を実行します。フラグが解除されている場合は、falseと解釈され、{}の間に書かれた指示は実行されません。

宣言されていないフラグはすべて、falseとみなされます。

以下は、「...でない」(!)記号をif文内で使用する方法の例です。これらの例は論理的には同じであり、プレイヤーのエクスペリエンスも同じになります。

バージョン1:

@escape room
    *say
        あなたは今部屋の中にいます。
    *then
        if skeletonkey {
            -> open door
        }

        -> door locked

バージョン2:

@escape room
    *say
        あなたは今部屋の中にいます。
    *then
        if !skeletonkey {
            -> door locked
        }

        -> open door

以下は、if指示内に指定されたflagunflagなど、複数の指示を実行する方法の例です。これは、何でも開けられる鍵がゲーム内で1回しか使えないアイテムの場合に便利です。

*then
        if skeletonkey {
            unflag skeletonkey
            -> open door
        }

複数のフラグをチェックする

andorを使ってif文内の複数のフラグをチェックします。

*then
        if skeletonkey and talked_to_wizard {
            -> open door
        }

この例は、プレイヤーが何でも開けられる鍵を持っており、かつ魔法使いに話しかけた場合にのみ扉を開けられるという設定を表します。ここでは、フラグが2つともセットされなければ文がtrueにはなりません。

以下は、orを使った例です。

*then
        if skeletonkey or talked_to_wizard {
            -> open door
        }

こちらは、プレイヤーが何でも開けられる鍵を持っているか、魔法使いに話しかけたかのいずれかの場合に扉を開けられるという設定を表します。

変数を設定し使用する

ゲームがプレイされなければ判断できない値を処理するには、変数を使います。たとえば、playerClassという変数を作成して、ゲーム中にプレイヤーが選択するキャラクターのクラスを格納します。

以下は、プレイヤーの応答に基づいてクラスを設定する方法の例です。

@choose class
    *say
        クラスを選んでください。戦士、賢者、盗賊の
        どれですか?
    *then
        hear 戦士 {
            set playerClass as '戦士'
            -> play introduction
        }

        hear 賢者 {
            set playerClass as '賢者'
            -> play introduction
        }

        hear 盗賊 {
            set playerClass as '盗賊'
            -> play introduction
        }

シーンの*thenセクションで、Alexaはプレイヤーが「戦士」、「賢者」、「盗賊」のいずれかを答えるまで待機します。プレイヤーがいずれかの単語を答えると、playerClassという変数に値が入ります。

  • ユーザーが「戦士」と答えた場合はクラスに「戦士」を設定します。
  • ユーザーが「賢者」と答えた場合はクラスに「賢者」を設定します。
  • ユーザーが「盗賊」と答えた場合はクラスに「盗賊」を設定します。

ナレーションで変数を使う

ナレーションをパーソナライズするには、*sayセクションや*repromptセクションで変数を使います。その場合、変数は波括弧({})で囲みます。以下はその例です。

@play introduction
    *say
        ミステリアスワールドへようこそ。あなたのクラスは{playerClass}です。

プレイヤーがフレーズを聞くときには、{playerClass}が変数の値で置き換えられています。

ゲームロジックで変数を使う

変数を使って、ゲームの動作を制御します。

@play introduction
    *say
        ミステリアスワールドへようこそ。あなたのクラスは{playerClass}です。
    *then
        if playerClass is '賢者' {
            -> mage start
        }

        if playerClass is '戦士' {
            -> warrior start
        }

        if playerClass is '盗賊' {
            -> thief start
        }

この例では、playerClassに格納された値によって次のシーンが決まります。

変数に数字を入れ、ゲームが進むにつれて変数を操作することもできます。以下の例は、playerHealthという変数の初期値を表しています。

set playerHealth as 10

以下はこの変数の値が減る場合の例です。

@take damage
    *say
        1ダメージを受けました。
    *then
        decrease playerHealth by 1

        if playerHealth <= 0 {
            -> game over
        }

この例ではplayerHealth変数の値が減り、値が0未満になったかどうかを確認することでgameoverというシーンに遷移するかどうかをすぐに判断しています。

decreaseコマンドは、変数の値から指定した数を引くコマンドです。変数関連の指示については、その他のセクションを参照してください。

変数が宣言されていない場合、変数を評価する文はすべてfalseを返します。たとえば、playerHealthが宣言されていない場合、if playerHealth <= 0はfalseを返し、ゲームロジックはplayerHealthを正の値とみなして進みます。

ランダム機能を使用して、プレイヤーに代わって決定する

ゲーム内でランダムに決定を行う場合、あるいは動的コンテンツの乱数を生成する場合には、roll指示を使用できます。

roll指示は転がすサイコロの数、面の数を組み合わせた引数を1つ取り、1から最大数までの範囲で結果を返します。標準的な6面のサイコロを転がす場合はroll 1d6、2面のコインを転がす場合はroll 1d2のように記述します。1行にroll指示だけを記述する場合、結果はrollResultという特殊な変数に格納されるので、以降の行で確認できます。

以下は、ユーザーが「私の代わりに決めて」と言った場合に、ユーザーを@scene one@scene twoのいずれかにランダムに遷移させる例です。

*then
    hear 私の代わりに決めて {
        roll 1d2
            if rollResult == 1 {
            -> scene one
            }
        -> scene two
    }

視覚要素を追加する

*showプロパティを使ってシーンの視覚要素を定義することで、Alexa Presentation Language(APL)をスキルに追加できます。

@My Showy Scene
    *say
        ハイキングに行きましょう。
    *show
        template: 'default'
        background:'https://www.example.com/url/to/image.jpg'
        title: 'ACEフレームワーク'
        subtitle: 'ハイキングの始まり'
    *then
        -> startHike

例では、次の要素を定義しています。

  • 「template」にプロジェクトで使用する「default」というAPLテンプレートを定義します。
  • 「background」に画像を指定します。
  • 「title」に'ACEフレームワーク'と指定します。
  • 「subtitle」に'ハイキングの始まり'と指定します。

Alexa Content Engineに含まれるストーリー例では、content/en-us/example_story/resources/apl-templates.jsonファイルでストーリーのAPLテンプレートを定義しています。例のapl-templates.jsonファイルは、defaultキーの下の「default」テンプレートを定義しています。

APLテンプレートは、視覚インターフェースの構造を定義します。シーンの*showセクションを使ってコンテンツに渡すコンポーネントを表示するには、apl-templates.jsonファイルの各APLテンプレートに対して、datasourcesとしてコンポーネントを指定します。以下は、datasourcesの例です。

{
    "default": {
        ...
        "datasources": {
            "visualProperties": {
                "background": "https://www.example.com/url/to/image.jpg",
                "title": "",
                "subtitle": ""
            }
        }
    }
}

各コンポーネントについて、デフォルト値がない場合には""を指定するか、デフォルト値を二重引用符(")で囲んで指定します。

独自のAPLテンプレートを作成する方法については、Alexa Presentation Languageを参照してください。

すべてのシーンに視覚要素を追加する

特定のシーンで上書きされない場合にデフォルトで表示するシーンを追加するには、以下のように@global prepend*showプロパティを追加します。

// すべてのシーンに視覚要素を追加します
@global prepend
    *show
        template: 'default'
        background:'https://www.example.com/url/to/image.jpg'
        title: 'ABCフレームワーク'
        subtitle: ''
    *then
        // どのシーンでも「最初から始めて」を聞き取ります
        hear 最初から始めて {
            // 最初のシーンに戻ります
            -> start
        }

この例では、グローバルのstart overコマンドをすべてのシーンに追加しています。これにより、プレイヤーが「最初から始めて」と言うと最初のシーンに戻ります。

@global prependは、プレイヤーがどこからでも再起動できるようにするヘルプメニューを追加するのセクションで使った@global appendに似ています。2つともほかのすべてのシーンに適用される点は同じですが、各シーンのどこに適用されるかという点が違います。@global prependは、名前のとおり、シーンの前に適用されます。同様に、@global appendは、シーンの後に適用されます。

音響効果を追加する

AlexaでサポートされるSSMLタグを使ってコンテンツをカスタマイズできます。コンテンツに音響効果やオーディオファイルを追加するには、SSMLのaudioタグを使います。SSMLリファレンスのaudioタグを参照してください。

@start
    *say
        すごいゲームにようこそ!
        <audio src='https://s3.amazonaws.com/.../yourAudioFile.mp3' />
        海賊と商人、どちらになりたいですか?

別の音声を追加する

SSMLのvoiceタグを使って、Alexaスキルでさまざまな音声を使用できます。さまざまな音声の詳細については、SSMLリファレンスのvoiceタグを参照してください。

    @start
        *say
            <voice name='Kendra'>私は人間ではありません。</voice>

bgm(バックグラウンドミュージック)

    *then
        bgm https://url-to-the-background-music.mp3

シーンのナレーションにBGMを組み合わせます。

BGMは、カスタムのAmazon Pollyを使ったフォアグラウンドのオーディオまたはナレーションと組み合わせた場合にのみ機能します。Alexaの音声と組み合わせることはできません。*thenの後にbgmを挿入します。