I have made an application that enables to use android phone as touchpad.
It is working correctly as it should.
But only thing bothering me is that there is LAG. mouse on laptop sometimes lags i.e not in complete sync with touch on android.
The only reason i could think of lag is the logic used in calculating the next coordinates.
Here is the code for Android Application that sends coordinates on touch event :(t is TextView)
t.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN){
startX = event.getX();
startY = event.getY();
}
if(event.getAction() == MotionEvent.ACTION_MOVE)
{
out.println("X:"+(event.getX()-startX)+"Y:"+(event.getY()-startY));
startX=event.getX();
startY=event.getY();
}
return true;
}
});
Logic i am using is that i am sending difference of the coordinates.
On serverside , basic thing happening is ('in' is BufferedReader ):
PointerInfo a = MouseInfo.getPointerInfo();
Point b = a.getLocation();
currX = (int)b.getX();
currY=(int)b.getY();
while ((inputLine = in.readLine()) != null) {
if(inputLine.equals("LeftClick"))
{
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
}
else if(inputLine.equals("RightClick")){
robot.mousePress(InputEvent.BUTTON3_MASK);
robot.mouseRelease(InputEvent.BUTTON3_MASK);
}
else{
outputLine = kkp.processInput(inputLine);
//To break the string into X cordi and Y cordi.
yloc = inputLine.indexOf("Y");
float xcord = Float.parseFloat(inputLine.substring(2,yloc));
float ycord = Float.parseFloat(inputLine.substring(yloc+2));
robot.mouseMove(currX+Math.round(xcord),currY+Math.round(ycord));
currX+=Math.round(xcord);
currY+=Math.round(ycord);
}
}
Is the delay normal like Can't be improved . or can be improved by changing the calculations in above code. and PS: i am not using UDP.
Related
How to show a response while gesture input is in progress?
I'm using swipe down gesture to reload my WebView.
Using this for gesture detection:How to detect swipe direction between left/right and up/down
Problem
SimpleGestureListener captures the result of user input only. It cannot be used to show a response, e.g. animation, while the user is performing a gesture.
Imperfect inelegant solution:
flaw: Shows animation independent of SimpleOnGestureListener; a response to user gesture input is displayed and gesture input may still fail or vice versa.
private volatile float userTouchY = -1;
// translating WebView every onTouch event call is inefficient.
// only translate when translateYBy value is greater than a threshold.
private float translateYBy = 0;
/**
* Shift webView without animation.
* #param num
*/
private void __shiftWebViewDownBy(int num){
float current = webView.getY();
if(current >= webviewTranslationLimit) return;
current += num;
if(current> webviewTranslationLimit) current = webviewTranslationLimit;
webView.setY(current);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
//Skip everything unless at the content top.
if(webView.getScrollY() > 0) return false;
int action = event.getAction();
if(action == MotionEvent.ACTION_MOVE){
float y = event.getY();
float dif = y - userTouchY;
if(dif < webviewTranslationLimit/10){
//dif less than screenHeight*1/40, ignore input
}else if(dif < -(webviewTranslationLimit/5)){
//swipe up
userTouchY = -1;//not swipe down cancelling
__shiftWebViewTopTo(0);
}else if(userTouchY < y) {
//swipe down
translateYBy += dif;
if(userTouchY == -1){
//userTouchY at the initial value, ignore for this once.
userTouchY = y;
}else{
userTouchY = y;
if(translateYBy > 5 ){
__shiftWebViewDownBy((int)translateYBy);
translateYBy = 0;
}
}
}
}else{
Log.d(TAG,"action not move:" +MotionEvent.actionToString(action));
// Webview shift down should only occur while moving
// Once finger is off,cancel
__shiftWebViewTopTo(0);
userTouchY = -1;
}
boolean result = gestureDetector.onTouchEvent(event);
return result;
}
Writing a GestureListener of a sort from scratch obviously solves the problem and I can simply use Toast to message the user for a failed gesture input, but there ought to be an easier, more readable solution.
I am developing an android application where I am creating dynamic Images arrow on relative layout. The images are created on a x,y coordinated of the click area of relative layout. Below is the code the I am using for it.
presciptionScreenArrowImg.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (canSelectMedianStatus == 2) {
if (event == simulationEvent)
return false;
int action = event.getAction();
int x = (int) event.getX();
int y = (int) event.getY();
Log.e("onTouchListener", "User touch at X:" + x + " Y:" + y);
pointerArrow = new ImageView(getApplication());
pointerArrow.setImageResource(R.drawable.pointer);
pointerArrow.setId(imageArrayTag);
imageArrayTag++;
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(40, 40);
params.topMargin = y;
params.leftMargin = x;
pointerArrow.setLayoutParams(params);
presciptionScreenArrowImg.addView(pointerArrow);
long length = 0;
if (action == MotionEvent.ACTION_DOWN) {
// click(v, x, y);
}
}
return false;
}
});
Now, I need is there on button click the last Image drawn should remove first. Basically I need an undo functionality to remove Images as LIFO structure.
let consider presciptionScreenArrowImg is your main layout which contains your all views so for removing
int index=presciptionScreenArrowImg.getChildCount();
if(index>0)
presciptionScreenArrowImg.removeViewAt(index-1);
from above get count of child and remove last view if you have any problem let me know
Store the views in a Queue, and when you add a new view check if the queue is full. If it is, pop a view from the queue, and call presciptionScreenArrowImg.remove(poppedView);
We have puzzle game Fruit Dating that is some time already out. Now we got report from one of our players that he can not touch any item in menu. We sent him special version with onscreen debugging. We focused on touches and he returned us this result:
There is every touch event intercepted. I split set of touch events for every single "game touch" in the picure with red lines on the left. Every game touch event is like this: down - (one or more drag) - up. What is strange is that before there is touch up there is always big jump in touch coordinates with touch dragged event.
I think that most of the drag events is just bouncing but there is always at least one that jumps coordinates to lower left corner. Following up event is then with these incorrect coordinates. As we are checking whether the player is touching up in the same area (see area parameter) as he began when touching down then there is never any match and player has feeling that the game is stuck.
The player that reported error has THL W200 phone. We previously tested on lot of different physical devices but never encountered this problem...
Does anyone have some idea why there is motion event (drag) with such a strange coordinates? Did any of you encountered it?
Our game is JNI with thin Java layer. Motionevents are sent to c++ from view like this:
#Override
public boolean onTouchEvent(final MotionEvent aEvent)
{
final int action = aEvent.getAction();
queueEvent(new Runnable()
{
int motionEvent = -1;
public void run()
{
if (action == MotionEvent.ACTION_DOWN)
{
motionEvent = ANDROID_TOUCH_ACTION_DOWN;
}
else if (action == MotionEvent.ACTION_UP)
{
motionEvent = ANDROID_TOUCH_ACTION_UP;
}
else if (action == MotionEvent.ACTION_MOVE)
{
motionEvent = ANDROID_TOUCH_ACTION_MOVE;
}
SBCEngine.engine_on_touch((int) aEvent.getX(), (int) aEvent.getY(), motionEvent);
}
});
return true;
}
Finally found the solution, so if anyone is interested...
The above code is not safe. Before the event is processed the referenced event object may change. The code was taken from book on porting Doom and Quake to Android and you may found similar code at web. It worked on all tested devices until yesterday. It failed on THL W200 device.
I changed the code to this:
#Override
public boolean onTouchEvent(final MotionEvent aEvent)
{
// get masked (not specific to a pointer) action
int maskedAction = aEvent.getActionMasked();
switch (maskedAction)
{
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
{
// get pointer index from the event object
int pointerIndex = aEvent.getActionIndex();
// get pointer ID
int pointerId = aEvent.getPointerId(pointerIndex);
//Log.d("POINTER", "pointer down: ID = " + pointerId + " x=" + aEvent.getX(pointerIndex) + ", y = " + aEvent.getY(pointerIndex));
queueEvent(new MotionEventRunnable(pointerId, maskedAction,
(int) aEvent.getX(pointerIndex),
(int) aEvent.getY(pointerIndex)));
break;
}
case MotionEvent.ACTION_MOVE:
{
// a pointer was moved
int size = aEvent.getPointerCount();
for (int i = 0; i < size; i++)
{
// Get the pointer ID and index
int pointerId = aEvent.getPointerId(i);
int pointerIndex = aEvent.findPointerIndex(pointerId);
//Log.d("POINTER", "pointer move: ID = " + pointerId + " x=" + aEvent.getX(pointerIndex) + ", y = " + aEvent.getY(pointerIndex));
queueEvent(new MotionEventRunnable(pointerId, maskedAction,
(int) aEvent.getX(pointerIndex),
(int) aEvent.getY(pointerIndex)));
}
break;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_CANCEL:
{
// get pointer index from the event object
int pointerIndex = aEvent.getActionIndex();
// get pointer ID
int pointerId = aEvent.getPointerId(pointerIndex);
//Log.d("POINTER", "pointer up: ID = " + pointerId + " x=" + aEvent.getX(pointerIndex) + ", y = " + aEvent.getY(pointerIndex));
queueEvent(new MotionEventRunnable(pointerId, maskedAction,
(int) aEvent.getX(pointerIndex),
(int) aEvent.getY(pointerIndex)));
break;
}
}
return true;
}
with MotionEventRunnable class like this:
class MotionEventRunnable implements Runnable
{
private int mPointerID;
private int mActionID;
private int mX, mY;
//-----------------------------------------------------
public MotionEventRunnable(int aPointerID, int aActionID, int aX, int aY)
{
mPointerID = aPointerID;
mActionID = aActionID;
mX = aX;
mY = aY;
}
//-----------------------------------------------------
#Override
public void run()
{
// send to native
SBCEngine.engine_on_touch(mPointerID, mX, mY, mActionID);
}
}
The code is more complex as it also handles multitouch but the point is that I cache all the required values: pointer id, action, x and y. It solved my problems.
I'm trying to make an Android puzzle game out of a picture.
What i've done 'till now is:
-i've cut the picture in how many parts i get from the EditText field;
-i've put the cut pictures in a gridview and got a puzzle table;
-i've also used the Collection.suffle(list) to suffle the images in the gridview;
Now, i am trying to implement the sliding effect on two images from gridview. So what i want to achieve is a sliding effect similar to CandyCrush app or this one http://www.youtube.com/watch?v=qUoP87fNB8w . I mean, i want to hold an image and drag it top so it should slide top. If i click the picture and slide bottom, it should change with the picture below it and so on...
Here is my code:
Reset = (Button) findViewById(R.id.BReset);
SplitNo = (EditText) findViewById(R.id.edSplitBy);
SplitBy = Integer.parseInt(SplitNo.getText().toString());
ImgNo = SplitBy * SplitBy;
puzzle = (GridView) findViewById(R.id.puzzle);
rootImg = (ImageView) findViewById(R.id.source_image);
splitImage(rootImg);
formPuzzle(smallimages);
Reset.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Reset.setText("Reset");
SplitNo.getEditableText().toString();
SplitBy = Integer.parseInt(SplitNo.getText().toString());
ImgNo = SplitBy * SplitBy;
Collections.shuffle(smallimages);
formPuzzle(smallimages);
}
});
And here is how i form the puzzle:
private void formPuzzle(ArrayList<PuzzleItem> smallimages) {
SMI = new SmallImageAdapter(this, smallimages);
puzzle.setAdapter(SMI);
puzzle.setNumColumns(SplitBy);
puzzle.setHorizontalSpacing(0);
puzzle.setVerticalSpacing(0); }
PuzzleItem.class:
public class PuzzleItem {
Bitmap puzzlepartImage;
int correctPosition;
public PuzzleItem(Bitmap d, int index) {
puzzlepartImage = d;
correctPosition = index;
}
I used this class just to remember the position of the pieces so i can check if the puzzle is finished...
So i'm only interested in how to implement the sliding motion by draging an item from gridview...
Thanks :)
EDIT: Should i use an OnTouchListener ?
Ok, I've managed to find the solution by myself :
private void formPuzzle(final ArrayList<PuzzleItem> smallimages) {
SMI = new SmallImageAdapter(this, smallimages);
puzzle.setAdapter(SMI);
puzzle.setNumColumns(SplitBy);
puzzle.setHorizontalSpacing(0);
puzzle.setVerticalSpacing(0);
puzzle.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
startX = event.getX();
startY = event.getY();
smallimage_Position = puzzle.pointToPosition((int) startX,
(int) startY);
return true;
}
case MotionEvent.ACTION_MOVE: {
endX = event.getX();
endY = event.getY();
Log.d("X", "..." +endX);
Log.d("Y", "..." +endY);
if(endX > startX + smallimage_Width/2 && (endY < startY - smallimage_Height/2 || endY < startY + smallimage_Height/2) ){
PuzzleItem p1 = SMI.smallimages.get(smallimage_Position);
PuzzleItem p2 = SMI.smallimages.get(smallimage_Position +1);
SMI.smallimages.set(smallimage_Position, p2);
SMI.smallimages.set(smallimage_Position +1, p1);
SMI.notifyDataSetChanged();
startX = endX*200;
startY = endY*200;
}
return true;
}
}
return true;
}
});
The slide is given by the MotionEvent.Action_MOVE and by calculating the pixels you can find out in what direction is the finger moving ... For example .. the if from my Action_Move case is recognising a swipe to the right ...
I hope this will help some of you guys ...
Another way to go about achieving slides in a slider puzzle game is to use a game engine. I recommend Cocos2D for Android, and theres a detailed tutorial on that here ...
http://denvycom.com/blog/step-by-step-guide-on-how-to-build-your-first-slider-puzzle-game-in-cocos2d-for-android-part-1/
I've been exploring into Nim Game on Android. The players are going to take objects from heaps. I use openGLES to draw the objects and heaps. Where I'm stuck is how to "take".
As the samples shown on official dev guide
, I can override onTouchEvent method in the class that extends GLSurfaceView for the interaction. However, how I could tell where the objects have been drawn? Or are there any objects at the coordinates where I touch?
Any ideas?
Thx in advance!
If I'm understanding your question correctly, it sounds like you want to do some simple collision detection to see if your touch point is inside one of the objects on the heap. You can do this with some basic math between the coordinates of the touch point and the center coordinates which you used to draw the object.
For instance, assuming your objects are rectangles, this would be the general idea:
boolean detectCollision(Object object, TouchPoint touch) {
return object.x - object.width/2 <= touch.x &&
object.x + object.width/2 >= touch.x &&
object.y - object.height/2 <= touch.y &&
object.y + object.height/2 >= touch y;
}
You could then iterate through all of the objects in your heaps and if this returns true for any of them, then you know your touchpoint is inside of that object and can proceed to call whatever you need to call on it.
Keep in mind that the touch coordinates the system gives you will be screen coordinates, so you have to take into account any discrepancies between the screen coordinate system and the coordinate system you defined with your view frustum.
public class Main extends Activity implements OnTouchListener {
public boolean onTouch(View v, MotionEvent event) {
synchronized (this) {
if (!_isPaused) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
_touchedX = event.getX();
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
float touchedX = event.getX();
float dx = Math.abs(_touchedX - touchedX);
_dxLowPassed = lowPass(dx, _dxLowPassed);
switch (_screenUsage) {
case HALF_SCREEN:
if (touchedX < _width / 2) {
if(touchedX < _touchedX) {
_zAngle = (2 * _dxLowPassed / _width) * TOUCH_SENSITIVITY * ANGLE_SPAN;
_zAngleLowPassed = lowPass(_zAngle, _zAngleLowPassed);
GLES20Renderer._zAngle = GLES20Renderer._zAngle + _zAngleLowPassed;
}
} else {
if( touchedX > _touchedX ) {
_zAngle = (2 * _dxLowPassed / _width) * TOUCH_SENSITIVITY * ANGLE_SPAN;
_zAngleLowPassed = lowPass(_zAngle, _zAngleLowPassed);
GLES20Renderer._zAngle = GLES20Renderer._zAngle - _zAngleLowPassed;
}
}
Log.d("TOUCH", new Float(_zAngleLowPassed).toString());
break;