學習:cocos2d-x手機游戲開發(四)簡單實現人物移動代碼,cocos2d-2.1beta3-x-2.1.1 vs2010


HelloWorldScene.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

#include "SimpleAudioEngine.h"

class HelloWorld : public cocos2d::CCLayer
{
public:
    virtual bool init();  

 
    static cocos2d::CCScene* scene();
    

    void menuCloseCallback(CCObject* pSender);

    // implement the "static node()" method manually
    CREATE_FUNC(HelloWorld);
    virtual ~HelloWorld();  
    cocos2d::CCTMXTiledMap *map;
    cocos2d::CCAnimation *walkAnimations[4];
    cocos2d::CCSprite *heroSprite;
    typedef enum{
        kDown,
        kLeft,
        kRight,
        kUp,
        kTotal
    }HeroDirection;
    cocos2d::CCAnimation *createAnimationByDirection(HeroDirection direction);
       
    void menuCallbackMove(CCObject *pSender);          
     
    void setFaceDirection(HeroDirection direction);          
         
    void onWalkDone(CCNode *pTarget, void *data);              
         
    bool isHeroWalking;          
          
    cocos2d::CCPoint positionForTileCoord(cocos2d::CCPoint tileCoord);          
          
    void setSceneScrollPosition(cocos2d::CCPoint position);          
          
    void update(float dt);          
         
    cocos2d::CCPoint tilecoordForPosition(cocos2d::CCPoint position);          
          
    typedef enum{
        kNone,          
        kWall,          
        kEnemy,
    }CollisionType;          
          
    CollisionType checkCollision(cocos2d::CCPoint heroPosition); 

};

#endif  // __HELLOWORLD_SCENE_H__

HelloWorldScene.cpp

#include "HelloWorldScene.h"

using namespace cocos2d;

CCScene* HelloWorld::scene()
{
    CCScene * scene = NULL;
    do 
    {
        // 'scene' is an autorelease object
        scene = CCScene::create();
        CC_BREAK_IF(! scene);

        // 'layer' is an autorelease object
        HelloWorld *layer = HelloWorld::create();
        CC_BREAK_IF(! layer);

        // add layer as a child to scene
        scene->addChild(layer);
    } while (0);

    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    bool bRet = false;
    do 
    {
        //////////////////////////////////////////////////////////////////////////
        // super init first
        //////////////////////////////////////////////////////////////////////////

        CC_BREAK_IF(! CCLayer::init());

        //////////////////////////////////////////////////////////////////////////
        // add your codes below...
        //////////////////////////////////////////////////////////////////////////

        // 1. Add a menu item with "X" image, which is clicked to quit the program.

        // Create a "close" menu item with close icon, it's an auto release object.
        CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
            "CloseNormal.png",
            "CloseSelected.png",
            this,
            menu_selector(HelloWorld::menuCloseCallback));
        CC_BREAK_IF(! pCloseItem);

        // Place the menu item bottom-right conner.
        pCloseItem->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20));

        // Create a menu with the "close" menu item, it's an auto release object.
        CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
        pMenu->setPosition(CCPointZero);
        CC_BREAK_IF(! pMenu);

        // Add the menu to HelloWorld layer as a child layer.
        this->addChild(pMenu, 1);

        //加入TMX地圖          
        map = CCTMXTiledMap::create("0.tmx");//CCTMXTiledMap::tiledMapWithTMXFile("0.tmx");          
        this->addChild(map);              
        for (int i=0; i<kTotal; i++)
        {
            walkAnimations[i] = createAnimationByDirection((HeroDirection)i);      
        }
        //創建勇士,用第一幀作為勇士的靜態圖 
        
        
        heroSprite =CCSprite::createWithSpriteFrame(((CCAnimationFrame*)(walkAnimations[kDown]->getFrames()->objectAtIndex(0)))->getSpriteFrame());          
        heroSprite->setAnchorPoint(CCPointZero);          
        heroSprite->setPosition(positionForTileCoord(ccp(7, 0)));          
        this->addChild(heroSprite);              
        //加入4個行走方向的控制菜單          
        CCMenuItem *down = CCMenuItemFont::create("down", this, menu_selector(HelloWorld::menuCallbackMove));
            //CCMenuItemFont::create("down", this, menu_selector(HelloWorld::menuCallbackMove));
            //CCMenuItemFont::itemWithString("down", this, menu_selector(HelloWorld::menuCallbackMove));          
        CCMenuItem *left = CCMenuItemFont::create("left", this, menu_selector(HelloWorld::menuCallbackMove));
            //CCMenuItemFont::itemWithString("left", this, menu_selector(HelloWorld::menuCallbackMove));          
        CCMenuItem *right = CCMenuItemFont::create("right", this, menu_selector(HelloWorld::menuCallbackMove));
            //CCMenuItemFont::itemWithString("right", this, menu_selector(HelloWorld::menuCallbackMove));          
        CCMenuItem *up = CCMenuItemFont::create("up", this, menu_selector(HelloWorld::menuCallbackMove));
            //CCMenuItemFont::itemWithString("up", this, menu_selector(HelloWorld::menuCallbackMove));          
        CCMenu *menu =CCMenu::create(down,left,right,up,NULL);
            //CCMenu::menuWithItems(down, left, right, up, NULL);             
        //為了方便查找給菜單項添加tag          
        down->setTag(kDown);          
        left->setTag(kLeft);          
        right->setTag(kRight);          
        up->setTag(kUp);              
        //菜單項水平排列          
        menu->alignItemsHorizontallyWithPadding(30);          
        this->addChild(menu);             
        //啟動定時器          
        this->schedule(schedule_selector(HelloWorld::update));  
        this->isHeroWalking = false;
        bRet = true;
    } while (0);

    return bRet;
}

void HelloWorld::menuCloseCallback(CCObject* pSender)
{
    // "close" menu item clicked
    CCDirector::sharedDirector()->end();
}
/************************************************************************          
設置行走方向  
*********************************************[2013年1月24日 12:04:13]***/
CCAnimation *HelloWorld::createAnimationByDirection(HeroDirection direction)  
{      
    //將圖片生成紋理,保存到全局的紋理緩沖區      
    CCTexture2D *heroTexture = CCTextureCache::sharedTextureCache()->addImage("hero.png");              
    //用紋理創建4幀動畫      
    CCArray *animFrames = new CCArray[4];      
    for (int i=0; i<4; i++)      
    {          
        CCSpriteFrame *fream = CCSpriteFrame::createWithTexture(heroTexture,CCRectMake(32*i, 32*direction, 32, 32));
            //CCSpriteFrame::frameWithTexture(heroTexture, CCRectMake(32*i, 32*direction, 32, 32));          
        animFrames->addObject(fream);      
    }      
    // 用4個動畫幀生成CCAnimation對象(動畫模板),其中0.2f是每幀之間的時間間隔      
    CCAnimation *animation = new CCAnimation();      
    animation->initWithSpriteFrames(animFrames, 0.2f);      
    return animation;  
}      
/************************************************************************          
設置行走方向變化的回調函數  
*********************************************[2013年1月24日 12:04:13]***/    
void HelloWorld::menuCallbackMove(CCObject *pSender)  
{      
    //如果勇士正在移動,不接受指令      
    if (this->isHeroWalking)          
        return;              
    CCNode *node = (CCNode*)pSender;      
    //按鈕的tag就是需要走的方向      
    HeroDirection tag = (HeroDirection)node->getTag();      
    //根據方向計算移動的距離      
    CCPoint moveByPosition;      
    switch(tag)      
    {      
    case kDown:          
        moveByPosition = ccp(0, -32);          
        break;      
    case kLeft:          
        moveByPosition = ccp(-32, 0);          
        break;      
    case kRight:          
        moveByPosition = ccp(32, 0);          
        break;      
    case kUp:          
        moveByPosition = ccp(0, 32);          
        break;      
    }      
    //計算目標坐標,用勇士當前坐標加上移動距離      
    CCPoint targetPosition = ccpAdd(heroSprite->getPosition(), moveByPosition);     
    CCPoint tilePoint = tilecoordForPosition(targetPosition);      
    //檢查碰撞類型,如果是牆壁,則只需要設置勇士的朝向      
    if (checkCollision(targetPosition) == kWall)      
    {          
        setFaceDirection(tag);          
        return;      
    }              
    //利用ccspawn將行走動畫和移動同時執行      
    CCAction *action =CCSequence::create( //CCSequence::actions(
        CCSpawn::create(//CCSpawn::actions(
            CCAnimate::create(walkAnimations[tag]),//CCAnimate::actionWithAnimation(walkAnimations[tag]),
            CCMoveBy::create(0.28f,moveByPosition),NULL),//CCMoveBy::actionWithDuration(0.28f, moveByPosition), NULL),
        //把當前的行走方向傳遞給onwalkdone          
            CCCallFuncND::create(this,callfuncND_selector(HelloWorld::onWalkDone),(void*)(tag)),NULL);
                
        
    heroSprite->runAction(action);          
    //設置移動狀態      
    this->isHeroWalking = true;  
}  
/************************************************************************          
設置行走方向  *********************************************[2013年1月24日 13:08:06]***/
void HelloWorld::setFaceDirection(HeroDirection direction)  
{      
    heroSprite->setTextureRect(CCRectMake(0, 32.0f*direction, 32, 32));  
}      
/************************************************************************          
停止行走的回調  
*********************************************[2013年1月24日 13:08:06]***/
void HelloWorld::onWalkDone(CCNode *pTarget, void *data)  
{      
    //設置移動狀態     
    this->isHeroWalking = false;      
    HeroDirection direction = (HeroDirection)(int)data;     
    this->setFaceDirection(direction);  
}  
/************************************************************************          
游戲場景的移動  
*********************************************[2013年1月24日 16:05:27]***/
void HelloWorld::setSceneScrollPosition(CCPoint position)  
{      
    CCSize screenSize = CCDirector::sharedDirector()->getWinSize();      
    //計算TMXtilemap的寬高      
    CCSize mapSize = CCSizeMake(map->getMapSize().width*map->getTileSize().width,         
        map->getMapSize().height*map->getTileSize().height);      
    float x = MAX(position.x, screenSize.width/2.0f);      
    float y = MAX(position.y, screenSize.height/2.0f);          
    if (mapSize.width > screenSize.width)         
        x = MIN(x, mapSize.width - screenSize.width/2.0f);      
    if (mapSize.height > screenSize.height)          
        y = MIN(y, mapSize.height - screenSize.height/2.0f);          
    CCPoint heroPosition = ccp(x, y);      
    CCPoint screenCenter = ccp(screenSize.width/2.0f, screenSize.height/2.0f);      
    CCPoint scrollPosition = ccpSub(screenCenter, heroPosition);        
    this->setPosition(scrollPosition); 
}      
/************************************************************************      
定時器回調函數,更新地圖  
***********************************************[2013年1月24日 17:12:16]**/
void HelloWorld::update(float dt)  
{      
    if (isHeroWalking)        
        setSceneScrollPosition(heroSprite->getPosition()); 
}      
/************************************************************************      
從cocos2d-x坐標轉換成Tilemap坐標  
***********************************************[2013年1月24日 17:13:09]**/
CCPoint HelloWorld::tilecoordForPosition(CCPoint position)  
{      
    int x = int(position.x/map->getTileSize().width);    
    int y = int(position.y/map->getTileSize().height);     
    return ccp(x, y); 
}     
/************************************************************************     
從Tilemap坐標轉換成cocos2d-x坐標  
***********************************************[2013年1月24日 17:27:37]**/
CCPoint HelloWorld::positionForTileCoord(CCPoint position) 
{      
    float x = float(position.x*map->getTileSize().width);     
    float y = float(position.y*map->getTileSize().height);     
    return ccp(x, y); 
}    
/************************************************************************      
根據勇士當前位置判斷碰撞類型
***********************************************[2013年1月24日 17:15:38]**/
HelloWorld::CollisionType HelloWorld::checkCollision(cocos2d::CCPoint heroPosition)  
{     
    //將cocos2d-x坐標轉換成為Tilemap坐標     
    CCPoint tileCoord = tilecoordForPosition(heroPosition);       
    //如果勇士坐標超過地圖邊框,返回kWall類型,阻止其移動    
    if (heroPosition.x < 0 || tileCoord.x > map->getMapSize().width-1    
        || tileCoord.y < 0 || tileCoord.y > map->getMapSize().height-1)    
        return kWall;    
    //由於TMX文件的坐標與游戲中坐標定義不同轉換一下;  
    tileCoord.y = map->getMapSize().height - 1 - tileCoord.y;  
    //獲取當前圖塊的ID,為1表示有牆    
    if(map->layerNamed("wall")->tileGIDAt(tileCoord))    
    {
        return kWall;  
    }
    //其他可以通行  
    if (map->layerNamed("floor")->tileGIDAt(tileCoord))
    {
        return kNone;  
    }
    
           
}      
/************************************************************************     
析構函數  *********************************************[2013年1月24日 13:08:06]***/
HelloWorld::~HelloWorld() 
{     
    //釋放內存   
    for (int i=0; i<4; i++)     
    {         
        CC_SAFE_RELEASE(walkAnimations[i]);     
    }      this->unscheduleAllSelectors(); 
}      

 

 tmx、png文件下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM