用Cocos2dx实现超级玛丽,首先用帧循环定时器判断方向,再在类中实现运行以及判断是否能运动。
方向控制
void LayerGame::moveMario(float dt)
{
#ifdef WIN32short key;key = GetKeyState('F');if (key < 0) _marioDir = Common::RIGHT;key = GetKeyState('D');if (key < 0) _marioDir = Common::LEFT;key = GetKeyState('J');if (key < 0)_mario->jump();#endifif (_marioDir==Common::LEFT){//CCLog("left\n");_marioDir=Common::NONE;_mario->moveLeft(dt);}else if(_marioDir==Common::RIGHT){//CCLog("right\n");_marioDir=Common::NONE;_mario->moveRight(dt);}else{//CCLog("stop\n");_menuShow->setTexture(_textureDirNone);_mario->stop();}_mario->moveUp(dt);_mario->moveDown(dt);
}
判断是否能向上,向左,向右,向下运动,利用碰撞检测
bool Mario::canMoveLeft(float dt)
{//judge if mario is out of the mapCCRect rcMario=this->boundingBox();CCPoint ptMario=ccp(rcMario.getMinX(),rcMario.getMinY());CCTMXTiledMap *map=getMap();CCPoint ptMarioInWorld=map->convertToWorldSpace(ptMario);if (ptMarioInWorld.x-dt*_speed<0) {return false;}//judge if partition by a wallCCPoint pt[3];pt[0] = ccp(rcMario.getMinX() - dt*_speed, rcMario.getMidY());pt[1] = ccp(rcMario.getMinX() - dt*_speed, rcMario.getMinY());pt[2] = ccp(rcMario.getMinX() - dt*_speed, rcMario.getMaxY());//transform position,change pt into tile and get gid to decide whether be stoped by wallfor(int i=0;i<3;i++){if (pt[i].y >= map->getContentSize().height)continue;CCPoint ptTile=Common::Point2Tile(map,pt[i]);//wall water pipe and floorstatic const char* layerName[3] = { "block", "pipe", "land" };for(int j=0;j<3;j++){CCTMXLayer *layer=map->layerNamed(layerName[j]);int gid=layer->tileGIDAt(ptTile);if (gid!=0){return false;}}}return true;
}
bool Mario::canMoveRight(float dt)
{CCRect rcMario = boundingBox();CCTMXTiledMap* map = getMap();CCPoint pt[3];pt[0] = ccp(rcMario.getMaxX() + dt*_speed, rcMario.getMidY());pt[1] = ccp(rcMario.getMaxX() + dt*_speed, rcMario.getMinY());pt[2] = ccp(rcMario.getMaxX() + dt*_speed, rcMario.getMaxY());// 坐标转换,将pt转化成地图格子坐标,然后获取gid,判断gid是不是被阻挡for (int i = 0; i < 3; ++i){if (pt[i].y >= map->getContentSize().height)continue;CCPoint ptTile = Common::Point2Tile(map, pt[i]);// 水管、砖头,地板static const char* layerName[3] = { "block", "pipe", "land" };for (int j = 0; j < 3; ++j){CCTMXLayer* layer = map->layerNamed(layerName[j]);int gid = layer->tileGIDAt(ptTile);if (gid != 0){return false;}}}return true;
}
bool Mario::canMoveDown(float dt)
{CCRect rcMario = boundingBox();CCTMXTiledMap* map = getMap();CCPoint pt[3];//dt*_speedDownpt[0] = ccp(rcMario.getMidX(), rcMario.getMinY() - dt*_speedDown);pt[1] = ccp(rcMario.getMinX(), rcMario.getMinY() - dt*_speedDown);pt[2] = ccp(rcMario.getMaxX(), rcMario.getMinY() - dt*_speedDown);if (pt[0].y >= map->getContentSize().height)return true;// 坐标转换,将pt转化成地图格子坐标,然后获取gid,判断gid是不是被阻挡for (int i = 0; i < 3; ++i){CCPoint ptTile = Common::Point2Tile(map, pt[i]);// 水管、砖头,地板static const char* layerName[3] = { "block", "pipe", "land" };for (int j = 0; j < 3; ++j){CCTMXLayer* layer = map->layerNamed(layerName[j]);int gid = layer->tileGIDAt(ptTile);if (gid != 0){// 微调CCPoint ptLB = Common::Tile2PointLB(map, ptTile+ccp(0, -1));this->setPositionY(ptLB.y);return false;}}}return true;
}
bool Mario::canMoveUp(float dt)
{CCRect rcMario = boundingBox();CCTMXTiledMap* map = getMap();CCPoint pt[3];pt[0] = ccp(rcMario.getMidX(), rcMario.getMaxY() + dt*_speedUp);pt[1] = ccp(rcMario.getMinX(), rcMario.getMaxY() + dt*_speedUp);pt[2] = ccp(rcMario.getMaxX(), rcMario.getMaxY() + dt*_speedUp);if (pt[0].y >= map->getContentSize().height)return true;// 坐标转换,将pt转化成地图格子坐标,然后获取gid,判断gid是不是被阻挡for (int i = 0; i < 3; ++i){CCPoint ptTile = Common::Point2Tile(map, pt[i]);// 水管、砖头,地板static const char* layerName[3] = { "block", "pipe", "land" };for (int j = 0; j < 3; ++j){CCTMXLayer* layer = map->layerNamed(layerName[j]);int gid = layer->tileGIDAt(ptTile);if (gid != 0){// 微调CCPoint ptLB = Common::Tile2PointLB(map, ptTile);this->setPositionY(ptLB.y);return false;}}}return true;
}
运行实现
void Mario::moveLeft(float dt)
{if (_dirRun!=Common::LEFT){_dirRun=Common::LEFT;_dirFace=Common::LEFT;updateStatus();}if (!canMoveLeft(dt))return;Common::moveNode(this,ccp(-dt*_speed,0));//scroll mapCCNode *map=this->getParent();CCPoint ptWorld=map->convertToWorldSpace(this->getPosition());if (ptWorld.x<winSize.width/2&&map->getPositionX()<0){Common::moveNode(map,ccp(dt*_speed,0));}
}void Mario::moveRight(float dt)
{if (_dirRun!=Common::RIGHT){_dirRun=Common::RIGHT;_dirFace=Common::RIGHT;updateStatus();}if (!canMoveRight(dt))return;Common::moveNode(this,ccp(dt*_speed,0));//scroll mapCCNode *map=this->getParent();CCPoint ptWorld=map->convertToWorldSpace(this->getPosition());if (ptWorld.x>winSize.width/2){Common::moveNode(map,ccp(-dt*_speed,0));}
}void Mario::moveUp(float dt)
{if (_speedUp<=0){return;}if (!canMoveUp(dt)){// 反弹效果_speedDown = _speedUp;_speedUp = 0; // 不继续上升了return;}Common::moveNode(this,ccp(0,dt*_speedUp));_speedUp-=_speedAcc;//_speedDown=_speedUp;
}
void Mario::moveDown(float dt)
{if(_speedUp<=0){if (canMoveDown(dt)){if (_bFly==false){_bFly=true;updateStatus();}Common::moveNode(this,ccp(0,-dt*_speedDown));_speedDown+=_speedAcc;}else{if (_bFly){_bFly = false;_speedDown = _speedAcc;updateStatus();}}}}void Mario::stop()
{if (_dirRun!=Common::NONE){_dirRun=Common::NONE;updateStatus();}
}
void Mario::jump()
{static int i=0;CCLog("speed%d=%d",++i,_speedUp);if (_bFly)return;_speedUp=300;_bFly=true;updateStatus();
}
运行状态机,控制运行时的动画
void Mario::updateStatus()
{stopAllActions();if (_bFly){if (_dirFace==Common::LEFT){setDisplayFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("SmallJumpLeft"));}else if(_dirFace==Common::RIGHT){setDisplayFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("SmallJumpRight"));}return;}if (_dirRun==Common::LEFT){this->runAction(CCRepeatForever::create(CCAnimate::create(CCAnimationCache::sharedAnimationCache()->animationByName("SmallWalkLeft"))));}else if (_dirRun==Common::RIGHT){this->runAction(CCRepeatForever::create(CCAnimate::create(CCAnimationCache::sharedAnimationCache()->animationByName("SmallWalkRight"))));}else{if (_dirFace==Common::LEFT){this->setDisplayFrameWithAnimationName("SmallWalkLeft",0);}else if(_dirFace==Common::RIGHT){this->setDisplayFrameWithAnimationName("SmallWalkRight",0);}}
}
注:在实现这个功能的时候,由于把等于写成赋值,发生了许多灵异的错误,要小心啊,等于与赋值。