+ All Categories
Home > Documents > Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences...

Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences...

Date post: 10-Jul-2018
Category:
Upload: vankien
View: 225 times
Download: 0 times
Share this document with a friend
28
1 Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract This article intends to serve as a tutorial on how to use near field communications (NFC) and Wi-Fi Direct in developing multi-device and multi-user application experiences on Intel® Atom™ processor- based tablets running Microsoft Windows 8*. A simple game app is used as an example to describe how to enable the proximity capabilities in the new Windows Store apps. 1 NFC and Wi-Fi Direct on Intel Atom Processor-based Tablets Intel Atom processor-based tablets running Windows 8 support Near Field Communications (NFC) and Wi-Fi Direct through Windows.Networking.Proximity namespace API. NFC is a set of communication standards that allows peer-to-peer data exchanges between two closely held devices. If two devices are held closely to each other (less than 4 centimeters) or are simply “tapped” together, the NFC components on the devices can discover each other and the operating systems can set up connection between the two devices to exchange data. Wi-Fi Direct is a technology that allows Wi-Fi devices to directly connect to each other without connecting to a wireless access point. Using Wi-Fi Direct, a device can browse for other devices within the Wi-Fi radio range, and request direct connection with these devices. Based on the Windows Proximity API on NFC and Wi-Fi Direct, we can create multi-device, multi-user experiences on tablets with Intel Atom processors. 2 Windows Proximity API
Transcript
Page 1: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

1

Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On

Intel® Atom™ Processor-Based Tablets

Abstract

This article intends to serve as a tutorial on how to use near field communications (NFC) and Wi-Fi

Direct in developing multi-device and multi-user application experiences on Intel® Atom™ processor-

based tablets running Microsoft Windows 8*. A simple game app is used as an example to describe

how to enable the proximity capabilities in the new Windows Store apps.

1 NFC and Wi-Fi Direct on Intel Atom Processor-based Tablets

Intel Atom processor-based tablets running Windows 8 support Near Field Communications (NFC)

and Wi-Fi Direct through Windows.Networking.Proximity namespace API.

NFC is a set of communication standards that allows peer-to-peer data exchanges between two

closely held devices. If two devices are held closely to each other (less than 4 centimeters) or are

simply “tapped” together, the NFC components on the devices can discover each other and the

operating systems can set up connection between the two devices to exchange data.

Wi-Fi Direct is a technology that allows Wi-Fi devices to directly connect to each other without

connecting to a wireless access point. Using Wi-Fi Direct, a device can browse for other devices

within the Wi-Fi radio range, and request direct connection with these devices.

Based on the Windows Proximity API on NFC and Wi-Fi Direct, we can create multi-device, multi-user

experiences on tablets with Intel Atom processors.

2 Windows Proximity API

Page 2: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

2

On Windows 8, the Windows.Networking.Proximity namespace API provides access to NFC and Wi-Fi

Direct hardware features. In the following sections, we will go through the process of developing a

“Tic-Tac-Toe” game app (Figure 1) using Microsoft Visual Studio 2012* and C# to show how to use

Windows Proximity API to create connections between two proximity devices.

An important note is this app must be run on two devices equipped with a NFC component and/or a

Wi-Fi adapter that supports Wi-Fi Direct.

Figure 1 The Tic-Tac-Toe game

3 Developing a Multi-Player Game Using Windows Proximity API

To start the Tic-Tac-Toe game app development, we assume you have already installed and set up

Visual Studio 2012 on your Windows 8 development system, and you have basic knowledge of the

C# programming language and XAML. To learn using C# and XAML to develop Windows Store apps,

please go to the link http://msdn.microsoft.com/en-us/library/windows/apps/hh974581.aspx.

Page 3: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

3

3.1 Create a C# Project and Enable Proximity Capabilities

Let’s start with creating the C# project. Open Visual 2012, select File->New->Project…, then select

“Visual C#” on the left pane, and “Blank App (XAML)” on the right pane. In the project name field,

enter “TicTacToe” (Figure 2), and click “OK”.

Figure 2 Creating a new C# project

Now we have the project created. On the “Solution Explorer” window we can see a file named

“Package.appxmanifest”. Double click the file to open it, and select the “Capabilities” tab within the

view of the file, and check the “Proximity” capability item (Figure 3).

Page 4: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

4

Figure 3 Adding proximity in the application capabilities

3.2 Add the UI XAML Code

Now let’s define the Tic-Tac-Toe game UI in XAML. On Solution Explorer screen, double click the file

“MainPage.xaml” to open it. Copy the contents in Figure 4 and paste to overwrite and replace the

original MainPage.xaml file content.

<Page

x:Class="TicTacToe.MainPage"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:local="using:TicTacToe"

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

xmlns:mc="http://schemas.openxmlformats.org/markup-

compatibility/2006"

mc:Ignorable="d">

<Grid x:Name="LayoutRoot" >

<Grid.ColumnDefinitions>

<ColumnDefinition Width="Auto"/>

<ColumnDefinition Width="*"/>

</Grid.ColumnDefinitions>

<StackPanel Height="Auto" VerticalAlignment="Top"

HorizontalAlignment="Left" Grid.Column="0">

<GridView x:Name="TicTacToeGridView" Width="Auto"

Page 5: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

5

Height="Auto" Background="Green"

BorderBrush="LightGray"

BorderThickness="2" VerticalAlignment="Stretch"

ScrollViewer.VerticalScrollBarVisibility="Auto"

ScrollViewer.HorizontalScrollBarVisibility="Auto"

IsItemClickEnabled="True"

>

<GridView.ItemsPanel>

<ItemsPanelTemplate>

<WrapGrid Orientation="Horizontal"

MaximumRowsOrColumns="3"/>

</ItemsPanelTemplate>

</GridView.ItemsPanel>

<Button x:Name="Grid_Button00"

Click="HandleClick_Button00" Height="200" Width="200" />

<Button x:Name="Grid_Button01"

Click="HandleClick_Button01" Height="200" Width="200" />

<Button x:Name="Grid_Button02"

Click="HandleClick_Button02" Height="200" Width="200" />

<Button x:Name="Grid_Button03"

Click="HandleClick_Button03" Height="200" Width="200" />

<Button x:Name="Grid_Button04"

Click="HandleClick_Button04" Height="200" Width="200" />

<Button x:Name="Grid_Button05"

Click="HandleClick_Button05" Height="200" Width="200" />

<Button x:Name="Grid_Button06"

Click="HandleClick_Button06" Height="200" Width="200" />

<Button x:Name="Grid_Button07"

Click="HandleClick_Button07" Height="200" Width="200" />

<Button x:Name="Grid_Button08"

Click="HandleClick_Button08" Height="200" Width="200" />

</GridView>

</StackPanel>

<StackPanel Orientation="Vertical" HorizontalAlignment="Left"

Margin="10,10,10,10" Grid.Column="1" >

<Button x:Name="StartPlayGameButton" Content="Start Game"

Background="Blue" Visibility="Collapsed" Margin="0,0,10,0"/>

<Button x:Name="FindPlayersButton" Content="Find Players"

Background ="Blue" Visibility="Collapsed" Margin="0,0,10,0"/>

<Button x:Name="InvitPlayerButton" Content="Invite A

Player" Background="Blue" Visibility="Collapsed" Margin="0,0,10,0"/>

<Button x:Name="AcceptButton" Content="Accept The

Invitation" Background="Blue" Visibility="Collapsed"

Margin="0,0,10,0"/>

<Button x:Name="EndGameButton" Content="End This Game"

Background="Blue" Visibility="Collapsed" Margin="0,0,10,0"/>

<Button x:Name="ReplayGameButton" Content="Play Again"

Background="Blue" Visibility="Collapsed" Margin="0,0,10,0"/>

<TextBlock x:Name="OutputTextBlock" FontSize="20"

Margin="0,0,10,0" />

<ListBox x:Name="ProximityDeviceList"

Background="LightBlue" >

</ListBox>

</StackPanel>

</Grid>

</Page>

Page 6: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

6

Figure 4 The MainPage.xaml file (**)

You will see the Tic-Tac-Toe basic UI appear on the design view (Figure 5).

Figure 5 The MainPage.xaml Design view

3.3 Attach PeerFinder Event Handlers and Start PeerFinder

In this game app, we support setting up device connections using either NFC tap gestures or Wi-Fi

Direct peer browsing. This is done by handling the PeerFinder.TriggeredConnectionStateChanged

and PeerFinder.ConnectionRequested events. We attach these event handlers in the “Start Game”

button click event handler. We then start PeerFinder. Figure 6 shows the “Start Game” button click

event handler code, which is in the C# file named MainPage.xaml.cs.

void StartPlayGame(object sender, RoutedEventArgs e)

{

if (!_peerFinderStarted)

{

// tap triggered state change handler

Page 7: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

7

PeerFinder.TriggeredConnectionStateChanged += new

TypedEventHandler<object,

TriggeredConnectionStateChangedEventArgs>(TriggeredConnectionStateChang

edEventHandler);

// ConnectionRequested event handler

PeerFinder.ConnectionRequested += new

TypedEventHandler<object,

ConnectionRequestedEventArgs>(ConnectionRequestedEventHandler);

// start the proximate device peer finder

PeerFinder.Start();

_peerFinderStarted = true;

}

}

Figure 6 Attaching the PeerFinder event handlers (**)

3.4 Handle PeerFinder Events

Now let’s implement the two PeerFinder event handlers. In the connection triggered by tap gestures,

after the connection is set up, we start data read and write using the Proximity stream socket

created during the connection setting up. If the connection is initiated using Wi-Fi Direct peer

browsing, we will display an “Accept” button to let the user confirm the connection.

async private void

TriggeredConnectionStateChangedEventHandler(object sender,

TriggeredConnectionStateChangedEventArgs eArgs)

{

if (eArgs.State == TriggeredConnectState.PeerFound)

{

// devices tap and detect each other, socket connection

set is setup.

DisplayConsoleMessage("Starting the connection ...");

}

if (eArgs.State == TriggeredConnectState.Completed)

{

DisplayConsoleMessage("Connect has been set up");

// get the socket which has been set up

_connectionSocket = eArgs.Socket;

await

Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>

{

this.StartSocketReadWrite();

});

}

Page 8: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

8

if (eArgs.State == TriggeredConnectState.Failed)

{

DisplayConsoleMessage("Failed to set up socket

connection.");

}

}

private async void ConnectionRequestedEventHandler(object

sender, ConnectionRequestedEventArgs args)

{

_invitedPlayerDevice = args.PeerInformation;

await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, ()

=>

{

DisplayConsoleMessage("Another player is available on

" + args.PeerInformation.DisplayName);

this.AcceptButton.Visibility = Visibility.Visible;

});

}

Figure 7 The implementation of the PeerFinder event handlers (**)

3.5 Exchange Messages Using the Proximity Stream Socket

After the connection between the two devices is set up, the two devices can exchange messages

using the StreamSocket object created by the Proximity API (Figure 8). This game app uses these

back-and-forth messages to inform the other player about the game moves and synchronize the

current state of the game.

void StartSocketReadWrite()

{

StartPlayGameButton.Visibility = Visibility.Collapsed;

InvitPlayerButton.Visibility = Visibility.Collapsed;

AcceptButton.Visibility = Visibility.Collapsed;

ProximityDeviceList.Visibility = Visibility.Collapsed;

FindPlayersButton.Visibility = Visibility.Collapsed;

_reader = new DataReader(_connectionSocket.InputStream);

_writer = new DataWriter(_connectionSocket.OutputStream);

_connectionSocketClosed = false;

ReadSocketMessage();

}

async void ReadSocketMessage()

{

try

{

uint byteCount = await _reader.LoadAsync(sizeof(uint));

if (byteCount > 0)

{

Page 9: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

9

uint len = (uint)_reader.ReadUInt32();

byteCount = await _reader.LoadAsync(len);

if (byteCount > 0)

{

String message = _reader.ReadString(len);

ProcessReadMessage(message);

// get the move of the other player, now is my

turn to play

_turnToPlay = true;

ReadSocketMessage(); // waiting for the next

socket read

}

else

{

HandleSocketError("The socket reading

failed.");

}

}

else

{

HandleSocketError("The socket reading failed.");

}

}

catch (Exception e)

{

if (!_connectionSocketClosed)

{

HandleSocketError("The socket reading failed with

the reason " + e.Message);

}

}

}

async private void SendMessage(String msg)

{

DisplayConsoleMessage("");

String message = msg;

if (!_connectionSocketClosed)

{

if (message.Length > 0)

{

try

{

uint len = _writer.MeasureString(message);

_writer.WriteUInt32(len);

_writer.WriteString(message);

uint byteCount = await _writer.StoreAsync();

if (byteCount > 0)

{

DisplayConsoleMessage("Send the move to the

other player: " + message + " byte count: " + byteCount);

}

else

{

HandleSocketError("The communication with

Page 10: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

10

the other player interrupted.");

}

}

catch (Exception err)

{

if (!_connectionSocketClosed)

{

HandleSocketError("Communication with the

other player error: " + err.Message);

}

}

}

}

else

{

HandleSocketError("The communication with the other

player device is closed.");

}

}

Figure 8 Using the Proximity StreamSocket to exchange messages (**)

3.6 Other Game Logic

Besides the logic used to set up the connection between the two devices in proximity,

MainPage.xaml.cs includes code that implements the Tic-Tac-Toe game logic, for example, to

determine which player’s turn it is to play, if the game ends, etc. We attach the completed

MainPage.xaml.cs file here. On the Solution Explorer screen, you may double click the

MainPage.xaml.cs file to open it, and copy the contents of Figure 9 and paste to overwrite the

contents in your original MainPage.xaml.cs file.

using System;

using System.Collections.Generic;

using System.IO;

using System.Linq;

using Windows.ApplicationModel.Activation;

using Windows.Foundation;

using Windows.Foundation.Collections;

using Windows.UI.Core;

Page 11: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

11

using Windows.UI.Xaml;

using Windows.UI.Xaml.Controls;

using Windows.UI.Xaml.Controls.Primitives;

using Windows.UI.Xaml.Data;

using Windows.UI.Xaml.Input;

using Windows.UI.Xaml.Media;

using Windows.UI.Xaml.Media.Imaging;

using Windows.UI.Xaml.Navigation;

using Windows.Networking.Proximity;

using Windows.Networking.Sockets;

using Windows.Storage.Streams;

using System.Diagnostics;

// The Blank Page item template is documented at

http://go.microsoft.com/fwlink/?LinkId=234238

namespace TicTacToe

{

/// <summary>

/// An empty page that can be used on its own or navigated to

within a Frame.

/// </summary>

public sealed partial class MainPage : Page

{

private IReadOnlyList<PeerInformation> _deviceList;

private PeerInformation _invitedPlayerDevice;

private StreamSocket _connectionSocket = null;

private bool _connectionSocketClosed = true;

private bool _peerFinderStarted = false;

private DataWriter _writer;

private DataReader _reader;

private bool _triggeredSupported = false;

private bool _browseSupported = false;

bool _launchedActivatedByPeerFinder = false;

//stores the current state of a game cell, 0 - untaken 1-taken

by player 1, 2-taken by plaer 2

private int[] _grid;

// 1 - player 1, 2- payer 2

private int _playerID;

//my turn to play

private bool _turnToPlay = false;

//the game has reached an end game state, one side wins or the

game draws

private bool _gameEnds = false;

private Button[] _buttons;

// the messages used to exchange the current state of the game

private static string _iwin = "IWIN";

private static string _gameDraw = "DRAW";

private static string _replayRequest = "REPLAY";

Page 12: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

12

private static string _endGameRequest = "ENDGAME";

public MainPage()

{

this.InitializeComponent();

_buttons = new Button[9];

_buttons[0] = Grid_Button00;

_buttons[1] = Grid_Button01;

_buttons[2] = Grid_Button02;

_buttons[3] = Grid_Button03;

_buttons[4] = Grid_Button04;

_buttons[5] = Grid_Button05;

_buttons[6] = Grid_Button06;

_buttons[7] = Grid_Button07;

_buttons[8] = Grid_Button08;

_grid = new int[9];

for (int ix = 0; ix < 9; ix++)

{

_grid[ix] = 0;

}

_playerID = 0;

_triggeredSupported = (PeerFinder.SupportedDiscoveryTypes &

PeerDiscoveryTypes.Triggered) ==

PeerDiscoveryTypes.Triggered;

_browseSupported = (PeerFinder.SupportedDiscoveryTypes &

PeerDiscoveryTypes.Browse) ==

PeerDiscoveryTypes.Browse;

if (_triggeredSupported || _browseSupported)

{

StartPlayGameButton.Click += new

RoutedEventHandler(StartPlayGame);

FindPlayersButton.Click += new

RoutedEventHandler(FindPlayers);

InvitPlayerButton.Click += new

RoutedEventHandler(InvitePlayer);

AcceptButton.Click += new RoutedEventHandler(Accept);

ReplayGameButton.Click += new

RoutedEventHandler(Replay);

EndGameButton.Click += new RoutedEventHandler(EndGame);

StartPlayGameButton.Visibility = Visibility.Visible;

DisplayConsoleMessage("Press the Start Game to start a

new game.");

}

}

void StartPlayGame(object sender, RoutedEventArgs e)

{

DisplayConsoleMessage("");

if (!_peerFinderStarted)

{

// tap triggered state change handler

PeerFinder.TriggeredConnectionStateChanged += new

Page 13: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

13

TypedEventHandler<object,

TriggeredConnectionStateChangedEventArgs>(TriggeredConnectionStateChang

edEventHandler);

// ConnectionRequested event handler

PeerFinder.ConnectionRequested += new

TypedEventHandler<object,

ConnectionRequestedEventArgs>(ConnectionRequestedEventHandler);

// start the proximate device peer finder

PeerFinder.Start();

_peerFinderStarted = true;

if (_triggeredSupported && _browseSupported)

{

DisplayConsoleMessage("Tap two player devices

together, or click Find Players button.");

FindPlayersButton.Visibility = Visibility.Visible;

}

else if (_triggeredSupported)

{

DisplayConsoleMessage("Tap two player devices

together to set up connection.");

}

else if (_browseSupported)

{

DisplayConsoleMessage("Click Find Players

button.");

}

}

}

async private void

TriggeredConnectionStateChangedEventHandler(object sender,

TriggeredConnectionStateChangedEventArgs eArgs)

{

if (eArgs.State == TriggeredConnectState.PeerFound)

{

// devices tap and detect each other, socket connection

set is setup.

DisplayConsoleMessage("Starting the connection ...");

}

if (eArgs.State == TriggeredConnectState.Completed)

{

DisplayConsoleMessage("Connect has been set up");

// get the socket which has been set up

_connectionSocket = eArgs.Socket;

await

Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>

{

this.StartSocketReadWrite();

});

}

if (eArgs.State == TriggeredConnectState.Failed)

{

DisplayConsoleMessage("Failed to set up socket

Page 14: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

14

connection.");

}

}

private async void ConnectionRequestedEventHandler(object

sender, ConnectionRequestedEventArgs args)

{

_invitedPlayerDevice = args.PeerInformation;

await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, ()

=>

{

DisplayConsoleMessage("Another player is available on

" + args.PeerInformation.DisplayName + ", press Accept button to play a

game.");

this.AcceptButton.Visibility = Visibility.Visible;

});

}

// Start the reader and the writer to talk to the other player

device

void StartSocketReadWrite()

{

StartPlayGameButton.Visibility = Visibility.Collapsed;

InvitPlayerButton.Visibility = Visibility.Collapsed;

AcceptButton.Visibility = Visibility.Collapsed;

ProximityDeviceList.Visibility = Visibility.Collapsed;

FindPlayersButton.Visibility = Visibility.Collapsed;

_reader = new DataReader(_connectionSocket.InputStream);

_writer = new DataWriter(_connectionSocket.OutputStream);

_connectionSocketClosed = false;

ReadSocketMessage();

}

async void ReadSocketMessage()

{

try

{

uint byteCount = await _reader.LoadAsync(sizeof(uint));

if (byteCount > 0)

{

uint len = (uint)_reader.ReadUInt32();

byteCount = await _reader.LoadAsync(len);

if (byteCount > 0)

{

String message = _reader.ReadString(len);

ProcessReadMessage(message);

if (_gameEnds != true)

{

DisplayConsoleMessage("Received the move

from the other player, your turn to play.");

}

// get the move of the other player, now is my

turn to play

_turnToPlay = true;

Page 15: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

15

ReadSocketMessage(); // waiting for the next

socket read

}

else

{

HandleSocketError("The socket reading

failed.");

}

}

else

{

HandleSocketError("The socket reading failed.");

}

}

catch (Exception e)

{

if (!_connectionSocketClosed)

{

HandleSocketError("The socket reading failed with

the reason " + e.Message);

}

}

}

private void ProcessReadMessage(String msg)

{

char[] delimiters = { '|', '\t' };

String[] elems = msg.Split(delimiters);

if (elems.Length == 1)

{

if (elems[0].Equals(_replayRequest,

StringComparison.OrdinalIgnoreCase))

{

ResetGame();

DisplayConsoleMessage("The other player has

requested to play again.");

}

else if (elems[0].Equals(_endGameRequest,

StringComparison.OrdinalIgnoreCase))

{

_gameEnds = true;

ReplayGameButton.Visibility = Visibility.Visible;

DisplayConsoleMessage("The other player has

requested to end this game.");

}

}

if (elems.Length > 1)

{

int rivalPlayer = Convert.ToInt32(elems[0]);

int pos = Convert.ToInt32(elems[1]);

MakeThePlay(rivalPlayer, pos);

if (elems.Length > 2)

{

if (elems[2].Equals(_iwin,

StringComparison.OrdinalIgnoreCase))

{

Page 16: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

16

_gameEnds = true;

HandleGameEnds(GameEndsType.OTHERSIDEWON);

}

else if (elems[2].Equals(_gameDraw,

StringComparison.OrdinalIgnoreCase))

{

_gameEnds = true;

HandleGameEnds(GameEndsType.DRAW);

}

}

}

}

private void HandleSocketError(String errMessage)

{

DisplayConsoleMessage(errMessage);

StartPlayGameButton.Visibility = Visibility.Visible;

if (_browseSupported)

{

FindPlayersButton.Visibility = Visibility.Visible;

}

if (!_connectionSocketClosed)

{

_connectionSocketClosed = true;

_connectionSocket.Dispose();

_connectionSocket = null;

}

}

async void FindPlayers(object sender, RoutedEventArgs e)

{

DisplayConsoleMessage("Looking for other players...");

try

{

_deviceList = await PeerFinder.FindAllPeersAsync();

}

catch (Exception ex)

{

DisplayConsoleMessage("Looking for other players

encountered problem: " + ex.Message);

}

if (_deviceList.Count > 0)

{

ProximityDeviceList.Items.Clear();

for (int i = 0; i < _deviceList.Count; i++)

{

ListBoxItem lbItem = new ListBoxItem();

lbItem.Content = _deviceList[i].DisplayName;

ProximityDeviceList.Items.Add(lbItem);

}

InvitPlayerButton.Visibility = Visibility.Visible;

ProximityDeviceList.Visibility = Visibility.Visible;

DisplayConsoleMessage("Other players are available,

press the Invite A Player button to invite a player to play.");

Page 17: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

17

}

else

{

DisplayConsoleMessage("No other player is available");

InvitPlayerButton.Visibility = Visibility.Collapsed;

ProximityDeviceList.Visibility = Visibility.Collapsed;

}

}

async void InvitePlayer(object sender, RoutedEventArgs e)

{

DisplayConsoleMessage("");

PeerInformation playerInvted = null;

try

{

// by default, select the first player

if (ProximityDeviceList.SelectedIndex == -1)

{

playerInvted = _deviceList[0];

}

else

{

playerInvted =

_deviceList[ProximityDeviceList.SelectedIndex];

}

DisplayConsoleMessage("Inviting the play on " +

playerInvted.DisplayName + " to play...");

_connectionSocket = await

PeerFinder.ConnectAsync(playerInvted);

DisplayConsoleMessage("The game is set up. Your turn to

play.");

StartSocketReadWrite();

_playerID = 1;

_turnToPlay = true;

EndGameButton.Visibility = Visibility.Visible;

}

catch (Exception err)

{

DisplayConsoleMessage("Failed to set up the game

connection with player on " + playerInvted.DisplayName + " reason: " +

err.Message);

}

}

async private void Accept(object sender, RoutedEventArgs e)

{

_playerID = 2;

_turnToPlay = false;

DisplayConsoleMessage("Setting up the game with player on "

+ _invitedPlayerDevice.DisplayName + "...");

AcceptButton.Visibility = Visibility.Collapsed;

EndGameButton.Visibility = Visibility.Visible;

try

{

_connectionSocket = await

PeerFinder.ConnectAsync(_invitedPlayerDevice);

Page 18: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

18

DisplayConsoleMessage("The game connection was set up

successfully. The other player's turn to play.");

StartSocketReadWrite();

}

catch (Exception err)

{

DisplayConsoleMessage("Setting up game connection with

player on " + _invitedPlayerDevice.DisplayName + " failed: " +

err.Message);

}

}

private void Replay(object sender, RoutedEventArgs e)

{

ResetGame();

SendMessage(_replayRequest);

}

private void EndGame(object sender, RoutedEventArgs e)

{

_gameEnds = true;

SendMessage(_endGameRequest);

ReplayGameButton.Visibility = Visibility.Visible;

DisplayConsoleMessage("The game was stopped.");

}

private void ResetGame()

{

DisplayConsoleMessage("");

for (int ix = 0; ix < 9; ix++)

{

MakeThePlay(0, ix);

}

_gameEnds = false;

ReplayGameButton.Visibility = Visibility.Collapsed;

EndGameButton.Visibility = Visibility.Visible;

}

/// <summary>

/// Invoked when this page is about to be displayed in a Frame.

/// </summary>

/// <param name="e">Event data that describes how this page was

reached. The Parameter

/// property is typically used to configure the page.</param>

protected override void OnNavigatedTo(NavigationEventArgs e)

{

LaunchActivatedEventArgs launchActivatedEventArgs =

e.Parameter as LaunchActivatedEventArgs;

if ((launchActivatedEventArgs != null) &&

(launchActivatedEventArgs.Arguments ==

"Windows.Networking.Proximity.PeerFinder:StreamSocket"))

{

_launchedActivatedByPeerFinder = true;

}

if (_triggeredSupported || _browseSupported)

Page 19: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

19

{

StartPlayGameButton.Visibility = Visibility.Visible;

FindPlayersButton.Visibility = Visibility.Collapsed;

InvitPlayerButton.Visibility = Visibility.Collapsed;

ProximityDeviceList.Visibility = Visibility.Collapsed;

AcceptButton.Visibility = Visibility.Collapsed;

EndGameButton.Visibility = Visibility.Collapsed;

if (_launchedActivatedByPeerFinder)

{

DisplayConsoleMessage("This game was started by

player on a proximity device");

_launchedActivatedByPeerFinder = false;

StartPlayGame(null, null);

}

}

else

{

DisplayConsoleMessage("Proximity API is not supported

on this device. This app can not run.");

}

}

// Invoked when the main page navigates to a different scenario

protected override void

OnNavigatingFrom(NavigatingCancelEventArgs e)

{

if (_peerFinderStarted)

{

PeerFinder.TriggeredConnectionStateChanged -= new

TypedEventHandler<object,

TriggeredConnectionStateChangedEventArgs>(TriggeredConnectionStateChang

edEventHandler);

PeerFinder.ConnectionRequested -= new

TypedEventHandler<object,

ConnectionRequestedEventArgs>(ConnectionRequestedEventHandler);

PeerFinder.Stop();

if (_connectionSocket != null)

{

_connectionSocketClosed = true;

_connectionSocket.Dispose();

_connectionSocket = null;

}

_peerFinderStarted = false;

}

}

public async void DisplayConsoleMessage(string strMessage)

{

await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, ()

=>

{

OutputTextBlock.Text = "\n" + strMessage;

});

}

void HandleClick_Button00(object sender, RoutedEventArgs e)

Page 20: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

20

{

HandleClick(0, sender, e);

}

void HandleClick_Button01(object sender, RoutedEventArgs e)

{

HandleClick(1, sender, e);

}

void HandleClick_Button02(object sender, RoutedEventArgs e)

{

HandleClick(2, sender, e);

}

void HandleClick_Button03(object sender, RoutedEventArgs e)

{

HandleClick(3, sender, e);

}

void HandleClick_Button04(object sender, RoutedEventArgs e)

{

HandleClick(4, sender, e);

}

void HandleClick_Button05(object sender, RoutedEventArgs e)

{

HandleClick(5, sender, e);

}

void HandleClick_Button06(object sender, RoutedEventArgs e)

{

HandleClick(6, sender, e);

}

void HandleClick_Button07(object sender, RoutedEventArgs e)

{

HandleClick(7, sender, e);

}

void HandleClick_Button08(object sender, RoutedEventArgs e)

{

HandleClick(8, sender, e);

}

void HandleClick(int btnIndex, object sender, RoutedEventArgs

e)

{

Button srcButton = sender as Button;

if ((_gameEnds == false) && (_turnToPlay == true) &&

(_grid[btnIndex] == 0))

{

MakeThePlay(_playerID, btnIndex);

GameEndsType moveResult = CheckIfGameEnds(_playerID,

btnIndex);

String msg = _playerID.ToString();

msg += "|";

msg += btnIndex.ToString();

if (moveResult == GameEndsType.IWON)

Page 21: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

21

{

_gameEnds = true;

msg += "|";

msg += _iwin;

}

else if (moveResult == GameEndsType.DRAW)

{

_gameEnds = true;

msg += "|";

msg += _gameDraw;

}

SendMessage(msg);

if (_gameEnds != true)

{

DisplayConsoleMessage("The move was sent to the

other player, now is the other player's turn to play.");

}

_turnToPlay = false;

if (_gameEnds == true)

{

HandleGameEnds(moveResult);

}

}

}

private void MakeThePlay(int _playerID, int btnIndex)

{

if (_playerID == 1)

{

_buttons[btnIndex].Background = new ImageBrush

{ ImageSource = new BitmapImage(new Uri("ms-

appx:///Assets/ximage.png")) };

}

else if (_playerID == 2)

{

_buttons[btnIndex].Background = new ImageBrush

{ ImageSource = new BitmapImage(new Uri("ms-

appx:///Assets/oimage.png")) };

}

else if (_playerID == 0)

{

_buttons[btnIndex].Background = new ImageBrush

{ ImageSource = new BitmapImage(new Uri("ms-

appx:///Assets/initialimage.png")) };

}

_grid[btnIndex] = _playerID;

}

private GameEndsType CheckIfGameEnds(int player, int btnIdx)

{

GameEndsType res = GameEndsType.CONTINUE;

switch (btnIdx)

{

case 0:

Page 22: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

22

if (((_grid[1] == _grid[0]) && (_grid[2] ==

_grid[0])) ||

((_grid[3] == _grid[0]) && (_grid[6] ==

_grid[0])) ||

((_grid[4] == _grid[0]) && (_grid[8] ==

_grid[0])))

{

res = GameEndsType.IWON;

}

break;

case 1:

if (((_grid[0] == _grid[1]) && (_grid[2] ==

_grid[1])) ||

((_grid[4] == _grid[1]) && (_grid[7] ==

_grid[1])))

{

res = GameEndsType.IWON;

}

break;

case 2:

if (((_grid[0] == _grid[2]) && (_grid[1] ==

_grid[2])) ||

((_grid[5] == _grid[2]) && (_grid[8] ==

_grid[2])) ||

((_grid[4] == _grid[2]) && (_grid[6] ==

_grid[2])))

{

res = GameEndsType.IWON;

}

break;

case 3:

if (((_grid[4] == _grid[3]) && (_grid[5] ==

_grid[3])) ||

((_grid[0] == _grid[3]) && (_grid[6] ==

_grid[3])))

{

res = GameEndsType.IWON;

}

break;

case 4:

if(((_grid[1] == _grid[4]) && (_grid[7] ==

_grid[4])) ||

((_grid[3] == _grid[4]) && (_grid[5] ==

_grid[4]))||

((_grid[0] == _grid[4]) && (_grid[8] ==

_grid[4])) ||

((_grid[2] == _grid[4]) && (_grid[6] ==

_grid[4])))

{

res = GameEndsType.IWON;

}

break;

case 5:

if (((_grid[3] == _grid[5]) && (_grid[4] ==

_grid[5])) ||

((_grid[2] == _grid[5]) && (_grid[8] ==

_grid[5])))

Page 23: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

23

{

res = GameEndsType.IWON;

}

break;

case 6:

if (((_grid[7] == _grid[6]) && (_grid[8] ==

_grid[6])) ||

((_grid[0] == _grid[6]) && (_grid[3] ==

_grid[6])) ||

((_grid[4] == _grid[6]) && (_grid[2] ==

_grid[6])))

{

res = GameEndsType.IWON;

}

break;

case 7:

if (((_grid[6] == _grid[7]) && (_grid[8] ==

_grid[7])) ||

((_grid[1] == _grid[7]) && (_grid[4] ==

_grid[7])))

{

res = GameEndsType.IWON;

}

break;

case 8:

if (((_grid[6] == _grid[8]) && (_grid[7] ==

_grid[8])) ||

((_grid[2] == _grid[8]) && (_grid[5] ==

_grid[8])) ||

((_grid[4] == _grid[8]) && (_grid[0] ==

_grid[8])))

{

res = GameEndsType.IWON;

}

break;

}

if (res != GameEndsType.IWON)

{

bool gameTies = true;

for (int ix = 0; ix < 9; ix++)

{

if (_grid[ix] == 0)

{

gameTies = false;

}

}

if (gameTies == true)

{

res = GameEndsType.DRAW;

}

}

return res;

}

private void HandleGameEnds(GameEndsType type)

{

switch (type)

Page 24: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

24

{

case GameEndsType.IWON:

DisplayConsoleMessage("I Won!");

break;

case GameEndsType.OTHERSIDEWON:

DisplayConsoleMessage("The Other Side Won!");

break;

case GameEndsType.DRAW:

DisplayConsoleMessage("A Draw!");

break;

}

ReplayGameButton.Visibility = Visibility.Visible;

}

async private void SendMessage(String msg)

{

DisplayConsoleMessage("");

String message = msg;

if (!_connectionSocketClosed)

{

if (message.Length > 0)

{

try

{

uint len = _writer.MeasureString(message);

_writer.WriteUInt32(len);

_writer.WriteString(message);

uint byteCount = await _writer.StoreAsync();

if (byteCount > 0)

{

}

else

{

HandleSocketError("The communication with

the other player interrupted.");

}

}

catch (Exception err)

{

if (!_connectionSocketClosed)

{

HandleSocketError("Communication with the

other player error: " + err.Message);

}

}

}

}

else

{

HandleSocketError("The communication with the other

player device is closed.");

}

}

}

public enum GameEndsType

Page 25: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

25

{

IWON,

OTHERSIDEWON,

DRAW,

CONTINUE

};

}

Figure 9 The MainPage.xaml.cs file (**)

3.7 Run the App

After you finish the changes described in the above sections and you successfully build the solution,

you can deploy the app on two tablets that support NFC and/or Wi-Fi Direct peer browsing. You can

play the game in action on the two devices (Figure 10).

Figure 10 The Tic-Tac-Toe game start screen

Page 26: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

26

4 Summary

On Intel Atom processor-based tablets running Windows 8, by using Windows Proximity API, we can

create connections between two devices with a simple tap gesture, or through Wi-Fi Direct peer

browsing. The connected devices can then exchange data with each other without connecting to a

network. The Windows Proximity API enables application developers to enhance their apps and

create multi-player application experiences.

About the Author

Miao Wei works as a software engineer with Intel Corporation’s Software and Services Group.

Notices

INFORMATION IN THIS DOCUMENT IS PROVIDED IN CONNECTION WITH INTEL PRODUCTS. NO

LICENSE, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, TO ANY INTELLECTUAL PROPERTY

RIGHTS IS GRANTED BY THIS DOCUMENT. EXCEPT AS PROVIDED IN INTEL'S TERMS AND

CONDITIONS OF SALE FOR SUCH PRODUCTS, INTEL ASSUMES NO LIABILITY WHATSOEVER AND

INTEL DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY, RELATING TO SALE AND/OR USE OF INTEL

PRODUCTS INCLUDING LIABILITY OR WARRANTIES RELATING TO FITNESS FOR A PARTICULAR

PURPOSE, MERCHANTABILITY, OR INFRINGEMENT OF ANY PATENT, COPYRIGHT OR OTHER

INTELLECTUAL PROPERTY RIGHT.

UNLESS OTHERWISE AGREED IN WRITING BY INTEL, THE INTEL PRODUCTS ARE NOT DESIGNED NOR

INTENDED FOR ANY APPLICATION IN WHICH THE FAILURE OF THE INTEL PRODUCT COULD CREATE

A SITUATION WHERE PERSONAL INJURY OR DEATH MAY OCCUR.

Intel may make changes to specifications and product descriptions at any time, without notice.

Designers must not rely on the absence or characteristics of any features or instructions marked

"reserved" or "undefined." Intel reserves these for future definition and shall have no responsibility

whatsoever for conflicts or incompatibilities arising from future changes to them. The information

here is subject to change without notice. Do not finalize a design with this information.

Page 27: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

27

The products described in this document may contain design defects or errors known as errata

which may cause the product to deviate from published specifications. Current characterized errata

are available on request.

Contact your local Intel sales office or your distributor to obtain the latest specifications and before

placing your product order.

Copies of documents which have an order number and are referenced in this document, or other

Intel literature, may be obtained by calling 1-800-548-4725, or go

to: http://www.intel.com/design/literature.htm

Intel, the Intel logo and Atom are trademarks of Intel Corporation in the U.S. and other countries.

*Other names and brands may be claimed as the property of others

**This sample source code is released under the Intel Sample Source Code License Agreement

Copyright© 2012 Intel Corporation. All rights reserved.

Page 28: Creating Multi-Player Experiences Using NFC and Wi-Fi ... · Creating Multi-Player Experiences Using NFC and Wi-Fi* Direct On Intel® Atom™ Processor-Based Tablets Abstract ...

28

Optimization Notice

Optimization Notice

Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations

that are not unique to Intel microprocessors. These optimizations include SSE2, SSE3, and SSE3 instruction sets

and other optimizations. Intel does not guarantee the availability, functionality, or effectiveness of any

optimization on microprocessors not manufactured by Intel.

Microprocessor-dependent optimizations in this product are intended for use with Intel microprocessors. Certain

optimizations not specific to Intel microarchitecture are reserved for Intel microprocessors. Please refer to the

applicable product User and Reference Guides for more information regarding the specific instruction sets

covered by this notice.

Notice revision #20110804


Recommended