Programujemy pod Android: pełna obsługa multitouch w grze
Dodać do programu (gry) obsługę dotyku pod Androidem jest niezmiernie prosto. Wystarczy kilka linijek kodu:
@Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: processTouchDown(x, y); break; case MotionEvent.ACTION_UP: processTouchUp(x, y); break; } return false; }
Schody zaczynają się w momencie, gdy chcemy zrobić np. pełne sterowanie postacią – a jego ramach np. ruch oraz strzelanie. Już przy pierwszym teście dochodzimy do wniosku, że chcemy obsługiwać wiele palców naraz, niezależnych od siebie.
Z pomocą przychodzi nam mechanizm dodany w API Level 8, czyli od Androida 2.2.x Froyo. Każdy event dotyku zawiera w sobie pełną informację o wszystkich ewentualnych punktach nacisku, ich pozycji itd. Dlatego, naszą obsługę zdarzeń rozwiniemy tak:
private int actionMovementId = -1; private int actionFiringId = -1;
@Override public boolean onTouchEvent(MotionEvent event) { int actionId = event.getActionIndex(); float x = event.getX(actionId); float y = event.getY(actionId); switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_POINTER_DOWN: processTouchDown(x, y, actionId); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: processTouchUp(x, y, actionId); break; } return false; }
private void processTouchDown(float x, float y, int actionId) { Point displaySize = new Point(CgEngine.display.getWidth(), CgEngine.display.getHeight()); int touchableArea = displaySize.y * 3 / 4; int halfX = displaySize.x / 2; if (y > touchableArea) { // fire! if (x < halfX) { CgEngine.playerFireAction = CgEngine.PLAYER_FIRE_SHOOT; actionFiringId = actionId; } // steering else { if (x < halfX * 1.5) CgEngine.playerRunAction = CgEngine.PLAYER_TURN_LEFT_1; else CgEngine.playerRunAction = CgEngine.PLAYER_TURN_RIGHT_1; actionMovementId = actionId; } } }
private void processTouchUp(float x, float y, int actionId) { if (actionFiringId == actionId) { CgEngine.playerFireAction = CgEngine.PLAYER_FIRE_HOLD; actionFiringId = -1; } if (actionMovementId == actionId) { CgEngine.playerRunAction = CgEngine.PLAYER_RELEASE; actionMovementId = -1; } }
Jak widać, przy rozpoczynaniu każdej akcji, musimy zapamiętać identyfikator palca, który ją uruchomił – później, gdy przyjdzie event puszczenia palca, będzie można łatwo zidentyfikować, która akcja powinna się zakończyć.
Jeżeli macie jakieś spostrzeżenia, bądź pytania, zapraszam do dyskusji na forum.
Powodzenia!
utak3r