今天我们来教妳有关「cocos2dx游戏开发教程」cocos2dx菜鸟教程,以下2个关于欧冠皇马的观点希望能帮助到您找到想要的答案。
如何在Cocos2d-x中集成安卓版微信SDK
本文贡献者:【荒﹫人说梦﹌】, 疑问关键字:cocos2dx游戏开发教程, 下面就让重庆云诚科技小编为你解答,希望本文能找到您要的答案!
答如何在Cocos2d-x中集成安卓版微信SDK
方法/步骤
1.如果能在Cocos2d-x中集成微信SDK,让游戏能分享给好友或者朋友圈,那对游戏推广将会是非常有利的。好了,本文就是手把手地教大伙如何在Cocos2d-x中集成微信SDK。
先看下效果分享给好友,点击即可跳转链接:
分享到朋友圈,点击即可跳转链接:
2.环境
OS: Mac OSX
IDE: Xcode v5.11 and Eclipse ADT v22.3
Android SDK:4.3
Adnroid NDK:r9d
Cocos2d-x 3.2release
3.创建Cocos2d-x工程这里不再详述,网上的资料多如牛毛了。这里我按自己习惯的方式来。(1)命令行创建Cocos2dxWechat项目
$ cocos new -p com.fusijie.cocos2dxwechat -l cpp -d . Cocos2dxWechat
(2)交叉编译生成so文件
$ cd Cocos2dxWechat/proj.android/
$ ./build_native.py
(3)导入Eclipse生成APK导入libcocos2dx项目和Cocos2dxWechat项目到Eclipse中。在真机中成功运行Cocos2dxWechat.apk。4.申请创建微信应用这一步主要是在微信开放平台上申请创建移动应用,获取AppID。微信开放平台的网址(1)注册帐号,进入管理中心,点击创建移动应用。(2)第一步是填写应用名,描述,图标等等。如下图。
(3)填写应用官网,勾选Android应用,填写签名,包名等等。如下图。
注意:这里需要特别注意的是应用签名这一项。在第三步的时候,真机中成功运行Cocos2dxWechat.apk之后,我们需要从微信开放平台下载一个签名生成软件GenSignature
安装签名生成后,打开软件输入游戏包名获取即可。
这里的签名和游戏的包名和keystore是相关联的,如果修改了包名或者更换了keystore,必须同步更新微信开放平台管理中心的信息,防止失效。本示例采用的是debug签名。在完成工作后,提交审核即可。说是7天,实际上一般1~2天就审核过了。5.集成微信SDK刚才都是铺垫,这里开始才是进入主题了。要在Cocos2d-x调用微信安卓SDK,Jni跑不掉的。这里只演示如何进行分享到朋友圈和分享给好友,微信SDK还有很多高级的功能,如支付,收藏等等接口,有需要自行参考文档(移动应用开发)进行开发。
这里主要分成3部分来解释:
微信SDK下载,jar包导入
Android代码
C++代码
(1)下载微信SDK
(2)打开下载的Android_SDK.zip。解压,将lib目录下的libammsdk.jar拷到Cocos2dxWechat项目下的libs目录。(3)右键单击工程,选择Build Path中的Configure Build Path.,选中Libraries这个tab,并通过Add Jars.导入工程libs目录下的libammsdk.jar文件。
(4)在AppActivity中添加成员变量
private static final String APP_ID = "wx81115d2aa55710fa";//AppID,从第四步获取
private static IWXAPI api;//微信API接口
private static AppActivity instance;//类静态实例,为了方便后面静态函数的调用
(5)注册到微信打开AppActivity,在onCreate()中调用regToWX()注册到微信
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
instance = this;
regToWX();
}
private void regToWX(){
api = WXAPIFactory.createWXAPI(this, APP_ID, true);
api.registerApp(APP_ID);
}
(6)由于这里采用的分享示例传递了一张icon,所以需要额外的一个bitmap的解析类Util类,这个类可以到微信官方SDK demo下载,也可以在本示例中下载(早期的SDK版本这个类是集成在微信SDK中)。icon放在res目录下的drawable目录,我这里偷个懒直接使用了应用icon。(7)分享给好友
public static void sendMsgToFriend(){
if(api.openWXApp())
{
WXWebpageObject webpage = new WXWebpageObject();
webpage.webpageUrl = "";
WXMediaMessage msg = new WXMediaMessage(webpage);
msg.title = "Tittle";
msg.description = "Description";
Bitmap thumb = BitmapFactory.decodeResource(instance.getResources(), R.drawable.icon);
msg.thumbData = Util.bmpToByteArray(thumb, true);
SendMessageToWX.Req req = new SendMessageToWX.Req();
req.transaction = buildTransaction("webpage");
req.message = msg;
req.scene = SendMessageToWX.Req.WXSceneSession;
api.sendReq(req);
}
else
{
Toast.makeText(instance, "未安装微信", Toast.LENGTH_SHORT).show();
}
}
(8)分享到朋友圈
public static void sendMsgToTimeLine(){
if(api.openWXApp())
{
if(api.getWXAppSupportAPI() >= 0x21020001)
{
WXWebpageObject webpage = new WXWebpageObject();
webpage.webpageUrl = "";
WXMediaMessage msg = new WXMediaMessage(webpage);
msg.title = "Tittle";
msg.description = "Description";
Bitmap thumb = BitmapFactory.decodeResource(instance.getResources(), R.drawable.icon);
msg.thumbData = Util.bmpToByteArray(thumb, true);
SendMessageToWX.Req req = new SendMessageToWX.Req();
req.transaction = buildTransaction("webpage");
req.message = msg;
req.scene = SendMessageToWX.Req.WXSceneTimeline;
api.sendReq(req);
}
else{
Toast.makeText(instance, "微信版本过低", Toast.LENGTH_SHORT).show();
}
}
else
{
Toast.makeText(instance, "未安装微信", Toast.LENGTH_SHORT).show();
}
}
其中buildTransaction()用于生成一个唯一的会话标识符。
private static String buildTransaction(final String type) {
return (type == null) String.valueOf(System.currentTimeMillis()) : type + System.currentTimeMillis();
}
代码不难,所以不再逐行解释,可以参考SDK文档。(9)JNI调用在Classes目录下新建一个WeixinShare类,主要包含2个静态函数:
void WeiXinShare::sendToFriend()
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) //判断当前是否为Android平台
JniMethodInfo minfo;
bool isHave = JniHelper::getStaticMethodInfo(minfo,"org/cocos2dx/cpp/AppActivity","sendMsgToFriend", "()V");
if (!isHave) {
log("jni:sendMsgToFriend is null");
}else{
//调用此函数
minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID);
}
#endif
}
void WeiXinShare::sendToTimeLine()
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) //判断当前是否为Android平台
JniMethodInfo minfo;
bool isHave = JniHelper::getStaticMethodInfo(minfo,"org/cocos2dx/cpp/AppActivity","sendMsgToTimeLine", "()V");
if (!isHave) {
log("jni:sendMsgToTimeLine is null");
}else{
//调用此函数
minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID);
}
#endif
}
(10)Cocos2d-x使用这个就比较简单了,只要包含这个WeiXinShare类,调用这两个静态函数即可。
void HelloWorld::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
//WeiXinShare::sendToFriend();
WeiXinShare::sendToTimeLine();
#endif
}
(11)Android.mk的修改最后不要忘记修改Android.mk文件。
复制代码
LOCAL_SRC_FILES := hellocpp/main.cpp \
//Classes/AppDelegate.cpp \
//Classes/HelloWorldScene.cpp \
//Classes/WeiXinShare.cpp
(12)重新交叉编译,打包为APK即可6.总结本文写的比较详细,但是也忽略了比如如何接收微信的请求及返回值的说明以及如何进行混淆等等,算是一个初级教程吧。主要是面向对jni调用,第三方安卓sdk集成不太了解的朋友。这里虽然只是针对微信sdk的部分功能集成进行说明,但是道理都是共通的,如何集成微博分享,如何集成第三方广告等等,用类似的方法都可以实现。
以上就是重庆云诚科技小编解答(荒﹫人说梦﹌)分析关于“如何在Cocos2d-x中集成安卓版微信SDK”的答案,接下来继续为你详解体育用户(双彭丹)解答“如何基于cocos2dx3.x实现A星寻路算法”的一些相关解答,希望能解决你的问题!

如何基于cocos2dx3.x实现A星寻路算法
本文贡献者:【双彭丹】, 疑问关键字:cocos2dx游戏开发教程, 下面就让重庆云诚科技小编为你解答,希望本文能找到您要的答案!
答在学习本篇教程之前,如果你有cocos2d-x的开发经验,将会有所帮助。如果没有也没关系,因为你可以将这里讲解的例子迁移到其他的语言或者框架中。
找到到达你键盘的最短路径,开始吧!
Maze猫
首先介绍下我们将要在本篇教程中开发的简单游戏。
前往下载本篇教程的 工程代码 。编译运行工程,你将看到以下画面。
在这款游戏中,你扮演着一只小偷猫,在一个由危险的狗守护着的地牢里小心穿行。如果你试图穿过一只狗,他会把你吃掉 – 除非你可以用骨头去贿赂它!
所以在这款游戏中,你的任务是尝试以正确的顺序捡起骨头,然后 寻找路线 穿过狗逃离。
注意到猫只能水平或者垂直的移动(例如不能斜线移动),并且会从一个方块的中心点移动到另一个中心点。每个方块既可以是可通行的也可以是不可通行的。
尝试下这款游戏,看看你能否找到出路!建议你阅读代码以熟悉它的原理。这是一款相当普通的方块-地图式游戏,我们会在接下来的教程中修改它并使用上A星寻路算法。
Maze猫和A星概览
正如你所看到的,当你点击地图某处时,猫会沿着你点击的方向跳到相邻的方块上。
我们想对程序做修改,让猫持续的往你点击的方块方向前进,就像许多RPGs或者point-and-click冒险类游戏。
让我们看下控制触摸事件代码的工作原理。如果你打开HelloWorldScene.cpp文件,你将看到像下面这样去实现触摸操作:
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches( true );
listener->onTouchBegan = [ this ](Touch *touch, Event *event){
if (_gameOver)
{
return false ;
}
Point touchLocation = _tileMap->convertTouchToNodeSpace(touch);
_cat->moveToward(touchLocation);
return true ;
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this );
你可以看到这里只是对猫精灵调用了一个方法,让猫在方块地图上往你点击的地方移动。
我们现在要做的是修改在CatSprite.m文件中的以下方法,寻找到达该点的最短路径,并且开始前进:
void CatSprite::moveToward( const Point &target)
{
}
创建ShortestPathStep类
我们开始创建一个内部类,代表路径上的一步操作。在这种情况下,它是一个方块和由A星算法计算出来的的F,G和H scores。
class ShortestPathStep : public cocos2d::Object
{
public :
ShortestPathStep();
~ShortestPathStep();
static ShortestPathStep *createWithPosition( const cocos2d::Point &pos);
bool initWithPosition( const cocos2d::Point &pos);
int getFScore() const ;
bool isEqual( const ShortestPathStep *other) const ;
std::string getDescription() const ;
CC_SYNTHESIZE(cocos2d::Point, _position, Position);
CC_SYNTHESIZE( int , _gScore, GScore);
CC_SYNTHESIZE( int , _hScore, HScore);
CC_SYNTHESIZE(ShortestPathStep*, _parent, Parent);
};
现在添加以下代码到CatSprite.cpp文件的顶部。
CatSprite::ShortestPathStep::ShortestPathStep() :
_position(Point::ZERO),
_gScore(0),
_hScore(0),
_parent(nullptr)
{
}
CatSprite::ShortestPathStep::~ShortestPathStep()
{
}
CatSprite::ShortestPathStep *CatSprite::ShortestPathStep::createWithPosition( const Point &pos)
{
ShortestPathStep *pRet = new ShortestPathStep();
if (pRet && pRet->initWithPosition(pos))
{
pRet->autorelease();
return pRet;
}
else
{
CC_SAFE_DELETE(pRet);
return nullptr;
}
}
bool CatSprite::ShortestPathStep::initWithPosition( const Point &pos)
{
bool bRet = false ;
do
{
this ->setPosition(pos);
bRet = true ;
} while (0);
return bRet;
}
int CatSprite::ShortestPathStep::getFScore() const
{
return this ->getGScore() + this ->getHScore();
}
bool CatSprite::ShortestPathStep::isEqual( const CatSprite::ShortestPathStep *other) const
{
return this ->getPosition() == other->getPosition();
}
std::string CatSprite::ShortestPathStep::getDescription() const
{
return StringUtils::format( "pos=[%.0f;%.0f] g=%d h=%d f=%d" ,
this ->getPosition().x, this ->getPosition().y,
this ->getGScore(), this ->getHScore(), this ->getFScore());
}
正如所见,这是一个很简单的类,记录了以下内容:
- 方块的坐标
- G值(记住,这是开始点到当前点的方块数量)
- H值(记住,这是当前点到目标点的方块估算数量)
- Parent是它的上一步操作
- F值,这是方块的和值(它是G+H的值)
这里定义了getDescription方法,以方便调试。创建了isEquals方法,当且仅当两个ShortestPathSteps的方块坐标相同时,它们相等(例如它们代表着相同的方块)。
创建Open和Closed列表
打开CatSprite.h文件,添加如下代码:
cocos2d::Vector _spOpenSteps;
cocos2d::Vector _spClosedSteps;
检查开始和结束点
重新实现moveToward方法,获取当前方块坐标和目标方块坐标,然后检查是否需要计算一条路径,最后测试目标方块坐标是否可行走的(在这里只有墙壁是不可行走的)。打开CatSprite.cpp文件,修改moveToward方法,为如下:
void CatSprite::moveToward( const Point &target)
{
Point fromTileCoord = _layer->tileCoordForPosition( this ->getPosition());
Point toTileCoord = _layer->tileCoordForPosition(target);
if (fromTileCoord == toTileCoord)
{
CCLOG( "You're already there! :P" );
return ;
}
if (!_layer->isValidTileCoord(toTileCoord) || _layer->isWallAtTileCoord(toTileCoord))
{
SimpleAudioEngine::getInstance()->playEffect( "hitWall.wav" );
return ;
}
CCLOG( "From: %f, %f" , fromTileCoord.x, fromTileCoord.y);
CCLOG( "To: %f, %f" , toTileCoord.x, toTileCoord.y);
}
编译运行,在地图上进行点击,如果不是点击到墙壁的话,可以在控制台看到如下信息:
From: 24.000000, 0.000000
To: 20.000000, 0.000000
其中 **From** 就是猫的方块坐标,**To**就是所点击的方块坐标。
实现A星算法
根据算法,第一步是添加当前坐标到open列表。还需要三个辅助方法:
- 一个方法用来插入一个ShortestPathStep对象到适当的位置(有序的F值)
- 一个方法用来计算从一个方块到相邻方块的移动数值
- 一个方法是根据"曼哈顿距离"算法,计算方块的H值
打开CatSprite.cpp文件,添加如下方法:
void CatSprite::insertInOpenSteps(CatSprite::ShortestPathStep *step)
{
int stepFScore = step->getFScore();
ssize_t count = _spOpenSteps.size();
ssize_t i = 0;
for (; i < count; ++i)
{
if (stepFScore <= _spOpenSteps.at(i)->getFScore())
{
break ;
}
}
_spOpenSteps.insert(i, step);
}
int CatSprite::computeHScoreFromCoordToCoord( const Point &fromCoord, const Point &toCoord)
{
// 忽略了可能在路上的各种障碍
return abs(toCoord.x - fromCoord.x) + abs(toCoord.y - fromCoord.y);
}
int CatSprite::costToMoveFromStepToAdjacentStep( const ShortestPathStep *fromStep, const ShortestPathStep *toStep)
{
// 因为不能斜着走,而且由于地形就是可行走和不可行走的成本都是一样的
// 如果能够对角移动,或者有沼泽、山丘等等,那么它必须是不同的
return 1;
}
接下来,需要一个方法去获取给定方块的所有相邻可行走方块。因为在这个游戏中,HelloWorld管理着地图,所以在那里添加方法。打开HelloWorldScene.cpp文件,添加如下方法:
PointArray *HelloWorld::walkableAdjacentTilesCoordForTileCoord( const Point &tileCoord) const
{
PointArray *tmp = PointArray::create(4);
// 上
Point p(tileCoord.x, tileCoord.y - 1);
if ( this ->isValidTileCoord(p) && ! this ->isWallAtTileCoord(p))
{
tmp->addControlPoint(p);
}
// 左
p.setPoint(tileCoord.x - 1, tileCoord.y);
if ( this ->isValidTileCoord(p) && ! this ->isWallAtTileCoord(p))
{
tmp->addControlPoint(p);
}
// 下
p.setPoint(tileCoord.x, tileCoord.y + 1);
if ( this ->isValidTileCoord(p) && ! this ->isWallAtTileCoord(p))
{
tmp->addControlPoint(p);
}
// 右
p.setPoint(tileCoord.x + 1, tileCoord.y);
if ( this ->isValidTileCoord(p) && ! this ->isWallAtTileCoord(p))
{
tmp->addControlPoint(p);
}
return tmp;
}
可以继续CatSprite.cpp中的moveToward方法了,在moveToward方法的后面,添加如下代码:
bool pathFound = false ;
_spOpenSteps.clear();
_spClosedSteps.clear();
// 首先,添加猫的方块坐标到open列表
this ->insertInOpenSteps(ShortestPathStep::createWithPosition(fromTileCoord));
do
{
// 得到最小的F值步骤
// 因为是有序列表,第一个步骤总是最小的F值
ShortestPathStep *currentStep = _spOpenSteps.at(0);
// 添加当前步骤到closed列表
_spClosedSteps.pushBack(currentStep);
// 将它从open列表里面移除
// 需要注意的是,如果想要先从open列表里面移除,应小心对象的内存
_spOpenSteps.erase(0);
// 如果当前步骤是目标方块坐标,那么就完成了
if (currentStep->getPosition() == toTileCoord)
{
pathFound = true ;
ShortestPathStep *tmpStep = currentStep;
CCLOG( "PATH FOUND :" );
do
{
CCLOG( "%s" , tmpStep->getDescription().c_str());
tmpStep = tmpStep->getParent(); // 倒退
} while (tmpStep); // 直到没有上一步
_spOpenSteps.clear();
_spClosedSteps.clear();
break ;
}
// 得到当前步骤的相邻方块坐标
PointArray *adjSteps = _layer->walkableAdjacentTilesCoordForTileCoord(currentStep->getPosition());
for (ssize_t i = 0; i < adjSteps->count(); ++i)
{
ShortestPathStep *step = ShortestPathStep::createWithPosition(adjSteps->getControlPointAtIndex(i));
// 检查步骤是不是已经在closed列表
if ( this ->getStepIndex(_spClosedSteps, step) != -1)
{
continue ;
}
// 计算从当前步骤到此步骤的成本
int moveCost = this ->costToMoveFromStepToAdjacentStep(currentStep, step);
// 检查此步骤是否已经在open列表
ssize_t index = this ->getStepIndex(_spOpenSteps, step);
// 不在open列表,添加它
if (index == -1)
{
// 设置当前步骤作为上一步操作
step->setParent(currentStep);
// G值等同于上一步的G值 + 从上一步到这里的成本
step->setGScore(currentStep->getGScore() + moveCost);
// H值即是从此步骤到目标方块坐标的移动量估算值
step->setHScore( this ->computeHScoreFromCoordToCoord(step->getPosition(), toTileCoord));
// 按序添加到open列表
this ->insertInOpenSteps(step);
}
else
{
// 获取旧的步骤,其值已经计算过
step = _spOpenSteps.at(index);
// 检查G值是否低于当前步骤到此步骤的值
if ((currentStep->getGScore() + moveCost) < step->getGScore())
{
// G值等同于上一步的G值 + 从上一步到这里的成本
step->setGScore(currentStep->getGScore() + moveCost);
// 因为G值改变了,F值也会跟着改变
// 所以为了保持open列表有序,需要将此步骤移除,再重新按序插入
// 在移除之前,需要先保持引用
step->retain();
// 现在可以放心移除,不用担心被释放
_spOpenSteps.erase(index);
// 重新按序插入
this ->insertInOpenSteps(step);
// 现在可以释放它了,因为open列表应该持有它
step->release();
}
}
}
} while (_spOpenSteps.size() > 0);
if (!pathFound)
{
SimpleAudioEngine::getInstance()->playEffect( "hitWall.wav" );
}
添加以下方法:
ssize_t CatSprite::getStepIndex( const cocos2d::Vector &steps, const CatSprite::ShortestPathStep *step)
{
for (ssize_t i = 0; i < steps.size(); ++i)
{
if (steps.at(i)->isEqual(step))
{
return i;
}
}
return -1;
}
编译运行,在地图上进行点击,如下图所示:
From: 24.000000, 0.000000
To: 23.000000, 3.000000
PATH FOUND :
pos=[23;3] g=10 h=0 f=10
pos=[22;3] g=9 h=1 f=10
pos=[21;3] g=8 h=2 f=10
pos=[20;3] g=7 h=3 f=10
pos=[20;2] g=6 h=4 f=10
pos=[20;1] g=5 h=5 f=10
pos=[21;1] g=4 h=4 f=8
pos=[22;1] g=3 h=3 f=6
pos=[23;1] g=2 h=2 f=4
pos=[24;1] g=1 h=3 f=4
pos=[24;0] g=0 h=0 f=0
注意该路径是从后面建立的,所以必须从下往上看猫选择了哪条路径。
跟随路径前进
现在已经找到了路径,只需让猫跟随前进即可。需要创建一个数组去存储路径,打开CatSprite.h文件,添加如下代码:
cocos2d::Vector _shortestPath;
打开CatSprite.cpp文件,更改moveToward方法,注释掉语句**bool pathFound = false**;,如下:
//bool pathFound = false;
替换语句**pathFound = true;**为如下:
//pathFound = true;
this ->constructPathAndStartAnimationFromStep(currentStep);
并且注释掉下方的调试语句:
//ShortestPathStep *tmpStep = currentStep;
//CCLOG("PATH FOUND :");
//do
//{
// CCLOG("%s", tmpStep->getDescription().c_str());
// tmpStep = tmpStep->getParent(); // 倒退
/
最后,你如何评价[cocos2dx游戏开发教程]?欢迎下面互动!想了解更多精彩内容,快来关注本站吧。
推荐文章:
本文由网上采集发布,不代表我们立场,转载联系作者并注明出处:https://www.cqycseo.com/zixun/296.html
