I have stone sprite class in which I have defined touch, drag and throw actions. My stone sprite move well when I touch and drag it around screen. My expectation is sprite should move only within limited circular area (visible/invisible).
This is my code below
#Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float pTouchAreaLocalY)
{
if (pSceneTouchEvent.isActionMove() || pSceneTouchEvent.isActionDown() || pSceneTouchEvent.isActionOutside())
{
this.setX(pSceneTouchEvent.getX() - this.getWidth() / 2);
this.setY(pSceneTouchEvent.getY() - this.getHeight() / 2);
}
else if (pSceneTouchEvent.isActionUp())
{
mPhysicsHandler.setVelocityX((originX - getX()) * 5);
mPhysicsHandler.setVelocityY((originY - getY()) * 5);
mPhysicsHandler.setAccelerationY(100);
}
return true;
}
Please help.
Before applying the move when dragging, check to see if the touch event falls within the circle. To do this, measure the distance from the center of the circle. If the distance is less than the radius of the circle, then move the object. If not, do nothing.
#Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float pTouchAreaLocalY)
{
if (pSceneTouchEvent.isActionMove() || pSceneTouchEvent.isActionDown() ||
pSceneTouchEvent.isActionOutside())
{
// Use Pythagorean theorem to get distance between 2 points;
// center is a point you declare
// radius is a value you declare that is the radius of the circular area
Float distance = (pSceneTouchEvent.getX() - center.x)*(pSceneTouchEvent.getX() - center.x) + (pSceneTouchEvent.getY() - center.y) * (pSceneTouchEvent.getY() - center.y);
distance = Math.sqr(distance);
if(distance < radius){
// Only move if touch event is inside the circle area
this.setX(pSceneTouchEvent.getX() - this.getWidth() / 2);
this.setY(pSceneTouchEvent.getY() - this.getHeight() / 2);
}
}
else if (pSceneTouchEvent.isActionUp())
{
mPhysicsHandler.setVelocityX((originX - getX()) * 5);
mPhysicsHandler.setVelocityY((originY - getY()) * 5);
mPhysicsHandler.setAccelerationY(100);
}
return true;
}
Related
The animation I am working on achieving is shown below in Figure 1.
1)I have a list containing points on a 2D plane(left) that I am working on animating.
2)A touch is made at location x, and an invisible circle is drawn (middle). I want all of the points contained in that circle to move away from the center (x).
3) A final result example (right)
I am planning on applying this in a way that I can supply any list of points, touch location, numFrames, and force applied on each point per frame. An array of length numFrames is returned, each array item being an already animated list.
Since I plan on implementing this on screen touch, it is possible for another touch to happen while the first touch animation is already in progress. How can I handle these collisions?
Figure 1:
here's my 2 cents, you need a list of points, these points should have a position, a velocity and a method to update the position. something like this
public class Point {
public float x, y;
public boolean isMoving;
private float dx,dy;
public Point(float x, float y){
this.x = x;
this.y = y;
}
public boolean move(float maxWidth, float maxHeight){
if(!isMoving) return false;
// update the position
x += dx;
y += dy;
dx /= FRICTION;
dy /= FRICTION;
// bounce...?
if(x < 0 || x > maxWidth){
dx *= -1;
}
if(y < 0 || y > maxHeight){
dy *= -1;
}
if(Math.abs(dx) < MOVEMENT_THRESHOLD && Math.abs(dy) < MOVEMENT_THRESHOLD){
isMoving = false;
}
return isMoving;
}
}
on every touch event you apply a force to every point within the radius and set their velocity
for(Point point : mPoints){
float distance = point.distance(x,y);
if(distance > mTouchRange) continue;
float force = (float) Math.pow(1 - (distance / mTouchRange), 2) * mForceFactor;
float angle = point.angle(x,y);
point.dx -= Math.cos(angle) * force;
point.dy -= Math.sin(angle) * force;
point.isMoving = true;
}
then you need an animation that call move on every frame and eventully stops when there are no moving points
you can find the full example here
I am trying to create a pad-like view in android. I got a circle that follows user's gestures and I am using distance to keep the circle of going outside the main circle of the pad control.
My problem is I want the circle to keep following the gesture, but to stay inside of the main circle. I am using the formula for finding a point using angle and radius, but it does some funky stuff.
I am translating the canvas, so that the center of the main circle is at 0, 0.
Here is the code:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(this.mainRadius, this.mainRadius);
canvas.drawCircle(0, 0, this.mainRadius, this.debugPaint);
canvas.drawCircle(this.handleX, this.handleY, this.handleRadius, this.handlePaint);
}
private void translateHandle(MotionEvent event) {
int x = (int) (event.getX() - this.mainRadius);
int y = (int) (event.getY() - this.mainRadius);
double distance = distanceFromCenter(x, y);
if (distance <= this.maxDistance) {
this.handleX = x;
this.handleY = y;
} else {
float angle = (float) Math.toDegrees(Math.atan2(y, x));
if (angle < 0)
angle += 360;
this.handleX = (int) ((this.mainRadius - this.handleRadius) * Math.cos(angle));
this.handleY = (int) ((this.mainRadius - this.handleRadius) * Math.sin(angle));
}
//onTranslateHandle(distance);
}
And here is the funky stuff in a gif image:
I cannot verify this change into your code snippet but do hope it gives some idea how to proceed further anyway;
private void translateHandle(MotionEvent event) {
float x = event.getX() - this.mainRadius;
float y = event.getY() - this.mainRadius;
double distance = distanceFromCenter(x, y);
if (distance > this.maxDistance) {
// If distance is i.e 2.0 and maxDistance is 1.0 ==> adjust is 0.5
// which repositions x and y making distance 1.0 maintaining direction
double adjust = this.maxDistance / distance;
x = (float)(x * adjust);
y = (float)(y * adjust);
}
this.handleX = (int)x;
this.handleY = (int)y;
}
I can update the answer where needed if this does not give any useful results.
i am trying to study andengine. When i am touching on center of sprite(tree) everything works fine. But when i am touching on top of the sprite it jump to the center of the sprite.
hope my question is clear.
this is the on touch event code i am using
final Sprite face = new Sprite(centerX, centerY, this.mFaceTextureRegion, this.getVertexBufferObjectManager()) {
#Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2, pSceneTouchEvent.getY() - this.getHeight() / 2);
return true;
}
};
I think you want your sprite to center of the Scene when you touch it on any part of sprite,
But you are using onAreaTouched for that use should use IOnSceneTouchListener for that like below :-
#Override
public boolean onSceneTouchEvent(final Scene pScene,
final TouchEvent pSceneTouchEvent) {
this.setPosition(pSceneTouchEvent.getX() - face.getWidth() / 2, pSceneTouchEvent.getY() - face.getHeight() / 2);
return false;
}
I am moving an image around a circle via touch events.
I want the user to touch the image and when the user drags this image around the cirle, it moves, otherwise it doesn't move.
Could someone please help with the math on how to check if the finger in moving along the circle or not and them move the image accordingly.
Thanks.
UPDATE:
I am trying to revolve an image around a circle. It is already placed on the circle edge.
But on touch and move actions it takes it self as the centre and then starts moving around a defined radius.
could someone pls see the code and let me know where i am going wrong.
Thanks.
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mInitialX = event.getX();
mInitialY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
mEndX = event.getX();
mEndY = event.getY();
float deltaX = mEndX - mInitialX;
float deltaY = mEndY - mInitialY;
double angleInDegrees = Math.atan(deltaY / deltaX) * 180 / Math.PI;
mInitialX = mEndX;
mInitialY = mEndY;
mCurrTempIndicator.setRotation((float)angleInDegrees);
mCurrTempIndicator.setTranslationX((float)(310*(Math.cos(angleInDegrees))));
mCurrTempIndicator.setTranslationY((float)(310*(Math.sin(angleInDegrees))));
break;
case MotionEvent.ACTION_UP:
allowRotating = true;
break;
}
return true;
}
float dx = event.getX() - circleCenterX
float dy = event.getY() - circleCenterY;
// r is now the radius of the touch event, you can compare it with the radius of your circle to find out if it's close enough
float r = FloatMath.sqrt((dx * dx) + (dy * dy));
if(r > circleRadius - 10 && r < circleRadius + 10){
// a is now the angle between the center point and the touch point in radians. With 0 being 3 o'clock, -/+PI being 9 o'clock -PI/2 at 12 o'clock and +PI/2 at 6 o'clock.
float a = Math.atan2(dy, dx);
}
Adding to the above answer. I made some changes to make it work properly. In this I'm making an ImageView to revolve around a fixed center point meaning ImageView will move along the circumference of the circle.
double centerX, centerY; //Center coordinates of the circle
int radius; //Set the radius in pixels
//The view which will revolve on the circumference of the circle
imageView = new ImageView(this);
imageView.setBackgroundResource(android.R.drawable.ic_menu_add); //Set your view icon
imageView.setPadding(10, 10, 10, 10);
relativeLayout.addView(imageView);
//Setting the imageView on the circumference of the circle
imageView.setTranslationX(centerX + radius);
imageView.setTranslationY(centerY);
//Add imageview to the parent layout dynamically(choice)
relativeLayout.addView(imageView);
imageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_MOVE:
double dx = motionEvent.getRawX() - centerX;
double dy = motionEvent.getRawY() - centerY; //Also subtract toolbar height and status bar height if applicable
//Distance between user's point of touch and circle center
double distance = Math.sqrt((dx * dx) + (dy * dy));
if (distance > radius - 200 && distance < radius + 200) {
double angle = Math.atan2(dy, dx);
//Getting the point on the circumference of the circle using the angle and the radius
double x = centerX + radius * Math.cos(angle);
double y = centerY + radius * Math.sin(angle);
//Finally move the view along the circimference of the circle as the user drags the view
imageView.animate().y((float) y).x((float) x).setDuration(0).start();
}
break;
}
return true;
}
});
I am new to andengine and even android game development. i have created sprite as a box. this box is now draggable by using this coding. it works fine.
but i want multitouch on this which i want to rotate a sprite with 2 finger in that box and even it should be draggable. .... plz help someone...
i am trying this many days but no idea.
final float centerX = (CAMERA_WIDTH - this.mBox.getWidth()) / 2;
final float centerY = (CAMERA_HEIGHT - this.mBox.getHeight()) / 2;
Box= new Sprite(centerX, centerY, this.mBox,
this.getVertexBufferObjectManager()) {
public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
float pTouchAreaLocalX, float pTouchAreaLocalY) {
this.setPosition(pSceneTouchEvent.getX() - this.getWidth()/ 2,
pSceneTouchEvent.getY() - this.getHeight() / 2);
float pValueX = pSceneTouchEvent.getX();
float pValueY = CAMERA_HEIGHT-pSceneTouchEvent.getY();
float dx = pValueX - gun.getX();
float dy = pValueY - gun.getY();
double Radius = Math.atan2(dy,dx);
double Angle = Radius * 360 ;
Box.setRotation((float)Math.toDegrees(Angle));
return true;
}
Make sure you enabled multi touch in your game. You can use the same code used in the MultiTouchExample in the onLoadEngine method.
The algorithm is quite simple, similar to what you've posted here.
Keep track of up to 2 pointer IDs you get in onAreaTouched method. (You can get the pointer ID by calling pSceneTouchEvent.getPointerID()).
Keep track of the pointers' state (Currently touching/not touching) and location (pTouchAreaLocalX and pTouchAreaLocalY).
Whenever 2 pointers are touching (You received ACTION_DOWN for both), save the initial angle. (Math.tan2(pointer1Y - pointer2Y, pointer1X - pointer2X)).
As long as ACTION_UP is not called for the pointers, update the new angle in every ACTION_MOVE event of the pointers, and get the angle delta (delta = currentAngle - initialAngle). Then call setRotation(Math.toDegrees(delta)).
To make the sprite dragable with 2 pointers, you need to move your sprite the lesser of the distance each pointer has moved. For example, if:
pointer1.dX = 50;
pointer1.dY = -20;
pointer2.dX = 40;
pointer2.dY = -10;
the sprite should move +40 units in the X axis, and -10 units in the Y axis.