cocos2d-x 공부용2014. 9. 3. 18:34

원글 출처 : http://horns.tistory.com/6

-3- 액션(Action)

1. 적 Action 추가

HelloWorldScene.h

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class HelloWorld : public cocos2d::Layer
{
private:
    Size _screenSize;
 
    Action* _enemyMove;
    Action* _treeMove;
 
public:
    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::Scene* createScene();
 
    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();  
    
    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);
 
    ~HelloWorld(void);//클래스 소멸자 추가
 
    void createGameScene(void);
    void createGameAction(void);
};

HelloWorldScene.cpp

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
HelloWorld::~HelloWorld(){
    CC_SAFE_RELEASE(_enemyMove);
}
 
// on "init" you need to initialize your instance
bool HelloWorld::init() {
    //////////////////////////////
    // 1. super init first
    if (!Layer::init()) {
        return false;
    }
 
    createGameAction();
    createGameScene();
 
    return true;
}

여기까지 해두고 바로 빌드해버리면 당연히 에러가 난다.
init()에서 createGameAction()을 호출해놓고 createGameAction()을 정의해두지 않았기 때문에.
나처럼 성질이 급해서 바로 빌드해보고 싶다면 아래쪽에 빈 함수라도 정의해놓고 빌드해봐서 오타가 있는지 없는지 확인하면 된다.

이제 엑션을 추가한다.

HelloWorldScene.cpp

65
66
67
68
69
70
71
72
void HelloWorld::createGameAction(){
    FiniteTimeAction* enemySwing = Sequence::create(
            EaseInOut::create(RotateTo::create(1.2f, -10), 2),
            EaseInOut::create(RotateTo::create(1.2f,10),2), NULL);
    
    _enemyMove = RepeatForever::create((ActionInterval*)enemySwing);
    _enemyMove->retain();
}

Sequence::create( A, B, NULL);
액션 A와 B를 순차적으로 실행한다.

RotateTo 지정한 각도까지 회전한다.
RotateBy 지정한 각도만큼 회전한다.
기억이 맞다면 각도 값은 라디안이 아니라 디그리로.

EaseIn 점점 빠르게
EaseOut 점점 느리게
EaseInOut 빨랐다가 느리게
Speed 해당 속도값대로

EaseInOut::create(action, rate)
rate는 탄성이라고 하는데 이걸 바꾸면 어떻게 동작하는거라고 콕 찝어 설명해준게 없는듯..

RepeatForever::create(action);
action을 무한 반복한다.

HelloWorldScene.cpp

59
60
61
62
63
//적 이미지 추가
    Sprite* enemy = Sprite::create("enemy_01.png");
    enemy->setPosition(ccp(_screenSize.width * 0.7f, _screenSize.height * 0.8f));
    enemy->runAction(_enemyMove);
    this->addChild(enemy);

여기까지 빌드하고 실행하면 적 이미지가 좌우로 왔다갔다 하게 된다.

 

왔다갔다..


2. 나무 Action 추가

* 회전 중심 변경한 상태로 바로 적용한다.

HelloWorldScene.cpp

19
20
21
22
HelloWorld::~HelloWorld(){
    CC_SAFE_RELEASE(_enemyMove);
    CC_SAFE_RELEASE(_treeMove);
}

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
void HelloWorld::createGameAction(){
    FiniteTimeAction* enemySwing = Sequence::create(
            EaseInOut::create(RotateTo::create(1.2f, -10), 2),
            EaseInOut::create(RotateTo::create(1.2f,10),2), NULL);
 
    _enemyMove = RepeatForever::create((ActionInterval*)enemySwing);
    _enemyMove->retain();
 
    FiniteTimeAction* treeSwing = Sequence::create(
            EaseInOut::create(RotateTo::create(2.0f, -5), 2),
            EaseInOut::create(RotateTo::create(2.0f, 5), 2), NULL);
 
    _treeMove = RepeatForever::create((ActionInterval*)treeSwing);
    _treeMove->retain();
}

그리고 나서 나무에 액션을 추가합시다.
그런데.... [tree->runAction((CCAction*)_treeMove->copy()->autorelease());]를 사용하니 분명 빌드는 되는데,
실행을 하니 아주 예쁘게 에러를 뱉으면서 앱이 죽으셨습니다--;;; 검색해보니 copy()는 3.0버전부터 더이상 지원을 안하는군요.
아래 내용을 참고하여 변경합니다.
1// v2.1
2CCMoveBy *action = (CCMoveBy*) move->copy();
3action->autorelease();
4
5// v3.0
6// No need to do autorelease, no need to do casting.
7auto action = move->clone();
릴리즈 노트 원본을 못찾겠네요....여튼 이제 오토릴리즈 할 필요가 없다고 고치라니까 고쳐봅니다.

HelloWorldScene.cpp

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//나무 이미지 삽입
    Sprite* tree = Sprite::create("tree_01.png");
    tree->setPosition(ccp(_screenSize.width * 0.2f, _screenSize.height * 0.7f));
    tree->setAnchorPoint(ccp(0.5f,0));
    tree->runAction((Action*)_treeMove->clone());
    this->addChild(tree);
 
    tree = Sprite::create("tree_02.png");
    tree->setPosition(ccp(_screenSize.width * 0.35f, _screenSize.height * 0.7f));
    tree->setAnchorPoint(ccp(0.5f,0));
    tree->runAction((Action*)_treeMove->clone());
    this->addChild(tree);
 
    tree = Sprite::create("tree_03.png");
    tree->setPosition(ccp(_screenSize.width * 0.8f, _screenSize.height * 0.7f));
    tree->setAnchorPoint(ccp(0.5f,0));
    tree->runAction((Action*)_treeMove->clone());
    this->addChild(tree);

실행 결과:

 

잘 움직이네요..

오늘은 여기까지입니다.

-----------------------------------------------------------------------------------------------------------------
이거 정리하느라 퇴근을 못해서 배고프네요
소스 설명이나 그런건 내일 추가해야겠습니다.
내일부터는 걍 소스 라인넘버 변경 안하고 해야겠네요..이게 은근 번거롭네요




Posted by 아이시네프
cocos2d-x 공부용2014. 9. 3. 17:24

원글 출처 : http://horns.tistory.com/5

-2- 기본 화면 구성

1. 화면을 세로로 고정하기

/proj.android/AndroidManifest.xml에서 20번째 줄의 screenOrientation을 portrait로 수정한다.

18
19
20
21
22
<activity android:name="org.cocos2dx.cpp.AppActivity"
                  android:label="@string/app_name"
                  android:screenOrientation="portrait"
                  android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
                  android:configChanges="orientation">


2. 배경 이미지 삽입

1) 시작하기

불필요한 코드를 삭제하고 아래와 같이 시작한다.

/Classes/HelloWorldScene.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
 
#include "cocos2d.h"
 
using namespace cocos2d;
 
class HelloWorld : public cocos2d::Layer
{
public:
    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::Scene* createScene();
 
    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();  
    
    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);
};
 
#endif // __HELLOWORLD_SCENE_H__
 
볼드체로 된 using namespace cocos2d;를 반드시 추가한다.
이걸 하지 않으면 헤더파일 내에서 cocos2d 클래스랑 연결이 되지 않음.

/Classes/HelloWorldScene.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include "HelloWorldScene.h"
 
USING_NS_CC;
 
Scene* HelloWorld::createScene()
{
    // 'scene' is an autorelease object
    auto scene = Scene::create();
    
    // 'layer' is an autorelease object
    auto layer = HelloWorld::create();
 
    // add layer as a child to scene
    scene->addChild(layer);
 
    // return the scene
    return scene;
}
 
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
 
    return true;
}


2) 배경 이미지 삽입

*게임에 사용된 이미지는 원출처(http://horns.tistory.com/5)에 있으므로 여기에 추가로 업로드 하지 않는다.

HelloWorldScene.h에 다음과 같이 변수 및 함수 추가.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
 
#include "cocos2d.h"
 
using namespace cocos2d;
 
class HelloWorld : public cocos2d::Layer
{
private:
    Size _screenSize;
public:
    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::Scene* createScene();
 
    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();  
    
    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);
 
    void createGameScene(void);
};
 
#endif // __HELLOWORLD_SCENE_H__

HelloWorldScene.cpp에서 배경 이미지를 생성한다.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    
    createGameScene();
 
    return true;
}
 
void HelloWorld::createGameScene(){
    _screenSize = Director::sharedDirector()->getWinSize();
 
    //배경 이미지 삽입
    Sprite* background = Sprite::create("game_back.png");
    background->setPosition(ccp(_screenSize.width/2, _screenSize.height/2));
    background->setScale(_screenSize.width/background->getContentSize().width); //화면에 꽉차게 배경화면 띄우기
    this->addChild(background);
}


2) 나무 및 적 이미지 삽입

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
void HelloWorld::createGameScene() {
    _screenSize = Director::sharedDirector()->getWinSize();
 
    //배경 이미지 삽입
    Sprite* background = Sprite::create("game_back.png");
    background->setPosition(ccp(_screenSize.width / 2, _screenSize.height / 2));
    background->setScale(_screenSize.width / background->getContentSize().width); //화면에 꽉차게 배경화면 띄우기
    this->addChild(background);
 
    //나무 이미지 삽입
    Sprite* tree = Sprite::create("tree_01.png");
    tree->setPosition(ccp(_screenSize.width * 0.2f, _screenSize.height * 0.8f));
    this->addChild(tree);
 
    tree = Sprite::create("tree_02.png");
    tree->setPosition(ccp(_screenSize.width * 0.35f, _screenSize.height * 0.8f));
    this->addChild(tree);
 
    tree = Sprite::create("tree_03.png");
    tree->setPosition(ccp(_screenSize.width * 0.8f, _screenSize.height * 0.8f));
    this->addChild(tree);
 
    //적 이미지 추가
    Sprite* enemy = Sprite::create("enemy_01.png");
    enemy->setPosition(ccp(_screenSize.width * 0.7f, _screenSize.height * 0.8f));
    this->addChild(enemy);
}

Ctrl+B버튼을 눌러서 빌드해준 뒤 에러가 없는지 확인하고 실행해본다.
에러가 발생한다면 오타가 있는지 확인할 것.

실행 화면:



----------------------------------------------------------------------------------------------------------------

소스 삽입기가 라인넘버까지 지정이 가능하면 좋을텐데...뭔가 다른 편한걸 찾아봐야겠네요.


Posted by 아이시네프
cocos2d-x 공부용2014. 9. 3. 15:51

원글 출처 : http://horns.tistory.com/4


horns님께 허락을 구해서 첫 포스팅부터 해봅니다.
실은 어제부터 시작했는데 오늘 출근해보니 이클립스가 아침부터 에러로 절 환영해준덕에...ㅡㅡ;
잡설은 치우고, 기본적인 구상이나 진행등은 horns님이 포스팅해주신대로 진행하며,
저는 3.2로 그걸 따라하면서 변경된 소스를 올리는 정도로만 포스팅합니다.

예전에 2.0.4 버전으로 강좌를 따라하다가, 중간에 없는 클래스(메서드라고 해야하나? 용어에는 좀 약하네요)때문에 중단했는데
지금 회사 일이 잠깐 비어서 시간이 남는 김에 새로 시작하려고 합니다.

이걸 포스팅 하는 중간중간 지금 제가 회사 프로젝트를 수정하는데 사용한 소스 코드도 따로 작성하고 그래야겠네요.

여하튼, 허락해주신 horns님께 다시 한 번 감사드립니다.


프로젝트 환경

cocos2d-x 3.2버전

Eclipse Kepler SR2

windows 8 64bit


코드 삽입용 : http://prev.kr/apps/ColorScripter/?run=1

Posted by 아이시네프
cocos2d-x 공부용2014. 9. 3. 15:02

항상 외우는 부분이 아니라 까먹을것을 대비해 적어둔다.
회사 프로그램을 쓰면서 밥먹듯이 써먹은 2.0.4버전은 이제 기억하지만, 새로 설치한 3.2는 방법도 새롭고 많이 달라져서 매번 프로젝트를 만들때마다 까먹을 것 같아 저장.
지금이야 한번만 하는 설정은 다 해놨지만 퇴사하고 노트북 반납하게 되면 나중에 처음부터 다시해야할테니....항상 적어두는 습관을 가져야 하는데 그러지 않아서 늘 고생하는듯.

1. 프로젝트 생성하는법

출처 : http://cafe.naver.com/cocos2dxusers/18776

Projects폴더로 이동해서 cocos new (프로젝트명) -l cpp -p (패키지명)


2. 프로젝트를 이클립스에 import하고 빌드하는 법

출처 : http://makerj.tistory.com/156
(ㅠㅠ이분덕에 빌드 성공했음 정말 내 은인이심)

프로젝트 import한 후 소스 코드 변경

/cocos2d/cocos/3d/CCBundleReader.h의 tell()함수를

long int tell(); --> ssize_t tell();로 변경.


그리고 /jni/Android.mk에서 

LOCAL_SRC_FILES := hellocpp/main.cpp \
../../Classes/AppDelegate.cpp \
../../Classes/HelloWorldScene.cpp

부분을

FILE_LIST := $(wildcard $(LOCAL_PATH)/../../Classes/*.cpp)
LOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%)
LOCAL_SRC_FILES += hellocpp/main.cpp

로 변경합니다.


****그리고 나처럼 2.0.4 빌드하느라고 설치한 ndk버전이 낮을 시!!

3.2로 만든 프로젝트를 빌드하려고 보면 프로젝트가 에러를 뿜뿜하는 경우가 있음.
지금 해결해와서 정확한 에러코드를 읽을 수 없으나 Aborting stop이건가? 하는 내용이 있다면

jni/Application.mk로 가서

APP_STL := c++_static
NDK_TOOLCHAIN_VERSION=clang

APP_CPPFLAGS := -frtti -DCC_ENABLE_CHIPMUNK_INTEGRATION=1 -std=c++11 -fsigned-char
APP_LDFLAGS := -latomic

를 전부 지우고

APP_STL := gnustl_static

APP_CPPFLAGS := -frtti -DCOCOS2D_DEBUG=1 -std=c++11 -Wno-literal-suffix -fsigned-char

로 바꿔준다!!!


그러나 아직 Android Library update랑 C/C++ indexer 에러 뜨는건 방법이 없음 하라는 짓을 다해봐도 안됨ㅡㅡ;;
지금도 새로 프로젝트 만들고 임포트해서 빌드 성공 했는데.....또 노트북 껐다 켜면 에러를 뿜을지도 모름

Posted by 아이시네프
cocos2d-x 공부용2014. 9. 1. 14:13

package com.example.download_progress;


import java.io.BufferedInputStream;

 import java.io.FileOutputStream;

 import java.io.InputStream;

 import java.io.OutputStream;

 import java.net.URL;

 import java.net.URLConnection;

 

import android.app.Activity;

 import android.app.Dialog;

 import android.app.ProgressDialog;

 import android.os.AsyncTask;

 import android.os.Bundle;

 import android.util.Log;

 import android.view.View;

 import android.view.View.OnClickListener;

 import android.widget.Button;

 

public class MainActivity extends Activity {

     

    public static final int DIALOG_DOWNLOAD_PROGRESS = 0;

     private Button startBtn;

     private ProgressDialog mProgressDialog;

     

    /** Called when the activity is first created. */

     @Override

     public void onCreate(Bundle savedInstanceState) {

         super.onCreate(savedInstanceState);

         setContentView(R.layout.activity_main);

         startBtn = (Button)findViewById(R.id.startBtn);

         startBtn.setOnClickListener(new OnClickListener(){

             public void onClick(View v) {

                 startDownload();

             }

         });

     }

 

    private void startDownload() {

         String url = "http://192.168.13.114:8080/aaa.pdf";

         new DownloadFileAsync().execute(url);

     }

     @Override

     protected Dialog onCreateDialog(int id) {

         switch (id) {

             case DIALOG_DOWNLOAD_PROGRESS:

                 mProgressDialog = new ProgressDialog(this);

                 mProgressDialog.setMessage("Downloading file..");

                 mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

                 mProgressDialog.setCancelable(false);

                 mProgressDialog.show();

                 return mProgressDialog;

             default:

                 return null;

         }

     }

     

     class DownloadFileAsync extends AsyncTask<String, String, String> {

         

        @Override

         protected void onPreExecute() {

             super.onPreExecute();

             showDialog(DIALOG_DOWNLOAD_PROGRESS);

         }

 

        @Override

         protected String doInBackground(String... aurl) {

             int count;

 

            try {

                 URL url = new URL(aurl[0]);

                 URLConnection conexion = url.openConnection();

                 conexion.connect();

 

                int lenghtOfFile = conexion.getContentLength();

                 Log.d("ANDRO_ASYNC", "Lenght of file: " + lenghtOfFile);

 

                InputStream input = new BufferedInputStream(url.openStream());

                 OutputStream output = new FileOutputStream("/mnt/sdcard/aaa.pdf");

 

                byte data[] = new byte[1024];

 

                long total = 0;

 

                while ((count = input.read(data)) != -1) {

                     total += count;

                     publishProgress(""+(int)((total*100)/lenghtOfFile));

                     output.write(data, 0, count);

                 }

 

                output.flush();

                 output.close();

                 input.close();

             } catch (Exception e) {}

             return null;

 

        }

         protected void onProgressUpdate(String... progress) {

              Log.d("ANDRO_ASYNC",progress[0]);

              mProgressDialog.setProgress(Integer.parseInt(progress[0]));

         }

 

        @Override

         protected void onPostExecute(String unused) {

             dismissDialog(DIALOG_DOWNLOAD_PROGRESS);

         }

     }

 }

Posted by 아이시네프