31
Developing Cross- Developing Cross- Platform Networked Game Platform Networked Game with XNA 2.0 Game with XNA 2.0 Game Studio Studio 2008. 5. 24. 2008. 5. 24. 김김김 김김김 ([email protected]) ([email protected]) Xbox & HW STE Xbox & HW STE Microsoft Korea EDD R&D Microsoft Korea EDD R&D

XNA2.0 Network Programming

Embed Size (px)

DESCRIPTION

XNA2.0 Network Programming

Citation preview

Page 1: XNA2.0 Network Programming

Developing Cross-Platform Developing Cross-Platform Networked Game with XNA Networked Game with XNA

2.0 Game Studio2.0 Game Studio

2008. 5. 24.2008. 5. 24.김의열 김의열 ([email protected])([email protected])

Xbox & HW STEXbox & HW STEMicrosoft Korea EDD R&DMicrosoft Korea EDD R&D

Page 2: XNA2.0 Network Programming

AgendaAgenda

XNA & Cross-Platform Game DevelopmentXNA & Cross-Platform Game Development

Preview: Net RumblePreview: Net Rumble

Initializing Game ServicesInitializing Game Services

Creating a SessionCreating a Session

Finding and Joining a SessionFinding and Joining a Session

Managing Players Joining and LeavingManaging Players Joining and Leaving

Managing Players from Lobby to GameplayManaging Players from Lobby to Gameplay

Sending & Receiving DataSending & Receiving Data

Ending the GameEnding the Game

DEMODEMO

TIPSTIPS

Q & AQ & A

Page 3: XNA2.0 Network Programming

XNA & Cross-Platform Game Development XNA & Cross-Platform Game Development (1)(1)

What is the cross-platform game?What is the cross-platform game?

LIVE ServerLIVE Server

PCPC

Xbox360Xbox360

Page 4: XNA2.0 Network Programming

XNA & Cross-Platform Game Development XNA & Cross-Platform Game Development (2)(2)

.NET Framework for .NET Framework for Windows,Windows, & .NET & .NET Compact Framework Compact Framework for Xbox 360for Xbox 360

공통된 공통된 XNA Framework XNA Framework – – 하나의 하나의 sourcesource codecode로 각 로 각 platformplatform 에서 에서 컴파일 및 실행 가능컴파일 및 실행 가능

추가적인 추가적인 source codesource code나 나 architecture architecture 없이 없이 cross-platform cross-platform networking networking 지원지원

FrameworkFramework FrameworkFramework

Your GameYour Game Your GameYour Game

Page 5: XNA2.0 Network Programming

Preview: Net Rumble (DEMO)Preview: Net Rumble (DEMO)

Download from XNA Creators’ Club (Download from XNA Creators’ Club (http://creators.xna.com/))> Education > Starter kits > Net Rumble> Education > Starter kits > Net Rumble

DEMODEMO

Page 6: XNA2.0 Network Programming

Preview: Net Rumble (FSM)Preview: Net Rumble (FSM)

GamerJoined GamerLeft

GameStarted

SessionEnded

Create(…)Create(…)

StartGame()StartGame()EndGame()EndGame()

Dispose()Dispose()

GameEnded

HostChanged

Page 7: XNA2.0 Network Programming

Initiating Gamer ServicesInitiating Gamer Services

Networking API call Networking API call 이전에 이전에 Gamer ServicesGamer Services 가 반드시 가 반드시 initializeinitialize되어야 함되어야 함

Components.Add(new GamerServicesComponent(this));Components.Add(new GamerServicesComponent(this));

GamerGamer 들의 들의 LIVE sign in/out LIVE sign in/out 관리관리

GamerGamer 의 의 Profile Profile 정보 제공정보 제공Gamerscore, Gamerzone, Gamer Picture, Region, Motto, Reputation, …Gamerscore, Gamerzone, Gamer Picture, Region, Motto, Reputation, …

SignedInGamerSignedInGamer 의 의 GameDefaults GameDefaults 정보 제공 정보 제공 (preferred settings)(preferred settings)Controller sensitivity, Game difficulty, Auto-aim, Axis inversion, …Controller sensitivity, Game difficulty, Auto-aim, Axis inversion, …

SignedInGamerSignedInGamer 의의 Privileges Privileges 정보 제공정보 제공AllowCommunication, AllowOnlineSessions, AllowProfileViewing, LIVE-enabled AllowCommunication, AllowOnlineSessions, AllowProfileViewing, LIVE-enabled or guestor guest

자동으로 자동으로 GamerServicesDispatcher.Update() GamerServicesDispatcher.Update() 호출호출 , , Gamer.SignedInGamers collectionGamer.SignedInGamers collection 을 업데이트을 업데이트

Page 8: XNA2.0 Network Programming

Initiating Game Services: CodeInitiating Game Services: Code

InitializingInitializing 에 시간이 많이 에 시간이 많이 소요되므로 소요되므로 constructorconstructor에서 수행에서 수행

GuideGuide 를 통해 를 통해 LIVE sign LIVE sign in/outin/out 을 수행을 수행

Gamer.SignedInGamersGamer.SignedInGamers 를 를 통해 통해 locallocal 에 에 sign-insign-in 한 한 GamerGamer 의 의 collectioncollection 을 을 가져옴가져옴

using Microsoft.Xna.Framework.GamerServices… public NetRumbleGame(){ … Components.Add(new GamerServicesComponent(this)); …}

using Microsoft.Xna.Framework.GamerServices… public NetRumbleGame(){ … Components.Add(new GamerServicesComponent(this)); …}

if (!Guide.IsVisible){ Guide.ShowSignIn(1, false);}

if (!Guide.IsVisible){ Guide.ShowSignIn(1, false);}

bool signedIntoLive = false;if (Gamer.SignedInGamers.Count > 0){ foreach (SignedInGamer signedInGamer in Gamer.SignedInGamers) { if (signedInGamer.IsSignedInToLive) { signedIntoLive = true; break; } } State = signedIntoLive ? MainMenuState.SignedInLive : MainMenuState.SignedInLocal;}else{ State = MainMenuState.SignedOut;}

bool signedIntoLive = false;if (Gamer.SignedInGamers.Count > 0){ foreach (SignedInGamer signedInGamer in Gamer.SignedInGamers) { if (signedInGamer.IsSignedInToLive) { signedIntoLive = true; break; } } State = signedIntoLive ? MainMenuState.SignedInLive : MainMenuState.SignedInLocal;}else{ State = MainMenuState.SignedOut;}

Page 9: XNA2.0 Network Programming

Creating a SessionCreating a Session

Network sessionNetwork session 은 은 gamergamer 의 집합과 속성으로 이루어짐의 집합과 속성으로 이루어짐 ..AllGamers, LocalGamers, RemoteGamers, Host, …AllGamers, LocalGamers, RemoteGamers, Host, …

SessionType, SessionState, SessionProperties, …SessionType, SessionState, SessionProperties, …

IsEveryoneReady, IsHost, …IsEveryoneReady, IsHost, …

NetworkSession.Create(…)NetworkSession.Create(…) 를 통해 를 통해 session session 생성생성 . . public static NetworkSession Create(NetworkSessionType sessionType, int public static NetworkSession Create(NetworkSessionType sessionType, int maxLocalGamers, int maxGamers);maxLocalGamers, int maxGamers);

public static NetworkSession Create(NetworkSessionType sessionType, int public static NetworkSession Create(NetworkSessionType sessionType, int maxLocalGamers, int maxGamers, int privateGamerSlots, maxLocalGamers, int maxGamers, int privateGamerSlots, NetworkSessionProperties sessionProperties);NetworkSessionProperties sessionProperties);

.BeginCreate(…) ~ .EndCreate(…).BeginCreate(…) ~ .EndCreate(…) 를 통한 비동기식 방식 가능를 통한 비동기식 방식 가능 ..

NetworkSessionNetworkSession 을 생성한 을 생성한 playerplayer 는 는 hosthost 가 됨가 됨 ..

NetworkException, GamerPrivilegeExceptionNetworkException, GamerPrivilegeException

관심 있는 이벤트를 관심 있는 이벤트를 subscribe.subscribe.

Page 10: XNA2.0 Network Programming

Creating a Session – Network Creating a Session – Network RequirementsRequirements

Xbox 360 ConsoleWindows-Based Computer

Run an XNA Framework Game

LIVE Silver membership + Creators Club membership

No memberships Required

Use System Link

LIVE Silver membership + Creators Club membership

No memberships Required

Sign-on to Xbox Live and Games for Windows - LIVE Servers

LIVE Silver membership + Creators Club membership

LIVE Silver membership + Creators Club membership

Use LIVE MatchmakingLIVE Gold membership + Creators Club membership

LIVE Gold membership + Creators Club membership

Page 11: XNA2.0 Network Programming

Creating a Session: Code (1)Creating a Session: Code (1)

NetworkSession.Create(…)NetworkSession.Create(…)은 은 NetworkSessionNetworkSession 을 을 반환한다반환한다 ..

enum enum 을 활용하여 을 활용하여 NetworkSessionProperties NetworkSessionProperties 이용이용 ..

BeginCreate(…) ~ BeginCreate(…) ~ EndCreate(…)EndCreate(…) 를 이용하여 를 이용하여 비동기적으로 비동기적으로 sessionsession 을 을 생성할 수 있다생성할 수 있다 ..

AllowHostMigration?AllowHostMigration?

AllowJoinInProgress?AllowJoinInProgress?

using Microsoft.Xna.Framework.Net;…enum SessionProperties { GameMode, ScoreToWin }enum GameMode { FreeForAll, CaptureTheFlag }…NetworkSessionProperties sessionProperties = new NetworkSessionProperties();sessionProperties[(int)SessionProperties.GameMode] = (int)GameMode.FreeForAll;sessionProperties[(int)SessionProperties.ScoreToWin] = 1000;…NetworkSession session;int maxLocalGamers = 1;int maxGamers = 8;int privateGamerSlots =2;session = NetworkSession.Create(NetworkSessionType.SystemLink, maxLocalGamers, maxGamers, privateGamerSlots, sessionProperties);

using Microsoft.Xna.Framework.Net;…enum SessionProperties { GameMode, ScoreToWin }enum GameMode { FreeForAll, CaptureTheFlag }…NetworkSessionProperties sessionProperties = new NetworkSessionProperties();sessionProperties[(int)SessionProperties.GameMode] = (int)GameMode.FreeForAll;sessionProperties[(int)SessionProperties.ScoreToWin] = 1000;…NetworkSession session;int maxLocalGamers = 1;int maxGamers = 8;int privateGamerSlots =2;session = NetworkSession.Create(NetworkSessionType.SystemLink, maxLocalGamers, maxGamers, privateGamerSlots, sessionProperties);NetworkSession networkSession = null;…IAsyncResult asyncResult = NetworkSession.BeginCreate(sessionType, 1, World.MaximumPlayers, null, null);…if ((asyncResult != null) && asyncResult.IsCompleted){ networkSession = NetworkSession.EndCreate(asyncResult);… networkSession.AllowHostMigration = true; networkSession.AllowJoinInProgress = false;…}

NetworkSession networkSession = null;…IAsyncResult asyncResult = NetworkSession.BeginCreate(sessionType, 1, World.MaximumPlayers, null, null);…if ((asyncResult != null) && asyncResult.IsCompleted){ networkSession = NetworkSession.EndCreate(asyncResult);… networkSession.AllowHostMigration = true; networkSession.AllowJoinInProgress = false;…}

Page 12: XNA2.0 Network Programming

Creating a Session: Code (2)Creating a Session: Code (2)

SessionSession 을 생성한 후에는 을 생성한 후에는 NetworkSessionNetworkSession 에서 에서 발생하는 이벤트를 발생하는 이벤트를 subscribesubscribe하여 적절하게 반응한다하여 적절하게 반응한다 ..

GameEnded GameEnded 이벤트이벤트GameStarted GameStarted 이벤트이벤트GamerJoined GamerJoined 이벤트이벤트GamerLeft GamerLeft 이벤트이벤트HostChanged HostChanged 이벤트이벤트SessionEnded SessionEnded 이벤트이벤트

EventHandler<GameStartedEventArgs> gameStartedHandler;EventHandler<GamerJoinedEventArgs> gamerJoinedHandler;EventHandler<NetworkSessionEndedEventArgs> sessionEndedHandler;…

public override void LoadContent(){ … networkSession.GamerJoined += gamerJoinedHandler; networkSession.GameStarted += gameStartedHandler; networkSession.SessionEnded += sessionEndedHandler; …}

void networkSession_GamerJoined(object sender, GamerJoinedEventArgs e){…}

EventHandler<GameStartedEventArgs> gameStartedHandler;EventHandler<GamerJoinedEventArgs> gamerJoinedHandler;EventHandler<NetworkSessionEndedEventArgs> sessionEndedHandler;…

public override void LoadContent(){ … networkSession.GamerJoined += gamerJoinedHandler; networkSession.GameStarted += gameStartedHandler; networkSession.SessionEnded += sessionEndedHandler; …}

void networkSession_GamerJoined(object sender, GamerJoinedEventArgs e){…}

Page 13: XNA2.0 Network Programming

Finding and Joining a SessionFinding and Joining a Session

NetworkSession.Find(NetworkSession.Find(……)) 를 통해 원하는 를 통해 원하는 sessionsession 의 집합 의 집합 AvailableNetworkSessionCollectionAvailableNetworkSessionCollection 을 가져옴을 가져옴 . .

public static AvailableNetworkSessionCollection Find(NetworkSessionType public static AvailableNetworkSessionCollection Find(NetworkSessionType sessionType, int maxLocalGamers, NetworkSessionProperties sessionType, int maxLocalGamers, NetworkSessionProperties searchProperties);searchProperties);

.BeginFind(.BeginFind(……) ~ .EndFind() ~ .EndFind(……)) 를 통한 비동기식 방식 가능를 통한 비동기식 방식 가능 ..

AvailableNetworkSessionAvailableNetworkSession 에서 다음과 같은 정보를 가져올 수 있다에서 다음과 같은 정보를 가져올 수 있다 ..HostGamertag, CurrentGamerCount, OpenPrivateGamerSlots, HostGamertag, CurrentGamerCount, OpenPrivateGamerSlots, OpenPublicGamerSlots, …OpenPublicGamerSlots, …

원하는 원하는 AvailableNetworkSessionAvailableNetworkSession 을 을 NetworkSession.Join(NetworkSession.Join(……)) 에 에 인자로 넘겨주면 해당 인자로 넘겨주면 해당 sessionsession 을 반환하고 을 반환하고 JoinJoin 이 일어난다이 일어난다 ..

session = NetworkSession.Join(availableSessions[selectedSessionIndex];session = NetworkSession.Join(availableSessions[selectedSessionIndex];

NetworkException, GamerPrivilegeExceptionNetworkException, GamerPrivilegeException

관심 있는 이벤트를 관심 있는 이벤트를 subscribe.subscribe.

Page 14: XNA2.0 Network Programming

Finding and Joining a Session: Code (1)Finding and Joining a Session: Code (1)

NetworkSession.Create(…)NetworkSession.Create(…)에 사용하였던 것과 같은 에 사용하였던 것과 같은 방식으로 방식으로 NetworkSessionProperties NetworkSessionProperties 구성구성 ..

availableSessionsavailableSessions 로부터 로부터 HostGamertag, HostGamertag, CurrentGamerCount, CurrentGamerCount, OpenPrivateGamerSlots, OpenPrivateGamerSlots, 등등의 정보를 가져옴등등의 정보를 가져옴 ..

Quick MatchQuick Match 의 경우는 바로 의 경우는 바로 availableSessions[0]availableSessions[0] 을 을 통해 통해 join.join.

using Microsoft.Xna.Framework.Net;…enum SearchProperties { GameMode, ScoreToWin }enum GameMode { FreeForAll, CaptureTheFlag }…NetworkSessionProperties searchProperties = new NetworkSessionProperties();searchProperties[(int)SearchProperties.GameMode] = (int)GameMode.FreeForAll;searchProperties[(int)SearchProperties.ScoreToWin] = 1000;searchProperties[2] = 3;…AvailableNetworkSessionCollection availableSessions;int maxLocalGamers = 1;availableSessions = NetworkSession.Find(NetworkSessionType.PlayerMatch, maxLocalGamers, searchProperties);

using Microsoft.Xna.Framework.Net;…enum SearchProperties { GameMode, ScoreToWin }enum GameMode { FreeForAll, CaptureTheFlag }…NetworkSessionProperties searchProperties = new NetworkSessionProperties();searchProperties[(int)SearchProperties.GameMode] = (int)GameMode.FreeForAll;searchProperties[(int)SearchProperties.ScoreToWin] = 1000;searchProperties[2] = 3;…AvailableNetworkSessionCollection availableSessions;int maxLocalGamers = 1;availableSessions = NetworkSession.Find(NetworkSessionType.PlayerMatch, maxLocalGamers, searchProperties);

if (availableSessions != null){ foreach (AvailableNetworkSession availableSession in availableSessions) { if (availableSession.CurrentGamerCount < World.MaximumPlayers) { MenuEntries.Add(availableSession.HostGamertag + " (" + availableSession.CurrentGamerCount.ToString() + "/" + World.MaximumPlayers.ToString() + ")"); } }}

if (availableSessions != null){ foreach (AvailableNetworkSession availableSession in availableSessions) { if (availableSession.CurrentGamerCount < World.MaximumPlayers) { MenuEntries.Add(availableSession.HostGamertag + " (" + availableSession.CurrentGamerCount.ToString() + "/" + World.MaximumPlayers.ToString() + ")"); } }}

Page 15: XNA2.0 Network Programming

Finding and Joining a Session: Code (2)Finding and Joining a Session: Code (2)

NetworkSession.JoinNetworkSession.Join 에 에 참여를 원하는 참여를 원하는 availableSessionavailableSession 을 을 넘겨주면 바로 넘겨주면 바로 join join 완료완료 ..

SessionSession 에 에 joinjoin 한 후에는 한 후에는 NetworkSessionNetworkSession 에서 에서 발생하는 이벤트를 적절하게 발생하는 이벤트를 적절하게 subscribesubscribe 한다한다 ..

SessionSession 이 종료될 때는 이 종료될 때는 subscribesubscribe 했던 이벤트를 했던 이벤트를 unsubscribe.unsubscribe.

NetworkSession session;…session = NetworkSession.Join(availableSessions[selectedSessionIndex]);

NetworkSession session;…session = NetworkSession.Join(availableSessions[selectedSessionIndex]);

EventHandler<GameStartedEventArgs> gameStartedHandler;EventHandler<GamerJoinedEventArgs> gamerJoinedHandler;EventHandler<NetworkSessionEndedEventArgs> sessionEndedHandler;…

public override void LoadContent(){ … networkSession.GamerJoined += gamerJoinedHandler; networkSession.GameStarted += gameStartedHandler; networkSession.SessionEnded += sessionEndedHandler; …}

void networkSession_GamerJoined(object sender, GamerJoinedEventArgs e){…}

EventHandler<GameStartedEventArgs> gameStartedHandler;EventHandler<GamerJoinedEventArgs> gamerJoinedHandler;EventHandler<NetworkSessionEndedEventArgs> sessionEndedHandler;…

public override void LoadContent(){ … networkSession.GamerJoined += gamerJoinedHandler; networkSession.GameStarted += gameStartedHandler; networkSession.SessionEnded += sessionEndedHandler; …}

void networkSession_GamerJoined(object sender, GamerJoinedEventArgs e){…}

Page 16: XNA2.0 Network Programming

Managing Players Joining and LeavingManaging Players Joining and Leaving

NetworkSessionNetworkSession 은 은 GamerGamer 들의 들의 listlist 를 보유 를 보유 public GamerCollection<NetworkGamer> AllGamers {get;}public GamerCollection<NetworkGamer> AllGamers {get;}

public GamerCollection<LocalNetworkGamer> LocalGamers {get;}public GamerCollection<LocalNetworkGamer> LocalGamers {get;}

public GamerCollection<NetworkGamer> RemoteGamers {get;} public GamerCollection<NetworkGamer> RemoteGamers {get;}

public NetworkGamer Host {get;}public NetworkGamer Host {get;}

SessionSession 의 의 gamer listgamer list 는 는 machine machine 간에 서로 같음이 보장간에 서로 같음이 보장 ..Local gamer / Remote gamerLocal gamer / Remote gamer

Host gamer / guest gamerHost gamer / guest gamer

sessionsession 에 에 gamergamer 가 가 joined joined 할 때 할 때 session.GamerJoined session.GamerJoined 이벤트이벤트 발생발생 ..

sessionsession 에 에 gamergamer 가 가 left left 할 때 할 때 session.GamerLeft session.GamerLeft 이벤트이벤트 발생발생 ..

Gamer.Tag objectGamer.Tag object 를 이용해 를 이용해 playerplayer 의 상태와 연결하는 데 사용한다의 상태와 연결하는 데 사용한다 ..

Page 17: XNA2.0 Network Programming

Managing Players Joining and Leaving: Managing Players Joining and Leaving: CodeCode

NetworkSession.GamerJoinNetworkSession.GamerJoined, ed, NetworkSession.GamerLeft NetworkSession.GamerLeft 이벤트는 이벤트는 session session 생성 당시 생성 당시 subscribesubscribe 하기로 등록된 상태하기로 등록된 상태

GamerJoined GamerJoined 이벤트에 따라 이벤트에 따라 joinedjoined 한 한 playerplayer 에 에 data data 할당할당

Object typeObject type 인 인 Gamer.TagGamer.Tag를 이용하여 를 이용하여 gamegame 에 에 사용되는 사용되는 player classplayer class 를 를 연결연결

GamerLeft GamerLeft 이벤트에 따라 이벤트에 따라 leftleft 한 한 playerplayer 의 의 data data cleanupcleanup

void networkSession_GamerJoined(object sender, GamerJoinedEventArgs e){ for (int i = 0; i < networkSession.AllGamers.Count; i++) { if (networkSession.AllGamers[i] == e.Gamer) { PlayerData playerData = new PlayerData(); e.Gamer.Tag = playerData; … } } // Code for broadcasting the new player information …}

void networkSession_GamerJoined(object sender, GamerJoinedEventArgs e){ for (int i = 0; i < networkSession.AllGamers.Count; i++) { if (networkSession.AllGamers[i] == e.Gamer) { PlayerData playerData = new PlayerData(); e.Gamer.Tag = playerData; … } } // Code for broadcasting the new player information …}

void networkSession_GamerLeft(object sender, GamerLeftEventArgs e){ PlayerData playerData = e.Gamer.Tag as PlayerData; if ((playerData != null) && (playerData.Ship != null)) { playerData.Ship.Die(null, true); // Remove the player }}

void networkSession_GamerLeft(object sender, GamerLeftEventArgs e){ PlayerData playerData = e.Gamer.Tag as PlayerData; if ((playerData != null) && (playerData.Ship != null)) { playerData.Ship.Die(null, true); // Remove the player }}

Page 18: XNA2.0 Network Programming

Managing Players from Lobby to GameplayManaging Players from Lobby to Gameplay

각 각 GamerGamer 는 는 IsReady IsReady 속성을 가지고 있음속성을 가지고 있음 ..

생성된 생성된 NetworkSessionNetworkSession 은 은 IsEveryoneReady IsEveryoneReady 속성을 가지고 있음속성을 가지고 있음 ..

각 각 GamerGamer 의 의 .IsReady .IsReady 값을 초기화하기 위한 값을 초기화하기 위한 .ResetReady() .ResetReady() 메소드메소드 ..

NetworkSessionNetworkSession 은 은 NetworkSessionStateNetworkSessionState 를 가진다를 가진다 ..NetworkSessionState.LobbyNetworkSessionState.Lobby

NetworkSessionState.PlayingNetworkSessionState.Playing

NetworkSessionState.EndedNetworkSessionState.Ended

LobbyLobby 에서 에서 PlayingPlaying 으로 으로 statestate 를 를 transittransit 하기 위해 하기 위해 HostHost 가 가 NetworkSession.StartGame() NetworkSession.StartGame() 호출호출 ..

Page 19: XNA2.0 Network Programming

Managing Players from Lobby to Gameplay: CodeManaging Players from Lobby to Gameplay: Code

LocalGamerLocalGamer 가 가 IsReadyIsReady 가 가 아니라면 아니라면 ReadyReady 하라는 하라는 메시지메시지

IsEveryoneReadyIsEveryoneReady 가 가 아니라면 모두 아니라면 모두 ReadyReady 하기를 하기를 기다리라는 메시지기다리라는 메시지

모두 모두 Ready Ready 상태가 되면 상태가 되면 HostHost 가 아닌 경우는 대기가 아닌 경우는 대기 , , HostHost 라면 라면 .StartGame().StartGame() 와 와 호출호출 , , 게임 시작게임 시작 ..

NetworkSession.GameStarNetworkSession.GameStartedted 이벤트의 이벤트의 EventHandlerEventHandler에서 에서 worldworld 를 생성 및 초기를 생성 및 초기화화 ..

if (!networkSession.LocalGamers[0].IsReady){ MenuEntries[0] = "Press X to Mark as Ready";}else if (!networkSession.IsEveryoneReady){ MenuEntries[0] = "Waiting for all players to mark as ready...";}else if (!networkSession.IsHost){ MenuEntries[0] = "Waiting for the host to start game...";}else{ MenuEntries[0] = "Starting the game..."; networkSession.StartGame();}

if (!networkSession.LocalGamers[0].IsReady){ MenuEntries[0] = "Press X to Mark as Ready";}else if (!networkSession.IsEveryoneReady){ MenuEntries[0] = "Waiting for all players to mark as ready...";}else if (!networkSession.IsHost){ MenuEntries[0] = "Waiting for the host to start game...";}else{ MenuEntries[0] = "Starting the game..."; networkSession.StartGame();}

void networkSession_GameStarted(object sender, GameStartedEventArgs e){ if ((networkSession != null) && networkSession.IsHost && (world != null)) { world.GenerateWorld(); }}

void networkSession_GameStarted(object sender, GameStartedEventArgs e){ if ((networkSession != null) && networkSession.IsHost && (world != null)) { world.GenerateWorld(); }}

Page 20: XNA2.0 Network Programming

Sending & Receiving Data: Network TopologySending & Receiving Data: Network Topology

• Server-Client model vs. Peer-to-Peer modelServer-Client model vs. Peer-to-Peer model• NetworkSessionNetworkSession 의 의 hosthost 가 가 game logicgame logic 상 상 server server 역할을 의미하지는 역할을 의미하지는

않음않음 ..• HostHost 의 역할은 의 역할은 sessionsession 의 의 descriptiondescription 을 을 ownown 하고하고 , session, session 의 의 propertyproperty 와 와 statestate

를 를 change/updatechange/update 하고하고 , player, player 를 를 sessionsession 에서 제거하는 것에만 국한에서 제거하는 것에만 국한 ..

• HostMigrationHostMigration 이 허용되는 경우 자동으로 새 이 허용되는 경우 자동으로 새 hosthost 가 선출됨 가 선출됨 (NetworkSession.HostChanged (NetworkSession.HostChanged 이벤트이벤트 발생발생 ))

• Server-Client modelServer-Client model 의 경우 의 경우 server gamerserver gamer 가 갑자기 가 갑자기 disconnectdisconnect 되는 되는 상황 등 고려상황 등 고려

Page 21: XNA2.0 Network Programming

Sending & Receiving DataSending & Receiving Data

Reliable UDPReliable UDP 에 기반한 에 기반한 packet packet 전송전송

LocalNetworkGamerLocalNetworkGamer 의 의 SendData(…)SendData(…) 함수 호출함수 호출public void SendData(PacketWriter data, SendDataOptions options);public void SendData(PacketWriter data, SendDataOptions options);

public void SendData(byte[] data, SendDataOptions options);public void SendData(byte[] data, SendDataOptions options);

public void SendData(byte[] data, int offset, int count, SendDataOptions public void SendData(byte[] data, int offset, int count, SendDataOptions options, NetworkGamer recipient);options, NetworkGamer recipient);

PacketWriterPacketWriter 를 이용하거나 를 이용하거나 bytebyte 들의 들의 arrayarray 를 전달를 전달특정 특정 NetworkGamerNetworkGamer 에게 전달하거나 에게 전달하거나 broadcastbroadcast

상황에 맞는 상황에 맞는 SendDataOptionsSendDataOptions.None: Unreliable, out-of-order.None: Unreliable, out-of-order

.InOrder: Unreliable, in-order.InOrder: Unreliable, in-order

.Reliable: Reliable, out-of-order.Reliable: Reliable, out-of-order

.ReliableInOrder: Reliable, in-order.ReliableInOrder: Reliable, in-order

LocalNetworkGamerLocalNetworkGamer 가 가 .IsDataAvailable.IsDataAvailable 일 때 일 때 ReceiveData(…) ReceiveData(…) 호출호출

public int ReceiveData(PacketReader data, out NetworkGamer sender);public int ReceiveData(PacketReader data, out NetworkGamer sender);

public int ReceiveData(byte[] data, int offset, out NetworkGamer sender);public int ReceiveData(byte[] data, int offset, out NetworkGamer sender);

Page 22: XNA2.0 Network Programming

Sending & Receiving Data: Code (1)Sending & Receiving Data: Code (1)

PacketWriter PacketWriter 혹은 혹은 byte[] byte[] 이용이용 ..

PacketWriterPacketWriter 는 는 SendData SendData 수행 후 자동으로 수행 후 자동으로 clearclear되므로 하나의 되므로 하나의 instance instance 생성 생성 후 재사용후 재사용 ..

Gamer state dataGamer state data 는 는 SendDataOptions.InOrder SendDataOptions.InOrder 사용사용 ..

GamerJoined, GamerLeft GamerJoined, GamerLeft 등 중요한 이벤트에 대해서등 중요한 이벤트에 대해서는 는 .ReliableInOrder .ReliableInOrder 활용활용 ..

꼭 정보가 필요한 사람에게만 꼭 정보가 필요한 사람에게만 전달하여 전달하여 traffictraffic 을 최소화을 최소화 ..

PacketWriter packetWriter = new PacketWriter();…PlayerData playerData = networkSession.LocalGamers[0].Tag as PlayerData;if ((playerData != null) && (playerData.Ship != null)){ packetWriter.Write((int)World.PacketTypes.ShipData); packetWriter.Write(playerData.Ship.Position); packetWriter.Write(playerData.Ship.Velocity); packetWriter.Write(playerData.Ship.Rotation); packetWriter.Write(playerData.Ship.Life); packetWriter.Write(playerData.Ship.Shield); packetWriter.Write(playerData.Ship.Score); networkSession.LocalGamers[0].SendData(packetWriter, SendDataOptions.InOrder);}

PacketWriter packetWriter = new PacketWriter();…PlayerData playerData = networkSession.LocalGamers[0].Tag as PlayerData;if ((playerData != null) && (playerData.Ship != null)){ packetWriter.Write((int)World.PacketTypes.ShipData); packetWriter.Write(playerData.Ship.Position); packetWriter.Write(playerData.Ship.Velocity); packetWriter.Write(playerData.Ship.Rotation); packetWriter.Write(playerData.Ship.Life); packetWriter.Write(playerData.Ship.Shield); packetWriter.Write(playerData.Ship.Score); networkSession.LocalGamers[0].SendData(packetWriter, SendDataOptions.InOrder);}

void networkSession_GamerJoined(object sender, GamerJoinedEventArgs e){ … if ((networkSession.LocalGamers.Count > 0) && !e.Gamer.IsLocal) { PlayerData playerData=networkSession.LocalGamers[0].Tag as PlayerData; if (playerData != null) { packetWriter.Write((int)World.PacketTypes.PlayerData); … networkSession.LocalGamers[0].SendData(packetWriter, SendDataOptions.ReliableInOrder, e.Gamer); } }}

void networkSession_GamerJoined(object sender, GamerJoinedEventArgs e){ … if ((networkSession.LocalGamers.Count > 0) && !e.Gamer.IsLocal) { PlayerData playerData=networkSession.LocalGamers[0].Tag as PlayerData; if (playerData != null) { packetWriter.Write((int)World.PacketTypes.PlayerData); … networkSession.LocalGamers[0].SendData(packetWriter, SendDataOptions.ReliableInOrder, e.Gamer); } }}

Page 23: XNA2.0 Network Programming

Sending & Receiving Data: Code (2)Sending & Receiving Data: Code (2)

PacketReader PacketReader 혹은 혹은 byte[] byte[] 이용이용 ..

.IsDataAvailable.IsDataAvailable 로 받은 로 받은 packetpacket 이 있는지 확인이 있는지 확인

.ReceiveData.ReceiveData 에 에 packetReaderpacketReader 와 와 out out sendersender 를 인자로 전달하여 를 인자로 전달하여 누가 보냈는지 추적누가 보냈는지 추적 ..

PacketPacket 의 구조에 따라 의 구조에 따라 적절하게 적절하게 PacketRead PacketRead 함수 함수 사용사용 ..

PacketReader packetReader = new PacketReader();…while (networkSession.LocalGamers[0].IsDataAvailable){ NetworkGamer sender; networkSession.LocalGamers[0].ReceiveData(packetReader, out sender);

PacketTypes packetType = (PacketTypes)packetReader.ReadInt32();

switch (packetType) { … case PacketTypes.ShipData: if ((sender != null) && !sender.IsLocal) { UpdateShipData(sender); } break;

case PacketTypes.WorldData: if (!networkSession.IsHost && Initialized) { UpdateWorldData(); } break; … }}

PacketReader packetReader = new PacketReader();…while (networkSession.LocalGamers[0].IsDataAvailable){ NetworkGamer sender; networkSession.LocalGamers[0].ReceiveData(packetReader, out sender);

PacketTypes packetType = (PacketTypes)packetReader.ReadInt32();

switch (packetType) { … case PacketTypes.ShipData: if ((sender != null) && !sender.IsLocal) { UpdateShipData(sender); } break;

case PacketTypes.WorldData: if (!networkSession.IsHost && Initialized) { UpdateWorldData(); } break; … }}

Page 24: XNA2.0 Network Programming

Latency & Packet Loss SimulationLatency & Packet Loss Simulation

SystemLinkSystemLink 에 비해 전송이 원활하지 않은 상황을 에 비해 전송이 원활하지 않은 상황을 simulationsimulation

NeetworkSession NeetworkSession 인스턴스의 속성인스턴스의 속성TimeSpan SimulatedLatencyTimeSpan SimulatedLatency

Float SimulatedPacketLossFloat SimulatedPacketLoss

SendDataOptionsSendDataOptions 들은 들은 simulation simulation 상황에 관계 없이 존중됨상황에 관계 없이 존중됨 ..

일반적인 일반적인 internetinternet 을 통한 을 통한 network game playnetwork game playLatency up to 200msLatency up to 200ms

Packet loss up to 0.1 (10%)Packet loss up to 0.1 (10%)

Page 25: XNA2.0 Network Programming

Ending the GameEnding the Game

NetworkSessionNetworkSession 은 은 NetworkSessionStateNetworkSessionState 를 가진다를 가진다 ..NetworkSessionState.LobbyNetworkSessionState.Lobby

NetworkSessionState.PlayingNetworkSessionState.Playing

NetworkSessionState.EndedNetworkSessionState.Ended

PlayingPlaying 에서 에서 LobbyLobby 로 로 statestate 를 를 transittransit 하기 위해 하기 위해 NetworkSession.EndGame() NetworkSession.EndGame() 호출호출 ..

LobbyLobby 로 돌아갈 수도 있고 로 돌아갈 수도 있고 NetworkSession.Dispose()NetworkSession.Dispose() 를 통해 를 통해 sessionsession 을 종료할 수도 있음을 종료할 수도 있음 ..

다른 다른 playerplayer 에 의해 에 의해 sessionsession 이 종료된 경우 이 종료된 경우 NetworkSessionState.Ended stateNetworkSessionState.Ended state 로 이동로 이동 . . NetworkSession.SessionEnded NetworkSession.SessionEnded 이벤트의 이벤트의 argumentargument 로 로 NetworkSessionEndReasonNetworkSessionEndReason 이 제공이 제공 ..

.ClientSignedOut, .HostEndedSession, .RemovedByHost, .Disconnected.ClientSignedOut, .HostEndedSession, .RemovedByHost, .Disconnected

Page 26: XNA2.0 Network Programming

Ending the Game: CodeEnding the Game: Code

조건에 따라서 조건에 따라서 HostHost 인 인 gamergamer 가 가 .EndGame() .EndGame() 호호출출 ..

NetworkSession.GameEndNetworkSession.GameEndeded 의 의 EventHandlerEventHandler 에서 에서 worldworld 의 제거 및 후처리의 제거 및 후처리 ..

EndGame() EndGame() 후 후 lobbylobby 로 로 돌아갈 것인가 돌아갈 것인가 sessionsession 을 을 종료할 것인가는 종료할 것인가는 designdesign 하기 하기 나름나름 ..

SessionSession 이 종료될 때 이 종료될 때 subscribesubscribe 했던 이벤트를 했던 이벤트를 unsubscribe.unsubscribe.

void networkSession_GameEnded(object sender, GameEndedEventArgs e){ if ((world != null) && !world.GameWon && !world.GameExited) { world.GameExited = true; } if (!IsExiting && ((world == null) || world.GameExited)) { … }}…if (world.GameExited) { … if (world != null) { world.Dispose(); world = null; } if (networkSession != null) { networkSession.Dispose(); networkSession = null; }…}

void networkSession_GameEnded(object sender, GameEndedEventArgs e){ if ((world != null) && !world.GameWon && !world.GameExited) { world.GameExited = true; } if (!IsExiting && ((world == null) || world.GameExited)) { … }}…if (world.GameExited) { … if (world != null) { world.Dispose(); world = null; } if (networkSession != null) { networkSession.Dispose(); networkSession = null; }…}

switch (packetType) {… case PacketTypes.GameWon: … if (networkSession.IsHost && (networkSession.SessionState == NetworkSessionState.Playing)) { networkSession.EndGame(); } break;}

switch (packetType) {… case PacketTypes.GameWon: … if (networkSession.IsHost && (networkSession.SessionState == NetworkSessionState.Playing)) { networkSession.EndGame(); } break;}

Page 27: XNA2.0 Network Programming

DEMODEMO

Xbox360 Xbox360 연결하기연결하기Xbox360Xbox360 용으로 컴파일 및 게임 실행용으로 컴파일 및 게임 실행Cross-platform Cross-platform 매치매치 : Net Rumble: Net Rumble

Page 28: XNA2.0 Network Programming

TIP 1: Control & BalanceTIP 1: Control & Balance

InputInput 을 을 xbox360xbox360 과 과 keyboard/mousekeyboard/mouse 로부터 동시에 받도록 코드 로부터 동시에 받도록 코드 구성구성게임의 성격에 따라 컨트롤의 밸런스에 주의게임의 성격에 따라 컨트롤의 밸런스에 주의

GamePadState gamePad;KeyboardState keyboard;…protected override void Update(GameTime gameTime){ gamePad = GamePad.GetState(PlayerIndex.One); keyboard = Keyboard.GetState();

gamePadUp = gamePad.DPad.Up == ButtonState.Pressed || gamePad.ThumbSticks.Left.Y > 0.5f; gamePadDown = gamePad.DPad.Down == ButtonState.Pressed || gamePad.ThumbSticks.Left.Y < -0.5f; float moveFactorPerSecond = 0.5f * (float)gameTime.ElapsedRealTime.TotalMilliseconds/1000.0f;

if (gamePadUp || keyboard.IsKeyDown(Keys.Up)) rightPaddlePosition -= moveFactorPerSecond; if (gamePadDown || keyboard.IsKeyDown(Keys.Down)) rightPaddlePosition += moveFactorPerSecond; …}

GamePadState gamePad;KeyboardState keyboard;…protected override void Update(GameTime gameTime){ gamePad = GamePad.GetState(PlayerIndex.One); keyboard = Keyboard.GetState();

gamePadUp = gamePad.DPad.Up == ButtonState.Pressed || gamePad.ThumbSticks.Left.Y > 0.5f; gamePadDown = gamePad.DPad.Down == ButtonState.Pressed || gamePad.ThumbSticks.Left.Y < -0.5f; float moveFactorPerSecond = 0.5f * (float)gameTime.ElapsedRealTime.TotalMilliseconds/1000.0f;

if (gamePadUp || keyboard.IsKeyDown(Keys.Up)) rightPaddlePosition -= moveFactorPerSecond; if (gamePadDown || keyboard.IsKeyDown(Keys.Down)) rightPaddlePosition += moveFactorPerSecond; …} ??

Page 29: XNA2.0 Network Programming

TIP 2: SafeAreaTIP 2: SafeArea

화면의 가장자리에 중요한 화면의 가장자리에 중요한 UI UI 정보를 출력하지 않는다정보를 출력하지 않는다 ..VGA VGA 케이블로 연결된 케이블로 연결된 PC PC 모니터모니터 : 100% : 100% 혹은 이하혹은 이하SCART SCART 케이블로 연결된 구형 모니터케이블로 연결된 구형 모니터 : : 약약 92%92%

컴포넌트 케이블로 연결된 컴포넌트 케이블로 연결된 HDTV HDTV 모니터모니터 : 93~95%: 93~95%

일부 구형 모니터일부 구형 모니터 : 80~90%: 80~90%

SafeArea

Page 30: XNA2.0 Network Programming

TIP 3: No Foreign ReferencesTIP 3: No Foreign References

XNA FrameworkXNA Framework 에서 제공하는 에서 제공하는 dlldll 외의 외의 dlldll 들을 함부로 호출하면 들을 함부로 호출하면 Xbox360Xbox360 에서 정상적으로 컴파일에서 정상적으로 컴파일 //실행되지 않을 수 있음실행되지 않을 수 있음 ..

mscorlib.~mscorlib.~

System.~System.~

Microsoft.Xna.Framework.~Microsoft.Xna.Framework.~Microsoft.Xna.Framework.dll (XNA Graphic Engine)Microsoft.Xna.Framework.dll (XNA Graphic Engine)

Microsoft.Xna.Framework.Game.dll (XNA Game Application Model)Microsoft.Xna.Framework.Game.dll (XNA Game Application Model)

Microsoft.Xna.Framework.Conponent.Pipeline.dll (XNA Content Pipeline)Microsoft.Xna.Framework.Conponent.Pipeline.dll (XNA Content Pipeline)

Page 31: XNA2.0 Network Programming

Q & AQ & A

Any questions?Any questions?

Refer to Creators Club (Refer to Creators Club (http://creators.xna.com) & MSDN!!) & MSDN!!

E-mail: [email protected]: [email protected]