2010년 3월 31일 수요일

BitmapData

BitmapData

 

BitmapData 클래스를 사용하면 Bitmap 객체의 데이터(픽셀)를 처리할 수 있다.

BitmapData는 1pixel당 8bit 자리 BitmapData를 가지고 있다.

 

 

 

 

BitmapData 생성시 반듯이 width,heighth 값을 가져야 한다.

BitmapData의 fillColor는 배경색으로 기본적으로 ARGB이다.

 

 

 

:: 모든 UI 객체는 DisplayObject를 가지고 있다.

 

 

 

 

[그림 1]에서 처럼 하나의 이미지 파일에는 위와 같은 정보를 담고 있다. 사진과 같은 UI객체인 이미지 파일은 DisplayObject 이다. DisplayObject 는 눈에 보이는 모든 객체를 말한다.

 

만약 이미지에 대한  픽셀값을 가지고 싶다면 BitmapData의 draw()를 사용하면 된다.

 

 

 

draw() 를 이용하며 DisplayObject가 BitmapData로 떨어진다.

여기서 중요한 건 draw()의 매개변수인 IBitmapDrawable을 반드시 가지고 있어야 한다.

 

 

 

:: DisplayObject(눈에 보이는 모든 객체)는 반드시 IBitmaDrawable을 가지고 있어야한다.

 

사진이나 이미지는 눈에 보이는 객체이므로 DisplayObject를 상속받는다.

 

이 객체를 draw() 하는 순간 BitmapData는 [그림 1]과 같은 정보를 갖게 된다.  

 

5. 다양한 객체 만들기 _ Duplicate (1) 랜덤하게 위치하기

한 개의 클래스를 이용하여 다양한 객체를 만들어 생성하고 제거할 수 있다. 어떻게 하나의 클래스를 가지고 다양한 객체를 만드냐 하면 바로 복제하기를 이용하면 된다.

역시 예제를 통해 이해하는 것이 빠를것 같다. 그럼 예제를 하나 만들어보자.

 

플래시 파일을 하나 열어 하나의 무비클립을 만들고 Linkage 설정에서 class명을 Seed라고 만들자. 반복문을 통해 Seed 클래스 100개를 만들어 크기 및 알파, 필터 값을 적용하는 예제를 만들어보자.

 

[code as3]
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.filters.GlowFilter;

public class DuplicateExample extends Sprite
{
 public function DuplicateExample()
 {
  super(); // Sprite 객체 생성
  configureListener(); // 화면 및 버튼 설정
 }

 /**
  *  @private
  *  
  */
 private var seedBox:Sprite;

 /**
  *  @private
  *  화면 구성 설정
  */
 public function configureListener():void
 {
  seedBox = new Sprite(); // 화면에 붙일 패널 객체 생성
  addChild(seedBox); // 패널 화면에 표시

  redbtn_mc.addEventListener(MouseEvent.CLICK, redbtnClickHandler);
  greenbtn_mc.addEventListener(MouseEvent.CLICK, greenbtnClickHandler);
  bluebtn_mc.addEventListener(MouseEvent.CLICK, bluebtnClickHandler);
 }

 /**
  *  @private
  *  화면 초기화
  *
  *  Sprite.numChildren : 객체의 자식수를 반환  
  *  Sprite.removeChildAt() : index 위치 자식 객체 제거, 최하위 index = 0
  */
  private function removeAllChildren():void
    {
        while(seedBox.numChildren) // 패널에 객체가 없어질때까지 반복
        {
            seedBox.removeChildAt(0); // 지정된 index 위치에 있는 객체 제거
        }
    }

 /**
  *  @private
  *  기본 객체
  *
  *  Math.random() : 0 ~ 1 사이의 난수
  */
 public function redbtnClickHandler(event:MouseEvent):void
 {
  removeAllChildren(); // 화면 Clear

  for(var i:int=0; i<100; i++) // 100개 생성
  {
   var temp:MovieClip = new Seed(); // 표시할 객체 생성

   temp.x = Math.random() * stage.stageWidth; // stage 범위 안에 표시할 수 있도록 x좌표 계산
   temp.y = Math.random() * stage.stageHeight; // stage 범위 안에 표시할 수 있도록 x좌표 계산/

   seedBox.addChild(temp); // 생성한 패널에 객체 표시
  }
 }

 /**
  *  @private
  *  객체 크기 및 알파 조절
  *
  *  Math.random() : 0 ~ 1 사이의 난수
  */
 public function greenbtnClickHandler(event:MouseEvent):void
 {
  removeAllChildren(); // 화면 Clear

  for(var i:int=0; i<100; i++) // 100개 생성
  {
   var temp:MovieClip = new Seed(); // 표시할 객체 생성
   temp.x = Math.random() * stage.stageWidth; // stage 범위 안에 표시할 수 있도록 x좌표 계산
   temp.y = Math.random() * stage.stageHeight; // stage 범위 안에 표시할 수 있도록 y좌표 계산

   temp.scaleX = temp.scaleY = Math.random() * 2; // 객체의 가로, 세로 크기 계산

   temp.alpha = Math.random(); // 임의의 값 적용

   seedBox.addChild(temp); // 생성한 패널에 객체 표시
  }
 }

 /**
  *  @private
  *  객체 Glow 필터 적용
  *
  *  Math.random() : 0 ~ 1 사이의 난수
  */
 public function bluebtnClickHandler(event:MouseEvent):void
 {
  removeAllChildren(); // 화면 Clear

  for(var i:int=0; i<100; i++) // 100개 생성
  {
   var temp:MovieClip = new Seed(); // 표시할 객체 생성

   temp.x = Math.random() * stage.stageWidth; // stage 범위 안에 표시할 수 있도록 x좌표 계산
   temp.y = Math.random() * stage.stageHeight; // stage 범위 안에 표시할 수 있도록 y좌표 계산

   temp.scaleX = temp.scaleY = Math.random() * 2; // 객체의 가로, 세로 크기 계산
   temp.alpha = Math.random(); // 임의의 값 적용

   temp.filters = [ new GlowFilter() ]; // Glow 필터 적용

   seedBox.addChild(temp); // 생성한 패널에 객체 표시
  }
 }
}
}
[/code]

 

 

 

44~46 번째 라인에서 numChildren과 removeChildAt() 이라는 메서드가 나왔다.

그럼 다음번에 numChildren과 removeChildAt()에 대해 알아보자.

 

#FLV 플레이어 완성

[code as3]
package
{
import fl.events.SliderEvent;

import flash.display.Sprite;
import flash.events.*;
import flash.media.Video;
import flash.media.SoundTransform;
import flash.net.NetConnection;
import flash.net.NetStream;

public class Main extends Sprite
{
 public function Main()
 {
  super(); // Sprite 클래스 생성

  configurePlayer(); // player 설정
 }

 private var firstFlag:Boolean = true;

 private var isPlaying:Boolean = false;

 private var isConnection:Boolean = false;

 private var isPause:Boolean = false;

 /**
  *  @private
  *  비디오 파일
  */
 private var videoURL:String = "once.flv";

 /**
  *  @private
  *  비디오 연결
  */
 private var connection:NetConnection;

 /**
  *  @private
  *  비디오 스트림
  */
 private var stream:NetStream;

 /**
  *  @private
  *  비디오 플레이어 설정
  *  
  *  connect() : 로컬 컴퓨터에서 비디오 파일과 연결 중이라면 null로 설정
  *  snapInterval : 볼륨 조절시 값이 증가하거나 감소하는 기준 간격
  */
 private function configurePlayer():void
 {
  connection = new NetConnection(); // 비디오 연결 객체 생성
  connection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); // 비디오 연결상태 이벤트 등록
  connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); // 보안오류 이벤트 등록
  connection.connect(null);

  play_mc.addEventListener(MouseEvent.CLICK, playClickHandler); // 재생버튼 이벤트 등록
  pause_mc.addEventListener(MouseEvent.CLICK, pauseClickHandler); // 일시정지 버튼 이벤트 등록
  stop_mc.addEventListener(MouseEvent.CLICK, stopClickHandler); // 정지버튼 이벤트 등록
  slider_comp.addEventListener(SliderEvent.THUMB_DRAG, volumeSliderHandler); // 볼륨조절 이벤트 등록

  slider_comp.maximum = 1; // 볼륨 최대값 설정
  slider_comp.minimum = 0; // 볼륨 최소값 설정
  slider_comp.snapInterval = 0.1; // 0.1만큼 증가 감소
  slider_comp.value = 0.5; // 초기 볼륨값 설정
 }

 /**
  *  @private
  *  비디오 스트림
  *
  *  attachNetStream : 비디오 스트리밍
  */
 private function setStream():void
 {
  stream = new NetStream(connection); // Connection을 통해 객체 생성
  stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); // 연결된 데이터 가져오는 상태 이벤트 등록
  stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler); // 비동기적 예외발생 이벤트 등록

  var video:Video = new Video();  // 비디오 객체 생성

  video.x = 30; // 비디오 x좌표
  video.y = 10; // 비디오 y좌표

  video.width = 500; // 비디오 너비
  video.height = 330; // 비디오 높이

  video.attachNetStream(stream); // 읽어온 데이터를 화면에 연결
  addChild(video); // 화면에 표시

  isConnection = true; // 비디오 연결됨
 }

 /**
  *  @private
  *  비디오 연결 상태
  */
 private function netStatusHandler(event:NetStatusEvent):void
 {
  switch(event.info.code)
  {
   case "NetConnection.Connect.Success" :
    setStream(); // 비디오 연결 성공시 호출
    break;

   case "NetStream.Play.StreamNotFound";
    trace("Unable to locate video: " + videoURL);
    break;
  }
 }

 /**
  *  @private
  *  비디오 보안 오류
  */
 private function securityErrorHandler(event:SecurityErrorEvent):void
 {
  trace("sequrityError");
 }

 /**
  *  @private
  *  비디오 비동기적 예외 발생
  */
 private function asyncErrorHandler(event:AsyncErrorEvent):void
 {
  trace("async error");
 }

 /**
  *  @private
  *  비디오 재생
  */
 private function playClickHandler(event:MouseEvent):void
 {
  if(isConnection && firstFlag)
  {
   firstFlag = false;
   stream.play(videoURL); // 비디오 파일 재생

   var st:SoundTransform = stream.soundTransform; // 재생되는 비디오 사운드 정보 넘겨줌
   st.volume = slider_comp.value; // 뵬륨 조절
   stream.soundTransform = st; // 변환된 볼륨 재적용
   isPlaying = true; // 재생상태
  }

  if(isPause && !isPlaying) // 정지 중
  {
   stream.resume(); // 정지했던 비디오 스트림 다시 재생
   isPause = false; // 일시정지상태
   isPlaying = true; // 재생상태
  }
 }

 /**
  *  @private
  *  비디오 일시정지
  */
 private function pauseClickHandler(event:MouseEvent):void
 {
  if(isPlaying && !isPause) // 재생 중
  {
   stream.pause(); // 비디오 정지
   isPlaying = false; // 재생상태
   isPause = true; // 일시정지상태
  }
 }

 /**
  *  @private
  *  비디오 정지
  */
 private function stopClickHandler(event:MouseEvent):void
 {
  stream.pause(); // 비디오 정지
  stream.seek(0); // 처음 재생 상태로 돌아감
  isPlaying = false; // 재생 상태
  isPause = true; // 정지상태
 }

 /**
  *  @private
  *  비디오 볼륨
  */
 private function volumeSliderHandler(event:SliderEvent):void
 {
  var st:SoundTransform = stream.soundTransform; // 재생되는 비디오 사운드 정보 넘겨줌
  st.volume = event.value; // 볼륨 조절
  stream.soundTransform = st; // 변환된 사운드 재적용
 }
}
}
[/code]

 

2010년 3월 30일 화요일

#FLV 플레이어 _ (1) Video, NetConnection, NetStream

FLV 플레이어를 만들어보기 전에 용어 몇가지를 알아보자.

 

#FLV(Flash Video)

 

Flash Player를 재생할 수 있는 동영상 파일 포맷이며 확장자는 .flv이다.

 

동영상 인코딩이란 아날로그 영상을 디지털 영상으로 변환해주는 일련의 과정을 말한다.

즉, 각종 장비들의 데이터를 PC에서 재생할 수 있는 동영상 파일로 변환해 주는 과정이란 뜻한다.

 

#인코딩

 

아날로그 형식을 디지털 형식으로 변환.

 

일반 동영상 포맷(AVI, MPEG, MOV)은 swf 실행 중에 실시간으로 로드하여 재생할 수 없다. 그렇기 때문에 swf 런타임에서 실시간 로드가 가능한 포맷인 flv로 변환해야하며, 그 변환과정을 인코딩이라 한다.

 

#스트리밍 

 

파일을 다운로드 하면서 재생하는 방식.  

 

#flv 활용 방법 ( [windows] → [Components] : ctrl + F7)

 

1. FLVPlayback 컴포넌트 :  플레이어 구성 요소들이 다 갖추어져있는 구조.

 

2. Video UI 컴포넌트 : 플레이어 구성 요소들이 분리되어 있어 원하는 위치로 이동시켜 사용.

 

비디오를 변형하여 자신이 만들고 싶은 구조의 플레이어를 제작하려면 Video 클래스를 사용하는 것이 좋다.

 

먼저 FLV Player의 흐름이 어떻게 되는지 살펴보자.

 

 

 

 

1. FLV 파일과 Flash Player와 연결
2. 연결 하려면 NetConnection 클래스 필요
3. 연결 되었으면 NetStream 클래스로 데이터를 받아온다.
4. NetStream으로 받아온 데이터를 Video 클래스에서 재생한다.

 

FLV Player의 흐름은 위와 같다. 그럼 우리가 알아야 할 것은 Video , NetConnection, NetStream 이다. 이것들이 무엇인지 한번 알아보자.

 

Video 클래스

 

실시간 또는 기록된 비디오를 표시한다. 즉, 서버 또는 로컬에 저장된 flv파일이나 사용자의 컴퓨터에서 캡쳐한 실시한 비디오를 재생하는 비디오 객체를 생성한다.

 

쉽게 말하자면 그냥 화면에 표시해주는 것이다.

 

Video 클래스는 단지 화면에 표시하기만 할 뿐이고 실제 비디오 스트림을 재생하려면 attachNetStream()을 사용하여 Video객체에 첨부한 다음 addChlid()를 사용하여 Video 객체를 추가한다.

 

 

 

음.. Video 클래스 만으로는 동영상을 재생 시킬 수 없다.

 

 

NetConnection 클래스

 

클라이언트와 서버를 연결하는 파이프와 같다.  만약 Flash Media Server가 없으면 NetConnection 클래스를 사용해서 로컬 파일 시스템 또는 웹 서버에서 비디오 파일이나 MP3 파일을 재생할 수 있다.

 

 

즉, 파일을 연결짓는 연결고리 역할을 하는 셈이다.

 

 

NetStream 클래스

 

스트리밍에 관련된 것을 관리하는 클래스로 NetConnection 객체 안에 있는 채널이다.

 

 

 

즉, 정지/재생/탐색 등 스트리밍에 관련된 것을 관리하는 클래스이다.

 

 

#사운드를 이용한 mp3 플레이어 완성

지금까지 Sound, SoundChannel, SoundTransform을 이용하여 만들어 보았다. 그렇다면 좀더 시각적인 효과를 넣어 만들어 보자. 지금까지 만들어진 파일에 몇가지를 추가해보자.

사운드 스펙트럼을 추가하여 재생되고 있는 사운드 데이터 파형을 시각적으로 보여주고, 사운드의 진행상태를 파악하기 위해 progress bar를 추가하여 보겠다.

 

[code as3]
package
{
import fl.events.SliderEvent;
import fl.controls.Slider;

import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundTransform;
import flash.net.URLRequest;

public class MyMusic extends Sprite
{
 public function MyMusic()
 {
  super(); // Sprite 클래스(상속하는 상위클래스)  생성.
  configureSound(); // 사운드 설정
 }

 /**
  *  @private
  *   사운드 객체 : 객체 생성시 자동으로 사운드 파일 로드.
  */
 private var music:Sound = new PowerUp(); //new Sound(new URLRequest("힘을내줘.mp3"));

 /**
  *  @private
  *  사운드 채널
  */
 private var channel:SoundChannel;

 /**
  *  @private
  *  현재 재생 위치(ms)
  */
 private var position:Number = 0;

 /**
  *  @private
  *  사운드 변환 : 볼륨 및 패닝 속성 포함.
  */
 private var vol_tran:SoundTransform;

 /**
  *  @private
  *  사운드 스펙트럼.
  */
 private var spectrum:Sprite;

/**
  *  @private
  *  스펙트럼 그리기.
  */
 private var gt:Graphics;

 /**
  *  @private
  *  사운드 ByteArray
  */
 private var ba:ByteArray;

 /**
  *  @private
  *  사운드 초기화
  *
  *  Slider(클래스) snapInterval(속성) : 패닝 slider 이동시 값이 증가하거나 감소하는 기준 간격 설정.
  */
 private function configureSound():void
 {
  pan_slider.maximum = 1; // 패닝 Slider 최대값 설정.
  pan_slider.minimum = -1; // 패닝 Slider 최소값 설정.
  pan_slider.value = 0;    // 기본값 0으로 설정.
  pan_slider.snapInterval = 0.1; // 0.1만큼 증가 감소.
  pause_btn.mouseEnabled = false; // 일시정지버튼 비활성화.
  play_btn.mouseEnabled = true;   // 재생 버튼 활성화.

  pause_btn.addEventListener(MouseEvent.CLICK, pauseButtonClickHandler); //일시정지버튼 이벤트 등록.
  play_btn.addEventListener(MouseEvent.CLICK, playButtonClickHandler); // 재생버튼 이벤트 등록.
  sound_vol.addEventListener(SliderEvent.THUMB_DRAG, volumeSliderHandler); // 볼륨조절 이벤트 등록
  pan_slider.addEventListener(SliderEvent.THUMB_DRAG, panSliderHandler); // 패닝조절 이벤트 등록
 }

/**
  *  @private
  *  재생시간 출력  :  단위시간을 00:00 형식으로 출력
  *
  *  분 : Math.floor(sec/60)
  *  초 : Math.floor(sec%60)
  *  Math 클래스의 유용한 메서드 : Math.ceil() - 올림, Math.round() - 반올림, Math.floor() - 내림  
  */
 private function ConverTime(milli:Number):String
 {
  var n:Number = milli / 1000;  // 입력값이 ms(밀리초)이므로 1000으로 나눠 초단위로 바꿈
  var min:int = Math.floor(n/60); // 분 계산
  var second:int = Math.floor(n%60); // 초 계산
  var min_str:String; // 분 단위 형식 저장
  var second_str:String; // 초 단위 형식 저장
  if(min<10) // 계산된 분이 10보다 작으면
  {
   min_str = "0" + min; // "0" 와 계산된 분을 더해 분의 두자리 형식 만듬
  }
  else // 계산된 분이 10보다 크면
  {
   min_str = String(min); // 계산된 분을 String으로 캐스팅
  }
  if(second<10) // 계산된 초가 10보다 작으면
  {
   second_str = "0" +second; // "0" 와 계산된 초를 더해 초의 두자리 형식 만듬
  }
  else // 계산된 초가 10보다 크면
  {
   second_str = String(second); // 계산된 초를 String으로 캐스팅
  }
  return min_str + ":" + second_str; // 계산된 분과 초를 "00:00" 형식으로 만들어 반환
 }

 /**
  *  @private
  *  사운드 진행상태( progress_mc 와 스펙트럼)
  *
  *  percent(백분율)  :  현재 재생 위치 / 사운드 시간
  *  ByteArray :  만들어진 ByteArray 객체의 크기는 512개의 부동 소수점 값으로 고정.
  *               처음 256개의 값은 왼쪽 채널을, 다음 256개의 값은 오른쪽 채널.
  *  진폭 범위 : -1 ~ 1 (부동 소수점 값)
  */
 private function barEnterFrameHandler(event:Event):void
 {
  var percent:Number = (channel.position / music.length) * 100;
  progress_mc.bar_mc.scaleX = percent; // percent값을 bar_mc에 적용
  position_txt.text = (ConverTime(channel.position)); // 현재 재생 시간
  length_txt.text = (ConverTime(music.length)); //전체 재생 시간

  if(!spectrum)
  {
   spectrum = new Sprite(); // 사운드 스펙트럼을 그려 넣을 Sprite 객체 생성
   gt = spectrum.graphics; // 스펙트럼 그리기위해 Graphics 클래스 생성

   spectrum.y = 150; //  사운드 스펙트럼 위치 설정
   addChild(spectrum); // 사운드 스펙트럼 화면에 표시(Sprite 객체 DisplayObject에 추가)
   ba = new ByteArray(); // 512byte의 사운드 정보를 담음
  }

  gt.clear(); // 스팩트럼 그리기 전에 지움
  gt.lineStyle(1, 0x0000FF, 1); // 선 스타일 지정 : 선의 두께, 색상값, 알파값
  gt.beginFill(0x0000FF, 1); // 색 채우기 : 채울 색상값, 알파값
  gt.moveTo(0, 0); // 현재 위치 이동 : pixel단위

  SoundMixer.computeSpectrum(ba, false); // 사운드 정보 저장, 사운드 파형은 진폭.

  for(var i:uint = 0; i < 512; i++)
  {
   var n:Number = ba.readFloat() * 100;
   gt.lineTo(i, n);
  }
 }

 /**
  *  @private
  *  사운드 종료
  */
 private function barSoundCompletehandler(event:Event):void
 {
  removeEventListener(Event.ENTER_FRAME, barEnterFrameHandler); // 사운드 종료 후 이벤트 제거
 }

 /**
  *  @private
  *  사운드 볼륨
  *
  *  사운드 볼륨 범위 : 0 ~ 1
  *  SoundTransForm의 volume 속성 값 : 0 ~ 1
  *  Slider Component 값(정수값) : -1, 0, 1
  *  event.target : 마우스로 Slider를 클릭한 지점
  *  Slider(클래스) value(속성) : 현재 값을 가져오거나 설정.
  *                               이 값은 최소값과 최대값 사이에서 슬라이더 썸의 위치에 따라 결정.
  *  Slider : maximum = 10, minimum = 0
  */
 private function volumeSliderHandler(event:SliderEvent):void
 {
  vol_tran = channel.soundTransform; // 현재 재생되고 있는 사운드의 볼륨 정보를 넘겨줌.
  vol_tran.volume = event.target.value / 10; // 실제 보륨에 적용하기 위해 단위변환.  
  channel.soundTransform = vol_tran; // 변환된 사운드의 볼륨을 다시 적용.
 }

 /**
  *  @private
  *  사운드 패닝
  *
  *  사운드 패닝 범위 : -1 ~ 1
  *  SoundTransForm의 volume 속성 값 : 0 ~ 1
  *  Slider Component 값(정수값) : -1, 0, 1
  */
 private function panSliderHandler(event:SliderEvent):void
 {
  vol_tran = channel.soundTransform; // 현재 재생되고 있는 사운드의 패닝 정보를 넘겨줌.
  vol_tran.pan = event.value;
  channel.soundTransform = vol_tran; // 변환된 사운드의 패닝 다시 적용.
 }

 /**
  *  @private
  *  일시정지 버튼
  *  channel : 사운드 정지시 등록한 이벤트 제거
  *  progress_mc : 사운드 정지시 진행상황 등록 이벤트 제거
  */
 private function pauseButtonClickHandler(event:MouseEvent):void
 {
  pause_btn.mouseEnabled = false; // 일시정지버튼 비활성화
  play_btn.mouseEnabled = true; // 재생 버튼 활성화

  position = channel.position; // 현재 재생 위치 저장
  channel.stop(); // 사운드 정지

  channel.removeEventListener(Event.SOUND_COMPLETE, barSoundCompletehandler);
  progress_mc.removeEventListener(Event.ENTER_FRAME, barEnterFrameHandler);
 }

 /**
  *  @private
  *  재생 버튼
  *  channel : 재생이 끝나면 다시 재생시킬 수 있도록 이벤트 등록
  *  progress_mc : 지속적으로 현재 재생 위치를 알아오기 위해 이벤트 등록
  */
 private function playButtonClickHandler(event:MouseEvent):void
 {
  pause_btn.mouseEnabled = true; // 일시정지버튼 활성화
  play_btn.mouseEnabled = false; // 재생버튼 비활성화

  channel = music.play(position); // 사운드 재생
  vol_tran = channel.soundTransform;  // 현재 재생되고 있는 사운드의 볼륨, 패닝 정보를 넘겨줌.
  vol_tran.volume = sound_vol.value / 10;

  channel.soundTransform = vol_tran; // 변환된 사운드의 볼륨, 패닝을 다시 적용.

  channel.addEventListener(Event.SOUND_COMPLETE, barSoundCompletehandler);
  progress_mc.addEventListener(Event.ENTER_FRAME, barEnterFrameHandler);
 }
}
}
[/code]

 


2010년 3월 27일 토요일

#사운드를 이용한 mp3 플레이어_(3)SoundTransform

SoundTransform 클래스에는 볼륨, 패닝(왼쪽 스피커와 오른쪽 스피커의 음량 조절) 등에

대한 속성이 포함되어 있다. 따라서 사운드의 볼륨과 패닝을 조절하기 위해서는 SoundTransform 클래스를 이용해야한다.

 

 

SoundTransform 객체를 생성하는 방법에는 두가지가 있다.

 

첫번째

 

[code as3]
var vol_tran:SoundTransform = channel.soundTransform;
[/code]

 

두번째

 

[code as3]
var vol_tran:SoundTransform = new SoundTransform(1, 0);
[/code]

 

첫번째 방법은 SoundChannel 클래스의 soundTransform 속성을 사용하여 생성한다.

 

 

두번째 방법은 SoundTransform 클래스에서 객체를 생성한다.

첫번째 파라미터는 볼륨값이고, 두번째 파라미터는 패닝값이다.

 

 

첫번째 방법을 이용하여 사운드 볼륨과 패닝을 조절하겠다. 그럼 이제 만들어보자.

 

[code as3]
package
{
import fl.events.SliderEvent;
import fl.controls.Slider;

import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundTransform;
import flash.net.URLRequest;

public class MyMusic extends Sprite
{
 public function MyMusic()
 {
  super(); // Sprite 클래스(상속하는 상위클래스)  생성.
  configureSound(); // 사운드 설정
 }

 /**
  *  @private
  *   사운드 객체 : 객체 생성시 자동으로 사운드 파일 로드.
  */
 private var music:Sound = new Sound(new URLRequest("힘을내줘.mp3"));

 /**
  *  @private
  *  사운드 채널
  */
 private var channel:SoundChannel;

 /**
  *  @private
  *  현재 재생 위치(ms)
  */
 private var position:Number = 0;

 /**
  *  @private
  *  사운드 변환 : 볼륨 및 패닝 속성 포함.
  */
 private var vol_tran:SoundTransform;

 /**
  *  @private
  *  사운드 초기화
  *
  *  Slider(클래스) snapInterval(속성) : 패닝 slider 이동시 값이 증가하거나 감소하는 기준 간격 설정.
  */

 private function configureSound():void
 {
  pan_slider.maximum = 1; // 패닝 Slider 최대값 설정.
  pan_slider.minimum = -1; // 패닝 Slider 최소값 설정.
  pan_slider.value = 0;    // 기본값 0으로 설정.
  pan_slider.snapInterval = 0.1; // 0.1만큼 증가 감소.
  pause_btn.mouseEnabled = false; // 일시정지버튼 비활성화.
  play_btn.mouseEnabled = true;   // 재생 버튼 활성화.

  pause_btn.addEventListener(MouseEvent.CLICK, pauseButtonClickHandler); //일시정지버튼 이벤트 등록.
  play_btn.addEventListener(MouseEvent.CLICK, playButtonClickHandler); // 재생버튼 이벤트 등록.
  sound_vol.addEventListener(SliderEvent.THUMB_DRAG, volumeSliderHandler); // 볼륨조절 이벤트 등록
  pan_slider.addEventListener(SliderEvent.THUMB_DRAG, panSliderHandler); // 패닝조절 이벤트 등록
 }

 /**
  *  @private
  *  사운드 볼륨
  *
  *  사운드 볼륨 범위 : 0 ~ 1
  *  SoundTransForm의 volume 속성 값 : 0 ~ 1
  *  Slider Component 값(정수값) : -1, 0, 1
  *  event.target : 마우스로 Slider를 클릭한 지점
  *  Slider(클래스) value(속성) : 현재 값을 가져오거나 설정.
  *                               이 값은 최소값과 최대값 사이에서 슬라이더 썸의 위치에 따라 결정.
  *  Slider : maximum = 10, minimum = 0
  */
 private function volumeSliderHandler(event:SliderEvent):void
 {
  vol_tran = channel.soundTransform; // 현재 재생되고 있는 사운드의 볼륨 정보를 넘겨줌.
  vol_tran.volume = event.target.value / 10; // 실제 보륨에 적용하기 위해 단위변환.
  channel.soundTransform = vol_tran; // 변환된 사운드의 볼륨을 다시 적용.
 }

 /**
  *  @private
  *  사운드 패닝
  *
  *  사운드 패닝 범위 : -1 ~ 1
  *  SoundTransForm의 volume 속성 값 : 0 ~ 1
  *  Slider Component 값(정수값) : -1, 0, 1
  */
 private function panSliderHandler(event:SliderEvent):void
 {
  vol_tran = channel.soundTransform; // 현재 재생되고 있는 사운드의 패닝 정보를 넘겨줌.
  vol_tran.pan = event.value;
  channel.soundTransform = vol_tran; // 변환된 사운드의 패닝 다시 적용.
 }

 /**
  *  @private
  *  일시정지 버튼 
  */
 private function pauseButtonClickHandler(event:MouseEvent):void
 {
  pause_btn.mouseEnabled = false; // 일시정지버튼 비활성화.
  play_btn.mouseEnabled = true; // 재생 버튼 활성화.
  position = channel.position; // 현재 재생 위치 저장.
  channel.stop(); // 사운드 정지.
 }

 /**
  *  @private
  *  재생 버튼
  */
 private function playButtonClickHandler(event:MouseEvent):void
 {
  pause_btn.mouseEnabled = true; // 일시정지버튼 활성화.
  play_btn.mouseEnabled = false; // 재생버튼 비활성화.
  channel = music.play(position); // 사운드 재생.
  vol_tran = channel.soundTransform;  // 현재 재생되고 있는 사운드의 볼륨, 패닝 정보를 넘겨줌.
  vol_tran.volume = sound_vol.value / 10;
  channel.soundTransform = vol_tran; // 변환된 사운드의 볼륨, 패닝을 다시 적용.
 }
}
}
[/code]

 

2010년 3월 26일 금요일

#사운드를 이용한 mp3 플레이어_(2)SoundChannel

사운드 일시정지와 재생을 만들어보자.

 

- 사운드 재생 :  Sound 클래스의 play() 메서드 담당.

- 사운드 일시정지 : SoundChannel 클래스의 stop() 메서드 담당.

 

그런데 Sound 클래스의 play()메서드를 살펴보자.

 

 

 

play() 메서드를 실행하면 리턴값으로 SoundChannel을 반환한다.

따라서 일시정지를 하려면 Sound 클래스의 play() 메서드를 통해 생성해야한다.  

 

 

 

[code as3]
var sound:Sound = new Sound(new URLRequest("힘을내줘.mp3"));

var channel:SoundChannel = sound.play(); // SoundChannel 객체 생성

channel.stop();
[/code]

이렇게 하면 사운드를 정지시킬 수 있께 된다. 정지시킨 다음에 다시 재생을 해보자.

그럼 처음부터 다시 재생이 된다. 처음부터 재생되는 것이 아니라 일시정지된 지점부터 재생되게 하고싶다.

사운드의 정지된 지점을 알고 싶을 때는 SoundChannel 클래스의 position속성을 사용한다.

 

 

 

[code as3]
var position:Number = 0;

var sound:Sound = new Sound(new URLRequest("힘을내줘.mp3"));

var channel:SoundChannel = sound.play(); // SoundChannel 객체 생성

position  = channel.position;  // 사운드가 재생되는 현재위치 저장.

channel.stop(); // 사운드 정지.

sound.play(position); // 사운드가 저장된 위치부터 다시 재생.
[/code]


 

그럼 제대로 한번 만들어보자.

새로운 플래시 파일을 하나 만들고 거기에 2개의 무비클립 재생버튼(play_btn)과 일시정지버튼(pause_btn)을 만들어 사운드가 재생, 일시정지 되도록 만들어보자.

 

[code as3]
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.net.URLRequest;

public class MyMusic extends Sprite
{
 public function MyMusic()
 {
  super(); // Sprite 클래스(상속하는 상위클래스)  생성
  configureSound(); // 사운드 설정 메서드 호출
 }

 /**
  *  @private
  *   사운드 객체 : 객체 생성시 자동으로 사운드 파일 로드
  */
 private var music:Sound = new Sound(new URLRequest("힘을내줘.mp3"));

 /**
  *  @private
  *  사운드 채널
  */
 private var channel:SoundChannel;

 /**
  *  @private
  *  현재 재생 위치(ms)
  */
 private var position:Number = 0;

 /**
  *  @private
  *  사운드 버튼 설정
  */
 private function configureSound():void
 {
  pause_btn.mouseEnabled = false; // 일시정지버튼 비활성화
  play_btn.mouseEnabled = true;   // 재생 버튼 활성화
  pause_btn.addEventListener(MouseEvent.CLICK, pauseButtonClickHandler); //일시정지버튼 이벤트 등록
  play_btn.addEventListener(MouseEvent.CLICK, playButtonClickHandler); // 재생버튼 이벤트 등록
 }

 /**
  *  @private
  *  일시정지 버튼 클릭
  */
 private function pauseButtonClickHandler(event:MouseEvent):void
 {
  pause_btn.mouseEnabled = false; // 일시정지버튼 비활성화
  play_btn.mouseEnabled = true; // 재생 버튼 활성화
  position = channel.position; // 현재 재생 위치 저장
  channel.stop(); // 사운드 정지
 }

 /**
  *  @private
  *  재생 버튼 클릭
  */
 private function playButtonClickHandler(event:MouseEvent):void
 {
  pause_btn.mouseEnabled = true; // 일시정지버튼 활성화
  play_btn.mouseEnabled = false; // 재생버튼 비활성화
  channel = music.play(position); // 사운드 재생
 }
}
}
[/code]

 

 

 

 

실행시켜보자.

#사운드를 이용한 mp3 플레이어_(1)Sound

사운드를 이용하기 위해서는 사운드의 재생, 로드, 정지, 볼륨 등의 기능을 담당하고 있는

각각의 클래스를 알아야한다. 사운드 관련 클래스는 flash.media 패키지에 안에 있다.

 

사운드의 기능을 담당하는 클래스들이 분리되어 있어 패키지안에 있는 클래스를 잘 알아봐야한다. 주로 쓰이는 클래스들을 간다히 정리해보자.

 

 flash.media.Sound  사운드 로드 및 재생
 flash.media.SoundChannel  사운드 채널 볼륨 제어
 flash.media.SoundLoaderContext  보안 / 버퍼링
 flash.media.SoundMixer  스트리밍사운드 제어
 flash.media.SoundTransform  패닝 및 볼륨 조절

참조

 

https://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/ 

 

http://help.adobe.com/ko_KR/AS3LCR/Flash_10.0/index.html?flash/display/Graphics.html&flash/display/class-list.html

 

1.  Sound 클래스

 

 

Sound 객체를 만들고 외부 MP3파일을 해당 객체로 로드할여 재생할 수 있으며, 사운드 스트림을 닫고, 스트림의 바이트 수 및 ID3 메타데이터에 대한 정보 같은 사운드 관련 데이터에 액세스할 수 있다. 한마디로 주요 기능은 외부 MP3 파일을 로드, 재생 한다는 것이다.

 

 

주요 기능인 로드, 재생 메서드를 살펴보자.

 

 

 

 

1.1 외부 사운드 파일 재생(mp3 포맷만 지원)

 

사운드를 재생하면 먼저 Sound객체를 이용하여 Sound 객체를 만들어야한다.

 

여기서 알아야 할 것은 외부에서 파일을 불러오려면 URLRequest 클래스를 이용해야한다.

위의 메서드에서 봤듯이 Sound 클래스에서 파일을 로드할 때 첫 번째 파라미터인 stream은
URLRequset로 되어있다.

 

URLRequest 클래스는 " 하나의 HTTP 요청에 포함된 모든 정보를 캡처 "하는 클래스이다.

 

캡쳐?..음..이해가 잘 안되는 군...그래서 야훔님께서 해주신 설명에 따르면...

 

# URLRequest 클래스

 

- 통신을 하기위해 기본적으로 갖춰야할 데이터를 저장하는 VO 클래스라고 볼 수 있다.

   

# VO 클래스(Value Object)

 

-  값을 저장 하기 위해 미리 Field를 만들어두고 값을 저장하게 끔 만들어진

   모델 데이터 클래스를 이야기한다.

 

잘 이해가 안될것 같아 다음번에 예제를 통해 다시 설명을 하겠다.

 

어쨌든 외부에서 파일을 가져오려면 URLRequest를 이용해서 가져와야한다는 것만 알아두자.

그럼 이제 하나씩 만들어보자.

 

플래시에서 파일 하나를 만들자.

 

 

 

 

 

위에서 처럼 플래시파일, AS파일, 음악 파일은 한 폴더안에 만들었다. 그러고나서 설정해야하는 것이 플래시파일 properties 에서 class로 연결해 주어야한다.

 

 

 

[code as3]
package
{
import flash.display.Sprite;
import flash.media.Sound;
import flash.net.URLRequest;

public class MyMusic extends Sprite
{
 public function MyMusic()
 {
  super();

  var file:URLRequest = new URLRequest("안녕나의사랑.mp3");

  var music:Sound = new Sound();
 
  music.load(file);
  music.play();
 }
}
}
[/code]

 

실행시켜보자. 노래가 잘 나오는가? 음..로드가 잘되었군.

 

13번째~18번째 라인을 이렇게도 쓸수있다.

 

[code as3]
var music:Sound = new Sound(new URLRequest("안녕나의사랑.mp3"));

music.play();
[/code]

 

2010년 3월 25일 목요일

(3) 충돌 감지 _ hitTestPoint()

hitTestPoint()

 

hitTestPoint(x:Number, y:Number, shapeFlag:Boolean = false):Boolean 메서드는 영역대 포인트를 감지해서 hit를 발생시킨다. 여기서 말하는 영역이란 Flash에서 무비클립을 하나 만들면 그 무비클립 외각에 생기는 사각형 영역을 말한다. point는 객체를 말하는 것이다.

즉, 객체만을 인식하겠다는 것이다.

 

hitTestPoint()는 DisplayObject클래스의 메서드로 3개의 매개변수를 갖는다.

 

hitTestPoint(x:Number, y:Number, shapeFlag:Boolean = false):Boolean

 

x는 x좌표, y는 y좌표, shapeFlag는 객체(true)의 실제 픽셀을 검사할 것인지 아니면 경계 상자(false)를 검사할 것인지를 나타낸다.

 

여기서 shapeFlag = true로 하면 영역을 인식하는 것이 아니라 객체만 인식하겠다는 것이다.

 

[code as3]
package
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.Timer;

public class Main extends Sprite
{
 public function Main()
 {
  super();

  setTimer();
 }

 private function setTimer():void
 {
  var timer:Timer = new Timer(200, 50);

  timer.addEventListener(TimerEvent.TIMER, timerEventHandler);

  timer.start();
 }

 private function timerEventHandler(event:TimerEvent):void
 {
  var temp:Star = new Star();
  temp.tx = Math.random()* 3 + 1;
  temp.ty = Math.random()* 3 + 1;

  addChild(temp);

  temp.addEventListener(Event.ENTER_FRAME, tempEnterFrameHandler);
 }

 private function tempEnterFrameHandler(event:Event):void
 {
  var mc:MovieClip = MovieClip(event.target);

  if(mc.x < 0 || mc.x > stage.stageWidth)
  {
   mc.tx = -mc.tx; // swiching해줌
  }

  if(mc.y < 0 || mc.y > stage.stageHeight)
  {
   mc.ty = -mc.ty;
  }

  if( bg.hitTestPoint(mc.x, mc.y, true))
  {
   mc.gotoAndStop(2);

   mc.rotate = -5; //  dynamic 변수
  }
  else
  {
   mc.gotoAndStop(1);
   mc.rotate = 5;
  }

  mc.x += mc.tx;
  mc.y += mc.ty;
  mc.rotation += mc.rotate;
 }
}
}
[/code]

 

 

30~31번째 라인에서 정의 되지 않는 속성 tx, ty를 사용하였는데 이렇게 정의 되지 않는 속성을 사용할 수 있는 것은 MovieClip이 다이나믹으로 정의되어 있어서이다.

 

 

 

MovieClip이 다이나믹으로 되어있어서 변수명을 아무렇게나 지정해 주어도 생성한다.

대표적인 예로 object가 있다.

 

[code as3]
var o:Object = new Object();

o.a = 1; // 속성에는 a, b 가 없지만 a,b를 생성해준다.
o.b = 2

trace(a); // 1 출력
trace(b); // 2 출력
[/code]

 

(2) 충돌감지 _ hitTestObject()

hitTestObject()

 

hitTestObject(obj:DisplayObject):Boolean 메서드는 영역 대 영역을 감지하여 hit를 발생시킨다. 여기서 말하는 영역이란 Flash에서 무비클립을 하나 만들면 그 무비클립 외각에 생기는 사각형 영역을 말한다.

 

 

위에서 파란색 사각형이 핑크색 무비클립의 영역에 해당한다. 그럼 이제 hitTestObject() 메서드를 이용한 예제를 한번 만들어보자.

 

[code as3]
package classes.display
{
import flash.display.Sprite;
import flash.events.MouseEvent;

public class Main extends Sprite
{
 public function Main()
 {
  super();

  cir_mc.addEventListener(MouseEvent.MOUSE_DOWN, cirMouseDownHandler);
  cir_mc.addEventListener(MouseEvent.MOUSE_UP, cirMouseUpHandler);
  rect_mc.addEventListener(MouseEvent.MOUSE_DOWN, rectMouseDownHandler);
  rect_mc.addEventListener(MouseEvent.MOUSE_UP, rectMouseUpHandler);
 }

 private function cirMouseDownHandler(event:MouseEvent):void
 {
  cir_mc.alpha = 0.3;
 }

 private function cirMouseUpHandler(event:MouseEvent):void
 {
  if(cir_mc.hitTestObject(cirFrame_mc))
  {
   cir_mc.x = cirFrame_mc.x;
   cir_mc.y = cirFrame_mc.y;
  }
 }

 private function rectMouseDownHandler(event:MouseEvent):void
 {
  rect_mc.alpha = 0.3;
 }

 private function rectMouseUpHandler(event:MouseEvent):void
 {
  if(rect_mc.hitTestObject(rectFrame_mc))
  {
   rect_mc.x = rectFrame_mc.x;
   rect_mc.y = rectFrame_mc.y;
  }
 }
}
}
[/code]

 

 

위의 핑크 사각형을 드래그해서 점선 사각형 안에 넣으면 hit가 발생한다. 음...사각형으로 해서 그런가 그닥 와닿지 않는것 같아 원형으로 한번 더 만들어 보겠다.

 

 

위의 원을 점선 원안에 넣으면 hit가 발생한다. 원과 원이 닿지도 않았는데 hit가 발생했다.

이것이 바로 영역을 인식하여 hit를 발생시키는 hitTestObject()이다.

 

 

이제 조금 감이 오는가? 이렇게 무비클립자체의 shape가 닿아서 발생하는 것이 아니라

무비클립 외각의 사각형 영역끼리 닿으면 hit가 발생하는 것, 이것이 hitTestObject()이다.

 

위의 코드에 해당하는 실제 예제는 아래와 같다.

 

2010년 3월 24일 수요일

Symbol의 Linkage 설정

Linkage 설정

 

1. 플래시 파일에서 심볼을 만들고, 그 심볼을 Linkage 시킬 때, Class명 과 Base class명을

   입력할 수 있다. 처음에는 자동으로 심볼명과 같은 이름이 입력된다.

  

   플래시에서는자동으로 심볼을 클래스로 만들어 주는데, Linage에서 설정한 Class명을

   가지고 클래스를 만든다는 것이다. 그러므로 Class명은 꼭 대문자로 써 주어야 한다.

 

 

여기선 circle이라는 이름을 가진 심볼을 Circle이라는 이름의 클래스를 만들어 Linkage 시키겠다는 것이다. (대소문자 구분) Class명 주는 부분 아래에 보면 Base class라는 것이 있다.

 

 

Class는 Base class를 상속받는다. 위의 내용으로 설명하자면 Circle 클래스는 flash.display 패키지에 있는  MovieClip 클래스를 상속받는 것이다.

 

즉,  Class extends Base class 이렇게 되는 것이다.

 

만약, Class 명과 Base class 명이 같다면 Class는 자기자신이 된다.

(왜냐하면 자기자신을 상속받았으니까.)

 

2.  플래시에서 만든 무비클립은 Sprite로 만든 것보다 무겁다는 것이다. 그래서 애니메이션등과 같은 것을 만드는 것이 아니면 Sprite로 만들어 addChild() 시켜 사용하는 것이 더 좋다.

 

https://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/

 

2010년 3월 23일 화요일

(1) Drag & Drop

먼저 간단한 예제를 하나 만들어보자.

 

[code as3]
package classes.display
{
import flash.display.Sprite;
import flash.events.MouseEvent;

public class DragExample extends Sprite
{
 public function DragExample()
 {
  super();

  buttonMode = true;
  addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
  addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
 }
 private function mouseDownHandler(event:MouseEvent):void
 {
  this.startDrag();
 }
 private function mouseUpHandler(event:MouseEvent):void
 {
  this.stopDrag();
 }
}
}
[/code]

 

 

위의 핑크색 사각에 마우스를 대면 손모양으로 바뀌며 사각형을 드래그 할 수 있다.

 

그런데 Sprite 메서드에서 startDrag()메서드에 2개의 매개변수값을 지정할 수 있었다.

startDrag(lockCenter :Boolean = false, bounds;Rectangle = null) 이렇게..

 

(1) lockCenter : Boolean

 

lockCenter는 " 드래그 가능 Sprite가 마우스 위치의 가운데에서 잠기는지(true) 아니면 사용자가 Sprite를 맨 처음 클릭한 곳에서 잠기는지(false)를 지정한다 "라고 설명을 해 놓았지만.. 무슨말인지...그래서 위에 있는 코드에 값을 넣어보겠다.

 

[code as3]
package classes.display
{
import flash.display.Sprite;
import flash.events.MouseEvent;

public class DragExample extends Sprite
{
 public function DragExample()
 {
  super();

  buttonMode = true;
  addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
  addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
 }
 private function mouseDownHandler(event:MouseEvent):void
 {
  this.startDrag(true, null);
 }
 private function mouseUpHandler(event:MouseEvent):void
 {
  this.stopDrag();
 }
}
}
[/code]

 

18번째 라인에 lockCenter값을 true로 넣어주었다. 실행결과를 확인해 보면 핑크사각형 위의 어느 부분에서든 마우스를 클릭하게 되면 그 클릭한 부분이 중심이 되어 lock이 되는 것이다.

 

 

 

loockCenter = true 로 하면 위와 같이 되며 일반적으로 false이다.

 

(2) bounds : Rectangle

 

bounds는 " Sprite의 제한 영역을 지정하는 Sprite의 부모의 좌표와 관련된 값입니다. "이다.

음...Sprite의 제한영역을 지정한다...한번 만들어보자.

 

[code as3]
package classes.display
{
import flash.display.Sprite;
import flash.geom.Rectangle;
import flash.events.MouseEvent;

public class DragExample extends Sprite
{
 public function DragExample()
 {
  super();

  buttonMode = true;
  addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
  addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
 }
 private function mouseDownHandler(event:MouseEvent):void
 {
  var rectangle:Rectangle = new Rectangle( 0, 0, 200, 200);  

  this.startDrag(false, rectangle);
 }
 private function mouseUpHandler(event:MouseEvent):void
 {
  this.stopDrag();
 }
}
}
[/code]

 

 

19번째 라인에서 Rectangle클래스를 이용하여 일정한 영역만큼 값을 주어 그 영역 안에서만 움직일 수 있도록 하였다. 이것이 bounds이다. 위의 핑그색 사각형을 이동시켜보면 파란색 영역까지만 움직인다. 이렇게 영역을 제한하는 것이 bounds이다.

 

음....그런데 여기서 뭔가 이상한 걸 느끼지 않았나? 잘 보면 사각형을 마우스 다운해서 이동시킨 후에 파란색 영역 바깥에서 마우스 업시키면 계속해서 사각형이 이동한다.

 

MouseEvent.MOUSE_UP은 객체를 마우스 다운해서 이동시킨 후 그 객체 위에서 마우스 업을 하지 않으면 계속 이동(Drag)된 상태가 유지된다.

 

만약, 객체 위에서가 아닌 다른 영역에서 MOUSE_UP이 되게 하고 싶으면 stage를 쓰면된다.

브라우저(Flash® Player)에서 실행 중인 SWF 내용의 경우 Stage는 Flash 내용이 표시되는 전체 영역을 나타낸다.(가장 최상위)

 

 

[code as3]
package classes.display
{
import flash.display.Sprite;
import flash.geom.Rectangle;
import flash.events.MouseEvent;

public class DragExample extends Sprite
{
 public function DragExample()
 {
  super();

  buttonMode = true;
  addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
  stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
 }
 private function mouseDownHandler(event:MouseEvent):void
 {
  var rectangle:Rectangle = new Rectangle( 0, 0, 200, 200);  

  this.startDrag(false, rectangle);
 }
 private function mouseUpHandler(event:MouseEvent):void
 {
  this.stopDrag();
 }
}
}
[/code]

 

 

 

15번째 라인에서 이벤트를 stage에 걸어주어 사각형 바깥영역에서 마우스 업이 되게 하였다.

 

* Drag & Drop을 배우면서 얻은 정보 *

 

mouseDownHandler 같은 메서드는 많이 쓰인다. 만약, 이 mouseDownHandler를 쓰고 있는 클래스를 상속받는 곳에서 다시 mouseDownHandler를 사용해서 쓰려고 하면 충돌나서 에러난다. 따라서 상속하려는 상위클래스의 mouseDownHanlder를 protected로 지정해 주어 사용하면 된다.

2010년 3월 22일 월요일

4.Sprite 클래스

Sprite 클래스

 

Sprite 클래스는 MovieClip 클래스의 기능을 대체하는 클래스로 타임라인이 필요 없는 객체에 적합한 기본 클래스이다. Sprite는 일반적으로 타임라인을 사용하지 않는 사용자 인터페이스(UI) 구성요소에 대한 논리 기본 클래스가 된다.

 

 

   

     참조 : www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/

 

Sprite 클래스에 대해서도 간다히 알아봤으니, 이제 속성과 메서드를 알아보자.

 

 속성


 buttonMode : Boolean  버튼 모드
 dropTarget : DisplayObject

[read-only]

 드래그하는 Sprite 아래 

 의 표시 객체 또는

 Sprite를 드래그해 놓은

 표시 객체를 지정.

 graphics : Graphics

[read-olny]

 벡터 드로잉 명령을 내

 릴 수 있는 이 Sprite에 

 속한 Graphics 객체를

 지정.

 hitArea : Sprite  Sprite의 히트 영역으로

 사용할 다른 Sprite를

 지정.

 soundTransform : 

 SoundTransform

 Sprite 내에서 사운드를

 제어.

 useHandCursor :

 Boolean

 buttonMode 속성이

 true로 설정된 Sprite 위

 로 마우스를 움직일 때

 손 모양(손 모양 커서)을

 표시할지 여부를 나타내

 는 부울 값.


메서드

 

 Sprite()  Sprite 객체 생성

 startDrag

(lockCenter:Boolean = false, bounds:Rectangle = null):void

 지정된 Sprite를 드래그

 할 수 있도록 함.

 stopDrag():void  starDrag() 메서드 종료.

Sprite 클래스에는 위와 같은 속성과 메서드들이 있다. 이제 이것을 이용하여 예제를 만들어 보자.

 

 

Actionscript 3.0 _ code templete(주석달기)

[code as3]
package
{
 //-------------------------------------------------
 //
 //  Import
 //
 //-------------------------------------------------
 //-------------------------------------------------
 //
 //  Constants
 //
 //-------------------------------------------------
 //-------------------------------------------------
 //
 //  Embeded Images
 //
 //-------------------------------------------------
 //-------------------------------------------------
 //
 //  Constructor
 //
 //-------------------------------------------------
 /**
  *  Constructor
  */
 //-------------------------------------------------
 //
 //  Variables
 //
 //-------------------------------------------------
 /**
  *  @private
  */
 //-------------------------------------------------
 //
 //  Override Properties
 //
 //-------------------------------------------------
 //-------------------------------------------------
 //
 //  Properties
 //
 //-------------------------------------------------
 //-------------------------------------------------
 //
 //  Override Methods
 //
 //-------------------------------------------------
 //-------------------------------------------------
 //
 //  Methods : about ____________
 //
 //-------------------------------------------------
 /**
  *  @private
  *  funtion explain
  *
  *  @param parameter_name explain
  * 
  *  @return
  */
 //-------------------------------------------------
 //
 //  EventHandlers
 //
 //-------------------------------------------------
 /**
  *  @private
  */
}[/code]

2010년 3월 20일 토요일

접근제어자

접근제어자

 

접근제어자에는 public, private, protected가 있다. 어떤 제어 접근자를 쓰는가에 따라 클래스의 멤버에 접근할 수 있는 권한 틀려지기 때문에 잘 사용해야한다.

 

1. public - 어디에서나 객체의 멤버 접근 가능.(아무런 제약 없이 접근 가능)

 

2. protected - 상속받은 클래스나 같은 패키지에 있는 클래스에서 접근 가능.

 

3. private : 클래스의 외부에서 접근 불가능.(클래스 안에서만 사용 가능)

 


 

 

 public

protected

 private

상속

 O

 O

 O

 overriding

 O

 O

 X

 외부 클래스 접근

 O

 X

 X


 

overriding _메서드 오버라이딩(메서드 재정의)

 

클래스를 상속받아 사용할 때 public, protected로 선언된 멤버 변수나 메서드를 상속받아 사용할 수 있다. overriding은 상위 클래스의 메서드를 개선하거나 하위 클래스에 맞게 변경하여 사용할 수 있게 해주는 기능이다.

인터페이스 클래스

인터페이스 클래스

 

인터페이스 클래스는 정보클래스라고도 한다. (인터페이스 = 정보)

 

클래스 안에 메서드, 프로퍼티의 나열만 있고 실제로 뭔가를 만들지는 않는다.

즉, "뭘 만들겠다"고 지정만 해두는 것이다.

 

실제로 구혈할 클래스에서 implements로 인터페이스 클래스를 지정해두면, 인터페이스 클래스에서 지정한 메서드를 구현하지 않으면 컴파일 단계에서 에러를 낸다.

(디버깅 횟수를 줄일 수 있다.)

 

서로 다른 클래스 일지라도 같은 인터페잇 클래스로 구현해 놓으면 같은 데이터 형처럼 캐스팅해서 쓸 수 있다.

 

 

좀더 자세한 내용을 알고 싶다면 야훔님 블로그를 찾아가보자.

Vector 와 Array의 차이

Array이는 C언어와 자료구조를 배우면서 많이 사용하였지만...Vector는 잘 모르겠다. java를 배우면서 Vector라는 말은 들어보았지만...배우지는 않았다. 그래서 인턴 면접을 봤을 때도 Vector에 대해 설명해 보라고 했을 때 아무말도 하지 못했다. 흠...슬프다. 하지만 이제 알았다. 하하하 이제라도 알았으니 다행이다.

 

Array _배열

 

- 어떤 객체도 다 들어감

( 어떤 객체가 들어갈지 몰라 검사하는 과정에서 Vector랑 속도차이가 나서 더 느리다. )

- 많은 양의 데이터를 처리하는 경우 유용하게 사용할 수 있다.

- 참조값이라서 데이터 접근이 느리다.

- 각 값에 대해 메모리 주소값만 가지고 있다.

- 메모리 주소로 이동하고, 그 이동된 주소에서 해당 데이터가 맞는지 확인하고 난 뒤 값을   

   전달한다.

 

[code as3]
var arr:Array = [];
[/code]

 

[]는 Array 객체를 의미한다. new Array()하는 것보다 []를 써주는 것이 속도가 빠르다.

 

Vector_벡터

 

- Vector 변수 선언할 때 어떤 객체가 들어갈지 미리 지정해 놓고 사용한다.

  즉, 자료형이 지정되어 있어 데이터의 접근이 빠르다.

- 연속성 데이터 즉, 메모리가 연속해서 배치되어 있다.

- 해당 값을 바로 찾는다.

 

[code as3]
var vec:Vector = new Vector.<Object>;
[/code]

 

이렇게 하면 모든 객체를 담을 수 있지만, Vector가 빨라질 수 있는 이유는 정해진 포맷을 미리 지정해 놨기 때문에 별도의 연산이 필요하지 않아서이다.

 

#데이터 접근  :  Vector(빠르다) > Array(느리다)

 

Vector는 Array이와는 달리 데이터형을 지정할 수 있어 데이터형에 따라 할당된 메모리 사이즈가 정해져 있기때문이다. (C에서는 데이터 사이즈를 제어할 수 있다. )

 

#중간에 값을 삽입하여 넣을 때  : Vector(느리다) < Array(빠르다)

 

Array이는 주소값만 바꿔주면 되지만, Vector는 메모리 값들을 죄다 쉬프트 해주고 공간을 마련해 놓고 데이터를 저장하기 때문이다.

 

#Vector가 주로 쓰이는 경우

 

- Bitmap 데이터나 객체의 움직임을 제어할 때, 속도를 최적화 하려고 쓰인다.

- Bitmap 에서 하나의 픽셀에 4byte씩 할당.

- FF를 2진수로 바꾸면 8비트, 비트맵 데이터 = ARGB , 8*4 = 32 bit 할당

- 이미지를 수정할 경우 Vector는 연속된 메모리의 정보를 가지고 있으므로 Vertor가 빠름.

 

2010년 3월 18일 목요일

(1) ColorTransform 예제

[code as3]
package
{
import flash.display.Sprite;
import flash.geom.ColorTransform;
import fl.events.SliderEvent;

public class ColorTransformExample extends Sprite
{
 public function ColorTransformExample()
 {
  super();
  configure();
 }

 public function configure():void
 {
  red.maximum = 10;
  red.minimum = -10;
  red.value = 10;
  green.maximum = 10;
  green.minimum = -10;
  green.value = 10;
  blue.maximum = 10;
  blue.minimum = -10;
  blue.value = 10;

  red.addEventListener(SliderEvent.THUMB_DRAG, changeColorHandler);
  green.addEventListener(SliderEvent.THUMB_DRAG, changeColorHandler);
  blue.addEventListener(SliderEvent.THUMB_DRAG, changeColorHandler);
 }

 public function changeColorHandler(event:SliderEvent):void
 {
  var ct:ColorTransform = pic.transform.colorTransform;
 
  ct.redMultiplier = red.value / 10;
  ct.greenMultiplier = green.value / 10;
  ct.blueMultiplier = blue.value / 10;
  pic.transform.colorTransform = ct;
 }
}
}
[/code]

 

3. ColorTransform 클래스

ColorTransform 클래스

 

ColorTransform 클래스는 DisplayObject의 색상값을 조절할 수 있는 클래스로 Actionscriot로Advanced Effect 효과를 낼 수 있다.

 

아, 여기서 알아둬야 할것이 있는데 모든 UI객체ColorTransform 객체를 가지고 있다.

 

참고로 모니터는 빛의 삼원색으로 이해해야 한다. (빛의 삼원색 : 빨강, 초록, 파랑)

 

 

 

출처 : 네이버 백과사전 http://100.naver.com/100.nhn?docid=839807

 

1px 은 AARRGGBB로 표현되며 16진수로는 0x00000000(Alpha, Red, Green, Blue)로 나타낸다. 여기서 AA는 Alpha(투명도)를 말한다. Alpha는 주로 bitmap data에 사용되며 일반적으로 RRGGBB(0x000000)를 사용한다.

 

플래시는 각각의 색을 8bit로 할당한다. 24bit로 색상을 표현하므로 RGB는 24bit로 구성되어있으며, 만약 Alpha까지 포함한다면 32bit가 된다.

 

RGB의 색상값은 255를 넘지 않는다. 왜냐하면 한 색상의 범위는 0~255이므로 한 색상은 8bit이고 이 색상이 표현할 수 있는 값은 2의 8승 즉, 256개의 색상을 가질 수 있다.

 

 

 

 위와 같이 1장(1px)은 R, G, B가 층층이 쌓여 이루어졌다. 그렇기 때문에 RGB값을 이용하여 다양한 색상을 만들어 낼 수 있는 것이다.  

 

이제 구조를 다 알았으니 예제를 하나 만들어보자.  플래시 파일에서 1개의 이미지 무비클립과 3개의 slider 컴포넌트를 이용하여 색상값을 조절하는 예제를 만들어보겠다.

 

2. Rectangle 클래스

Rectangle 클래스

 

Rectangle 은 직사각형이라는 뜻이다. 그럼 Rectangle 클래스는 사각형을 만들기위한 기능을 가진 클래스라는 것이군. 그럼 Rectangle 클래스를 이용하여 사각형을 만들어보자.

 

[code as3]
package
{
import flash.display.Sprite;
import flash.geom.Rectangle;

public class Rectangle extends Sprite
{
 public function Rectangle()
 {
  var rx:Number = 0;
  var ry:Number = 0;
  var rw:Number = 100;
  var rh:Number = 50;

  var rect:Rectangle = new Rectangle(rx, ry, rw, rh);
 }
}
}
[/code]

 

이렇게 하면 내부적으로 사각형을 생성하기만 할 뿐 화면에 나타나지는 않는다. 화면에 사각형을 그리려면 Graphics 클래스의 drawRect() 메서드를 사용해야한다.

그럼 drawRect() 메서드를 이용하여 사각형을 그려보자.

 

[code as3]
package
{
import flash.display.Sprite;
import flash.display.Graphics;

public class Rectangle extends Sprite
{
 public function Rectangle()
 {
  super();
  drawRect();
 }

 public function drawRect():void
 {
  var g:Graphics = this.graphics;

  g.clear();
  g.beginFill(0xFF0000, 1);
  g.drawRect(0, 0, 100, 100);
  g.endFill();
 }
}
}
[/code]

 

 

빨간색 사각형이 생겼다.

 

아, 플래시에서 사용하는 좌표는 상단 왼쪽 끝이 (0, 0)이 된다. 상단 왼쪽 끝에서 오른쪽으로 갈수록, 상단 왼쪽에서 하단 아래로 내려갈수록 양의 값을 갖는다.

2010년 3월 17일 수요일

(4) 극 좌표를 직교 좌표계의 한 점으로 변환 - Point.polar()

[code as3]
package
{
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.geom.Point;

public class DistanceExample extends Sprite
{
 public function DistanceExample()
 {
  super();
  configureListener();
 }

 private var circle1:Circle;
 private var circle2:Circle;

 public function configureListener():void
 {
  if(!circle1)
  {
   circle1 = new Circle();
   circle1.x = 100;
   circle1.y = 100;

   addChild(circle1);
  }

  if(!circle2)
  {
   circle2 = new Circle();
   circle2.x = 200;
   circle2.y = 200;
   addChild(circle2);
  }

  circle1.addEventListener(MouseEvent.MOUSE_DOWN, circle1DownHandler);
  circle1.addEventListener(MouseEvent.MOUSE_UP, circle1UpHandler);
  circle2.addEventListener(MouseEvent.MOUSE_DOWN, circle2DownHandler);
  circle2.addEventListener(MouseEvent.MOUSE_UP, circle2UpHandler);
 }

 public function circle1DownHandler(event:MouseEvent):void
 {
  circle1.startDrag(false, null);
 }

 public function circle1UpHandler(event:MouseEvent):void
 {
  circle1.stopDrag();
  var point1:Point = new Point(circle1.x, circle1.y);
  var point2:Point = new Point(circle2.x, circle2.y);

  distance_txt.text = Point.distance(point1, point2).toString();
 }

 public function circle2DownHandler(event:MouseEvent):void
 {
  circle2.startDrag(false, null);
 }

 public function circle2UpHandler(event:MouseEvent):void
 {
  circle2.stopDrag();
  var point1:Point = new Point(circle1.x, circle1.y);
  var point2:Point = new Point(circle2.x, circle2.y);
  distance_txt.text = Point.distance(point1, point2).toString();
 }
}
}
[/code]

 

 

(3) 두 점 사이의 일정한 비율의 위치 - Point.interpolate()

[code as3]
package
{
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.geom.Point;
public class DistanceExample extends Sprite
{
 public function DistanceExample()
 {
  super();
  configureListener();
 }

 private var circle1:Circle;
 private var circle2:Circle;
 public function configureListener():void
 {
  if(!circle1)
  {
   circle1 = new Circle();
   circle1.x = 100;
   circle1.y = 100;

   addChild(circle1);
 
  }

  if(!circle2)
  {
   circle2 = new Circle();
   circle2.x = 200;
   circle2.y = 200;

   addChild(circle2);
  }
  circle1.addEventListener(MouseEvent.MOUSE_DOWN, circle1DownHandler);
circle1.addEventListener(MouseEvent.MOUSE_UP, circle1UpHandler);
circle2.addEventListener(MouseEvent.MOUSE_DOWN, circle2DownHandler);
circle2.addEventListener(MouseEvent.MOUSE_UP, circle2UpHandler);
 }

 public function circle1DownHandler(event:MouseEvent):void
 {
  circle1.startDrag(false, null);
 }

 public function circle1UpHandler(event:MouseEvent):void
 {
  circle1.stopDrag();
  var point1:Point = new Point(circle1.x, circle1.y);
  var point2:Point = new Point(circle2.x, circle2.y);
  distance_txt.text = Point.distance(point1, point2).toString();
 }

 public function circle2DownHandler(event:MouseEvent):void
 {
  circle2.startDrag(false, null);
 }

 public function circle2UpHandler(event:MouseEvent):void
 {
  circle2.stopDrag();
  var point1:Point = new Point(circle1.x, circle1.y);
  var point2:Point = new Point(circle2.x, circle2.y);
  distance_txt.text = Point.distance(point1, point2).toString();
 }
}
}
[/code]

 

(2) 두 점 사이의 거리 - Point - distance()

[code as3]
package
{
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.geom.Point;

public class DistanceExample extends Sprite
{
 public function DistanceExample()
 {
  super();
  configureListener();
 }

 private var circle1:Circle;
 private var circle2:Circle;

 public function configureListener():void
 {
  if(!circle1)
  {
   circle1 = new Circle();
   circle1.x = 100;
   circle1.y = 100;
   addChild(circle1);
  }

  if(!circle2)
  {
   circle2 = new Circle();
   circle2.x = 200;
   circle2.y = 200;
   addChild(circle2);
  }

  circle1.addEventListener(MouseEvent.MOUSE_DOWN, circle1DownHandler);
circle1.addEventListener(MouseEvent.MOUSE_UP, circle1UpHandler);
circle2.addEventListener(MouseEvent.MOUSE_DOWN, circle2DownHandler);
circle2.addEventListener(MouseEvent.MOUSE_UP, circle2UpHandler);
}

 public function circle1DownHandler(event:MouseEvent):void
 {
  circle1.startDrag(false, null);
 }

 public function circle1UpHandler(event:MouseEvent):void
 {
  circle1.stopDrag();
  var point1:Point = new Point(circle1.x, circle1.y);
  var point2:Point = new Point(circle2.x, circle2.y);
  distance_txt.text = Point.distance(point1, point2).toString();
 }

 public function circle2DownHandler(event:MouseEvent):void
 {
  circle2.startDrag(false, null);
 }

 public function circle2UpHandler(event:MouseEvent):void
 {
  circle2.stopDrag();
  var point1:Point = new Point(circle1.x, circle1.y);
  var point2:Point = new Point(circle2.x, circle2.y);
  distance_txt.text = Point.distance(point1, point2).toString();
 }
}
}
[/code]

 

 

(1) (0, 0)에서 한 점까지의 거리 - length

[code as3]
package
{
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.geom.Point;

public class Length extends Sprite
{
 public function Length()
 {
  super();
  configureListener();
 }

 private var circle:Circle;

 public function configureListener():void
 {
  if(!circle)
  {
   circle = new Circle();
   circle.x = stage.stageWidth / 2;
   circle.y = stage.stageHeight / 2;
   addChild(circle);
  }

  circle.addEventListener(MouseEvent.MOUSE_DOWN, ptMouseDownHaldner);
  circle.addEventListener(MouseEvent.MOUSE_UP, ptMouseUpHandler);
 }

 function ptMouseDownHaldner(event:MouseEvent):void
 {
  circle.startDrag(false, null);
 }

 function ptMouseUpHandler(event:MouseEvent):void
 {
  circle.stopDrag();
  var point1:Point = new Point(circle.x, circle.y);
  length_txt.text = point1.length.toString();
 }
}
}
[/code]

 

 

2010년 3월 15일 월요일

1. Point 클래스

Point 클래스

 

Point 클래스는 점, 사각형 등 기하학적 객체를 정의하는 클래스들 중 하나로 직교 좌표계의 한 점을 가지는 클래라고 한다.

 

음...무슨 소린진 잘 모르겠다.  일단 Point 클래스의 속성과 메서드를 살펴보자.

 

Point 클래스 속성과 메서드

 

속성

 

 length : Number [read-only]  (0, 0)에서 한 점까지 길이
 x : Number  x좌표 값
 y : Number  y좌표 값

메서드
 

 Point(x:Number=0, y:Number=0)  새로운 점 만듬
 add(v:Point):Point  좌표값을 추가하여 새로운 점 만듬
 clone():Number  Point 객체 복사본 만듬
 distance(pt1:Point, pt2:Point):Number)  두 점 사이의 거리
 equals(toCompare:Point)  두 점이 같은지 결정
 interpolate(pt1:Point, pt2:Point, f:Number):Point  두 점 사이에서 원하는 비율을 설정하면 계산된 점을 Point 객체로 반환
 normarlize(thickness:Number):void  좌표를 (0,0)기준으로 설정된 거리로 조절
 offset(dx:Number, dy:Number):void  현 Point 객체를 지정된 만큼 이동
 polar(len:Number, angle:Number):Point  지정된 거리와 각도에 위치된 좌표를 반환
 subtract(v:Point):Point  현재 점에서 다른 점의 좌표를 빼서 새 점 만듬
 toString():String  x , y 값 문자열로 반환

이제 속성과 메서드도 알아봤으니 하나씩 만들어 보겠다. 음, 다 만들 수는 없고 속성에서 length와 메서드에서 distance, interpolate, polar 정도만 만들어보겠다.