참고: Selective Search(https://donghwa-kim.github.io/SelectiveSearch.html) 참고: EdgeBoxes(https://donghwa-kim.github.io/EdgeBoxes.html) 참고: https://www.youtube.com/watch?v=nDPWywWRIRo

  1. Abstract
    • SPPNet [1] and Fast R-CNN [2] have reduced the running time of detection networks, exposing region proposal computation as a bottleneck
    • We introduce a Region Proposal Network (RPN) that shares full-image convolutional features with the detection network (predicts object bounds and objectness scores at each position)
    • Use Fast R-CNN for detection, changed Region Proposal Algorithm into RPN merging RPN and Fast R-CNN into a single network (Only 300 proposals; 2000 proposals in R-CNN)
  1. Introduction
    • Now, proposals are the test-time computational bottleneck in state-of-the-art detection systems
      • Selective Search [4], one of the most popular methods, greedily merges superpixels based on engineered low-level features
      • EdgeBoxes [6] currently provides the best tradeoff between proposal quality and speed
    • We introduce novel Region Proposal Networks that share convolutional layers with state-of-the-art object detection networks
    • Our observation is that the convolutional feature maps used by region-based detectors, like Fast RCNN, can also be used for generating region proposals
    • RPNs are designed to efficiently predict region proposals with a wide range of scales and aspect ratios (Figure 1-a, 1-b, 1-c)
    • RPNs completely learn to propose regions from data, and thus can easily benefit from deeper and more expressive features
  1. Related Work
    • Object Proposals
      • Grouping super-pixels: Selective Search [4], CPMC [22], MCG [23]
      • Sliding windows: objectness in windows [24], EdgeBoxes [6]
    • Deep Networks for Object Detection
      • R-CNN [5]
      • Predicting object bounding boxes: [25], OverFeat method [9], MultiBox methods [26, 27], DeepMask method [28]
      • Shared Computation of convolutions: [9, 1, 29, 7, 2]
  1. Faster R-CNN
    • Region Proposal Networks 참고: ZFNet(https://oi.readthedocs.io/en/latest/computer_vision/cnn/zfnet.html)
      • Network takes as input an nnn * n spatial window
      • Intermediate layer maps input into a lower dimensional feature
      • Box-regression layer and a box-classification layer are used
      • Anchor is centered at the sliding window in question, and is associated with a scale and aspect (by default 3 scales([128, 256, 512]) * 3 aspect ratios([1:1, 1:2, 2:1]), total k=9 anchors at each sliding position)
      • Translation-Invariant Anchors: Anchors and the Functions that compute proposals relative to the anchors
      • Multi-Scale Anchors as Regression References
      • Loss Function (Multi-task Loss)
      • dd
  1. Experiments
  1. Conclusion


Uploaded by N2T

  1. Abstract
    • Key of Semantic Segmentation: rich spatial information, sizable receptive field
    • For realtime inference speed, spatial resoltuion is compromised
    • Design
      • Spatial Path with a small stride (for spatial information + generate high-resoltuion features)
      • Context Path with a fast downsampling (for sufficient receptive field)
      • Feature Fusion Module to combine two features
    • Experiments
      • Cityscapes, CamVid, COCO-Stuff
  1. Introduction
    • [34, 39] try to restrict the input size
    • [1, 8, 25] try to prune the channels of the network
    • [25] proposes to drop the last stage of the model
    • [1, 25, 35] use U-shape architecture to fuse the hierarchical features
    • Propose a novel approach to decouple the function of spatial information preservation and receptive field offering into two paths.
      • Spatial Path for spatial information
      • Context Path for large receptive field
  1. Related work
    • Spatial information
      • DUC [32], PSPNet [40], DeepLab v2, v3 [5, 6] use the dilated convolution to preserve the spatial size of the feature map
      • Global Convolution Network [26] uses large kernel to enlarge the receptive field
    • U-Shape method
      • FCN [22], U-Net [27] encode multi level features by skip connection
      • [1, 24] use deconvolution layers to construct U-shape structure
      • Laplacian Pyramid Reconstruction Network [10]
      • RefineNet [18] adds multi-path refinement structure
      • DFN [36] designs channel attention block
    • Context information
      • [5, 6, 32, 37] employ the different dilation rates in conv layers.
      • [5] uses ASPP module
      • PSPNet [40] applies “PSP” module (different scales of average pooling layers)
      • [6] uses ASPP with global average pooling
      • [38] uses scale adaptive convolution layer
      • DFN [36] adds global pooling on the top of the U-shape structure
    • Real time segmentation
      • Lightweight model: SegNet [1], E-Net [25]
      • Image Cascade or Cascade network: ICNet [39], [17]
      • [34] designs a novel two-column network and spatial sparsity
    1. Bilateral Segmentation Network
      • Spatial Path → Rich spatial information
        • Three layers (Conv with stride=2 + BN + ReLU): 1/8 of original image
      • Context Path → Large receptive field
        • ASPP, Pyramid Pooling, Large Kernel require both computation and memory a lot
        • Lightweight model + Global average pooling
      • Training
        • Loss: Softmax + Cross Entropy (Main) + Cross Entropy loss from different stages (Aux)
        • Used backbone model(Xception39) for Context path
    1. Experimental Results
      • Accuracy & Speed Analysis

        Table 7~9

      • Ablation Studies…

Uploaded by N2T

'Paper_Reading' 카테고리의 다른 글

Faster R-CNN  (0) 2022.09.07
Resnet: Deep Residual Learning for Image Recognition  (0) 2022.09.07
  1. Abstract
    • We present a residual learning framework to ease the training of networks that are substantially deeper than those used previously
    • Reformulate the layers → Residual functions with reference to the layer inputs (instead of learing unreferenced functions)
    • Provide empirical evidence of the power of residual connnections (ImageNet-ILSVRC 2015-, CIFAR-10/100, PASCAL, MS COCO) Deeper than VGGNet, still lower complexity
    • Performance
      • 28% relative improvement on the COCO object detection dataset
      • 3.57% error on the ImageNet test (+1st place on the task of ImageNet competitions)
  1. Introduction
    • Deep networks naturally integrate low/mid/high-level features and classifiers in an end-to-end multi-layer fashion
    • Driven by the significance of depth, a question arises: Is learning better networks as easy as stacking more layers? → Obstacle: vanishing/exploding gradients → Remedy: nomalized initialization, normalization layers
    • Degradation problem: with the network depth increasing, accuracy gets saturated and then degrades rapidly
    • We address the degradation problem by introducing a deep residual learning framework
      • Instead of hoping each few stacked layers directly fit a desired underlying mapping, we explicitly let these layers fit a residual mapping
      • Hypothesis: it is easier to optimize the residual mapping than to optimize the original, unreferenced mapping
    • Experiments in two points
      • Easier training: Our deep residual nets are easy to optimize, but the counterpart plain nets are hard to train when the depth is increasing
      • Higher performance: Our deep residual nets can easily enjoy accuracy gains from greatly increased depth
    • This strong evidence shows that the residual learning principle is generic, and we expect that it is applicable in other vision and non-vision problems
  1. Related Work
    • Residual Representations
      • Image Recognition - VLAD: representation that encodes by the residual vectors with respect to a dictionary - Fisher Vector: probabilistic version of VLAD
      • For vector quantization, encoding residual vectors is effective than encoding original vectors
      • Low-level vision and computer graphics (solving PDEs-Partial Differential Equations-) - Multigrid: reformulates the system as subproblems at multiple scales (each subproblem is responsible for the residual lsoultion betw. a coarser and a finer scale) - Hierarchical basis preconditioning: relies on variables that represent residual vectors betw. two scales
    • Shortcut Connections
      • Several techniques - MLPs: add a linear layer connected from the network input to the output - Few intermediate layers directly connected to auxiliary classifiers - Methods(using shortcut connections) considering centering layer responses, gradients, and propagated errors - Inception: composed of a shortcut branch and a few deeper branches
      • Concurrent work - Highway networks: shortcut connections with gating functions (Data-dependent gate, trainable. Resnet is parameter-free)
  1. Deep Residual Learning
    • Residual Learning xx: the inputs to the first of these layers (Input) H(x)H(x): underlying mapping (Output) F(x):=H(x)xF(x) := H(x) - x: neural network layer/block, thus F(x)+x=H(x)F(x) + x = H(x): original function - If the added layers can be constructed as identity mappings, a deeper model should have training error no greater than its shallower counterpart - The degradation problem suggests that the solvers might have difficulties in approximating identity mappings by multiple nonlinear layers
    • Identity Mapping by Shortcuts y=F(x,Wi)+xy = F(x, {W_i}) + x modified equation: y=F(x,Wi)+Wsxy = F(x, {W_i}) + W_sx
    • Network Architectures
      • Plain Network Our plain baselines are mainly inspired by the philosophy of VGGNets (i) for the same output feature map size, the layers have the same number of filters (ii) if the feature map size is halved, the number of filters is doubled so as to preserve the time complexity per layer - downsampling directly by convolutional layers that have a stride of 2
      • Residual Network
  1. Experiments
    • ImageNet Classification
    • CIFAR-10 and Analysis
    • Object Detection on PASCAL and MS COCO

Uploaded by N2T

'Paper_Reading' 카테고리의 다른 글

Faster R-CNN  (0) 2022.09.07
BiSeNet: Bilateral Segmentation Network for Real-time Semantic Segmentation  (0) 2022.09.07



iOS7부터는 전화번호부 접근시 사용자 동의를 필요로 한다. 책에 있던 코드만으로는 부족해서 구글링하며 고친 코드.

거의 다 참고해서 만든 것이라 이렇게 올려도 되나 싶지만, 혹시라도 도움이 될까 올림.



char* ConvertCFStringCopyUTF8String(CFStringRef cfString){

    if(cfString == NULL){

        return NULL;

    }

    

    CFIndex length = CFStringGetLength(cfString);

    CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);

    char* pBuffer = (char*)malloc(maxSize);

    

    if(CFStringGetCString(cfString, pBuffer, maxSize, kCFStringEncodingUTF8)){

        return pBuffer;

    }

    

    return NULL;

}


- (void)getFriendData:(void*)friendDatas{

    std::vector<FriendData*>* userFriendDatas = (std::vector<FriendData*>*)friendDatas;

    

    // Request to authorise the app to use addressbook

    ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(nil, nil);

    

    if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {

        ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {

            if (granted) {

                // If the app is authorized to access the first time then add the contact

                //[self _addContactToAddressBook];

                

                //ABAddressBookRef addressBook = ABAddressBookCreate();

                //CFErrorRef *error = NULL;

                //ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);

                CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBookRef);

                CFIndex nPeople = ABAddressBookGetPersonCount(addressBookRef);

                

                for(int i = 0 ; i < nPeople ; ++i){

                    ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);

                    CFStringRef firstName = (CFStringRef)ABRecordCopyValue(ref, kABPersonFirstNameProperty);

                    CFStringRef lastName = (CFStringRef)ABRecordCopyValue(ref, kABPersonLastNameProperty);

                    

                    FriendData* pFriendData = new FriendData();

                    

                    if(firstName){

                        char* pFirstName = ConvertCFStringCopyUTF8String(firstName);

                        if(pFirstName != NULL){

                            pFriendData->name = pFirstName;

                            pFriendData->name += " ";

                        }

                        free(pFirstName);

                        

                        if(firstName != nil){

                            CFRelease(firstName);

                        }

                    }

                    

                    if(lastName){

                        char* pLastName = ConvertCFStringCopyUTF8String(lastName);

                        if(pLastName != NULL){

                            pFriendData->name += pLastName;

                        }

                        free(pLastName);

                        

                        if(lastName != nil){

                            CFRelease(lastName);

                        }

                        

                        if(pFriendData->name.length() == 0){

                            delete pFriendData;

                            continue;

                        }

                    }

                    

                    ABMultiValueRef phoneNums = (ABMultiValueRef)ABRecordCopyValue(ref, kABPersonPhoneProperty);

                    

                    bool bFoundPhoneNumber = false;

                    for(CFIndex j = 0 ; j < ABMultiValueGetCount(phoneNums); ++j){

                        CFStringRef label = ABMultiValueCopyLabelAtIndex(phoneNums, j);

                        CFStringRef tempRef = (CFStringRef)ABMultiValueCopyLabelAtIndex(phoneNums, j);

                        

                        if(CFStringCompare(label, kABPersonPhoneMobileLabel, 0) == kCFCompareEqualTo){

                            if(tempRef != nil){

                                bFoundPhoneNumber = true;

                                

                                char* pPhoneNumber = ConvertCFStringCopyUTF8String(tempRef);

                                pFriendData->phoneNumber = pPhoneNumber;

                                free(pPhoneNumber);

                            }

                        }

                        

                        CFRelease(label);

                        CFRelease(tempRef);

                    }

                    

                    if(bFoundPhoneNumber == false || pFriendData->phoneNumber.length() == 0){

                        delete pFriendData;

                    }

                    else{

                        userFriendDatas->push_back(pFriendData);

                    }

                }

                

                CFRelease(allPeople);


            } else {

                // Show an alert here if user denies access telling that the contact cannot be added because you didn't allow it to access the contacts

            }

        });

    }

    else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {

        // If the user user has earlier provided the access, then add the contact

        //[self _addContactToAddressBook];

        

        //ABAddressBookRef addressBook = ABAddressBookCreate();

        CFErrorRef *error = NULL;

        ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);

        CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);

        CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);

        

        for(int i = 0 ; i < nPeople ; ++i){

            ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);

            CFStringRef firstName = (CFStringRef)ABRecordCopyValue(ref, kABPersonFirstNameProperty);

            CFStringRef lastName = (CFStringRef)ABRecordCopyValue(ref, kABPersonLastNameProperty);

            

            FriendData* pFriendData = new FriendData();

            

            if(firstName){

                char* pFirstName = ConvertCFStringCopyUTF8String(firstName);

                if(pFirstName != NULL){

                    pFriendData->name = pFirstName;

                    pFriendData->name += " ";

                }

                free(pFirstName);

                

                if(firstName != nil){

                    CFRelease(firstName);

                }

            }

            

            if(lastName){

                char* pLastName = ConvertCFStringCopyUTF8String(lastName);

                if(pLastName != NULL){

                    pFriendData->name += pLastName;

                }

                free(pLastName);

                

                if(lastName != nil){

                    CFRelease(lastName);

                }

                

                if(pFriendData->name.length() == 0){

                    delete pFriendData;

                    continue;

                }

            }

            

            ABMultiValueRef phoneNums = (ABMultiValueRef)ABRecordCopyValue(ref, kABPersonPhoneProperty);

            

            bool bFoundPhoneNumber = false;

            for(CFIndex j = 0 ; j < ABMultiValueGetCount(phoneNums); ++j){

                CFStringRef label = ABMultiValueCopyLabelAtIndex(phoneNums, j);

                CFStringRef tempRef = (CFStringRef)ABMultiValueCopyLabelAtIndex(phoneNums, j);

                

                if(CFStringCompare(label, kABPersonPhoneMobileLabel, 0) == kCFCompareEqualTo){

                    if(tempRef != nil){

                        bFoundPhoneNumber = true;

                        

                        char* pPhoneNumber = ConvertCFStringCopyUTF8String(tempRef);

                        pFriendData->phoneNumber = pPhoneNumber;

                        free(pPhoneNumber);

                    }

                }

                

                CFRelease(label);

                CFRelease(tempRef);

            }

            

            if(bFoundPhoneNumber == false || pFriendData->phoneNumber.length() == 0){

                delete pFriendData;

            }

            else{

                userFriendDatas->push_back(pFriendData);

            }

        }

        

        CFRelease(allPeople);


    }

    else {

        // If the user user has NOT earlier provided the access, create an alert to tell the user to go to Settings app and allow access

        

        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"연락처 접근 실패" message:@"Access to the addressbook is currently restricted. Setting>Privacy>contacts 에서 수정해주세요." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];

        [alert show];

        [alert release];

    }

    

}

구글에 팀블로그로 같이 작성하다 보니 약간 이 블로그에 소홀했다. 원래부터 이런 블로깅을 잘 해본 적이 없는지라 처음 초대장을 받을 때 했던 결심도 무뎌지더라.

구글블로그에 작성했던 글 중 가장 도움이 될 글 하나를 퍼왔다.


1. Cocos2d-x Reference
cocos2d-x에서 제공하는 레퍼런스. 중간에 버전을 바꾸면 해당 버전의 레퍼런스로 이동한다. ex : V3alpha1, V2.2.1
http://www.cocos2d-x.org/reference/native-cpp/V2.2.1/index.html

2. Cocos2d-x 사용자 모임
'시작하세요! cocos2d-x 프로그래밍' 저자가 운영하는 네이버 카페. 비교적 활발한 교류가 이루어지고 있다.
http://cafe.naver.com/cocos2dxusers#

3. Cocos2d-x 모바일 인디 개발자 모임
'-만들면서 이해하는- 실전! Cocos2d-x 3.x 게임 프로그래밍' 저자가 운영하는 다음 카페. 내용은 적은 편이나 Q&A를 저자가 꼬박꼬박 달아 주셔서 유용하다.
http://cafe.daum.net/cocos2d-x

4.. Cocos2d-x 개인 블로그
Cocos2d-x Tutorial 이라는 주제로 기초적인 cocos2d-x를 다룸.
(Sprite, Collision, Sound)
http://cocos2dx.tistory.com/category/cocos2d-x%20Tutorial

5. 현's 블로그
Cocos2d-x뿐 아니라 많은 주제에 대해 포스팅 중.
(에러처리, 메뉴, 장면전환 등 기초적인 cocos2d-x 에 대해 모두 다루고 있다.)
http://hyunssssss.tistory.com/category/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/cocos2d-x

6. 뽀삐 블로그
드래곤빌리지, 몬스터 월드 개발자의 블로그.
cocos2d-x에 관한 각종 강좌가 있다.
http://blog.naver.com/PostList.nhn?blogId=dlehddus84

7. 궁극의 잡 블로그
말 그대로 잡 블로그. cocos2d-x관한 설명이 많은 편. 특히 버전별로 소개된 부분이 있어 참고할 부분이 많을 듯.
http://zzaps.tistory.com/

8. Singleton's Programming, Game.. and Fantasy.
게임개발 탭을 보면 cocos2d-x 관련자료가 많음.
http://singleton.tistory.com/category/%EA%B2%8C%EC%9E%84%EA%B0%9C%EB%B0%9C

9. 철이의 컴노리
게임개발팁에 cocos2d-x관련 자료가 있고, 다른 부분도 참고할 만함.(아이폰, 안드로이드 등)
http://skyfe.tistory.com/category/%EA%B2%8C%EC%9E%84%EA%B0%9C%EB%B0%9C%ED%8C%81

10.tilemap tutorial
타일맵을 어떻게 하는지 잘 나와있는듯. 교재에서도 이 사이트를 참고해서 만든 것 같다.
http://www.raywenderlich.com/39113/cocos2d-x-tile-map-tutorial-part-1/

11. VLink Blog
애니메이션 타일에 관한 자료가 있다.
http://hashs.tistory.com/category/%EC%BD%94%EC%BD%94%EC%8A%A42D-X

12. ULSANSTAR
다양한 cocos2d-x관련 링크 제공. 시간될때마다 확인할것.
http://blog.naver.com/PostList.nhn?blogId=ulsanstar00

13. 터프 프로그래머 블로그
cocos2d-x 관련 자료 및 다양한 자료 있음.
http://growingdever.tistory.com/category/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/Game


1. shared의 사용


[2.x]

shared**->getInstance()


[3.x]

**::getInstance()


2. 터치 이벤트


[2.x]

ccTouches


[3.x]

onTouches

cocos2d-x를 접한지도 이제 어언 1주가 다 되어가는 듯 하다.

(첫 번째 포스팅과 날짜 차이가 얼마 안나는 이유는 포스팅 차체를 늦게 한 때문이지, 9일날 처음 배운 게 아니다!)

아직 모르는 게 너무 많고, 나 또한 C++기반의 이 툴이 어색했기 때문에 포스팅을 하지 않으려 했었다.

그렇지만, 이렇게 포스팅을 하면서 꾸준히 정리해 나가다 보면 이 자체가 큰 공부가 된다는 조언을 듣고 다시 글을 쓰기로 했다.


처음 Cocos2d-x 프로젝트를 만들면 기본으로 HelloWorldScene이 생성이 되는데, 이것 저것 달려있는 주석을 제치고 보면 종료 버튼을 만들 수 있는 CCItemImage(3.0 이후는 auto) 빼고 두 가지를 찾을 수 있을 것이다.

하나는 label인데,

CCLabelTTF(3.0 이후 Label)으로 구현하는 이 클래스는 cocos2d-x에서 글씨를 나타낼 때 기본적으로 사용하는 방법이다.

구현 방법은 여느 오브젝트 생성과 같다.

CCLabelTTF* pLabel(오브젝트이름) = CCLabelTTF::create("(쓰고 싶은 글)", "(사용하고 싶은 글씨체)", "(글자 크기)");

this->addChild(pLabel);


다른 하나는 Sprite로,

게임을 만들 때 삽입되는 모든 이미지 파일(png로 읽는다)을 출력하는 기본 클래스라고 할 수 있다.

구현 방법은

CCSprite* pSprite(오브젝트이름) = CCSprite::create("HelloWorld.png(Resources 폴더에 등록되어 있는 파일명-단순히 폴더에 파일이 있다고 되는 게 아니다. 반드시 Xcode에서 그 파일을 등록해야 한다-)");

this->addChild(pSprite);


모든 오브젝트는 생성 후 addChild를 통해서 출력이 된다. cocos2d-x는 Node라는 최상위 클래스에서 계속 상속하는 것으로 구현하기 때문이다.


3.0에서 label 이나 Sprite 구현은 더 쉽다.

cocos2d에서 따온 CC들을 빼고 Label* pLabel = Label::create~ 나 Sprite* pSprite=Sprite::create~같이 표현해 줄 수도 있고, auto pLabel = Label::create~, auto pSprite = Sprite::create~ 또한 가능하다.

3.0에서 도입된 auto는 auto-release object 를 생성할 때 그 클래스 이름을 앞에 쓰는 것 대신 사용할 수 있어 편리하다.


...auto-release object 가 뭐냐고?

object가 자기 자신의 사용이 종료되었을 때 스스로 메모리를 회수하고 삭제하는 object다. C++로 작성되는 cocos2d-x이기에 메모리 관리를 잘 할 수 있도록 도와주는 역할을 한다고 볼 수 있다.

HelloWorldScene.h의  CREATE_FUNC(HelloWorld); 구문이 우리가 create 메소드를 사용해 오브젝트를 생성할 수 있게 도와주고, 또한 그로 인해 생성하는 object 가 auto release되게 한다.

(Xcode를 사용하고 있다면 커맨드+마우스 클릭키로 CREATE_FUNC을 들어가보자. 오픈 소스니까 뒤지면 어떻게든 알 수 있다.)


이외에도 Scene, Layer, Director 와 같은 여러 클래스가 많지만, 그건 차차 알아가도록 하자.

cocos2d-x를 만날 수 밖에 없었던 데에는 그럴듯한 이유가 있었다.

학기를 바쳐가며 게임 어플리케이션을 개발하는 정부지원 프로젝트를 받았고, 이왕이면 아이폰, 안드로이드 모두 출시할 수 있는 멀티플랫폼 게임엔진으로는 cocos2d-x가 내 상황에 맞았기 때문이다.


물론 우려도 있었다. C와 Java만 다뤄본 내가 C++를 공부하지도 않고 바로 C++기반의 cocos2d-x에 도전한다는 것은 어찌보면 큰 모험이었다... 라기보단 C++을 배우는 겸 해서 선택한 것이 cocos2d-x였다고 하는 게 더 솔직한 심정이었던 것 같다.


그래도 '요즘은 컴퓨터 관련 도서도 잘 나와있으니 배우면서 하면 괜찮겠지' 하는 마음으로 cocos2d-x 서적을 뒤져보았는데, 그것이 이 cocos2d-x 포스트를 쓰게 된 이유가 되었다.



<무엇이 나를 어렵게 하였는가>


이미 아이폰, 안드로이드 게임을 Java와 Objective-C로 개발해왔던 프로그래머들에게는 cocos2d-x가 쉬워서인지(실제로 cocos2d-x자체가 아이폰 게임을 만드는 cocos2d엔진의 아류(?)이니까, 그리고 엔진 자체가 매우 쉽다고 하더라... 공감은 못했지만) 관련 서적이 너무 적었다. 또 하나의 문제는 서적들이 나온 지 얼마 되지 않았는데도 지속적으로 버전이 업데이트 되면서 서적들이 알려주고 있는 버전은 이미 너무 옛날 것들이 되어버렸다는 점이었다.


어차피 결국엔 3.0버전으로 올라갈 것이라 판단한 나는 많은 서적들이 대상으로 삼고있는 2.0.4버전 대신 2.2.1 버전과 3.0alpha1를 이용해 공부를 하게 되었다.


이제부터 쓰는 글들은 아마 버전 차이로 인해 고통받았던 나의 경험으로부터 시작된 것이다. 결국 선택한 버전은 3.0alpha1이지만, 간혹 터치이벤트와 같이 버전별 차이가 심한 챕터의 경우 버전별로 이야기할 것이다.


조금이나마 다른 이들에게 도움이 되었으면 한다.


미리 이야기하자면, 모든 공부를 맥에서 했기 때문에 윈도우에서 작성하는 방법은 모른다. 언젠가 cocos2d-x를 윈도우에서 쓸날이 온다면 재 포스팅을 할지도...?


---------

버전별 Cocos2d-x 프로젝트 생성의 차이점


2.0.4 - 2.1.5 버전 : Xcode 내에서 생성이 가능하다. (이보다 쉬울 수 없겠지)

2.2.1 버전 - 3.0 버전들 : 터미널에 들어가서 python명령어로 생성이 가능하다.


터미널 사용에서 필요한 명령어는 두 개.

cd 와 ls 가 그것인데, cd는 그냥 쓰면 상위폴더로, cd (하위 폴더 이름) 을 쓰면 하위 폴더로 이동할 수 있게 해준다.

그렇지만 폴더명을 정확히 알아야한다.

폴더명을 정확히 외우고 있지 못하는 사람들이 대다수일 것이기에 ls 명령어가 필요하다. ls를 치면 해당 위치에 있는(폴더 안에 있는) 파일, 폴더 들의 이름을 모두 출력한다.


cd와 ls의 조합으로 cocos2d-x 설치 폴더에 들어간 뒤 tools/project-creator 안에 있는 create_project.py 를 python create_project.py 이렇게 써주면 된다. 그러면 사용법이 나올테고, 그에 맞춰서 다시 쓰면 생성.


2.2.1~3.0alpha1까지는 사용법에 맞추어 생성해야 하는데, 3.0beta부터는 아예 GUI를 지원한다.


python create_project.py를 치고 나면 팝업창이 뜨고 거기에 입력해 넣으면 쉽게 생성이 가능하다.


---------

Q. 많은 버전 중 무엇을 선택해야 할까?


A. 정답이 어디 있겠는가? 자신이 참고할 것들이 많은 버전이면 좋겠지만, 나처럼 어차피 3.0으로 올라갈 것이기 때문에 먼저 익숙해지겠다는 의도로 최신 버전을 선택해도 좋다. 물론 그만큼 헷갈리게 되는 건 부담해야 할 것이다.


물론 이 질문은 C++에 익숙한 개발자나, 이미 아이폰, 안드로이드 어플을 개발한 경험이 풍부한 사람이라면 의미가 없을 것이다. 어차피 오픈 소스 게임 엔진이기 때문에 http://www.cocos2d-x.org/reference/native-cpp/V3.0alpha1/index.html (중간에 버전만 바꾸면 해당 버전의 레퍼런스 페이지로 이동한다. ex. V2.2.1)에 들어가면 다 나와있다.


3.0을 선택한다면, 궁금한 게 생길 때 댓글로 질문을 해 주시면 됩니다. 저도 열심히 찾아서 도울 수 있는 데까지 도와드릴게요.


p.s 존댓말로 안쓰는 이유는 안그래도 줄글인데, 더 길어지면 가독성이 떨어질 것 같아서입니다 하하;


'(Backup)' 카테고리의 다른 글

cocos2d-x 전화번호부 연동  (0) 2014.07.11
Cocos2d-x 관련 도움 링크 모음  (0) 2014.02.20
[Cocos2d-x] 2. 하나씩 배워보자. label, sprite  (0) 2014.01.14

+ Recent posts