'cocos2d for android 예제분석/SchedulerTest.java 분석'에 해당되는 글 1건

  1. 2011.09.17 SchedulerTest.java (cocos2d 안드로이드 예제 분석강좌)
1. 목적 
==> Action 과 밀접한 관련을 가지 scheduler 를 정확하게 인지 함으로 써 
     보다 나은 시스템을 구현하고자 합니다. 

2. 소스 분석. 
  2-1 안로로이드 activity 생명주기와  관련된 cocos2d 기본 셋팅.

==>이것은 기본 셋팅부분입니다. 이전 MenuTest 첫번째 강좌에서도 분석이 했기에 생략합니다. 


2.2. 기본 셋팅을 제외한 나머지 분석. 

2.2-1 멤버변수 

public static final int kTagAnimationDance = 1;
 

/*레이어 인덱스 번호*/
static
int sceneIdx=-1;

/* 구현될 클래스 */
static
Class<?> transitions[] = {

  SchedulerAutoremove.class,

  SchedulerPauseResume.class,

  SchedulerUnscheduleAll.class,

  SchedulerUnscheduleAllHard.class,

  SchedulerSchedulesAndRemove.class,

  SchedulerUpdate.class,

  SchedulerUpdateAndCustom.class,

  SchedulerUpdateFromCustom.class,

};



2.2-2  static classSchedulerTestLayer extendsCCLayer 

static class SchedulerTestLayer extends CCLayer {

    publicSchedulerTestLayer() {

      super();

 

      CGSize s = CCDirector.sharedDirector().winSize();

 

      CCLabel label = CCLabel.makeLabel(title(),"DroidSans", 24);

      addChild(label);

      label.setPosition(CGPoint.make(s.width / 2, s.height / 2 - 50));

 

      String subtitle = subtitle();

      if (subtitle!= null) {

        CCLabel l = CCLabel.makeLabel(subtitle(),"DroidSans", 16);

        addChild(l, 1);

        l.setPosition(s.width/2, s.height-80);

      }

 

      CCMenuItemImage item1 = CCMenuItemImage.item("b1.png", "b2.png", this, "backCallback");

      CCMenuItemImage item2 = CCMenuItemImage.item("r1.png", "r2.png", this, "restartCallback");

      CCMenuItemImage item3 = CCMenuItemImage.item("f1.png", "f2.png", this, "nextCallback");

 

      CCMenu menu = CCMenu.menu(item1,item2, item3);

      menu.setPosition(0, 0);

      item1.setPosition(s.width / 2 - 100, 30);

      item2.setPosition(s.width / 2, 30);

      item3.setPosition(s.width / 2 + 100, 30);

      addChild(menu, 1);

}

==> 레이어 공통을 따로 뽑아 구현 


2.2-3 
SchedulerTestLayer상속해서 구현해야 할 클래스들 

static class SchedulerAutoremove extendsSchedulerTestLayer
static classSchedulerPauseResume extendsSchedulerTestLayer
static classSchedulerUnscheduleAll extends chedulerTestLayer
static class chedulerUnscheduleAllHarextend SchedulerTestLayer 
static classchedulerSchedulesAndRemovextends chedulerTestLayer
static classTestNode extendsCCNode implements                                                        UpdateCallback

static classSchedulerUpdateAndCustom extends                          SchedulerTestLayer implementsUpdateCallback 

static classSchedulerUpdateFromCustom extends                        SchedulerTestLayer implementsUpdateCallback  
 
 



3. 주요 클래스 분석
3.1 static class SchedulerAutoremove extendsSchedulerTestLayer 

static class SchedulerAutoremove extends SchedulerTestLayer {

    float accum;

    publicSchedulerAutoremove() {

      super();

      schedule("autoremove", 0.5f);

      schedule("tick", 0.5f);

      accum = 0;

    }

    public void tick(float dt) {

      ccMacros.CCLOG(LOG_TAG, "Thisscheduler should not be removed");

    }

    public void autoremove(float dt) {

      accum += dt;

      String s = String.format("Time: %f", accum);

      ccMacros.CCLOG(LOG_TAG, s);

      if( accum > 3 ) {

        unschedule("autoremove");

        unschedule("tick");

        ccMacros.CCLOG(LOG_TAG, "schedulerremoved");

      }

    }

    public Stringtitle() {

      return "Self-remove an scheduler";

    }

    public Stringsubtitle() {

      return "1 scheduler will be autoremoved in 3seconds. See console";

}

}

==>schedule("tick", 0.5f);

   public void tick(float dt) {

      ccMacros.CCLOG(LOG_TAG, "Thisscheduler should not be removed");

   }
   에서 볼수 있듯이 기본본적으로 로그를 확인해야 알수 있다 .
==>Log 사용법은 tick(float dt)에 나와 있듯이 사용하면됩니다. 
==>schedule 함수 에서 알수 있듯이  첫번째 파라미터는 콜백함수 두번째 파라미터는 
   반복적으로 호출되어질 주기를 설정한다.
==>콜랙함수를 String 타임으로 넘기는것을 selector 라고 한다  당장은 이걸 왜 
   빨간색으로 했는지는 모르겟지만 뒤에 이것에 대한 것이 나온다 . 일단 알고갑시다.
==>
unschedule("autoremove"); 에서 볼수 있듯이 스케쥴의 해제는           unschedule(String selector)을 쓴다. 
==>특별히 어려운건 없습니다.  

3.2 static classSchedulerPauseResume extends chedulerTestLayer 

  static class SchedulerPauseResume extends SchedulerTestLayer {

    publicSchedulerPauseResume() {

      super();

      schedule(newUpdateCallback() {

        @Override

        public void update(float d) {

          tick1(d);

        }

      } , 0.5f);

      schedule(newUpdateCallback() {

        @Override

        public void update(float d) {

          tick2(d);

        }

      } , 1);

      schedule(newUpdateCallback() {

       

        @Override

        public void update(float d) {

          pause(d);

        }

      } , 3);

    }

    public void tick1(float dt) {

      ccMacros.CCLOG(LOG_TAG, "tick1");

    }

    public void tick2(float dt) {

      ccMacros.CCLOG(LOG_TAG, "tick2");

    }

    public void pause(float dt) {

      CCScheduler.sharedScheduler().pause(this);

    }

    public Stringtitle() {

      return "Pause / Resume";

    }

    public Stringsubtitle() {

      return "Scheduler should be paused after 3seconds. See console";

    }                 

  }

==>schedule(new UpdateCallback() {

        @Override

        public void update(float d) {

          tick1(d);

        }

      } , 0.5f);
    에서 볼수 있듯이 좀전과는 다르게 selector를 사용하지 않고  
UpdateCallback()
    인터페이스를 구현 해서 스케쥴하였습니다. 뒤에 0.5f 는 당연히 주기겟죠
    좀전에 selector를 기어억하라고 했던것은 이 때문입니다. 
==>
schedule을 구현하는데 있어서 2가지 방법이 바로 selector                                          와 UpdateCallback()구현입니다. 잘기억해두세요 

3.3 static classSchedulerUnscheduleAll extends                                                   SchedulerTestLayer 

static class SchedulerUnscheduleAll extends SchedulerTestLayer {

    publicSchedulerUnscheduleAll() {

      super();

      schedule("tick1", 0.5f);

      schedule("tick2", 1);

      schedule("tick3", 1.5f);

      schedule("tick4", 1.5f);

      schedule("unscheduleAll", 4);

    }

    public Stringtitle() {

      return "Unschedule All selectors";

    }

    public Stringsubtitle() {

      return "All scheduled selectors will beunscheduled in 4 seconds. See console";

    }

    public void tick1(float dt) {

      ccMacros.CCLOG(LOG_TAG, "tick1");

    }

    public void tick2(float dt) {

      ccMacros.CCLOG(LOG_TAG, "tick2");

    }

    public void tick3(float dt) {

      ccMacros.CCLOG(LOG_TAG, "tick3");

    }

    public void tick4(float dt) {

      ccMacros.CCLOG(LOG_TAG, "tick4");

    }

    public void unscheduleAll(float dt) {

      unscheduleAllSelectors();

    }

}

==> 이번에 하는것은 첫번째 것을 잘 보셨다면 무리 없이 진행 하실수 있을것입니다. 
     selector를 이용한 스케쥴링입니다. 
==> 다만 새롭게 나온것은  unscheduleAllSelectors(); 별거 없습니다. 
   selector로 등록했으니까 AllSelectors란 접미사가 붙는건 당연합니다. 
   selector로 등록한 모든 콜백을 삭제하라입니다. 


3.4 static class SchedulerUnscheduleAllHard extends                                                    SchedulerTestLayer 

static class SchedulerUnscheduleAllHard extends SchedulerTestLayer {

    publicSchedulerUnscheduleAllHard() {

      super();

      schedule("tick1", 0.5f);

      schedule("tick2", 1);

      schedule("tick3", 1.5f);

      schedule("tick4", 1.5f);

      schedule("unscheduleAll", 4);

    }

    public Stringtitle() {

      return "Unschedule All selectors #2";

    }

    public Stringsubtitle() {

      return "Unschedules all selectors after 4s.Uses CCScheduler. See console";

    }

    public void tick1(float dt) {

      ccMacros.CCLOG(LOG_TAG, "tick1");

    }

    public void tick2(float dt) {

      ccMacros.CCLOG(LOG_TAG, "tick2");

    }

    public void tick3(float dt) {

      ccMacros.CCLOG(LOG_TAG, "tick3");

    }

    public void tick4(float dt) {

      ccMacros.CCLOG(LOG_TAG, "tick4");

    }

    public void unscheduleAll(float dt) {

      CCScheduler.sharedScheduler().unscheduleAllSelectors();

    }

  }

==> 3.3의 살짝 변형인데요 모두 동일하고  
    3.3은 CCNode의 unscheduleAllSelectors() 함수를 이용했고
   3.4는 
sharedScheduler를 직접 이용했습니다. 
==> 바로 여기서 결정적인 차이가 나는데요 . CCNode의 schedule()함수를사용
   하면 해당 CCNode의 스케쥴만 헤제되는데 비해서 3.4처럼 해줘버리면
   cocos2d 전체의 스케쥴 걸어놓은것이 다 멈추어 버립니다. 그래서 제목에
   Hard가 붙은것이죠  

3.5 static classSchedulerSchedulesAndRemove extends                                                       SchedulerTestLayer 

static class SchedulerSchedulesAndRemove extends                                                     SchedulerTestLayer {

    publicSchedulerSchedulesAndRemove() {

      super();

      schedule("tick1", 0.5f);

      schedule("tick2", 1);

      schedule("scheduleAndUnschedule", 4);

    }

    public Stringtitle() {

      return "Schedule from Schedule";

    }

    public Stringsubtitle() {

      return "Will unschedule and scheduleselectors in 4s. See console";

    }

    public void tick1(float dt) {

      ccMacros.CCLOG(LOG_TAG, "tick1");

    }

    public void tick2(float dt) {

      ccMacros.CCLOG(LOG_TAG, "tick2");

    }

    public void tick3(float dt) {

      ccMacros.CCLOG(LOG_TAG, "tick3");

    }

    public void tick4(float dt) {

      ccMacros.CCLOG(LOG_TAG, "tick4");

    }

    public void scheduleAndUnschedule(float dt) {

      unschedule("scheduleAndUnschedule");

      unschedule("tick1");

      unschedule("tick2");

      schedule("tick3", 1);

      schedule("tick4", 1);

    }

}

==>지금까지는 대부분이 생성자에서 스케쥴링하는것인데 비해서 
   이번것은 selector에서 스케쥴을 생성해도 되는 것이냐 인데  됩니다. ㅎ
   이것도 흐름만을 잘읽어 간다면 무리없을듯 합니다.

3.6 static classSchedulerSchedulesAndRemove extends                                                SchedulerTestLayer 

static class TestNode extends CCNode implements UpdateCallback {

    String string_;

    publicTestNode(String string, int priority) {

      super();

      string_ = string;

      scheduleUpdate(priority);

    }

    public void update(float dt) {

      ccMacros.CCLOG(LOG_TAG, string_);

    }

}

static class SchedulerUpdate extendsSchedulerTestLayer {

    publicSchedulerUpdate() {

      super();

      //schedule in different order... just another test

      TestNode d = new TestNode("---", 50);

      addChild(d);

      TestNode b = new TestNode("3rd", 0);

      addChild(b);

      TestNode a = new TestNode("1st", -10);

      addChild(a);

      TestNode c = new TestNode("4th", 10);

      addChild(c);

      TestNode e = new TestNode("5th", 20);

      addChild(e);

      TestNode f = new TestNode("2nd", -5);

      addChild(f);

      schedule("removeUpdates", 4.0f);

    }

    public Stringtitle() {

      return "Schedule update with priority";

    }

    public Stringsubtitle() {

      return "3 scheduled updates. Priority shouldwork. Stops in 4s. See console";

    }

    public void removeUpdates(float dt) {

      if(getChildren() != null) {

        for (CCNodenode : getChildren()) {

          node.unscheduleAllSelectors();

        }

      }

    }

}


==>위의 예제는 2가지를 담고 있습니다. 한가지는 자식 노드의 스케쥴방법과 스케쥴의 
   우선순위 입니다.
==> 잘생각해본다면 우리가 구현하고자 하는 레이어의 어디에서 스케쥴을 정했는지 알수 
   있습니다. 바로 생성자에서 지정했습니다. 그리고 레이어쪽만 하다 잠시 까먹을 수도 
   있지만. 레이어도 Scene의 자식 CCNode 입니다. 똑같죠  ㅎㅎㅎㅎ
==> 자그럼 이번에 할것은 스케쥴이 동시에 발생하면 어느것이 먼저 발생할까요? 그거야    먼저 실핼됐던놈이 먼저 시작되는게 원칙이겟죠 ㅎㅎ



3-7 static classSchedulerUpdateAndCustom                                extends SchedulerTestLayer implements pdateCallback

static class SchedulerUpdateAndCustom extends                               SchedulerTestLayer implementsUpdateCallback {

    publicSchedulerUpdateAndCustom() {

      super();

      scheduleUpdate();

      schedule(newUpdateCallback() {       

        @Override

        public void update(float d) {

          tick(d);

        }

      });

      schedule(newUpdateCallback() {

        @Override

        public void update(float d) {

          stopSelectors(d);

        }

      }, 4.0f);

    }

    public Stringtitle() {

      return "Schedule Update + customselector";

    }

    public Stringsubtitle() {

      return "Update + custom selector at the sametime. Stops in 4s. See console";

    }

    public void update(float dt) {

      String s = String.format("update called:%f", dt);

      ccMacros.CCLOG(LOG_TAG, s);

    }

    public void tick(float dt) {

      String s = String.format("custom selector called:%f", dt);

      ccMacros.CCLOG(LOG_TAG, s);

    }

    public void stopSelectors(float dt) {

      unscheduleAllSelectors();

    }

}

==> 여기에서는 scheduleupdate() 함수와 커스텀 updatecallback 를 썩어 놓았습니다. 동작은 매 프레임마다 update()와 tick() 이 호출됩니다. 
이두개는 현제 레이어에 포함되어 있으므로 최종적으로 unscheduleAllSelectors();에 의해서 모두 제거 됩니다. 



3.8 static classSchedulerUpdateFromCustom extends                               SchedulerTestLayer implementsUpdateCallback

static class SchedulerUpdateFromCustom extends SchedulerTestLayer implementsUpdateCallback {

    publicSchedulerUpdateFromCustom() {

            super();

      schedule("schedUpdate", 2.0f);

    }

    public Stringtitle() {

      return "Schedule Update in 2 sec";

    }

    public Stringsubtitle() {

      return "Update schedules in 2 secs. Stops 2sec later. See console";

    }                 

    public void update(float dt) {

      String s = String.format("update called:%f", dt);

      ccMacros.CCLOG(LOG_TAG, s);

    }

    public void stopUpdate(float dt){

      unscheduleUpdate();

      unschedule("stopUpdate");

    }

    public void schedUpdate(float dt) {

      unschedule("schedUpdate");

      scheduleUpdate();

      schedule("stopUpdate", 2.0f);

    }

}

 

==> 여기서도 진행상에는 무리가 없습니다. 클래스명에서도 알수 있듯이 
    커스텀으로 만든 selector 에서 scheduleUpdate(); 를 사용하였습니다. 
    어찌보면 당연한 말이지요. 왜 이렇게 까지 했나 싶기도 하거든요. ㅎㅎㅎ


ScheduleTest.java 힘들고 복잡할꺼라 생각했는데 생각보다 별내용은 없네요
정리 하자면 이렇습니다.

1. 스케쥴을 생성하는 방법으로 3가지 있습니다. 
  1-1, selector이용
  1-2, updateCallback() 의 구현.
  1-3, update() 이용 입니다. 
  ==> 1-2와 1-3 거의 같은 말입니다.

2, 스케쥴 우선순위
3, 스케쥴 해제 방법

요렇게 3가지 정도로 압축되네요.  

Posted by 수다쟁이증후군 :