实现超级玛丽上下左右运动
2016-03-09 20:53
225 查看
用Cocos2dx实现超级玛丽,首先用帧循环定时器判断方向,再在类中实现运行以及判断是否能运动。
方向控制
void LayerGame::moveMario(float dt) { #ifdef WIN32 short 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(); #endif if (_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 map CCRect 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 wall CCPoint 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 wall for(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 floor 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::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*_speedDown pt[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 map CCNode *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 map CCNode *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); } } }
注:在实现这个功能的时候,由于把等于写成赋值,发生了许多灵异的错误,要小心啊,等于与赋值。
运行结果
相关文章推荐
- HDU-1312-Red and Black
- 两个栈实现队列
- ProcessOn -在线绘图
- 使用脚本编写 Vim 编辑器,第 4 部分: 字典
- Python之多线程学习
- C Primer Plus外藩(一)---枚举
- Ubuntu14.04配置记录
- 采集项目记录1
- [绍棠] Xcode把应用程序打包成ipa
- 使用脚本编写 Vim 编辑器,第 3 部分: 内置列表
- 创建有颜色的Layer
- 如何为ESXI安装网卡驱动
- online_judge_1518
- Eclipse中定位至某一行的快捷键
- JS中的Json和String的转换
- You Only Look Once: Unified, Real-Time Object Detection
- HttpServletRequest对象方法的用法
- 13. SpringMVC 文件上传与下载
- 【转】人生如梦游戏间,RPG游戏开源开发讲座(JAVA篇)[2]——踏破红尘
- 使用脚本编写 Vim 编辑器,第 2 部分: 用户定义函数