I have a problem with implementing touch events on GLSurfaceView. Views size is 1280x696, because of android (tablet) status bar at bottom with soft keys, time etc.., (screen resolution is 1280x800), but OnTouchListener is receiving touch events with coords [646.0,739.0], and thus my gluunproject method fails to return correct values
is there any way to return events that respect these boundaries? or how should I recalculate the position?
In general to transition between such coordinate systems: If you transition from system A to B and you have points
AOrigin (left upper corner of your receiver view)
AEnd (right bottom corner of your receiver view (origin + size))
BOrigin (left upper corner of your GL view)
BEnd (right bottom corner of your GL view (origin + size))
where AOrigin and BOrigin represent the same location in view and same goes for AEnd and BEnd
then for point P in the receiver view:
X = B.Origin.x + ((P.x - AOrigin.x)/(AEnd.x - AOrigin.x)) * (BEnd.x - B.Origin.x)
Y = B.Origin.y + ((P.y - AOrigin.y)/(AEnd.y - AOrigin.y)) * (BEnd.y - B.Origin.y)
For your case (I'm not sure because of lack of information) AOrigin is at (0,0), AEnd is at (646, 739), BOrigin is at (0,0) and BEnd is at (1280, 800):
X = P.x/646 * 1280
Y = P.y/739 * 800
You can also use this to transition to/from "GL" coordinates. A common case is having a view with upper left corner at (0, 0) and lower bottom at (1280, 800) and your "GL" coordinates are from (-1, 1) to (1, -1):
X = -1 + (P.x/1280)*2
Y = 1 + (P.y/800)*(-2)
Also note that you may use any 2 pairs of points that represent same location on screen as long as (origin-end).x != 0 AND (origin-end).y != 0
Related
I'm putting together a demo of indoor positioning technology for an Android device. The problem is that I am getting quadrant 3 positions from the system I'm using, where 0,0 origin is in the upper right. The map is placed in an imageview that has the origin in the upper left (quadrant 4).
Naturally, when I try to put another image on top to move around according to the position I am getting, it is backwards on the X-axis. What is the best way to display the right coordinates? Can I transform the points as I get them, or is there a way to somehow flip the imageview so that the origin is in the upper right?
You will have to transform the coordinates yourself. It is not complex - mapping the values from one to the other, in general. If the image has a width of "Wo" and you have Vo (View Origin) and Mo (Map Origin) then an x coordinate from the Map is Mx and is transformed as Vx = Mx + Wo. (Mx are map x coordinates that have negative values, no greater than Wo and no less than 0). To transform from the view to the map, do the opposite: Mx = Vx - Wo. (The Vx x-coordinates will not have values less than 0, and at its greatest width, it should result in a "0" on the map.)
That is not CPU intensive, so it should be fast.
my app contains an object moving on a surfaceview. I am able to move it around via accelerometer.
Here's the movement code of the player object:
if(x + mx*speed > 0 && x + mx*speed < GameView.WIDTH) {
x += mx*speed;
}
if(y+ my*speed > 0 && y+ my*speed < GameView.HEIGHT) {
y+=my*speed;
}
x and y are the player's coordinates
mx is the value the player gets from the accelerometer, for example: when tilting to the left, mx is -2, when tilting more, mx is -4, -5, -6 etc. --> my is the same for the y-axis
the speed is a variable to modify and play around when i want to have a faster movement.
as you can see I tried to limit the movement to only move when the player is inside of the view.
Now my problem is: when tilting the device intensively to the right, mx turns to something like 6. speed is set to 5. This means, when the player's position + 6 * 5 is bigger than the game view it should not move any more. But this results in the player stopping pixels in front of the right side of the view... when tilting lightly to the right, the object stops perfectly at the border of the view...
Now how should i change the code to achieve an object that stops it's movement perfectly at borders of the screen?
On this picture you can see the circle not stopping quite at the bottom, as there are some pixels between the circle and the bottom border. when going slightly back with the accelerometer, the circle aligns itself to the bottom of the screen:
But now, i can only reach the screen borders when moving slowly, which means with a low mx or my.
the screenshots you can see the mY values. On the first picture my = ca. 8 and on the second ca. 6.
Any ideas?
Thanks in advance
Try to instead cap the value to the border like so
x = Math.max(Math.min(x + mx*speed, GameView.WIDTH), 0.0f));
y = Math.max(Math.min(y + my*speed, GameView.HEIGHT, 0.0f));
I'm trying to make a custom view with clickeable areas for my app. Those areas are relative to the image pixel coords that will fill that view. I've placed those images at drawable-nodpi to avoid system scaling.
My custom view takes one of those images, resizes it keeping the aspect ratio to fit its parent and then resizes the view to the size of the resulting image. So at this point I have a view that maintains the ratio of the source, so the resulting view click (onTouch event.getX and event.getY) coordinates are relative to the original image pixel coords.
From the other hand I have all the coordinates of the shapes that define the clickeable areas in a xml file wich I load when my activity starts. Those areas are defined by a type: circle or rect.
circle: center x-y and radius in px according to the original image
rect: center x-y, width and height in px according to the original image
Now I need to detect if my touch x-y is inside of the coordinates of any of those areas, but keeping in mind the scaling that my original image suffered.
How could I detect the "collitions" between my touch coordinates and the clickeable areas coords? I mean how do I calculate that even without resizing my original image?
I have made a View like this myself,
i added objects containing an image and x/y coords.
Now u need to have a list of those Objects, and in case you get an ontouchEvent, you iterate over that list do something like objectHit()
public boolean objectHit(int x, int y){
int touchdistance = Math.sqrt((double)(this.getX()-x)*(double)(this.getX()-x)) + ((double)(this.getY()-y)*(double)(this.getY()-y));
return touchdistance <= this.getTouchableArea();
}
And you implement getTouchableArea for the Object basicly the same way.
public double getTouchAbleArea() {
return Math.sqrt(Math.pow(getBitmap().getHeight(),2)+Math.pow(getBitmap().getWidth(),2))/2;
}
So what you are doing with this code is, you determine if the touch is within the size of the Image representing the object.
This is what I ended up doing
for(i=0;i<level.getDiffs();i++){
DifferencesData diff = level.getDifference(i);
if(!diff.getFinded()){
x = diff.getX();
y = diff.getY();
if(diff.getType() == 0){
double d = Math.sqrt(Math.pow(x - event.getX(),2) + Math.pow(y - event.getY(),2));
if(d <= diff.getRadius()){
hit = true;
break;
}
}else{
double dx = Math.sqrt(Math.pow(x - event.getX(),2));
double dy = Math.sqrt(Math.pow(y - event.getY(),2));
if(dx <= (diff.getWidth() / 2) && dy <= (diff.getHeight() / 2)){
hit = true;
break;
}
}
}
}
First I scaled the original coordinates by the same scale that my image was scaled by. Then, inside an OnTouchListener I calculated the distance of my touch to the ratio of the circle, or to the half width and half height of my rectangles.
Thank you Daniel for your help!
I am trying to make a small game where you can fling a coin on the screen. while i was searching for that kind of animation i found this page
http://mobile.tutsplus.com/tutorials/android/android-gesture/
I managed to customise the events according to my aim, but i couldn't manage to set boundaries on the screen so that the coin(bitmap) will bounce back when it comes to the edges.
I tried several calculations but in the end the coin moves weirdly based on the contact points on the edges.
Can someone help me about it, according to the working code on the website
Below is a sample code from my pong game. Each object has position (x,y) and its speed. Movement is speed applied to position. One extra info is that the screen coordinate system starts from the left top corner. Y axis go down but increasing. Since screen coordinates start from 0, the boundaries become screen.width -1 and screen.height -1
#Override
public void onDraw(Canvas c){
p.setStyle(Style.FILL_AND_STROKE);
p.setColor(0xff00ff00);
// If ball's current x location plus the ball diameter is greater than screen width - 1, then make speed on x axis negative. Because you hit the right side and will bounce back to left.
if((Px+ballDiameter) > width - 1){
Vx = -Vx;
}
// If ball's current y location plus the ball diameter is greater than screen height -1, then make speed on y axis negative. Because you hit the bottom and you will go back up.
if((Py + ballDiameter) > height - 1){
Vy = -Vy;
}
// If current x location of the ball minus ball diameter is less than 1, then make the speed on x axis nagative. Because you hit to the left side of the screen and the ball would bounce back to the right side
if((Px - ballDiameter) < 1){
Vx = -Vx;
}
// If current y location of the ball minus ball diameter is less than 1, then make the speed on y axis negative. Because the ball hit the top of the screen and it should go down.
if((Py - ballDiameter ) <1){
Dy = 1;
Vy = -Vy;
}
Px += Vx; // increase x position by speed
Py += Vy; // increase y position by speed
c.drawCircle(Px, Py, ballDiameter, p);
invalidate();
}
I want to achieve a tilt effect when a button is clicked, on Android OS.
Tilt Effect: Not the whole button will be seen as pressed. Only the part that touch event occured should seem to be pressed.
Is this easily possible on Android?
A simple way would be to use canvas draws to draw 4 sided shapes.
Consider each 4 corners. The "untouched" rectangle would be full size the touched rectangle would be smaller.
You just need to draw your four sided shape using a point you calculate for each part of the rectangle. You can get the touch position, then figure out how much "weight" to give each point.
to calculate each corner, you need to figure out how much "weight" to give the touched coordinate, and how much "weight" to give the untouched coordinate. If you touch the top left corner, that corner would use 100% of the touched coordinate, and the other three corners would all use the untouched coordinate.
If you touched the top middle, you would get a shape like this:
We can calculate the corners for any touch spot, by calculating how far from the corner your touch is
float untouchedXWeight1 = Math.abs(xt - x1)/width;
//maximum of 1, minimum of 0
float untouchedYWeight1 = Math.abs(yt - y1)/height;
float untouchedWeight1 = (untouchedXWeight1 + untouchedYWeight1)/2;
//also maximum of 1, minimum of 0
float touchedWeight1 = 1 - untouchedWeight1;
so with those weights, you can calculate your x and y positions for that corner:
x1 = xUntouched1 * untouchedWeight + xTouched1 * touchedWeight1;
y1 = yUntouched1 * untouchedWeight + yTouched1 * touchedWeight1;
Then do similarly for the other 3 corners.
I've created a first draft here : https://github.com/flavienlaurent/TiltEffect
In a second step, I will make it usable with Button etc.
Unfortunatly, I didn't use the very good (but too mathematical for me) answer of HalR