예전에 개발을 할 때 flash를 개발할 때 arguments같은 기능이 있지 않을까 해서 많이 찾아 헤매었던 기억이 있다. 왜 찾았었냐하면 특정 폰트에 이펙트를 입힌 swf를 많이 그려줘야 하는데 하나하나 만들기 도저히 귀찮아서 못하겠던 것. 그래서 나는 결국 글자를 동적으로 바꿀 수 있는 방법을 구상했고, 그래서 찾아 낸 방법은 FlashVars였다. 


 FlashVars는 Flash에 특정 인자를 전달하여, 로딩할 때 구동되게 하는 방식이다. 상당힌 간결하게 이용이 가능한데, flash에서는 어떻게 받아왔었는지 기억조차 나지 않지만 어쨌든 쉽게 받아왔었다.


 그래서 Flex(Flash Builder)에서 이용하려고 하는데 기억이 안나서 잠시 기억 좀 더듬고 인터넷좀 찾아서 기억해냈다. 하하.


* 보고 따라하실 분들은 맨 아래부터 보시면 되겠다. 위에부터 따라하면 패망함.


우선 FlashVars를 이용하려면 플래시를 불러오는 HTML파일을 수정할 필요가 있다. 기본적으로 Flex를 컴파일하면 생성되는 파일인 Project명.html을 열어보면 아래 두 개의 부분을 주의깊게 봐주자.




우선 첫 번째 소스코드이다. JS에서 swf를 불러오는 것을 생성해주는 부분이다. 여기서 원래 일반 소스에는 


var flashvars = {};

var params = {};


와 같은 방식으로 되어있다. 그러나 flashvars에 새 내용을 추가하고 싶다면 저 두 줄 사이에  


flashvars.변수명 = 값 


으로 작성할 수 있다(물론 꼭 두 번째 줄이어야하는 것은 아니고 swfobject.embedSWF 전에만 하면 될 것 같지만 저게 더 예쁠 것 같다)


예를 들자면


var flashvars = {};

flashvars.id = 3;

var params = {};


으로 하면 된다.




그리고 또 다음 소스에도 비슷한 방향으로 변경해주어야 한다.


원래는 param에 


<param name="FlashVars" value="name=idiot!" />


이 행은 아예 존재하지도 않는다. 그러므로 새롭게 추가하여 value에 key=value쌍으로 추가해주면 된다. 중복적으로 추가해주고 싶을 경우 get request를 설정하듯 key1=value1&key2=value2 와 같은 방식으로 설정할 수 있다.


그리고 소스코드를 수정한다. 




root.loaderInfo.parameters.변수명 으로 접근을 하면 된다.


그러면 성공적으로 이용할 수 있다.



Posted by TY
,

무비클립 내부에 무비클립이 있을 경우 정지와 재생이 뜻대로 되지 않는다. 이를 해결하기 위해 재귀 함수를 간단히 만들어보았다. 재귀로 하지 않는 방법이 있다면 좋겠지만 그런 방법은 잘 생각이 나지 않는다. 음... 


Posted by TY
,

어젠가 그젠가 Deepcopy에 대한 글을 올린 적이 있다. 테스트도 해봤고 해서 너무 잘 되길래 쓰려고 했더니... 어머나.. Movieclip은 안되더라-_-;


 그래서 도움을 구하여보니, export for ActionScript 를 한 다음 new를 해주면 된다 하더라. 여러가지 삽질을 했는데 안되서 다시 질문을 했더니, 친절하게도 예제를 만들어주더라(이 자리를 빌어서 도움을 주신 전수열님께 감사드립니다.)


 아래와 같은 방식으로 처리했다.



1. 만들어진 무비클립(library에 있는 것)의 property에서 Export for ActionScript를 체크해준다.


2. 화면 상의 심볼에 이름을 정해준다.



그리고 소스코드에서 다음과 같이 이용한다.


* 참고로 나는 BulkLoader를 이용한다. MIT LICENSE만세!




public class Test extends Sprite

{

var loader:BulkLoader;

var a:MovieClip;

var b:MovieClip;

public function Test()

{

loader = new BulkLoader("test");

loader.add("duck.swf");

loader.addEventListener(BulkProgressEvent.COMPLETE,onCompleteHandler);

loader.start();

}

public function onCompleteHandler(e:BulkProgressEvent):void

{

a = new(loader.getMovieClip("duck.swf").deco.constructor)();

b = new(loader.getMovieClip("duck.swf").deco.constructor)();

a.x = 100;

a.y = 100;

b.x = 300;

b.y = 300;

addChild(a);

addChild(b);

}

}





그러면 아래와 같은 화면을 얻을 수 있게 된다.




해결이 되서 너무 기분이 좋다!




Posted by TY
,

* 아래 내용은 지돌스타님의 ActionScript 3.0 Prototype 디자인 패턴(http://starpl.com/jidolstar/10052497) 내용을 참고하여 작성된 글입니다. 이해하기 쉽고, 요점만을 알기 위해 작성한 글이라고 생각하시면 되며 깊은 이해를 위해 위의 링크를 타고 이동해서 읽어주시면 감사하겠습니다.


 사실 이 내용은 3일밤낮을 머리싸매고 고민하며 온갖 방법들을 이용해서 Deep copy를 시도하다가 모르겠어서 맘먹고 구글링을 한 3시간 해서 찾아낸 결과이다. 정말 힘들었다. ㅠㅠ


 학생들을 가르치다보면 벽에 부딪히는 부분이 가끔 있다. Call by value Call by reference 차이를 이해를 한다는 것이었다. C언어를 가르칠 포인터를 설명하며 알려주면 쉽게 이해하는 부분이었지만, 요즘 대부분은 모바일의 여파 때문인지 JAVA 먼저 배우는 같다.( 안드로이드 때문 --;) 그래서 들에게 설명할 머릿속에는 포인터로 이해되어있는 내용을 포인터란 단어를 꺼내지 않고 설명하는 것은 상당히 곤란한 일이었다. 그래서 언제나 예시로 배열을 하나 생성해서 대입을 해주고 값을 바꿔서 ' 신기하지? 단순 자료형이 아닌 경우는 주소를 참조하게 되는거야'라고 하며 배열 모양의 메모리에 주소들을 붙이고 주소값을 넣는다며 배열 객체 자체를 출력하며 알려주었던 기억이 난다.


 요즘 대부분의 언어는 객체간의 대입 기호(=) reference형으로 연산을 한다. 그건 어떻게 보면 엄청 좋은 것이지만, 어떤 면으로는 엄청 짜증날 때가 있는데 동일한 객체를 복사해야 때이다.물론 클래스의 원형을 갖고 new 이용하면 되겠지만 비용 소모적인 문제도 있으나 결정적으로 MovieClip 받아왔을 new로 상속받는 방법은 굉장히 까다로우며 후임자가 봤을 경우 몹시 화가날 경우가 있다고 생각했다. 경우에 따라 매번 새롭게 할당받을 수 있으나 그 경우는 트래픽 문제 상 게임엔 적합하지 않다고 생각하여, 리소스로 넘어오는 swf파일에 최대한 추가 작업을 하지 않고 받아오는 방법에 대해서 생각해보아서 다음과 같은 물음에 도달했다.


 "shallow copy가 아닌 deep copy를 as3에서 사용할 수는 없나?"


 예전 as2 시절에는 duplicateMovieClip이라는 함수가 있었다고 하지만 지금은 존재하지 않으며, 인터넷 검색결과 대부분 ByteArray로 파일을 재 할당하여 대입하는 것을 알 수 있었다.


소스는 다음과 같이 구성되어있다.


public function createClone(source:*):*

{

var clone:ByteArray;

clone = new ByteArray();

clone.writeObject(source);

clone.position = 0;

return (clone.readObject());

}


위와 같은 방식으로 구성하면 되는데 위의 방법에 문제가 있다.


그래서 아래와 같은 방식을 이용한다고 한다. 대부분의 외국사이트들도 아래와 같은 방식을 채택하고 있다. 사용자정의 클래스를 복사하려면 이 방법이 더 좋은 것 같다. 


public function createClone(source: *):*

{

var className:String = getQualifiedclassName(source);


try

{

getClassByAlias(className);

}

catch(e:ReferenceError)

{

registerClassAlias(className, getDefinitionByName(className) as Class);

}


var clone:ByteArray;

clone = new ByteArray();

clone.writeObject(source);

clone.position = 0;

return clone.readObject();

}


결론은 MovieClip을 DeepCopy를 하기 위해선 위와 같은 함수를 추가해서 풀어야 한다는 말이다.


도움을 준 이근배(터칭시그널) 님과 전수열(Joyfl) 님에게 감사드립니다.


Posted by TY
,

BulkLoaderdㅔ는 크게 2개의 이벤트로 나눌 수 있따


BulkProgressEvent에서


PROGRESS와 COMPLETE이다.


PROGRESS는 데이터를 로딩할 때 계속 호출되는 이벤트이고, COMPLETE는 모든 데이터를 불러왔을 때 호출되는 이벤트이다.


progress는 로딩의 진행상황 같은걸 알 때 쓰이는데, 사실 나는 이게 로딩화면 말고 과연 쓰이는 곳이 있을까 의문이다 ( --;) 하지만 있음으로 해서 매우 훌륭한 이벤트임은 틀림없다.


한 클래스에서 좀 로더를 여러개 쓰기 싫어서 몇 가지 삽질을 했고 내린 결론이다.


1. 


알다시피 이벤트 기반의 프로그램은 (이게 시분할을 해서 돌아가는건지 모르겠지만) 리스너를 마구 건들면 안되는데 weakreference 로 참조하여 둘 다 호출을 하면 중복호출이 혹시 안되지 않을까 했다.


결론: 둘다 된다. GC에서 reference로 체크를 안해서 빨리 날릴 뿐이지 뭐 별다를 건 없었다. 역시 add를 해줬으면 remove를 해줘야한다.


2. 

그 다음엔 리스너를 add한 후 start하고 리스너를 remove 한 다음에 다른 리스너를 애드를 하면 어떻게 될까?


이벤트 기반이라 로딩은 따로 돌아가고 프로그램은 계속 다음 라인으로 넘어간다. 즉 로딩하기 전에  remove를 하면 어떻게 될까?


결론: ㅎㅎㅎ역시 ㅎㅎㅎ 안됨 ㅎㅎㅎ 




최종도출결론: 그래서 리스너를 두 개로 나누었습니다.


진작에 나눌것을.


...하아...



Posted by TY
,

다들 몸은 건강하신가요. 감기 조심하세요. 감기 1주일 째 빌빌거리고 있습니다.


최근에 깨달은 몇 가지 사항입니다. 기초적인 것이 많을 수도 있습니다.


1. toString() 메서드는 override가 가능하나 override를 작성하지 않는다.

 저는 해당 오브젝트에 대한 내용을 얻어올 때 Object객체에서 getObject()함수를 호출해서 toString()으로 받게 됩니다.


이러면 보통 아래와 같은 형식으로 출력이 되죠.


[object BitmapData]


하지만 저는 각각의 경우를 분할하기 위해서 toString()메서드를 override할 수 있지 않을까 생각했습니다. 


그래서 public override function toString()


와 같은 방식으로 작성을 했는데, 에러가 나더라구요. 그래서 override를 뺐더니 잘 작동을 합니다. 


그래서 위와 같은 방식으로 구분을 할 수 있지 않을까 생각하네요.


2. Dictionary 자료형에서 foreach나 for문을 이용한 iterator 이용

dictionary에서 iterator를 돌리려고 할 때 난감한 경우가 많았던 것 같습니다. 

그래서 조금 뒤져보니 다음과 같은 내용이 나오더라구요.


for(var key:String in dict) {


}


위와 같은 방식을 이용했을 때에 dictionary의 key들을 순서대로 얻어옵니다(제 생각에는 등록된 것의 역순으로 나오는 듯 하더군요.. 아니면 제가 쓰는게 stack형식으로 구현이 되는걸지도^^;;)


value는 다음과 같은 방식으로 얻어올 수 있습니다.


for each(var value:Object in dict)

{


}


저러면 Object만 얻어올 수 있습니다. 만약 두 개를 섞고 싶다면


for(var key:String in dict) {

if(dict.hasOwnPriority(key))

{

value = dict[key];

}

}


와 같은 방식으로 얻어올 수 있습니다.


3.  BulkLoader에서 id로 줘봤자 해당 id로 얻어오는 것은 힘들다

넘어온 Event객체나, loader를 뒤져도 해당 id로 iterate 하는 것은 힘듭니다. 그래서 주소에 충분한 구분자를 둬서 구분해야 합니다.


4. Flash Builder에서 Static Value의 값을 얻어올 수 없다.

 예를 들어서

 ResourceManager라는 클래스를 만들고 모든 변수를 static하게 관리한다고 하면, 디버거에서 Expression에서 얻어올 수 없습니다. 일일히 trace로 찍어야 합니다 --;



Posted by TY
,