• Unity3d使用蓝牙(bluetooth)开发IOS点对点网络游戏


    著作权声明:本文由http://www.cnblogs.com/icker 原创,欢迎转载分享。转载时请保留该声明和作者博客链接,谢谢!

      最近使用Unity3d制作的IOS游戏需要加入联网对战功功能,因此使用ObjC语言利用IOS SDK的GameKit.framework的Peer-to-peer Connectivity实现了网络连接,在此分享。

    啥话都不说,先上代码。点我下载工程文件

    类NetWorkP2P,继承自NSObject。提供GKSessionDelegate和GKPeerPickerControllerDelegate的实现。并且利用单例模式实现一个类方法+( NetWorkP2P *) sharedNetWorkP2P;此方法返回一个NetWorkP2P的实例。

    //
    // NetWorkP2P.h
    // P2PTapWar
    //
    // Created by on 11-9-14.
    // Copyright 2011年 __MyCompanyName__. All rights reserved.
    //

    #import <Foundation/Foundation.h>
    #import <GameKit/GameKit.h>

    #define AMIPHD_P2P_SESSION_ID @"amiphd-p2p"
    #define START_GAME_KEY @"startgame"
    #define TIME_KEY @"time"
    #define END_GAME_KEY @"endgame"
    #define TAP_COUNT_KEY @"taps"
    #define TIMES_KEY @"times"

    @interface NetWorkP2P : NSObject<GKSessionDelegate,GKPeerPickerControllerDelegate>{

    UInt32 playerScore;
    UInt32 opponentScore;

    UInt32 playerTimes;
    UInt32 opponentTimes;

    NSString
    *opponentID;
    BOOL actingAsHost;
    GKSession
    *gkSession;
    }
    +( NetWorkP2P *) sharedNetWorkP2P;
    -(void)showPeerPickerController;

    -(void)addTheScore: (UInt32)score;
    -(void)addTimes;

    -(UInt32)getOpponentScore;
    -(UInt32)getPlayerScore;
    -(UInt32)getPlayerTimes;
    -(UInt32)getOpponentTimes;

    -(NSString *)getOpponentID;
    @end

    类NetWorkP2P的实现文件,fileName:NetWorkP2P.m

    //
    // NetWorkP2P.m
    // P2PTapWar
    //
    // Created by on 11-9-14.
    // Copyright 2011年 __MyCompanyName__. All rights reserved.
    //

    #import "NetWorkP2P.h"

    @implementation NetWorkP2P
    +(NetWorkP2P *) sharedNetWorkP2P{
    static NetWorkP2P *sharedNetWorkObject;
    if(!sharedNetWorkObject)
    sharedNetWorkObject
    =[[NetWorkP2P alloc] init];
    return sharedNetWorkObject;
    }

    - (id)init
    {
    self
    = [super init];
    if (self) {
    // Initialization code here.
    }

    return self;
    }
    -(UInt32)getPlayerScore{
    return playerScore;
    }
    -(UInt32)getOpponentScore{
    return opponentScore;
    }
    -(UInt32)getOpponentTimes{
    return opponentTimes;
    }
    -(UInt32)getPlayerTimes{
    return playerTimes;
    }
    -(NSString *)getOpponentID
    {
    return opponentID;
    }
    -(void) showPeerPickerController
    {
    if(!opponentID)
    {
    actingAsHost
    =YES;
    GKPeerPickerController
    *peerPickerContrller=[[GKPeerPickerController alloc] init];
    peerPickerContrller.
    delegate=self;
    peerPickerContrller.connectionTypesMask
    =GKPeerPickerConnectionTypeNearby;
    [peerPickerContrller show];
    }
    }
    -(void)addTheScore:(UInt32)score
    {
    playerScore
    +=score;
    NSMutableData
    *message=[[NSMutableData alloc]init];
    NSKeyedArchiver
    *archiver=[[NSKeyedArchiver alloc]initForWritingWithMutableData:message];
    [archiver encodeInt:playerScore forKey:TAP_COUNT_KEY];
    [archiver finishEncoding];
    GKSendDataMode sendMode
    =GKSendDataUnreliable;
    [gkSession sendDataToAllPeers:message withDataMode:sendMode error:NULL];
    [archiver release];
    [message release];

    }
    -(void)addTimes
    {
    playerTimes
    ++;
    NSMutableData
    *message=[[NSMutableData alloc]init];
    NSKeyedArchiver
    *archiver=[[NSKeyedArchiver alloc] initForWritingWithMutableData:message];
    [archiver encodeInt:playerTimes forKey:TIMES_KEY];
    [archiver finishEncoding];
    GKSendDataMode sendMode
    =GKSendDataUnreliable;
    [gkSession sendDataToAllPeers:message withDataMode:sendMode error:NULL];
    [archiver release];
    [message release];
    }
    #pragma mark game logic

    -(void) initGame{
    playerScore
    =0;
    opponentScore
    =0;
    }
    -(void) hostGame{
    [self initGame];
    NSMutableData
    *message=[[NSMutableData alloc] init];
    NSKeyedArchiver
    *archiver=[[NSKeyedArchiver alloc] initForWritingWithMutableData:message];
    [archiver encodeBool:YES forKey:START_GAME_KEY];
    [archiver finishEncoding];

    NSError
    *sendErr=nil;
    [gkSession sendDataToAllPeers:message withDataMode:GKSendDataReliable error:
    &sendErr];
    if (sendErr) {
    NSLog(
    @"send greeting failed : %@",sendErr);
    }
    [message release];
    [archiver release];
    }
    -(void) joinGame{
    [self initGame];
    }
    -(void) showEndGameAlert{
    }
    -(void) endGame{
    opponentID
    =nil;
    [gkSession disconnectFromAllPeers];
    [self showEndGameAlert];
    }

    #pragma mark GKPeerPickerControllerDelegate methods

    -(GKSession *) peerPickerController:(GKPeerPickerController *)picker sessionForConnectionType:(GKPeerPickerConnectionType)type
    {
    if(!gkSession)
    {
    gkSession
    =[[GKSession alloc] initWithSessionID:AMIPHD_P2P_SESSION_ID displayName:nil sessionMode:GKSessionModePeer];
    gkSession.
    delegate=self;
    }
    return gkSession;
    }
    -(void) peerPickerController:(GKPeerPickerController *) picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session
    {
    NSLog (
    @"connected to peer %@", peerID);
    [session retain];
    // TODO: who releases this?
    [picker dismiss];
    [picker release];
    }
    - (void)peerPickerControllerDidCancel:(GKPeerPickerController *)picker {
    NSLog (
    @"peer picker cancelled");
    [picker release];
    }

    #pragma mark GKSessionDelegate methods

    //START:code.P2PTapWarViewController.peerdidchangestate
    - (void)session:(GKSession *)session peer:(NSString *)peerID
    didChangeState:(GKPeerConnectionState)state {
    switch (state)
    {
    case GKPeerStateConnected:
    [session setDataReceiveHandler: self withContext: nil];
    opponentID
    = peerID;
    actingAsHost
    ? [self hostGame] : [self joinGame];
    break;
    }
    }
    //END:code.P2PTapWarViewController.peerdidchangestate


    //START:code.P2PTapWarViewController.didreceiveconnectionrequestfrompeer
    - (void)session:(GKSession *)session
    didReceiveConnectionRequestFromPeer:(NSString
    *)peerID {
    actingAsHost
    = NO;
    }
    //END:code.P2PTapWarViewController.didreceiveconnectionrequestfrompeer

    - (void)session:(GKSession *)session connectionWithPeerFailed:(NSString *)peerID withError:(NSError *)error {
    NSLog (
    @"session:connectionWithPeerFailed:withError:");
    }

    - (void)session:(GKSession *)session didFailWithError:(NSError *)error {
    NSLog (
    @"session:didFailWithError:");
    }
    #pragma mark receive data from session
    -(void) receiveData: (NSData *) data fromPeer : (NSString *) peerID inSession: (GKSession *) session context:(void *) context{
    NSKeyedUnarchiver
    *unarchiver=[[NSKeyedUnarchiver alloc] initForReadingWithData:data];
    if([unarchiver containsValueForKey:TAP_COUNT_KEY])
    {
    opponentScore
    =[unarchiver decodeIntForKey:TAP_COUNT_KEY];
    }
    if([unarchiver containsValueForKey:TIMES_KEY])
    {
    opponentTimes
    =[unarchiver decodeIntForKey:TIMES_KEY];
    }
    if([unarchiver containsValueForKey:END_GAME_KEY])
    {
    [self endGame];
    }
    if([unarchiver containsValueForKey:START_GAME_KEY])
    {
    [self joinGame];
    }
    [unarchiver release];
    }
    @end

    fileName:NetWorkP2PBinding.m在此文件中实现C语言接口,以方便在UnityScript中调用。

    //NetWorkP2PBinding.mm
    #import "NetWorkP2P.h"

    extern "C"{
    void _showPeerPicker()
    {
    [[NetWorkP2P sharedNetWorkP2P] showPeerPickerController];
    NSLog(
    @"call the mothed _showPeerPicker");
    }

    const char* _getName()
    {
    return [@"fyn" UTF8String];
    }
    int _getOpponentScore()
    {
    return [[NetWorkP2P sharedNetWorkP2P]getOpponentScore];
    }
    int _getPlayerScore()
    {
    return [[NetWorkP2P sharedNetWorkP2P]getPlayerScore];
    }

    void _addTheScore( UInt32 score)
    {
    [[NetWorkP2P sharedNetWorkP2P] addTheScore:score];
    }
    void _addTheTimes()
    {
    [[NetWorkP2P sharedNetWorkP2P] addTimes];
    }
    int _getOpponentTimes()
    {
    return [[NetWorkP2P sharedNetWorkP2P] getOpponentTimes];
    }
    int _getPlayerTimes()
    {
    return [[NetWorkP2P sharedNetWorkP2P] getPlayerTimes];
    }
    const char * _getOpponentID()
    {
    return [[[NetWorkP2P sharedNetWorkP2P ]getOpponentID] UTF8String];
    }
    }

    FileName:P2PBinding.cs 这是在Unity3d中C#脚本,在这里面调用NetWorkP2PBinding.mm实现的C语言方法。

    //P2PBinding.cs

    using UnityEngine;
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;


    public class P2PBinding{
    [DllImport(
    "__Internal")]
    private static extern void _showPeerPicker();

    public static void showPeerPicker()
    {
    if(Application.platform==RuntimePlatform.IPhonePlayer)
    _showPeerPicker();
    }

    [DllImport(
    "__Internal")]
    private static extern int _getOpponentScore();

    [DllImport(
    "__Internal")]
    private static extern int _getOpponentTimes();

    [DllImport(
    "__Internal")]
    private static extern int _getPlayerScore();

    [DllImport(
    "__Internal")]
    private static extern int _getPlayerTimes();

    [DllImport(
    "__Internal")]
    private static extern void _addTheTimes();

    [DllImport(
    "__Internal")]
    private static extern void _addTheScore(int score);

    public static int getOpponentScore()
    {
    if(Application.platform==RuntimePlatform.IPhonePlayer)
    {
    return _getOpponentScore();
    }
    return -1;
    }
    public static int getOpponentTimes()
    {
    if(Application.platform==RuntimePlatform.IPhonePlayer)
    {
    return _getOpponentTimes();
    }
    return -1;
    }
    public static int getPlayerScore()
    {
    if(Application.platform==RuntimePlatform.IPhonePlayer)
    {
    return _getPlayerScore();
    }
    return -1;
    }
    public static int getPlayerTimes()
    {
    if(Application.platform==RuntimePlatform.IPhonePlayer)
    {
    return _getPlayerTimes();
    }
    return -1;
    }
    public static void addTheScore(int score)
    {
    if(Application.platform==RuntimePlatform.IPhonePlayer)
    {
    _addTheScore(score);
    }
    }
    public static void addTheTimes()
    {
    _addTheTimes();
    }
    }

    FileName:GameDate.cs 此文件提供游戏的数据,并保持和NetWorkP2P文件中数据同步,将此文件附加到一个GameObject上。

    using UnityEngine;
    using System.Collections;

    public class GameDate : MonoBehaviour {

    public string opponentID;

    public int playerTimes;
    public int opponentTimes;
    public int playerScore;
    public int opponentScore;

    // Use this for initialization
    void Start () {
    P2PBinding.showPeerPicker();
    }

    // Update is called once per frame
    void Update () {
    opponentTimes
    =P2PBinding.getOpponentTimes();
    opponentScore
    =P2PBinding.getOpponentScore();
    }
    }


  • 相关阅读:
    从Android源码修改cpu信息
    lintcode-->翻转字符串
    lintcode-->哈希函数
    PCP架构设计
    PCP项目立项
    linux下wc功能的简单实现
    goahead3.6.3就基本使用(后台上传信息到html页面),高手请忽略
    四则运算生成器
    快速看完软件工程教材后,我的疑惑
    软件工程学习
  • 原文地址:https://www.cnblogs.com/icker/p/2182326.html
Copyright © 2020-2023  润新知