I have an Android game where user moves player by touching left and right side of the screen. I tried the game on Android and all worked OK. But one day it stopped working: buttons work but I can't control the Player by touching screen sides. I tried to reinstall Unity, delete Library folder and even tried other OS. It didn't help. How can I fix my project?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class MovingPlayer : MonoBehaviour
{
public float playerSpeed;
public float maxPos = 2.7f;
Vector3 position;
public uiManager ui;
public AudioManager am;
public Text coinCount;
int coin;
bool currntPlatformAndroid = false;
Rigidbody2D rb;
public GameObject particleSystemPrefab;
void Awake()
{
rb = GetComponent<Rigidbody2D>();
#if UNITY_ANDROID
currntPlatformAndroid = true;
#else
currentPlatformAndroid = false;
#endif
am.playerSound.Play();
}
// Use this for initialization
void Start()
{
coin = 0;
position = transform.position;
}
// Update is called once per frame
void Update()
{
if (currntPlatformAndroid == true)
{
TouchMove();
//AccelerometerMove();
}
else
{
position.x += Input.GetAxis("Horizontal") * playerSpeed * Time.deltaTime;
position.x = Mathf.Clamp(position.x, -2.7f, 2.7f);
transform.position = position;
}
position = transform.position;
position.x = Mathf.Clamp(position.x, -2.7f, 2.7f);
transform.position = position;
}
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.tag == "CubeObstacle")
{
//Destroy (gameObject);
foreach (ContactPoint2D contact in col.contacts)
{
Instantiate(particleSystemPrefab, contact.point, Quaternion.identity);
}
//gameObject.SetActive(false);
GameOverActivated();
ui.gameOverActivated();
am.playerSound.Stop();
}
if (col.gameObject.tag == "Coin")
{
Destroy(col.gameObject);
coin += 1;
coinCount.text = coin.ToString();
Debug.Log("Coin");
}
}
public void GameOverActivated()
{
Time.timeScale = 0;
PlayerPrefs.SetInt("coins", PlayerPrefs.GetInt("coins") + coin);
}
void AccelerometerMove()
{
float x = Input.acceleration.x;
if (x < -0.1f)
{
MoveLeft();
}
else if (x > 0.1f)
{
MoveRight();
}
else
{
SetVelocityZero();
}
}
void TouchMove()
{
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
float middle = Screen.width / 2;
if (touch.position.x < middle && touch.phase == TouchPhase.Began)
{
MoveLeft();
}
else if (touch.position.x > middle && touch.phase == TouchPhase.Began)
{
MoveRight();
}
}
else
{
SetVelocityZero();
}
}
public void MoveLeft()
{
rb.velocity = new Vector2(-playerSpeed, 0);
}
public void MoveRight()
{
rb.velocity = new Vector2(playerSpeed, 0);
}
public void SetVelocityZero()
{
rb.velocity = Vector2.zero;
}
}
You don't need to use Input.Touches, this should work fine:
void Update()
{
#if UNITY_EDITOR
position.x += Input.GetAxis("Horizontal") * playerSpeed * Time.deltaTime;
position.x = Mathf.Clamp(position.x, -2.7f, 2.7f);
transform.position = position;
#else
if (Input.GetMouseButton(0))
{
if (Input.mousePosition.x > Screen.width/2)
{
MoveRight();
}
else
{
MoveLeft()
}
}
else
{
SetVelocityToZero();
}
#endif
}
Hope this helps :)
I am working on 2D infinite runner. I have below code to take input from screen swipe to jump, slide and run fast. I am providing jumpHeight from editor and value is 500 with frame rate of 30. Code works fine generally but sometimes player jumps too high for up swipe. Similar code works as expected if input is from Keyboard. Why this is happening is beyond my understanding of unity. Any help is greatly appreciated.
using UnityEngine;
public class PlayerControl : MonoBehaviour
{
public float ForwardSpeed = 3.7f; //moves player in forward direction
public float speedOffset = 0.0f; //offset speed of player
public float JumpHeight = 250; //moves player in verticle direction
bool grounded = false; //checks if player is grounded or not
public Transform groundCheck;
float groundCheckRadius = 0.3f; //radius of groundcheck circle to check grounded bool
public LayerMask groundLayer;
Vector2 fingerStart;
Vector2 fingerEnd;
void Update()
{
foreach (Touch touch in Input.touches)
{
if (touch.phase == TouchPhase.Began)
{
fingerStart = touch.position;
fingerEnd = touch.position;
}
if (touch.phase == TouchPhase.Moved)
{
fingerEnd = touch.position;
if (Mathf.Abs(fingerEnd.y - fingerStart.y) > 50)//Vertical swipe
{
if (fingerEnd.y - fingerStart.y > 50)//up swipe
{
Jump();
}
else if (fingerEnd.y - fingerStart.y < -50)//Down swipe
{
//Slide();
}
fingerStart = touch.position;
}
}
if (touch.phase == TouchPhase.Stationary)
{
RunFast();
}
if (touch.phase == TouchPhase.Ended)
{
fingerEnd = touch.position;
if (Mathf.Abs(fingerEnd.y - fingerStart.y) > 50)//Vertical swipe
{
if (fingerEnd.y - fingerStart.y > 50)//up swipe
{
Jump();
}
else if (fingerEnd.y - fingerStart.y < -50)//Down swipe
{
//Slide();
}
}
}
}
if (Input.GetButton("Fire1"))
{
speedOffset = 2.5f;
}
else
{
speedOffset = 0.0f;
}
if (grounded && Input.GetKeyDown(KeyCode.UpArrow))
{
grounded = false;
GetComponent<Rigidbody2D>().AddForce(new Vector2(0, JumpHeight));
}
//check if circle overlaps with ground layer
grounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, groundLayer);
//Debug.Log(grounded);
}
void FixedUpdate()
{
//set players forward velocityto forward speed variable
Vector2 PlayerForwardvelocity = GetComponent<Rigidbody2D>().velocity;
// Vector2 PlayerJumpHeight = GetComponent<Rigidbody2D>().AddForce()
PlayerForwardvelocity.x = ForwardSpeed + speedOffset;
GetComponent<Rigidbody2D>().velocity = PlayerForwardvelocity;
}
void Jump()
{
if (grounded)
{
GetComponent<Rigidbody2D>().AddForce(new Vector2(0, JumpHeight));
speedOffset = 0.0f;
}
}
void RunFast()
{
if (Input.GetButton("Fire1"))
{
speedOffset = 2.5f;
}
else
{
speedOffset = 0.0f;
}
}
}
You have 2 problems with your code.
Your first problem lies in this line of code:
grounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, groundLayer);
This line of code is failing. grounded is always true. Because of this, jump is called too many times while player is not grounded.
Replace this line of code with
Collider2D playerCollider = gameObject.GetComponent<Collider2D>();
grounded = Physics2D.OverlapCircle(playerCollider.transform.position, 1, groundLayer);
OR
Collider2D playerCollider = gameObject.GetComponent<Collider2D>();
grounded = playerCollider.IsTouchingLayers(groundLayer.value);
Another problem with your code is a false report.Sometimes, collider overlapping returns true even if it is false. I tried moving that part of code to LateUpdate function but that didn't fix it.
You can fix it by implementing a timer. The timer resets to 0 and starts counting to 0.5 whenever player jumps. Don't jump when timer has not reached the value it is counting to. .5 to 1 is a perfect value for this. Increment the timer with Time.deltaTime. Below is your whole code with timer and fixes.
public class PlayerControl : MonoBehaviour
{
public float ForwardSpeed = 3.7f; //moves player in forward direction
public float speedOffset = 0.0f; //offset speed of player
public float JumpHeight = 250; //moves player in verticle direction
bool grounded = false; //checks if player is grounded or not
public Transform groundCheck;
float groundCheckRadius = 0.3f; //radius of groundcheck circle to check grounded bool
public LayerMask groundLayer;
Vector2 fingerStart;
Vector2 fingerEnd;
public float resetTimer = 0.5f; //.5 second
float timerCounter = 0;
Collider2D playerCollider = null;
Rigidbody2D playerRigidBody;
void Start()
{
playerRigidBody = GetComponent<Rigidbody2D>();
playerCollider = gameObject.GetComponent<Collider2D>();
}
void Update()
{
foreach (Touch touch in Input.touches)
{
if (touch.phase == TouchPhase.Began)
{
fingerStart = touch.position;
fingerEnd = touch.position;
}
if (touch.phase == TouchPhase.Moved)
{
fingerEnd = touch.position;
if (Mathf.Abs(fingerEnd.y - fingerStart.y) > 50)//Vertical swipe
{
if (fingerEnd.y - fingerStart.y > 50)//up swipe
{
Jump();
}
else if (fingerEnd.y - fingerStart.y < -50)//Down swipe
{
//Slide();
}
fingerStart = touch.position;
}
}
if (touch.phase == TouchPhase.Stationary)
{
RunFast();
}
if (touch.phase == TouchPhase.Ended)
{
fingerEnd = touch.position;
if (Mathf.Abs(fingerEnd.y - fingerStart.y) > 50)//Vertical swipe
{
if (fingerEnd.y - fingerStart.y > 50)//up swipe
{
Jump();
}
else if (fingerEnd.y - fingerStart.y < -50)//Down swipe
{
//Slide();
}
}
}
}
if (Input.GetButton("Fire1"))
{
speedOffset = 2.5f;
}
else
{
speedOffset = 0.0f;
}
if (grounded && Input.GetKeyDown(KeyCode.UpArrow))
{
grounded = false;
playerRigidBody.AddForce(new Vector2(0, JumpHeight));
}
//check if circle overlaps with ground layer
grounded = Physics2D.OverlapCircle(playerCollider.transform.position, 1, groundLayer);
//OR Use grounded = playerCollider.IsTouchingLayers(groundLayer.value);
//Increment Timer if it is still less than resetTimer
if (timerCounter < resetTimer)
{
timerCounter += Time.deltaTime;
}
}
void FixedUpdate()
{
//set players forward velocityto forward speed variable
Vector2 PlayerForwardvelocity = playerRigidBody.velocity;
// Vector2 PlayerJumpHeight = playerRigidBody.AddForce()
PlayerForwardvelocity.x = ForwardSpeed + speedOffset;
playerRigidBody.velocity = PlayerForwardvelocity;
}
void Jump()
{
if (grounded)
{
//Exit if timer has not reached the required value to jump again
if (timerCounter < resetTimer)
{
Debug.Log("Failed To Jump because timer has not yet reached");
return; //Exit
}
timerCounter = 0; //Reset Timer
playerRigidBody.AddForce(new Vector2(0, JumpHeight));
speedOffset = 0.0f;
Debug.Log("Jumped");
}
else
{
Debug.Log("Not on the Ground");
}
}
void RunFast()
{
if (Input.GetButton("Fire1"))
{
speedOffset = 2.5f;
}
else
{
speedOffset = 0.0f;
}
}
}
I have a custom view, and within the custom view I create 4 text views. I want each of these text views to respond to on touch events. However, the textviews themselves do not respond to an on touch event. I can however, make an ontouch listener for the entire custom view. However, I do not want the whole view to have an ontouch event because I want the textviews that I have created to be dragged and dropped. I tried going the route of registering the x and y coordinates of the ontouch event and assuming that if the ontouch event is within the bounds of a textview, to change the coordinates of the textview, but that was overly complicated because if one textview got dragged to the coordinates of another one, then the ontouch event would "pick up" the other textview, so then I'd be moving two text views, which is not what I want. So, to sum it up, I want to know if it's possible to set in ontouch listener for a textview inside a customview, and if possible, why it is not working:
mScale.mPositive.get(0).setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
mScale.mCurrentXPos[0] = event.getX();
mScale.mCurrentYPos[0] = event.getY();
mScale.mDrag = true;
return true;
}
});
This same code works for the custom view, but not for the specific textviews inside that customview.
Here is the custom view code:
public class Scale extends View
{
public Scale(Context context, AttributeSet attrs)
{
super(context, attrs);
mContext = this.getContext();
h = new Handler();
mCalendarDbHelper=new CalendarDbAdapter(mContext);
mCalendarDbHelper.open();
Cursor thoughts = mCalendarDbHelper.fetchThoughts();
//create a string array of negative thoughts from the db
while (thoughts.moveToNext())
{
if (thoughts.getString(thoughts.getColumnIndexOrThrow(CalendarDbAdapter.COLUMN_NAME_THOUGHT)).length() > 0 && thoughts.getString(thoughts.getColumnIndexOrThrow(CalendarDbAdapter.COLUMN_NAME_THOUGHT)).charAt(0) == '-')
{
negative_thoughts.add(thoughts.getString(thoughts.getColumnIndexOrThrow(CalendarDbAdapter.COLUMN_NAME_THOUGHT)));
}
}
thoughts.close();
array_size = negative_thoughts.size();
mBag =BitmapFactory.decodeResource(getResources(), R.drawable.bag);
mGreenBag = BitmapFactory.decodeResource(getResources(), R.drawable.green_bag);
for (int i = 0; i < 72; i ++)
{
try
{
mScale[i] = BitmapFactory.decodeStream(context.getAssets().open("scale_"+i+".gif"));
}
catch (IOException e)
{
}
}
}
private Runnable r= new Runnable()
{
#Override
public void run() {
invalidate();
}
};
protected void onDraw (Canvas canvas)
{
if (first == true)
{
width = this.getWidth();
height = this.getHeight();
mScale[i] = Bitmap.createScaledBitmap(mScale[i], (int) (width * 1.5), height, true);
mBag = Bitmap.createScaledBitmap(mBag, width/2, height/2, true);
negative = new TextView(mContext);
word = negative_thoughts.get((int) (Math.random() * array_size));
negative.setText(word);
negative.layout(0, 0, width/3, height/4);
negative.setGravity(Gravity.CENTER);
negative.setTextSize(15);
negative.setTextColor(Color.BLACK);
negative.setTypeface(Typeface.DEFAULT_BOLD);
negative.setShadowLayer(5, 2, 2, Color.WHITE);
negative.setDrawingCacheEnabled(true);
negative.setBackgroundResource(R.drawable.graycloud);
positive_paint.setColor(Color.parseColor("#FF4444"));
positive_paint.setShadowLayer(5, 2, 2, Color.YELLOW);
positive_paint.setTypeface(Typeface.DEFAULT_BOLD);
positive_paint.setTextSize(25);
mCurrentXPos[0] = (width/2);
mCurrentYPos[0] = height/4;
mCurrentXPos[1] = (width/2) + (width/8);
mCurrentYPos[1] = height/6;
mCurrentXPos[2] = width/2;
mCurrentYPos[2] = height/12;
mCurrentXPos[3] = (width/2) + (width/8);
mCurrentYPos[3] = height/18;
mMoveXPos[0] = ((width/2) - width)/FRAME_RATE;
mMoveYPos[0] = ((height/4) - (height + (height/4)))/FRAME_RATE;
mMoveXPos[1] = (((width/2) + (width/8)) - width)/ FRAME_RATE;
mMoveYPos[1] = ((height/6) - (height + (height/4)))/FRAME_RATE;
mMoveXPos[2] = ((width/2) - width)/ FRAME_RATE;
mMoveYPos[2] = ((height/12) - (height + (height/4)))/FRAME_RATE;
mMoveXPos[3] = (((width/2) + (width/8)) - width)/ FRAME_RATE;
mMoveYPos[3] = ((height/18) - (height + (height/4)))/FRAME_RATE;
mMoveByXPos[0] = -(width/2)/ FRAME_RATE;
mMoveByYPos[0] = -(height/4)/FRAME_RATE;
mMoveByXPos[1] = ((width - (width/3)) - (width/2 + (width/8)))/ FRAME_RATE;
mMoveByYPos[1] = -(height/6)/FRAME_RATE;
mMoveByXPos[2] = - (width/2)/ FRAME_RATE;
mMoveByYPos[2] = ((height) - (height/12))/FRAME_RATE;
mMoveByXPos[3] = ((width - (width/3)) - (width/2 + (width/8)))/ FRAME_RATE;
mMoveByYPos[3] = ((height) - (height/18))/FRAME_RATE;
currentX = width;
currentY = height + height/4;
first = false;
}
if (game_over == false)
{
canvas.drawBitmap(mScale[i], 0 - (width/4), 0, null);
canvas.drawBitmap(negative.getDrawingCache(),(int) (width/12), (int) (height - (height)/2.5) - (j), null);
}
else
{
canvas.drawBitmap(mBag, width/4, height/4, null);
}
if (mMoveScale == true)
{
i++;
j+=3;
ScaleIt(canvas, i);
if (i == 21 || i == 37 || i == 53 || i == 71)
{
mMoveScale = false;
}
}
if (tracker > 0)
{
if (tracker == 1)
{
if (currentX > width/2 && currentY > height/4 && sStop == false)
{
currentX += mMoveXPos[0];
currentY += mMoveYPos[0];
canvas.drawBitmap(mPositive.get(tracker -1 ).getDrawingCache(), currentX, currentY, null);
}
else
{
if (sStop == false)
{
mMoveScale = true;
sStop = true;
currentX = width;
currentY = height + height/4;
draw_em++;
}
}
}
if (tracker == 2)
{
if (currentX > width/2 + (width/8) && currentY > (height/6) && sStop == false)
{
currentX += mMoveXPos[1];
currentY += mMoveYPos[1];
canvas.drawBitmap(mPositive.get(tracker -1 ).getDrawingCache(), currentX, currentY, null);
}
else
{
if (sStop == false)
{
mMoveScale = true;
sStop = true;
currentX = width;
currentY = height + height/4;
draw_em++;
}
}
}
if (tracker == 3)
{
if (currentX > width/2 && currentY > height/12 && sStop == false)
{
currentX += mMoveXPos[2];
currentY += mMoveYPos[2];
canvas.drawBitmap(mPositive.get(tracker -1 ).getDrawingCache(), currentX, currentY, null);
}
else
{
if (sStop == false)
{
mMoveScale = true;
sStop = true;
currentX = width;
currentY = height + height/4;
draw_em++;
}
}
}
if (tracker == 4)
{
if (currentX > width/2 + (width/8) && currentY > (height/18) && sStop == false)
{
currentX += mMoveXPos[3];
currentY += mMoveYPos[3];
canvas.drawBitmap(mPositive.get(tracker -1 ).getDrawingCache(), currentX, currentY, null);
}
else
{
if (sStop == false)
{
mMoveScale = true;
sStop = true;
game_over = true;
currentX = width;
currentY = height + height/4;
draw_em++;
}
}
}
if (draw_em > 0 && game_over == false)
{
for (int i = 0; i < draw_em; i ++)
{
if (i == 0)
{
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), width/2, height/4 + j, null);
}
if (i == 1)
{
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), width/2 + (width/8), height/6 + j, null);
}
if (i == 2)
{
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), width/2, height/12 + j, null);
}
if (i == 3)
{
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), width/2 + (width/8), height/18 + j, null);
}
}
}
else if (game_over == true)
{
for (int i = 0; i < draw_em; i++)
{
if (i == 0 && mCurrentXPos[0] > 0 && mCurrentYPos[0] > 0 && mDrag == false)
{
mCurrentXPos[0] += mMoveByXPos[0];
mCurrentYPos[0] += mMoveByYPos[0];
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), mCurrentXPos[0], mCurrentYPos[0], null);
}
else if (i == 0 && mCurrentXPos[0] <= 0 || mCurrentYPos[0] <= 0 && mDrag == false)
{
canvas.drawBitmap(mPositive.get(0).getDrawingCache(), 0, 0, null);
}
else if (i == 0 && mDrag == true)
{
canvas.drawBitmap(mPositive.get(0).getDrawingCache(), mCurrentXPos[0], mCurrentYPos[0], null);
}
if (i == 1 && mCurrentXPos[1] < (width - (mPositive.get(i).getWidth()/2)) && mCurrentYPos[1] > mPositive.get(i).getHeight()/2)
{
mCurrentXPos[1] += mMoveByXPos[1];
mCurrentYPos[1] += mMoveByYPos[1];
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), mCurrentXPos[1], mCurrentYPos[1], null);
}
else if (i == 1 && mCurrentXPos[1] >= (width - (mPositive.get(i).getWidth()/2)) || mCurrentYPos[1] <= mPositive.get(i).getHeight()/2)
{
canvas.drawBitmap(mPositive.get(1).getDrawingCache(), width - (width/3), 0, null);
}
if (i == 2 && mCurrentXPos[2] > (mPositive.get(i).getWidth()/2) && mCurrentYPos[2] < (height - mPositive.get(i).getHeight()/2))
{
mCurrentXPos[2] += mMoveByXPos[2];
mCurrentYPos[2] += mMoveByYPos[2];
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), mCurrentXPos[2], mCurrentYPos[2], null);
}
else if (i == 2 && mCurrentXPos[2] <= (mPositive.get(i).getWidth()/2) || mCurrentYPos[2] >= (height - mPositive.get(i).getHeight()/2))
{
canvas.drawBitmap(mPositive.get(2).getDrawingCache(), 0, height - (height/4), null);
}
if (i == 3 && mCurrentXPos[3] < (width - (mPositive.get(i).getWidth()/2)) && mCurrentYPos[3] < (height - mPositive.get(i).getHeight()/2))
{
mCurrentXPos[3] += mMoveByXPos[3];
mCurrentYPos[3] += mMoveByYPos[3];
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), mCurrentXPos[3], mCurrentYPos[3], null);
}
else if (i == 3 && mCurrentXPos[3] >= (width - (mPositive.get(i).getWidth()/2)) || mCurrentYPos[3] >= (height - mPositive.get(i).getHeight()/2))
{
canvas.drawBitmap(mPositive.get(3).getDrawingCache(), width - (width/3), height - (height/4), null);
}
}
}
}
h.postDelayed(r, FRAME_RATE);
}
protected void moveIt(Canvas canvas, int moveX,int moveY, int i)
{
if (i == 0)
{
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), moveX, moveY, null);
}
if (i == 1)
{
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), moveX, moveY, null);
}
if (i == 2)
{
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), moveX, moveY, null);
}
if (i == 3)
{
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), moveX, moveY, null);
}
}
protected void moveEm(Canvas canvas, int[]mMovePosX, int[] mMovePosY)
{
for (int i = 0; i < 4; i++)
{
}
}
protected void ScaleIt(Canvas canvas, int i)
{
mScale[i] = Bitmap.createScaledBitmap(mScale[i], (int) (width * 1.5), height, true);
mScale[i-1].recycle();
}
}
And here is the activity:
public class ScaleView extends Activity
{
Context mContext;
Scale mScale;
EditText positive_thought;
Button fire;
TextView pos;
private static Set<String> mPositiveWords;
private static Set<String> mNegativeWords;
int count;
private Pattern four_letter_words = Pattern.compile("not|cant|cnt|can't");
String inputLine;
private String[] inputTokens;
Button question;
Button skip;
public static boolean populatePositiveWords(Context context)
{
mNegativeWords = new HashSet<String>();
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(context.getAssets().open("negative_words.txt")));
String line = reader.readLine();
while (line != null)
{
mNegativeWords.add(line.toLowerCase(Locale.US));
line = reader.readLine();
}
reader.close();
}
catch (IOException exception)
{
return false;
}
return true;
//TODO list of negative words
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.getActionBar().hide();
mContext = this;
populatePositiveWords(mContext);
setContentView(R.layout.activity_scale);
mScale = (Scale) findViewById(R.id.anim_view);
mScale.setClickable(true);
positive_thought = (EditText) findViewById(R.id.thoughts);
fire = (Button) findViewById(R.id.scale_it);
skip = (Button) findViewById(R.id.skip);
question = (Button) findViewById(R.id.question);
InputFilter[] FilterArray = new InputFilter[1];
FilterArray[0] = new InputFilter.LengthFilter(60);
positive_thought.setFilters(FilterArray);
fire.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View view)
{
//if the button is clicked invalidate the ondraw method and pass in the text of the positive word
inputLine = positive_thought.getText().toString();
inputTokens = inputLine.split(" ");
if (inputLine.isEmpty())
{
Toast.makeText(mContext, "You have to write something!", Toast.LENGTH_SHORT).show();
return;
}
if (inputTokens.length < 3)
{
Toast.makeText(mContext, "At least three words are required.", Toast.LENGTH_SHORT).show();
return;
}
if (four_letter_words.matcher(inputLine).find() == true)
{
Toast.makeText(mContext, "Make an affirmative statement!", Toast.LENGTH_SHORT).show();
return;
}
boolean matchesToken = false;
for (int i = 0; i < inputTokens.length; i++)
{
String token = inputTokens[i];
if (mNegativeWords.contains(token.toLowerCase(Locale.US)))
{
matchesToken = true;
break;
}
}
if (matchesToken == true)
{
Toast.makeText(mContext, "Use positive words!", Toast.LENGTH_SHORT).show();
return;
}
else
{
InputMethodManager imm = (InputMethodManager)mContext.getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(positive_thought.getWindowToken(), 0);
pos = new TextView (mContext);
pos.layout(0, 0, mScale.width/3, mScale.height/4);
pos.setGravity(Gravity.CENTER);
pos.setTextSize(15);
pos.setTextColor(Color.RED);
pos.setTypeface(Typeface.DEFAULT_BOLD);
pos.setShadowLayer(5, 2, 2, Color.YELLOW);
pos.setText(positive_thought.getText().toString());
pos.setDrawingCacheEnabled(true);
pos.setBackgroundResource(R.drawable.whitecloud);
pos.setClickable(true);
mScale.mPositive.add(pos);
mScale.scale_it = true;
count++;
mScale.sStop = false;
mScale.tracker = count;
if (count == 4)
{
((RelativeLayout)question.getParent()).removeView(question);
((RelativeLayout)skip.getParent()).removeView(skip);
mScale.mPositive.get(0).setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
mScale.mCurrentXPos[0] = event.getX();
mScale.mCurrentYPos[0] = event.getY();
mScale.mDrag = true;
return true;
}
});
}
}
positive_thought.setText(null);
}
});
}
}
The reason your TextView cannot receive touch events is that the TextView is drawn on the canvas just as a bitmap, not as a View. An excerpt from your code shown below illustrates this.
protected void onDraw(Canvas canvs)
{
....
negative = new TextView(mContext);
...
canvas.drawBitmap(negative.getDrawingCache(), ...)
To deliver touch events to your TextView, your Scale class should extend not View but ViewGroup and the TextView needs to be added as a subview to Scale class by using ViewGroup.addView() or addViewInLayout(). It is not a simple task to implement a ViewGroup subclass. You may have to implement onInterceptTouchEvent(MotionEvent) depending on your needs.
Android's source code will be of help.
Is your CustomView also sets some TouchListner??
If yes then this might causing issue..Remove TouchListner from CustomView and see if it works..
I am creating a game which uses andendgine and here is my code:
Player stanley = new Player();
...
scene.registerUpdateHandler(new IUpdateHandler() {
public void onUpdate(float pSecondsElapsed) {
stanX = stanley.getX();
destX = x.getX();
if(destX < stanX){
if(hasMovedRight == 1){
stanley.stop();
hasMovedRight = 0;
}
else{
stanley.moveLeft();
hasMovedRight = 0
hasMovedLeft = 1;
}
}
if(destX > stanX){
if(hasMovedLeft == 1){
stanley.stop();
hasMovedLeft == 0;
}
else{
stanley.moveRight();
hasMovedLeft = 0;
hasMovedRight = 1;
}
}
}
}
what i want is to stop Player from walking whenever his position X is equal to the touched area X. The problem is it never stop from walking. Thanks!
Your if statements are missing an element where destX == stanX. and you should really use else if. See modified code below.
if(destX + 8 < stanX){
if(hasMovedRight == 1){
stanley.stop();
hasMovedRight = 0;
}
else{
stanley.moveLeft();
hasMovedRight = 0
hasMovedLeft = 1;
}
}
else if(destX - 8 > stanX){
if(hasMovedLeft == 1){
stanley.stop();
hasMovedLeft == 0;
}
else{
stanley.moveRight();
hasMovedLeft = 0;
hasMovedRight = 1;
}
}
else //makes stanley stop. (calls stop method), if at touched x.
{
stanley.stop();
hasMovedRight = 0;
hasMovedLeft = 0;
}
try this one
setOnSceneTouchListener(new IOnSceneTouchListener() {
#Override
public boolean onSceneTouchEvent(Scene scene, TouchEvent event) {
int touchX = (int) (event.getX() - (sCHARStanley.getWidth() / 2));
//so that your sprite will go to the touched part of the screen
}
I am creating softkeyboard for android 2.2 and higher. everything is fine but when i type really quick then some time my ACTION_DOWN method is not calling. Actual flow of called method should look like
1) motionEvent.ACTION_DOWN
2) OnPress()
3) motionEvent.ACTION_UP
4) OnRelease() and repeat same order for next word.
if i type at normal speed then it works fine but if i type fast then above order of method execution looks like
1) motionEvent.ACTION_DOWN
2) OnPress()
3) OnRelease()
4) motionEvent.ACTION_UP and for next word OnPress and OnRelease() methods are being called.
any suggestions?
Edit
My LatinKeyboardView class that contains MotionActionEvents
enter code here #Override
public boolean onTouchEvent(MotionEvent me) {
// Moved next line and added lines to help solve reentrant problem.
int action = me.getAction();
// next 2 lines required for multitouch Andr 2+
int act = action & MotionEvent.ACTION_MASK;
final int ptrIndex = (act & MotionEvent.ACTION_POINTER_ID_MASK) //Renamed to ACTION_POINTER_INDEX_MASK in later Andro versions
>> MotionEvent.ACTION_POINTER_ID_SHIFT;//Renamed to ACTION_POINTER_INDEX_SHIFT in later Andro versions
// currentX = me.getX();
// currentY = me.getY();
calcMinSlide();
// int act = me.getAction();
if (act == android.view.MotionEvent.ACTION_DOWN) {
Log.v(tag, "ANGLE_ACTION_DOWN : ");
if (pw != null) {
pw.dismiss();
pw = null;
}
lastDirection = direction = 0;
touchDownPoint.set(me.getX(), me.getY());
// Will added next two lines
touchDragPoint.set(me.getX(), me.getY());
thresholdPoint.set(me.getX(), me.getY());
// Will6 added to improve accuracy
thresholdPoint1_5 = false;
// Will7 added next 4 for Andro 2+
currentX = me.getX();
currentY = me.getY();
// Save the ID of this first pointer (touch) down
currentPointerID = me.getPointerId(0);
nextPointerID = INVALID_POINTER_ID;
previousDownTime = me.getEventTime();
me.setLocation(touchDownPoint.x, touchDownPoint.y);
// start timer on touch down
startTimer(me, 300); // 150); Will7 changed this and removed method: checkLongPress
} else if (act == android.view.MotionEvent.ACTION_UP
|| act == android.view.MotionEvent.ACTION_MOVE) {
Log.v(tag, "ANGLE_ACTION_UP : ");
//touchdragPoint and previoustouchPoint for calculating velocity
PointF previousTouchPoint = new PointF(touchDragPoint.x,touchDragPoint.y);
//Will7 added next if for Andro 2+: Find the index of the active pointer and fetch its position
if (act == android.view.MotionEvent.ACTION_MOVE && me.getPointerId(ptrIndex) != currentPointerID) {
//Log.v(tag, "Cancel ATION_MOVE!! ID: "+me.getPointerId(ptrIndex));
return super.onTouchEvent(me);
}
touchDragPoint.set(me.getX(), me.getY());
dy = me.getY() - touchDownPoint.y;
dx = me.getX() - touchDownPoint.x;
// added for Andro 2+
currentX = touchDragPoint.x;
currentY = touchDragPoint.y;
//calculate time interval from down time to current time
long timeInterval = me.getEventTime() - previousDownTime;
previousDownTime = me.getEventTime();
velocityThresDir = VELOCITY_THRESHOLD;
float touchVelocity = Math.abs(distanceBetweenPoints(touchDragPoint, previousTouchPoint) / timeInterval);
if (distanceFromCenter(dx,dy) > minSlide) {
// Log.v(tag, "direction to detect angle....after... dx..."+dx+" dy "+dy);
//Log.v(tag, "ANGLE angle.... after..."+distanceFromCenter(dx,dy)+" slide distance "+ minSlide);
/* cancel the timer*/
if (cDownTimer != null) {
cDownTimer.cancel();
cDownTimer = null;
}
/* coding for calculating velocity threshold*/
float angleThreshold = 0.0f;
if ((thresholdPoint.x == touchDownPoint.x) && (thresholdPoint.y == touchDownPoint.y)){
thresholdPoint.set(touchDragPoint.x, touchDragPoint.y);
}
else {
//Will6 - added next if to improve accuracy
if ((distanceFromCenter(dx,dy) > (minSlide * 1.5)) && !thresholdPoint1_5){
thresholdPoint.set(me.getX(),me.getY());
thresholdPoint1_5 = true;
}
float angleP1= calcAngle(touchDownPoint, thresholdPoint);
float angleP2= calcAngle(previousTouchPoint, touchDragPoint);
angleThreshold = Math.abs(angleP1 - angleP2);
if (angleThreshold > Math.PI) angleThreshold = (float) (2.0 * Math.PI) - angleThreshold;
}
// velocityThresDir = (float) Math.abs((Math.cos(angleThreshold) * touchVelocity*1000));
velocityThresDir = (float) (Math.cos(angleThreshold) * touchVelocity*1000);
//end of calculation for velocity threshold
double angle = newM(touchDownPoint.x, touchDownPoint.y, touchDragPoint.x, touchDragPoint.y);
// Log.v(tag, "ANGLE_FIRST_X "+touchDownPoint.x+"FIRST_Y "+touchDownPoint.y);
// Log.v(tag, "ANGLE_SECOND_X "+touchDragPoint.x+"SECOND_Y "+touchDragPoint.y);
// Log.v(tag, "ANGLE_FIRST"+angle);
if ((touchDownPoint.x != thresholdPoint.x) || (touchDownPoint.y != thresholdPoint.y)) {
double angleThresh = newM(touchDownPoint.x, touchDownPoint.y, thresholdPoint.x, thresholdPoint.y);
double angleBetween = Math.abs(angle - angleThresh);
if(angleBetween < 45 || angleBetween > 315){
if(angleBetween > 315) {
if (angle < angleThresh) {
angle += 360;
}
else if (angle > angleThresh) {
angleThresh += 360;
}
angle = Math.abs((angle - angleThresh)%360) / 2.0;
// Log.v(tag, "ANGLE_SECOND"+angle);
}
else {
angle = (angle + angleThresh * 1.0) / 2.0;
// Log.v(tag, "ANGLE_THIRD"+angle);
}
}
}
if (angle > 337.5){
direction = 3;
}else if (angle > 292.5){
direction = 5;
}else if (angle > 247.5){
direction = 4;
}else if (angle > 202.5){
direction = 6;
}else if (angle > 157.5){
direction = 1;
}else if (angle > 112.5){
direction = 7;
}else if (angle > 67.5){
direction = 2;
}else if (angle > 22.5){
direction = 8;
}else{
direction = 3;
}
/* start timer if velocity is below velocity threshold*/
if ((velocityThresDir < VELOCITY_THRESHOLD) &&
(act == android.view.MotionEvent.ACTION_MOVE) && (cDownTimer == null) &&
(pw == null)) { //"&& cDownTimer" can be removed I think
/* start timer with motionEvent and time in ms as a parameter */
// added next two lines
callOnLongPress(me);
startTimerShowPopup(me,100);//Will changed from 150
}
} else {
direction = 0;
}
if (act == android.view.MotionEvent.ACTION_MOVE) {
return true;
} else if (act == android.view.MotionEvent.ACTION_UP) {
if (cDownTimer != null) {
cDownTimer.cancel();
cDownTimer = null;
}
if (pw != null)
pw.dismiss();
if (longPressedKey) {
SoftKeyboard.mComposing
.append(charset[mappedKey][direction]);
popUpTextEntryScheme = true;
}
longPressedKey = false;
currentPointerID = INVALID_POINTER_ID;
}
}
else if (act == android.view.MotionEvent.ACTION_POINTER_DOWN) {
// if (me.getPointerCount() > 1) { //Should always be true, I think
nextPointerID = me.getPointerId(ptrIndex);
nextTouchDownPoint.set(me.getX(ptrIndex),me.getY(ptrIndex));
// }
}
else if (act == android.view.MotionEvent.ACTION_CANCEL) {
currentPointerID = INVALID_POINTER_ID;
nextPointerID = INVALID_POINTER_ID;
}
else if (act == android.view.MotionEvent.ACTION_POINTER_UP) {
// Extract the index of the pointer that left the touch sensor
final int pointerId = me.getPointerId(ptrIndex);
if (pointerId == currentPointerID) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = ptrIndex == 0 ? 1 : 0;
currentPointerID = nextPointerID;//(0);
touchDownPoint.set(nextTouchDownPoint.x,nextTouchDownPoint.y);
if (cDownTimer != null) {
cDownTimer.cancel();
cDownTimer = null;
}
if (pw != null) {
pw.dismiss();
pw = null;
}
if (longPressedKey) {
SoftKeyboard.mComposing
.append(charset[mappedKey][direction]);
popUpTextEntryScheme = true;
}
longPressedKey = false;
lastDirection = direction = 0; // keysAtOnce=0;
touchDragPoint.set(me.getX(newPointerIndex),me.getY(newPointerIndex));
thresholdPoint.set(nextTouchDownPoint.x,nextTouchDownPoint.y);
//added to improve accuracy
thresholdPoint1_5 = false;
// added next 3 for Andro 2+
currentX = touchDragPoint.x;
currentY = touchDragPoint.y;
// Save the ID of this first pointer (touch) down
previousDownTime = me.getEventTime();
me.setLocation(touchDownPoint.x, touchDownPoint.y);
//start timer on touch down
startTimer(me,300); //150); Will7 changed this and removed method: checkLongPress
} else { //Second pointer up before first. (Not handling 3 or more pointers yet!)
// nextPointerID = INVALID_POINTER_ID;
}
} //else
return super.onTouchEvent(me); // after we return here the service will get notified, etc
// return true;
}
and my SoftKeyboard class..
public void onPress(int primaryCode) {
Log.v("SoftKeyboard", "ANGLE_ACTION_ON_PRESS : ");
// added next section for repeating backspace
if (RepeatBSTimer != null) {
RepeatBSTimer.cancel();
RepeatBSTimer = null;
}
if (mp != null) { // /Will7 moved this from just above keystroke
// statement
mp.release();
mp = null;
}
// added for Andro 2+ multitouch
if (primaryCode == pressedCode
&& LatinKeyboardView.nextPointerID != LatinKeyboardView.INVALID_POINTER_ID) {
// I need to look up the real primaryCode here. (Not sure how!)
// Android gives wrong values when touches overlap.
wrongPrimaryCode = true;
return;
} else
wrongPrimaryCode = false;
pressedCode = primaryCode;
// added next section for repeating backspace
if (primaryCode == Keyboard.KEYCODE_DELETE) {
RepeatBSTimer = new CountDownTimer(1500000, 75) {
#Override
public void onTick(long millisUntilFinished) {
int primaryCode2;
if (LatinKeyboardView.longPressedKey
|| (1500000 - millisUntilFinished > 500)) {
primaryCode2 = getCharFromKey(pressedCode,
LatinKeyboardView.direction, mInputView
.getKeyboard());
if (primaryCode2 == Keyboard.KEYCODE_DELETE) {
repeating = true;
handleBackspace();
} else if (primaryCode2 == KEYCODE_DELETEWORD
&& (millisUntilFinished % 150) < 75) {
repeating = true;
deleteLastWord();
}
}
}
#Override
public void onFinish() {
}
};
RepeatBSTimer.start();
}
// added section for repeating backspace
Uri uri = Uri.parse("android.resource://" + getPackageName() + "/"
+ R.raw.keystroke);// Play Key Click
try {
mp = new MediaPlayer();
mp.setDataSource(this, uri);
mp.prepare();
mp.start();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void onRelease(int primaryCode) {
// Will7 added next line if for Andro 2+ multitouch
if (wrongPrimaryCode
&& LatinKeyboardView.nextPointerID != LatinKeyboardView.INVALID_POINTER_ID) {
return;
}
// else pressedCode = primaryCode;
// added next sections for repeating backspace
primaryCode = getCharFromKey(pressedCode, LatinKeyboardView.direction,mInputView.getKeyboard());
if (primaryCode == Keyboard.KEYCODE_DELETE && !repeating)
handleBackspace();
if (primaryCode == KEYCODE_DELETEWORD && !repeating)
deleteLastWord();
repeating = false;
if (RepeatBSTimer != null) {
RepeatBSTimer.cancel();
RepeatBSTimer = null;
}
// moved all the rest of this method from onKey()
int[] keyCodes;
// added this var for Andro 2+ multitouch
keyCodes = keyCodesSave;
commitTyped(getCurrentInputConnection());
if (isWordSeparator(primaryCode) && (char) primaryCode != '.'
&& (char) primaryCode != '!' && (char) primaryCode != '?') {
// Handle separator
if (mComposing.length() > 0) {
commitTyped(getCurrentInputConnection());
}
sendKey(primaryCode);
updateShiftKeyState(getCurrentInputEditorInfo());
} else if (primaryCode == Keyboard.KEYCODE_DELETE) {
// commented out next line for repeating backspace
// handleBackspace();
} else if (primaryCode == Keyboard.KEYCODE_SHIFT || primaryCode == -1) {
handleShift();
} else if (primaryCode == Keyboard.KEYCODE_CANCEL) {
handleClose();
return;
} else if (primaryCode == KEYCODE_ESCAPE) {
// Do nothing on Escape key
} else if (primaryCode == LatinKeyboardView.KEYCODE_OPTIONS) {
// Show a menu or something
} else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE
&& mInputView != null) {
Keyboard current = mInputView.getKeyboard();
if (current == mSymbolsKeyboard
|| current == mSymbolsShiftedKeyboard) {
getCurrentInputConnection().finishComposingText();
current = mQwertyKeyboard;
} else {
getCurrentInputConnection().finishComposingText();
current = mSymbolsKeyboard;
}
mInputView.setKeyboard(current);
if (current == mSymbolsKeyboard) {
current.setShifted(false);
}
} else if (primaryCode == KEYCODE_CAPSLOCK)// handle caps lock
{
if (mInputView.getKeyboard() == mQwertyKeyboard
|| mInputView.getKeyboard() == mSymbolsKeyboard) {
mInputView.setKeyboard(mQwertyKeyboardUpperCase);
mQwertyKeyboardUpperCase.setShifted(true);
mCapsLock = true;
} else {
mQwertyKeyboard.setShifted(false);
mInputView.setKeyboard(mQwertyKeyboard);
mCapsLock = false;
}
} else if (primaryCode == KEYCODE_DELETEWORD) {
// commented out next line for repeating backspace
// deleteLastWord();
} else if (primaryCode == KEYCODE_FULL_STOP_AND_SPACE) {
// added next line
backspaceIfSpaceLeft();
getCurrentInputConnection().finishComposingText();
handleCharacter((int) '.', keyCodes);
handleCharacter((int) ' ', keyCodes);
handleShift();
}
// added next 5 KEYCODES
else if (primaryCode == KEYCODE_EXCLAMATION) {
// added next line
backspaceIfSpaceLeft();
getCurrentInputConnection().finishComposingText();
handleCharacter((int) '!', keyCodes);
handleCharacter((int) ' ', keyCodes);
handleShift();
} else if (primaryCode == KEYCODE_QUESTION_MARK) {
// added next line
backspaceIfSpaceLeft();
getCurrentInputConnection().finishComposingText();
handleCharacter((int) '?', keyCodes);
handleCharacter((int) ' ', keyCodes);
handleShift();
} else if (primaryCode == KEYCODE_COMMA) {
// added next line
backspaceIfSpaceLeft();
getCurrentInputConnection().finishComposingText();
handleCharacter((int) ',', keyCodes);
handleCharacter((int) ' ', keyCodes);
} else if (primaryCode == KEYCODE_COLON) {
// added next line
backspaceIfSpaceLeft();
getCurrentInputConnection().finishComposingText();
handleCharacter((int) ':', keyCodes);
handleCharacter((int) ' ', keyCodes);
} else if (primaryCode == KEYCODE_SEMICOLON) {
// added next line
backspaceIfSpaceLeft();
getCurrentInputConnection().finishComposingText();
handleCharacter((int) ';', keyCodes);
handleCharacter((int) ' ', keyCodes);
} else {
handleCharacter(primaryCode, keyCodes);
}
}
Thanks..
This is a very long onTouchEvent handler, I suggest breaking it up into more logical steps. I also have had the issue of seemingly "out-of-order" events when trying to handle the touchscreen.
I found that I wasn't handling the events per pointer ID correctly. I'd check to make sure you are handling multiple pointers as expected. The device I test with (N1) only supports two pointers, but others support many more, and those should be accounted for.
For handling touchscreen "soft-buttons" as an onTouchEvent event, I've found it useful to create a state machine class. Use the MotionEvent parameters as input events to the state machine, and cause state transitions to trigger your wanted events. An explicit, state-driven approach will give you the expected results you are looking for.