1. 2013년 월별 방문자수 추이
2. 2012년과 2013년의 월별 방문자수비교 그래프
3. 블로그 시작일부터 지금까지 월별 방문자 수
4. 인터넷 브라우저별 페이지뷰 비율
5. 모바일기기별 페이지뷰 비율
|
1. 2013년 월별 방문자수 추이
2. 2012년과 2013년의 월별 방문자수비교 그래프
3. 블로그 시작일부터 지금까지 월별 방문자 수
4. 인터넷 브라우저별 페이지뷰 비율
5. 모바일기기별 페이지뷰 비율
|
private function onSelected($evt:Event):void {
var list:Array = _pathFile.getDirectoryListing();
for (var i:int = 0; i < _pathFile.length; i++) {
list[i].addEventListener(Event.COMPLETE, onFileLoaded);
list[i].load();
}
}
private function onFileLoaded($evt:Event):void
{
trace(1);
}
위와 같은 코드를 작성하고 실행했는데 1이 출력되지 않는 것이었다.
그런데 이렇게 짠 다른 프로그램은 잘 동작하는 현상..
이유는, 그 프로그램에서는 onFileLoaded함수에서 $evt인자를 받아 어떤 처리를 하는데,
여기선 list의 요소를 참조하지 않아서 객체가 못 쓰는 상태(객체의 모든 참조 제거)가 되어버린 것이었다..
결국 list배열을 멤버변수로 둬서 해결..
--------------------------------------------------------------------------
케르발 스페이스 프로그램이라는 게임을 하다가 우연히 일식이 되는 걸 발견해서 찍어봤습니다.
('뮌'에 가려진 태양의 모습)
(케르빈에 가려진 태양의 모습)
========================================================================
loop {
switch(n) {
case 1 : return 3
case 2 : return 4
case 3 : return 5
위와 같이 반복되는 switch문에서
n이 1인 경우와 3인 경우에 값이 반환되는 데 걸리는 시간이 같은거라는 착각이 잠시 들어서
직접 구조를 보기로 했다.
우선 비주얼스튜디오에서 x86어셈블리를 생성해 보았다.
switch(num) {
00D817FC mov eax,dword ptr [ebp-8]
00D817FF mov dword ptr [ebp+FFFFFF30h],eax
00D81805 cmp dword ptr [ebp+FFFFFF30h],0
00D8180C je 00D81822
00D8180E cmp dword ptr [ebp+FFFFFF30h],1
00D81815 je 00D8182D
00D81817 cmp dword ptr [ebp+FFFFFF30h],2
00D8181E je 00D81838
00D81820 jmp 00D81843
case 0: result++; break;
00D81822 mov eax,dword ptr [ebp-10h]
00D81825 add eax,1
00D81828 mov dword ptr [ebp-10h],eax
00D8182B jmp 00D8184C
case 1: result++;break;
00D8182D mov eax,dword ptr [ebp-10h]
00D81830 add eax,1
00D81833 mov dword ptr [ebp-10h],eax
00D81836 jmp 00D8184C
case 2: result++;break;
00D81838 mov eax,dword ptr [ebp-10h]
00D8183B add eax,1
00D8183E mov dword ptr [ebp-10h],eax
00D81841 jmp 00D8184C
default: result++;break;
00D81843 mov eax,dword ptr [ebp-10h]
00D81846 add eax,1
00D81849 mov dword ptr [ebp-10h],eax
}
return 0;
00D8184C xor eax,eax
}
if - else 문을 썼을 때 처럼
num의 값과 case에 있는 값들을 윗쪽부터 차례차례 비교해나간다는 것을 볼 수 있다.
이번에는 액션스크립트 바이트코드를 보자.
다음과 같은 코드를 작성하고 flex sdk에 포함되어 있는 swfdump로 바이트코드를 생성했다.
D0 getlocal0
30 pushscope
D0 getlocal0
24 01 pushbyte 1
68 03 initproperty :n
10 28 00 00 jump L0
09 L1: label
D0 getlocal0
24 11 pushbyte 17
68 05 initproperty :m
10 68 00 00 jump L2
09 L3: label
D0 getlocal0
24 12 pushbyte 18
68 05 initproperty :m
10 5E 00 00 jump L2
09 L4: label
D0 getlocal0
24 13 pushbyte 19
68 05 initproperty :m
10 54 00 00 jump L2
09 L5: label
D0 getlocal0
24 14 pushbyte 20
68 05 initproperty :m
10 4A 00 00 jump L2
D0 L0: getlocal0
66 03 getproperty :n
D5 setlocal1
24 00 pushbyte 0
D1 getlocal1
1A 06 00 00 ifstrictne L6
24 00 pushbyte 0
10 26 00 00 jump L7
24 01 L6: pushbyte 1
D1 getlocal1
1A 06 00 00 ifstrictne L8
24 01 pushbyte 1
10 19 00 00 jump L7
24 02 L8: pushbyte 2
D1 getlocal1
1A 06 00 00 ifstrictne L9
24 02 pushbyte 2
10 0C 00 00 jump L7
10 06 00 00 L9: jump L10
24 03 pushbyte 3
10 02 00 00 jump L7
24 03 L10:pushbyte 3
08 01 L7: kill 1
1B BD FF FF 03 9F FF FF A9 FF FF B3 FF FF BD FF FF
lookupswitch default:L5 maxcase:3 L1 L3 L4 L5
47 L2: returnvoid
예를 들어 A9로 점프하라는 명령이 있으면 L3 : 붙은 곳으로 점프되는 것이다.
코드를 보면, 우선 변수들을 초기화하고 L0으로 점프한다.
그리고 스택에 0을 넣고 ifstrictne명령으로 n과 0을 비교하는 연산을 수행한다.
스택에 들어있는 두 값이 다르면 점프를 하고 같으면 점프하지 않고 다음 인스트럭션을 실행한다.
여기서는 n이 1이므로 L6으로 점프하게 된다.
L6의 ifstrictne에선 값이 같다고 판단되므로 L8로 점프하지 않고 그냥 통과하여
jump 명령에 의해 L7로 점프한다.
여기서 점프하기 전에 스택에 1을 넣어두는데
이 값이 L7의 lookupswitch에서 어디로 분기할지를 결정하게 된다.
이 코드의 lookupswitch에서는 스택에 0이 있을 때 9F FF FF 만큼 점프하고,
1이 있을 때는 A9 FF FF만큼 점프한다. (2의 보수로 음수를 표현한 형태임)
A9 FF FF만큼 점프한 위치에는 L3이 있는데 이 부분의 인스트럭션부터 다시 아래로 실행을 시작한다.
L3으로 가 보면 m에 18을 대압하는 것을 볼 수 있다.
최종적으로는 L2로 점프하여 실행을 마친다.
===========================================================================
(이 글은 tibyte.kr와 cafe.naver.com/sdbx에 동시 게시됩니다.)
플래시를 제작하고 swf파일을 생성하면 액션스크립트 코드는
ABC(Actionscript ByteCode)라는 어셈블리 형식의 코드로 저장됩니다.
swf파일을 재생하면 그 코드를 AVM(Actionscript Virtual Machine) 인터프리터가
한줄씩 읽어서 실행하게 되는것이죠.
FlexSDK에 포함되어있는 swfdump 프로그램을 쓰면 이 코드를 쉽게 볼 수 있습니다.
이곳에서 FlexSDK를 다운로드 받을 수 있습니다.
http://www.adobe.com/devnet/flex/flex-sdk-download.html
그리고 flexsdk가 설치된 경로를 환경변수에 등록해야하는데 이것은 검색을 해 보시면
쉽게 찾을 수 있을겁니다.
flexsdk 세팅을 완료했다면 cmd창을 열고 아래와 같은 명령어를 쳐줍니다.
가령 swf파일의 이름이 abc.swf라면,
swfdump -abc -showbytecode abc.swf > abc.txt
물론 swf파일이 다른 디렉터리에 있다면 경로를 지정해 주어야 합니다.
제대로 실행됐다면 [그림2]와 같이 바이트코드가 있는 파일이 생성됩니다.!
[그림1] cmd창에서 swfdump 실행.
[그림2] 코드가 저장된 txt파일.
==================================================================================
세미콜론 뒤에 커서를 놓고 Ctrl+D를 누르면 윗줄이 그대로 복사된다.
복사 후 필요한 부분만 수정.
------------------------------------------------------------------------------------------------
Alt+Shift 키를 누른 상태에서 ←키와 ↑키를 눌러 블록선택.
선택된 상태에서 4줄의 이름을 한번에 바꿀 수 있다.
==============================================================================================
Adobe Flash Professional CS5 버전에서 CS5.5, CS6, CC로 제작된 fla파일을 열려고 하면 열 수 없다는 오류가 뜨는데,
Flannel이라는 프로그램을 쓰면 그런 상위버전의 fla파일들을 CS5에서 열 수 있다.
http://ajarproductions.com/blog/2012/03/06/flannel-open-newer-fla-files/
공식 블로그에서 바로 다운받을 수 있게 되어있다.
Adobe AIR로 만들어진 프로그램인데 사용방법은 매우 간단하다.
바꿀 파일을 Flannel안으로 드래그하면 끝.
이렇게 잘 열린다!!
===========================================================================================
플래시디벨롭에서 아래와 같은 식을 입력하면
num = (a+b)*(c+b);
num = a*sin(c) + b*cos(d);
세미콜론으로 문장을 마치거나 엔터로 줄바꿈을 하는 순간 이렇게 변해버린다.
num = (a + b) * (c + b);
num = a * sin(c) + b * cos(d);
개인의 선호도에 따라 이런 자동 띄어쓰기가 상당히 거슬릴 수도 있는데
설정창에서 이것을 해제할 수 있다.
Tools메뉴에서 Program Settings에 들어간다.
위 사진에서처럼 ASCompletion항목을 클릭해서
Helpers에 있는 Characters Requiring Whitespace를 확인하고 연산자들을 지운다.
(잘못 지웠을 때를 대비해 어떤 연산자들이 있었는지 기억해 두면 좋을 것이다...)
이 때 = 만 남기고 +를 지운다든지 하면
+= 연산자를 사용했을 때 간격이 떨어져서 + = 가 돼버릴 수 있으니 주의해야 한다.
설정을 마치면 연산자 양 옆에 더 이상 자동으로 간격이 벌어지지 않는다.
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 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 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | package kr.tibyte { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Shape; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Point; import flash.geom.Vector3D; /** * ... * @author */ public class Main extends Sprite { [Embed(source= "../../sample1.png" )] private var SampleImage1:Class; [Embed(source= "../../sample2.png" )] private var SampleImage2:Class; private var _bitmaps:Vector.<Bitmap> = new Vector.<Bitmap>(IMG_NUM); private var _imgArr:Vector.<Sprite> = new Vector.<Sprite>(IMG_NUM); private var _imgWidth: int = 120 ; private var _imgHeight: int = 80 ; private var _r: Number ; //회전반경 private var _yaw: Number = 0 ; private var _container:Sprite = new Sprite(); private const IMG_NUM: int = 6 ; private const THETA: Number = 0.003 * 3 / 180 *Math.PI; //회전각속도 private const MARGIN: int = 20 ; //이미지 간격 public function Main(): void { for ( var i: int = 0 ; i<IMG_NUM; i++) { if (Math.random()> 0.6 ) _bitmaps[i] = new SampleImage1(); else _bitmaps[i] = new SampleImage2(); _bitmaps[i].x = -_bitmaps[i].width/ 2 -MARGIN; _bitmaps[i].y = -_bitmaps[i].height/ 2 ; _imgArr[i] = new Sprite(); _imgArr[i].addChild(_bitmaps[i]); _imgArr[i].width = _imgWidth; _imgArr[i].height = _imgHeight; _container.addChild(_imgArr[i]); } //회전반경을 이미지크기+마진값에 딱 맞게 설정 _r = (_imgWidth+ 2 *MARGIN)/( 2 *Math.tan(Math.PI/IMG_NUM)); _container.x = 200 ; _container.y = 150 ; this .transform.perspectiveProjection.projectionCenter = new Point(_container.x, _container.y); addChild(_container); stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler); stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler); } private function mouseMoveHandler($evt:MouseEvent): void { var old:Point = this .transform.perspectiveProjection.projectionCenter; old.y = stage.mouseY; root.transform.perspectiveProjection.projectionCenter = old; } private function enterFrameHandler($evt:Event): void { //마우스로 회전제어 _yaw += THETA*(stage.mouseX-stage.stageWidth/ 2 ); display(); } private function display(): void { var angle: Number ; for ( var i: int = 0 ; i<IMG_NUM; i++) { angle = _yaw+i* 2 *Math.PI/IMG_NUM; _imgArr[i].x = _r*Math.cos(angle); _imgArr[i].z = _r*Math.sin(angle); //angle과 수직이 되도록 rotationY 를 설정 _imgArr[i].rotationY = ( 180 /Math.PI)*- 1 *(Math.PI/ 2 +angle); /* //rotationY 대신 transform속성으로 회전하기 _imgArr[i].transform.matrix3D.pointAt(new Vector3D(),Vector3D.Z_AXIS, new Vector3D(0, -1, 0)); */ } //다시 그리기 var seq:Vector.< int > = genSequence(IMG_NUM); seq.sort(compare); _container.removeChildren(); for (i = 0 ; i<IMG_NUM; i++) { _container.addChild(_imgArr[seq[i]]); } //z소팅을 위한 비교함수 function compare($a: int , $b: int ): Number { if (_imgArr[$a].z>_imgArr[$b].z) return - 1 ; else if (_imgArr[$a].z==_imgArr[$b].z) return 0 ; else return 1 ; } } private function genSequence($n: int ):Vector.< int > { var arr:Vector.< int > = new Vector.< int >($n); for ( var i: int = 0 ; i<$n; i++) { arr[i] = i; } return arr.concat(); } } } |