Kingbluesapphire Kingbluesapphire - 8 days ago 7
Android Question

Make image go where user taps

For an android app im coding i am trying to make it so when the users taps the screen the "player" which is an image slides over until it reaches that x value

I tried calling this method when the player touches the screen in a MotionEvent

public void movementUpdate(int x){
if(goalX < x){
goalX -= width;
}
if(goalX > x){
goalX += width;
}
goalX = x;
}


then in an update method i call

public void update(){
if(goalX > x)
x += 4;
if(goalX < x)
x -= 4;
}


but the image always goes past it or not far enough

Also since the image is drawn in java from the left corner when you tap infront of the image do you have to minus 1/2 the width so it stops in the middle and not the edge, and if you click behind minus 1/2 too?

Answer

I made a basic structure for you to use also. If you paste the code you may have to add the package name, change the activity name, change the layout name, and add a png image named grey_star to the drawable folder.

import android.os.CountDownTimer;
import android.provider.ContactsContract;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

//the vars that contains the users touch coords, I set some place holders the disapear as soon
//as the user touches the screen
private float touchX = 100;
private float touchY = 100;

//number of pixels to be moved every tick you should
//calculate them based on the screen size in a setup method
private int xSpeed = 10;
private int ySpeed = 10;

//bounds of the screen
private int leftBound;
private int rightBound;
private int topBound;
private int bottomBound;

//screen dimensions
private float pxScreenWidth;
private float pxScreenHeight;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);


    //make the scree go fullscreen
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);

    //remove action bar, and set content view
    setContentView(R.layout.activity_main);
    ActionBar actionBar = getSupportActionBar();
    actionBar.hide();

    //obtain the width and height of the screen in pixels
    DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
    pxScreenHeight = displayMetrics.heightPixels;
    pxScreenWidth = displayMetrics.widthPixels;

    //set bounds
    leftBound = 0;
    rightBound = (int) pxScreenWidth;
    topBound = 0;
    bottomBound = (int) pxScreenHeight;


    mainGame();
}

private void mainGame() {


    //some kind of timer I am lazy and used the countdown for this example
    //it does something every millisecond
    //first value is number of ticks second is the size 1 = 1ms 1000=1s
    new CountDownTimer(1000000, 1) {

        public void onTick(long millisUntilFinished) {

            //get the image view
            ImageView thing = (ImageView) findViewById(R.id.thing);
            int x = (int) thing.getX();
            int y = (int) thing.getY();


            moveThing(x, y, (int) touchX, (int) touchY);


        }

        public void onFinish() {

        }
    }.start();

}

private void moveThing(int xCoord, int yCoord, int targetX, int targetY) {

    //adjust these values to center
    ImageView thing = (ImageView) findViewById(R.id.thing);
    targetX = targetX - thing.getWidth() / 2;
    targetY = targetY - thing.getHeight() / 2;

    int width = thing.getWidth();
    int height = thing.getHeight();

    //for recording intended position
    int tempX = 0;
    int tempY = 0;

    //check so don't run if don't have to.
    if (xCoord != targetX) {
        boolean lessX = false;

        //set value to move forward
        int x = xCoord + xSpeed;

        //but if has to move backwards set the value to move backwards
        if (targetX < xCoord) {
            x = xCoord - xSpeed;
            lessX = true;

        }

        //if the amount of pixes goes over the target set it to the target
        if (lessX == false && x > targetX) {
            x = targetX;

        } else if (lessX == true && x < targetX) {
            x = targetX;

        }

        //check x bounds
        int temp = checkXBounds(x, width, leftBound, rightBound);
        if(temp != -1){
            x = temp;

        }

        //draw the thing in the new location
        if (xCoord < targetX || (xCoord > targetX && lessX == true)) {
            thing.setX(x);

        }
        tempX = (int) x;


    }

    //check so don't run if don't have to.
    if (yCoord != targetY) {

        //set value to move forward
        int y = yCoord + ySpeed;
        boolean lessY = false;

        //but if has to move backwards set the value to move backwards
        if (targetY < yCoord) {
            y = yCoord - ySpeed;
            lessY = true;

        }

        //if the amount of pixes goes over the target set it to the target
        if (y > targetY && lessY == false) {
            y = targetY;

        } else if (y < targetY && lessY == true) {
            y = targetY;

        }

        //check y bounds
        int temp = checkYBounds(y, topBound, bottomBound, height);
        if(temp != -1){
            y = temp;

        }

        //draw the thing in the new location
        if (yCoord < targetY || (yCoord > targetY && lessY == true)) {
            thing.setY(y);

        }

        tempY = (int) y;
    }


    TextView textView = (TextView) findViewById(R.id.coords);
    textView.setText("x: " + tempX + " " + "y: " + tempY);

}

private int checkXBounds(int xCoord, int width, int leftBound, int rightBound){

    if(checkLeftBound(xCoord, leftBound) == false){
        return leftBound;

    }
    if(checkRightBound(xCoord, rightBound, width) == false){
        return rightBound - width;

    }

    return -1;
}

private int checkYBounds(int yCoord, int topBound, int bottomBound, int height){

    if(checkTopBound(yCoord, topBound) == false){
        return topBound;

    }

    if(checkBottomBound(yCoord, bottomBound, height) == false){
        return bottomBound - height;

    }

    return -1;
}

private boolean checkLeftBound(int xCoord, int leftBound) {
    if(xCoord < leftBound){
        return false;

    }

    return true;
}

private boolean checkRightBound(int xCoord, int rightBound, int width){
    if(xCoord + width > rightBound){
        return false;

    }

    return true;
}

private boolean checkTopBound(int yCoord, int topBound){
    if(yCoord < topBound){
        return false;

    }

    return true;
}

private boolean checkBottomBound(int yCoord, int bottomBound, int height){
    if(yCoord + height > bottomBound){
        return false;

    }

    return true;
}


//gets touch coordinates and handles moving the ship
@Override
public boolean onTouchEvent(MotionEvent event) {

    //get the touch coordinates
    touchX = event.getX();
    touchY = event.getY();


    return super.onTouchEvent(event);

}

}

This is the XML file. In a real game I would not make the ship this way. You will need to change a bit of the XML to make it work. Also, you will want to set the size of the image view a different way, because hard coding a value like I did is bad. I did it for speed.

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.honeymanappdev.bradleyhoneyman.moveaimageviewbasedonusertouch.MainActivity">

<ImageView
    android:id="@+id/thing"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:src="@drawable/grey_star"/>

<TextView
    android:id="@+id/coords"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"/>

I'd recommend using something else to load your bitmaps.

Comments