[Starling-09] Starling의 Button 클래스 사용

Programming/Framework 2012. 1. 9. 11:22
Starling은 버튼을 쉽게 구현할 수 있도록 Button 클래스가 포함되어 있다. Button 클래스는 DisplayObjectContainer 클래스의 서브 클래스다. 따라서 모든 표시 객체를 자식으로 가질 수 있지만 보통은 스킨 이미지와 제목을 표시한다. 그리고 버튼 클릭을 알리는 기능이 있다.

아래가 Button의 생성자다. 첫 번째 인수는 버튼에 대한 스킨이 되는 텍스처이고 옵션으로, 두 번째 인수에 제목을, 3번 째 인수에는 누를 때 표시할 텍스처를 지정할 수 있다.
Button(upState:Texture, text:String = "", downState:Texture=null)

Flash Professional에서 만든 버튼과 달리, "오버" 스킨은 지정할 수 없다. 아마도 이것은 터치 장치의 이용을 전제로 하고 있기 때문이라고 생각된다.

버튼을 클릭하면 (또는 탭하면) triggered라는 이벤트가 발생한다. 클릭시 실행하고 싶은 처리는 triggered 이벤트 리스너 함수에 작성한다. 아래는 그 예제다. 텍스처 포함 관련 부분은 여러번 나왔기 때문에 생략한다.
import starling.display.Button;
	import starling.events.Event;

	private var myButton:Button;

	private function onAddedToStage(e:Event):void {
		var myBitmap:Bitmap = new MyBitmap  ;
		var myTexture:Texture = Texture.fromBitmap(myBitmap);

		// 텍스처를 지정하여 단추의 객체를 생성
		myButton = new Button(myTexture);

		// triggered 이벤트 수신기를 추가
		myButton.addEventListener(Event.TRIGgered, onTriggered);
	}

	private function onTriggered(e:Event):void {
		// 이벤트를 발생 개체를 가져
		trace(e.target);
	}

Staring 이벤트는 Flash Player의 이벤트처럼 버블링(표시 목록 계층 간에 전파, 자식에서 부모 방향으로만 지원) 하는 여러 버튼을 사용할 때는 triggered 이벤트를 부모 객체에서 처리하는 것도 가능하다.


스킨 지정
Starling 버튼은 터치하면 (또는 버튼에 마우스가 눌러진 상태가 되면), 버튼의 표시 크기가 조금 작아진다. 손가락을 떼면 원래 크기로 돌아간다. 이 것은 버튼에 표준 텍스처 하나만 지정된 경우의 동작이다. 버튼을 눌린 상태에 해당하는 텍스처를 지정하면 텍스처가 작아지는 대신 스킨이 바뀐다.

이 두 텍스처는 생성자에 지정할 수 있지만 나중에 속성에서도 설정할 수 있다. 아래가 속성 목록이다.

upState : 버튼이 터치되지 않은 상태로 표시되는 텍스처
downState : 버튼이 터치되는 상태로 표시되는 텍스처
scaleWhenDown : 터치되어있는 상태 텍스처의 표시 비율

upState과 downState가 각 상태로 표시하는 텍스처를 설정하는 속성이다. (upState는 생성자에서 지정 필수) 성능의 관점에서 어느 텍스처도 같은 텍스처 아틀라스에 있는 것이 바람직할 것이다. 마지막 scaleWhenDown는 0에서 1 사이의 숫자를 지정한다. 이 값은 downState = null의 경우에만 사용할 수 있다.

위에서도 썼지만, 단순한 장식 추가가 필요한 경우, 2 개의 텍스처 이외에도 항시 표시 객체를 추가할 수 있다. 만약 동작을 변경하려면, 커스텀 버튼 클래스를 만드는 편이 빠를지도 모른다.


텍스트 표시
Starling의 버튼은 텍스처로 지정한 이미지에 텍스트를 표시할 수 있다. 텍스트는 생성자에서 지정하거나 인스턴스 생성 후, text 속성에 설정한다. textBounds 속성을 사용하여 텍스트의 위치를​​ 지정할 수도 있다.

text : 버튼에 표시되는 텍스트
textBounds : 텍스트 표시 영역을 Rectangle로 지정

텍스트 표시에 사용할 글꼴의 모양을 설정하는 속성도 있다. 거의 TextField의 경우와 동일하다.

fontName : 텍스트 표시에 사용할 글꼴 이름
fontSize : 텍스트 표시에 사용할 글꼴의 크기
fontColor : 글꼴 색상
fontBold : 글꼴을 굵게 표시 여부를 지정

포함된 글꼴과 비트맵 글꼴을 사용할 수 있다.


버튼 비활성화
버튼을 사용할 수 없는 상태라면 enabled 속성의 값을 false로 적용한다.

enabled : 버튼을 사용할 수 있는지 여부를 지정
alphaWhenDisabled : 버튼이 비활성화 때 알파 값

기본적으로 단추를 비활성화하면 버튼의 표시가 반투명하게 된다. 그 때 사용되는 알파 값은 alphaWhenDisabled에 설정된 값이다.


원본 : http://cuaoar.jp/2012/01/starling-button.html




package {
	import starling.events.Event;
	import starling.core.Starling;
	import starling.display.Sprite;
	import starling.display.Button;
	import starling.textures.Texture;
	import starling.display.DisplayObject;
	import flash.geom.Rectangle;
	import flash.display.Bitmap;

	public class Demo extends Sprite {

		[Embed(source="icon128.png")]
		private var MyBitmap:Class;
		
		private var myButton:Button;

		public function Demo() {
			// addedToStage 이벤트에 대한 리스너 추가
			addEventListener( Event.ADDED_TO_STAGE , onAddedToStage);
		}


		private function onAddedToStage(e:Event):void {
			var myBitmap:Bitmap = new MyBitmap() as Bitmap;
			var myTexture:Texture = Texture.fromBitmap(myBitmap);

			// 텍스처를 지정하여 단추의 객체를 생성
			myButton = new Button(myTexture);
			
			// 터치 상태일 때, 텍스처의 표시 비율
			myButton.scaleWhenDown = 0.95;
			
			myButton.fontColor = 0xFFFFFF;
			myButton.fontBold = true;
			myButton.fontSize = 24;
			myButton.text = "BUTTON";
			myButton.textBounds = new Rectangle(myButton.width-60>>1, 85, 60, 30);
			
			// 
			addChild(myButton);
			setAlign(myButton);
			
			// triggered 이벤트 수신기를 추가
			myButton.addEventListener(Event.TRIGGERED, onTriggered);
		}

		private function onTriggered(e:Event):void {
			// 이벤트를 발생 개체를 가져
			trace(e.target);
			myButton.fontColor = Math.random()*0xFFFFFF;
		}

		private function setAlign(inTarget:DisplayObject):void {
			inTarget.x = stage.stageWidth - inTarget.width >> 1;
			inTarget.y = stage.stageHeight - inTarget.height >> 1;
		}

		public override function dispose():void {
			removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
			super.dispose();
		}
	}
}

    

설정

트랙백

댓글

[Starling-07] MovieClip 클래스를 이용한 애니메이션

Project/Programming 2012. 1. 9. 00:49
Flash에서 애니메이션이라고 하면 역시 MovieClip이지만 Starling에도 MovieClip 클래스가 있다. 물론 애니메이션을 위한 클래스지만 Starling의 MovieClip은 화면에 표시할 수 있는 것이 비트맵 이미지 또는 색상을 지정한 사각형 뿐이다. 따라서 MovieClip라는 이름은 같지만 Starling의 MovieClip은 프레임마다 할당된 비트맵을 표시하는 클래스인 것이다.

또한 Starling MovieClip의 자식 객체를 관리하거나 프레임에 스크립트가 들어가는 기능은 없다. 이 점도 Flash Player의 MovieClip과는 크게 다르다. (Starling은 표시 목록의 관리는 Sprite의 책임이다. 한편, MovieClip은 Image 클래스에 타임 라인 기능을 더한 Image의 서브 클래스다. MovieClip이 Sprite의 하위 클래스인 Flash Player와는 달리, 양쪽의 역할은 분리되어 있다.)


스프라이트 시트와 TextureAtlas
MovieClip의 각 프레임을 볼 때 GPU는 표시 프레임에 할당된 텍스처, 셰이더에서 사용할 수 있도록 준비가 이루어진다. 이 때 텍스처가 프레임마다 물리적으로 다른 비트맵 파일이면 프레임을 진행할 때마다 텍스처 전환이 발생한다.

텍스처 전환 처리에는 당연히 시간이 걸린다. 또한 텍스처의 GPU에 업로드가 필요할 때 추가 오버헤드가 증가한다. 일반적으로 이 문제를 해결하기 위해 각 프레임의 텍스처를 하나의 파일에 정의한다. 이 것을 스프 라이트 시트라고  한다.

아래 그림은 Starling 샘플에 포함된 스프라이트 시트의 일부를 자른 것이다.




여러 프레임에 해당하는 텍스처가 1개의 파일로 되어 있으면 GPU를 이용해서 사용 위치를 바꾸는 것만으로 텍스처 자체를 전환하지 않고 렌더링 처리가 가능하다. 따라서 고속 프레임을 업데이트할 수 있다.

또한 Stage3D에서 취급할 수 있는 텍스처의 폭은 2의 계승이라는 규칙 때문에, 그 이외의 너비 텍스처는 Starling 내부에 여분의 사전 처리가 발생한다. 하지만 스프라이트 시트의 경우 표시되는 텍스처가 더 큰 텍스처(스프라이트시트)가 아니기 때문에 개별 텍스처 너비 사이즈를 걱정할 필요가 없다.

이 것을 최적화한 1단계가 TextureAtlas다. TextureAtlas는 여러 스프라이트시트를 하나의 파일에 정리한 것이다. 동시에 여러 애니메이션을 재생하는 경우 특히 유용하다. TextureAtlas를 만들기 위해, 차기 버전의 Flash Professional CS6에서 지원되는 것 같다. 벡터 애니메이션 스프라이트시트로 내보내기 기능을 기다리거나 Texture Packer 등의 도구를 이용하면 된다.


TextureAtlas 로드
TextureAtlas를 사용하여 프레임마다 각각 TextureAtlas의 어떤 영역을 표시할지 정보가 필요하다. 따라서 다음과 같은 형식으로 각 프레임의 텍스처 정보를 지정하게 되어 있다. 도구를 사용하여 TextureAtlas를 생성하는 경우 이러한 XML 파일도 동시에 생성된다.

  
  
  
  


TextureAtlas 태그 imagePath 속성은 TextureAtlas의 파일 이름이다. SubTexutre 태그의 name 속성은 애니메이션의 고유 이름 뒤에 프레임 번호를 추가한 것이다. 나머지 x, y, height, width에서 텍스처로 사용 영역을 지정한다. (실제로 SubTexture는 텍스처의 일부를 처리하는 클래스가 있다) TextureAtlas가 준비되면 다음과 같은 프로그램에 포함한다.
[Embed (source = "atlas.png")]
private static const MyBitmap:Class;
 
[Embed (source = "atlas.xml"mimeType = "application / octet - stream")]
private static const MyXml:Class;

이러한 정보는 TextureAtlas라는 클래스에서 함께 관리한다. TextureAtlas(PNG 파일)은 일단 Texture 클래스 로딩하면서 XML 파일과 함께 TextureAtras 생성자에 전달한다. TextureAtlas 객체에서 고유 이름을 지정하여 Texture(실제로는 SubTexture의) 벡터를 얻을 수 있다. 이 때 사용하는 메소드가 getTextures()다.
import starling.textures.TextureAtlas;

	private function onAddedToStage(e:Event):void {
		// 텍스처 아틀라스로드
		var myTexture:Texture = Texture.fromBitmap(new MyBitmap);
		// 텍스처 아틀라스의 영역 정보 가져오기
		var myXml:XML = XML(new MyXml);

		// TextureAtlas 인스턴스 생성
		var myTextureAtlas:TextureAtlas = new TextureAtlas(myTexture,myXml);
		// "walk_"를 식별 이름으로 가진 Texture 벡터 생성
		var frames:Vector. = myTextureAtlas.getTextures("walk_");

		// ... 앞으로는 아래에 계속
	}

벡터의 첫 번째 텍스처의 크기가 애니메이션의 영역을 결정한다. 애니메이션 여기까지 왔으면 나머지는 MovieClip의 인스턴스를 생성하면 된다. MovieClip 생성자의 인수에서 얻은 텍스처 벡터를 지정한다.
import starling.display.MovieClip;

	private var myMovieClip:MovieClip;

	private function onAddedToStage(e:Event):void {
		//... 위에서 계속

		// MovieClip 객체의 생성
		myMovieClip = new MovieClip(frames);

		// 애니메이션 재생 시작
		Starling.juggler.add(myMovieClip);
		addChild(myMovieClip);
	}

알겠지만, Tween뿐만 아니라 MovieClip의 재생도 Juggler을 사용한다. MovieClip도 IAnimatable의 서브클래스다. Juggler에 MovieClip을 추가하면 재생이 시작된다. 재생을 제어하는​​ 세 가지 메소드가 포함되어 있다.
myMovieClip.play();
myMovieClip.pause();
myMovieClip.stop();

pause()를 실행한 다음에 play()를 실행하면 현재 상태부터 재생되지만 stop()을 실행한 다음에 play()를 호출하면 처음 부터 다시 재생된다. 애니메이션은 default로 반복 재생된다. 이 설정은 loop 속성을 설정하여 바꿀 수 있다. 재생 여부 isPlaying 속성을 확인한다. 애니메이션이 끝까지 재생되면 movieComplete 이벤트가 발생한다. 재생이 완​​료되면 다음 작업으로 이동하고자하는 경우에 사용할 수 있을 것이다.
myMovieClip.addEventListener(Event.MOVIE_COMPLETED, onMovieComplete);

애니메이션이 반복되는 경우에는 재생이 완​​료될 때마다 movieComplete 이벤트가 발생한다. MovieClip의 부모 Sprite가 Stage에서 제거되면 MovieClip 재생을 중지해야한다. 그래서 다음과 같은 코드를 추가한다.
addEventListener(Event.REMOVED_FROM_STAGE,onRemovedFromStage);

	private function onRemovedFromStage(event:Event):void {
		Starling.juggler.remove(myMovieClip);
	}

Juggler의 remove() 메소드는 MovieClip뿐만 아니라 Tween도 삭제할 수 있다. 또 다른 MovieClip 사용 MovieClip의 생성자의 두 번째 파라미터에 임의의 프레임 속도를 지정할 수 있다.
// 40 fps를 지정
myMovieClip = new MovieClip (frames, 40);

MovieClip마다 다른 프레임 속도를 지정할 수 있다. 재생중인 프레임 속도는 fps 속성에서 가져올 수 있다. 또한 fps 속성 값을 설정하여 프레임 속도를 변경할 수도 있다. 그리고 모든 프레임에 대해 별도의 재생 시간을 지정할 수 있다. 아래는 5 번째 프레임을 2 초 동안 재생하도록 설정하는 예다.
myMovieClip.setFrameDuration(5, 2);

나중에 프레임을 추가하거나 삭제할 수도 있다. 이를 위해서 addFrameAt() removeFrameAt() 메서드를 사용한다. 아래는 5 프레임 애니메이션을 10번 째 프레임에 추가하거나 5 프레임을 제거하는 것이다. 
myMovieClip.addFrameAt(5, frames [10]);
myMovieClip.removeFrameAt(5);

프레임의 텍스처를 바꿀 수도 있다. setFrameTexture() 메소드를 사용하면 된다.
myMovieClip.setFrameTexture(5, frames [10]);

프레임에 소리를 연결할 수도 있다. setFrameSound() 메서드를 사용한다.
[Embed (source = "step.mp3")]

private static const StepSound:Class;
 
myMovieClip.setFrameSound (5, new StepSound() as Sound);

이제 5번 째 프레임이 표시되는 타이밍에 지정한 소리가 재생된다. 프레임에 직접 스크립트를 연결할 수는 없다. 그 대신 Juggler.delayCall() 메서드를 사용할 수 있다. 이상에서 Starling 애니메이션의 기본은 끝이다. Starling 표현의 유연성은 CPU 렌더링보다 미약하다. 그러나 빠른 렌더링을 안정적으로 해야할 경우에 선택하면 적당할 것이다.


원본 : http://cuaoar.jp/2011/12/movieclip-starling.html


 


package {
	import starling.events.Event;
	import starling.display.Sprite;
	import starling.display.DisplayObject;
	import starling.display.Image;
	import starling.textures.Texture;
	import starling.textures.RenderTexture;
	import starling.textures.TextureAtlas;
	import starling.display.MovieClip;
	import starling.core.Starling;

	public class Demo extends Sprite {

		[Embed(source = "patch.png")]
		private var MyBitmap:Class;

		[Embed(source = "patch.xml",mimeType = "application/octet-stream")]
		private var MyXml:Class;
		
		private var _arrMovieClips:Array;


		public function Demo() {
			// addedToStage 이벤트에 대한 리스너 추가
			addEventListener(Event.ADDED_TO_STAGE,onAddedToStage);
		}
		private function onAddedToStage(e:Event):void {

			// 텍스처 아틀라스로드
			var myTexture:Texture = Texture.fromBitmap(new MyBitmap());

			// 텍스처 아틀라스의 영역 정보 가져오기
			var myXml:XML = XML(new MyXml());

			// TextureAtlas 인스턴스 생성
			var myTextureAtlas:TextureAtlas = new TextureAtlas(myTexture,myXml);

			// "walk_"를 식별 이름으로 가진 Texture 벡터 생성
			var frames:Vector.<Texture>=myTextureAtlas.getTextures("patch_");

			// MovieClip 객체의 생성
			
			_arrMovieClips = [];
			var count:int = 20;
			for(var i:int=0;i<count;i++){
				var myMovieClip = new MovieClip(frames, 60);
				myMovieClip.x = 20+((stage.stageWidth-90)/count)*i;
				myMovieClip.y = stage.stageHeight - myMovieClip.height >> 1;
				Starling.juggler.add(myMovieClip);
				_arrMovieClips.push(myMovieClip);
				addChild(myMovieClip);
				
			}
			
		//	myMovieClip.setFrameDuration(5, 2);

		//	myMovieClip.addFrameAt(5,frames[10]);
		//	myMovieClip.removeFrameAt(5);
		}

		private function setAlign(inTarget:DisplayObject):void{
			inTarget.x = stage.stageWidth >> 1;
			inTarget.y = stage.stageHeight >> 1;
		}

		public override function dispose():void {
			removeEventListener(Event.ADDED_TO_STAGE,onAddedToStage);
			super.dispose();
		}
	}
}

    

설정

트랙백

댓글