Cocos2d-x中文教程:Hello, CCMapView

  • 格式:doc
  • 大小:85.00 KB
  • 文档页数:10

本文由麦可网cocos2d-x http://www.microoh.com/course/19 收集整理,转载请注明出处。 Cocos2d-x中文教程:Hello, CCMapView ;移动平台下的游戏有着区别于其他平台独特的优势,比如携带便捷,基于地理位置的社交,触摸的用户体验等等。 公司正在开发的游戏也利用了地理位置的优势,开发了社交功能,即将附近的玩家显示出来,可以和他们对战,聊天等等,之前的做法是利用cocos2d-x模拟的地图,根据服务器下发的附近玩家的信息显示,光是手势就实现了两种(捏合和滑动这两种在地图上使用最多的手势),但是效果很不好,于是决定使用ios自带的地图框架,与cocos2d-x结合来实现!于是,一个简单的CCMapView诞生了!

1.结构 cocos2d-x 主要特点是跨平台,于是需要定义一个跨平台的接口,然后在不同平台上做不同实现(因为地图UI是基于系统的),今天主要以ios平台为例 回调函数指针: CCMapViewCallback 跨平台接口类: CCMapView ios平台实现: CCMapViewIOS ios平台对MKMapView的封装类: MapView

2.接口: (1)回调函数:CCMapViewCallback 由于objective c和c++通信只能通过指针,所以我们需要定义通信的函数指针类型,于是我定义了两个接口,一个用于系统定位完成之后回调游戏,另一个用于选中地图中的annotation之后回调游戏(这种从ios到游戏的接口可能是比较复杂一点,相当于回调。至于从游戏调用ios则感觉顺畅的多,只要保存一个对应类型的指针即可) #ifndef Cocos2dxMap_MapViewCallback_h #define Cocos2dxMap_MapViewCallback_h

typedef void (*DidLocatedCallback)(double latitude, double longtitude); typedef void (*SelectedPlayerCallback)(unsigned long long playerID);

#endif

(2)跨平台接口类:CCMapView 首先定义了一个附近玩家信息的结构体,这个结构体是我们在地图中显示annotation时需要的信息 typedef struct { unsigned long long mPlayerID; bool mIsMan; std::string mPlayerName; 本文由麦可网cocos2d-x http://www.microoh.com/course/19 收集整理,转载请注明出处。 float mLatitude; float mLongtitude; } CCPlayerInMap;

然后定义了一个简单的接口类,用于封装系统的地图空间,使用了组合的方式,这里利用void*的特点,实现了跨平台class CCMapView: public cocos2d::CCNode {

public: CCMapView(cocos2d::CCRect const& frame); ~CCMapView();

public: void StartLocating(); void StopLocating(); // in meters void SetRadius(float radius); void AddPlayer(CCPlayerInMap const& ccPlayerInMap); void RemoveAllPlayers();

public: void SetPosition(cocos2d::CCPoint const& pos);

public: void SetDidLocatedCallback(DidLocatedCallback callback); void SetSelectedPlayerCallback(SelectedPlayerCallback callback);

private: void* mMapView;

};

3.实现 定义一个类MapView来继承MKMapView并且实现CLLocationManager和MKMapViewDelegate协议(原谅我比较懒并且对objective-c的语法没啥自信吧,分开实现或许是更好的选择。。。),继承MKMapView是为了使用ios原生地图控件,实现CLLocationManager和MKMapViewDelegate协议是为了提高定位和地图显示和交互的回调接口! @interface MapView : MKMapView { // Location CLLocationManager* mLocationManager;

float mRadius; 本文由麦可网cocos2d-x http://www.microoh.com/course/19 收集整理,转载请注明出处。 // for refreshing NSMutableArray* mAnnoArray;

// Data NSMutableArray* mNearbyPlayers;

DidLocatedCallback mDidLocatedCallback; SelectedPlayerCallback mSelectedPlayerCallback;

UIImage* mMaleImage; UIImage* mMaleSelectedImage; UIImage* mFemaleImage; UIImage* mFemaleSelectedImage;

MapAnnotationView* mPreMapAnnotionView; }

@property (retain) CLLocationManager* mLocationManager; @property (readwrite) float mRadius; @property (nonatomic, retain) NSMutableArray* mAnnoArray; @property (nonatomic, retain) NSMutableArray* mAnnoViewArr; @property (nonatomic, retain) NSMutableArray* mNearbyPlayers; @property (nonatomic, readwrite) DidLocatedCallback mDidLocatedCallback; @property (nonatomic, readwrite) SelectedPlayerCallback mSelectedPlayerCallback;

- (void)StartLocating; - (void)StopLocating;

- (void)AddNearbyPlayer:(PlayerInMap *) player; - (void)RemoveAllPlayers;

- (void)HandleTap:(UIGestureRecognizer *)recognizer; @end 在实现中,我运用了一个小技巧,绕过了大头针annotation不设置title就不能接受回调的显示,简单来说就是为每个MapAnnotationView添加一个Tap手势注册,而不是通过其自身的点击事件,其它的写法和一般的地图写法并没有太大差别,如果你的项目中没有这么强的定制性,可以添加一个title,就可以在didSelectedxxx函数中接收到点击回调了!(ps:重点是在定位完成后和点击地图中的annotation调用设置好的函数指针回调游戏) // // MapView.m // Cocos2dxMap // 本文由麦可网cocos2d-x http://www.microoh.com/course/19 收集整理,转载请注明出处。 // Created by quyou on 13-2-22. // //

#import "MapView.h" #import "MapAnnotation.h" #import "CCMapViewCallback.h"

@implementation MapView @synthesize mLocationManager; @synthesize mRadius; @synthesize mAnnoArray; @synthesize mAnnoViewArr; @synthesize mNearbyPlayers; @synthesize mDidLocatedCallback; @synthesize mSelectedPlayerCallback;

- (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code self.mLocationManager = [[[CLLocationManager alloc] init] autorelease]; if (![CLLocationManager locationServicesEnabled]) { NSLog(@"User has opted out of location services!"); return self; }

mMaleImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"male" ofType:@"png"]]; mMaleSelectedImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"male_selected" ofType:@"png"]]; mFemaleImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"female" ofType:@"png"]]; mFemaleSelectedImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"female_selected" ofType:@"png"]];