I have 2 sprites, I would like to move both of them, when I touched sprite A and moved it, sprite B will be moved also without touching sprite B at the same time. thanks for the help
here is the code
I have 2 sprites, I would like to move both of them, when I touched sprite A and moved it, sprite B will be moved also without touching sprite B at the same time. thanks for the help
here is the code
center = new AnimatedSprite(0, 0, resourcesManager.interact, vbom) {
#Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent,final float pTouchAreaLocalX, final float pTouchAreaLocalY)
{
//SPrite A
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2,
pSceneTouchEvent.getY() - this.getHeight() / 2);
//Sprite B
return true;
}
};
If you can post some code it would help in creating a more helpful answer.
In essence, when you handle the touch event and apply the movement to sprite A all you need to do is also apply the movement to sprite B.
If you post your code I will be able to edit and add an example.
You can change position of sprite B at the same moment with sprite A, inside spriteA's onAreaTouched method:
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent,final float pTouchAreaLocalX, final float pTouchAreaLocalY)
{
//SPrite A
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2,
pSceneTouchEvent.getY() - this.getHeight() / 2);
spriteB.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2,
pSceneTouchEvent.getY() - this.getHeight() / 2);
};
Related
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 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;
}
I am currently following some tutorials to get introduced to andEngine and box2d and I would like to drag an object (sprite attached to body), whilst it is bouncing (it is registered to a physics world).
I would like to drag so I can see my character moving. It works only if I comment the code as below (the part where I am registering Physics connector). If I uncomment it, everything will work (e.g. even if I set other properties), except setPosition!! - I am sure the code is entering the ACTION_MOVE case
Question 1: why is this approach not working?
- maybe I have to drag the body and not the sprite?
Question 2: how can I refer to the body and make operations in it WITHIN THE onAreaTouched?
- I tried many different approaches, but it seams that you have to create the onAreaTouch when declaring the sprite only.
Reference: http://stuartmct.co.uk/2012/07/18/andengine-touch-events-with-sprites-and-shapes/ and AndEngine Book
Sprite sPlayer = new Sprite(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2,
playerTextureRegion,
this.mEngine.getVertexBufferObjectManager()) {
#Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent,
final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
Log.i(this.getClass().getName(), "area touched");
switch (pSceneTouchEvent.getAction()) {
case TouchEvent.ACTION_DOWN:
break;
case TouchEvent.ACTION_UP:
break;
case TouchEvent.ACTION_MOVE:
this.setPosition(pSceneTouchEvent.getX() - this.getWidth()
/ 2, pSceneTouchEvent.getY() - this.getHeight() / 2);
break;
}
return true;
}
};
FixtureDef PLAYER_FIX = PhysicsFactory.createFixtureDef(10.0f, 0.75f,
0.0f);
// apply all forces, collisions to body - Dynamic
Body body = PhysicsFactory.createCircleBody(physicsWorld, sPlayer,
BodyType.DynamicBody, PLAYER_FIX);
The following code does not let me setPosition of Sprite:
/*
// relate to collisions after adding to scene
physicsWorld.registerPhysicsConnector(new PhysicsConnector(sPlayer,
body, true, true));
*/
this.scene.registerTouchArea(sPlayer);
this.scene.setTouchAreaBindingOnActionDownEnabled(true);
this.scene.attachChild(sPlayer);
You will need to go
myPad.setTransform(pSceneTouchEvent.getX() - (this.getWidth()
/ 2), pSceneTouchEvent.getY() - (this.getHeight() / 2), 0);//the zero at the end is for setting the angle
Because with box2d you need to move the body and the physics connector
physicsWorld.registerPhysicsConnector(new PhysicsConnector(sPlayer,
body, true, true));
will make the sprite follow the body.
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.
Please see each section below for a description of my problem described in three separate ways. Hopefully should help people to answer.
Problem: How do you find a pair of coordinate expressed in canvas/userspace when you only have the coordinate expressed in terms of a zoomed image, given the original scale point & scale factor?
Problem in practice:
I'm currently trying to replicate the zoom functionality used in apps such as the gallery / maps, when you can pinch to zoom/zoom out with the zoom moving towards the midpoint of the pinch.
On down I save the centre point of the zoom (which is in X,Y coordinates based on the current screen). I then have this function act when a "scale" gesture is detected:
class ImageScaleGestureDetector extends SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
if(mScaleAllowed)
mCustomImageView.scale(detector.getScaleFactor(), mCenterX, mCenterY);
return true;
}
}
The scale function of the CustomImageView look like this:
public boolean scale(float scaleFactor, float focusX, float focusY) {
mScaleFactor *= scaleFactor;
// Don't let the object get too small or too large.
mScaleFactor = Math.max(MINIMUM_SCALE_VALUE, Math.min(mScaleFactor, 5.0f));
mCenterScaleX = focusX;
mCenterScaleY = focusY;
invalidate();
return true;
}
The drawing of the scaled image is achieved by overriding the onDraw method which scales the canvas around the centre ands draw's the image to it.
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.translate(mCenterScaleX, mCenterScaleY);
canvas.scale(mScaleFactor, mScaleFactor);
canvas.translate(-mCenterScaleX, -mCenterScaleY);
mIcon.draw(canvas);
canvas.restore();
}
This all works fine when scaling from ScaleFactor 1, this is because the initial mCenterX and mCenterY are coordinates which are based on the device screen. 10, 10 on the device is 10, 10 on the canvas.
After you have already zoomed however, then next time you click position 10, 10 it will no longer correspond to 10, 10 in the canvas because of the scaling & transforming that has already been performed.
Problem in abstraction:
The image below is an example of a zoom operation around centre point A. Each box represents the position and size of the view when at that scale factor (1, 2, 3, 4, 5).
In the example if you scaled by a factor of 2 around A then you clicked on position B, the X, Y reported as B would be based on the screen position - not on the position relative to 0,0 of the initial canvas.
I need to find a way of getting the absolute position of B.
So, after redrawing the problem I've found the solution I was looking for. It's gone through a few iteration's but here's how I worked it out:
B - Point, Center of the scale operation
A1, A2, A3 - Points, equal in user-space but different in canvas-space.
You know the values for Bx and By because they are always constant no matter what the scale factor (You know this value in both canvas-space and in user-space).
You know Ax & Ay in user-space so you can find the distance between Ax to Bx and Ay to By. This measurement is in user-space, to convert it to a canvas-space measurement simply divide it by the scale factor. (Once converted to canvas-space, you can see these lines in red, orange and yellow).
As point B is constant, the distance between it and the edges are constant (These are represented by Blue Lines). This value is equal in user-space and canvas-space.
You know the width of the Canvas in canvas-space so by subtracting these two canvas space measurements (Ax to Bx and Bx to Edge) from the total width you are left with the coordinates for point A in canvas-space:
public float[] getAbsolutePosition(float Ax, float Ay) {
float fromAxToBxInCanvasSpace = (mCenterScaleX - Ax) / mScaleFactor;
float fromBxToCanvasEdge = mCanvasWidth - Bx;
float x = mCanvasWidth - fromAxToBxInCanvasSpace - fromBxToCanvasEdge;
float fromAyToByInCanvasSpace = (mCenterScaleY - Ay) / mScaleFactor;
float fromByToCanvasEdge = mCanvasHeight - By;
float y = mCanvasHeight - fromAyToByInCanvasSpace - fromByToCanvasEdge;
return new float[] { x, y };
}
The above code and image describe when you're clicking to the top left of the original centre. I used the same logic to find A no matter which quadrant it was located in and refactored to the following:
public float[] getAbsolutePosition(float Ax, float Ay) {
float x = getAbsolutePosition(mBx, Ax);
float y = getAbsolutePosition(mBy, Ay);
return new float[] { x, y };
}
private float getAbsolutePosition(float oldCenter, float newCenter, float mScaleFactor) {
if(newCenter > oldCenter) {
return oldCenter + ((newCenter - oldCenter) / mScaleFactor);
} else {
return oldCenter - ((oldCenter - newCenter) / mScaleFactor);
}
}
Here is my solution based on Graeme's answer:
public float[] getAbsolutePosition(float Ax, float Ay) {
MatrixContext.drawMatrix.getValues(mMatrixValues);
float x = mWidth - ((mMatrixValues[Matrix.MTRANS_X] - Ax) / mMatrixValues[Matrix.MSCALE_X])
- (mWidth - getTranslationX());
float y = mHeight - ((mMatrixValues[Matrix.MTRANS_Y] - Ay) / mMatrixValues[Matrix.MSCALE_X])
- (mHeight - getTranslationY());
return new float[] { x, y };
}
the parameters Ax and Ay are the points which user touch via onTouch(), I owned my static matrix instance in MatrixContext class to hold the previous scaled/translated values.
Really sorry this is a brief answer, in a rush. But I've been looking at this recently too - I found http://code.google.com/p/android-multitouch-controller/ to do what you want (I think - I had to skim read your post). Hope this helps. I'll have a proper look tonight if this doesn't help and see if I can help further.