구성

1. 서비스 실행 시 알림 띄우기

2. 알림을 지워지지 않게 만들기('실행 중' 탭에 띄우기)




1장.


 안드로이드 이전 버전에서는 노티피케이션(Notification)을 띄우기 위해 Notification 인스턴스를 만들어 사용했지만

지금은 Notification.Builder를 통해 생성하도록 권장하고 있다.

여기서는 이전 버전과의 호환성을 위해 android.support.v4.app 패키지의 NotificationCompat.Builder 객체를 사용한다.


 그렇기 때문에 android-support-v4.jar 파일을 프로젝트에 추가해야 하는데

이 파일은 안드로이드sdk 설치 디렉토리 - extras - android - support - v4  경로에 있다.

이 파일을 이클립스 기준으로, 프로젝트속성 - java build path - libraries에 들어가 포함시키면 된다.




 서비스에서 노티피케이션을 띄우기 위한 코드는 서비스의 onStartCommand 함수 내에 작성한다.

먼저 NotificationCompat.Builder 객체를 생성하고, 필수로 SmallIcon과 ContentTitle, ContentText를 지정해 주어야 한다.


(▽ 상단바에 왼쪽편에 있는 아이콘들이 SmallIcon들이다.) 


(▽ "USB가 연결되었습니다"문구가 ContentTitle이고, "컴퓨터로부터 또는 컴퓨터로..."부분이 ContentText이다.) 



그리고 노티피케이션을 터치했을 때 어떤 동작을 할 것인가를 지정해 주는데

여기서는 메인 액티비티인 MainActivity를 실행해 주기로 하였다.


Intent를 만든 뒤 TaskStackBuilder 객체에 추가하고

그것을 바탕으로 TaskStackPendingIntent 객체를 완성한다.

그리고 그 객체를 처음에 만들었던 NotificationCompat.Builder 객체에서 setContentIntent()로 설정.

마지막으로 NotificationManager를 생성하여 notify()시키면 노티피케이션이 뜨게 된다.


코드는 아래와 같다. 


   NotificationCompat.Builder mBuilder =

    new NotificationCompat.Builder(this)

    .setSmallIcon(R.drawable.smallicon)

    .setContentTitle("알림바 실험")

    .setContentText("알림바입니다..");

   

   Intent resultIntent = new Intent(getApplicationContext(),MainActivity.class);

 

   TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);

   stackBuilder.addParentStack(MainActivity.class);

   stackBuilder.addNextIntent(resultIntent);

   

   PendingIntent resultPandingIntent =

    stackBuilder.getPendingIntent(

    0,

    PendingIntent.FLAG_UPDATE_CURRENT

    );

   

   mBuilder.setContentIntent(resultPandingIntent);

   

   NotificationManager mNotificationManager =

  (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);

 

   mNotificationManager.notify(3452, mBuilder.build());



 NotificationCompat.Builder 객체를 만들 때, 스타일을 설정하는 set메서드들이 NotificationCompat.Builder 반환값을 가지므로

.setSmaillIcon().setContentTitle().setContentText() 와 같이 이어지게 될 수 있다.


 (노티피케이션이 등록될 때 상단바에 메시지가 나타나는 것은 setTicker().로 설정할 수 있다.)

 

 MainActivity라고 되어있는 부분은 노티피케이션을 선택했을 때 실행할 액티비티이며 상황에 맞게 다른 액티비티 이름이 올 수 있다.


 notify()함수에서 3452는 노티피케이션을 관리하기 위한 id값으로 여기서는 임의의 값을 써 둔 것이다.



다른 컨텍스트에서 노티피케이션을 종료해야 할 때는 다시 NotificationManager를 생성하여

아까 지정한 id(3452)를 통해 지울 수 있다. 코드는 다음과 같다.


  NotificationManager mNotificationManager =

   (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);

 

  mNotificationManager.cancel(3452); 




2장. 


 안드로이드 운영체제는 시스템 자원이 부족하다든지 하는 경우에 실행 중인 서비스를 끌 수도 있다. (꺼졌다가 다시 켜지기도 한다)

이를 방지하기 위해선 서비스를 포그라운드(Foreground)로 실행해야 한다. 

또한 알림을 지워지지 않고 '실행 중'탭에 놓기 위해서도 역시 포그라운드로 서비스를 실행하면 된다.

서비스를 포그라운드로 실행하려면 노티피케이션을 띄워 주어야 하는데

1장에서 만든 NotificationCompat.Builder 객체를 그대로 사용할 수 있다.

코드는 아래와 같다. (위 코드와 중복되는 부분이 대부분)



    NotificationCompat.Builder mBuilder =

     new NotificationCompat.Builder(this)

     .setSmallIcon(R.drawable.smallicon)

     .setContentTitle("알림바 실험")

     .setContentText("알림바입니다..");

    

    Intent resultIntent = new Intent(getApplicationContext(),MainActivity.class);

  

    TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);

    stackBuilder.addParentStack(MainActivity.class);

    stackBuilder.addNextIntent(resultIntent);

    

    PendingIntent resultPandingIntent =

     stackBuilder.getPendingIntent(

     0,

     PendingIntent.FLAG_UPDATE_CURRENT

     );

    

    mBuilder.setContentIntent(resultPandingIntent);

    

   this.startForeground(3452,mBuilder.build());


1장의 코드와 비교하여 NotificationManager 부분이 없어지고 startForeground()함수를 추가됐다.


노티피케이션을 제거할 때는 아래 코드로 포그라운드를 취소하면 된다.


this.stopForeground(true);




 ====================================================================================================


var urlLdr:URLLoader = new URLLoader();

try {

urlLdr.load(new URLRequest("http://tibyte.kr/tibyte.txt"));

} catch (e:IOError) {  //cannot catch

}


다음과 같이 존재하지 않는 파일을 로드하면 런타임 에러가 뜬다.

예외처리를 했는데도 catch가 되지 않는데, 에러가 비동기적으로 발생하기 때문.

그래서 이벤트를 통해 예외처리를 해야한다. 


var urlLdr:URLLoader = new URLLoader();

urlLdr.addEventListener(IOErrorEvent.IO_ERROR, function h(e:IOErrorEvent){});

urlLdr.load(new URLRequest("http://tibyte.kr/tibyte.png"));


 ※Loader클래스일때는 contentLoaderInfo속성에 IOErrorEvent를 걸어주면 된다. 














https://play.google.com/store/apps/details?id=com.podocube.sunglass

화면을 좀더 어둡게 해 주는 어플을 만들어서 구글플레이에 처음으로 올려보았다.

생각만큼 쉽게 업로드되지는 않았다.

올리는 과정을 한번 해보다는 목적으로 해서 어플자체는 완성도가 떨어진다..

제목의 sunglass가 sunglasses가 아닌 이유는 glass가 하나이기 때문(?)







=====================================================================


관련글 : http://tibyte.kr/252


1.

전위/후위 증감 연산자를 복합적으로 썼을 경우에 대한 분석을 간단하게 해 보았다.

C언어로 코드를 작성하여 VC++컴파일러로 x86어셈블리를 뽑았다.



2. 사례

1) 전후위 연산자를 앞뒤로 쓴 경우


 int a=1;

00E53427  mov         dword ptr [ebp-8],1 

int b=1;

00E5342E  mov         dword ptr [ebp-14h],1 

int c=1;

00E53435  mov         dword ptr [ebp-20h],1 

int num1 = b+++a+++c;

00E5343C  mov         eax,dword ptr [ebp-14h] 

00E5343F  add         eax,dword ptr [ebp-8] 

00E53442  add         eax,dword ptr [ebp-20h] 

00E53445  mov         dword ptr [ebp-2Ch],eax 

00E53448  mov         ecx,dword ptr [ebp-8] 

00E5344B  add         ecx,1 

00E5344E  mov         dword ptr [ebp-8],ecx 

00E53451  mov         edx,dword ptr [ebp-14h] 

00E53454  add         edx,1 

00E53457  mov         dword ptr [ebp-14h],edx 


→ num1 = b+++a+++c;에 대한 어셈블리 코드를 보면 처음 4행은 num1에 대한 연산을 하는 부분이다. 

ebp-14h, ebp-8, ebp-20h 메모리의 수를 그냥 더해서 2bp-2Ch(num1 변수)메모리에 복사한다.

num1의 결과값은 1+1+1 = 3이 된다.

그리고 그 다음줄(00E53448)부터 3행에서 ebp-8 메모리(변수 a)에 1을 더하고,

마지막 3행에선 ebp-14 메모리(변수b)에  1을 더해 두고 있다.

이처럼 앞뒤로 ++a++ 꼴이 될 경우엔 왼쪽 부터 처리된다는 것을 볼 수 있다.(당연한 일이겠지만...)






2) 같은 변수에 대해 전후위 증감 연산을 여러 번 쓴 경우


int a=5,b=5,c=5,num1,num2,num3;

00E5339E  mov         dword ptr [ebp-8],5 

00E533A5  mov         dword ptr [ebp-14h],5 

00E533AC  mov         dword ptr [ebp-20h],5 

num1 = (++a)+(++a);

00E533B3  mov         eax,dword ptr [ebp-8] 

00E533B6  add         eax,1 

00E533B9  mov         dword ptr [ebp-8],eax 

00E533BC  mov         ecx,dword ptr [ebp-8] 

00E533BF  add         ecx,1 

00E533C2  mov         dword ptr [ebp-8],ecx 

00E533C5  mov         edx,dword ptr [ebp-8] 

00E533C8  add         edx,dword ptr [ebp-8] 

00E533CB  mov         dword ptr [ebp-2Ch],edx 

→ 식에서 ++a 부분을 먼저 처리한다. 이 때, 한 번 증가 연산을 하고 나서 

  그 값을 다시 ebp-8 메모리에 복사하고 그 값을 다시 레지스터로 읽어와

  다음 1을 더하는 작동을 하므로 a변수는 총 2 증가하게 된다.

  여기까지가 ++a를 두 번 연산한 단계이다.

  그리고 결과값인 num1변수(ebp-2Ch 메모리)의 값으로는 a를 두 번 더한 7+7 = 14가 나온다.


num2 = (b++)+(b++);

00E533CE  mov         eax,dword ptr [ebp-14h] 

00E533D1  add         eax,dword ptr [ebp-14h] 

00E533D4  mov         dword ptr [ebp-38h],eax 

00E533D7  mov         ecx,dword ptr [ebp-14h] 

00E533DA  add         ecx,1 

00E533DD  mov         dword ptr [ebp-14h],ecx 

00E533E0  mov         edx,dword ptr [ebp-14h] 

00E533E3  add         edx,1 

00E533E6  mov         dword ptr [ebp-14h],edx 

→ 앞의 항과 뒤의 항을 먼저 더하고 ebp-38h메모리(num2변수)에 복사 후

ebp-14h메모리(b변수)는 ecx레지스터와 edx레지스터를 거쳐 증가가 두 번 된다.

결과값은 num은 5+5=10 이고 b는 7이다.


num3 = (++c)+(c++);

00E533E9  mov         eax,dword ptr [ebp-20h] 

00E533EC  add         eax,1 

00E533EF  mov         dword ptr [ebp-20h],eax 

00E533F2  mov         ecx,dword ptr [ebp-20h] 

00E533F5  add         ecx,dword ptr [ebp-20h] 

00E533F8  mov         dword ptr [ebp-44h],ecx 

00E533FB  mov         edx,dword ptr [ebp-20h] 

00E533FE  add         edx,1 

00E53401  mov         dword ptr [ebp-20h],edx

→  처음 3행을 보면 c값은 1 증가하여 6이 된다.

   그 다음 3행에서 c+c를 하여 num3(ebp-44h 메모리)에는 12가 들어간다. 

  마지막 3행에서 c변수에(ebp-20h 메모리) 1을 더한다.


위 세 가지 사례들을 종합해 보면, 식의 전위 증감 연산자들이 먼저 처리되어

그 결과(전위증감연산)를 반영한 값으로 식이 계산된 후에, 후위 증감 연산자가 처리된다는 것을 알 수 있다.





3) 함수의 인자에 썼을 때.


function(n++,++n);

00B517E5  mov         eax,dword ptr [ebp-8] 

00B517E8  add         eax,1 

00B517EB  mov         dword ptr [ebp-8],eax 

00B517EE  mov         ecx,dword ptr [ebp-8] 

00B517F1  mov         dword ptr [ebp-0d0h],ecx 

00B517F7  mov         edx,dword ptr [ebp-8] 

00B517FA  add         edx,1 

00B517FD  mov         dword ptr [ebp-8],edx 

00B51800  mov         eax,dword ptr [ebp-8] 

00B51803  push        eax  

00B51804  mov         ecx,dword ptr [ebp-0d0h

00B5180A  push        ecx  

00B5180B  call         00B511C2 

00B51810  add         esp,8 


↓ 이 코드가 동작할 때 두 개의 메모리와 eax ecx edx 레지스터의 상태를 표로 만들어 보았다. 

   (글을 작성하다 n을 선언하는 부분을 빼먹었는데, n의 초기값은 10 였다고 하겠습니다.)


00B517E5  mov         eax,dword ptr [ebp-8] 

00B517E8  add         eax,1 

00B517EB  mov         dword ptr [ebp-8],eax 

→ 함수호출시 두 개의 인수 중 두 번째가 스택에 나중에 들어가므로 먼저 처리된다(후입선출)

  즉 function(n++, ++n)에서 뒤쪽의 ++n이 먼저 처리되는 것이다.

 n변수(ebp-8 메모리)에 1을 더해 둔다. 

그러면 이 시점에서 n의 값은 11.



00B517EE  mov         ecx,dword ptr [ebp-8] 

00B517F1  mov         dword ptr [ebp-0d0h],ecx 

00B517F7  mov         edx,dword ptr [ebp-8] 

00B517FA  add         edx,1 

00B517FD  mov         dword ptr [ebp-8],edx 

→ n의 값을 ebp-0d0h 메모리에 복사한다.

  그리고 n에 1을 더한다. 이 시점에서 n은 12.



00B51800  mov         eax,dword ptr [ebp-8] 

00B51803  push        eax  

00B51804  mov         ecx,dword ptr [ebp-0d0h

00B5180A  push        ecx  

→ ebp-8 메모리의 값을 eax레지스터로 복사해 와서 함수 스택에 push 한다.

  그리고 ebp-0d0h 메모리의 값도 함수 스택에 push.

  먼저 push 되는게 마지막 인자이다.

  그래서함수 내부에서 매개변수의 값을 찍어보면

  첫 번째 인자의 값은 11,

  두 번째 인자의 값은 12이다.



00B5180B  call         00B511C2 

00B51810  add         esp,8 

→ 다음에 실행할 인스트럭션이 있는 주소 00B511C2로 이동한다.
  함수가 4바이트 매개변수 2개를 썼으므로 esp레지스터에 4*2=8을 더한다.



3. 결론
전,후위 증감 연산자를 헷갈리지 않게 의미가 잘 드러나도록 쓰자.. 

내용추가+)
3가지 컴파일러로 컴파일해 본 결과 : http://tibyte.kr/252



========================================================================







일전에 덧셈과 뺄셈으로 두 변수의 값을 바꾸는 것을 올렸었다.(http://www.tibyte.kr/95)

이 방법은 연산과정에서 데이터형의 비트수를 넘어가면 오버플로우가 발생할 수 있는데,

다음과 같이 비트XOR(배타적논리합)연산을 쓰면 오버플로가 일어날 일이 없다.


a = a^b;

b = a^b;

a = a^b;


//한 줄로 쓰면

a ^= b ^= a^= b;


배타적 논리합 연산이므로 1행에서 a와 b의 각 자리의 비트열 차이(같은지 다른지)에 대한 정보가 a에 할당된다.

2행에서 b 우측의 항은 결과적으로 a^b^b 연산이 되어 a값이 들어간다.

3행이 처리될 때 a는 a^b 이고 b는 초기의a값이므로 a^b^a가 되어 b값이 들어가게 된다.

이렇게 a와 b의 값이 서로 바뀌게(swap) 되는 것이다.



==========================




 


웹페이지에 소스코드를 올릴 때 그냥 붙여넣으면 모두 같은 색으로 나와서 읽기가 어렵다.

이럴 때 SyntaxHighlighter는 코드의 키워드나 명령문, 주석 등에 색을 입혀서 가독성을 높여준다.



(▼ 코드가 색칠된 모습을 볼 수 있다.)




 SyntaxHighlighter를 블로그에 적용하면 게시물을 쓸 때

간단한 태그로 쉽게 코드에 색을 입힐 수 있다.


먼저 http://alexgorbatchev.com/SyntaxHighlighter/download/ 에서 최신 버전의 파일을 내려받는다.

scripts 폴더를 보면 각종 프로그래밍 언어들의 Brush 파일들이 있는데

shAutoloader, shCore, shLegacy파일은 필수적으로 업로드하고, 추가로 자신이 쓸 언어들을 더 올린다.

여기서는 AS3, Cpp, Java, JS, Php, Xml 파일을 선택했다.





그 다음 스타일시트 파일을 올리는데, shCore.css 파일은 기본적으로 올려야 하고

기본 스타일로 하려면 shCoreDefault, shThemeDefault 파일을 선택한다.

하이라이터가 다른 모양으로 나타나게 하려면 그 테마의 스타일시트 파일을 올려야 한다.

테마가 적용된 모습은 http://alexgorbatchev.com/SyntaxHighlighter/manual/themes/ 여기서 볼 수 있다. 




필요한 파일을 다 올렸으면 메인 스킨의 html파일로 들어가서

head태그 안에 아래와 같은 코드를 추가해야 한다.

<link rel="stylesheet" type="text/css" href="./images/shCore.css" />
<link rel="stylesheet" type="text/css" href="./images/shCoreDefault.css" />
<link rel="stylesheet" type="text/css" href="./images/shThemeDefault.css" />
<script type="text/javascript" src="./images/shCore.js"></script>
<script type="text/javascript" src="./images/shAutoloader.js"></script>
<script type="text/javascript" src="./images/shBrushAS3.js"></script>
<script type="text/javascript" src="./images/shBrushCpp.js"></script>
<script type="text/javascript" src="./images/shBrushJava.js"></script>
<script type="text/javascript" src="./images/shBrushXml.js"></script>
<script type="text/javascript" src="./images/shBrushJScript.js"></script>
<script type="text/javascript" src="./images/shLegacy.js"></script>
<script type="text/javascript">
    SyntaxHighlighter.all();
</script>

코드를 보면 아까 업로드한 css파일과 js파일들의 경로를 볼 수 있다. (티스토리는 리소스 파일들이 images폴더에 저장되어 저런 경로를 써주어야한다.)

테마나 다른 언어를 추가하고자 할 땐 이것도 추가해야 한다.

그리고 마지막으로는 SyntaxHilighter.all();함수를 호출한다.


 


이제 블로그 게시글을 쓸 때 하이라이터를 쓸 수 있는데,

<pre class="brush:언어의 명칭(alias)">

코드

</pre>

HTML 모드로 들어가서 위와 같이 적어주면 된다.


예를 들어 C++언어를 쓰려고 한다면

<pre class="brush:cpp">

코드

</pre>

로 적어주면 되는것이다.


나머지 언어들의 alias들은 여기서 확인할 수 있다.

http://alexgorbatchev.com/SyntaxHighlighter/manual/brushes/





한가지 중요한 주의점이 있는데

코드에 < 문자가 들어가면 코드가 깨지고 하이라이팅도 정상적으로 되지 않으므로

<문자가 있으면 모두 &lt; 로 바꿔야 한다.

찾아바꾸기를 지원하는 텍스트 에디터를 쓰거나 직접 간단한 프로그램을 작성하여 일괄적으로 바꿔놓으면 간단하다.


<pre>태그 대신 <srcipt>태그를 쓰면 이 문제는 해결되지만

특정환경(티스토리 모바일 등)에선 코드가 아예 안보이게 되는 점을 주의해야 한다.


script태그로 코드를 넣는 법은

http://alexgorbatchev.com/SyntaxHighlighter/manual/installation.html 

이 주소에 쉽게 설명되어 있다.



그리고 여러 가지 기능을 비롯한 더 자세한 설명은 신택스하이라이터 공식 페이지에 접속하면 볼 수 있다.

http://alexgorbatchev.com/SyntaxHighlighter



 




isometirc 쿼터뷰의 타일을 만들 때 64x32크기의 타일을 그냥 이어붙여 버리면

타일의 가장자리가 짤리는 현상이 발생한다.

경계선을 원래크기로 보면 가느다란 선으로 보일 뿐이지만 실제로는 픽셀로 맞물려 있기 때문이다.

아래그림처럼 경계선(테두리)의 굵기가 1이면 해당 경계선을 어느 타일이 덮어야할지 모호해진다






그래서 타일의 경계에 있는 픽셀(외곽 픽셀)들이 겹치게 하면 안되는데, 

타일이 차지하는 영역이 짝수x짝수이면 대각선 사이에 넣어야 할 타일이

꼭 들어맞지 않게 된다. (하단의 선이 직선이 되지 않고 엇갈려 있다)





그렇기 때문에 타일하나의 크기가 홀수x짝수나 짝수x홀수의 형태가 되어야 하는데

여기서는 너비가 높이보다 길기 때문에 높이는 그대로 두고 너비를 한 픽셀 줄여서 홀수로 만든다.

(그림은 32x16타일의 픽셀들을 나타낸 것으로 오른쪽 세로 한줄이 비어있는것을 볼 수 있다.)




이렇게 해서 타일을 붙이면 네 타일이 만나는 부분이 아래 그림과 같이 된다.







이제 타일들을 맞물리게 배치했다.

비록 실제 타일크기는 31x16이지만, 각 타일들의 좌표 기준점들은

(0,0), (32,0), (16,0), (32,16), (16,8) 등으로 프로그램에서 처리하기 쉽게 딱딱 떨어진다.






타일하나당 픽셀을 채워 넣는 다른 방법도 있는데,

타일들이 서로 겹치지 않고 꼭 들어맞는지,

배치한 타일의 좌표값이 타일크기에 맞게 결정되는지,  

타일들의 경계선이 엇갈려 있지 않고 직선이 되는지를 만족해야 할 것이다.













구의 일부분이 되는 붉게 표시한 원을 구할 때

원의 반지름은 rcos(t)

중심점으로부터의 높이는 rsin(t)



point.z = r*sin(t);

point.x = r*cos(t)*cos(경도);  

point.y = r*cos(t)*sin(경도);


z값은 중심점으로부터의 높이로 두고

x와 y값은 반지름( rcos(t) )에 경도의 코사인값과 사인값을 취하여 곱한다.













 코딩을 하면서 각종 상황에 대한 테스트가 필요했기 때문에

Valve社의 게임에서 볼 수 있는 것과 비슷한 콘솔 창을 구현하기로 했다.  


 콘솔 창은 싱글턴 패턴으로 프로그래밍했는데

액션스크립트는 생성자 함수의 접근제한자로 private를 둘 수 없기 때문에

해당 클래스 파일의 패키지 외부에 클래스 하나를 더 두고

싱글턴 클래스 생성자의 매개변수로 그 클래스 타입을 넣어주어야 한다.

아래와 같은 모양이다.


package {

public class Singleton {

private static var instance...

public function Singleton(block:SingletonBlocker)

{

if (block == null) throw new Error...

}

public static function getInstance()...

}

}

class SingletonBlocker{}



 프로젝트의 클래스에서 콘솔 창에 뭔가를 표시하는 함수를 호출하면 

콘솔창이 없을 경우 새로 창을 띄우고 있으면 그 창에 내용을 출력한다.


 콘솔 창은 NativeWindow클래스를 사용하여 새 윈도우를 띄우게 되는데,

이 윈도의 크기가 원하는 대로 되지 않았다. 액션스크립트 도움말을 보면 

NativeWindow객체의 stage.stageWidth 나 Height속성을 조절하면 창 크기가 

그에 맞게 바뀐다고 하는데 전혀 그렇지가 않는 것이었다..


 해결책은 역시 도움말에 나와있었는데  

_mainWindow.stage.scaleMode = StageScaleMode.NO_SCALE;

_mainWindow.stage.align = StageAlign.TOP_LEFT;

이 두 구문이 있어야 제대로 창크기 조절이 된다.



코드를 컴파일후 실행시키니 제대로 출력이 나왔다.






 다음은 게임에서 사용할 월드 데이터 파일을 제작하는 간단한 툴을 만드는 것이었다.

FileStream클래스와 File클래스로 파일쓰기를 한다.


File객체를 만들 때, 파일쓰기 하려는 위치가 어플리케이션이 있는 폴더라면

var file:File = File.applicationDirectory;

와 같이 초기화해야 한다고 해서 그렇게 해 보니 보안문제로 오류가 났다.-_-;


이 경우에는 

var file:File = new File(File.applicationDirectory.nativePath);

file = file.resolvePath("하위폴더"+File.separator+파일이름+".확장자");

요렇게 하니까 되더라..


 그 다음 이렇게 해서 생성된 월드 데이터파일에 어플리케이션을 연결해 보기로 했다.

이 작업은 그리 어렵지 않게 할 수 있다.

if(NativeApplication.nativeApplication.isSetAsDefaultApplication("확장자")==false)

NativeApplication.nativeApplication.setAsDefaultApplication("확장자");

연결이 되어 있지 않으면 '이 어플리케이션'을 해당 file의 연결 프로그램으로 설정한다.

단, 응용 프로그램 설명자(xml파일)의 fileTypes노드에 파일의 정보가 선언되어 있어야 한다.


 빌드를 하니 128x128 아이콘 파일의 크기가 맞지 않는다는 오류가 계속 뜨는데

src폴더 내의 파일을 수정해도 빌드만 하면 다시 129x129크기의 파일로 바뀌어 버렸다.

bin-debug폴더에 들어있는 파일을 지우니 제대로 빌드가 되었다.



(▲ 데이터파일의 아이콘이 바뀐 모습. 실행하면 맵에디터가 열리고 해당 파일을 불러들인다.) 



하나 빼먹은 게 있어 추가로 적는데,

프로그램 연결은 연결프로그램으로 쓸 어플리케이션이 컴퓨터에 설치되어 있는 상태여야 한다. (디버그모드에서는 확인할 수 없다.)








 





 

 오래전부터 공책에 구상하고 있었던 게임이 있었는데 10월 넷째주부터 본격적으로 작업을 시작했다. 

만드려는 게임은 isometric 시점의 타일기반 rpg게임이다. 

플래시빌더를 써서 action script 3.0으로 코딩을 하는데 오랜만에 다시 해보는거라 적응이 잘 안되어 힘들다. 

우선 게임내의 지형을 처리/표시하는 클래스를 구현하기 시작했다. 지형 데이터파일과 이미지파일에서 각각 

리소스를 로드하여 화면에 표시하는 부분이다. 타일과 맵 데이터 클래스를 만들고, 파일에서 지형 데이터를

읽어들이는 클래스를 만들었다.

 화면 표시를 담당하는 클래스를 따로 만든 뒤 실행을 해 보았는데 흰 화면만 나타나는 것이었다.

한참을 살펴보아도 잘못된 부분을 찾을 수 없었지만 클래스들을 다시 훑어보다가 정작 메인클래스에는 

아무런 내용도 넣어두지 않았다는 사실을 깨닫고 황당하지 않을 수 없었다. 이러한 착오들을 자주 일으켰기

때문에 다시 겪지 않기 위해 이렇게 기록해두기로 하였다. 



보여질 때는 등각투상도(isometric view)로 보여지지만 맵 데이터는  


이런 식으로 직사각형의 모양을 갖는 2차원 데이터가 기록되어 있다.(기록된 상태는 1차원이겠지만..)

데이터에서 특정 x, y위치에는 어떤 타입의 타일정보가 들어있는가를 읽어와서 타일을 하나씩 화면에 붙인다.

간단한 식을 유도하여 타일들이 표시될 위치를 화면에 들어맞게 잡아준 뒤 결과를 출력해 보았다. 



타일들이 지형을 이루는 것을 보고 한숨을 돌렸다. 데이터대로 맵을 출력하는 걸 성공하긴 했으나 아직 

남은 일들이 아득하다. 그래픽, 세부기획, 구현해야 할 기능들 등등..

 그리고 이중for문을 쓸 때 변수초기화를 빼먹거나 String을 as uint로 캐스팅하려 하는 실수를 범한 상태라

앞으로 또 어떤 착오나 버그들이 나타날지 불안감이 엄습해 온다. 









 


  

+ Recent posts