2015년 1월 12일 월요일

cocos2d-x tiled를 이용한 타일게임 제작 -cocos2d-x 에 타일맵 충돌 판정

캐릭터까지 움직이는 것을 다 했다면 타일맵으로 물체와 충돌하여 보자.

우선 tiled에서 아래 보이는 것처럼 레이어를 2개 추가 하고 tileset 을 하나 추가하자.

 tileset은 분홍색과 파란색 타일 두개가 있다.
 



레이어는 Tree와 Meta 라는 이름으로 2가지를 만들었고

Tree레이어로 나무와 물등 각각의 지형을 추가하자.

그후 Meta레이어로 분홍색 타일을 고른다음 충돌판정을 일으키고 싶은 곳에 타일을 두면 위

화면처럼 보일 것이다.

그후 분홍 타일의 Properties 에 property를 하나 추가한 다음 이름을 Collidable 이라하고  값을

True로 설정해놓는다.

헤더에 아래함수를 추가하고
CCPoint tileCoordForPosition(CCPoint position);

그후 cpp 코드에서 함수를 정의해준다.

CCPoint HelloWorld::tileCoordForPosition(CCPoint position)
{
 int x = position.x / _tileMap->getTileSize().width;
 int y = ((_tileMap->getMapSize().height * _tileMap->getTileSize().height) - position.y) / _tileMap->getTileSize().height;
 return ccp(x, y);
}

그다음 update에서 지속적으로 체크해준다 .

void HelloWorld::update(float delta){

 auto sprPlayer = (Sprite*)this->getChildByTag(TAG_SPRITE_PLAYER);
 this->setViewPointCenter(_player->getPosition());

 if (wKeyCheck){
  CCPoint playerPos = sprPlayer->getPosition();

  CCPoint tileCoord = this->tileCoordForPosition(playerPos + Point(0, 10));
  int tileGid = _meta->tileGIDAt(tileCoord);

  auto properties = _tileMap->propertiesForGID(tileGid);

  ValueMap map = properties.asValueMap();

  String propertyValue = map["Collidable"].asString();
  if (propertyValue.compare("True") == 0) {
   auto action = (Action*)sprPlayer->getActionByTag(TAG_SPRITE_PLAYER_ACTION_W);

   sprPlayer->getActionManager()->removeAction(action);
   wMoveCheck = false;
  }
 else{

  if (!wMoveCheck){
    auto action_0 = MoveBy::create(0.1, Point(0, TAG_SPRITE_PLAYER_SPEED));
    auto action_1 = RepeatForever::create(action_0);

    action_1->setTag(TAG_SPRITE_PLAYER_ACTION_W);

   sprPlayer->runAction(action_1);
    wMoveCheck = true;
   }
  }
 
 }

 if (sKeyCheck){
  CCPoint playerPos = sprPlayer->getPosition();

  CCPoint tileCoord = this->tileCoordForPosition(playerPos + Point(0, -10));
  int tileGid = _meta->tileGIDAt(tileCoord);

  CCLOG("tileGID:%d", tileGid);

  auto properties = _tileMap->propertiesForGID(tileGid);

  ValueMap map = properties.asValueMap();

  String propertyValue = map["Collidable"].asString();
  if (propertyValue.compare("True") == 0) {
   auto action = (Action*)sprPlayer->getActionByTag(TAG_SPRITE_PLAYER_ACTION_S);

   sprPlayer->getActionManager()->removeAction(action);
   sMoveCheck = false;
   CCLOG("sussece");

  }
  else{

   if (!sMoveCheck){
    auto action_0 = MoveBy::create(0.1, Point(0, -TAG_SPRITE_PLAYER_SPEED));
    auto action_1 = RepeatForever::create(action_0);
    action_1->setTag(TAG_SPRITE_PLAYER_ACTION_S);
    sprPlayer->runAction(action_1);
    sMoveCheck = true;
   }
  }

 

 }


 if (dKeyCheck){
  CCPoint playerPos = sprPlayer->getPosition();

  CCPoint tileCoord = this->tileCoordForPosition(playerPos + Point(10, 0));
  int tileGid = _meta->tileGIDAt(tileCoord);

  CCLOG("tileGID:%d", tileGid);

  auto properties = _tileMap->propertiesForGID(tileGid);

  ValueMap map = properties.asValueMap();

  String propertyValue = map["Collidable"].asString();
  if (propertyValue.compare("True") == 0) {
   auto action = (Action*)sprPlayer->getActionByTag(TAG_SPRITE_PLAYER_ACTION_D);

   sprPlayer->getActionManager()->removeAction(action);

   dMoveCheck = false;
   CCLOG("sussece");

  }
  else{

   if (!dMoveCheck){
    auto action_0 = MoveBy::create(0.1, Point(TAG_SPRITE_PLAYER_SPEED, 0));
    auto action_1 = RepeatForever::create(action_0);
    action_1->setTag(TAG_SPRITE_PLAYER_ACTION_D);
    sprPlayer->runAction(action_1);
    dMoveCheck = true;
   }
  }
 

 }
 if (aKeyCheck){
  CCPoint playerPos = sprPlayer->getPosition();

  CCPoint tileCoord = this->tileCoordForPosition(playerPos + Point(-10, 0));
  int tileGid = _meta->tileGIDAt(tileCoord);

  CCLOG("tileGID:%d", tileGid);


  auto properties = _tileMap->propertiesForGID(tileGid);

  ValueMap map = properties.asValueMap();

  String propertyValue = map["Collidable"].asString();
  if (propertyValue.compare("True") == 0) {
   auto action = (Action*)sprPlayer->getActionByTag(TAG_SPRITE_PLAYER_ACTION_A);

   sprPlayer->getActionManager()->removeAction(action);
   aMoveCheck = false;
   CCLOG("sussece");

  }
  else{

   if (!aMoveCheck){

    auto action_0 = MoveBy::create(0.1, Point(-TAG_SPRITE_PLAYER_SPEED, 0));
    auto action_1 = RepeatForever::create(action_0);
    action_1->setTag(TAG_SPRITE_PLAYER_ACTION_A);
    sprPlayer->runAction(action_1);
    aMoveCheck = true;
   }
  }
 }

 }

 위 소스에서 중요한 부분은 플레이어의 위치로부터 그 위치에있는 포인트를 tileCoord 로 변환

한 다음 그곳의 타일 ID를 가져온다. 그후 

auto properties = _tileMap->propertiesForGID(tileGid);

  ValueMap map = properties.asValueMap();

  String propertyValue = map["Collidable"].asString();

과정을 통해서  propertyValue 에 값을 넣은 다음 그 값이

if (propertyValue.compare("True") == 0) 이면

다음에 취할 명령을 넣으면 된다.

댓글 없음:

댓글 쓰기