Overview 1.preprocessing
(Data is always dirty, and once you’ve found your data set, you’ll need to clean it up.) 2.Loading the Data (Acquire and Parse)
(A single location will be defined using a second class named Place.) 3.Drawing a Scatterplot of Zip Codes (Mine and Represent)
(After parsing your data, you must give some consideration to how the data is mapped to the screen.) 4.Highlighting Points While Typing (Refine and Interact)
(the focus is now to add interaction so that users can explore how the postal codes relate to
geography./The refinement stage begins with choosing a set of colors.) 5.Show the Currently Selected Point (Refine)
(we’ll show the location of a fully typedout, five-digit zip code as a rectangle and add text to its
upper-right corner that names the location.) 6.Progressively Dimming and Brightening Points (Refine)
(a class called ColorIntegrator does the same, but interpolates between two colors. Instead of a
float, the ColorIntegrator.target( ) method takes a color.) 7.Zooming In (Interact)
(the crux of the representation is the map( ) function, which remaps a series of coordinates (with a
predefined range) to a specific location on the screen (with a new range)) 8.Changing How Points Are Drawn When Zooming (Refine)
(points should become larger as more digits are typed.) 9.Deployment Issues (Acquire and Refine)
( A better alternative is to use the built-in Thread class to load the data asynchronously.) 10.Next Steps
(several directions in which to take this project.)
Detail 1.DBF file을 받아 데이터를 정리하는 방법
1차 DBF->excel/open office 로 열기->CSV,TSV로 저장->
2차 ->PROCESSING+FITS+CSV(TSV) WITH 8 ISSUES->최종결과치->최종 CLEANED FILE 얻기
2,새로운 텝을 열어 place class를 만들기
pasing을 위해 readData( ) parseInfo( )parsePlace( ) method 이용하기
readData( )->데이터 읽어들이기
parseInfo( )->데이터 파일의 첫번째 single line 분석 with comma (파일개수/위도,경도의 최대 최소값)
parsePlace( )->나머지 single line 분석 with tap
3.map()을 이용하여 stage 내 특정 영역에 데이터 뿌리기
4.입력 텍스트와 관련한 변수,method, array 지정/ keypress handling /depth 와 color를 입력 텍스트 상태에 따라서 match 시키기
char typedChars[] = new char[5]; letters typed
int typedCount; number of digits entered.
float messageX, messageY; location where the text should...
int foundCount; number of locations currently selected.
keyPressed( )
typedPartials[typedCount] 입력되는 코드들을 10으로 나누고 그 몫을 취하여 인식하도록 함 for (int j = typedCount-1; j > 0; --j) { typedPartials[j] = typedPartials[j + 1] / 10; }
int partial[];
int matchDepth;
check()
5.default로 chosen을 null시키고 null이 되지 않았을 때 선택된 점들을 rect()로 그려주는 코드 지정 최종 셀렉트 된 point와 일치하는 지점 위에 텍스트가 위치하는 방식 정의 외곽 등에 존재하는 놈들은 이상하게 보이지 않도록 additional rule 지정
6.입력값과 정확하게 match되는 point만 highlight(target=highlight color) 해주고 나머지는 모두 dimmed(target=unhighlight color) 시키기
7. zoom 상태에 따라서 remap하기 When zoom is not enabled, the horizontal coordinate of a location on screen is calculated by using map( ) to convert the value from the range minX to maxX into the range mapX1 to mapX2. When zooming, we replace minX and maxX with the minimum and maximum values that we want to be visible onscreen.
9.온라인 상의 효율성을 증가시키기 위해 data를 load하는 것을 별도 class로 만들기 class Slurper{
public void run( ) {
} }
void readData( ) { new Slurper( );
}
10.next stap
이번 쳅터의 시스템을 기본으로 하여 그 밖의 다양한 데이터 및 방식으로 접근할 수 있습니다. Germany and the UK 의 zip code
town names/migration patterns
street names
area codes
other questions
additional data sets—whether satellite photography, geographicboundaries, interstate highways,
or map images.
Chapter 4. Time Series • Acquiring a table of data from a text file
• Parsing the contents of the file into a usable data structure
• Calculating the boundaries of the data to facilitate representation
• Finding a suitable representation and considering alternatives
• Refining the representation with consideration for placement, type, line weight, and color
• Providing a means of interacting with the data so that we can compare variables
against one another or against the average of the whole data set
• 데이터 구간설정을 위해 읽어들인 데이터의 최대/최소를 구하는 방법, MIN_FLOT, MAX_FLOAT
• 읽어들인 데이터를 map을 사용하여 디스플레이의 플롯(plot)에 매핑하기
• Labeling
• createFont() 를 이용한 시스템 폰트 사용
• 키보드 입력을 통한 화면 전환
• Too many labels make the diagram look like graph paper, and too few suggests that
only the minimum and maximum values need to be shown.
• % 연산자 (modulo : 나누기 나머지 구하기) - 반복적인 무언가를 할때 활용 가능
if (data % 7 == 0) {
// 여기서 무언가 할일 작성 하면 7의 간격으로 실행됨
}
• Grid 를 제공하여 가독성 높이기
• Vertex 사용하기
beginShape( );
vertex(10, 10);
vertex(90, 30);
vertex(40, 90);
vertex(50, 40);
endShape(); -> endShape(CLOSE); 하면 구간이 닫히고 면적으로 표시됨
• 특정 점에서 Mouse rollover 사용하기 - dist 활용
if (dist(mouseX, mouseY, x, y) < 3) {
// rollover 시 동작 작성
}
Chapter 1. The Seven Stages of Visualizing Data
- characteristics of a data set
- data is a moving target
- Great information visualization never starts from the standpoint of the data set; it starts with questions.
Why was the data collected, what’s interesting about it, and what stories can it tell?
The most important part of understanding data is identifying the question that you want to answer.
- The more specific you can make your question, the more specific and clear the visual result will be.
- Proper visualization is a kind of narrative, providing a clear answer to a question without extraneous
details.
- Each Project Has Unique Requirements
- Who is your audience? What are their goals when approaching a visualization?
Chapter 3. Mapping - 외부에서 데이터를 읽어들이고, 가공하고, 목적에 맞게 사용하는 과정을 공부했습니다.
여기서는 .tsv 라는 저자가 직접 만든 데이터 파일을 다루었고, 우리가 앞으로 주로 다룰 데이터는 이렇게
컴퓨터에 파일로 있는것도 있을 수 있지만, 음악파일, 책 텍스트파일 등을 비롯해 인터넷상에서 얻어지는
데이터들, XML 형식 등 무궁무진하게 다양합니다.
그러나 DB이던 파일이던 XML 이던 데이터 형식이 어떻든 간에, 우리는 일단 최초에 할일이 읽어들일
데이터를 우리의 목적에 맞게 잘라내고 가공해야 한다는 건 공통적입니다.
- 데이터베이스(Database) 와 클래스(Class)에 관한 간략한 설명.
- 이 챕터에서는 저자가 작성해놓은 Table 이라는 데이터를 모델링한 class를 사용하여 데이터를 저장/관리.
- 데이터를 가공할때 자주쓰는 주요 함수(function) 를 공부함
map / norm / lerpColor
- 음/양 부호와 크기를 가지는 데이터를 효과적으로 표현하기 위한 여러가지 방법 시도(크기, 색, 투명도 등등)
- 마우스를 통한 사용자 interaction 요소 추가
- 수치 표시할때 자주쓰는 함수 공부 (자리수)
nf / nfp
- 저자가 만든 Integrator 라는 class 를 활용하여 좀더 값이 부드럽게 변하도록 시도
(이 클래스도 다른곳에서 활용 가능할듯)
1.Papervision3D 관련 class들을 다운받는다. ( http://code.google.com/p/papervision3d/ )
2.Papervision3D는 AS3.0의 기본 계층구조와는 다른 별도의 계층구조를 가지고 있으므로 경우에 따른 상속관계를 잘 따져보아야 한다. (무엇을 상속 받았는가에 따라 가능한 기능이 달라지므로 계층구조를 숙지해야할 필요가 있다.)
3.Papervision3D의 기본 요소(viewPort3D, Sceane3D, Camera3D, BasicRenderEngine )를 익히고 활용해본다.
[SWF (width="640", height="480", frameRate="36", backgroundColor="0xEEEEEE")] //meta tag는 꼭 붙여줍니다.
public class PV3Test1 extends Sprite
{ // 1. ViewPort
private var viewPort:Viewport3D; // 2. Scene3D
private var scene3D:Scene3D; // 3. Camera3D
private var camera3D:Camera3D; // 4. BasicRenderEngine
private var randerEngine:BasicRenderEngine;
//3D Object
private var plan:Plane;
public function PV3Test1()
{
super(); //1.ViewPort 만들고 화면에 붙이기
this.viewPort= new Viewport3D();
this.addChild(this.viewPort); //눈에 보이는 것이므로 addChild //2.Scene3D 만들기
this.scene3D= new Scene3D(); //3.Camera3D 만들기
this.camera3D= new Camera3D();
this.camera3D.zoom=40;
this.camera3D.moveBackward(500); //4.RanderEngine 만들기
this.randerEngine= new BasicRenderEngine();
//3D Object 만들기
this.plan= new Plane();
this.scene3D.addChild(this.plan); //눈에 보이는 것이므로 addChild
위의 코드는 PV3D의 기본 틀이다. 자 이제부터는 위의 기본 요소들을 하나씩 짚어보면서 Papervision3D의 상속관계를 알아본다.
!!!!!상속받은 class로 직접 이동하는 방법.. ctrl을 누르고 원하는 class 이름 위에 커서를 올리면 이름에 underline이 생깁니다. 그 상태에서 class 이름을 클릭하면 곧바로 해당 class 로 이동하게 됩니다. (mac은 사과를 누르세요~) 이러한 방법으로 잘 모르는 class일지라도 상속관계를 찾아들어가 유추할 수 있는 것입니다.
1. ViewPort *상속관계 ViewPort3D -> Sprite
(ViewPort는 Sprite 상속받았으므로 눈에 보이는 것임을 알 수 있다.)
ViewPort는 PV3D에 의해서 만들어지는 화면(이미지/영상)을 플래시에 연결시키는 ... 클래스이다.
PV3D는 flash와는 전혀 다른 독자적인 화면랜더링 방식을 취하기 때문에 PV3D와 flash를 연결해주는 것이 필요하다.
그 역할을 ViewPort가 하는 것이다. { PV3D <--> flash }
2. Scene3D *상속관계 Scene3D -> SceneObject3D -> DisplayObjectContainer3D -> EventDispatcher -> Object (기본 상속관계 뼈대를 벗어나 자기만의 상속관계를 가진다는 것을 알 수 있다.)
Scene3D는 PV3D에서 stage와 같은 역할을 하는 객체이다. 그러므로 container 역할이 필요함( DisplayObjectContainer3D 상속 )
여기서 DisplayObjectContainer3D 는 DisplayObject3D를 담을 수 있는 능력이 있어서
addChild( displayObject3D ) / removeChild / numChildren 와 같은 기능이 가능하다.
( AS3 DisplayObject 기본 계층구조의 DisplayObjectContainer 참조)
3. Camera3D *상속관계 Camera3D -> CameraObject3D -> DisplayObject3D -> DisplayObjectContainer3D -> EventDispatcher -> Object
( DisplayObjectContainer3D을 상속받았다는 것이 매우 중요하다.)
DisplayObject3D ::: 플래시의 Sprite 같은 객체로서
x, y, z, scaleX, scaleY, scaleZ, rotationX, rotationY, rotationZ, alpha, ... addChild/ removeChild 가 가능하다.
기존 flash는 고정 카메라였으나 PV3D에서는 다양한 각도와 움직임이 있기 때문에 상당히 복잡한 메카니즘을 가지게 된다.
4.BasicRenderEngine 만들기 *상속관계 BasicRenderEngine -> AbstractRenderEngine -> EventDispatcher -> Object
플래쉬는 플래시 플레이어가 알아서 랜더링 해주지만 플래시 플레이어는 DisplayObject를 상속받은 객체만 랜더링 해준다...
PV3D는 DisplayObject를 상속받은게 아니라서.... 별로도 랜더링 해 줄수있는... flashPlayer 같은 객체가 필요하다...!!
그 역할을 RenderEngine이 하는 것이다.
*** Plane (for 3D Object) *상속관계 Plane -> TriangleMesh3D -> Vertices3D -> DisplayObject3D -> DisplayObjectContainer3D -> EventDispatcher -> Object
TriangleMesh3D :: 삼각형 면 <--- 안에 내용( material )을 채울 수 있다..
눈에 보이기 위한 최소면 단위는 삼각형이다. (3개 vertexs(점들)이 이루는 최소면 ) 그래서 눈에 보이는 도형들은 모두 TriangleMesh3D 로 만든다. (점 두개가 모이면 선...선은 눈에 보이지 않는다...점 세개가 모이면 면이 된다. 그러므로 최소한의 면은 점 세개가 모여서 만들어진 트라이앵글이다.) 복잡한 도형의 경우 여러개의 triangle을 연결하여 만드는 것이다.
3.Papervision3D 활용 Basic 틀이 되는 코드 만들기 SuperClass: Sprite
[SWF (width="640", height="480", frameRate="36", backgroundColor="0xEEEEEE")] //meta tag는 꼭 붙여줍니다.
public class PV3DTest extends Sprite
{ // 1. ViewPort
private var viewPort:Viewport3D; // 2. Scene3D
private var scene3D:Scene3D; // 3. Camera3D
private var camera3D:Camera3D; // 4. BasicRenderEngine
private var randerEngine:BasicRenderEngine;
//3D Object
private var plan:Plane;
public function PV3DTest()
{
super(); //1.ViewPort 만들고 화면에 붙이기
this.viewPort= new Viewport3D();
this.addChild(this.viewPort); //눈에 보이는 것이므로 addChild //2.Scene3D 만들기
this.scene3D= new Scene3D(); //3.Camera3D 만들기
this.camera3D= new Camera3D();
this.camera3D.zoom=40;
this.camera3D.moveBackward(500); //4.RanderEngine 만들기
this.randerEngine= new BasicRenderEngine();
//3D Object 만들기
this.plan= new Plane();
this.scene3D.addChild(this.plan); //눈에 보이는 것이므로 addChild
내부가 채워지지 않고 뼈대만으로 구성된 사각형 도형이 가운데 축을 중심으로 빙글빙글 돕니다.
참고로 뼈대의 색은 렌덤하게 설정되므로 Test할 때마다 변합니다.
기본이 되는 코드를 별도 class로 만들어 놓으면 기본 사항을 반복하여 코딩하지 않아도 되므로 유용하다.
기본 내용을 포함한 Base3D라는 class를 만들어 저장하고 이것을 Document class로 불러들여 (상속) 활용하도록 해보자.
먼저 flex내에서 Base3D class를 만들기 위한 as 파일을 생성한다.
해당 프로젝트 src폴더에서 오른쪽 마우스 클릭 > new > Actionscript class
팝업이 뜨면 package 이름/ 경로와 as. 파일의 name, 기본적으로 상속받을 Superclass를 지정해준다. (Superclass 시작은 대문자)
package 이름/경로는 본인이 원하는대로 적어주면 자동으로 생성된다.
여기서는 자신이 만든 class를 timo라는 폴더에 넣어두어 관리하고있다.
public class Base3D extends Sprite
{
public var viewPort3D: Viewport3D;
public var scene3D: Scene3D;
public var camera3D: Camera3D;
public var renderEngine: BasicRenderEngine;
public function Base3D( width: Number = 640,
height: Number = 480,
autoScaleToStage: Boolean = false,
interactive: Boolean = false )
{
super(); // 1. viewPort
this.viewPort3D = new Viewport3D( width,height, autoScaleToStage, interactive );
this.addChild( this.viewPort3D ); // 2. stage
this.scene3D = new Scene3D(); // 3. camera
this.camera3D = new Camera3D();
this.camera3D.zoom = 40;
this.camera3D.moveBackward( 500 ); // 4. render
this.renderEngine = new BasicRenderEngine(); // 5. 매 프레임마다 렌더링..
this.addEventListener( Event.ENTER_FRAME, onEnter );
}
private function onEnter( e: Event ): void
{
this.renderEngine.renderScene( this.scene3D, this.camera3D, this.viewPort3D );
}
}//class
}//package
Base3D를 상속받은 여러가지 Document class를 만들어보기
Document calss를 만드는 것은 위의 Base3D class를 만드는 방법과 유사하다. 차이점이 있다면 package를 써주지 않고 as 파일을 생성한 후에 방금 만든 Document calss 파일 위에서 오른쪽 마우스 클릭을 하여 Set as a default application을 체크해주어야 한다는 것이다.
[SWF (width="640", height="480", frameRate="36", backgroundColor="0xEEEEEE")] //Meta tag는 꼭 써줍니다.
public class PV3Test1 extends Sprite
{ //1. viewPort
private var viewPort:Viewport3D; //2.Sceane3D
private var scene3D:Scene3D; //3.camera
private var camera3D:Camera3D; //4.randerEngine 위 네가지 요소가 기본적으로 필요한 필수사항이므로 머리에 기억하고 있어야 한다.
private var randerEngine:BasicRenderEngine;
private var plan:Plane;
public function PV3Test1()
{
super();
//1. viewPort 만들고 화면에 붙이기::스프라이트를 상속받았으므로 눈에보인다.
this.viewPort= new Viewport3D(640,480,false,false); // autoscale은 화면에 꽉 채울 것인지를 묻는 것임 (false가 기본) //interactive는 인터렉션이 가능하도록 할 것인지를 묻는 것임
this.addChild(this.viewPort);
//this.viewPort.scaleX=2; //기준점을 기준으로 화면 스케일을 쭉~ 늘리는 것임 //화면전환을 하고 싶다면 뷰포트 2개를 만들어서 애드차일드를 번갈아 가면서 한다.
//2.Sceane3D 만들기
this.scene3D= new Scene3D();
//3.camera 만들기
this.camera3D= new Camera3D();
this.camera3D.zoom=40;
this.camera3D.moveBackward(500);
//4.randerEngine 만들기
this.randerEngine= new BasicRenderEngine();
//3D 오브젝트 만들기 // 뼈대 이외의 속성들은 material이라는 것으로 컨트롤 한다.(material은 plane 윗라인에 쓰자)
var material:ColorMaterial= new ColorMaterial(0xFF0000);
material.doubleSided=true;
this.plan= new Plane(material); //뼈대를 만드는 것 !!!!!
this.scene3D.addChild(this.plan);
[ SWF (width="640", height="480", frameRate="36", backgroundColor="0xEEEEEE")]//꼭써주자!!
public class PV3DTest2 extends Base3D
{
private var plane:Plane;
private var plane2:Plane; private var planeContainer:DisplayObject3D;
public function PV3DTest2(width:Number=640, height:Number=480, autoScaleToStage:Boolean=false, interactive:Boolean=false)
{ //부모클래스의 생성자 호출 base3d의 것 모두 가짐
super(width, height, autoScaleToStage, interactive); //3D 객체 생성하기
this.createObject3D(); //매 프래임마다 할 일 (객체변화주기)
this.addEventListener(Event.ENTER_FRAME, onEnter);
}
private function createObject3D():void
{ //채울물질 만들기 var material:ColorMaterial= new ColorMaterial(0xFF99999); var material2:ColorMaterial= new ColorMaterial(0xFFF078); //material.doubleSided=true;//2개의 plane을 만들 것이므로 더블사이드일 필요가 없으니 지워준다.
//물질이 채워진 면 만들기 this.plane= new Plane(material); //material을 꼭 넣어주어 해당 요소를 적용시킨다. this.plane2= new Plane(material2); //material을 꼭 넣어주어 해당 요소를 적용시킨다. this.plane.rotationY=180;//2개의 plane의 등이 맡닿을 수 있도록 한쪽면을 180도로 회전시킨다.
//this.scene3D.addChild(this.plane);
//this.scene3D.addChild(this.plane2); this.planeContainer= new DisplayObject3D(); this.scene3D.addChild(this.planeContainer); this.planeContainer.addChild(this.plane); this.planeContainer.addChild(this.plane2);
}
private function onEnter(e:Event):void
{
//this.plane.rotationY+=10;
//this.plane2.rotationY+=10; this.planeContainer.rotationY+=10;
}
}//class
}//package
/* 과정
1. case로 활용할 planeContainer라는 변수를 선언한다. 2. plane을 2개 만들어 2개의 material로 각각 다른 색을 입힌다.
3. 두개의 plane을 planeContainer에 담고 planeContainer를 회전시켜준다. 즉 두가지 오브젝트를 한 case에 넣고 case 자체를
회전하는 것이다.
[ SWF( width="640", height="480", frameRate="36", backgroundColor="0xEEEEEE")]
public class PV3DTest3 extends Base3D
{
public function PV3DTest3( width:Number=640, height:Number=480, autoScaleToStage:Boolean=false, interactive:Boolean=false)
{ // 부모클래스의 생성자 호출..
super(width, height, autoScaleToStage, interactive);
// 3D 객체 생성하기
this.createObject3D();
// 매 프레임마다 할 일... {객체변화주기}
this.addEventListener( Event.ENTER_FRAME, onEnter );
}
private var planeContainer: DisplayObject3D;
private var plane1: Plane;
private var plane2: Plane;
private function createObject3D(): void
{ // 채울 물질 만들기
var material1: ColorMaterial = new ColorMaterial( 0xFF9900 );
var material2: ColorMaterial = new ColorMaterial( 0x0000FF );
// 물질이 채워진 면 만들기
this.plane1 = new Plane( material1, 400, 400 );
this.plane2 = new Plane( material2, 400, 400 );
// this.plane1.x = 200; this.plane2.x = 200;
this.plane2.rotationY = 180;
this.planeContainer = new DisplayObject3D();
this.scene3D.addChild( this.planeContainer );
}
} /* 회전의 중심을 바꾸려면 DisplayObject3D를 Sprite 처럼 활용하자 flash stage와는 다르게 PV3D에서 오브젝트의 중심은 기본적으로 오브젝트의 중심이다. 그러므로 가로 세로길이가 각 400인 오브젝트에서는 그 중심에서 200만큼 증가시키면
한쪽 변을 중심으로 도는 모션을 구현할 수 있다.
노란색 면을 기준으로 하여 왼쪽 모서리를 중심으로 (파란색 면은 오른쪽 모서리) 뱅글뱅글 회전.
[ SWF (width="640", height="480", frameRate="36", backgroundColor="0xEEEEEE")]//꼭써주자!!
public class PV3DTest4 extends Base3D
{
public function PV3DTest4(width:Number=640, height:Number=480, autoScaleToStage:Boolean=false, interactive:Boolean=false)
{
super(width, height, autoScaleToStage, interactive);
this.createObject3D();
this.addEventListener(Event.ENTER_FRAME, onEnter);
}
private var earth:Sphere;
private function createObject3D(): void
{
var bitmapData:BitmapData= new BitmapData(400,300,false,0); bitmapData.perlinNoise( 128,128,8,12345, true, true);//네번째 트루는 말렸을 때 끝이 매끄럽게 연결하는것 // bitmapData.perlinNoise( 128,128,8,12345, false, true);
var material:BitmapMaterial = new BitmapMaterial(bitmapData);
this.earth= new Sphere(material, 300,20,20) //껍질, 반지름 , 가로세로등분
this.scene3D.addChild(this.earth);
}
private function onEnter(e:Event):void
{
this.earth.rotationX+=2;
this.earth.rotationY+=3;
}
}
}
<변경사항>
Object3D를 만들기 위해 함수 createObject3D를 만든다. perlinNoise를 쓰기위해 bitmapData를 상속받는다.
private var earth: Sphere; private var moon: Sphere; private var moonContainer: DisplayObject3D;
private function createObject3D(): void
{
// 지구 만들기 var material1: BitmapFileMaterial = new BitmapFileMaterial( "./img/world.jpg" );
this.earth = new Sphere( material1, 300, 12, 12 );
this.scene3D.addChild( earth );
this.earth.rotationZ = -20;
// 달 만들기 var material2: BitmapFileMaterial = new BitmapFileMaterial( "./img/img1.jpg" );
this.moon = new Sphere( material2, 50, 8, 8 ); this.moon.x = 450;
// 달을 화면에 붙이기 { moonContainer - moon } this.moonContainer = new DisplayObject3D(); this.moonContainer.rotationZ = -25; this.moonContainer.addChild( moon ); this.scene3D.addChild( this.moonContainer );
}
private function onEnter( e: Event ): void
{ this.earth.rotationY += 1; // 지구 자전 this.moonContainer.rotationY += 2; // 달이 지구를 중심으로 공전 this.moon.rotationY += 1; // 달 자전
// this.earth.rotationX += 3;
}
} // class
} // package
과정 moon의 case역할을 하게 될 moonContainer 변수 만들기 ( DisplayObject3D 임포트) earth와 moon 변수 생성하고 각각 material 처리 오브젝트인 moon의 중심점 x위치를 450 만큼 증가 (earth와의 실질적인 거리차이) moon을 moonContainer 에 넣기 moonContainer를 earth를 중심으로 공전하도록 함 earth를 자전하도록 함
moonContainer에 moon을 넣었기 때문에 earth와 rotationY 를 공유할 수 있는 것임 moonContainer를 쓰지 않았다면 각기 다른 기준점으로 공전/자전을 해야함
그렇게 되면 오브젝트가 많아질 경우 각각 기준점이 다르기 때문에 컨트롤하기가 어려워짐 그러므로 컨테이너를 적극 활용하여 움직임 컨트롤를 쉽게 해야함.
지구와 지구 주위를 도는 달 (달 sphere를 만들고 달의 공전 중심을 지구로 설정합니다. this.moonContainer.rotationY += 2; )
Superclass Base3D (특정 개체의 움직임을 절대 중심에 두고 카메라를 이동 시켜보기 )
private var earth: Sphere;
private var moon: Sphere;
private var moonContainer: DisplayObject3D;
private function createObject3D(): void
{ // 지구 만들기
var material1: BitmapFileMaterial = new BitmapFileMaterial( "./img/world.jpg" );
this.earth = new Sphere( material1, 300, 12, 12 );
this.scene3D.addChild( earth );
this.earth.rotationZ = -20;
// 달 만들기
var material2: BitmapFileMaterial = new BitmapFileMaterial( "./img/img1.jpg" );
this.moon = new Sphere( material2, 50, 8, 8 );
this.moon.x = 450;
// 달을 화면에 붙이기 { moonContainer - moon }
this.moonContainer = new DisplayObject3D();
this.moonContainer.rotationZ = -25;
this.moonContainer.addChild( moon );
this.scene3D.addChild( this.moonContainer );
}
private function onEnter( e: Event ): void
{
this.earth.rotationY += 1; // 지구 자전
this.moonContainer.rotationY += 2; // 달이 지구를 중심으로 공전
this.moon.rotationY += 1; // 달 자전
// this.earth.rotationX += 3;
this.camera3D.x += 0.01 * ( 2000 - this.camera3D.x ); this.camera3D.z += 0.01 * ( 2000 - this.camera3D.z ); this.camera3D.y += 0.01 * ( 2000 - this.camera3D.y ); this.camera3D.lookAt( this.earth ); //이차원에서는 좌우상하로 돌아보기만 하면 되지만 삼차원에서는 좌우상하로 바라보고 / 카메라의 위치도 틀어야 한다. //어려운 프로세스이므로 기본적으로 lookAt(특정개체) 를 제공한다. // lookAt(특정개체)를 쓰면 특정개체의 움직임을 화면 정면으로 바라본 채 카메라가 움직인다. 즉 특정 개체는 항상 화면의 중앙에 놓이게 된다. 특정 개체가 절대기준이 되는 것임. lookAt(특정개체)을 dimmed시키고 실험해보면 차이점을 알수 있다.
}
} // class
} // package
로딩하자마자 달과 지구는 앞으로 zoom in되다가 서서히 zoom out 됩니다. 지구와 달은 중앙에서 벗어나지 않습니다.
[SWF (width="550", height="400", frameRate="36", backgroundColor="0x666666")]
public class EmbedTest1 extends Sprite
{ //[ Embed ( source="./img/img0.jpg")] public var ImgClass0:Class; 이와 같은 것을 2줄로 한것 //img0이라는 쏘스 이미지를 포함시키고 그것을 imgClass0라는 이름으로 클라스로 만들겠다.
[ Embed ( source="./img/img0.jpg")]
public var ImgClass0:Class;
[ Embed ( source="./img/img1.jpg")]
public var ImgClass1:Class;
public function EmbedTest1()
{
super();
//Embed로 등록한 ImgClass0을 생성하고 Bitmap형태로 저장하시오.
var img:Bitmap= new ImgClass0() as Bitmap;
this.addChild(img);
var img2:Bitmap= new ImgClass1() as Bitmap;
this.addChild(img2);
[SWF (width="550", height="400", frameRate="36", backgroundColor="0xEEEEEE")]
public class BitmapTest2 extends Sprite
{
private var clip:PolygomClip= new PolygomClip();
private var bitmapData:BitmapData= new BitmapData(550,400,false,0);
private var bitmap:Bitmap= new Bitmap(bitmapData);
[ SWF( width="550", height="400", frameRate="36", backgroundColor="0xEEEEEE")]
public class BitmapTest2 extends Sprite
{ // private var clip: PolygonClip = new PolygonClip();
private var tf: TextField = new TextField();
private var bitmapData: BitmapData = new BitmapData( 550, 400, false, 0 );
private var bitmap: Bitmap = new Bitmap( bitmapData );
public function BitmapTest2()
{
this.tf.autoSize = TextFieldAutoSize.LEFT;
this.addChild( bitmap );
this.addEventListener( Event.ENTER_FRAME, onEnter );
}
private function onEnter( e: Event ): void
{
tf.text = Math.random().toString(); // 행렬 // a: 가로확대, d: 세로확대, b, c ==> 기울임// tx: x 위치, ty: y 위치
var matrix: Matrix = new Matrix();
matrix.a = matrix.d = 2*Math.random();
matrix.tx = 550 * Math.random();
matrix.ty = 400 * Math.random();
// 색상을 랜덤으로..
var colorTransform: ColorTransform = new ColorTransform();
colorTransform.color = 0xFFFFFF * Math.random();
// 객체 새롭게 그리기
this.bitmapData.draw( this.tf, matrix, colorTransform );
// 필터 적용
var blur: BlurFilter = new BlurFilter( 2, 2, 1 );
bitmapData.applyFilter( bitmapData, bitmapData.rect, new Point( 1, 0 ), blur );
}
}
}
//this.bitmapData.draw(this.clip, matrix, colorTransform); // 객체 색상은 ColorTransform으로 변경한다.. //matrix: 위치나 크기를 조절하는 것
[ SWF( width="550", height="400", frameRate="36", backgroundColor="0xEEEEEE")]
public class BitmapTest1 extends Sprite
{
[ Embed( source="./img/img2.jpg")]
private var ImgClass: Class;
private var bitmapData: BitmapData = new BitmapData( 550, 400, false, 0x000000 );
private var bitmap: Bitmap = new Bitmap( bitmapData );
private var bitmapCase: Sprite = new Sprite();
private var tf: TextField = new TextField();
public function BitmapTest1()
{
super();
var img: Bitmap = new ImgClass() as Bitmap;
this.addChild( bitmapCase ); bitmapCase.addChild( bitmap );
bitmapCase.y = 21;
bitmapData.draw( img );
// 현재 화면 카피하는 방법 ::: // 1. BitmapData 생성 // 2. BitmapData를 보여줄 Bitmap을 생성하고 화면에 붙이기 // 3. BitmapData.draw( 카피할화면 ) //비트맵데이타 비트맵 비트맵 케이스 각각 이유와 역할 을 잘 알아야 한다.
// 비트맵 /* - BitmapData -> Object - Bitmap -> DisplayObject - Sprite 화면을 복제하려면, BitmapData.draw() 눈내리는 효과에서 에벡같은 효과를 주고 싶으면 현재의 벡터 기반이 아닌 비트맵으로 전환해준다.
var img: Bitmap = new ImgClass() as Bitmap; 비트맵을 ImgClass라는 이름으로 지정
this.addChild( bitmapCase ); 비트맵케이스를 this에 addChild bitmapCase.addChild( bitmap ); bitmap을 비트맵케이스에 addChild
bitmapCase.y = 21; 비트멥케이스(비트멥과 비트멥데이터를 포함하고 있다)를 21만큼 y축이동
bitmapData.draw( img ); img를 그리기
=>bitmapCase를 쓴 이유는
마우스로 이미지를 찍었을 때 이미지의 좌표값의 기준을 stage가 아니라 이미지 좌표값으로 하여 정확한 컬러값을 얻기위함이다.
[ SWF( width="550", height="400", frameRate="36", backgraundColor="0xEEEEEE")]
public class BitmapTest extends Sprite
{
[ Embed( source ="./img/img0.jpg" )]
private var ImgClass:Class; // 이미지 정보를 담고 있는 데이터 객체 : Object 상속받음..
private var bitmapData: BitmapData= new BitmapData(550,400,false, 0xFF0000 );
// 이미지 정보를 담고있는 bitmapData로부터 이미지를 보여주게 하는... decoder.... // DisplayObject 상속
private var bitmap:Bitmap= new Bitmap( bitmapData );
public function BitmapTest()
{
super();
var img: Bitmap = new ImgClass() as Bitmap;
this.addChild(bitmap);
bitmapData.draw(img); //비트맵 안에 비트맵데이타를 그려라
}
}//class
}//package
// 실제 이미지 정보를 담고 있는 것은 aaa.jpg 처럼.. 파일.. // 화면에 이미지를 보여주게 되는 것은... : 포토샵이나 allsee, 이미지편집툴이다..!! // BitmapData :: 2차원 배열 형태의 데이터 파일로 생각하고 // Bitmap :: BitmapData의 정보를 읽어서 화면에 표시해주는 객체
1.플래쉬에서 버블을 하나 그리고 BubbleClip라는 이름의 무비클립을 만든다.(Export to Actionscript 박스
체크!) 그리고 SWC로 export한다.(저장 위치는 현재 작업하고 있는 해당 project안의 libs 폴더)
2.Bubble.as class를 작성한다.
3. Document class인 BubbleTest.as를 작성한다.
public class Bubble extends Sprite
{
private var clip: BubbleClip = new BubbleClip();
public var vx: Number = 1;
public var vy: Number = 1;
//public var topBound:Number=0; //public var rightBound:Number=800; //public var bottonBound:Number=400;
public static var topBound: Number = 0;
public static var rightBound: Number = 800;
public static var bottomBound: Number = 400;
public static var resistance: Number = 0.95;
public static var gravity: Number = 0.2 ;
public function Bubble()
{
super();
this.setLayout();
}
private function setLayout(): void
{
this.addChild( clip );
} // 움직임 명령이 주어지면, 매 프레임마다 할 액션 등록하기
public function startMove(): void
{
this.addEventListener( Event.ENTER_FRAME, onEnter );
} // 매 프레임마다... 할 일..
private function onEnter( e: Event ): void
{
this.x = this.x + this.vx;
this.y = this.y + this.vy;
//vx,vy가 변하지 않으면 등속도 운동... //-를 이용하면 언젠가는 반대로 움직여야 한다. //빙판과 같은 움직임 서서히 줄어드는 것은 곱하기로 한다.
this.vx = this.vx * Bubble.resistance; //공통으로 사용하는 것이므로 위에서 static처리 해준다. //this.vx.=this.vx*0.98;
this.vy = this.vy + Bubble.gravity;
1.flash에서 원을 하나 그리고 SnowClip라는 이름의 무비클립을 만든다.(Export to Actionscript 박스 체크!) 그리고 SWC로 export한다.(저장 위치는 flex내 현재 작업하고 있는 해당 project안의 libs 폴더)
2.Snow.as class를 작성한다.
3. Document class인 SnowTest.as를 작성한다.
눈내리는 효과
컴퓨터 bit :전기가 충전 / 방전 1,0
2bit ::00/01/10/11
8bit ::00110010 ---->1byte 0~256가지의 정보를 저장할 수 있다.
int::-20억~20억---->4byte
number는 8byte
public var vx:Number=1; ------------>8byte public var vy:Number=1; ------------>8byte public var ground:Number=400; ----->8byte 총 24byte
주로 변수들이 메모리를 차지한다.
그러므로 공유용인지 개별용인지를 구분하여 공유용인 것은 static으로 바꿔주어 메모리 할당량을 줄여준다.
실험을 해보면 static을 쓸때와 그렇지 않을 때 퍼포먼스의 차이가 많이 나게 되는 것을 알 수 있다.
public class Snow extends Sprite
{
private var clip: SnowClip = new SnowClip();
// 속도 변수 :: 외부에서 설정할 수 있도록... public으로 설정 //모든 눈의 속도는 다르므로 개별적으로 가져야한다.
public var vx: Number = 1; // 개별
public var vy: Number = 1; // 개별
// 공유변수는 static 변수로 설정 --> 클래스 변수 //모든 눈이 도달하는 ground위치는 같으므로 ground 변수는 공유해도 된다.
//public var ground: Number = 400; // 공유변수 !!!!! Snow.ground(아래의 static 변수와 비교하며 실험해본다.)
public static var ground: Number = 400; // 공유변수 !!!!! Snow.ground
//메서드는 따로 저장이 되므로 그냥 두고 변수 부분을 최대한 줄여보자!!!!!!! //공유변수는 static 변수로 설정 ====>클래스 변수
// static 함수 ---> 사용의 편의성 Math.random() // static 변수 ---> 공유의 목적...!!
public function Snow()
{
super();
this.setLayout();
this.addEvent();
}
private function setLayout(): void
{
this.addChild( clip );
}
private function addEvent(): void
{
}
// 이 함수가 호출되면, 매 프레임마다 움직이기 시작...!!
public function startMove(): void
{
this.addEventListener( Event.ENTER_FRAME, onEnter );
}
// 땅으로 떨어지고나면, 매 프레임마다 할 일 제거하고, 자신은 parent로부터 삭제 // removeChild할 경우, (하고있는 일을 멈추지 않고 잠깐 강의실을 나가있어라! 와 같은 뜻임) //(removeChild의 경우는 계속 Event.ENTER_FRAME은 여전히 작동중이므로 Event도 지워준다.) // 1. 애니메이션이 있으면 stop()시키고, // 2. EnterFrame 이벤트 삭제하기
if( this.y > Snow.ground ){
this.removeEventListener( Event.ENTER_FRAME, onEnter );
parent.removeChild( this );
}
}