Java Android onTouch Direction - java

I am trying to develop a simple game wherein I need to throw a bullet .
I would like the ball follows the touch, or swipe direction.
However, I have a small problem that I have not had success in solving.
I take coordinates on the ACTION_DOWN of MotionEvent, and the coordinates on the ACTION_UP of MotionEvent, then calculate the straight line equation in order to move the ball according to this straight line.
The problem is that when I swipe in a direction close to "up" or "forward" or "in front of", the ball moves at lightning speed while in the other direction of more skewed (right or left) or diagonal, the ball moves at a normal speed.
Where is the flaw in my calculation?
Help me please, I am not far from the result but need to you for solve this problem!
The onTouch method:
public boolean onTouchEvent(MotionEvent event) {
switch(event.getAction()) {
case(MotionEvent.ACTION_DOWN):
balle.setX(event.getX());
balle.setY(event.getY());
ya = event.getY();
xa = event.getX();
break;
case(MotionEvent.ACTION_UP):
xb = event.getX();
yb = event.getY();
balle.setMove(true);
break;
}
return true;
}
This is my moveDirection method:
public void moveDirection(float xa, float ya, float xb, float yb) {
if(!move) {
return;
}
else {
float m, b;
float dx = xb-xa;
m = (yb - ya) / (xb - xa);
b = ya - (m * xa);
if(dx > 0) {
this.x += speedX;
}
else {
this.x += -speedX;
}
this.y = (m * this.x + b);
}
}
Thank you in advance!

I see you are not capturing all the events so, maybe the code from the Android Documentation with de VelocityTracker api may help, in this example when you pull down your finger, a new tracker is created and when you move (in any direction) you capture the velocity of the event, i think you can move the ball according with the velocity and direction of touch.
public class MainActivity extends Activity {
private static final String DEBUG_TAG = "Velocity";
...
private VelocityTracker mVelocityTracker = null;
#Override
public boolean onTouchEvent(MotionEvent event) {
int index = event.getActionIndex();
int action = event.getActionMasked();
int pointerId = event.getPointerId(index);
switch(action) {
case MotionEvent.ACTION_DOWN:
if(mVelocityTracker == null) {
// Retrieve a new VelocityTracker object to watch the velocity of a motion.
mVelocityTracker = VelocityTracker.obtain();
}
else {
// Reset the velocity tracker back to its initial state.
mVelocityTracker.clear();
}
// Add a user's movement to the tracker.
mVelocityTracker.addMovement(event);
break;
case MotionEvent.ACTION_MOVE:
mVelocityTracker.addMovement(event);
// When you want to determine the velocity, call
// computeCurrentVelocity(). Then call getXVelocity()
// and getYVelocity() to retrieve the velocity for each pointer ID.
mVelocityTracker.computeCurrentVelocity(1000);
// Log velocity of pixels per second
// Best practice to use VelocityTrackerCompat where possible.
Log.d("", "X velocity: " +
VelocityTrackerCompat.getXVelocity(mVelocityTracker,
pointerId));
Log.d("", "Y velocity: " +
VelocityTrackerCompat.getYVelocity(mVelocityTracker,
pointerId));
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
// Return a VelocityTracker object back to be re-used by others.
mVelocityTracker.recycle();
break;
}
return true;
}
}
Link for doc.

Related

How to Pan Zoom in Zoom out Functionality in min3d Android

I am new in OpenGl Devloper,i want to render 3d model in OpenGl android so i choose min3d framework library.
I want to Pan Zoom in zoom out functionality for my model ,like camera zoom in zoom out in min3d
like , i have 3dmodel of lady and i want to zoom out her face any solution without scale object?
You need to change the camera position. I suggest you define some additional parameters center and distance since you want to pan.
When you have a zoom gesture you simply apply zoom scale to distance distance *= scale (or distance = originalDistance*scale depending on the implementation).
On pan you simply move the center by distances center.x += (newXOnScreen-oldXOnScreen)*speedFactor and center.y += (newYOnScreen-oldYOnScreen)*speedFactor. The speed factor may be constant here (play around a bit with it) but it might be best to multiply it by a zoom scale as well so that if it is very close the center will move less.
Now that you have these 2 parameters you need to apply them to the camera. Assuming you have a model position at (0,0,0):
scene.camera.position = {center.x, center.y, center.z-distance}
scene.camera.target = {center.x, center.y, center.z}
scene.camera.up = {0, 1, 0}
The following code snippet worked for me. It is not the complete code, but I have just added the part which does the pinch zoom and drag of the 3d object in min3d framework. I put together the code by following online tutorials from here and modified according to the application
//import statements
public class threedviewActivity extends RendererActivity {
private Object3dContainer Object3D;
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f,mLastTouchX,mLastTouchY,mPosX,mPosY;
private int mActivePointerId = INVALID_POINTER_ID,flag;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mScaleDetector = new ScaleGestureDetector(threedviewActivity.this, new ScaleListener());
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
// Let the ScaleGestureDetector inspect all events.
mScaleDetector.onTouchEvent(ev);
final int action = MotionEventCompat.getActionMasked(ev);
switch (action) {
case MotionEvent.ACTION_DOWN: {
final int pointerIndex = MotionEventCompat.getActionIndex(ev);
final float x = MotionEventCompat.getX(ev, pointerIndex);
final float y = MotionEventCompat.getY(ev, pointerIndex);
mLastTouchX = x;
mLastTouchY = y;
mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
updateScene();
break;
}
case MotionEvent.ACTION_MOVE: {
// Find the index of the active pointer and fetch its position
final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
final float x = MotionEventCompat.getX(ev, pointerIndex);
final float y = MotionEventCompat.getY(ev, pointerIndex);
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
// Remember this touch position for the next move event
mLastTouchX = x;
mLastTouchY = y;
flag = 1;
updateScene();
break;
}
case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = MotionEventCompat.getActionIndex(ev);
final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = MotionEventCompat.getX(ev, newPointerIndex);
mLastTouchY = MotionEventCompat.getY(ev, newPointerIndex);
mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
}
break;
}
}
return true;
}
#Override
public void initScene()
{
//this is where you initialize your 3d object. Check below for links for tutorials on that.
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
Object3D.scale().x = Object3D.scale().y = Object3D.scale().z = mScaleFactor*1.5f;
flag = 0;
updateScene();
return true;
}
}
#Override
public void updateScene()
{
if(flag == 1)
{
Object3D.position().x = mPosX/100;
Object3D.position().y = -mPosY/100;
}
}
}
For initalizing min3D, follow the tutorials here and here

Android- How to drag a picture on a canvas

I need to drag an image like in a videogame. I have a few lines drawed and I need to drag it and see the lines drawed before "out" of the window. I give you two images trying to help to understand it.
Image before drag:
Then I touch the screen with my finger and I make a move to the top of the screen, so this three lines have to be upper than the initial image, like this:
I don't know how to do this "drag efect", can someone help me? This is not an image as a .jpg file, is three lines drawed with "drawLine" on a canvas into an imageView.
My onTouchEvent Code and my drawRectangle code:
public boolean onTouch(View view, MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_UP:
{
x = event.getX();
y = event.getY();
getFirstFoot();
return true;
}
case MotionEvent.ACTION_MOVE:
{
ammountX = event.getX() - startX;
ammountY = event.getY() - startY;
canvas.save();
canvas.translate(ammountX, ammountY);
//canvas.restore();
imageView.invalidate();
return true;
}
case MotionEvent.ACTION_DOWN:
{
startX = event.getX();
startY = event.getY();
}
}
return true;
}
drawRectagle code:
private void drawRectangle(boolean erase)
{
buttonRed.setVisibility(View.VISIBLE);
buttonGree.setVisibility(View.VISIBLE);
buttonYellow.setVisibility(View.VISIBLE);
Bitmap bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.ascensorsininfo);
canvas.drawBitmap(bitmap2, x - (bitmap2.getWidth() / 2), y - bitmap2.getHeight(), new Paint());
drawedPoints.add(String.valueOf(x - (bitmap2.getWidth() / 2)));
drawedPoints.add(String.valueOf(y - bitmap2.getHeight()));
imageView.invalidate();
y -= bitmap2.getHeight();
}
Any solution would be apreciated. Thanks!
Check out Canvas.translate
It will "move" everything you draw afterwards the ammount you say in x and y axis.
Don't forget to save and restore it, like:
canvas.save();
canvas.translate(ammountX, ammountY);
// [draw your stuff here]
canvas.restore();
If your question is more towards how to detect the dragging effect, you have to Override your view's onTouchEvent method. Something like:
#Override
public boolean onTouchEvent (MotionEvent event){
if(event.getActionMasked() == MotionEvent.DOWN){
startX = event.getX();
startY = event.getY();
return true;
}else if(event.getActionMasked() == MotionEvent.MOVE){
ammountX = event.getX() - startX;
ammountY = event.getY() - startY;
return true;
}
return super.onTouchEvent(event);
}

Android - Java: how to draw a straight line slowly

I can't draw a straight line slowly!
when I slide slowly I have a wavy line instead a straight line.
I tried to use the tool "Pointer location" to check the points and I recived the same result.
But when I slide fastly, vertical, or horizontal, I recived straight line...
This is my code
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
String ms;
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
int xDown = (int)event.getX();
int yDown = (int)event.getY();
ms = "down";
out.println(xDown);
out.println(yDown);
out.println(ms);
break;
case MotionEvent.ACTION_MOVE:
ms = "move";
int hsize = event.getHistorySize();
for(int i=0;i<hsize;i++)
{
int x = (int)event.getHistoricalX(i);
int y = (int)event.getHistoricalY(i);
int hx = x;
int hy = y;
out.println(hx);
out.println(hy);
out.println(ms);
}
/*
int xMove = (int)event.getX();
int yMove = (int)event.getY();
out.println(xMove);
out.println(yMove);
ms = "move";
out.println(ms);
*/
break;
case MotionEvent.ACTION_UP:
int xUp = (int)event.getX();
int yUp = (int)event.getY();
out.println(xUp);
out.println(yUp);
ms = "up";
out.println(ms);
break;
}
return false;
}
I can suggest you to save starting location and redraw line each time from the starting point to the point where you are touching the screen.
If you don't want a polygon made of straight lines you can draw it by tapping the screen where you want to place next point.

Touch within view only- android

I am trying to do this but it gave me headache
I have a view that draw a color bar. And I want to allow user to move it around (drag and drop)
this is on draw method:
int r,g,b;
for(int i = 0; i < 64; i++)
{
r = Math.round((float)colorBuffer[i][0]*MAX_SCALING);
g = Math.round((float)colorBuffer[i][1]*MAX_SCALING);
b = Math.round((float)colorBuffer[i][2]*MAX_SCALING);
paint.setColor(Color.argb(MAX_SCALING, r, g, b));
canvas.drawLine(x1, y1, x2, y1, paint);
y1+=3;
}
rgb is just the color.
this is my ontouch implementation.
public boolean onTouchEvent(MotionEvent e)
{
float x = e.getX();
float y = e.getY();
switch (e.getAction())
{
case MotionEvent.ACTION_DOWN:
{
Toast t = Toast.makeText(getContext(), "Touch", Toast.LENGTH_SHORT);
t.show();
break;
}
case MotionEvent.ACTION_MOVE:
{
x1=(int) x;
x2=(int) (x+30);
y1=(int) y;
break;
}
case MotionEvent.ACTION_UP:
{
Toast t = Toast.makeText(getContext(), "Release", Toast.LENGTH_SHORT);
t.show();
x1=(int) x;
x2=(int) (x+30);
y1=(int) y;
break;
}
}
invalidate();
return true;
}
this works perfectly fine, but the problem is that it works even outside the view.
so if i touch outsite the view my bar move over there too
even when i click a button my bar try to move too
I want to drag and drop the component only if the user touch within the view
any help would be appreciate
thanks
On touch get the x, y, width, and height of your view. Then every time when you are moving the bar, as I understand in MotionEvent.ACTION_MOVE, check if current coordinates are whithin the views's bounds, if this is true, then allow to move the bar.

Functionality changes after Activity is restarted

I have a puzzle game where pieces are dragged around the screen but can not overlap. If they attempt to overlap, their position is changed back to where they were not overlapping and the UI is redrawn with invalidate(). This is working well except when the activity is destroyed and rebuilt like when closing the app and restarting it or when the orientation is changed.
What seems to happen is that the position variables that I use for collisions (x,y,right,bottom, etc.) are not reset to how they were initialized in the constructor. Pieces collide with invisible objects, snap to seemingly random positions, or move erratically.
The only ways to fix it are to manually kill the app (like with a task killer) or re-install it. Then it will work fine until the game activity is created a second time. What am I doing wrong? Any ideas? Here's how the piece are added in the onCreate() inside my GameView class:
Pieces redtiki = new Pieces(this,0,0,R.drawable.tikired);
...
board.addView(redtiki);
And this is a portion of my Pieces class:
public class Pieces extends View{
private int x;
private int y;
private int width;
private int height;
private int right;
private int bottom;
private int initialX;
private int initialY;
private Bitmap sizedBitmap;
private Bitmap sourceBitmap;
private int boardSize = 6;
public static ArrayList<Pieces> aPieces = new ArrayList<Pieces>();
//private final Paint mPaint = new Paint();
public Pieces(Context context, int x, int y, int img){
super(context);
this.x = x;
this.y = y;
sourceBitmap = BitmapFactory.decodeResource(getResources(), img);
aPieces.add(this);
initialX=x;
initialY=y;
}
private void sizePiece(){
int scaledWidth;
int scaledHeight;
int h = sourceBitmap.getHeight();
int w = sourceBitmap.getWidth();
if (h>w){
scaledWidth = 1;
}else if (w>h){
scaledWidth = w/h;
}else{
scaledWidth = 0;
}
if (h>w){
scaledHeight = h/w;
}else if (w>h){
scaledHeight = 1;
}else{
scaledHeight = 0;
}
int dstWidth = (((((View) getParent()).getWidth())*scaledWidth)/boardSize)-1;//TODO make sure that -1 is necessary for
int dstHeight = (((((View) getParent()).getHeight())*scaledHeight)/boardSize)-1;//fitting all pieces on the board
sizedBitmap = Bitmap.createScaledBitmap(sourceBitmap, dstWidth, dstHeight, true);
width = sizedBitmap.getWidth();
height = sizedBitmap.getHeight();
right = x+width;
bottom = y+height;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
sizePiece();
canvas.drawBitmap(sizedBitmap, x, y, null);
}
#Override
public boolean onTouchEvent(MotionEvent event){
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//check if touch is on piece
if (eventX > x && eventX < (x+width) && eventY > y && eventY < (y+height)){
initialX=x;
initialY=y;
break;
}else{
return false;
}
case MotionEvent.ACTION_MOVE:
//determine if piece should move horizontally or vertically
if(width>height){
for (Pieces piece : aPieces) {
//if object equals itself in array, skip to next object
if(piece==this){
continue;
}
//check if there the possibility for a horizontal collision
if(this.isAllignedHorizontallyWith(piece)){
//check for and handle collisions while moving left
if(this.isRightOf(piece)){
if(eventX>piece.right+(width/2)){
x = (int)(eventX-(width/2)); //move normally
/*for(Pieces piece2 : aPieces){
if(this.isAllignedHorizontallyWith(piece2)){
if(this.isLeftOf(piece2)){
if(eventX<piece2.x-(width/2)){
x = (int)(eventX-(width/2));
continue;
}else{
x = piece2.x-width-1;
}
}
}
}*/
continue;
}else{
x = piece.right+1;
}
}
//check for and handle collisions while moving right
if(this.isLeftOf(piece)){
if(eventX<piece.x-(width/2)){
x = (int)(eventX-(width/2));
continue;
}else{
x = piece.x-width-1;
}
}
break;
}else{
x = (int)(eventX-(width/2));
}
}
}
if(height>width){
for (Pieces piece : aPieces) {
//if object equals itself in array, skip to next object
if(piece==this){
continue;
}
//check if there the possibility for a vertical collision
if(this.isAllignedVerticallyWith(piece)){
//check for and handle collisions while moving up
if(this.isBelow(piece)){
if(eventY>piece.bottom+(height/2)){
y = (int)(eventY-(height/2)); //move normally
continue;
}else{
y = piece.bottom+1;
}
}
//check for and handle collisions while moving down
if(this.isAbove(piece)){
if(eventY<piece.y-(height/2)){
y = (int)(eventY-(height/2));
continue;
}else{
y = piece.y-height-1;
}
}
break;
}else{
y = (int)(eventY-(height/2));
}
}
}
invalidate();
break;
case MotionEvent.ACTION_UP:
// end move
if(this.moves()){
GameView.counter++;
}
initialX=x;
initialY=y;
break;
}
// parse puzzle
invalidate();
return true;
}
In your Activity class, implement the methods OnPause(), OnResume().
Use log statements within the above mentioned methods to see whether the positions/coordinates are changed during the closing/opening of the app.
You can save the state of the various components when "OnPause()" is called. When "OnResume()" is invoked (i.e application comes to the foreground) read the saved state and draw the View with the coordinates you read recently.
Please not that "OnCreate()" will only be called once when the Activity is being created. Switching orientations will not invoked "OnCreate()"
You will find a flowchart explaining the Android API documentation.
http://developer.android.com/reference/android/app/Activity.html
I just realized what was wrong. Each time that I create a new Pieces object, it is added to my ArrayList, aPieces. So every time that the orientation changed, or I loaded a new level, it would load all my new pieces and display them, but my old pieces were still in the ArrayList and, therefore, still being checked for collisions. to solve this, before I load each new level (and all the pieces that make up the level), I clear the list with Pieces.aPieces.clear();. Now, it works perfectly.

Categories