游戏开发过程
开发一款自己的游戏。:
- 熟悉c++
- 页面跳转
- 制作动画
- box2d的引用
- box2d的具体 状态
- 问题
cocos2d-x 可以用C++来写的语言
在创建 游戏的时候 对于类的创建。用的是 xxxxx *fff. = xxxxx::create(); 内置的预编译就可以帮助你创建需要的类。
#define CREATE_FUNC(__TYPE__) \
static __TYPE__* create() \
{ \
__TYPE__ *pRet = new(std::nothrow) __TYPE__(); \
if (pRet && pRet->init()) \
{ \
pRet->autorelease(); \
return pRet; \
} \
else \
{ \
delete pRet; \
pRet = nullptr; \
return nullptr; \
} \
}
就是这样的一个预编译。 所以创建之初 在xxx.h中 CREATE_FUNC(xxxxx); 当然要
include “cocos2d.h”
cocos2d-x 的场景跳转
这很简单 ,因为场景的引用多数是由于 导演来控制的。 也就是说用director->runWithScene(startScene);
SceneManager *manager = new SceneManager();
manager->createScene();
director->runWithScene(manager->startScene);
也就是说 需要创建一个中间类调配 场景的变换。所以我创建了一个SceneManager 去管理场景。当场景替换的时候导演进行就可以了。 所以场景跳转也不是什么问题。
Director::getInstance()->replaceScene(gameScene);
cocos2d-x 制作动画
制作动画的问题的难点还是动画的制作 。 比如画一个连续的画 。 最开始我以为需要7个连续的动作就可以形成一幅画。 连贯动作但是后来发现 除了左腿还有右腿 。所以连贯的画至少需要14幅。 才可以出现连贯的动作这一点很困难。
放在程序上实际上也是很简单的。用cocos2d 给的软件。 去综合所有图片去 生成一个plist文件。 然后再读区他,就可以了。
而读取的时候 只需要创建spriteFrameCache. 读区 plist文件 。和 一张综合的png的图片就可以了。
plist 就是那张png图片的坐标。
Vector<SpriteFrame*> spriteFrameVec;
spriteFrameCache = SpriteFrameCache::getInstance();
spriteFrameCache->addSpriteFramesWithFile("Animation10.plist","Animation10.png");
char path[256] ={0};
for(int i=1;i<=6;i++){
sprintf(path, "picture%d.png", i);
log("path = %s", path);
SpriteFrame *pSpriteFrame = spriteFrameCache->getSpriteFrameByName(path);
spriteFrameVec.pushBack(pSpriteFrame);
}
这样就可以把帧动画的坐标传入一个集合中去。 然后用Animation 去遍历集合。然后不断的设置无线循环它。
auto animation = Animation::createWithSpriteFrames(spriteFrameVec, 0.1);
animation->setDelayPerUnit(2.8f / 60.0f);//必须设置否则不会动态播放
animation->setRestoreOriginalFrame(true);//是否回到第一帧
animation->setLoops(-1);//重复次数 (-1:无限循环)
finiteTimeAction = Animate::create(animation);
当想启动的时候只需要 你定义的精灵 sprite runAction(this->getFiniteTimeAction()) ;就可以了。
而关闭。就用this->getSprite()->stopAllActions();
box2d的引用
本来希望用的内置引擎作为基础,制作一个打弹球,但是内置引擎的缺点时,刚体总是不断的晃动,无法再一个位置保持静止。 所以问题很严重。而且很容易两个刚体重合不分开,需要手动制作。 所用用box2d来制作游戏刚体。是正确的。
Size s = Director::getInstance()->getVisibleSize();
//重力参数
b2Vec2 gravity;
gravity.Set(0.0f, -60.0f);
//创建世界
world = new b2World(gravity);
// 允许物体是否休眠
world->SetAllowSleeping(true);
// 开启连续物理测试
world->SetContinuousPhysics(true);
//
retain();
创建世界这很简单,还需要设置一些什么。 这样容易。 世界的变化,遵循重力的变化,你可以设置。而里边刚体的移动变化需要迭代才能变化。
而box2d 的迭代 是迭代世界所有刚体,如果有那么根据物理定律调整它的物理位置。
void ControlLayer::update(float dt){
float timeStep = 0.03f;
int32 velocityIterations = 1;
int32 positionIterations = 8;
//世界的迭代。
world->Step(timeStep, velocityIterations, positionIterations);
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
{
if (b->GetUserData() != nullptr) {
Sprite* sprite = (Sprite*)b->GetUserData();
sprite->setPosition( Vec2( b->GetPosition().x *PTM_RATIO, b->GetPosition().y * PTM_RATIO) );
sprite->setRotation( -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()) );
}
}
}
box2d的具体 状态
现在我所开发的游戏,其实很简单 只是一个像魂斗罗一样的游戏而已。 所以我加上了。 手动摇杆。 和tmx瓦片形成的地图。
为整个地图附上刚体。 虽然把精灵附上刚体,很容易。 但是我在tmx上自动检测瓦片,然后针对瓦片 赴上刚体。 这个很难找到。
在cocos2d-x的书上有写上,在瓦片附上键值对, 再搜索键值对 用精灵的坐标在 那层瓦片上检测。 就可以判断碰撞检测, 但是无法把瓦片赋上物理的刚体。 然后用刚体去碰撞。 查遍了书,好像没有。
然后我就尝试一下找到了瓦片的坐标。然后 遍历所有瓦片。 把瓦片的GID编号,如果是相同的GID 就可以敷上一层属性的刚体。
void MapLayer::initMap(){
int t=0;
_background =_titleMap->getLayer("_background");
for(int i=0;i<=99;i++){
for(int j=0;j<=49;j++){
log("方块!!!!!");
int titleGid = _background->getTileGIDAt(Vec2(i,j));
if(titleGid>0){
CCLOG("i= %d, j = %d",i,j);
CCLog("error buffer:%d" ,titleGid);
if(titleGid == 1){
log("fffffAAAAAA");
auto sprite = Sprite::create("map/collidable_tiles1.jpg");
Vec2 vec0=_background->getPositionAt(Vec2(i,j));
Vec2 vec=Vec2(vec0.x+16, vec0.y+16);
sprite->setTag(t);
CCLOG("vec = %d,,,,,,,vec1 = %d",vec.x,vec.y);
this->addChild(sprite,1);
CCLOG("t = %d",sprite->getTag());
t++;
b2BodyDef bodyDef;
bodyDef.type = b2_staticBody;
bodyDef.position.Set(vec.x/32, (vec.y/32));
b2Body *body=world->CreateBody(&bodyDef);
body->SetUserData(sprite);
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(0.5, 0.5);
b2FixtureDef fixtureDef;
fixtureDef.shape = &dynamicBox;
body->CreateFixture(&fixtureDef);
}
}
}
}
this->setTMXLayer(_background);
}
这带来了很多的问题。
box2d的问题。
- 问题来了 很严重的问题。 就是视角很难移动。首先刚体状态下的地图,就算是移动了MapLayer->setposition(); 刚体还是在固定的坐标。而不会因为整座Layer移动而移动。
- 所以只能用
b2Vec2 b2vec = b2Vec2((this->body->GetPosition().x)-0.2,body->GetPosition().y);
body->SetTransform(b2vec,mapLayer->getRotation());
移动整座刚体来制作视角的移动。 但是这么做了, 就会导致游戏越来越慢, 性能浪费了很多。
因为要移动很多刚体,如果地图很大,同时移动的刚体会更多。 然后导致系统死机。
所以现在为止,我还没遇到什么好办法。 求大神帮忙。 如果地图不移动只移动主角,那么会被限制在一个很小的屏幕中。