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

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

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

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

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







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


podocube





플래시 프로패셔널(CS5 CS5.5 CS6 등)에서 굵은 글씨를 사용하고 싶은데 

이렇게 스타일이 비활성화 상태여서 선택을 못 할 때가 있다.




폰트에 bold스타일이 없는 경우 이렇게 선택할 수 없다.

플래시8 같은 데서 기존에 쓰던 방식으로 글자를 굵게 하려면 아래의 방법을 쓸 수 있다.

굵게 할 텍스트를 선택한 뒤, 메뉴에서 텍스트 - 스타일 - 가상 굵게를 눌러 체크하면 텍스트가 굵게 변하게 된다.




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








작동방법

- 마우스를 휘저어 보세요

- 화면을 클릭하고 마우스를 휘저어 보세요

- 오른쪽 아래 구석에 있는 podo로고를 클릭해 보세요

  한 번 누를 때 마다 노란 불빛이 켜졌다가 꺼졌다가를 반복하며

  불이 켜져 있을 때는 화면에 잔상이 남아서 색다른 모양을 볼 수 있습니다.

  

(1차 수정 : podo로고가 두번씩 눌려서 켜졌다가 다시 꺼지는 버그 수정)



(▼ 이곳에 플래시가 삽입되어 있습니다. 일부 환경에서는 보이지 않을 수 있습니다.) 




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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.geom.Point;
import flash.utils.ByteArray;
import flash.events.MouseEvent;
import flash.geom.ColorTransform;
import flash.filters.GlowFilter;
 
 
const MAX_UNIT:int = 4096;
 
 
var bmpDatF:BitmapData = new BitmapData(1,1,false,0x0000ff);
var bmpDatB:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight,false,0x000000);
var canvas:Bitmap = new Bitmap(new BitmapData(stage.stageWidth, stage.stageHeight,false,0xffffff));
var velVec:Vector.<Point> = new Vector.<Point>(MAX_UNIT);
var posVec:Vector.<Point> = new Vector.<Point>(MAX_UNIT);
var colorVec:Vector.<uint> = new Vector.<uint>(MAX_UNIT);
var blueTransform:ColorTransform = new ColorTransform(0.86,0.86,0.86);
 
 
var datumPoint:Point = new Point(0,0);
var theta:Number = 0;
 
velVec.fixed = true;
posVec.fixed = true;
colorVec.fixed = true;
 
for(var i:int=0; i<MAX_UNIT; i++) {
    velVec[i] = new Point(0,0);
    posVec[i] = new Point(0,0);
    colorVec[i] = getColorByHue(i/MAX_UNIT*i/MAX_UNIT*i/MAX_UNIT*i/MAX_UNIT*360);
}
addChild(canvas);
 
 
 
 
var timer:Timer = new Timer(1000/60);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
 
function timerHandler(evt:TimerEvent):void
{
    canvas.bitmapData.lock();
     
    if(podoed)
        canvas.bitmapData.colorTransform(canvas.bitmapData.rect, blueTransform);
    else
        canvas.bitmapData.copyPixels(bmpDatB,bmpDatB.rect,datumPoint);
         
    var dx:Number;
    var dy:Number;
    var direction:Number;
    var color:uint;
    for(var i:int=MAX_UNIT-1; i>=0; i--) {
        dx = stage.mouseX-posVec[i].x;
        dy = stage.mouseY-posVec[i].y;
        direction = Math.atan2(dy,dx);
         
        velVec[i].x += (i/MAX_UNIT*3.6+0.5)*Math.cos(direction);
        velVec[i].y += (i/MAX_UNIT*3.6+0.5)*Math.sin(direction);
         
        posVec[i].x += velVec[i].x;
        posVec[i].y += velVec[i].y;
         
        velVec[i].x *= i/MAX_UNIT*0.14+0.85;
        velVec[i].y *= i/MAX_UNIT*0.14+0.85;
         
        if(Math.abs(dx)<1&&Math.abs(dy)<1) {
            posVec[i].x = stage.mouseX;
            posVec[i].y = stage.mouseY;
            velVec[i].x = 0;
            velVec[i].y = 0;
        }
        canvas.bitmapData.setPixel(posVec[i].x,posVec[i].y,colorVec[i]);
    }
    canvas.bitmapData.unlock();
}
 
 
stage.addEventListener(MouseEvent.MOUSE_DOWN, clickHandler);
function clickHandler(evt:MouseEvent):void
{
    if(evt.stageX>podo.x && evt.stageX<podo.x+podo.width
       && evt.stageY>podo.y && evt.stageY<podo.y+podo.height) {
        podoClicked(null);
        return;
    }
    for(var i:int=0; i<MAX_UNIT; i++) {
        velVec[i].x = 0;
        velVec[i].y = 0;
        posVec[i].x = evt.stageX;
        posVec[i].y = evt.stageY;
        //velVec[i].y = Math.random()*-20;
         
    }
}
 
function getColorByHue(angle:Number):uint
{
var hue:Number = (angle+0) % 360;
    var variation:uint = uint((hue % 60)/60*0xff);
    var red:uint, blue:uint, green:uint;
    if (hue<60) {
        red = 0xff;
        blue = 0;
        green = variation;
    }
    else if (hue < 120) {
        red = 0xff - variation
        blue = 0;
        green = 0xff;
    }
    else if (hue < 180) {
        red = 0
        blue = variation;
        green = 0xff;
    }
    else if (hue < 240) {
        red = 0x0;
        blue = 0xff;
        green = 0xff-variation;
    }
    else if (hue < 300) {
        red = variation;
        blue = 0xff;
        green = 0x0;
    }
    else if (hue < 360) {
        red = 0xff;
        blue = 0xff-variation;
        green = 0;
    }
     
    return red<<16|green<<8|blue;
}
 
 
var podo:Sprite = new Podo();
podo.width*=0.40;
podo.height*=0.40;
podo.x = stage.stageWidth-podo.width;
podo.y = stage.stageHeight-podo.height;
stage.addChild(podo);
 
var podoed:Boolean = false;
var podoFilter:GlowFilter = new GlowFilter(0xffff00,1,4,4,4,3);
function podoClicked(evt:MouseEvent):void
{
    if(!podoed) {
        podo.filters = [podoFilter];
        podoed = true;
    }else{
        podo.filters = [];
        podoed = false;
    }
}
===========================================================================







자석과 나침반을 단순하게 구현한 것.

체크박스에 체크를 하면 자석이 나타난다.

막대자석 모양이 나타나지만 완벽하게 구현되어 있지는 않다..



▽이곳에 플래시가 삽입되어 있습니다.





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






Flash Professional에서 프레임에 직접 입력하였다.

스테이지에 btn0부터 btn15까지 16개의 버튼이 미리 배치되어 있다.


키보드 방향키로 상하좌우 이동을 하며 엔터 키로 버튼을 누를 수 있다.

코드는 아래에...


 





윈도우 바탕화면에서 아이콘을 키보드로 포커싱하는 것과 비슷하게 동작하도록 했다.
화면에 배치되어 있는 무비클립 객체들의 위치관계를 파악하여 각 방향으로
유출이 가능한지 여부에 대한 유향그래프를 생성한다.
그렇기 때문에 스테이지에서나 스크립트로 버튼의 배치를 바꿔도 
버튼들의 위치관계를 계산하여 문제없이 키보드 초점이동을 할 수 있다. 


코드 :

Hello SyntaxHighlighter

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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import flash.events.KeyboardEvent;
import flash.display.DisplayObject;
import flash.filters.DisplacementMapFilter;
 
const MAX_BTN:int = 16;
const RIGHT:int = 0;
const LEFT:int = 1;
const UP:int = 2;
const DOWN:int = 3;
 
var pressedKey:Array = new Array();
var lastKey:int;
var moveGraph:Array = new Array(MAX_BTN);
var focus:int = 0;
var time:int=0;
 
 
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown_h);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUp_h);
 
setFocus(0);
updateMoveGraph();
 
 
function keyDown_h(evt:KeyboardEvent):void
{
    if(getTimer()-time<50 && lastKey==evt.keyCode) return;
    time = getTimer();
    lastKey = evt.keyCode;
    //if(pressedKey[evt.keyCode] == true) return;
        switch(evt.keyCode) {
            case Keyboard.RIGHT:
            case Keyboard.LEFT:
            case Keyboard.UP:
            case Keyboard.DOWN:
                moveFocus(evt.keyCode);
                break;
            case Keyboard.ENTER:
                selectBtn();
                 
        }
    pressedKey[evt.keyCode] = true;
}
 
function keyUp_h(evt:KeyboardEvent):void
{
    pressedKey[evt.keyCode] = false;
    if(evt.keyCode == Keyboard.ENTER) this["btn"+focus].gotoAndStop("over");
}
 
 
function moveFocus(key:uint):void
{
    if(key == Keyboard.RIGHT) {
        setFocus(moveGraph[focus][RIGHT]);
    }
    else if(key == Keyboard.LEFT) {
        setFocus(moveGraph[focus][LEFT]);
    }
    else if(key == Keyboard.UP) {
        setFocus(moveGraph[focus][UP]);
    }
    else if(key == Keyboard.DOWN) {
        setFocus(moveGraph[focus][DOWN]);
    }
     
}
 
 
function updateMoveGraph():void
{
    var i:int, j:int;
    var dx:Number, dy:Number;
     
    for(i=0; i<MAX_BTN; i++) {
        moveGraph[i] = new Array(4);
        moveGraph[i][RIGHT] = -1;
        moveGraph[i][LEFT] = -1;
        moveGraph[i][UP] = -1;
        moveGraph[i][DOWN] = -1;
    }
    for(i=0; i<MAX_BTN; i++) {
        for(j=0; j<MAX_BTN; j++) {
            if(i==j) continue;
             
            dx = this["btn"+i].x - this["btn"+j].x
            dy = this["btn"+i].y - this["btn"+j].y
             
            if(dx<0 && dx*dx>dy*dy) {
                if(moveGraph[i][RIGHT] == -1)  moveGraph[i][RIGHT] = j;
                else if(getNear(this["btn"+i],this["btn"+j],this["btn"+moveGraph[i][RIGHT]]) == 1) {
                    moveGraph[i][RIGHT] = j;
                }
            }
             
            else if(dx>0 && dx*dx>dy*dy) {
                if(moveGraph[i][LEFT] == -1)  moveGraph[i][LEFT] = j;
                else if(getNear(this["btn"+i],this["btn"+j],this["btn"+moveGraph[i][LEFT]]) == 1) {
                    moveGraph[i][LEFT] = j;
                }
            }
             
            else if(dy>0 && dx*dx<dy*dy) {
                if(moveGraph[i][UP] == -1)  moveGraph[i][UP] = j;
                else if(getNear(this["btn"+i],this["btn"+j],this["btn"+moveGraph[i][UP]]) == 1) {
                    moveGraph[i][UP] = j;
                }
            }
             
            else if(dy<0 && dx*dx<dy*dy) {
                if(moveGraph[i][DOWN] == -1)  moveGraph[i][DOWN] = j;
                else if(getNear(this["btn"+i],this["btn"+j],this["btn"+moveGraph[i][DOWN]]) == 1) {
                    moveGraph[i][DOWN] = j;
                }
            }
             
        }
    }
}
 
 
function getNear(src:DisplayObject, dest1:DisplayObject, dest2:DisplayObject):int
{
    var distance1:Number;
    var distance2:Number;
    distance1 = (src.x-dest1.x)*(src.x-dest1.x)+(src.y-dest1.y)*(src.y-dest1.y);
    distance2 = (src.x-dest2.x)*(src.x-dest2.x)+(src.y-dest2.y)*(src.y-dest2.y);
    if(distance1<distance2) return 1;
    else if (distance1>distance2) return -1;
    return 0;
}
 
 
function setFocus(num:int):void
{
    if(num==-1) return;
    this["btn"+focus].gotoAndStop("up");
    focus = num;
    this["btn"+focus].gotoAndStop("over");
}
 
function selectBtn():void
{
    if(pressedKey[Keyboard.ENTER] != true) {
        this["btn"+focus].gotoAndStop("down");
    }
     
    if(focus==0) {
        //...
    }
    if(focus==1) {
        //...
    }
    if(focus==2) {
        //...
    }
    if(focus==3) {
        //...
    }
     
    //...
    //...
    //...
}


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





연습. (Flash swf포함)

유전적 알고리즘 연습


플래시가 첨부되어 있는 글입니다.




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






관련글 : 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



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












충북선 무궁화호 녹음.






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




+ Recent posts