간단한 게임을 하나 만들어 볼려고 하는데 아이폰과 안드로이드 모두 지원하는 Cocos2d-x를 사용해 보기로 했다. NDK도 기존에 사용하던 r5에서 새로운 버전으로 설치하였다. 맥 라이언에서 NDK r7과 cocos2d-1.0.1-x-0.10.0 기준이다.

1. 다운로드 및 설치
1.1 NDK
안드로이드 개발자 사이트에서 최신버전인 r7을 다운로드 받고 압축을 푼 후에 적당한 폴더로 복사한다.

1.2 Cocos2d-x
cocos2d-x의 다운로드 페이지에서 최신버전인 cocos2d-1.0.1-x-0.10.0을 다운로드 받고 압축을 푼 후에 적당한 폴더로 복사한다.

둘다 설치는 간단하다. 다운로드 받고 압축을 푼 후에 원하는 폴더로 복사하면 된다. 

2. 설정 수정
복사해 놓은 cocos2d-1.0.1-x-0.10.0 폴더로 이동한다.

2.1 create-android-project.sh

NDK_ROOT="/home/laschweinski/android/android-ndk-r5"
ANDROID_SDK_ROOT="/home/laschweinski/android/android-sdk-linux_86"

상단에 위와 같이 되어 있는 부분을 아래와 같이 실제 NDK와 안드로이드 SDK가 설치된 폴더로 변경한다.

NDK_ROOT="/Users/zzerr/android-ndk-r7"
ANDROID_SDK_ROOT="/Developer/SDKs/android"

2.2 ./cocos2dx/Android.mk

NDK r7에선 glplatform.h의 GL_GLEXT_PROTOTYPES 이 제거되어 컴파일시 오류가 발생한다. 설치된 폴더내에 cocos2d-x 폴더의 Android.mk를 열어 아래와 같이 수정한다. 

LOCAL_CFLAGS := -DUSE_FILE32API


하단의 위와같이 되어 있는 LOCAL_CFLAGS를 찾아 아래와 같이 GL_GLEXT_PROTOTYPES를 추가한다. 
 

LOCAL_CFLAGS := -DUSE_FILE32API -DGL_GLEXT_PROTOTYPES=1



3. 프로젝트 생성
3.1 create-android-project.sh 실행
안드로이드 프로젝트 생성을 위해서 cocos2d-x 폴더에서 create-android-project.sh 를 실행한다. 

 
실행후에 package path를 입력받는데 적당한 이름을 입력한다. 


다음으로 타겟 안드로이드 SDK 버전을 입력한다. 출력되는 리스트중에서 선택을 한후 'id:' 다음에 나오는 숫자를 입력한다.


그리고 프로젝트명을 입력하면 cocos2d-x 폴더 아래에 프로젝트 이름으로 프로젝트 폴더가 생성된다. 이클립스에서 새로운 프로젝트를 생성하고 위에서 생성된 프로젝트 폴더에서 android 폴더를 선택한다.

3.2 build_native.sh 실행
[프로젝트명]/android 폴더에 있는 build_native.sh를 실행하여 필요한 라이브러리들을 빌드하여 생성한다.

3.3 빌드 및 테스트
이클립스에서 빌드 후 테스트를 한다.


갤럭시탭에서 실행해서 화면에 빈공간이 많은 것 같다. 위에서 프로젝트 생성시 타겟 목록에 따로 갤럭시탭이 있기는 하다.

'안드로이드' 카테고리의 다른 글

Cocos2d-x 설치 및 테스트  (4) 2012.01.03

기타 2010.02.11 10:42
몇일전 주문한 모토로이를 받아 조금 사용해 보았습니다. 넥서스원이면 모를까 모토로이는 전혀 구매할 의사가 없었지만 현재 진행하고 있는 안드로이드 프로젝트 때문에 어쩔 수 없이 구입했습니다. 이전에 테스트용으로 잠시 써본적이 있어 전혀 관심이 가지 않는 제품이었습니다. 하지만 개발할 때도 쓰겠지만 집사람 핸드폰으로 구입한 것이고 집사람은 DMB만 되면 되니 괜찮을 것 같고 당장은 선택의 여지가 없어 바로 예약판매시 신청했습니다.


휴대용 젠더/DMB 안테나, 크래들, USB, 헤드셋, 차량용 충전기 등 구성품은 푸짐했습니다. 특히 크래들과 차량용 충전기는 아주 괜찮은 것 같습니다.

아이폰을 사용할때와 비해서 반응속도도 느리고 정확하지 않으며 스크롤시 딱딱 끊기는 느낌이 있습니다. 넥서스원을 사용해본 분의 이야기를 들어보면 같은 안드로이드지만 전혀 다른 OS라는 생각이들정도로 차이가 많이나고 모토로이가 부족하다고 했습니다. 내장되어 있는 문자인식 어플리케이션으로 책표지의 안드로이드란 큰 글씨를 인식시켜 보았는데 안드로메다로 인식하더군요. 묘한 기분이 들었습니다.

그나저나 안드로이드 개발을 하면서 구형 맥북의 한계를 느끼게 되는 일이 종종 있네요. 이로인해 조만간 아이맥을 구입하지 않을까 하는 걱정이 드는데 현실이 될 것 같습니다.

'기타' 카테고리의 다른 글

참고할만한 좋은 아이폰 소스  (19) 2010.05.04
세계지도 앱 - World Atlas  (2) 2010.04.21
모토로이  (6) 2010.02.11
역시 그냥 껐다 키는 것이...  (8) 2009.09.24
아이폰 3GS  (2) 2009.09.17
블로그를 또 다시 이전했습니다.  (4) 2009.05.11

얼마전 출판사에서 리뷰요청과 함께 책을 보내주어 아이폰과 안드로이드 관련 책을 받아 보았습니다. 마침 요즘 하고 있는 안드로이드 프로젝트 때문에 정신이 없어 이제서야 간단하게 나마 책에 대한 느낌을 올려 봅니다.

두권의 책은 일본서적을 번역한 것이라는 것과 초보자를 대상으로 하고 있다는 공통점을 가지고 있습니다. 안드로이드와 아이폰으로 나누어져 있다는 것만 제외하고는 편집상태도 그렇고 두책을 본 느낌은 거의 동일합니다. 이 두 책의 장점은 대상이 명확하다는 것입니다. 어느정도 익숙한 사람도 아닌 해당 플랫폼에 처음으로 입문하는 사람을 그 대상으로 하고 있습니다.

300페이지가 조금 넘어가는 부담없는 분량에 기본적으로 알아야할 내용들을 자세하게 설명하고 있습니다. 개발에 익숙하신 분들이면 하루 정도면 읽을 수있고 해당 플랫폼에서의 개발을 어느정도 이해하실 수 있습니다.

애플리케이션 개발자 안드로이드 매력에 빠지다
카테고리 컴퓨터/IT
지은이 HIDEO KINAMI (영진닷컴, 2010년)
상세보기
안드로이드 관련서적은 2개 정도 이미 가지고 있었습니다. 그 두책에 비해서 내용은 적지만 오히려 초반에 감을 익히기에는 이 책이 더 나았을 거란 생각이 들었습니다. 어차피 책은 처음에 개념만 익히는 것이고 실제 개발시에는 책보다는 대부분 관련 사이트의 레퍼런스를 많이 활용하게 됩니다.

내용은 쉽게 이해할 수 있도록 되어 있으나 오타들이 있는 것 같습니다. 100 페이지에 보면 아래와 같은 ImageView와 ImageButton의 속성을 정의하는 소스가 있습니다.

<ImageView
.. 중략 ..
android:text=@"android:drawable/ic_menu_help"/>

<ImageButton
.. 중략 ..
android:text="@android:drawable/btn_start_big_on"/>

ImageView, ImageButton 두 위젯 모두 'android:src'로 리소스를 지정하는데 'android:text'로 잘 못 지정되어 있습니다. btn_start_big_on도 btn_star_big_on로 변경되어야 하고요. 그외에 111 페이지에 있는 소스에서도 아래와 같은 이상한 내용의 소스가 있습니다.

<FrameLayout
<TableLayout
<FrameLayout
<LinearLayout
...중략...
>
<Chrometer
<Button
</LinearLayout>

붉은 색의 갑자기 나타나 닫히지도 않은 태그들은 아마 편집시 잘 못들어 온 것 같습니다. 현재까지 본 이 오타들은 처음 보는 분들에게는 혼란을 줄 수 있을고, 초보자를 대상으로 한 책에서 이런 오류는 아쉬운 부분입니다. 이런 오타에도 불구하고 누군가 안드로이드 입문서를 물어 본다면 이 책을 추천하겠습니다.

[2쇄 부터는 수정되어 인쇄되었다고 합니다]


애플리케이션 개발자 아이폰 매력에 빠지다
카테고리 컴퓨터/IT
지은이 KENGO TSURUZONO (영진닷컴, 2010년)
상세보기
이책 역시 처음 입문하는 분들을 대상으로 쉽고 친절하게 설명되어 있습니다. 광대한 범위를 다루고 있지는 않지만 아이폰 개발에 입문하기에 좋은 책으로 생각됩니다. 많은 이미지와 도표들이 있어 이해하기도 쉽습니다. 디자인적인 측면에서 읽기가 좀 불편하지 않나 하는 생각인데 이는 보는 사람들에게 따라 평가가 달라질 것 같습니다. 확인해 보니 원서와 같은 디자인인 것 같습니다.

위에서도 언급했듯이 두 책 다 제가 본 책중에선 가장 쉽게 초보자를 대상으로 잘 나온 책인 것 같습니다. 책은 아무래도 서점에서 직접 보고서 자신과 궁합이 맞는 것을 고르는 것이 가장 좋을 것 같습니다.


안드로이드 개발환경을 조금 더 살펴 볼려고 간단히 어플리케이션을 만들어 보았습니다. 처음 대쉬보드 바이오리듬을 시작한뒤로 바이오리듬을 너무 우려먹고 있는 것 같습니다. SDK의 설치나 사용방법은 이전에 포스팅한 구글 Android 개발환경 둘러 보기를 참조하시면 좋을 것 같습니다. 아래의 이미지는 에뮬레이터에서 실행한 모습입니다.


요즘 개발환경으로는 드물게 마우스 사용없이 GUI를 구현해야 하지만 레이아웃을 편집하면서 확인할 수 있으니 큰 불편은 없는 것 같습니다. 아래는 사용한 소스들과 간단한 설명입니다. 이클립스에서 안드로이드 프로젝트로 Biorhythm을 생성하고 각각의 소스를 아래와 같이 수정하시고, BioView.java를 추가하시면 위와 같이 실행해 보실 수 있습니다.

* Biorhythm.java
package com.zzerr;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class Biorhythm extends Activity {
    private BioView bioView;
    private EditText inputYear, inputMonth, inputDay;
   
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       
        setContentView(R.layout.main);
       
        bioView = (BioView)findViewById(R.id.myView);
       
        inputYear = (EditText)findViewById(R.id.inputYear);
        inputMonth = (EditText)findViewById(R.id.inputMonth);
        inputDay = (EditText)findViewById(R.id.inputDay);
       
        /** 버튼이 클릭되었을 경우 바이오리듬 출력 */
        Button button = (Button)findViewById(R.id.showButton);
        button.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                bioView.setBirthDay(Integer.parseInt(inputYear.getText().toString()),
                        Integer.parseInt(inputMonth.getText().toString()),
                        Integer.parseInt(inputDay.getText().toString()));
               
                bioView.invalidate();
            }
        });
    }
}


* BioView.java
View 클래스에서 상속 받아 main.xml에서 정의한 myView를 서브클래싱하는 클래스입니다. 바이오리듬을 계산한 후에 출력을 합니다.
package com.zzerr;

import android.view.View;
import android.content.Context;
import android.util.AttributeSet;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.Log;

import java.util.Date;

public class BioView extends View {
    /** 상수 */
    private static final int mMaxDays = 30;
    private static final int mMaxType = 3;
    private static final long mTDV = (60*60*24*1000);
    private static final double mPI = 3.14159;
   
    private static final double mBioValues[] = { 23.0, 28.0, 33.0 };
    private static final int mColors[] = { 0xff0000ff, 0xffff00ff, 0xff00ffff };
   
    /** 멤버변수 */
    private Paint mPaint;
    private Rect mRect;
    private double mStartDays;
    private Date mBirthDate, mTodayDate;
       
    public BioView(Context context, AttributeSet attrs) {
        super(context, attrs);
       
        mRect = new Rect();
        mPaint = new Paint();
       
        mRect.top = 0;
        mRect.bottom = getWidth();
        mRect.left = 0;
        mRect.right = getHeight();

        mTodayDate = new Date();
        Date startDate = new Date(mTodayDate.getYear(), mTodayDate.getMonth(), 1);
       
        mStartDays = startDate.getTime()/mTDV;
        mBirthDate = new Date();
       
        mBirthDate.setYear(0);
    }
   
    public void setBirthDay(int year, int month, int day) {
        mBirthDate.setYear(year);
        mBirthDate.setMonth(month);
        mBirthDate.setDate(day);
    }

   @Override
   protected void onDraw(Canvas canvas) {
        int cellWidth = getWidth()/mMaxDays;
       
        mRect.top = 0;
        mRect.bottom = getWidth();
        mRect.left = 0;
        mRect.right = getHeight();
       
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(0xFFFFFFFF);

        int x = 0, y = 0, oldY = 0;
         
        // 세로줄 출력
        for (int i = 0; i <= mMaxDays; i++) {
            x += cellWidth;
            canvas.drawLine(x, mRect.top, x, mRect.bottom, mPaint);
        }
         
        // 가로줄 출력
        canvas.drawLine(0, mRect.bottom/2, mRect.right, mRect.bottom/2, mPaint);
      
        // 오늘 날짜 출력
        mPaint.setColor(0xFFFFFF00);
        x = cellWidth * mTodayDate.getDate();
        canvas.drawLine(x, mRect.top, x, mRect.bottom, mPaint);
              
        // 바이오리듬 출력
        if (mBirthDate.getYear() != 0) {
            Log.e("LOG", "year:" + mBirthDate.getYear() +
                    "month:" + mBirthDate.getMonth() +
                    "day:" + mBirthDate.getDate());
           
            double startDays = mStartDays;
            double birthDays = mBirthDate.getTime()/mTDV;
                 
            for (int k = 0; k < mMaxType; k++) {
                x = 0;
             
                mPaint.setColor(mColors[k]);
             
                for (int i = 0; i <= mMaxDays; i++) {
                    double gab = birthDays - startDays;
                    double p = (int)(Math.sin((gab/mBioValues[k]) * 2.0 * mPI) * 100.0);
   
                    y = mRect.bottom/2 + (int)(p * ((mRect.bottom/2.0)/100.0));
                   
                    if (i != 0)
                        canvas.drawLine(x, oldY, x + cellWidth, y, mPaint);
                   
                    oldY = y;
                    startDays++;
                    x += cellWidth;
                }
            }
        }
        
        super.onDraw(canvas);
    }
}

* main.xml
GUI를 정의하는 곳입니다. 이곳에서의 수정은 아래의 R.java의 R 클래스에 자동으로 적용이 됩니다. com.zzerr.BioView와 같이 사용자 클래스도 정의하여 사용할 수 있습니다.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#666666"
    >

<com.zzerr.BioView android:id="@+id/myView"
    android:layout_width="fill_parent"
    android:layout_height="330px"
    android:background="#000000"
    />
   
<TextView android:id="@+id/helpLabel"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_below="@id/myView"
    android:layout_marginTop="20px"
    android:text="생년월일을 입력후에 보기버튼을 클릭해 주세요."
    />

<EditText android:id="@+id/inputYear"
    android:layout_width="80px"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:text=""
    />

<EditText android:id="@+id/inputMonth"
    android:layout_width="60px"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/inputYear"
    android:layout_alignTop="@id/inputYear"
    android:text=""
    />

<EditText android:id="@+id/inputDay"
    android:layout_width="60px"
    android:layout_height="wrap_content"
    android:layout_below="@id/myView"
    android:layout_toRightOf="@id/inputMonth"
    android:layout_alignTop="@id/inputMonth"
    android:text=""
    />
       
<Button android:id="@+id/showButton"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_alignParentRight="true"
     android:layout_marginLeft="10px"
     android:layout_toRightOf="@id/inputDay"
     android:layout_alignTop="@id/inputDay"
     android:text="보기"
     />

</RelativeLayout>

* R.java
주석에 설명되어 있는 것과 같이 자동으로 생성해 주는 파일입니다. main.xml을 편집하면 자동으로 그에 맞게 내용이 변경됩니다.
/* AUTO-GENERATED FILE.  DO NOT MODIFY.
 *
 * This class was automatically generated by the
 * aapt tool from the resource data it found.  It
 * should not be modified by hand.
 */

package com.zzerr;

public final class R {
    public static final class attr {
    }
    public static final class drawable {
        public static final int icon=0x7f020000;
    }
    public static final class id {
        public static final int helpLabel=0x7f050001;
        public static final int inputDay=0x7f050004;
        public static final int inputMonth=0x7f050003;
        public static final int inputYear=0x7f050002;
        public static final int myView=0x7f050000;
        public static final int showButton=0x7f050005;
    }
    public static final class layout {
        public static final int main=0x7f030000;
    }
    public static final class string {
        public static final int app_name=0x7f040001;
        public static final int hello=0x7f040000;
    }
}

Xcode와 Objective-C를 사용하는 아이폰 개발과는 달리 많은 개발자들에게 익숙한 이클립스와 Java를 사용하고, 윈도우 PC에서도 개발이 가능하니 시작하기는 더 쉬울 것 같다는 생각이 듭니다. 개발자 등록도 25달러로 더 저렴하고요. ^^

구글이 안드로이드 플랫폼 소스를 공개하였습니다. 플랫폼 전체 를 오픈소스로 만들어 버리는 것을 보면 과연 구글이라는 생각이 듭니다. 좌측은 안드로이드 캐릭터의 오픈소스 버젼입니다. 뚜껑을 열어 머릿속을 훤히 보여 주고 있습니다. ^^

다운로드 받아 볼까 했는데 파일크기가 2.1GB이고 6GB의 공간이 필요하기 때문에 다음 기회로 미루었습니다. '설치를 위해서는 Linux 또는 OS X가 필요하고 윈도우즈는 아직 지원하지 않는다'는 흔히 볼 수 없는 문구도 재미있습니다. 

이와 함께 안드로이드 개발자 블로그를 보면 Android Market: Now available for users란 제목으로 애플의 앱스토어와 유사한 어플리케이션 마켓을 런칭했다는 포스팅이 올라왔습니다. 현재까지는 50개의 어플리케이션이 올라와 있고 10월 27일 부터는 일반 개발자들도 어플리케이션을 등록할 수 있다고 합니다.

흥미로운 것은 개발자들에게 70%의 수익이 돌아 가는 부분은 애플의 앱스토어와 같지만, 나머지 30%에서도 구글은 수익을 가지고 가지 않는다고 합니다. 아무리 구글의 모토가 "Don't be evil"이지만 어지간히 통 큰 기업이 아닐 수 없네요.

개발자는 쉽게 유통시킬 수 있고 사용자는 경쟁적인 저렴한 가격에 소프트웨어를 구입할 수 있으니, SDK를 제공하고 온라인 상점을 이용해 개발자와 사용자를 직접 이어주는 이런 서비스가 많이 생기는 것은 양쪽 모두가 반길만한 일이라고 생각됩니다. 요즘 경제위기와 함께 IT의 빙하기가 도래한 우리나라 개발자들에게는 더 반가운 소식일 것 같습니다.

아이폰을 기다리다 지쳐 아이팟을 구입했는데, 문득 잘 한 것 같다는 생각이 듭니다. 휴대폰은 구글폰으로 구입해서 구글폰과 아이폰을 같이 가지고 다니면 심심할 일이 별로 없을 것 같습니다.