2015-07-31 9 views
0

Я изучал (медленно), как программировать игры для Android с помощью Java и Android Studio. Моим основным источником обучения были следующие учебные пособия, которые находятся на Kilobolt Tutorial Website. Я нашел их чрезвычайно полезными, но поскольку они являются учебниками по Android ADT для Eclipse, а им 3 года, мне пришлось многому научиться в каждом разделе, чтобы изучить Android Studio (огромный процесс).ACTION_UP не работает, но ACTION_DOWN отлично работает

Я обнаружил, что, в основном, логика в учебнике была прочной. Моя проблема заключается в том, что в классе SingleTouchHandler, предоставляемом Kilobolt, ACTION_UP не работает. Вот Input Класс:

public interface Input { 

public static class TouchEvent { 
    public static final int TOUCH_DOWN = 0; 
    public static final int TOUCH_UP = 1; 
    public static final int TOUCH_DRAGGED = 2; 
    public static final int TOUCH_HOLD = 3; 

    public int type; 
    public int x, y; 
    public int pointer; 

} 

public boolean isTouchDown(int pointer); 

public int getTouchX(int pointer); 

public int getTouchY(int pointer); 

public List<TouchEvent> getTouchEvents(); 

} 

и вот это реализация:

public class SingleTouchHandler implements TouchHandler { 
boolean isTouched; 
int touchX; 
int touchY; 
Pool<TouchEvent> touchEventPool; 
List<TouchEvent> touchEvents = new ArrayList<TouchEvent>(); 
List<TouchEvent> touchEventsBuffer = new ArrayList<TouchEvent>(); 
float scaleX; 
float scaleY; 

public SingleTouchHandler(View view, float scaleX, float scaleY) { 
    PoolObjectFactory<TouchEvent> factory = new PoolObjectFactory<TouchEvent>() { 
     @Override 
     public TouchEvent createObject() { 
      return new TouchEvent(); 
     } 
    }; 
    touchEventPool = new Pool<TouchEvent>(factory, 100); 
    view.setOnTouchListener(this); 

    this.scaleX = scaleX; 
    this.scaleY = scaleY; 
} 

@Override 
public boolean onTouch(View v, MotionEvent event) { 
    synchronized(this) { 
     TouchEvent touchEvent = touchEventPool.newObject(); 
     switch (event.getAction()) { 
      case MotionEvent.ACTION_DOWN: 
       touchEvent.type = TouchEvent.TOUCH_DOWN; 
       isTouched = true; 
       break; 
      case MotionEvent.ACTION_MOVE: 
       touchEvent.type = TouchEvent.TOUCH_DRAGGED; 
       isTouched = true; 
       break; 
      case MotionEvent.ACTION_CANCEL: 
      case MotionEvent.ACTION_UP: 
       touchEvent.type = TouchEvent.TOUCH_UP; 
       isTouched = false; 
       break; 
     } 

     touchEvent.x = touchX = (int)(event.getX() * scaleX); 
     touchEvent.y = touchY = (int)(event.getY() * scaleY); 
     touchEventsBuffer.add(touchEvent); 

     return true; 
    } 
} 

@Override 
public boolean isTouchDown(int pointer) { 
    synchronized(this) { 
     if(pointer == 0) 
      return isTouched; 
     else 
      return false; 
    } 
} 

@Override 
public int getTouchX(int pointer) { 
    synchronized(this) { 
     return touchX; 
    } 
} 

@Override 
public int getTouchY(int pointer) { 
    synchronized(this) { 
     return touchY; 
    } 
} 

@Override 
public List<TouchEvent> getTouchEvents() { 
    synchronized(this) { 
     int len = touchEvents.size(); 
     for(int i = 0; i < len; i++) 
      touchEventPool.free(touchEvents.get(i)); 
     touchEvents.clear(); 
     touchEvents.addAll(touchEventsBuffer); 
     touchEventsBuffer.clear(); 
     return touchEvents; 
    } 
} 
} 

Опять же, это основа обеспечивает хороший человек Джеймс Чо из Kilobolt и легко доступны на веб-сайте Kilobolt, если хочет ,

В моей реализации: TOUCH_DOWN, переменная, используемая для представления любого использования ACTION_DOWN, отлично работает. Однако TOUCH_UP (для ACTION_UP) не работает вообще. Вот блок кода, где я использую его в моих играх Обновление Функции:

int len = touchEvents.size(); 
    for (int i = 0; i < len; i++) { 
     TouchEvent event = (TouchEvent) touchEvents.get(i); 
     if (event.type == TouchEvent.TOUCH_DOWN) { 



     } 

     if (event.type == TouchEvent.TOUCH_UP) { 
      if (inBounds(event, 190, 350, 100, 100)) { 

       game.setScreen(new Menu(game)); 
      } 
     } 
    } 

В моем коде выше, когда сенсорный отрываются экран, TOUCH_UP должен позволить игровому состояние, чтобы перейти к экрану меню. Однако ничего не происходит.

Если я поместил game.setScreen(new Menu(game)); в заявлении, если:

if (event.type == TouchEvent.TOUCH_DOWN) он работает отлично.

Это ошибка в коде или у меня есть непонимание того, как ACTION_UP и другие действия работают? Я тестирую с помощью Samsung Galaxy S5.

Спасибо за любую помощь. Изучение Android Studio и разработка игр были одним из черт процесса, но я определенно улучшаюсь.

+0

Мне любопытно, почему вы это делаете. Вы выполняете большую работу по предоставлению API, который уже давно существует, и при этом не хватает важных деталей (например, разница между отменой и увеличением). –

+0

@Gabe Sechan вы могли бы разработать или предоставить мне ресурс для чтения? Я бы хотел знать. Как я уже сказал, я чрезвычайно новичок в Android Programming и Android Studio в целом (но немного в школе на Java). Я открыт ко всему и хочу узнать больше. –

ответ

0

Вы, кажется, изобретаете колесо здесь. Вы пробовали более простой подход?

Во-первых, реализуйте реальных слушателей, например View.OnTouchListener. Это просто, был введен в API уровня 1 и работает отлично.

Фактически, у меня даже не было класса SingleTouchHandler (если вы, конечно, не планируете устанавливать этот сенсорный прослушиватель на несколько видов. В этом случае реализуйте OnTouchListener вместо TouchHandler). Я бы просто инициализировать метод onTouch в конструкторе с OnTouchListener, например, так:

view.setOnTouchListener(new View.OnTouchListener(){ 
    @Override 
    public boolean onTouch(View v, MotionEvent event){ 
     //Synchronize if you wish 
     switch(event.getAction()){ 
      case MotionEvent.ACTION_DOWN: 
       //Press code 
       break; 
      case MotionEvent.ACTION_MOVE: 
       //Move code 
       break; 
      case MotionEvent.ACTION_UP: 
       //release code 
       break; 
     } 
     return true; 
    } 
}); 

Нет необходимости в каких-либо дополнительных классов вообще. Просто включите это в конструктор вашего подкласса View. Это было проверено и работает как ожидается в SurfaceViews, который, если вы кодируете динамические игры, вы должны использовать anyways. Во-вторых, как указано, если вы хотите установить этот OnTouchListener на несколько видов, тогда вам нужно будет сделать его собственным классом, как тот, который у вас уже есть (SingleTouchHandler), и заставить его реализовать View.OnTouchListener (а не TouchHandler). Однако, опять же, предполагая, что вы программируете динамические игры, вся графика, скорее всего, будет нарисована на одном SurfaceView, а это означает, что будет только один вид, на который можно назначить этот OnTouchListener, устраняя необходимость в классе все вместе (используйте подход показано выше).

+0

Я, вероятно, буду звучать очень наивно, но я пытаюсь понять это хорошо, поставил бы я код, который у вас выше, в моем классе TouchHandler, или это будет дополнительный метод в моем классе GameScreen? –

+0

Он должен быть помещен в конструктор вашего класса GameScreen (или любой другой метод присваивает ему представление). В принципе, если GameScreen расширяет какой-то вид, сразу после его инициализации вызовите вышеуказанный код. – Nerdizzle

+0

Я понял, где я смущен, я не уверен, где мой класс игры создает представление. У меня есть класс под названием AndroidFastRenderView, который, как я считаю, обрабатывает представление для всей игры и всех ее разных экранов/состояний, поэтому я задаюсь вопросом, принадлежит ли она там. –

1

Возможно, вы вернетесь false по телефону ACTION_DOWN.

ACTION_UP действует только при обращении true на ваш ACTION_DOWN событий.

Смежные вопросы