With the release of the Mango Toolset, Visual Basic support for XNA and Windows Phone has now been added. VB resources include VB XNA documentation and VB WP7 code samples and starter kits and this post is intended to walk you through some of the steps in creating a simple XNA application for Windows Phone 7 using VB.
What is XNA?
Microsoft XNA is the development framework and tools used to create application for the Xbox 360 / Desktop PC and also the windows Phone 7. It provides access to build managed game type applications. The goal as with any framework is to avoid the developer having to write a lot of low-level repetitive boilerplate code and to expose different aspects of game production into a single system.
The XNA toolset is not new although it has undergone a number of revisions. Although during its history it has only supported C# as a development language for a number of technical reasons, although some users managed to create workarounds to allow limited support. However with the advent of the Windows Phone 7 and its use of the XNA framework additional efforts were made to ensure Visual Basic developers were not left out of the game and with the Mango Tools update finally VB users are provided with full support within XNA.
Why is it important?
Windows Phone 7 as a platform is extremely important for Microsoft. The mobile platform had a fundamental reset to provide a much improved user experience. There are two different ways of developing applications for the platform – Silverlight and XNA.
The Silverlight support was implement a while back with specific project templates for the phone but XNA had a few more challenges which have required a bit more work. Silverlight is ideal for most applications that are not timing critical and works well in an event driven model, this is most similar to the type of applications most existing VB developers have created for Windows or the Web. Events are triggered (such as user clicking a button), code is then executed. However for many games, timing is obviously critical and this requires a different platform designed specifically for this type of application. This is best shown with the following diagram which shows the concept of the "Game Loop" – with more details shown a little bit later.
This post is only intended to show you how to get started with XNA development using Visual Basic. To fully realize the potential would take many more pages – entire books devoted to the subject have been written.
How do I use it?
The first thing to do is install the Windows Phone Developer Tools 7.1 Beta’ (Mango Toolset) onto a machine with Visual Studio 2010 SP1 installed. VS2010 SP1 is critical for this to work and also will change how Silverlight application developed using VB are now compiled. This will also install updated Windows Phone 7 templates.
Be aware that XNA requires a higher-end video card to allow the emulator to run; most modern machines have cards capable of supporting DirectX10 and 11 which should be sufficient. This is important as Silverlight applications using the emulation don’t require the higher end video card.
Let’s create something using VB and XNA
The first thing you will notice is when you create a new project that there is now a folder containing marked "XNA Game Studio 4.0" as well as the existing "Silverlight for Windows Phone 7" folder.
So let’s start by selecting "Windows Phone 7 4.0 Game" to demonstrate XNA.
The first thing you will notice that this Project type actually created 2 projects, a game project and a content project.
This post is working through a simple game application using XNA in order to show VB support. Although when running using the emulator you will not see the true experience, the application will be using the accelerometer sensor inputs of the phone when deployed to a windows Phone 7 device.
So the example is going to have a "Yoyo" type object that is bouncing around the screen and controlled by user inputs. The application will use some simple physics to implement the spring type functionality. Although this is really only a rough approximation of the physics involved it does utilize some items to simulate friction, gravity.
One of the main differences between typical VB "Event driven" applications and XNA "Game Type" applications is that for XNA – timing is absolutely critical. The XNA type applications generally follow a code flow similar to the following. The main bulk of the code is contained within the “Game Loop” cycle of Update/Draw.
The frame rate for the game equates to the speed at which the game loop is running – obviously we want to make the application appear fluid which involves setting one high enough that the animation is going to look smooth. Too low a value and the animate will look jerky, too high a value and the application can get bogged down in calculations which are really not perceptible and the more unnecessary processing the application is doing, the shorter the battery life will be – so there are trade-offs that are made.
The good thing about this frame rate is that it can be controlled really easily and doesn’t really involve having to a lot of low level code. By default the frame rate normally used is roughly 30 frames per second. This is slightly quicker than what the average person can detect and therefore animation at this rate appears smooth.
This can be altered by modifying the line
TargetElapsed = Timespan.FromTicks(3333333)
Now this has been established we need to add a couple of resources used by the application. We will add these to our “Content” Project. We will add the following existing items to the Content project.
To add the images, simply add using "Add an Existing Item" context menu options from solution explorer and selecting the images files. These items are now part of the content project. Not all graphic image formats are supported so you will need to be careful to select one that is. This is an important point that not all formats are supported for all actions. This relates to graphics/sounds etc. but this information is easily found within XNA links.
Next let’s open up game.vb in the game project and add a few fields which we are going to use for the application. These will be used to hold items required for the game.
Private WithEvents graphics As GraphicsDeviceManager Private WithEvents spriteBatch As SpriteBatch '//stores accelerometer's acceleration Dim accelerometer As Microsoft.Devices.Sensors.Accelerometer Dim accelX As Single = 0 Dim accelY As Single = 0 Dim spring As Single = 0.2 Dim friction As Single = 0.75 Dim gravity As Single = 17 'Finger Coordinates Dim fingerPosition_X As Single = 0 Dim fingerPosition_Y As Single = 0 'Yoyo Object Dim YoYo As Texture2D Dim PieceOfString As Texture2D Dim YoYo_Position_X As Single = 50 Dim YoYo_Position_Y As Single = 50 Dim YoYo_VelocityX As Single = 0 Dim YoYo_VelocityY As Single = 0 'Text Position and Score Dim font1 As SpriteFont Dim font_Position As Vector2 Dim ScreenCenter As Vector2 Dim textsize As Vector2 Dim Text As String = "Yoyo Attack" & vbLf & "by Spotty"
This has defined some basic items for our game but based upon the general flow diagram show above we will need to put some lines in the “LoadContent” method to use the content which we have already added into the content project (ie. Yoyo.png, PieceOfString.bmp)
We need to Load the content for our game application. The content is stored in the Content Project but when creating a new game, an automatic project to project reference was created between the two. So in the Game project, the “LoadContent” method will have the following code added initialize our game objects with the correct content.
Protected Overrides Sub LoadContent() ' Create a new SpriteBatch, which can be used to draw textures. spriteBatch = New SpriteBatch(GraphicsDevice) YoYo = Content.Load(Of Texture2D)("Yoyo") PieceOfString = Content.Load(Of Texture2D)("PieceOfString") font1 = Content.Load(Of SpriteFont)("CourierNew") Dim viewport As Viewport = Me.GraphicsDevice.Viewport ScreenCenter = New Vector2(viewport.Width / 2, viewport.Height / 2) Text = "Yoyo Attack" & vbCrLf & "By Spotty" textsize = font1.MeasureString(Text) End Sub
As the phone is a specific type of device that runs XNA (From the project templates you will have noticed you can target windows, Xbox 360 and Windows Phone 7 using XNA), for the purposes of this application we want to use the accelerometer on the phone so we will need to add a reference to allow us to capture this sensor input.
This requires the addition of the Microsoft.Devices.Sensors.dll in the “Game” project which is a specific class library used for Sensor inputs on the phone. This should show up in the list of applicable references shown on the add references dialog.
So within the Game Project Initialize Method we will add the following
Protected Overrides Sub Initialize() font_Position = New Vector2(graphics.GraphicsDevice.Viewport.Width / 2 - 100, graphics.GraphicsDevice.Viewport.Height / 2) If accelerometer Is Nothing Then '// Instantiate the accelerometer sensor accelerometer = New Microsoft.Devices.Sensors.Accelerometer AddHandler accelerometer.ReadingChanged, AddressOf accelerometer_ReadingChanged accelerometer.Start() End If MyBase.Initialize() End Sub
At this point you will notice a compile error on the AddHandler line because we don’t have a method called “Accelerometer_ReadingChanged” so we can use the “Generate from usage (GFU)” feature. This will generate a method with the following signature.
Private Sub accelerometer_ReadingChanged(sender As Object, e As Microsoft.Devices.Sensors.AccelerometerReadingEventArgs) End Sub
Within this method we will add a few lines of code to set the acceleration fields with values which are used in the update method.
accelX = CType(e.X, Single) accelY = CType(e.Y, Single)
So we now have much of the basic parts of the application but we still have not drawn anything on the screen. We are now going to code up the two major methods used for the game loop (update and draw)
So the first method which we will code up is the Update method.
Protected Overrides Sub Update(ByVal gameTime As GameTime) ' Allows the game to exit If GamePad.GetState(PlayerIndex.One).Buttons.Back = ButtonState.Pressed Then Me.[Exit]() End If 'get the state of the touch panel Dim curTouches As TouchCollection = TouchPanel.GetState() ' Process touch locations For Each location As TouchLocation In curTouches Select Case location.State Case TouchLocationState.Pressed fingerPosition_X = location.Position.X fingerPosition_Y = location.Position.Y Exit Select Case TouchLocationState.Released 'Don't care about released state in this demo Exit Select Case TouchLocationState.Moved fingerPosition_X = location.Position.X fingerPosition_Y = location.Position.Y Exit Select End Select Next Dim ax As Single = (fingerPosition_X - YoYo_Position_X) * spring Dim ay As Single = (fingerPosition_Y - YoYo_Position_Y) * spring 'Calculate Yoyo velocity based upon Finger acceleration, gavity and friction coefficients YoYo_VelocityY += ay YoYo_VelocityY += gravity * accelY YoYo_VelocityY *= friction YoYo_VelocityX += ax YoYo_VelocityX += -gravity * accelX YoYo_VelocityX *= friction 'Calculate Yoyo Position based upon velocity YoYo_Position_X += YoYo_VelocityX YoYo_Position_Y += YoYo_VelocityY MyBase.Update(gameTime) End Sub
The calculation of the yoyo velocity may seem a little complicated but it is based upon 3 factors Finger acceleration which is set as a result of the event we have just hooked up and the gravity and friction coefficient fields which we have established in the field declarations.
The method is calculating the Yoyo position based upon these inputs as well as determining if the back button as been pressed on the phone.
So now we have calculated our new position for the Yoyo, we need to draw the item.
Protected Overrides Sub Draw(ByVal gameTime As GameTime) Dim start As New Vector2(fingerPosition_X, fingerPosition_Y) Dim [end] As New Vector2(YoYo_Position_X, YoYo_Position_Y) Dim rotation As Single = CSng(Math.Atan2([end].Y - start.Y, [end].X - start.X)) 'calculate the distance between the start and end points Dim distance As Integer = CInt(Vector2.Distance(start, [end])) GraphicsDevice.Clear(Color.Navy) spriteBatch.Begin() 'Yoyo Drawing If PieceOfString IsNot Nothing Then spriteBatch.Draw(PieceOfString, start, Nothing, Color.Gray, rotation, Vector2.Zero, _ New Vector2(distance, 1.0F), SpriteEffects.None, 0.0F) End If spriteBatch.Draw(YoYo, New Vector2(YoYo_Position_X - YoYo.Width / 2, YoYo_Position_Y - YoYo.Height / 2), Color.White) 'Position Titles On Screen font_Position.X = ScreenCenter.X font_Position.Y = ScreenCenter.Y spriteBatch.DrawString(font1, Text, font_Position, Color.Bisque, MathHelper.ToRadians(270), Nothing, 1, SpriteEffects.None, 0) spriteBatch.End() MyBase.Draw(gameTime) End Sub
And last but not least we need to correctly clean up our application when it closes which requires calling out Content dispose methods
Protected Overrides Sub UnloadContent() YoYo.Dispose() PieceOfString.Dispose() target.Dispose() End Sub
So now we can debug the application, this will start up an instance of the emulator. As we don’t have a physical device we can use the mouse to click on the emulator and flick the Yoyo around. It works like a spring and we have written the code to control this, but it’s not very game-like and we want to add some more game features.
So we will create a simple item which well to create a 2nd item that will bounce around the screen and act as a target. This object has less physical properties but will have simple X/Y fixed velocity to determine its movement characteristics but will introduce boundaries and collision detection. A critical point here is that adding this 2nd item should absolutely NOT result in the game slowing down noticeable.
So we will add a few more fields used to store important data of the Target object.
'Target Object Dim target As Texture2D Dim TargetX As Single = 10 Dim TargetY As Single = 10 Dim TargetVelocityX As Single = 7 Dim TargetVelocityY As Single = 10 Dim TargetRadius As Single = 0
Then add need to add some content for the target object. So we will add Target.png to the content project and add code to Game project “LoadContent” method to ensure that we initialize the Target object with an appropriate image from Content project.
target = Content.Load(Of Texture2D)("Target")
The next thing we need to do is control is the ability of the Target Object to detect when it has reached the edge of the screen and make it appear to bounce of the edge. The important thing here is that that the Target object has two important items associated with it (Vector2D to control direction of movement and Texture2D that determines the appearance of the object such as size, content etc.). Based upon the field initialized values we have some initial values but these will change when it hits the edge so we need to write a little code.
For the physics we will assume that this object has zero friction and a fixed velocity. This should make implementing it a little easier. We will need to add some logic in the Update method to ensure we are calculating its new position. This code will need to include some logic to determine if it has reached the edges of the screen and the rebound behavior. Think of a Pool table and the ball bouncing off the edges.
So I’ll add an Enumeration for Direction
Public Enum Direction Up Down Left Right End Enum
And in add a couple more fields
Dim x_Direction As Direction = Direction.Down Dim y_Direction As Direction = Direction.Left
This will be used to determine the direction of travel in the collision detect logic. We can then create a simple method to control the Edge bounce behavior of the target object.
Private Sub DetectTargetEdgeBounce() If TargetX < 0 Then 'If hit Top Edge then x_Direction = Direction.Down ElseIf TargetX > GraphicsDevice.Viewport.Width Then 'Else IF Hit Bottom Edge then x_Direction = Direction.Up End If If TargetY < 0 Then 'If hit Top Edge then y_Direction = Direction.Right ElseIf TargetY >= GraphicsDevice.Viewport.Height Then 'Else IF Hit Bottom Edge then y_Direction = Direction.Left End If 'Determine new coordinatied based upon direction If x_Direction = Direction.Down Then TargetX = TargetX + TargetVelocityX ElseIf x_Direction = Direction.Up Then TargetX = TargetX - TargetVelocityX End If If y_Direction = Direction.Right Then TargetY = TargetY + TargetVelocityY ElseIf y_Direction = Direction.Left Then TargetY = TargetY - TargetVelocityY End If End Sub
The logic I have implemented is easy as it treats the X border detection and Y border detection as separate conditions and reverses the direction of travel when a collision is detected. There are many other ways of achieving the same logic but this is easy to understand.
We now need to make a couple more additions to the Update and draw methods. The following line should be added to the “Update” method calculate the new coordinate of the object based upon current coordinate, direction of travel, Velocity and screen size.
DetectTargetEdgeBounce() 'Movement of Target
Now we have determined the new position of the target object by called the “DetectTargetEdgeBounce” method, we need to ensure we draw it at this calculated position. This is as simple as adding the following lines to the Draw Method
spriteBatch.Draw(target, New Vector2(TargetX - Target.Width / 2, TargetY - Target.Height / 2), Color.Green)
So we now have two objects on the application – one is controlled by the user finger and exhibits some physical properties such as acceleration/gravity/Friction and the other is a much simpler one which appears to have no friction and fixed velocity that is bouncing off the edges of the screen.
We now have to implement a bit more logic to make it more game-like. This would involve some collision detection logic. We have a few logic items we want implement.
1. When Yoyo and target collide and the yoyo has velocity we score points.
2. The longer the collision duration the more points we score
3. We cannot touch the target – otherwise we will lose all points.
4. As we score more points the target becomes quicker.
As a result of this simple logic conditions we will change colors/Images, update score and play sounds. All these are elements of a simple game.
So let’s start with implementing some Collision Detection/Scoring code, as this is would appear to be the core component here. Each item has a single point representing it but obviously the image is bigger than that which is why we need to use both the Vector2d class for position and the Texture2d class for Size. As this seems to be something that we would want to keep together when referring to an game world “Object” , we can create a Type to represent this.
Structure WorldObject Sub New(Pos As Vector2, Texture As Texture2D) _Position = Pos _Texture = Texture End Sub Public Property _Texture As Texture2D Public Property _Position As Vector2 End Structure
We will also want to create a method to detect if these two items have collided based upon their positions and sizes. The following is a simple method which will determine a collision between two “WorldObject” Items, returning true if they have collided.
Public Function IsCollisonDetected(Item1 As WorldObject, Item2 As WorldObject) As Boolean 'Determine Bounding Rectangle for Item1 Dim Object_Item1 As New Rectangle(CInt(Item1._Position.X), CInt(Item1._Position.Y), Item1._Texture.Width, Item1._Texture.Height) Dim Object_Item2 As New Rectangle(CInt(Item2._Position.X), CInt(Item2._Position.Y), Item2._Texture.Width, Item2._Texture.Height) If Object_Item1.Intersects(Object_Item2) Then Return True Else Return False End If End Function
Now we have to add a little more code to determine the call this and determine some actions when a collision occurs. The first is to add a score field, which we will initialize with a zero value.
Dim Score As Integer = 0
Then in the “Update” method we will add the following code to call the IsCollisonDetected method for the various objects and determine if collisions have occurred between the Yoyo and Target objects and the Finger and Target objects.
So following code this should address the game logic items 1,2 ,3 and 4 in our list of game logic items.
Dim YoyoObject As New WorldObject(New Vector2(YoYo_Position_X, YoYo_Position_Y), YoYo) Dim TargetObject As New WorldObject(New Vector2(TargetX, TargetY), YoYo) Dim FingerObject As New WorldObject(New Vector2(fingerPosition_X, fingerPosition_Y), YoYo) If IsCollisonDetected(FingerObject, YoyoObject) Then Score = 0 Else 'Collision Detects If IsCollisonDetected(TargetObject, YoyoObject) Then If CInt(YoYo_VelocityX) <> 0 OrElse CInt(YoYo_VelocityX) <> 0 Then Score = Score + 1 CollisionSound.Play(1, 0, 0) End If End If Text = "YoYo Attack" & vbLf & "by Spotty" & vbCrLf & "Score:" & Score.ToString & vbCrLf & "Time Remaining:" & CalculateTimeRemaining() UpdateTargetSpeed(Score)
We don’t have an UpdateTargetSpeed method so will use the GFU to generate a method and adding the following code within the method
Sub UpdateTargetspeed(Score As Integer) 'Update Speed depending upon score Select Case Score Case Is < 10 TargetVelocityX = 10 TargetVelocityY = 10 Case 11 To 20 TargetVelocityX = 12 TargetVelocityY = 12 Case 21 To 30 TargetVelocityX = 14 TargetVelocityY = 14 Case 31 To 50 TargetVelocityX = 15 TargetVelocityY = 15 Case Is > 51 TargetVelocityX = 20 TargetVelocityY = 20 Case Else TargetVelocityX = 10 TargetVelocityY = 10 End Select End Sub
So now we have a basic game – with some scoring, collision detection and functionality but we want to add a few more elements such as sounds. So let’s add a background sounds track and some collision detect sounds.
This is simply a matter of adding the audio content to the Content Project. In our example we can add the following three wav files to our Content Project – ( BackGroundMusic.wav, Tada.wav and Ding.wav), just as we did for our graphics used in the application. For our sounds we will have a background music track and then add some sounds into the “Update” method when collisions are detected.
We then simply need to add the following code in the “LoadContent” and “Update “Methods.
The following lines need to be added into the appropriate methods
Dim BgSound As SoundEffect Dim BGInstance As SoundEffectInstance Dim CollisionSound As SoundEffect Dim TargetTouchSound As SoundEffect
CollisionSound = Content.Load(Of SoundEffect)("Tada") TargetTouchSound = Content.Load(Of SoundEffect)("Ding") BgSound = Content.Load(Of SoundEffect)("BackgroundMusic") BGInstance = BgSound.CreateInstance BGInstance.IsLooped = True BGInstance.Volume = 0.5 'half Volume BGInstance.Play()
“Update” Method (Full Method Shown with additional lines enlarged)
Protected Overrides Sub Update(ByVal gameTime As GameTime) ' Allows the game to exit If GamePad.GetState(PlayerIndex.One).Buttons.Back = ButtonState.Pressed Then Me.[Exit]() End If 'get the state of the touch panel Dim curTouches As TouchCollection = TouchPanel.GetState() ' Process touch locations For Each location As TouchLocation In curTouches Select Case location.State Case TouchLocationState.Pressed fingerPosition_X = location.Position.X fingerPosition_Y = location.Position.Y Exit Select Case TouchLocationState.Released 'Don't care about released state in this demo Exit Select Case TouchLocationState.Moved fingerPosition_X = location.Position.X fingerPosition_Y = location.Position.Y Exit Select End Select Next Dim ax As Single = (fingerPosition_X - YoYo_Position_X) * spring Dim ay As Single = (fingerPosition_Y - YoYo_Position_Y) * spring 'Calculate Yoyo velocity based upon Finger acceleration, gavity and friction coefficients YoYo_VelocityY += ay YoYo_VelocityY += gravity * accelY YoYo_VelocityY *= friction YoYo_VelocityX += ax YoYo_VelocityX += -gravity * accelX YoYo_VelocityX *= friction 'Calculate Yoyo Position based upon velocity YoYo_Position_X += YoYo_VelocityX YoYo_Position_Y += YoYo_VelocityY DetectTargetEdgeBounce() 'Movement of Target 'Detect Collisions Dim YoyoObject As New WorldObject(New Vector2(YoYo_Position_X, YoYo_Position_Y), YoYo) Dim TargetObject As New WorldObject(New Vector2(TargetX, TargetY), YoYo) Dim FingerObject As New WorldObject(New Vector2(fingerPosition_X, fingerPosition_Y), YoYo) If IsCollisonDetected(FingerObject, YoyoObject) Then TargetTouchSound.Play(1, 0, 0) Score = 0 Else If IsCollisonDetected(TargetObject, YoyoObject) Then If CInt(YoYo_VelocityX) <> 0 OrElse CInt(YoYo_VelocityX) <> 0 Then Score = Score + 1 CollisionSound.Play(1, 0, 0) End If End If Text = "YoYo Attack" & vbLf & "by Spotty" & vbCrLf & "Score:" & Score.ToString & vbCrLf & "Time Remaining:" & CalculateTimeRemaining() UpdateTargetspeed(Score) MyBase.Update(gameTime) End Sub
What’s not there in XNA / Phone applications?
We now have a basic game, with sound working on the phone using XNA. For those developers who may have tried experimenting a little with the basic code and using some of the other VB functions, you may have noticed that some expected items are found and others not. XNA uses a feature of the VB Compiler known as VB Core which embeds a reduced version of the Visual Basic runtime into the generated assembly. As this is a new platform for VB, many of these older legacy runtime functions contained in the desktop version of Microsoft.VisualBasic.dll do not exist in the VBCore runtime. Examples of this include the left, mid, right functions. This is intentional and provides VB support or the platform without unnecessarily bloating the assembly size with duplicate of existing framework functionality. So many of the types/functions etc. contained with the desktop versions Microsoft.VisualBasic.dll will not be present.
However, any as with any project types that utilizes the VB Core functionality, if you absolutely cannot live without some missing functionality you can add it simply by creating a method with the same name. Tools such as Reflector enable you to dissemble the code in Microsoft.VisualBasic.dll and see a source code equivalent for that function. Some functionality is not supported on new platforms using VBCore which also may be why they are not implemented – (a good example being Late Binding).
All phone projects now utilize the VB Core functionality to embed the required VB runtime functionality in your assemblies. This means that when you build your application (whether Silverlight or XNA) that there will no longer be a separate Microsoft.VisualBasic.dll that needs to be deployed as was the case with Silverlight Phone applications developed prior to the Mango Tools Update. To see this you can use a tool like ILDASM or Reflector to look at the assembly and you will now notice that the assembly now contains a Microsoft.VisualBasic namespace containing the reduced runtime.
To upgrade your existing windows phone 7 Silverlight projects to utilize this new feature, add the following line project file to
Also remove any reference to Microsoft.VisualBasic.dll from the .VBProj file.
XNA now fully supports Visual Basic on all platforms (Xbox360/Windows and Windows Phone 7). After completing this walkthrough VB developers should have an idea on how to write XNA applications. Although the model for developing game applications is different from that used by most VB Developers it is easy to get started. With the platform already well developed there are a huge number of resources available which VB Developers can use. VB developers can join the party and start creating to great applications using XNA.
Useful Web Links
· Windows Phone SDK Beta
- Download Center: http://go.microsoft.com/?linkid=9772716
- Go live license– http://go.microsoft.com/?linkid=9772717
· WPDT 7.1 Documentation
- Windows Phone Developer Tools 7.1 Release Notes: http://go.microsoft.com/fwlink/?LinkId=215231
- What’s New in Windows Phone Developer Tools: http://go.microsoft.com/fwlink/?LinkID=190409
- Code Samples for Windows Phone: http://go.microsoft.com/fwlink/?LinkId=219604
- · App Hub
Download page: http://create.msdn.com/en-us/resources/downloads
Getting Started: http://create.msdn.com/en-us/home/getting_started