2016-06-27 4 views
2

У меня есть Canvas, который масштабируется таким образом, все лучше подходит:Как сделать координаты MotionEvent совпадающими с масштабируемым холстом?

@Override 
public void draw(Canvas c){ 
    super.draw(c); 
    final float scaleFactorX = getWidth()/(WIDTH*1.f); 
    final float scaleFactorY = getHeight()/(HEIGHT*1.f); 

    if(c!=null) { 
     final int savedState = c.save(); 

     c.scale(scaleFactorX, scaleFactorY); 

     (rendering) 

     c.restoreToCount(savedState); 
    } 

} 

Он масштабируется на основе этих двух:

public static final int WIDTH = 856; 
public static final int HEIGHT = 1050; 

Что вызывает проблему, что координаты MotionEvent, который обрабатывает события прикосновения является не равным координатам, созданным с помощью Canvas. Это вызывает проблемы, когда я пытаюсь проверить столкновение между MotionEvent Rect и Rect класса, основанным на шкале рендеринга. Это приводит к тому, что координата X класса SuperCoin не будет равна координатам MotionEvent X. Обычно координаты MotionEvent, в обоих X и Y является способ больше, чем максимальный размер экрана (определяется WIDTH и HEIGHT)

@Override 
public boolean onTouchEvent(MotionEvent e) { 
    super.onTouchEvent(e); 

    switch (MotionEventCompat.getActionMasked(e)) { 
     case MotionEvent.ACTION_DOWN: 
     case MotionEvent.ACTION_POINTER_DOWN: 
      (...) 
      Rect r = new Rect((int)e.getX(), (int)e.getY(), (int)e.getX() + 3, (int)e.getY() + 3); 
      if(superCoins.size() != 0) { 
       for (SuperCoin sc : superCoins) { 
        if (sc.checkCollision(r)) { 
         progress++; 
         superCoins.remove(sc); 
        } 
       } 
      } 

      break; 

    } 

    return true; 

} 

И в SuperCoin:

public class SuperCoin { 
    private Bitmap bm; 
    public int x, y, orgY; 
    Clicker cl; 
    private Long startTime; 
    Random r = new Random(); 
    public SuperCoin(Bitmap bm, int x, int y, Clicker c){ 
     this.x = x; 
     this.y = y; 
     this.orgY = y; 
     this.bm = bm; 
     this.cl = c; 
     startTime = System.nanoTime(); 
     bounds = new Rect(x, y, x + bm.getWidth(), y + bm.getHeight()); 

    } 

    private Rect bounds; 

    public boolean checkCollision(Rect second){ 
     if(second.intersect(bounds)){ 
      return true; 
     } 
     return false; 
    } 


    private int velX = 0, velY = 0; 


    public void render(Canvas c){ 

     long elapsed = (System.nanoTime()-startTime)/1000000; 
     if(elapsed>50) { 


      int cx; 
      cx = r.nextInt(2); 
      if(cx == 0){ 
       velX = r.nextInt(4); 
      }else if(cx == 1){ 
       velX = -r.nextInt(4); 
      } 

      velY = r.nextInt(10) + 1; 

      startTime = System.nanoTime(); 
     } 

     if(x < 0) velX = +2; 
     if(x > Clicker.WIDTH) velX = -2; 

     x += velX; 
     y -= velY; 


     c.drawBitmap(bm, x, y, null); 
    } 
} 

Как я могу проверить столкновение между два разных, если координата MotionEvent X больше масштабных максимальных координат экрана?

Честно говоря, я не совсем уверен, почему Rect, определенный в классе SuperCoin, отличается от определения, определенного в методе onTouchEvent. Я предполагаю, потому что X и Y постоянно отличаются друг от друга, определенные MotionEvent, и те, которые определены масштабированным холстом. Rect в классе SuperCoin идет по ширине Bitmap, который был передан. Он масштабирует его по ширине и высоте растрового изображения.

ответ

0

После просмотра StackOverflow и Google в течение последних двух дней в поисках чего-то, что приближается к решению, я пришел к следующему: получить координаты холста после масштабирования вверх или вниз или перетаскивания в android. Это было очень трудно найти, потому что название было немного вводит в заблуждение (из другого вопроса)

float px = e.getX()/mScaleFactorX; 
float py = e.getY()/mScaleFactorY; 
int ipy = (int) py; 
int ipx = (int) px; 
Rect r = new Rect(ipx, ipy, ipx+2, ipy+2); 

Я добавил это как ответ и не принимать его, чтобы он больше не будет ответ вопроса, как она решается. Приведенный выше код преобразует координаты в целые числа, поэтому их можно использовать для проверки столкновения между пальцем и объектом, который я проверяю с помощью

-1

Не масштабируйте холст напрямую. Сделайте объект Matrix, масштабируйте его один раз. Тогда контактируйте это с холстом. Затем вы можете сделать инвертированную матрицу для ваших событий касания.

И просто сделать матрицу инвертировать всякий раз, когда вы меняете матрицу вида:

viewMatrix = new Matrix(); 
viewMatrix.scale(scalefactor,scalefactor); 
invertMatrix = new Matrix(viewMatrix); 
invertMatrix.invert(invertMatrix); 

Затем применить эти две матрицы для соответствующих событий.

@Override 
    public boolean onTouchEvent(MotionEvent event) { 
     event.transform(invertMatrix); 

А затем на событиях розыгрыша конкатентной матрицы.

@Override 
protected void onDraw(Canvas canvas) { 
    canvas.concat(viewMatrix); 

И вы сделали. все заботится о вас. Независимо от того, какие изменения вы внесете в матрицу вида, вы измените свой viewbox, и ваши события касания будут переведены на ту же сцену.

Если вы хотите добавить панорамирование или поворот, или даже перекосить вид, это все позаботится. Просто примените это к матрице, получите инвертированную матрицу, и представление будет выглядеть так, и события касания будут реагировать так, как вы ожидаете.

+0

, основанный на том, что обе шкалы одинаковы. Что, если масштаб X отличается от шкалы Y? – Zoe

+0

Тогда он отлично работает. – Tatarize

+0

viewMatrix.postScale (масштаб, масштаб, x, y); --- >> viewMatrix.postScale (масштаб, 1, x, y); ---- См. Работу. https://www.youtube.com/watch?v=GCG3i709g-Y&feature=youtu.be – Tatarize