라벨이 게임인 게시물 표시

충돌 체크: Circle vs Circle

이미지
원과 원의 충돌 테스트는 의외로 간단하다. 우선, 피타고라스의 정리를 사용해서 원의 중심점 간의 거리를 구한다. 중심점 간의 거리가 두 반지름의 합보다 크면, 두 원은 서로 충돌하지 않은 것이다. 중심점 간의 거리가 두 반지름의 합보다 작으면, 두 원은 서로 충돌한 것이다. 중심점 간의 거리와 두 반지름의 합이 같다면, 두 원은 서로 붙어 있는 경우이다.

충돌 체크: Oriented Bounding Box

이미지
이전 글 AABB에 이어서, 위의 그림과 같은 경우 AABB 테스트에서는 충돌로 판정된다. 하지만 이것은 우리가 원하는 충돌 판정이 아니다. 따라서, 필요하다면 Oriented Bounding Box 방식으로 보다 세밀하게 충돌 판정을 해 줄 필요가 있다. OBB란 바운딩 박스가 회전 되어서 좌표축에 나란하지 않다는 얘기다. OBB 방식의 충돌 문제를 구현하기 위한 여러 방식들 가운데 SAT라는 것이 있다. Separating Axis Theorem 두 개의 바운딩 박스가 서로 충돌하지 않는다면, 둘 사이를 가르는 직선이 존재한다. 바꾸어 말하자면, 둘 사이를 가르는 임의의 직선이 존재한다면, 두 개의 바운딩 박스는 서로 충돌하지 않는다고 할 수 있다. 위 그림에 그린 임의의 붉은 직선이 Separating Axis이다. Separating Axis에 직교하는 다른 직선에 바운딩 박스를 투영시켜 보자. 이 때 직선 상에 투영된 두 개의 선분이 서로 겹치지 않는다면 두 개의 바운딩 박스는 서로 충돌하지 않는다고 말할 수 있다. 그렇다면, Separating Axis는 어떻게 찾을 것인가. 라는 새로운 문제를 맞이하게 된다. Separating Axis는 다각형을 구성하고 있는 변들 중 하나 이상과 나란하다. 절차 바운딩 박스를 구성하는 변들 중 하나를 선택해서, 그 변과 나란한 가상의 축에 직교하는 임의의 축을 가정하고, 그 축에 바운딩 박스를 투영시킨다. 만일, 두 개의 선분이 겹치지 않으면 서로 충돌하지 않음으로 판정하고 종료, 두 선분이 서로 겹친다면 다른 변을 선택해서 반복 수행. 사각형 vs 사각형의 문제인 경우 최대 8개의 축에 대해 충돌 테스트를 시행해 보아야 한다. 그러나, 위 그림과 같이 서로 나란한 변이 있다면 시행 횟수는 줄어든다. [Tip] OBB는 직사각형이 아니어도, 다각형이어도 적용 가능하다. 그러나, 모서리가 안쪽으로 파인 모양에는 적용이 안된다. ...

충돌 체크: Axis Aligned Bounding Box

이미지
게임 개발에서 충돌 테스트의 가장 기본적인 전략은 AABB인데, Axis Aligned Bounding Box란 좌표 축에 나란한 사각형으로서, 캐릭터를 감싸는 최소한의 너비와 높이를 가진 직사각형이다. 두 개의 좌표축에 나란한 직사각형이 조금이라도 서로 겹치는지를 판단하면 된다. 바운딩 박스 A의 최대 x 좌표(right)가 바운딩 박스 B의 최소 x 좌표(left)보다 작으면 충돌이 아니다. 바운딩 박스 A의 최소 x 좌표(left)가 바운딩 박스 B의 최대 x 좌표(right)보다 크면 충돌이 아니다. 바운딩 박스 A의 최대 y 좌표(top)가 바운딩 박스 B의 최소 y 좌표(bottom)보다 작으면 충돌이 아니다. 바운딩 박스 A의 최소 y 좌표(bottom)가 바운딩 박스 B의 최대 y 좌표(top)보다 크면 충돌이 아니다. 이를 자바 코드로 작성하면 다음과 같다. 참 쉽다, 비교 몇 번이면 끝난다. public static boolean checkAABB (RectF a , RectF b) { return a. right > b. left && a. left < b. right && a. top > b. bottom && a. bottom < b. top ; } 그런데, 아래 그림에서처럼 캐릭터가 회전을 한다거나 하는 경우에는 정확도가 떨어진다는 단점이 있다. 다음 글에 이어서...

안드엔진: 터치 이벤트

터치 입력과 관련된 클래스들은 org.andengine.input.touch 패키지에서 찾아볼 수 있다. 장면 터치 이벤트 Scene 클래스의 setOnSceneTouchListener() 메서드를 사용해서 IOnSceneTouchListener 인터페이스를 구현한다. pScene.setOnSceneTouchListener( new IOnSceneTouchListener() {      @Override      public boolean onSceneTouchEvent (Scene pScene , TouchEvent pSceneTouchEvent) {           if (pSceneTouchEvent.isActionDown()) {               //TODO               return true;           }           return false;      } }) ; 영역 터치 이벤트 스프라이트 등 엔티티의 터치 여부를 처리하려면 엔티티의 onAreaTouched() 메서드를 오버라이드한 후, 장면의 registerTouchArea()메서드를 사용해서 터치 영역을 등록해줘야 한다. Sprite button = new Sprite(posX , posY ,           textureRegion , getVertexBufferObjectManager()){      @Override      public boolean onAreaTouched (TouchEvent pSceneTouchEvent , float pTouchAreaLocalX , float pTouchAreaLocalY) {           // TODO           return super .onAreaTouched(pSceneTouchEvent , pTouchAreaLocalX , pTouchAreaLocalY) ;      } } ; pScene....

안드엔진: 모디파이어

안드엔진의 모디파이어를 사용하면 엔티티의 전환 효과 또는 애니메이션 등을 쉽게 만들 수 있는데, org.andengine.entity.modifier 패키지 아래를 살펴보면 수많은 모디파이어 클래스가 있다. 클래스의 이름만으로도 해당 모디파이어가 무슨 일을 하는 것인지 쉽게 추론할 수 있다. AlphaModifier ,  ColorModifier ,  DelayModifier ,  FadeInModifier ,  FadeOutModifier ,  JumpModifier ,  MoveByModifier ,  MoveXModifier ,    MoveYModifier ,  RotationAtModifier ,  RotationByModifier ,  RotationModifier ,  ScaleAtModifier ,  ScaleModifier ,  SkewModifier ,  PathModifier,  CardinalSplineMoveModifier 사용법은 간단하다. 모디파이어의 생성자를 사용해서 인스턴스를 만들고, 엔티티의 registerEntityModifier() 메서드를 사용해서 엔티티에 장착해주면 된다. 해제하려면 unregisterEntityModifier() 메서드를 사용한다. 엔티티에 등록된 모든 모디파이어를 해제하려는 경우에는  clearEntityModifiers() 메서드를 사용하면 된다. 아래 소스코드는 이동 모디파이어인데, 첫 번째 매개변수를 소요 시간을 초로 나타낸 것이고, 그 외에 시작 좌표와 종료 좌표를 필요로 한다. MoveModifier moveModifier = new MoveModifier( 5 , 0 , 0 , posX , posY) ; sprite.registerEntityModifier(moveModifier) ; 모디파이어의 작동 시작과 종료 시점에 특별히 처리할 사항이 있다면 다음과 같이 메서드를 오버라이드하면 된다. MoveModifier moveModifier = new MoveMod...

안드엔진: 텍스트

안드엔진에서는 모든 컴포넌트가 엔티티이므로 텍스트 또한 엔티티이다. 우선, 텍스트에서 사용할 폰트 리소스를 불러들인 후, font = FontFactory. createFromAsset (getFontManager() ,           getTextureManager() , 256 , 256 ,           getAssets() , "NanumGothic.ttf" , 32f , true,           org.andengine.util.adt.color.Color. WHITE_ABGR_PACKED_INT ) ; font .load() ; Text 클래스를 사용해서 텍스트 인스턴스를 생성한다.  Text text = new Text(posX , posY , font , "Hello" , getVertexBufferObjectManager()) ; pScene.attachChild(text) ; setText() 메서드를 사용해서 표시할 텍스트를 변경할 수 있고, setColor() 메서드로 색상을 변경할 수도 있다. TickerText 클래스는 일정 시간 간격마다 화면에 한 글자씩 표시해준다. TickerTextOptions 클래스를 사용해서 초당 표시할 글자 수를 지정한다. TickerText text = new TickerText(posX , posY , font , "Hello" ,          new TickerText.TickerTextOptions( 1 ) , getVertexBufferObjectManager()) ;

안드엔진: 스프라이트

이미지
스프라이트란 장면 상에서 좌표 위치를 가지는 2차원 비트맵이다. Sprite 클래스에는 여러가지 생성자가 있으며 그 중 가장 간단한 생성자 메서드는 다음과 같은 식으로 사용할 수 있다. Entity layer = new Entity() ; sprite = new Sprite(posX , posY , textureRegion , getVertexBufferObjectManager()) ; layer.attachChild( sprite ) ; 엔티티의 attachChild() 메서드를 사용해서 스프라이트를 부모 엔티티에 붙인다. 엔티티를 제거하려면, 제거할 엔티티의 detachSelf() 메서드를 사용한다. Tiled Sprite TiledSprite 클래스는 normal, clicked 등의 상태에 따른 버튼을 만드는 데에 사용될 수 있다. 여러 장의 이미지가 필요하므로 TiledTextureRegion 클래스를 사용해야 한다.  TiledTextureRegion은 하나의 이미지 파일에 포함된 한 세트의 이미지를 불러온다. 매개변수로 열과 행의 갯수를 지정한다. final BuildableBitmapTextureAtlas buildableBitmapTextureAtlas = new BuildableBitmapTextureAtlas(getTextureManager() , 180 , 36 ) ; tiledTextureRegion = BitmapTextureAtlasTextureRegionFactory         . createTiledFromAsset (buildableBitmapTextureAtlas , this, "tiled.png" , 5 , 1 ) ; try {     buildableBitmapTextureAtlas.build( new BlackPawnTextureAtlasBuilder<IBitmapTextureAtlasSource , BitmapTex...

안드엔진: 엔티티

안드엔진을 사용하는 게임의 구성요소는 모두 Entity로 이루어진다. 이름하여, 엔티티-컴포넌트 모델. 즉, Scene, Sprite, Text, ParticleSystem, Rectangle, Mesh 등은 모두 Entity 클래스를 상속하는 하위 클래스들이다. Entity 클래스는 위치, 크기, 회전, 기울임, 스케일, 색상, 충돌 테스트 등 다양한 메서드를 가지고 있으니 꼭 한번씩은 살펴보아야 할 것이다. 몇 가지 유용한 메서드들을 나열해보면 다음과 같다. 렌더링 setVisible (pBoolean),  isVisible () setChildrenVisible (pBoolean) ,  isChildrenVisible () setCullingEnabled (pBoolean),  isCullingEnabled () setZIndex (pInt),  getZIndex () setIgnoreUpdate (pBoolean),  isIgnoreUpdate () setChildrenIgnoreUpdate (pBoolean),  isChildrenIgnoreUpdate () 구조 attachChild (pEntity) detachSelf () getRootEntity () setParent (pEntity),  hasParent () sortChildren () 색상 setColor (pRed, pGreen, pBlue),  getColor () 위치 setPosition (pX, pY),  setPosition (pEntity) getX (),  getY () setAnchorCenter (pAnchorCenterX, pAnchorCenterY) 크기 setWidth (pWidth),  setHeight (pHeight),  setSize (pWidth...

안드 엔진: 리소스 불러오기

안드 엔진에서는 그래픽, 사운드, 음악, 폰트 등의 리소스를 불러오기 위해 팩토리 클래스 사용하는데, 각각의 리소스를 담당하는  BitmapTextureAtlasTextureRegionFactory , SoundFactory , MusicFactory , FontFactory 클래스가 있다. 안드 엔진에서 리소스 파일들은 assets 폴더 아래에 리소스 별로 각각의 폴더에 나누어서 저장해 둔다. 예를 들어, 이미지 파일은 assets/gfx 폴더 안에, 사운드 파일은 assets/sfx 폴더 안에 등과 같은 방식이다. 각 팩토리 클래스마다 setAssetBasePath() 메서드를 통해서 기본 경로를 지정할 수 있다. BitmapTextureAtlasTextureRegionFactory. setAssetBasePath ( "gfx/" ) ; SoundFactory. setAssetBasePath ( "sfx/" ) ; MusicFactory. setAssetBasePath ( "music/" ) ; FontFactory. setAssetBasePath ( "font/" ) ; 그래픽 그래픽 이미지를 불러다 쓰는 과정은 뭔가 좀 복잡하다. 우선, BitmapTextureAtlas 클래스는 비트맵 이미지를 담아두는 그릇이다. atlas의 사전적 의미는 지도이므로, 이미지를 붙여다 놓을 맵 또는 캔버스 정도로 이해하면 좋을 듯 싶다. TextureRegion은 아틀라스의 일부 영역이며 실제 비트맵 데이터는 TextureRegion 객체로 불러온다.  그렇다면, 왜 이미지 파일을 직접 불러 오지 않고 BitmapTextureAtlas라는 클래스를 거치도록 만들었을까? 구글에서 검색한 결과들을 종합해본 결과 그 이유는 메모리를 효율적으로 사용하기 위해서이다. BitmapTextureAtlas는 GPU 상의 메모리 블럭이고 이 메모리 블럭에 비트맵 데이터를 불러다 놓고 ...

안드엔진의 종류

기본적인 엔진인 Engine 클래스 외에도, 안드엔진은 몇 가지 종류의 엔진을 내장하고 있으며, 개발 중인 게임에 맞게 개발자가 하나를 골라서 쓰면 된다. 엔진의 종류에는 org.andengine.engine 패키지 아래에 있는 Engine , FixedStepEngine , LimitedFPSEngine , 그리고, org.andengine.engine.splitscreen 패키지 아래에 있는 SingleSceneSpilitScreenEngine , 및  DoubleSceneSpilitScreenEngine 이 있다. Engine 기본적인 엔진이며 초당 프레임 수를 제한하지 않는다. FixedStepEngine 게임 루프의 업데이트 주기가 일정한 엔진이다. 엔진의 생성자를 통해서 초당 업데이트 수를 지정한다. LimitedFPSEngine 초당 최대 프레임 수를 제한하는 엔진이다. 엔진의 생성자에서 초당 프레임 수를 지정한다. SingleSceneSpilitScreenEngine,  DoubleSceneSpilitScreenEngine 하나의 장면을 공유하는 두 개의 카메라를 갖는 엔진이다. 멀티플레이어 게임 등에서 사용할 수 있다. BaseGameActivity 클래스를 살펴보면 다음 소스 코드와 같이 기본적으로 Engine 클래스가 정의되어 있다. @Override public Engine onCreateEngine ( final EngineOptions pEngineOptions) {      return new Engine(pEngineOptions) ; } 게임의 엔진을 변경하려면 액티비티의 onCreateEngine() 메서드를 오버라이드 하고, 새로운 엔진을 생성한 후에 반환하면 된다.  @Override public Engine onCreateEngine ( Engine...

안드엔진의 화면 크기 대응책

안드로이드 기기의 다양한 화면 크기에 대응하기 위해서 안드 엔진에서는 몇가지 화면 크기 처리 방식을 제공하고 있는데, org.andengine.engine.options.resolutionpolicy 패키지를 살펴보면 다음과 같은 것들이 있다. 이들은 모두 IResolutionPolicy 인터페이스를 구현하고 있는 추상 클래스인 BaseResolutionPolicy 클래스를 상속하고 있다. FillResolutionPolicy 화면의 가로 및 세로를 꽉 채운다. 다만, 화면상의 이미지들이 억지로 늘려지기 때문에 비율이 틀어져서 왜곡된다는 단점이 있다. FixedResolutionPolicy 일정한 화면 크기만을 사용하도록 고정시킨다. 지정된 화면 크기보다 큰 화면에서는 여백이 검게 남게 된다. 생성자에서 가로, 세로 크기를 지정한다. RatioResolutionPolicy 화면 가로/세로 비율을 일정하게 유지하도록 한다. 기기의 가로/세로 비에 따라서 검은 줄이 보일 수 있다. 생성자의 매개 변수로 (가로/세로) 값을 전달할 수도 있고, (가로, 세로)를 전달할 수도 있다. 아마도 대부분의 경우에 이 클래스를 사용하게 될 것 같다. RelativeResolutionPolicy 화면의 스케일을 지정할 수 있다. 이러한 ResolutionPolicy들은 엔진 옵션의 생성시에 지정하게 된다. 즉, 게임 액티비티의 onCreateEngineOptions() 메서드를 통해서 반환하게 될 엔진 옵션의 생성시에 매개변수 중 하나로 전달된다. EngineOptions engineOptions = new EngineOptions( true,           ScreenOrientation. LANDSCAPE_FIXED ,          new RatioResolutionPolicy( 800 , 480 ) , camera) ; Evernote는 모든 것을 기억하고 간편하게 정리하는데 도움이 됩니다. Ev...

안드엔진: 액티비티의 라이프 사이클

이미지
onCreate () 안드로이드 액티비티의 진입점이다. 안드 엔진에서는 onCreateEngine() 메서드를 통해서 엔진을 생성하고, onCreateEngineOptions() 메서드를 통해서 엔진 옵션을 설정한다. 또한, 서피스 뷰를 생성하고 액티비티의 레이아웃 컨텐트를 지정하는 역할을 한다. onResume () 웨이크락을 설정하고, 서피스 뷰를 리줌 시킨다. onCreateResources () 게임에 필요한 리소스를 불러온다. onCreateScene () 장면을 생성한다. onPopulateScene () 장면에 필요한 요소들을 추가한다. onResumeGame () 엔진 스레드가 시작된다. Evernote는 모든 것을 기억하고 간편하게 정리하는데 도움이 됩니다. Evernote를 다운로드하세요 .

Hello, AndEngine

안드 엔진의 최신 버전은 GLES2를 사용하는 Anchor Center이다. 다음의 위치로부터 소스코드를 다운로드 받을 수 있다. https://github.com/nicolasgramlich/AndEngine/tree/GLES2-AnchorCenter 소스 코드를 열어보면 알 수 있겠지만, API 문서도 없고 또한 주석도 없다. 헐~. 그나마 다행인 것은, 엔진의 소스 코드는 꽤 깔끔하게 짜여져 있으므로 소스코드의 변수명 등을 통해서 충분히 이해할 수 있는 수준이긴 하다. 안드 엔진은 하나의 액티비티 내에서 게임 상황따라 장면을 교체해 나가는 방식으로 작동한다. 그러므로 일반적인 앱과 마찬가지로, 안드엔진을 사용한 게임 개발은 액티비티부터 시작된다. 우선, 프로젝트를 만들고, BaseGameActivity 를 상속하는 새로운 액티비티를 만든다.  BaseGameActivity 를 상속한 클래스는 아래 소스와 같이 4가지 메서드를 추가적으로 구현해 줘야 한다. 아래는 안드로이드 폰의 스크린에 빨간색 바탕의 게임 화면을 띄우는 매우 간단한 소스코드이다. /** * Hello, AndEngine * Created by Elex on 2014-06-30. */ public class HelloAndEngine extends BaseGameActivity {      private static final int WIDTH = 800 ;     private static final int HEIGHT = 480 ;      /**      * 게임 엔진의 옵션을 설정한다 .      * @return      */    ...