No hay resultados
We are excited to share a new template for developers, GameHelper. This template helps you build game guides or user guides for your favorite game. In this tutorial, we will build a skill that tells you how to play chess. There will be five main interaction points that will provide information about how to play the game. The skill in this example will also have the ability to provide a user with a random tip to help improve a user’s game. For this game we also thought it would be interesting to allow the user to ask Alexa about a certain chess piece and get some information about it.
This skill can be adapted to accommodate your favorite game, by changing some basic text. It is also possible to add extra functionality to show features of your favorite game.
After completing this tutorial, you'll know how to do the following:
Skills are managed through the Amazon Developer Portal. You’ll link the Lambda function you created above to a Skill defined in the Developer Portal.
Next, we need to define our skill’s interaction model. Let’s begin with the intent schema. In the context of Alexa, an intent represents an action that fulfills a user’s spoken request. Intents can optionally have arguments called slots.
1. First, you will need to download the sample repository. Download the GameHelper Template and extract it to a local directory.
2. In the newly extracted template directory, go to the speech assets folder. Copy & paste the contents of Intent.json into the Intent Schema field.
Here is an example.
{ "intents": [{ "intent": "AMAZON.HelpIntent", "slots": [] },{ "intent": "AMAZON.StopIntent", "slots": [] },{ "intent": "AMAZON.CancelIntent", "slots": [] },{ "intent": "OverviewIntent", "slots": [] },{ "intent": "SetupIntent", "slots": [] },{ "intent": "GoalIntent", "slots": [] },{ "intent": "TipIntent", "slots": [] },{ "intent": "PieceIntent", "slots": [{ "name": "Piece", "type": "ChessPiece" }] } ] }
3. As part of the PieceIntent we are using a custom slot type, so the next thing we need to do is define this new slot type, to restrict the range of responses Alexa expects from a user. You do this by clicking the ‘Add a slot’ button and entering the details for a ‘ChessPiece’ slot type as shown below.
king queen rook bishop knight pawn
4. Click OK to save the slot, and you should see the slot listed.
5. Next we need to define the utterances. These are the phrase structures you want a user to speak. Copy & paste the contents of the Sample Utterances text file into the Sample Utterances field. Here is an example.
OverviewIntent How do I play
OverviewIntent How do I play chess
OverviewIntent give me an overview of chess
OverviewIntent give me an overview
SetupIntent how do I set up a chess game
SetupIntent how do I set up chess
SetupIntent how do I set up a chess board
SetupIntent how do I set up a game of chess
GoalIntent how do I win a game
GoalIntent how do I win a game of chess
GoalIntent how do I win chess
GoalIntent how do I win
TipIntent can I have a chess tip please
TipIntent give me a chess tip
PieceIntent Tell me about {ChessPiece}
6. Click Save and you should see the model being built (this may take a minute). Then click Next.
Now we need to create our AWS Lambda function to host our skill logic.
Installing and Working with the Alexa Skills Kit SDK for Node.js (alexa-sdk)
To make the development of skills easier, we have created the ASK SDK for Node.js.We will be using this module to deploy the sample. The alexa-sdk is immediately available on github here and can be deployed as a node package from within your Node.js environment.
To leverage the SDK for ASK you will need to install Node.js and update npm. To set this up on your machine, follow the steps described.
Once you have the source downloaded, node installed and npm updated, you are ready to install the ASK-SDK. Install this in the same directory as your src/index.js file for your skill. Open a terminal, change the directory to the src directory of your skill, and then in the command:
npm install --save alexa-sdk
Once this is installed you will need to include the node_modules directory with the source code for your skill when you compress the src for uploading to AWS Lambda. Let's do this with the example.
Navigate to where you downloaded the sample repository and installed the Alexa SDK in step 3. Select the src directory.
Compress the files inside the src directory into a zip file. Remember, do not compress the src directory itself, just the files within the directory, the index.js file and the node_modules folder. Your compressed file should show up in the src directory. You will use this file in a later step.
Open aws.amazon.com and then choose ‘Create a Free Account’
Sign in to the AWS Console
AWS Lambda lets you run code without provisioning or managing servers. You pay only for the compute time you consume - there is no charge when your code is not running. With Lambda, you can run code for virtually any type of application or backend service - all with zero administration. Just upload your code and Lambda takes care of everything required to run and scale your code with high availability.
Note: If you are new to Lambda and would like more information, visit the Lambda Getting Started Guide.
Select “Create a Lambda Function” to begin the process of defining your Lambda function.
At the bottom of the ‘Select Blueprint’ page, select “Next”
You should now be in the "Configure Function" section. Enter the Name, Description, and Runtime for your skill.
Select the ‘Code Entry Type’ as ‘Upload Zip File’ and upload the zip file containing the example you created at the end of step 2. Note: This zip file should contain the contents of the src directory, including the node_modules subfolder, and not the src folder itself.
Set your handler and role as follows:
Congratulations, you have created your AWS Lambda function. Copy the ARN for use in the Configuration section of the Amazon Developer Portal.
Navigate back to developer.amazon.com and select your skill from the list. You can select the skill name or the edit button.
Select the Configuration section. Add the ARN from the Lambda function you created in the AWS Console at the end of step 12. Select the Lambda ARN (Amazon Resource Name) radio button. Then, select “No” for account linking since we will not be connecting to an external account for this tutorial. Paste the ARN you copied earlier into the Endpoint field. Then select Next.
You have now completed the initial development of your skill. Now its time to test.
In the Test tab we are going to enter a sample utterance in the service simulator tab.
In this example we have called the skill ‘chess helper’ – This is the ‘Invocation Name’ we added when we set up the Skill.
Enter ‘open chess helper’ and select Ask.
You should see the formatted JSON request from the Alexa Service and response coming back.
If you look at the speech output in the Lambda response you can continue to have a conversation and test out the skill by entering responses to the questions and pressing ask once more.
Assuming your Echo device is online (and logged in with the same account as your developer account) you should now see your skill enabled in the Alexa Companion app and you should be able to ask Alexa to launch your skill.
Review the publication guidelines for functional tests that can be performed.
Not working? Are you getting an invalid response when testing your skill? * Do you have the right ARN copied from your Lambda function into the skill in the developer portal?
As part of this demo we will be placing an image of the chess piece on the home card along with a description of that piece. For more information on using Home Cards go here. First we created a group of images adhering to the guidelines:
You must supply two sizes of the image, so the image looks great on different screen sizes
Small Image 720x480 (pixels)
Large Image 1200x800 (pixels)
Hosting the images must also follow these guidelines:
The endpoint must supply an SSL certificate signed by an Amazon-approved certificate authority.
The endpoint must also allow cross-origin resource sharing (CORS). This allows Alexa to request the images for processing before they are displayed on the home card.
In this tutorial, we opted to use Amazon S3 to host the images needed. We simply created a new bucket and uploaded the images. You must then change the permissions of the images to be available to the public.
Finally you must configure the bucket to enable CORS. A tutorial for this can be found here.
Customize the Game
There are four main Intents which are defined in this skill and can be used to describe any game. These are:
OverviewIntent
This intent gives an overview of the game, some basic rules etc, it simply returns the value stored in the ‘overviewMessage’ variable.
SetupIntent
This intent should describe how to set up the game, so for example in a poker game how many cards does each player get etc. This also returns what is stored in the ‘setupMessage’ variable.
GoalIntent
This intent should describe how you can win the game, for example how would you win a game of Blackjack? This returns the value store in the variable ‘goalMessage’.
TipIntent
This intent should give the user some tips on how to play the game. These tips are held in a variable called ‘tips’. This intent works a little differently instead of just reading out a value, we chose one from a list at random. You can see the values near the top of your index.js file. The tips variable should look like this:
var tips = [
"U S Chess dot org recommends that you know what the pieces are worth.",
"U S Chess dot org recommends that you Look at your opponent's move",
"U S Chess dot org recommends that you Have a plan",
"U S Chess dot org recommends that you Control the center",
"U S Chess dot org recommends that you Keep your king safe",
"U S Chess dot org recommends that you Know when to trade pieces",
"U S Chess dot org recommends that you Think about the endgame",
"U S Chess dot org recommends that you Always be alert"];
The tips variable is an array of string values, you can add as many or as little of these tips as you like. However, it may be worth noting that the more tips you have in this list, the chance of the user hearing the same tips becomes smaller.
In this demo we added a feature which describes the chess pieces and what they do. This was done by adding a custom slot type to represent the available chess pieces, and then mapping that to a new intent. In this example we use the PieceIntent along with the custom slot to determine which chess piece the user would like to know about. Getting this value from the Intent can be seen in the following code:
var slotValue = this.event.request.intent.slots.Piece.value;
We use this slot value to look into an array of objects which holds all of the details for the chess pieces, this can be seen below: (the values fields have been shortened for this example)
var pieces = [
{ key: "king", imageLarge: "https://s3.amazonaws.com/gamehelperimages/king_large.png", imageSmall: "https://s3.amazonaws.com/gamehelperimages/king_small.png", value: "In chess, the king is the most important piece. The object of the game is to threaten the opponent's king in such a way that escape is not possible (checkmate). A king can move one square in any direction (horizontally, vertically, or diagonally) unless the square is already occupied by a friendly piece or the move would place the king in check. As a result, the opposing kings may never occupy adjacent squares." },
{ key: "queen", imageLarge: "https://s3.amazonaws.com/gamehelperimages/queen_large.png", imageSmall: "https://s3.amazonaws.com/gamehelperimages/queen_small.png", value: "The queen is the most powerful piece in the game of chess, able to move any number of squares vertically, horizontally or diagonally. Each player starts the game with one queen, placed in the middle of the first rank next to the king." },
{ key: "rook", imageLarge: "https://s3.amazonaws.com/gamehelperimages/rook_large.png", imageSmall: "https://s3.amazonaws.com/gamehelperimages/rook_small.png", value: "A rook (borrowed from Persian \"chariot\") is a piece in the strategy board game of chess. Formerly the piece was called the tower, marquess, rector, and comes (Sunnucks 1970). The term castle is considered informal, incorrect, or old-fashioned. The Rook moves horizontally or vertically, through any number of unoccupied squares." },
{ key: "bishop", imageLarge: "https://s3.amazonaws.com/gamehelperimages/bishop_large.png", imageSmall: "https://s3.amazonaws.com/gamehelperimages/bishop_small.png", value: "A bishop is a piece in the board game of chess. Each player begins the game with two bishops. One starts between the king's knight and the king, the other between the queen's knight and the queen. The bishop has no restrictions in distance for each move, but is limited to diagonal movement. Bishops, like all other pieces except the knight, cannot jump over other pieces. A bishop captures by occupying the square on which an enemy piece sits." },
{ key: "knights", imageLarge: "https://s3.amazonaws.com/gamehelperimages/knight_large.png", imageSmall: "https://s3.amazonaws.com/gamehelperimages/knight_small.png", value: "The knight is a piece in the game of chess, representing a knight (armored cavalry). It is normally represented by a horse's head and neck. Each player starts with two knights, which begin on the row closest to the player, one square from each corner.The knight move is unusual among chess pieces. When it moves, it can move to a square that is two squares horizontally and one square vertically, or two squares vertically and one square horizontally. The complete move therefore looks like the letter L. Unlike all other standard chess pieces, the knight can 'jump over' all other pieces (of either color) to its destination square." },
{ key: "pawn", imageLarge: "https://s3.amazonaws.com/gamehelperimages/pawn_large.png", imageSmall: "https://s3.amazonaws.com/gamehelperimages/pawn_small.png", value: "The pawn is the most numerous piece in the game of chess, and in most circumstances, also the weakest. It historically represents infantry, or more particularly, armed peasants or pikemen. Each player begins a game of chess with eight pawns, one on each square of the rank immediately in front of the other pieces. Unlike the other pieces, pawns may not move backwards. Normally a pawn moves by advancing a single square, but the first time a pawn is moved, it has the option of advancing two squares. Pawns may not use the initial two-square advance to jump over an occupied square, or to capture." }
];
As in the example above, each object in the list is made of three fields, a key, which we use to store the pieces name. The object also has an image field, this is used to store the image URLS (one for small images, one for large images) which can be used to show on the skills card in the Alexa app. Finally we have a value field, this is used to store any information about that piece.
When the PieceIntent is invoked, we get the slot value, we then use that to check against the key values in the pieces list. If the key exists in the list, then we know we have found the piece the user wants to know about, and we can parse out the data we need, as shown in the code below:
'PieceIntent': function () {
// get value from slot
var slotValue = this.event.request.intent.slots.Piece.value;
// initialize the output text to an error message
var outputText = errorMessage;
var cardTitle = "";
var cardContent = "";
var largeImage = "";
var smallImage = "";
// Using the slot value, search the list of piece objects and find the one where the key is the same as slot value.
for (var i = 0; i < pieces.length; i++) {
if (pieces[i].key == slotValue) {
// When we have found the piece we are looking for,
// set the output text to the value field of the found object.
outputText = pieces[i].value;
cardTitle = "The " + pieces[i].key;
cardContent = pieces[i].value;
// Set image URL
smallImage = pieces[i].imageSmall;
largeImage = pieces[i].imageLarge;
}
}
// Create image object for home card
var imageObj = {
smallImageUrl: smallImage,
largeImageUrl: largeImage
};
outputText = outputText + ", " + pieceMessage;
this.emit(':askWithCard', outputText, repromtMessage, cardTitle, cardContent, imageObj);
}
}
Not seeing your images on the home card?
You can check that the correct information is being sent to Alexa by using the Amazon developer console. Using the Test tab you are able to make requests and see the response being produced by your code. You can also see the information which is to be used to create the card:
"card": {
"text": "Some text goes here.",
"title": "Card title",
"image": {
"smallImageUrl": "some url to image",
"largeImageUrl": " some url to image "
},
"type": "Standard"
},
If you copy and paste either the smallImageUrl value or the largeImageUrl into a browser, can you see the image?
Does the card part of your response have the same format as the card section above?
Does the hosting endpoint support cross-origin resource sharing (CORS)?
Do your images conform to the standards described here?
Here are some other things to try:
Can you see if you can read in the tips from an external JSON file?
Can you use Dynamo to store who won the game last time?
Can you save the information of the people you usually play with?
i.e John always like to be the car when playing Monopoly.
Can you incorporate your user profiles into the “Set up” section of the game?
Can you create a leader board, and create a Scoreboard Intent?
How would you tackle a game like Magic the Gathering?
If you need a reminder of how to complete the Publishing Information or Privacy and Compliance, please see one of our earlier tutorials.
We look forward to seeing the new skills you will create with this template. And don't forget to get your free Alexa dev t-shirt. See terms and conditions.
Code happy,
Noelle
@NoelleLaCharite