아틴
Atin
아틴
전체 방문자
오늘
어제
  • 분류 전체보기 (460)
    • Devlopment (246)
      • 정리 글 (20)
      • MicroServices (0)
      • Reactive, Concurrenc.. (12)
      • Java (44)
      • Spring (20)
      • C,C++,Ruby,Python (52)
      • Mobile (39)
      • Web (35)
      • Tip & Info (14)
      • Unit Test (7)
    • Infra (44)
      • OS (21)
      • RDBMS (13)
      • NoSQL&Cache (5)
      • AWS (4)
    • Computer Science (11)
    • Etc (156)

블로그 메뉴

  • Home
  • Guestbook

공지사항

인기 글

태그

  • 아이폰
  • 정읍
  • 전라도
  • jsp
  • Android
  • Dungeons & Dragons
  • javascript
  • 자바
  • Linux
  • 여행
  • Java
  • Python
  • 해킨토시
  • mysql
  • 던젼 앤 드래곤즈
  • TRPG
  • 안드로이드
  • CSS
  • Ruby on Rails
  • C

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
아틴

Atin

Devlopment/Mobile

COCOS2D Android에서 드래그 앤 드랍(Drag & Drop)

2012. 1. 31. 01:45
반응형
음, 안드로이드에서 COCOS2D를 쓰면 쓸수록 삽질을 많이 한다.
특히나 아이폰에 맞춰 만들어진 것을 안드로이드용으로 포팅하면서 많은 문제가 아직 남아있다는 걸 느낀다.

지난 게임 관련 포스팅을 할 때 COCOS2D 안드로이드 엔진에 대한 문제를 몇 가지 적어놓았다.
이번에는 드래그 앤 드랍을 안드로이드용으로 하는 소스를 써보려 한다.

아래 소스를 참조하자.
[1]을 보고 만든 것이다. Objective C를 자바 형태로 센스있게 바꾸면서 작업했다.
Objective C에 있는 메소드나 클래스명이 거의 그대로 자바 엔진에 있었다. 메소드명이나 파라미터 형태가 조금 다른게 몇 개 있었지만 나름 잘 짜여져 있었다. 

다만 몇 가지 문제가 있었는데.
문제 1. 아이폰에서는 ccTouchesMoved(드래그중 호출되는 메소드) 메소드에서 UITouch라는 클래스의 객체를 받고 이전 터치값을 받아올 수 있지만 안드로이드에서는 이게 빠져있다. 그래서 이전 값을 갖는 부분과 계산해주는 방법을 추가해주었다.

문제 2. Sprite 드래그 앤 드랍을 잘 되었다. 그러나 배경 드래그를 할 때는 좌표값 계산에 문제가 생긴다. 화면위치와 현재 드래그 위치를 계산해주는 convertTouchToNodeSpace 메소드에 문제가 있는 것으로 생각되어서 직접 이 메소드를 구현해 보았지만 웃기게도 똑같은 결과가 나온다. 이 문제는 좌표 계산한 결과값이 오차가 크게 나오면서 배경을 드래그 할 때 배경 위치값이 왔다갔다하면서 화면이 치직거리는듯한 모양을 보여줘버린다.
 그래서 이 것을 해결하기 위해서 배경을 드래그 할 떄는 MotionEvent의 값만을 사용해서 계산했다.

힘들게 만든 후에 너무 짜증나서 포스팅하고 싶은 마음도 없었지만, 나 같이 안드로이드이서 COCOS2D 사용하느랴고 고생하는 사람들을 배려하기 위해 포스팅을 한다. 안드로이드 COCOS2D 개발 문서는 정말 너무 없으니까 말이다. 

import java.util.ArrayList;

import org.cocos2d.actions.base.CCRepeatForever;
import org.cocos2d.actions.interval.CCRotateBy;
import org.cocos2d.actions.interval.CCRotateTo;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.events.CCTouchDispatcher;
import org.cocos2d.layers.CCColorLayer;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.CGRect;
import org.cocos2d.types.CGSize;
import org.cocos2d.types.ccColor4B;

import android.view.MotionEvent;

public class GameLayer extends CCColorLayer {
private CCSprite background;
private CCSprite selSprite;
private ArrayList<CCSprite> movableSprites;
private CGPoint oldTouchLocation = CGPoint.zero();
private CGSize winSize;
GameLayer(ccColor4B color) {
super(color);

// get View Size
winSize = CCDirector.sharedDirector().winSize();

// set Background
background = CCSprite.sprite("bg_game.jpg");
background.setAnchorPoint(CGPoint.make(0.0F, 0));
background.setPosition(0, 0);
this.addChild(background, 0);

// init
movableSprites = new ArrayList<CCSprite>();
//
for(int i=1; i < 5; i++) {
CCSprite sprite = CCSprite.sprite("icon.png");
sprite.setAnchorPoint(CGPoint.zero());
sprite.setPosition(i * 100, winSize.height/2);
this.addChild(sprite, 1);
movableSprites.add(sprite);
}

this.setIsTouchEnabled(true);

CCTouchDispatcher.sharedDispatcher().addTargetedDelegate(this, 0, true);
}

public void selectSpriteForTouch(CGPoint touchLocation) {
CCSprite newSprite = null;
for (CCSprite sprite : movableSprites) {
if (CGRect.containsPoint(sprite.getBoundingBox(), touchLocation)) {            
newSprite = sprite;
break;
}        
}

if (newSprite != selSprite) {
if(selSprite != null) {
selSprite.stopAllActions();
selSprite.runAction(CCRotateTo.action(0.1F, 0));
}

if(newSprite != null) {
CCRotateBy rotLeft = CCRotateBy.action(0.1F, -4.0F);
CCRotateBy rotCenter = CCRotateBy.action(0.1F, 0.0F);
CCRotateBy rotRight = CCRotateBy.action(0.1F, 4.0F);
CCSequence rotSeq = CCSequence.actions(rotLeft, rotCenter, rotRight, rotCenter);
newSprite.runAction(CCRepeatForever.action(rotSeq));
}
selSprite = newSprite;
}
}

public CGPoint boundLayerPos(CGPoint newPos) {
CGSize winSize = CCDirector.sharedDirector().winSize();
CGPoint retval = newPos;
retval.x = Math.min(retval.x, 0);
retval.x = Math.max(retval.x, - background.getContentSize().width+winSize.width);
retval.y = this.position_.y;
return retval;

}

public void panForTranslation(CGPoint translation) {
if (selSprite != null) {
CGPoint newPos = CGPoint.ccpAdd(selSprite.getPosition(), translation);
selSprite.setPosition(newPos);
} else {
CGPoint newPos = CGPoint.ccpAdd(this.position_, translation);
this.setPosition(boundLayerPos(newPos));      
}  
}

@Override
public boolean ccTouchesMoved(MotionEvent event) {
CGPoint touchLocation, translation;
if(selSprite == null) {
// background
touchLocation = CGPoint.ccp(event.getX(), event.getY());
} else {
// sprite
touchLocation = convertTouchToNodeSpace(event);
}
translation = CGPoint.ccpSub(touchLocation, oldTouchLocation);
panForTranslation(translation);
oldTouchLocation = touchLocation;
return true;
}
@Override
public boolean ccTouchesBegan(MotionEvent event) {
CGPoint touchLocation = this.convertTouchToNodeSpace(event);
selectSpriteForTouch(touchLocation);
if(selSprite == null) {
oldTouchLocation.set(event.getX(), event.getY());
} else {
oldTouchLocation.set(selSprite.getPosition().x, selSprite.getPosition().y);
}
return true;
}
}

GameLayer.java



추가로 자체적으로 만들어본 convertMyTouchToNodeSpace메소드. ( convertTouchToNodeSpace와 결과가 같기에 별로 쓸 필요는 없다;)

private CGPoint convertMyTouchToNodeSpace(MotionEvent event) {
CGPoint eventPoint = CGPoint.ccp(event.getX(), winSize.height - event.getY());
CGPoint curPoint = getPosition();
curPoint.set(-curPoint.x, curPoint.y);
return CGPoint.ccpAdd(curPoint, eventPoint);
}




Reference
[1] iPhone COCOS2D 드래그 앤 드랍 (  http://www.raywenderlich.com/2343/how-to-drag-and-drop-sprites-with-cocos2d  ) 
반응형

'Devlopment > Mobile' 카테고리의 다른 글

COCOS2D-X 윈도우에서 신규 솔루션으로 만들기  (0) 2012.02.03
COCOS2D-X 설치 (윈도우)  (4) 2012.02.03
[안드로이드 게임 개발] 1. 시작과 시행착오  (6) 2012.01.27
Cocos2d를 이용하영 FPS 출력하는 기본 소스  (0) 2012.01.25
안드로이드(Android) OnGestureListener 사용법  (0) 2011.12.27
안드로이드에서 OpenGL ES를 사용하는 GLSurfaceView의 기본 골격  (0) 2011.12.27
안드로이드 View, SurffaceView를 사용하는 기본 골격  (0) 2011.12.18
안드로이드 게임 엔진  (1) 2011.12.01
안드로이드 앱 'SD 카드로 이동', '디바이스로 이동' 기능  (0) 2011.10.14
안드로이드 여러 버전의 APK 배포  (0) 2011.10.14
    'Devlopment/Mobile' 카테고리의 다른 글
    • COCOS2D-X 윈도우에서 신규 솔루션으로 만들기
    • COCOS2D-X 설치 (윈도우)
    • [안드로이드 게임 개발] 1. 시작과 시행착오
    • Cocos2d를 이용하영 FPS 출력하는 기본 소스
    아틴
    아틴

    티스토리툴바