Android: Animate onscreen joystick

Invalidate more often, display nub as pressed when in use, and implement
basic nub bounds.
This commit is contained in:
Sean Maas 2017-05-13 19:16:07 -04:00
parent 247cdca9b9
commit 6190b1c4e2
2 changed files with 106 additions and 70 deletions

View File

@ -139,7 +139,6 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
{ {
button.setPressedState(true); button.setPressedState(true);
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(), ButtonState.PRESSED); NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(), ButtonState.PRESSED);
invalidate();
} }
break; break;
case MotionEvent.ACTION_UP: case MotionEvent.ACTION_UP:
@ -151,7 +150,6 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
} }
button.setPressedState(false); button.setPressedState(false);
invalidate();
break; break;
} }
} }
@ -193,7 +191,6 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
} }
setDpadState(dpad, up, down, left, right); setDpadState(dpad, up, down, left, right);
invalidate();
} }
break; break;
case MotionEvent.ACTION_UP: case MotionEvent.ACTION_UP:
@ -207,7 +204,6 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
} }
} }
dpad.setState(InputOverlayDrawableDpad.STATE_DEFAULT); dpad.setState(InputOverlayDrawableDpad.STATE_DEFAULT);
invalidate();
break; break;
} }
} }
@ -224,6 +220,8 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
} }
} }
invalidate();
return true; return true;
} }
@ -333,11 +331,9 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
mJoystickBeingConfigured = null; mJoystickBeingConfigured = null;
} }
break; break;
} }
} }
return true; return true;
} }
@ -414,15 +410,13 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
} }
if (mPreferences.getBoolean("buttonToggleGc9", true)) if (mPreferences.getBoolean("buttonToggleGc9", true))
{ {
overlayJoysticks.add(initializeOverlayJoystick(getContext(), overlayJoysticks.add(initializeOverlayJoystick(getContext(), R.drawable.gcwii_joystick_range,
R.drawable.gcwii_joystick_range, R.drawable.gcwii_joystick, R.drawable.gcwii_joystick, R.drawable.gcwii_joystick_pressed, ButtonType.STICK_MAIN));
ButtonType.STICK_MAIN));
} }
if (mPreferences.getBoolean("buttonToggleGc10", true)) if (mPreferences.getBoolean("buttonToggleGc10", true))
{ {
overlayJoysticks.add(initializeOverlayJoystick(getContext(), overlayJoysticks.add(initializeOverlayJoystick(getContext(), R.drawable.gcwii_joystick_range,
R.drawable.gcwii_joystick_range, R.drawable.gcpad_c, R.drawable.gcpad_c, R.drawable.gcpad_c_pressed, ButtonType.STICK_C));
ButtonType.STICK_C));
} }
} }
@ -487,9 +481,8 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
} }
if (mPreferences.getBoolean("buttonToggleWii10", true)) if (mPreferences.getBoolean("buttonToggleWii10", true))
{ {
overlayJoysticks.add(initializeOverlayJoystick(getContext(), overlayJoysticks.add(initializeOverlayJoystick(getContext(), R.drawable.gcwii_joystick_range,
R.drawable.gcwii_joystick_range, R.drawable.gcwii_joystick, R.drawable.gcwii_joystick, R.drawable.gcwii_joystick_pressed, ButtonType.NUNCHUK_STICK));
ButtonType.NUNCHUK_STICK));
} }
} }
@ -548,15 +541,13 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
} }
if (mPreferences.getBoolean("buttonToggleClassic12", true)) if (mPreferences.getBoolean("buttonToggleClassic12", true))
{ {
overlayJoysticks.add(initializeOverlayJoystick(getContext(), overlayJoysticks.add(initializeOverlayJoystick(getContext(), R.drawable.gcwii_joystick_range,
R.drawable.gcwii_joystick_range, R.drawable.gcwii_joystick, R.drawable.gcwii_joystick, R.drawable.gcwii_joystick_pressed, ButtonType.CLASSIC_STICK_LEFT));
ButtonType.CLASSIC_STICK_LEFT));
} }
if (mPreferences.getBoolean("buttonToggleClassic13", true)) if (mPreferences.getBoolean("buttonToggleClassic13", true))
{ {
overlayJoysticks.add(initializeOverlayJoystick(getContext(), overlayJoysticks.add(initializeOverlayJoystick(getContext(), R.drawable.gcwii_joystick_range,
R.drawable.gcwii_joystick_range, R.drawable.gcwii_joystick, R.drawable.gcwii_joystick, R.drawable.gcwii_joystick_pressed, ButtonType.CLASSIC_STICK_RIGHT));
ButtonType.CLASSIC_STICK_RIGHT));
} }
} }
@ -787,12 +778,13 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
* *
* @param context The current {@link Context} * @param context The current {@link Context}
* @param resOuter Resource ID for the outer image of the joystick (the static image that shows the circular bounds). * @param resOuter Resource ID for the outer image of the joystick (the static image that shows the circular bounds).
* @param resInner Resource ID for the inner image of the joystick (the one you actually move around). * @param defaultResInner Resource ID for the default inner image of the joystick (the one you actually move around).
* @param pressedResInner Resource ID for the pressed inner image of the joystick.
* @param joystick Identifier for which joystick this is. * @param joystick Identifier for which joystick this is.
* *
* @return the initialized {@link InputOverlayDrawableJoystick}. * @return the initialized {@link InputOverlayDrawableJoystick}.
*/ */
private static InputOverlayDrawableJoystick initializeOverlayJoystick(Context context, int resOuter, int resInner, int joystick) private static InputOverlayDrawableJoystick initializeOverlayJoystick(Context context, int resOuter, int defaultResInner, int pressedResInner, int joystick)
{ {
// Resources handle for fetching the initial Drawable resource. // Resources handle for fetching the initial Drawable resource.
final Resources res = context.getResources(); final Resources res = context.getResources();
@ -807,7 +799,8 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
// Initialize the InputOverlayDrawableJoystick. // Initialize the InputOverlayDrawableJoystick.
final Bitmap bitmapOuter = resizeBitmap(context, BitmapFactory.decodeResource(res, resOuter), scale); final Bitmap bitmapOuter = resizeBitmap(context, BitmapFactory.decodeResource(res, resOuter), scale);
final Bitmap bitmapInner = BitmapFactory.decodeResource(res, resInner); final Bitmap bitmapInnerDefault = BitmapFactory.decodeResource(res, defaultResInner);
final Bitmap bitmapInnerPressed = BitmapFactory.decodeResource(res, pressedResInner);
// The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay. // The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay.
// These were set in the input overlay configuration menu. // These were set in the input overlay configuration menu.
@ -835,10 +828,9 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
// Send the drawableId to the joystick so it can be referenced when saving control position. // Send the drawableId to the joystick so it can be referenced when saving control position.
final InputOverlayDrawableJoystick overlayDrawable final InputOverlayDrawableJoystick overlayDrawable
= new InputOverlayDrawableJoystick(res, = new InputOverlayDrawableJoystick(res, bitmapOuter,
bitmapOuter, bitmapInner, bitmapInnerDefault, bitmapInnerPressed,
outerRect, innerRect, outerRect, innerRect, joystick);
joystick);
// Need to set the image's position // Need to set the image's position
overlayDrawable.setPosition(drawableX, drawableY); overlayDrawable.setPosition(drawableX, drawableY);

View File

@ -18,42 +18,52 @@ import android.view.View;
* Custom {@link BitmapDrawable} that is capable * Custom {@link BitmapDrawable} that is capable
* of storing it's own ID. * of storing it's own ID.
*/ */
public final class InputOverlayDrawableJoystick extends BitmapDrawable public final class InputOverlayDrawableJoystick
{ {
private final int[] axisIDs = {0, 0, 0, 0}; private final int[] axisIDs = {0, 0, 0, 0};
private final float[] axises = {0f, 0f}; private final float[] axises = {0f, 0f};
private final BitmapDrawable ringInner;
private int trackId = -1; private int trackId = -1;
private int mJoystickType; private int mJoystickType;
private int mControlPositionX, mControlPositionY; private int mControlPositionX, mControlPositionY;
private int mPreviousTouchX, mPreviousTouchY; private int mPreviousTouchX, mPreviousTouchY;
private int mWidth;
private int mHeight;
private BitmapDrawable mOuterBitmap;
private BitmapDrawable mDefaultStateInnerBitmap;
private BitmapDrawable mPressedStateInnerBitmap;
private boolean mPressedState = false;
/** /**
* Constructor * Constructor
* *
* @param res {@link Resources} instance. * @param res {@link Resources} instance.
* @param bitmapOuter {@link Bitmap} which represents the outer non-movable part of the joystick. * @param bitmapOuter {@link Bitmap} which represents the outer non-movable part of the joystick.
* @param bitmapInner {@link Bitmap} which represents the inner movable part of the joystick. * @param bitmapInnerDefault {@link Bitmap} which represents the default inner movable part of the joystick.
* @param bitmapInnerPressed {@link Bitmap} which represents the pressed inner movable part of the joystick.
* @param rectOuter {@link Rect} which represents the outer joystick bounds. * @param rectOuter {@link Rect} which represents the outer joystick bounds.
* @param rectInner {@link Rect} which represents the inner joystick bounds. * @param rectInner {@link Rect} which represents the inner joystick bounds.
* @param joystick Identifier for which joystick this is. * @param joystick Identifier for which joystick this is.
*/ */
public InputOverlayDrawableJoystick(Resources res, public InputOverlayDrawableJoystick(Resources res, Bitmap bitmapOuter,
Bitmap bitmapOuter, Bitmap bitmapInner, Bitmap bitmapInnerDefault, Bitmap bitmapInnerPressed,
Rect rectOuter, Rect rectInner, Rect rectOuter, Rect rectInner, int joystick)
int joystick)
{ {
super(res, bitmapOuter); axisIDs[0] = joystick + 1;
this.setBounds(rectOuter); axisIDs[1] = joystick + 2;
axisIDs[2] = joystick + 3;
this.ringInner = new BitmapDrawable(res, bitmapInner); axisIDs[3] = joystick + 4;
this.ringInner.setBounds(rectInner);
SetInnerBounds();
this.axisIDs[0] = joystick + 1;
this.axisIDs[1] = joystick + 2;
this.axisIDs[2] = joystick + 3;
this.axisIDs[3] = joystick + 4;
mJoystickType = joystick; mJoystickType = joystick;
mOuterBitmap = new BitmapDrawable(res, bitmapOuter);
mDefaultStateInnerBitmap = new BitmapDrawable(res, bitmapInnerDefault);
mPressedStateInnerBitmap = new BitmapDrawable(res, bitmapInnerPressed);
mWidth = bitmapOuter.getWidth();
mHeight = bitmapOuter.getHeight();
setBounds(rectOuter);
mDefaultStateInnerBitmap.setBounds(rectInner);
mPressedStateInnerBitmap.setBounds(rectInner);
SetInnerBounds();
} }
/** /**
@ -66,11 +76,10 @@ public final class InputOverlayDrawableJoystick extends BitmapDrawable
return mJoystickType; return mJoystickType;
} }
@Override
public void draw(Canvas canvas) public void draw(Canvas canvas)
{ {
super.draw(canvas); mOuterBitmap.draw(canvas);
ringInner.draw(canvas); getCurrentStateBitmapDrawable().draw(canvas);
} }
public void TrackEvent(MotionEvent event) public void TrackEvent(MotionEvent event)
@ -82,12 +91,16 @@ public final class InputOverlayDrawableJoystick extends BitmapDrawable
case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN: case MotionEvent.ACTION_POINTER_DOWN:
if (getBounds().contains((int)event.getX(pointerIndex), (int)event.getY(pointerIndex))) if (getBounds().contains((int)event.getX(pointerIndex), (int)event.getY(pointerIndex)))
{
mPressedState = true;
trackId = event.getPointerId(pointerIndex); trackId = event.getPointerId(pointerIndex);
}
break; break;
case MotionEvent.ACTION_UP: case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP: case MotionEvent.ACTION_POINTER_UP:
if (trackId == event.getPointerId(pointerIndex)) if (trackId == event.getPointerId(pointerIndex))
{ {
mPressedState = false;
axises[0] = axises[1] = 0.0f; axises[0] = axises[1] = 0.0f;
SetInnerBounds(); SetInnerBounds();
trackId = -1; trackId = -1;
@ -136,12 +149,13 @@ public final class InputOverlayDrawableJoystick extends BitmapDrawable
int deltaY = fingerPositionY - mPreviousTouchY; int deltaY = fingerPositionY - mPreviousTouchY;
mControlPositionX += deltaX; mControlPositionX += deltaX;
mControlPositionY += deltaY; mControlPositionY += deltaY;
setBounds(new Rect(mControlPositionX, mControlPositionY, getBitmap().getWidth() + mControlPositionX, getBitmap().getHeight() + mControlPositionY)); setBounds(new Rect(mControlPositionX, mControlPositionY,
mOuterBitmap.getIntrinsicWidth() + mControlPositionX,
mOuterBitmap.getIntrinsicHeight() + mControlPositionY));
SetInnerBounds(); SetInnerBounds();
mPreviousTouchX = fingerPositionX; mPreviousTouchX = fingerPositionX;
mPreviousTouchY = fingerPositionY; mPreviousTouchY = fingerPositionY;
break; break;
} }
return true; return true;
} }
@ -164,17 +178,22 @@ public final class InputOverlayDrawableJoystick extends BitmapDrawable
private void SetInnerBounds() private void SetInnerBounds()
{ {
float floatX = this.getBounds().centerX(); int X = getBounds().centerX() + (int)((axises[1]) * (getBounds().width() / 2));
float floatY = this.getBounds().centerY(); int Y = getBounds().centerY() + (int)((axises[0]) * (getBounds().height() / 2));
floatY += axises[0] * (this.getBounds().height() / 2);
floatX += axises[1] * (this.getBounds().width() / 2); if (X > getBounds().centerX() + (getBounds().width() / 2))
int X = (int)(floatX); X = getBounds().centerX() + (getBounds().width() / 2);
int Y = (int)(floatY); if (X < getBounds().centerX() - (getBounds().width() / 2))
int width = this.ringInner.getBounds().width() / 2; X = getBounds().centerX() - (getBounds().width() / 2);
int height = this.ringInner.getBounds().height() / 2; if (Y > getBounds().centerY() + (getBounds().height() / 2))
this.ringInner.setBounds(X - width, Y - height, Y = getBounds().centerY() + (getBounds().height() / 2);
X + width, Y + height); if (Y < getBounds().centerY() - (getBounds().height() / 2))
ringInner.invalidateSelf(); Y = getBounds().centerY() - (getBounds().height() / 2);
int width = mPressedStateInnerBitmap.getBounds().width() / 2;
int height = mPressedStateInnerBitmap.getBounds().height() / 2;
mDefaultStateInnerBitmap.setBounds(X - width, Y - height, X + width, Y + height);
mPressedStateInnerBitmap.setBounds(mDefaultStateInnerBitmap.getBounds());
} }
public void setPosition(int x, int y) public void setPosition(int x, int y)
@ -182,4 +201,29 @@ public final class InputOverlayDrawableJoystick extends BitmapDrawable
mControlPositionX = x; mControlPositionX = x;
mControlPositionY = y; mControlPositionY = y;
} }
private BitmapDrawable getCurrentStateBitmapDrawable()
{
return mPressedState ? mPressedStateInnerBitmap : mDefaultStateInnerBitmap;
}
public void setBounds(Rect bounds)
{
mOuterBitmap.setBounds(bounds);
}
public Rect getBounds()
{
return mOuterBitmap.getBounds();
}
public int getWidth()
{
return mWidth;
}
public int getHeight()
{
return mHeight;
}
} }