I'm new to AndEngine and I want to draw a line by using my finger coordinates in the onSceneTouchEvent I did all what I knew and I think its right but there is something that keeps it from working I don't know what, I can't detect the problem :/
private Scene scene;
float startX;
float startY;
float lastX;
float lastY;
int lineUsageCount = 0;
#Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
switch (pSceneTouchEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = pSceneTouchEvent.getX();
startY = pSceneTouchEvent.getY();
lineUsageCount = 0 ;
break;
case MotionEvent.ACTION_MOVE:
lineUsageCount++;
lastX = pSceneTouchEvent.getX();
lastY = pSceneTouchEvent.getY();
break;
case MotionEvent.ACTION_UP:
if (lineUsageCount <= 5) {
final Line line = new Line(startX, startY, lastX,
lastY, this.getVertexBufferObjectManager());
line.setLineWidth(1);
line.setColor(255, 255, 255);
scene.attachChild(line);
}
break;
}
return true;
}
};
it should get the first coordinates startX, startY and then on the Action_Move it gets the lastX, lastY and draw the line but it doesn't seem to work :|
Problem is in this line of code: if (lineUsageCount <= 5) {
While you move your finger, lineUsageCount will be much more then 5. Debug this variable and than change it in "IF" or remove this "IF" from your code.
Related
I found this question, but it's for iOS development. I'm doing something in Android, so it wasn't any help.
I have a simple white rectangle on a black canvas, and I have an onTouchEvent set up. I can move the rectangle as expected, but this is not the functionality I'm looking for.
I'm needing to know how I can touch anywhere on the screen and move an object? I don't want the object's X and Y to become my touch event's getX() and getY().
For now, I have:
#Override
public boolean onTouchEvent(MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
myPoint.set((int)event.getX(), (int)event.getY());
}
return true;
}
My reasoning for this is so the object can be seen without a finger hovering over it. Is this possible?
Here is a visual representation of what I'm wanting to achieve:
Why not get and store the previous MotionEvent coordinates in the onTouchEvent callback, then when onTouchEvent fires again (first ACTION_MOVE after ACTION_DOWN and then so on for each ACTION_MOVE callback) work out the offset/difference between the values then get your own myPoint coordinates and add the offset to their current values. This way you're only moving the myPoint object by the position offset, not the actual coordinates.
This code isn't tested and I've not used an IDE but something like this:
private float oldX;
private float oldY;
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
oldX = event.getX();
oldY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
float newX = event.getX();
float newY = event.getY();
float offsetX = getOffset(oldX, newX, myPoint.x);
float offsetY = getOffset(oldY, newY, myPoint.y);
myPoint.set((int) offsetX, (int) offsetY);
oldX = newX;
oldY = newY;
break;
}
return true;
}
private float getOffset(float oldVal, float newVal, float current) {
return current + (newVal - oldVal);
}
Im trying to do a pinch to zoom on a imageview. The problem is that the when i zoom it does'nt scale where i pinched it scales up to the left corner. Im not sure why i does this and i seems that there is a lot of people having the same problem but i havent found a soloution to it yet.
public override bool OnTouchEvent(MotionEvent ev)
{
_scaleDetector.OnTouchEvent(ev);
MotionEventActions action = ev.Action & MotionEventActions.Mask;
int pointerIndex;
switch (action)
{
case MotionEventActions.Down:
_lastTouchX = ev.GetX();
_lastTouchY = ev.GetY();
_activePointerId = ev.GetPointerId(0);
break;
case MotionEventActions.Move:
pointerIndex = ev.FindPointerIndex(_activePointerId);
float x = ev.GetX(pointerIndex);
float y = ev.GetY(pointerIndex);
if (!_scaleDetector.IsInProgress)
{
// Only move the ScaleGestureDetector isn't already processing a gesture.
float deltaX = x - _lastTouchX;
float deltaY = y - _lastTouchY;
_posX += deltaX;
_posY += deltaY;
Invalidate();
}
_lastTouchX = x;
_lastTouchY = y;
break;
case MotionEventActions.Up:
case MotionEventActions.Cancel:
// We no longer need to keep track of the active pointer.
_activePointerId = InvalidPointerId;
break;
case MotionEventActions.PointerUp:
// check to make sure that the pointer that went up is for the gesture we're tracking.
pointerIndex = (int) (ev.Action & MotionEventActions.PointerIndexMask) >> (int) MotionEventActions.PointerIndexShift;
int pointerId = ev.GetPointerId(pointerIndex);
if (pointerId == _activePointerId)
{
// This was our active pointer going up. Choose a new
// action pointer and adjust accordingly
int newPointerIndex = pointerIndex == 0 ? 1 : 0;
_lastTouchX = ev.GetX(newPointerIndex);
_lastTouchY = ev.GetY(newPointerIndex);
_activePointerId = ev.GetPointerId(newPointerIndex);
}
break;
}
return true;
}
protected override void OnDraw(Canvas canvas)
{
base.OnDraw(canvas);
canvas.Save();
canvas.Translate(_posX, _posY);
canvas.Scale(_scaleFactor, _scaleFactor, _lastTouchX, _lastTouchY);
_icon.Draw(canvas);
canvas.Restore();
}
I think it might have to do with this code in the beginning of the class where the bounds of the image is set to 0. But if i delete that code the image wont render.
public GestureRecognizer(Context context, ImageView imgview)
: base(context, null, 0)
{
//_icon = context.Resources.GetDrawable(Resource.Drawable.ic_launcher);
_icon = imgview.Drawable;
_icon.SetBounds(0, 0, _icon.IntrinsicWidth, _icon.IntrinsicHeight);
_scaleDetector = new ScaleGestureDetector(context, new MyScaleListener(this));
}
Have a look at MultiTouchController library. It makes it much easier to write multitouch applications for Android and pinch to zoom, rotate and drag is nicely implemented. Here is the link.
I'm trying to make a basic "Paint"-esque app for a class, and part of what I'm trying to implement is the ability to draw a circle that scales in size as the user moves their finger to pick the center, and drags it outward to the desired radius. The problem is, no matter what I try it just ends up repeatedly stamping a small circle where ever the user moves their finger. The idea is the app will get the coordinates for the center (tX, tY) on the press down, draw a circle with a radius r every time the user moves, then finalize it when they lift their finger.
Edit: the commented out sections are parts where I was testing different things.
Code for my onMotionEvent custom class:
#Override
public boolean onTouchEvent(MotionEvent event) {
//detect user touch
float tX = event.getX();
float tY = event.getY();
float rX = 0;
float rY = 0;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
drawPath.moveTo(tX, tY);
break;
case MotionEvent.ACTION_MOVE:
if(shapes){
rX = (int) event.getX();
rY = (int) event.getY();
r = (float) Math.sqrt(Math.pow(tX - rX, 2) + Math.pow(tY - rY, 2));
drawCanvas.drawCircle(tX, tY, r, drawPaint);
invalidate();
}else{
drawPath.lineTo(tX, tY);
}
break;
case MotionEvent.ACTION_UP:
/*rX = event.getX();
rY = event.getY();
r = (float) Math.sqrt(Math.pow(tX - rX, 2) + Math.pow(tY - rY, 2));*/
if(shapes){
if(shape_sel == 0){
//drawCanvas.drawCircle(tX, tY, r, drawPaint);
drawPath.reset();
/*}else if(shape_sel == 1){
}
else{
*/}
}else{
drawCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
}
break;
default:
return false;
}
invalidate();
return true;
}
You aren't saving tx and ty on touch down, you're resetting them on every event. You need to save tx and ty in class level variables inside the down case.
I am using MotionEvent and Matrix to drag my bitmap but instead the bitmap gets "translated" to a nearby region (most of the times in the opposite direction of press). I want to be able to drag it using Matrix translations. Here's my code.
switch(action){
case MotionEvent.ACTION_DOWN: {
final float touchX = event.getX();
final float touchY = event.getY();
//check to see if the user is pressing at most 80 pixels far from the bitmap
if(((Math.abs(touchX - player.prevX)<=80) && ((Math.abs(touchY - player.prevY)<=80)))){
//if so then proceed to drag it to a new location
player.isDraggable = true;
}
break;
}
case MotionEvent.ACTION_MOVE: {
if(player.isDraggable){
player.x = event.getX();
player.y = event.getY();
float dx = player.x - player.prevX, dy = player.y - player.prevY;
player.matrix.postTranslate(dx, dy);
player.prevX = player.x;
player.prevY = player.y;
player.isDraggable = false;
}
break;
}
}
public void draw(Canvas canvas) {
canvas.drawBitmap(background, 0, 0, null);
canvas.drawBitmap(player.bmp, player.matrix, null);
for(int i=0;i<particles.size();i++){
particles.get(i).drawShower(canvas);
}
}
Your onTouch() method should return true to be able to get
continuously values from the MotionEvent.
You set the isDraggable attribute of your player immediately to
false, when an attempt to drag the image appears. After that, you check each time, if it is true, but it wont be. I don't know, what is the logic behind that, but try something else!
In my program I am having it draw a rectangle while the finger is down and moving than erase it after the finger is up. this is to show the user the range of values he/she is using as a "guess" to find the root. however the rectangle never shows up! But, if I remove the call to close the rectangle in the "action_up" part the user can draw the rectangle.
Here's the code:
in the on draw function:
if(dataline>1)//if greater than 1, draw rectangle
{
myPaint.setColor(Color.CYAN);
canvas.drawRect(tX1,0, tX2,canvas.getHeight(),myPaint);
}
in the motion event function:
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
// Remember where we started
mLastTouchX = x;
mLastTouchY = y;
tX1=(int)ev.getX();
tX2=tX1;
x_1 = ev.getX();
x_1=(x_1-X1)/(zoom_x);
clicks= 1;
tX1=(int) ev.getX();//set first x coord
tX2=tX1;// make second x coord equal to the first
}
case MotionEvent.ACTION_MOVE: {
final float x = ev.getX();
final float y = ev.getY();
// Calculate the distance moved
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mLastTouchX = x;
mLastTouchY = y;
dataline=2;//let onDraw() draw the rectangle while dragging finger
tX2+= (int)dx;// find new second coordinate
}
case MotionEvent.ACTION_UP: {
dataline=0;//if commented out, rectangle is drawn otherwise, it is never seen.
}
}
return true;
}
Problem solved! I have learned that you have to put a return statement in each case, or else it will just run all the cases.