Unity Gaming: Shooting/Aiming (part3) – Oculus

Last time on Unity Gaming – Getting a hold of learning how to aim and shoot…lol.

We created a scene where we aimed by getting the orientation of the camera and where we were looking. But then, when we tried using this same technique with the Oculus it didn’t work! Now our heroes are stuck. How will they get around their null reference exception and get their shooting ability working!?!?!

Well I mentioned it before.

“The other [method] draws a line from an object, like a gun, or hand out to a target.”

So let’s continue on!

Vector/Object Raycasting

There is no main camera in the scene. So now we need to implement the second common way of aiming and shooting. Which is from an object. Because we can no longer rely on the camera we can create a ray from an object right in front of our character to an angle created by the mouse that will still aim straight to where we are looking. =)

Create an empty GameObject and call it ShotSpawner (this object will act as the origin of our raycast). Child it to the OVRCameraRig.

Note: Remeber this can work without the oculus as well. So you can do this for shooting a gun. Just put the ShotSpawner on the tip of the gun!

ShotSpawnerOVR

In my scene I have moved the TargetCube to (0, 0, 15) to move it out of the way, but still give me a reference. And instead of drawing a Line in debugging I’m going to get the tag of whatever my raycast hits in debugging.

So let’s write the script that will do this.

In ShotSpawner add a new C# script component and name it OVRShoot. Unlike the other scripts we will be saving the gameobject our ray intersects; so we need a RaycastHit object, and a GameObject.

    RaycastHit hit;
    GameObject hitObject;

The Update method will then look like this:

    void Update()
    {
        if (Physics.Raycast(transform.position, transform.forward, out hit, 10))
        {
            hitObject = hit.collider.gameObject;
            Debug.Log(hitObject.tag);
        }
    } 

So whatever the raycast hits will be stored in the hit parameter of the method if it is true. We can then get the hit’s object, IF it has a collider! So remember if you want to be able to interact with an object it’s top most parent object needs to have a collider we can interact with! (<<– this is super important, and causes a lot of people grief because the raycast will hit a child objects collider instead of the parent’s and then the code breaks. So avoid that grief and remember this tid-bit, TRUST ME! Avoid common mistakes and developing will go a lot more smoothly.)

Before we run the Script now we need to add tags to the cubes in the scene. I’ve added the Enemy tag to them in the Tag drop down in the Inspector.

OculusRaycastWorking

And there you have it! It’s printing the Enemy Tag! So now you can use these methods in your own code. I’ll eventually show you how to use it in the Infinite Runner because I use a slightly different method there becuase of some assets I use.

Happy Coding

-TheNappingKat

Unity Gaming: Shooting/Aiming (part 2) – Oculus

So there are two main types of aiming. One, uses the camera’s view to shoot a ray directly out in front of you. This is great if you want to look at things to target them. The other draws a line from an object, like a gun, or hand out to a target.

Let’s do the camera one first.

Camera Raycasting

For this I am using the same scene I made in part 1 but I’ve added some cubes to aim at that are in the air to test out my targeting.

So I’m going to create a cube called TargetObject and attach it to my FirstPersonCamera under a gameobject. Then I’ll change the position to (0, 0, 10), and set it’s box collider to Is Trigger so it doesn’t interfere with my characters movement. I do this so I can get a good idea of where my ray is going to pointing. In Unity you can’t see the raycast that emitted unless you draw it with a line render or call debug.drawline (but that only draws it in the scene view). If I were to play the game now. I should see a cube 10 units away from where I’m looking at all times.

TargetObject

 

Great so now let’s write the raycast like before. Create a new C# script called RaycastShoot

In this update add the following lines:

void Update () {
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    RaycastHit hit;
    if (Physics.Raycast(ray, out hit, 100))
        Debug.DrawLine(ray.origin, hit.point);
    }

What the script is doing is creating a Ray where the orgin is the main camera and the direction is related to the mousePosition and the angle between it and the camera. Then if the raycast hits anything draw a line. In our scene the line should always be drawn since our target object is in front of our character.

DebugRaycast

It’s difficult to see the line, but you can tell in the pic it’s slightly darker than the others.

Now let’s try with the Oculus! You’ll see why we have to change our methods of aiming in a second.

Oculus and Camera Aiming

If you haven’t set up your environment to integrate oculus don’t worry I’ve posted about it before, here, Oculus setup! Again you don’t need the hardware to develop for VR.

First let’s disable our main Character by clicking on the checkbox in the upper left hand corner in the inspector; in disabled mode there should no longer be a check and the object should be greyed out in the hierarchy.

Cool now click and drag in the Oculus Player Controller.

OVRStartScene

Then create another Target cube so we can have a reference as to where we are looking. I moved it to under the OVRCamerRig to (0,0,5) position.

Next we need to add the Raycast script like before. I’ve added it to the OVRCameraRig.

OVRTargetCube

Now when we run it the game still plays but we don’t see the line in the scene view like before. This is because we get a Null ReferenceException from the RaycastShoot Script.

OculusError

The error above is referring to this line of code:

void Update () {
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); //this one
    RaycastHit hit;
    if (Physics.Raycast(ray, out hit, 100))
        Debug.DrawLine(ray.origin, hit.point);
    }

There is no main camera in the scene. So now we need to implement the second common way of aiming and shooting; which is from an object. Because we can no longer rely on the camera, we must create a ray from an object right in front of our character, to an angle created by the mouse. And since the mouse dictates the orientation of the head, we will still aim straight to where we are looking. =)

Correct Oculus shooting and the second type of shooting will be in part 3…

Happy Coding!

-TheNappingKat

Unity Gaming: Shooting (part 1)

Okay so this is a little jump ahead of the Unity Gaming Infinite Runner Series. I’ve gotten a lot of questions about this so I’m writing about it now. Because it’s out of order, the examples are in a blank scene, not the Infinite Runner main scene.

Okay, so, most likely when you are shooting something it’s from either right from of the center of the screen or it’s, for the most part, originating from another objet like a hand or gun. This gets kinda complicated when all of a sudden you are using two cameras to judge the “center” of what you are looking at; like when using an oculus…

But no fear learning the general method of shooting isn’t too bad; and then adding the oculus bit will be easy to understand.

Raycasting

So when you aim for or align something in real life do you draw an invisible line from where you are to the thing you are trying to hit? Yes, Great! If not well, cool, but that’s what Raycasting is.
There are 5 possible parameters for the raycasting method in Unity.

  1. Vector3 origin – which is the position in 3d space where you want the ray to start
  2. Vector3 direction – which is the direction you want the ray to point, the first to parameters make a Ray.
  3. *RaycastHit hitInfo – get whatever the Ray hits first and store it in this parameter
  4. *Float maxDistance – this is the magnitude of the Ray aka how far out you want the ray to point
  5. *Int layerMask – what the Ray can Hit

* Indicates that these parameters are optional

There are also two main ways the Raycast method is written.

  • Raycast(Vector3 origin, Vector3 direction, float maxDistance, int layerMask)
  • Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float maxDistance, int layerMask)

In Unity Raycast method return a Boolean value. True, if the ray hit something, and False if nothing was hit. I should also mention that in Unity Raycasts do not detect colliders for which the raycast is inside. However if you are creating an animation or moving, you should keep the Raycast method in a FixedUpdate method so that the physics library can update the data structures before the Raycast hits a collider at its new position.

Aiming

Now there are 2 types of aiming. One is simply shooting in the direction that the player is facing and one is shooting in the direction that the player is looking.
Let’s do the easy one first – aiming where the player is facing aka not aiming just shooting.
Cool so in my scene I have the regular First Person Character from the Unity Sample Assets package and created some ground by scaling a cube to have dimensions (10, 1, 30).

StartScene

Now lets create a shoot script called simpleShoot.

CreateSimpleScript

In the Update function we want to shoot a new sphere every time I click and shoot it in the “forward direction”. So let’s add the following lines.

void Update () {
    if (Input.GetButtonDown("Fire1"))
        {
            GameObject clonedBullet; 
            clonedBullet = Instantiate(GameObject.CreatePrimitive(PrimitiveType.Sphere),
                transform.position, transform.rotation) as GameObject;
            clonedBullet.AddComponent<Rigidbody>();
            clonedBullet.GetComponent<Rigidbody>().AddForce(clonedBullet.transform.forward * 2000);
        }

    }

Cool and if you check it out I’m shooting and the bullets go in the forward direction of the transform of my character! YAY!

SimpleShootScene

Mouse Aim

Okay but that doesn’t shoot the ball in the upward direction when I’m looking up, you say to me. Yes I know that’s the next thing we are going to do. =) …in part two!

Happy Coding! Part 2 coming soon =D

-TheNappingKat

Oculus Headset Unity Error: No HMD Detected

Hi All,

I solved the NO HMD DETECTED, Tracker Connected error you get with trying to do extended screen when using the headset for the Unity Editor.

NoHMD

Well I got it working, not necessarily solved.

Specs:

  • Lenovo X1 Carbon
  • Intel Core i7 – 3667U CPU 2.0ghz
  • 8gb ram
  • Windows 8.1
  • 64-bit
  • Intel HD Graphics 4000
  • Oculus DK2
  • SDK 5.0.1

To start I detached my oculus from the computer. Reattched the oculus, made sure it was working in the normal Direct HMD Access mode. It was.

1) Then I hit “Windows + P” and made sure my Projection setting was on extended.

2) Then I switched the mode to Extended in the Utility

3)  Then on the desktop I right clicked and hit Screen Resolution.

4) I selected the second screen and hit “Detect”, a window came up with Another display not detected.

5) I made the Oculus screen primary and then switched back to the main computer being primary and it worked. The screen now appeared in the Oculus but the orientation was off. so I just adjusted it in the Screen resolution window.

DisplaySettings

 

Now the Oculus Configuration Utility looks like this, but it works.

AttachedNoTracker

 

 

In the Unity Editor I can move the game tab to the Headset Screen and maximize it, I can still see the awkward black rim around the screen but it’s better than nothing. Hopefully the Oculus team can fix this soon.

 

OculusExtendedScreenFull

 

Hope this helps, Happy Coding!

 

-TheNappingKat

Hide and Seek: Sphero vs. Drone (Part 1)

SignalR and Backend Coding

Hey Everyone. So the backend part of games tends to be some of the most difficult code to write in the project. I’m also not of fan of backend Server code (but that’s just me). In this project I pushed out of my comfort zone to step more into the hardware back end world.

Really this tutorial is about Signal R in general. That way you can follow along and make a hide and seek game, or create your own game based on these principles and fundamentals.

Getting Started

So for those of you that haven’t used Visual Studio, that is the IDE I’m programming with in this tutorial. You can get for FREE here: http://www.visualstudio.com/ 

  1. Make a new empty project

Signal R – Backend

Create a new Project in web

 

Then, in the New ASP.NET Project window select MVC and Change Authentication to No Authentication.  Click Create Project.  Now you need to get the nugget package from the Package Manager.

Tools> Nuget Package Manager> Package Manager Console

Then type:

PM> install-package Microsoft.AspNet.SignalR

If you expand your Scripts folder you will see that the libraries for SignalR have been added.

 

Now Right-Click the Hubs folder, and click Add | New Item, select the Visual C# | Web | SignalR node in the Installed pane, select SignalR Hub Class (v2) from the options. And Create a new hub called GameHub.cs.

This Hub will be the host of your server and game logic. It will also be what all clients send their messages to.

 

Under our project create a new class called Startup.cs, by right clicking the project Add > Class.

 

 

Add the following code:

using Microsoft.Owin;

using Owin;

 

[assembly: OwinStartupAttribute(typeof(SRHS2backend.Startup))]

namespace SRHS2backend

{

public partial class Startup

{

public void Configuration(IAppBuilder app)

{

app.MapSignalR();

}

}

}

 

Now go to HomeController.cs in your Controllers folder.

Add the following code snippet:

public ActionResult Game()

{

return View();

}

 

Now this next part is mostly for seeing which messages are getting to the server and displaying them for the developers to see. We didn’t implement it in this code but there are sources online that show you the javascript and jQuery needed to print to the new view we just created her http://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalr-and-mvc

 

Now, your gamehub.cs class is derived from SignalR’s Hub class. This allows you to access all the currently connected clients and the methods within those clients.

 

To understand it better, the CreateGame(User user, Game g) method would be called in the client code, and defined in GameHub. While the Clients.All.gameGreate(g, sm) is defined in the client side of the code.

The User, Game, and ServerMessage are classes that I created for this specific game. They hold information that is required by each User, Game, and ServerMessage. While AllGamesList and AvailableGames, are Lists that I create in GameHUb so the server can reference all the active and passive games currently in progress.

 

Signal R – Front End

Now we will make the front end that links with Signal R.

First we want to create a new blank Universal App.

 

 

Next we install the SignalR Client NuGet package for both the phone and the windows 8.1 project.

 

Now the way that the client interacts with the server code that was written is by connecting with the hub and sending messages through that hub.

For the SignalR portion of the client code create a new folder call SignalRCommunication, that contains the following classes: ISignalRHubs.cs, SignalREventArgs.cs, SignalRMessagingContainers.cs, and SignalRMessagingHub.cs.

The ISignalRHub is the interface for your SignalRMessagingHub.

 

And the SingnalREventArgs.cs acts as the interface allowing all parts of the project to access the messaging events.

The SignalRMessagingHub is where the connection is created between the server hub and client is initiated.

Now to connect with the Server Hub we need the following code:

#region “Implementation”

 

public async virtual void UserLogin(User tabletChatClient)

{

// Fire up SignalR Connection & join chatroom.

try

{

await gameConnection.Start();

 

if (gameConnection.State == Microsoft.AspNet.SignalR.Client.ConnectionState.Connected)

{

await SignalRGameHub.Invoke(“Login”, tabletChatClient);

}

}

catch (Exception ex)

{

 

// Do some error handling. Could not connect to Sever Error.

Debug.WriteLine(“Error: “+ ex.Message);

}

I put mine inside of the first User interaction with the server, so in this case when the User logs in.

For the Phone application if using the emulator you will need to use long polling since the phone emulator uses the PC’s identification number and a lot more work has to go into formatting your computer to run it.

This is the code you will need

#if WINDOWS_PHONE_APP

connection.Start(new LongPollingTransport());

#else

connection.Start();

#endif

 

Now we need to write code that will listen to events on the SignalR Server and wire them up appropriately

Calling the .On method is how our proxy hub listens to any messages the server passes to the clients.

Lets make this easier to understand by going through .On and explaining what each part is doing.

SignalRGameHub.On<Game, ServerMessage>(“gameCreated”, (g, sm) =>

{

SignalREventArgs gArgs = new SignalREventArgs();

gArgs.CustomGameObject = g;

gArgs.CustomServerMessage = sm;

// Raise custom event & let it bubble up.

SignalRServerNotification(this, gArgs);

});

The .On method can take in as many parameters as needed depending on which server call it’s defining On<x,y,z>.

Before you saw the server gamehub call Clients.All.gameCreated(); in the client code the quotes in SignalRGameHub.On method refer to which ever method we are listening to and then dictates what the client code should do based on the delegate following the On method.

The (g, sm) are the parameters that we defined earlier <x,y> in this case <Game, ServerMessage>. They are a part of a delegate that will create the SignalREventArgs, to parse out a gameObject and a ServerMessage. Then it raises a SignalRServerNotification(this, gArgs) that will trigger an event. You still need to write that event in other parts of your code.

We now need to write the method for the SignalRServerNotification(this, gArgs)

#region “Methods”

 

public virtual void OnSignalRServerNotificationReceived(SignalREventArgs e)

{

if (SignalRServerNotification != null)

{

SignalRServerNotification(this, e);

}

}

 

#endregion

 

 

 

Cool now on to defining calls made by the client that will be sent to the Server.

Make sure to define all the methods that will be sending information to the server. These async virtual methods will be called by the ISignalRHub. The quoted part “UpdateUser”, “CreateGame” and “JoinGame” refer to the methods on the server side GameHub, if the names are not exactly correct the server methods won’t invoke.

 

SingnalRMesagingContainers refers to the objects that you want to send through JSON to the server to manipulate. Meaning you would define your object classes within this .cs file. However if you already defined your models, in a models(or other name) folder, that will work too, in fact it’s preferred.

Referencing Gamehub

In order for your Signal R Hub to be accessed by all parts/pages of your project you will need to modify the App.xaml.cs in Shared.

public static new App Current

{

get { return Application.Current as App; }

}

Then inside the OnLaunched(LaunchActivatedEventArgs e) method add

App.Current.SignalRHub = new SignalRMessagingHub();

 

 

Inportant! If you are going to be passing objects through SignalR both projects need to have the exact same code for the objects.

Now when calling/listening to the SignalR hub from different pages of your app easy now that we have everything set up.

CALLING

LISTENING

Inorder to approipately handle the triggered SignalRServerNotifaction we need to add SignalRServerNorification for that page by referencing the App.Current.SignalRHub.SignalRServerNotification

When implementing the SignalRHub_SignalRServerNotification be sure to appropriately handle the dispatcher so the page can still be responsive when events are triggered.

 

In my code I use the CustomSererMessage to find which state the server is on versus the game. You can implement changing and checking game state however you think best suits your game.

 

Publishing your Server code

Eventually you want to publish your code to an azure website so anyone who downloads the application can connect to the server.

Use the steps in this tutorial to do so: http://www.asp.net/signalr/overview/deployment/using-signalr-with-azure-web-sites

Sphero

Okay so we finally have the backend set up. Now it’s time to implement more of the front end. Depending on your game you might want to change some of the XAML and front end to suit your purposes but the connection and control of the Sphero will remain the same.

First thing is to add the Sphero SDK that you downloaded to your project references.

https://github.com/SoatExperts/sphero-sdk

Connecting to Sphero

Second is to modify the App.xaml.cs so all pages in the project can remain connected to the same Sphero.

 

Now go into the page that you want to initiate connection with your sphero. For Hide and Seek I put it in the lobbyPage.xaml.cs since I wanted to make sure users were connected before they started the game. One thing to note about the DiscoverSpheros method; it will only return a list of Spheros that are on and in Bluetooth connection state (blinking red and blue).

private async void DiscoverSpheros()

{

try

{

// Discover paired Spheros

List<SpheroInformation> spheroInformations = new List<SpheroInformation>(await SpheroConnectionProvider.DiscoverSpheros());

 

if (spheroInformations != null && spheroInformations.Count > 0)

{

// Populate list with Discovered Spheros

SpherosDiscovered.ItemsSource = spheroInformations;

}

else

{

// No sphero Paired

MessageDialog dialogNSP = new MessageDialog(“No sphero Paired”);

await dialogNSP.ShowAsync();

}

 

}

catch (NoSpheroFoundException)

{

MessageDialog dialogNSF = new MessageDialog(“No sphero Found”);

dialogNSF.ShowAsync();

}

catch (BluetoothDeactivatedException)

{

// Bluetooth deactivated

MessageDialog dialogBD = new MessageDialog(“Bluetooth deactivated”);

dialogBD.ShowAsync();

}

}

After you discover the Spheros you then need to connect to one.

 

Controlling Sphero

With your device now connected to the Sphero that you choose, it’s time to implement the controls. Go to the page that you want the controls to appear and open the page’s .xaml file. In this case it was my GamePlayPage.xaml.

Then add the following to the <Page> tag properties:  xmlns:Controls=”using:Sphero.Controls”

Now depending on what else you want to put on the page the placement of this next code block will differ, but the content is still the same.

<Controls:Joystick x:Name=”spheroJoystick” HorizontalAlignment=”Left” Margin=”30,0,0,30″ Grid.Row=”1″ VerticalAlignment=”Bottom” Calibrating=”spheroJoystick_Calibrating” CalibrationReleased=”SpheroJoystick_CalibrationReleased” Moving=”SpheroJoystick_Moving” Released=”SpheroJoystick_Released” PointerReleased=”SpheroJoystick_PointerReleased”/>

The important properties of the Controls:Joystick input are Calibrating, CalibrationReleased, Moving, Released, and PointerReleased. These can be added directly in the XAML or can be added in the Events tab of the Properties Window in Visual Studio.

 

Almost done, with Sphero. In order for the code in XAML to actually do anything, we need to make sure that the events are implemented and make sure the connection is still active.

private SpheroDevice _spheroDevice;

We check the connection and start the Joystick in the page’s initialize method.

 

Since we saved the connection in the App.CurrentConnection we can reference even if we navigate to a different page after the initial connection.

 

And that’s it! You can now get more information from the Sphero if you want to, and track more data. Look in the API for on how to do more with your Sphero.

 

 

 

 

 

 

Drone

So some quick background on the Drone. ARDrones produce their own wifi that your device will need to connect to. Normally not a problem. But when your app needs to also talk to a Server consistently it provides a problem at we were only able to fix by connecting a PC to a hardline and the drones wifi simultaneously.

Getting Started

Create a new Blank windows 8.1 app. Download the SDK off git. Unzip the package and copy the reference libraries you need into your project Folder. Then go to your Reference folder in your project and reference the new files that you just moved. Do this in order to keep all the references together so when you share the solution nothing becomes dereferenced.

Integrating Front end

Go to the page’s xaml page and add to the <Page properties/>

xmlns:input=”using:ARDrone2Client.Windows.Input”

 

The main thing that needs to be in the UI is the field of view from the drone’s camera. The allure of drones is being able to control a new perspective that we normally can’t see as a human.  The camera output is also a major way that the user can control the drone when they lose direct line of sight.

To add this camera output to the screen you need to insert a MediaElement into your page. I like the element to take up almost the entire screen and then over lay the Joystick, Takeoff, Landing, and other command buttons.

 

The next step is to add the JoystickControl from the Drone ToolBox and the corresponding XAML Controls.

 

Be sure to name them differently. I suggest naming them after what they control. “YawGazJostick” and “RollPitchJoystick”.

 

 

<Grid x:Name=”JoystickGrid”

Grid.Row=”1″>

<input:JoystickControl x:Name=”YawGazJoystick”

BorderElipseColor=”Red”

StickColor=”Black”

Margin=”0,0,80,80″

HorizontalAlignment=”Right”

VerticalAlignment=”Bottom”

Height=”200″

Width=”200″ />

<input:JoystickControl x:Name=”RollPitchJoystick”

BorderElipseColor=”Green”

StickColor=”Black”

Margin=”80,0,0,80″

HorizontalAlignment=”Left”

VerticalAlignment=”Bottom”

Height=”200″

Width=”200″ />

</Grid>

 

It’s also good to have a Take Off button as well as an Emergency Button. There are several other capabilities of the Drone that you can add to your project however we won’t be using them. Your button doesn’t need to look like this it can be just a normal button.

 

 

<Button x:Name=”TakeOffLandButton”

Grid.Row=”1″

VerticalAlignment=”Bottom”

HorizontalAlignment=”Center”

IsEnabled=”False”

BorderThickness=”0″

Click=”TakeOffLandButton_Click”

Style=”{StaticResource ImageButtonStyle}”>

<!–<Image x:Name=”TakeOffLandImage”

Source=”/Assets/Parrot/btn_take_off_normal.png”

Stretch=”None” />–>

<Grid>

<Grid.ColumnDefinitions>

<ColumnDefinition Width=”50″ />

<ColumnDefinition Width=”*” />

<ColumnDefinition Width=”50″ />

</Grid.ColumnDefinitions>

<Polygon Grid.Column=”0″

Fill=”{StaticResource Green}”

StrokeThickness=”0″

Points=”0,62 50,0 50,62 0,62″ />

<Rectangle Grid.Column=”1″

Fill=”{StaticResource Green}”

HorizontalAlignment=”Stretch”

VerticalAlignment=”Stretch”

StrokeThickness=”0″ />

<Rectangle Fill=”{StaticResource ParrotBrush}”

Grid.Column=”1″

Height=”3″

VerticalAlignment=”Top” />

<Polygon  Grid.Column=”2″

Fill=”{StaticResource Green}”

StrokeThickness=”0″

Points=”0,0 50,62 0,62 0,0″ />

<Line Grid.Column=”0″

X1=”50″

Y1=”0″

X2=”1″

Y2=”60″

Stroke=”{StaticResource ParrotBrush}”

StrokeThickness=”3″ />

<Line Grid.Column=”2″

X1=”0″

Y1=”0″

X2=”50″

Y2=”60″

Stroke=”{StaticResource ParrotBrush}”

StrokeThickness=”3″ />

<TextBlock x:Name=”TakeOffLandingTextBlock”

Grid.Column=”1″

TextAlignment=”Center”

VerticalAlignment=”Center”

Foreground=”White”

FontSize=”30″

Padding=”50,0″>TAKE OFF</TextBlock>

</Grid>

</Button>

 

Same with the Emergency Button. It doesn’t need to look as complicated as this. Just make sure you include a click event.

<Button x:Name=”EmergencyButton”

Grid.Row=”0″

Grid.RowSpan=”2″

HorizontalAlignment=”Center”

VerticalAlignment=”Top”

BorderThickness=”0″

Padding=”0″

Margin=”50″

Width=”300″

Height=”60″

Click=”Emergency_Click”

VerticalContentAlignment=”Stretch”

HorizontalContentAlignment=”Stretch”

Style=”{StaticResource ImageButtonStyle}”>

<!–<Image Source=”/Assets/Parrot/btn_emergency_normal.png”

Stretch=”None” />–>

<Grid>

<Grid.ColumnDefinitions>

<ColumnDefinition Width=”50″ />

<ColumnDefinition Width=”*” />

<ColumnDefinition Width=”50″ />

</Grid.ColumnDefinitions>

<Polygon Grid.Column=”0″

Fill=”{StaticResource Red}”

StrokeThickness=”0″

Points=”1,0 50,0 50,60 1,0″ />

<Rectangle Grid.Column=”1″

Fill=”{StaticResource Red}”

HorizontalAlignment=”Stretch”

VerticalAlignment=”Stretch”

StrokeThickness=”0″ />

<Rectangle Fill=”{StaticResource ParrotBrush}”

Grid.Column=”1″

Height=”3″

VerticalAlignment=”Bottom” />

<Polygon  Grid.Column=”2″

Fill=”{StaticResource Red}”

StrokeThickness=”0″

Points=”0,0 50,0 0,60 0,0″ />

<Line Grid.Column=”0″

X1=”1″

Y1=”-1″

X2=”50″

Y2=”60″

Stroke=”{StaticResource ParrotBrush}”

StrokeThickness=”3″ />

<Line Grid.Column=”2″

X1=”0″

Y1=”60″

X2=”50″

Y2=”-2″

Stroke=”{StaticResource ParrotBrush}”

StrokeThickness=”3″ />

<TextBlock Grid.Column=”1″

TextAlignment=”Center”

VerticalAlignment=”Center”

Foreground=”White”

FontSize=”30″>EMERGENCY</TextBlock>

</Grid>

</Button>

 

 

 

 

Drone Backend .xaml.cs

Now in the xaml.cs page we need to initialize the connection to the Drone and establish eventhandlers for the joysticks inputs and the emergency land and take off buttons.

The page needs the appropriate library references:

using ARDrone2Client.Common;

using ARDrone2Client.Common.Configuration;

using ARDrone2Client.Common.Input;

Inside of the class for the page initialize the DroneClienct and VideoSourceUrl as well as the DispatcherTimer, which will allow the app to continue other processes while it connects to your Drone.

private readonly DroneClient _droneClient;

private const string VideoSourceUrl = “ardrone://192.168.1.1”;

// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable

private readonly DispatcherTimer _timer;

Add the lines below so the Drone can be initialized and connect to the application.

 

For the Drone portion of the application we also need to add lines to the OnNavigatedTo portion of the page.

if (!_droneClient.IsActive)

await _droneClient.ConnectAsync();

UpdateDisplay();

 

The UpdateDisplay() Method is in charge of changing the Screen to allow the other Drone Activities to become active. However we aren’t going to use many of them so the only one we need to become actuve is TakeOffLanding, EmergencyButton, and ResetEmergency Button.

 

Now to see the video while we are controlling the Drone we need to set the MediaElement’s source to the Video URL in the Page_OnLoaded method.

private void Page_OnLoaded(object sender, RoutedEventArgs e)

{

ArDroneMediaElem.Source = new Uri(VideoSourceUrl);

UpdateDisplay();

}

 

We also need to handle what happens to the video when the app suspends and resumes.

private void OnResume(object sender, object e)

{

ArDroneMediaElem.Source = new Uri(VideoSourceUrl);

}

 

private async void OnSuspend(object sender, Windows.ApplicationModel.SuspendingEventArgs e)

{

var deferral = e.SuspendingOperation.GetDeferral();

ArDroneMediaElem.Source = null;

await Task.Delay(2000);

deferral.Complete();

}

 

Handling Drone input and Joystick controls are similar to how we did with the Sphero.

OnTakeOffButton_Clicked

private void TakeOffLandButton_Click(object sender, RoutedEventArgs e)

{

if (_droneClient.IsFlying())

_droneClient.Land();

else

_droneClient.TakeOff();

UpdateDisplay();

}

Emergency

OnPointerEntered

base.OnPointerEntered(e);

 

if (e.Pointer.PointerDeviceType != Windows.Devices.Input.PointerDeviceType.Touch)

return;

 

Point pos = e.GetCurrentPoint(JoystickGrid).Position;

var joy = pos.X < (ActualWidth / 2) ? RollPitchJoystick : YawGazJoystick;

var bounds = new Rect(joy.ActualWidth / 2, joy.ActualHeight / 2, JoystickGrid.ActualWidth – joy.ActualWidth / 2, JoystickGrid.ActualHeight – 75 – joy.ActualHeight / 2);

if (!bounds.Contains(pos))

return;

joy.Margin = new Thickness(pos.X – joy.ActualWidth / 2, pos.Y – joy.ActualHeight / 2, 0, 0);

joy.VerticalAlignment = VerticalAlignment.Top;

joy.HorizontalAlignment = HorizontalAlignment.Left;

 

OnPointerReleased

base.OnPointerReleased(e);

if (e.Pointer.PointerDeviceType != Windows.Devices.Input.PointerDeviceType.Touch)

return;

Point pos = e.GetCurrentPoint(JoystickGrid).Position;

var joy = pos.X < (ActualWidth / 2) ? RollPitchJoystick : YawGazJoystick;

joy.Margin = joy == YawGazJoystick ? new Thickness(0, 0, 80, 80) : new Thickness(80, 0, 0, 80);

joy.VerticalAlignment = VerticalAlignment.Bottom;

joy.HorizontalAlignment = joy == YawGazJoystick ? HorizontalAlignment.Right : HorizontalAlignment.Left;

joy.Reset();

 

 

Summary

So like I said, not an easy endeavor. Working with hardware takes a while and comes with its own set of unforeseen challenges. But, I hope this little post helps.

If you want to look at the source code it’s here:

Though I do have a caveat, most of this code was written last year and has not been updated since 2014. If major changes have happened in the SDK they have not been integrated yet. I’ll try and keep an eye out and update accordingly.

 

Happy Coding!

-TheNappingKat