電子發(fā)燒友App

硬聲App

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示
創(chuàng)作
電子發(fā)燒友網(wǎng)>電子資料下載>電子資料>適用于Amazon Alexa的游戲Speed Tap開源

適用于Amazon Alexa的游戲Speed Tap開源

2022-12-28 | zip | 0.04 MB | 次下載 | 免費(fèi)

資料介紹

描述

概括

Speed Tap 是一款適用于 Amazon Alexa 的游戲,它使用 Echo Buttons 來測(cè)試玩家的反應(yīng)時(shí)間和注意力。該按鈕會(huì)在隨機(jī)顏色之間循環(huán),玩家必須在按鈕為綠色時(shí)點(diǎn)擊該按鈕。隨著游戲的進(jìn)行,燈光速度加快,難度也越來越大。

該游戲結(jié)合了許多Alexa APIAWS 服務(wù)來創(chuàng)造引人入勝的體驗(yàn),同時(shí)保持簡(jiǎn)單的游戲玩法。這個(gè)故事將重點(diǎn)解釋為什么需要這些以及它們的大致工作原理,以便其他開發(fā)人員了解什么是可能的以及如何進(jìn)行。

這項(xiàng)技能是使用 Node、AWS 服務(wù)和alexa-app框架從頭開始構(gòu)建的。

關(guān)鍵概念和獨(dú)特功能

從較高的層面來看,這些是使這款游戲無論是作為 Alexa Skill 還是從開發(fā)/編程的角度來看都獨(dú)一無二的東西:

  • 玩家與所有 Alexa 用戶競(jìng)爭(zhēng)以獲得世界紀(jì)錄,這使得它比僅僅與自己對(duì)戰(zhàn)更有趣和互動(dòng)。
  • AlexaSpeedTap.com的集成網(wǎng)站具有一個(gè)自動(dòng)更新的排行榜,顯示每個(gè)玩家的高分。或者,玩家可以通過使用 Alexa API 的游戲本身在排行榜上無縫連接他們的真實(shí)姓名。
  • In-Skill-Purchases允許玩家購買額外的生命以在他們錯(cuò)過后繼續(xù)游戲。
  • Alexa 聲音庫隨機(jī)短語Speechcons(感嘆詞)用于使體驗(yàn)更加引人入勝和生動(dòng),并賦予其一些個(gè)性孩子們特別喜歡它。

架構(gòu)和 AWS 服務(wù)

?
poYBAGOrnF-ANzi3AACwMoGZYEo890.png
AWS 架構(gòu)
?

拉姆達(dá)

游戲的所有代碼都在 AWS Lambda 中。它是使用 alexa-app 框架在 Node.js 中編寫的。Alexa 事件(玩游戲的用戶)和 CloudWatch Events 使用相同的 lambda 函數(shù)代碼,這會(huì)觸發(fā)后臺(tái)任務(wù)來更新排行榜。

動(dòng)態(tài)數(shù)據(jù)庫

個(gè)人球員和全球世界紀(jì)錄統(tǒng)計(jì)數(shù)據(jù)都存儲(chǔ)在 DynamoDB 中。對(duì) DDB 的訪問是使用 Amazon 的 aws-sdk 包完成的,我在其頂部編寫了一個(gè)自定義層以簡(jiǎn)化 API 并在現(xiàn)有的 Promise 接口上提供一個(gè)異步/等待接口。

每次交互時(shí),用戶數(shù)據(jù)和狀態(tài)都會(huì)保存到 DDB,從而使游戲能夠以隨著時(shí)間的推移和適當(dāng)?shù)姆绞脚c用戶進(jìn)行交互(請(qǐng)參閱下面的用戶體驗(yàn)部分)。

S3

Lambda 函數(shù)每 5 分鐘生成一個(gè)包含所有高分和當(dāng)前世界紀(jì)錄數(shù)據(jù)的 JSON 文件,并將其存儲(chǔ)在公共 S3 存儲(chǔ)桶中。然后通過 AJAX 從網(wǎng)站加載此 JSON 文件以顯示排行榜并以大文本宣布當(dāng)前的記錄保持者。

后臺(tái)任務(wù) - CloudWatch Events

需要一個(gè)“后臺(tái)任務(wù)”來定期更新包含網(wǎng)站數(shù)據(jù)的 JSON 文件。由于無法按計(jì)劃觸發(fā) Lambda 函數(shù),因此使用 CloudWatch Events 觸發(fā)觸發(fā) Lambda 函數(shù)的事件。

然后,Lambda 函數(shù)代碼會(huì)檢測(cè)它是由 Alexa 還是 CloudWatch Events 觸發(fā)的,并做出相應(yīng)的行為。

ALEXA API 和功能

許多 Alexa API 和功能被用來創(chuàng)建這個(gè)游戲。以下是使用的內(nèi)容和原因的摘要。

小工具API

Gadgets API需要與 Echo Buttons 交互,實(shí)際上有兩種風(fēng)格,它們都必須聲明為技能所需的接口。

GAME_ENGINE是用于監(jiān)聽 Echo Buttons 事件的接口。

GADGET_CONTROLLER是用于實(shí)際設(shè)置按鈕本身的燈光模式的接口。

這是兩個(gè)不同的 API,要讓它們無縫地協(xié)同工作,一開始理解起來有點(diǎn)棘手。仔細(xì)閱讀文檔、了解每個(gè)文檔的局限性并在設(shè)計(jì)您的體驗(yàn)時(shí)了解什么是可能的、什么是不可能的,這一點(diǎn)很重要。

客戶資料 API

Customer Profile API允許技能請(qǐng)求有關(guān)用戶的信息,例如姓名、電子郵件地址和電話號(hào)碼。使用時(shí),該技能會(huì)在用戶的 Alexa 應(yīng)用程序中向用戶出示一張卡片以授予權(quán)限,然后才能訪問此信息。如果用戶請(qǐng)求,Speed Tap 使用此 API 獲取用戶名以顯示在網(wǎng)站的排行榜上。

技能購買

In-Skill Purchases (ISP) API允許技能請(qǐng)求用戶使用真錢進(jìn)行實(shí)際購買,以解鎖技能中的內(nèi)容或功能。Speed Tap 使用“消耗品”ISP (CISP),這是可以購買和用完的物品,而不是一次性購買和訂閱,它們不會(huì)在使用時(shí)消失。

Speed Tap 使用戶能夠在點(diǎn)擊錯(cuò)誤的顏色后繼續(xù)。每個(gè)新用戶都會(huì)獲得 5 條額外的生命,當(dāng)他們離開后,他們可以選擇使用 CISP 再購買 10 條生命。

展示

Speed Tap 利用顯示接口 API與 Echo Show 和 Echo Spot 設(shè)備上的顯示功能進(jìn)行交互,方法是在游戲開始時(shí)顯示彩色“啟動(dòng)畫面”,并在每次按下按鈕時(shí)顯示當(dāng)前回合。

?

隨著帶有顯示器的 Echo 設(shè)備變得越來越普遍,技能通過視覺提示和附加信息來補(bǔ)充其音頻輸出非常重要。

聲音庫

Alexa Skills Kit 聲音庫是可用于任何技能的音頻片段集合。這些音頻文件由亞馬遜存儲(chǔ),可以插入到任何響應(yīng)中,而無需技能作者創(chuàng)建、存儲(chǔ)或交付它們。例如:


		src='soundbank://soundlibrary/ui/gameshow/amzn_ui_sfx_gameshow_countdown_loop_32s_full_01'/> 
		

隨著用于多種用途的聲音樣本的選擇越來越多,這個(gè)庫為技能作者提供了一種簡(jiǎn)單的方法來為他們的技能添加一點(diǎn)額外的個(gè)性和樂趣。Speed Tap 在等待用戶按下按鈕以增加戲劇性和張力時(shí)將這些聲音用于音樂,以及用于積極和消極事件。

演講者

Alexa 語音輸出可以比默認(rèn)的文本轉(zhuǎn)語音更具表現(xiàn)力的方式說出某些詞。這些“ Speechcons ”僅限于每種支持語言的一組特定單詞,并使用標(biāo)記插入到您的 SSML 響應(yīng)中:

<say-as interpret-as="interjection">abracadabra!say-as> 

Speed Tap 使用 Speechcons 響應(yīng)每個(gè)按鈕按下,讓游戲?qū)τ脩魜碚f更有趣,并增加一點(diǎn)多樣性。玩游戲的孩子特別喜歡有趣的輸出。

Alexa 技能活動(dòng)

技能事件API允許技能響應(yīng)更改或事件,而無需用戶直接與技能交互。例如,當(dāng)用戶啟用或禁用技能時(shí),可以通知該技能。

當(dāng)用戶使用手機(jī)上的 Alexa 應(yīng)用程序啟用或禁用對(duì)其客戶資料信息的訪問時(shí),Speed Tap 使用 Skill Events API 立即做出響應(yīng)。收到此事件后,Speed Tap 會(huì)立即調(diào)用 API 獲取用戶姓名,因此無需用戶再次玩游戲即可更新排行榜。

用戶體驗(yàn)

語音應(yīng)用程序的用戶體驗(yàn)至關(guān)重要且微妙。網(wǎng)絡(luò)和移動(dòng)等顯示媒體不同,音頻需要更長的時(shí)間來呈現(xiàn)信息,并且用戶無法處理選項(xiàng)列表或掃描屏幕以了解他們下一步想做什么。

Speed Tap 實(shí)施了許多改進(jìn)用戶體驗(yàn)的方法,這些方法雖然不那么明顯,但卻產(chǎn)生了很大的不同。

共享的全球經(jīng)驗(yàn)

與移動(dòng)應(yīng)用程序不同,大多數(shù) Alexa 游戲都是單人游戲,不與其他玩家社區(qū)互動(dòng)。用戶是孤立的,通常玩游戲是為了個(gè)人高分或自己探索游戲。

但是……和別人一起玩游戲更有趣!

Speed Tap 朝著這個(gè)方向邁出了獨(dú)特的一步,讓玩家可以看到他們的分?jǐn)?shù)與其他人的比較情況。網(wǎng)站上的排行榜列出了每個(gè)玩家的個(gè)人最高分以及他們用了多少次連續(xù)得分來達(dá)到這一目標(biāo)。添加你的真實(shí)姓名的能力讓你有吹牛的權(quán)利,看看你是否在打敗你的朋友。

玩家知道什么與實(shí)際上是什么?

為用戶提供相關(guān)信息的一個(gè)重要部分是跟蹤他們所知道的,而不是實(shí)際情況。

在 Speed Tap 中,這與世界紀(jì)錄有關(guān)。當(dāng)用戶玩游戲時(shí),他們可能會(huì)被告知當(dāng)前的世界紀(jì)錄是 25 次點(diǎn)擊。但下次他們比賽時(shí),世界紀(jì)錄可能會(huì)增加到 30,他們很想知道。

懶人技能只會(huì)在用戶每次開始游戲時(shí)告訴用戶世界紀(jì)錄。但為了獲得更好的體驗(yàn),該技能需要知道用戶上次被告知的世界紀(jì)錄是什么,并且只有在更改時(shí)才告訴他們。通過這種方式,他們可以獲得他們想要的信息,但如果相同,則不必每次都被迫忍受關(guān)于當(dāng)前世界紀(jì)錄的相同句子。

Speed Tap 通過保留兩個(gè)獨(dú)立的數(shù)據(jù)區(qū)域來跟蹤此類事件。一個(gè)保存當(dāng)前的真實(shí)信息(例如當(dāng)前的世界紀(jì)錄和持有者),而另一個(gè)保存相同的信息,但處于用戶最后知道的狀態(tài)。然后將這些進(jìn)行比較以確定應(yīng)該告訴用戶什么。代碼如下所示:

sayif `Your high score is ${user.high_score} `;
// Check to see if there is a new world record to inform the user about
if (game.world_record) {
 if (user.world_record && user.world_record < game.world_record) {
   say `and there is a new world record. The highest score is now ${game.world_record}`;
 }
 else if (game.world_record_user && game.world_record_user===request.data.session.userId) {
   say `and you still hold the world record`;
 }
 else {
   say `and the world record is ${game.world_record}`;
 }
 user.world_record = game.world_record;
}

增量體驗(yàn)/會(huì)話跟蹤

由于用戶會(huì)多次玩游戲,因此不應(yīng)每次都向他們展示冗長的音頻介紹。當(dāng)他們多次使用特性時(shí),不應(yīng)該要求他們?nèi)淌軐?duì)他們已經(jīng)理解的東西的解釋。

出于這個(gè)原因,跟蹤用戶與技能交互時(shí)的體驗(yàn)對(duì)于技能來說很重要,這樣技能就知道何時(shí)可以縮短交互。這正是人類所做的,通過這樣做,一項(xiàng)技能似乎更自然。

Speed Tap 為每個(gè)用戶保留一個(gè)“體驗(yàn)”對(duì)象,該對(duì)象隨依賴于它的每種交互類型進(jìn)行更新。然后,根據(jù)用戶當(dāng)前的體驗(yàn)水平更改輸出。下面是一些示例代碼:

// Open with a more different intro depending on how often the user has played
if (request.experience("session_count",false) <= 1) {
 say `Welcome to ${speedtap}. This is a game of quick reactions and concentration. Would you like to hear a quick explanation of how to play?`;
}
else {
 if (request.experience("session_count",false) < 4) {
   say `Welcome back to ${speedtap}.`;
 }
 else {
   response.say(`Welcome back.`);
 }
} 

experience 對(duì)象還用于確定是否應(yīng)該給出有關(guān)排行榜如何工作、所需權(quán)限等的解釋。

隨機(jī)輸出

一遍又一遍重復(fù)相同輸出的技能變得非常重復(fù)并且感覺不自然。至少隨機(jī)化部分輸出很重要,這樣技能就不會(huì)感覺那么“僵硬”。

對(duì)于 Speed Tap,簡(jiǎn)單的隨機(jī)化是使用我在其他技能中實(shí)施的文本后處理技術(shù)完成的。

輸出文本時(shí),{braces} 可以放在作為隨機(jī)同義詞候選詞的任何單詞或短語周圍。然后,創(chuàng)建一個(gè)可能的同義詞列表,并在輸出字符串中僅使用主鍵。單詞會(huì)自動(dòng)隨機(jī)化,使技能感覺更自然,不那么機(jī)械化。

// The synonym list
const outputSynonyms = {
 "Okay, ": ["Okay, ","Alright, ",""]
};
// A method in the response object
"randomizeSynonyms": function(synonyms) {
 try {
   let ssml = this.response.response.outputSpeech.ssml;
   ssml = ssml.replace(/\{([^\}]+)\}/g, function (m, m1) {
     if (synonyms && synonyms[m1]) {
       let s = synonyms[m1];
       if (s.length) {
         // simple array of synonyms
         return s[Math.floor(Math.random() * s.length)];
       }
     }
     return m1;
   });
   this.response.response.outputSpeech.ssml = ssml;
 } catch(e) { }
}
// Example
response.say("{Okay, }let's play."); // Could be: "Alright, let's play" or "let's play" 
// Randomize synonyms in the output during app.post()
response.randomizeSynonyms(outputSynonyms);

執(zhí)行

本節(jié)將深入探討該技能的實(shí)現(xiàn)細(xì)節(jié),并展示演示每種功能如何實(shí)現(xiàn)的代碼片段。

觸發(fā)切換

Lambda 函數(shù)需要根據(jù)它是從 CloudWatch Events(更新排行榜)還是從 Alexa 觸發(fā)而表現(xiàn)不同。Lambda 函數(shù)處理程序使用以下代碼進(jìn)行切換:

// connect to lambda
exports.handler = function(event, context, callback) {
 if (event && "aws.events"===event.source) {
   // Scheduled Event!
   app.scheduled(event).then((response)=>{
     callback(null,response);
   }).catch((e)=>{
     callback(e);
   });
 }
 else {
   // Alexa Request
   log("Alexa Request");
   app.handler(event, context, callback);
 }
}; 

按鈕偵聽器事件

技能使用 Gadgets API 監(jiān)聽按鈕事件。該技能返回一個(gè)指令,定義觸發(fā)技能的確切條件。這是一個(gè)示例按鈕偵聽器指令,它將導(dǎo)致在按下按鈕或超時(shí)時(shí)調(diào)用技能。

{
 "type" : "GameEngine.StartInputHandler",
 "timeout" : 25000,
 "proxies" : ["button"],
 "recognizers" : {
   "button_down_recognizer" : {
     "type" : "match",
     "anchor" : "end",
     "fuzzy" : false,
     "pattern" : [{
         "action" : "down"
       }
     ]
   }
 },
 "events" : {
   "button_down_listener" : {
     "meets" : ["button_down_recognizer"],
     "reports" : "matches",
     "shouldEndInputHandler" : true
   },
   "timeout" : {
     "meets" : ["timed out"],
     "reports" : "history",
     "shouldEndInputHandler" : true
   }
 }
} 

光指令

有幾種不同格式的 GadgetController.SetLight 指令可以根據(jù)按鈕的狀態(tài)更改按鈕的顏色。API 文檔詳細(xì)介紹了這些狀態(tài)是什么以及它們?nèi)绾喂ぷ鳌?/font>

這是一個(gè)循環(huán)顯示顏色并等待用戶在按鈕變?yōu)榫G色時(shí)按下按鈕的示例指令。當(dāng)代碼接收到按鈕按下事件時(shí),它還會(huì)接收按鈕被按下時(shí)的顏色。這允許代碼檢查用戶是否在它為綠色時(shí)按下它。

{
 "type" : "GadgetController.SetLight",
 "version" : 1,
 "targetGadgets" : [],
 "parameters" : {
   "triggerEvent" : "none",
   "triggerEventTimeMs" : 0,
   "animations" : [
     {
       "repeat" : 255,
       "targetLights" : ["1"],
       "sequence" : [{
           "durationMs" : 1000,
           "blend" : false,
           "color" : "0000FF"
         }, {
           "durationMs" : 1000,
           "blend" : false,
           "color" : "FFA500"
         }, {
           "durationMs" : 1000,
           "blend" : false,
           "color" : "FF0000"
         }, {
           "durationMs" : 1000,
           "blend" : false,
           "color" : "FF00FF"
         }, {
           "durationMs" : 1000,
           "blend" : false,
           "color" : "00FF00"
         }
       ]
     }
   ]
 }
}

堅(jiān)持

所有持久化都是使用 DynamoDB (DDB) 完成的。

每次調(diào)用技能時(shí),它都會(huì)檢查會(huì)話是否有用戶對(duì)象。如果沒有,它會(huì)嘗試從請(qǐng)求中給定的 userId 的 DDB 加載它。如果用戶記錄存在,它會(huì)加載它并將其存儲(chǔ)在會(huì)話中,這樣就不需要在每次調(diào)用技能時(shí)都檢索它。

用戶數(shù)據(jù)在發(fā)生變化時(shí)會(huì)持久保存回 DDB。例如,新的高分、會(huì)話計(jì)數(shù)增量、使用額外的生命等。

在觸發(fā) In-Skill Purchase 流程的情況下,實(shí)際需要技能退出,會(huì)話結(jié)束。然后,當(dāng)玩家完成購買時(shí),將創(chuàng)建一個(gè)新會(huì)話。出于這個(gè)原因,在某些情況下需要保留當(dāng)前游戲的狀態(tài)。但在大多數(shù)情況下,當(dāng)前游戲的回合和分?jǐn)?shù)需要從用戶記錄中清除,而不是持久化。

持久化用戶記錄的通用函數(shù)會(huì)清除不應(yīng)持久化的數(shù)據(jù),并調(diào)用 DDB 持久化層來存儲(chǔ)數(shù)據(jù)。

async function persist_user(persist_game_state) {
 // Persist user session back to db if it has changed
 if (user) {
   let u = JSON.parse(JSON.stringify(user));
   if (!persist_game_state) {
     delete u.round;
     delete u.lives_used;
     delete u.state;
     delete u.buttonConnected;
   }
   delete u.game;
   delete u.listenerRequestId;
   await ddb.put(app.user_persistence_table, u);
 }
}

數(shù)據(jù)庫層

javascript 的 ask-sdk 模塊有很多很棒的功能,但它的 API 對(duì)我來說仍然太低級(jí)了。我圍繞 ask-sdk 函數(shù)編寫了一個(gè)包裝器,進(jìn)一步抽象了功能。

包裝器所做的其中一件事是提取從 ask-sdk 函數(shù)返回的 Promises,而是公開異步函數(shù),以便我的代碼可以使用 await。

包裝器代碼包含在源代碼中,我打算將其清理并作為 NPM 模塊分發(fā)。下面是一個(gè)示例函數(shù),它簡(jiǎn)化了從 DDB 中檢索單個(gè)記錄的過程:

'get': async function(table, keyAttribute, keyValue) {
 let params = {TableName:table, Key:{ [keyAttribute]:keyValue } };
 return docClient.get(params).promise()
   .then( (item)=> {
     if (!item || !item.Item) { return null; }
     return item.Item;
   });
}

會(huì)話/體驗(yàn)維護(hù)

游戲源中的用戶對(duì)象包括一個(gè)“體驗(yàn)”對(duì)象,用于存儲(chǔ)用戶在玩游戲時(shí)的體驗(yàn)。作為此體驗(yàn)對(duì)象的一部分,每次啟動(dòng)游戲時(shí)都會(huì)增加 session_count 屬性。

體驗(yàn)對(duì)象還包含跟蹤用戶是否已經(jīng)聽到特定響應(yīng)的鍵。如果他們有,那么下次觸發(fā)時(shí)他們會(huì)得到一個(gè)較短的版本。例如:

if (round===1 && request.experience('intro_1')) {
 say `That was easy, but now the lights will get a little faster every round. How far can you go? Keep going.`;
}
else if (round===1) {
 say `Nice, Keep going.`;
}

文本響應(yīng)后處理

構(gòu)建被翻譯成語音的文本輸出有一些煩惱,例如復(fù)數(shù)化和 is/are 等。Speed Tap 包含文本后處理功能,可大大簡(jiǎn)化常見用例。每次調(diào)用技能后,都會(huì)自動(dòng)對(duì)輸出 SSML 執(zhí)行此后處理。

以下是后處理功能可以執(zhí)行的操作的一些示例。

let coins=1;
say `There {are} ${coins} coin{s} left.`;

處理器處理 {are} 和 {s} 并查找附近的數(shù)字以確定應(yīng)如何處理它們。在本例中,它看到“1”并且輸出為:

"There is 1 coin left."

如果 coins==2,那么同一個(gè) say 調(diào)用的輸出將是:

"There are 2 coins left."

狀態(tài)和上下文意圖

意圖缺乏狀態(tài)和上下文。意思是,有全局 AMAZON.YesIntent 和 AMAZON.NoIntent 意圖,當(dāng)用戶說“是”或“否”時(shí)會(huì)被觸發(fā)。但是這些意圖不知道問的是哪個(gè)問題,所以一種常見的方法是在每個(gè)處理程序中構(gòu)建邏輯知道被問到的問題并采取適當(dāng)?shù)男袆?dòng)。

相反,我在 alexa-app 框架上構(gòu)建了一個(gè)層,允許我創(chuàng)建“上下文意圖”。當(dāng)用戶處于某種狀態(tài)時(shí),是或否將在用戶所在的上下文中觸發(fā)函數(shù),而不是全局意圖。

例如,如果詢問用戶是否要繼續(xù),他們的會(huì)話會(huì)更新以反映他們處于“繼續(xù)”狀態(tài),并且適當(dāng)?shù)靥幚硎腔蚍瘢?/font>

app.intentMap({
 "continue": {
   [YES]: async()=>{
     await continue_game();
   }
   ,[NO]: async()=>{
     await end_game();
   }
 }
});

技能購買

In-Skill Purchases 允許玩家購買額外的生命以在他們搞砸時(shí)繼續(xù)玩。這實(shí)際上是一個(gè)復(fù)雜的主題,有很多實(shí)施怪癖和細(xì)節(jié)。一些重要的注意事項(xiàng)值得一提:

  • ISP 只能使用 CLI 工具進(jìn)行配置和部署。
  • 它將您的技能限制在美國地區(qū)(這就是 Speed Tap 不在英國的原因)。
  • 需要從技能代碼中進(jìn)行 API 調(diào)用,以向其 API 端點(diǎn)發(fā)出 https 請(qǐng)求。
  • 當(dāng)ISP流程發(fā)起后,技能完全退出,會(huì)話結(jié)束。Alexa 服務(wù)控制并引導(dǎo)用戶完成購買流程。當(dāng)它完成時(shí) - 無論成功還是失敗 - 技能將再次啟動(dòng),并帶有指示購買狀態(tài)的“Connections.Response”事件類型。
  • 該技能必須處理購買流程中的錯(cuò)誤情況以及用戶是否拒絕購買。它還必須處理用戶在購買后要求退款的情況。
  • 對(duì)于消耗品 ISP,正如 Speed Tap 使用的那樣,該技能必須記住并存儲(chǔ)用戶購買了哪些物品以及他們還剩多少。Alex 服務(wù)不維護(hù)庫存。

要觸發(fā) ISP 購買流程,必須從技能返回指令并且必須關(guān)閉會(huì)話。該指令如下所示:

{
 'type': 'Connections.SendRequest',
 'name': 'Buy',
 'payload': {
   'InSkillProduct': {
     'productId': "XYZ"
   }
 },
 'token': "arbitrary-token"
}

Alexa 技能活動(dòng)

Alexa 技能事件允許技能在沒有用戶主動(dòng)與技能交互時(shí)響應(yīng)事件。對(duì)于 Speed Tap,它處理用戶授予或撤銷使用其真實(shí)姓名的權(quán)限的情況。

下面的代碼是 Speed Tap 如何響應(yīng)此事件,使用 API 檢索用戶的真實(shí)姓名,更新他們的用戶記錄,并持久化它。

app.on('AlexaSkillEvent.SkillPermissionAccepted', async()=>{
 try {
   let user_id = request.data.context.System.user.userId;
   user = await ddb.get(app.user_persistence_table, "userid", user_id);
   let name = await app.api("/v2/accounts/~current/settings/Profile.name");
   user.name = name;
   user.linked = true;
   await persist_user();
 } catch(e) {
   console.log(e.message);
 }
});

為了響應(yīng)這些事件,技能必須注冊(cè)它希望收到這些事件的通知。使用 CLI 時(shí),這些存儲(chǔ)在 manifest.events.subscriptions 下的 skill.json 中:

      "subscriptions": [
       {
         "eventName": "SKILL_PERMISSION_ACCEPTED"
       },
       {
         "eventName": "SKILL_PERMISSION_CHANGED"
       }
     ]

聲音庫

聲音庫是一種非常好的方法,可以輕松地將聲音包含在技能中。這些聲音都按類別列在“聲音庫”頁面上。

您無需執(zhí)行任何特殊操作即可使用這些聲音。只需找到您要使用的聲音,復(fù)制列出的 SSML 內(nèi)容,然后將其插入到您的響應(yīng)中。


		src='soundbank://soundlibrary/animals/amzn_sfx_bear_groan_roar_01'/> 
		

我假設(shè)使用該soundbank:協(xié)議可以最大限度地減少延遲,因?yàn)槁曇粑募鎯?chǔ)在靠近 Alexa 內(nèi)部服務(wù)器的某些邊緣服務(wù)器上。

啟動(dòng)畫面/顯示

當(dāng)技能啟動(dòng)時(shí),會(huì)顯示一個(gè)圖形啟動(dòng)畫面。這是通過使用 Display 接口在響應(yīng)中返回指令來實(shí)現(xiàn)的。可重用函數(shù)將功能包裝在一個(gè)地方:

function display_splash_screen(request,response) {
 if (has_display(request)) {
   response.directive({
     "type" : "Display.RenderTemplate",
     "template" : {
       "type" : "BodyTemplate1",
       "backButton" : "HIDDEN",
       "backgroundImage" : {
         "contentDescription" : "",
         "sources" : [{
           "url" : "https://alexaspeedtap.com/splash.jpg",
           "size" : "MEDIUM"
         },{
           "url" : "https://alexaspeedtap.com/splash-square.jpg",
           "widthPixels":640,
           "heightPixels":640
         }
         ]
       }
     }
   });
 }
}

這不一定代表展示的最佳做法,但它可以完成工作。

使用 Display 指令時(shí),技能必須檢測(cè)用戶的設(shè)備是否有屏幕,如果沒有則不發(fā)送指令,否則會(huì)拋出錯(cuò)誤。has_display() 函數(shù)封裝了該檢查。

const has_display = function(request) {  try {    return !!request.data.context.System.device.supportedInterfaces.Display;  }  catch(e) { return false; }}; 

還必須為該技能注冊(cè) RENDER_TEMPLATE 接口。如果跳過此步驟,任何返回 Display 指令的嘗試都將導(dǎo)致異常。

寫入 S3

當(dāng)后臺(tái)任務(wù)運(yùn)行并創(chuàng)建排行榜 JSON 文件時(shí),必須從技能代碼中將其寫入 S3 存儲(chǔ)桶。

我寫了一個(gè)簡(jiǎn)單的可重用函數(shù)來將任意 javascript 對(duì)象寫入我的存儲(chǔ)桶:

const putObjectToS3 = async function (o,filename) {
 let s3 = new AWS.S3({'region': 'us-east-1'});
 let params = {
   Bucket: "alexa-speed-tap",
   Key: filename,
   Body: JSON.stringify(o),
   ContentType: "application/json",
   CacheControl: "no-cache",
   ACL: "public-read"
 };
 return s3.putObject(params).promise();
}; 

CORS

由于排行榜 JSON 文件存儲(chǔ)在 AWS S3 上,在生成的 Amazon URL 上提供服務(wù),瀏覽器將阻止它從其他域加載,例如 AlexaSpeedTap.com。

為了允許瀏覽器訪問不同服務(wù)器上的內(nèi)容,托管服務(wù)器 (S3) 必須明確允許此類請(qǐng)求。

這可以使用如下策略在權(quán)限 --> CORS 配置下的 S3 存儲(chǔ)桶上進(jìn)行配置。


<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
   <AllowedOrigin>*AllowedOrigin>
   <AllowedMethod>GETAllowedMethod>
   <MaxAgeSeconds>3000MaxAgeSeconds>
   <AllowedHeader>*AllowedHeader>
CORSRule>
CORSConfiguration>

結(jié)論

構(gòu)建 Echo Buttons 是一個(gè)獨(dú)特的挑戰(zhàn),因?yàn)?API 和實(shí)際的小工具功能有點(diǎn)棘手。但是,一旦將預(yù)期調(diào)整為實(shí)際可能的情況,并構(gòu)建了基本功能,完善體驗(yàn)和讓游戲變得有趣就相對(duì)簡(jiǎn)單了。

盡管 Speed Tap 是一款易于玩和理解的游戲,但它使用了許多使其真正獨(dú)一無二的 Alexa 功能和概念,并為玩家提供了不同于其他游戲的體驗(yàn)。

我希望你喜歡它!

?


下載該資料的人也在下載 下載該資料的人還在閱讀
更多 >

評(píng)論

查看更多

下載排行

本周

  1. 1山景DSP芯片AP8248A2數(shù)據(jù)手冊(cè)
  2. 1.06 MB  |  532次下載  |  免費(fèi)
  3. 2RK3399完整板原理圖(支持平板,盒子VR)
  4. 3.28 MB  |  339次下載  |  免費(fèi)
  5. 3TC358743XBG評(píng)估板參考手冊(cè)
  6. 1.36 MB  |  330次下載  |  免費(fèi)
  7. 4DFM軟件使用教程
  8. 0.84 MB  |  295次下載  |  免費(fèi)
  9. 5元宇宙深度解析—未來的未來-風(fēng)口還是泡沫
  10. 6.40 MB  |  227次下載  |  免費(fèi)
  11. 6迪文DGUS開發(fā)指南
  12. 31.67 MB  |  194次下載  |  免費(fèi)
  13. 7元宇宙底層硬件系列報(bào)告
  14. 13.42 MB  |  182次下載  |  免費(fèi)
  15. 8FP5207XR-G1中文應(yīng)用手冊(cè)
  16. 1.09 MB  |  178次下載  |  免費(fèi)

本月

  1. 1OrCAD10.5下載OrCAD10.5中文版軟件
  2. 0.00 MB  |  234315次下載  |  免費(fèi)
  3. 2555集成電路應(yīng)用800例(新編版)
  4. 0.00 MB  |  33566次下載  |  免費(fèi)
  5. 3接口電路圖大全
  6. 未知  |  30323次下載  |  免費(fèi)
  7. 4開關(guān)電源設(shè)計(jì)實(shí)例指南
  8. 未知  |  21549次下載  |  免費(fèi)
  9. 5電氣工程師手冊(cè)免費(fèi)下載(新編第二版pdf電子書)
  10. 0.00 MB  |  15349次下載  |  免費(fèi)
  11. 6數(shù)字電路基礎(chǔ)pdf(下載)
  12. 未知  |  13750次下載  |  免費(fèi)
  13. 7電子制作實(shí)例集錦 下載
  14. 未知  |  8113次下載  |  免費(fèi)
  15. 8《LED驅(qū)動(dòng)電路設(shè)計(jì)》 溫德爾著
  16. 0.00 MB  |  6656次下載  |  免費(fèi)

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935054次下載  |  免費(fèi)
  3. 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
  4. 78.1 MB  |  537798次下載  |  免費(fèi)
  5. 3MATLAB 7.1 下載 (含軟件介紹)
  6. 未知  |  420027次下載  |  免費(fèi)
  7. 4OrCAD10.5下載OrCAD10.5中文版軟件
  8. 0.00 MB  |  234315次下載  |  免費(fèi)
  9. 5Altium DXP2002下載入口
  10. 未知  |  233046次下載  |  免費(fèi)
  11. 6電路仿真軟件multisim 10.0免費(fèi)下載
  12. 340992  |  191187次下載  |  免費(fèi)
  13. 7十天學(xué)會(huì)AVR單片機(jī)與C語言視頻教程 下載
  14. 158M  |  183279次下載  |  免費(fèi)
  15. 8proe5.0野火版下載(中文版免費(fèi)下載)
  16. 未知  |  138040次下載  |  免費(fèi)