Multitouch Pointer Problem

Hallo,
ich habe mal wieder ein neues Problem. Diesmal mit den Pointern im onTouchEvent.
Ich versuche zwei verschieden TouchEvents zu kontrollieren, mit dem einen kann man ein Raumschiff steuern, mit dem anderen soll man dann feuern können.
Anbei mal die zwei Methoden, zum einen die, die auf touch reagieren soll, zum anderen die Methode, die checked, ob es angeklickt wird.

Hierbei ist mir überhaupt nicht klar, warum isTouched true wird, obwohl der Pointer das Bitmap nicht berührt. Und zwar nur, wenn der Y-Wert des touchEvents größer als der Y-Wert des Bitmaps ist
Ich muss doch da irgendein Denkfehler haben, aber ich sehs nicht.
Die Koordinaten der Touchevents stimmen übrigens (lass ich mir anzeigen)

Hier mal der Code, kann mir da jemand sagen, was da nicht stimmt?!?

Vielen Dank,
Chris

	public boolean onTouchEvent(MotionEvent event) {

		// Loging Stuff
		Log.d(TAG, "MainGamePanel onTouchEvent");

		pointerCount = event.getPointerCount();
		p1x = (int) event.getX(0);
		p1y = (int) event.getY(0);
		
		if(pointerCount > 1) {
			p2x = (int) event.getX(1);
			p2y = (int) event.getY(1);
		}
		
		for (int i = 0; i < pointerCount; i++) {
			float x = event.getX(i);
			float y = event.getY(i);

			if (event.getAction() == MotionEvent.ACTION_DOWN) {
				// delegating event handling to the droid
				greenBall.handleActionDown((int) x, (int) y);
				redBall.handleActionDown((int)x, (int)y);
				
			}
			if (event.getAction() == MotionEvent.ACTION_MOVE) {
				// the gestures
				greenBall.handleActionDown((int) x, (int) y);
				redBall.handleActionDown((int)x, (int)y);
				if (greenBall.isTouched()) {
					// the droid was picked up and is being dragged
					// greenBall.setX((int)event.getX());Kann man nur noch
					// seitlich verschieben
					greenBall.setY((int) y);
					spaceShip.setPosY(greenBall.getY());
				}
			}
			if (event.getAction() == MotionEvent.ACTION_UP) {
				// touch was released
				if (greenBall.isTouched()) {
					greenBall.setTouched(false);
				}
				if (redBall.isTouched()) {
					redBall.setTouched(false);
				}
			}


		}
		return true;
	}```

Das ist die Methode, wo gecheckt wird, ob das Bitmap berührt wird.
```public void handleActionDown(int eventX, int eventY) {
		if (eventX >= (x - bitmap.getWidth() ) && (eventX <= (x + bitmap.getWidth()))) {
			if (eventY >= (y - bitmap.getHeight() ) && (y <= (y + bitmap.getHeight() ))) {
				// droid touched
				setTouched(true);
			} else {
				setTouched(false);
			}
		} else {
			setTouched(false);
		}

	}```

Was steckt hinter x und y in der handleActionDown Methode? Und warum wird die Breite/Höhe des Bitmaps von x/y abgezogen? Damit wird ein Bereich berücksichtigt, der doppelt so breit und hoch ist wie das Bitmap.
Hast Du evtl. ein Rectangle verfügbar, welches Postion und Ausdehnung repräsentiert? Dann würde ein einfaches contains(…) ausreichen.

Hallo,
Also x und y sind die Position des greenBall.
Die Breite und Höhe wird abgezogen falls jemand Wurstfinger hat :wink:

Gesendet von meinem GT-I9300 mit Tapatalk-4 now Free

OK Fehler gefunden:
Die Bedinung y <= (y + bitmap.getHeight()) ist immer erfüllt, wenn bitmap.getHeight()>=0. :wink:
Hier muss eventY geprüft werden.

Wenn X der Bildbereich ist, dann ist der “sensitive Bereich” im Moment etwa so


............
............
............
............
............
......XXXXXX
......XXXXXX
......XXXXXX
......XXXXXX
......XXXXXX

(also der X-Bereich und der ‘.’-Bereich!)

Mit einer Methode wie

private static boolean contains(int x, int y, int w, int h, int eventX, int eventY, int border)
{
    if (eventX < x-border) return false;
    if (eventY < y-border) return false;
    if (eventX > x+w+border) return false;
    if (eventY > y+h+border) return false;
    return true;
}

könnte man dort sowas schreiben wie

public void handleActionDown(int eventX, int eventY) {
    setTouched(contains(x,y,bitmap.getWidth(),bitmap.getHeight(),eventX,eventY, 10);
}

Dann wäre der sensitive Bereich


   ............
   ............
   ...XXXXXX...
   ...XXXXXX...
   ...XXXXXX...
   ...XXXXXX...
   ...XXXXXX...
   ............
   ............

[QUOTE=_Michael;69195]OK Fehler gefunden:
Die Bedinung y <= (y + bitmap.getHeight()) ist immer erfüllt, wenn bitmap.getHeight()>=0. :wink:
Hier muss eventY geprüft werden.[/QUOTE]
Yepp. vielen Dank, ich glaube, ich hätte das nie gesehen :wink:

Hallo,

ich habe leider immer noch das Problem, dass ich nicht zwei Pointer Events handeln kann.
Ich habe die onTouchEvent() Methode jetzt so umgeschrieben (aus dem Buch Beginning Android Games und mit dem Hinweis von Marco funktioniert auch das antippen wieder)

	public boolean onTouchEvent(MotionEvent event) {

		int action = event.getAction() & MotionEvent.ACTION_MASK;
		int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
		int pointerCount = event.getPointerCount();
		for (int i=0; i <10; i++)	{
			if(i >= pointerCount){
				touched** = false;
				id** = -1;
				continue;
			}
			if(event.getAction() != MotionEvent.ACTION_MOVE && i != pointerIndex) {
				// if its an up/down/cancel/out event, mask the id to see if we should process it for this touch point
				continue;
			}
			int pointerId = event.getPointerId(i);
			switch (action) {
			case MotionEvent.ACTION_DOWN:
			case MotionEvent.ACTION_POINTER_DOWN:
				touched** = true;
				id** = pointerId;
				x** = (int) event.getX(i);
				y** = (int) event.getY(i);
				
				greenBall.handleActionDown((int)x**,(int)y**);
				redBall.handleActionDown((int)x**,(int)y**);
				break;
			case MotionEvent.ACTION_UP:
			case MotionEvent.ACTION_POINTER_UP:
			case MotionEvent.ACTION_OUTSIDE:
			case MotionEvent.ACTION_CANCEL:
				touched** = false;
				id** = -1;
				x** = (int) event.getX(i);
				y** = (int) event.getY(i);
				
				greenBall.handleActionDown((int)x**,(int)y**);
				redBall.handleActionDown((int)x**,(int)y**);
				break;
				
			case MotionEvent.ACTION_MOVE:
				touched** = true;
				id** = pointerId;
				x** = (int) event.getX(i);
				y** = (int) event.getY(i);
				
				greenBall.handleActionDown((int)x**,(int)y**);
				redBall.handleActionDown((int)x**,(int)y**);
				break;
			}
		}
		
		
		return true;
	}```

Ich habe zwei Bitmaps, einen links, einen rechts in der Mitte, sie sind Instanzen der GreenBall Klasse
Aber wenn ich einen antippe und halte, dann setzt es auch onTouched auf true, aber so wie ich den zweiten zusätzlich antippe und halte, geht der erst auf false und der zweite auf true. lass ich den zweiten los, bleibt es aber so.
Tippe ich den zweiten an, geht der auf true, dann den ersten, dann wechselt es auch, und lass ich den ersten los, geht der auch wieder auf false und der zweite auf true.

Also irgendwie schaffe ich es nicht, beide gleichzeitig zu handeln und ich hab auch irgendwie keinen Plan, wie ich das am besten umsetze.
Kann mir da jemand helfen?

Ich hab mal die komplette Klasse vom GreenBall angehängt.

Danke
Chris

```package de.fuckthesystem.thenewboston;

import android.graphics.Bitmap;
import android.graphics.Canvas;

public class GreenBall {

	private Bitmap bitmap; // the actual bitmap
	private int x; // the X coordinate
	private int y; // the Y coordinate
	private boolean touched; // if droid is touched/picked up

	public GreenBall(Bitmap bitmap, int x, int y) {
		this.bitmap = bitmap;
		this.x = x;
		this.y = y;
	}

	public Bitmap getBitmap() {
		return bitmap;
	}

	public void setBitmap(Bitmap bitmap) {
		this.bitmap = bitmap;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public boolean isTouched() {
		return touched;
	}

	public void setTouched(boolean touched) {
		this.touched = touched;
	}

	public void draw(Canvas canvas) {
		canvas.drawBitmap(bitmap, x - (bitmap.getWidth() / 2),
				y - (bitmap.getHeight() / 2), null);
	}

	public void handleActionDown(int eventX, int eventY) {

		if (eventX >= (x - bitmap.getWidth())
				&& (eventX <= (x + bitmap.getWidth()))) {
			if (eventY >= (y - bitmap.getHeight())
					&& (eventY <= (y + bitmap.getHeight()))) {
				// droid touched
				setTouched(true);
			} else {
				setTouched(false);
			}

		} else {
			setTouched(false);
		}

	}
}

ohne den Code wirklich betrachtet zu haben, eine Vermutung:
Die Touch Events bzw. deren Koordinaten werden immer an alle Instanzen zur Prüfung weiter gegeben und dementsprechend das touched Flag gesetzt. Da diese aber auf verschiedenen Koordinaten liegen, wird logischer bei das, welches gedrückt wurde true und alle anderen false.

Das Setzen der Flags darf nur passieren, wenn mit dem Finger gedrückt wird. Das rücksetzen darf erst beim anheben des Fingers oder bei Abbruch o.ä passieren. Wenn ich das richtig sehe läuft bei dir aber beides über das Down Event

hmm…
danke erst mal für den Denkanstoß, ich muss das mal neu überlegen :wink: