Android: Make on-screen joysticks center on the initial touch input.

This commit is contained in:
Greg Wicks 2018-02-21 20:36:03 -05:00
parent 619f98b97b
commit b28236611d

View File

@ -12,7 +12,6 @@ import android.graphics.Canvas;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View;
/** /**
* Custom {@link BitmapDrawable} that is capable * Custom {@link BitmapDrawable} that is capable
@ -28,9 +27,12 @@ public final class InputOverlayDrawableJoystick
private int mPreviousTouchX, mPreviousTouchY; private int mPreviousTouchX, mPreviousTouchY;
private int mWidth; private int mWidth;
private int mHeight; private int mHeight;
private Rect mVirtBounds;
private Rect mOrigBounds;
private BitmapDrawable mOuterBitmap; private BitmapDrawable mOuterBitmap;
private BitmapDrawable mDefaultStateInnerBitmap; private BitmapDrawable mDefaultStateInnerBitmap;
private BitmapDrawable mPressedStateInnerBitmap; private BitmapDrawable mPressedStateInnerBitmap;
private BitmapDrawable mBoundsBoxBitmap;
private boolean mPressedState = false; private boolean mPressedState = false;
/** /**
@ -57,12 +59,17 @@ public final class InputOverlayDrawableJoystick
mOuterBitmap = new BitmapDrawable(res, bitmapOuter); mOuterBitmap = new BitmapDrawable(res, bitmapOuter);
mDefaultStateInnerBitmap = new BitmapDrawable(res, bitmapInnerDefault); mDefaultStateInnerBitmap = new BitmapDrawable(res, bitmapInnerDefault);
mPressedStateInnerBitmap = new BitmapDrawable(res, bitmapInnerPressed); mPressedStateInnerBitmap = new BitmapDrawable(res, bitmapInnerPressed);
mBoundsBoxBitmap = new BitmapDrawable(res, bitmapOuter);
mWidth = bitmapOuter.getWidth(); mWidth = bitmapOuter.getWidth();
mHeight = bitmapOuter.getHeight(); mHeight = bitmapOuter.getHeight();
setBounds(rectOuter); setBounds(rectOuter);
mDefaultStateInnerBitmap.setBounds(rectInner); mDefaultStateInnerBitmap.setBounds(rectInner);
mPressedStateInnerBitmap.setBounds(rectInner); mPressedStateInnerBitmap.setBounds(rectInner);
mVirtBounds = getBounds();
mOrigBounds = mOuterBitmap.copyBounds();
mBoundsBoxBitmap.setAlpha(0);
mBoundsBoxBitmap.setBounds(getVirtBounds());
SetInnerBounds(); SetInnerBounds();
} }
@ -80,6 +87,7 @@ public final class InputOverlayDrawableJoystick
{ {
mOuterBitmap.draw(canvas); mOuterBitmap.draw(canvas);
getCurrentStateBitmapDrawable().draw(canvas); getCurrentStateBitmapDrawable().draw(canvas);
mBoundsBoxBitmap.draw(canvas);
} }
public void TrackEvent(MotionEvent event) public void TrackEvent(MotionEvent event)
@ -93,6 +101,10 @@ public final class InputOverlayDrawableJoystick
if (getBounds().contains((int)event.getX(pointerIndex), (int)event.getY(pointerIndex))) if (getBounds().contains((int)event.getX(pointerIndex), (int)event.getY(pointerIndex)))
{ {
mPressedState = true; mPressedState = true;
mOuterBitmap.setAlpha(0);
mBoundsBoxBitmap.setAlpha(255);
getVirtBounds().offset((int)event.getX(pointerIndex) - getVirtBounds().centerX(), (int)event.getY(pointerIndex) - getVirtBounds().centerY());
mBoundsBoxBitmap.setBounds(getVirtBounds());
trackId = event.getPointerId(pointerIndex); trackId = event.getPointerId(pointerIndex);
} }
break; break;
@ -102,6 +114,10 @@ public final class InputOverlayDrawableJoystick
{ {
mPressedState = false; mPressedState = false;
axises[0] = axises[1] = 0.0f; axises[0] = axises[1] = 0.0f;
mOuterBitmap.setAlpha(255);
mBoundsBoxBitmap.setAlpha(0);
setVirtBounds(new Rect(mOrigBounds.left, mOrigBounds.top, mOrigBounds.right, mOrigBounds.bottom));
setBounds(new Rect(mOrigBounds.left, mOrigBounds.top, mOrigBounds.right, mOrigBounds.bottom));
SetInnerBounds(); SetInnerBounds();
trackId = -1; trackId = -1;
} }
@ -117,12 +133,12 @@ public final class InputOverlayDrawableJoystick
{ {
float touchX = event.getX(i); float touchX = event.getX(i);
float touchY = event.getY(i); float touchY = event.getY(i);
float maxY = getBounds().bottom; float maxY = getVirtBounds().bottom;
float maxX = getBounds().right; float maxX = getVirtBounds().right;
touchX -= getBounds().centerX(); touchX -= getVirtBounds().centerX();
maxX -= getBounds().centerX(); maxX -= getVirtBounds().centerX();
touchY -= getBounds().centerY(); touchY -= getVirtBounds().centerY();
maxY -= getBounds().centerY(); maxY -= getVirtBounds().centerY();
final float AxisX = touchX / maxX; final float AxisX = touchX / maxX;
final float AxisY = touchY / maxY; final float AxisY = touchY / maxY;
axises[0] = AxisY; axises[0] = AxisY;
@ -152,7 +168,13 @@ public final class InputOverlayDrawableJoystick
setBounds(new Rect(mControlPositionX, mControlPositionY, setBounds(new Rect(mControlPositionX, mControlPositionY,
mOuterBitmap.getIntrinsicWidth() + mControlPositionX, mOuterBitmap.getIntrinsicWidth() + mControlPositionX,
mOuterBitmap.getIntrinsicHeight() + mControlPositionY)); mOuterBitmap.getIntrinsicHeight() + mControlPositionY));
setVirtBounds(new Rect(mControlPositionX, mControlPositionY,
mOuterBitmap.getIntrinsicWidth() + mControlPositionX,
mOuterBitmap.getIntrinsicHeight() + mControlPositionY));
SetInnerBounds(); SetInnerBounds();
setOrigBounds(new Rect(new Rect(mControlPositionX, mControlPositionY,
mOuterBitmap.getIntrinsicWidth() + mControlPositionX,
mOuterBitmap.getIntrinsicHeight() + mControlPositionY)));
mPreviousTouchX = fingerPositionX; mPreviousTouchX = fingerPositionX;
mPreviousTouchY = fingerPositionY; mPreviousTouchY = fingerPositionY;
break; break;
@ -178,17 +200,17 @@ public final class InputOverlayDrawableJoystick
private void SetInnerBounds() private void SetInnerBounds()
{ {
int X = getBounds().centerX() + (int)((axises[1]) * (getBounds().width() / 2)); int X = getVirtBounds().centerX() + (int)((axises[1]) * (getVirtBounds().width() / 2));
int Y = getBounds().centerY() + (int)((axises[0]) * (getBounds().height() / 2)); int Y = getVirtBounds().centerY() + (int)((axises[0]) * (getVirtBounds().height() / 2));
if (X > getBounds().centerX() + (getBounds().width() / 2)) if (X > getVirtBounds().centerX() + (getVirtBounds().width() / 2))
X = getBounds().centerX() + (getBounds().width() / 2); X = getVirtBounds().centerX() + (getVirtBounds().width() / 2);
if (X < getBounds().centerX() - (getBounds().width() / 2)) if (X < getVirtBounds().centerX() - (getVirtBounds().width() / 2))
X = getBounds().centerX() - (getBounds().width() / 2); X = getVirtBounds().centerX() - (getVirtBounds().width() / 2);
if (Y > getBounds().centerY() + (getBounds().height() / 2)) if (Y > getVirtBounds().centerY() + (getVirtBounds().height() / 2))
Y = getBounds().centerY() + (getBounds().height() / 2); Y = getVirtBounds().centerY() + (getVirtBounds().height() / 2);
if (Y < getBounds().centerY() - (getBounds().height() / 2)) if (Y < getVirtBounds().centerY() - (getVirtBounds().height() / 2))
Y = getBounds().centerY() - (getBounds().height() / 2); Y = getVirtBounds().centerY() - (getVirtBounds().height() / 2);
int width = mPressedStateInnerBitmap.getBounds().width() / 2; int width = mPressedStateInnerBitmap.getBounds().width() / 2;
int height = mPressedStateInnerBitmap.getBounds().height() / 2; int height = mPressedStateInnerBitmap.getBounds().height() / 2;
@ -217,6 +239,12 @@ public final class InputOverlayDrawableJoystick
return mOuterBitmap.getBounds(); return mOuterBitmap.getBounds();
} }
private void setVirtBounds(Rect bounds) { mVirtBounds = bounds; }
private void setOrigBounds(Rect bounds) { mOrigBounds = bounds; }
private Rect getVirtBounds() { return mVirtBounds; }
public int getWidth() public int getWidth()
{ {
return mWidth; return mWidth;