Author Topic: swiping  (Read 4963 times)

JB

  • Guest
swiping
« on: May 23, 2012, 08:24:41 am »
Prospective question as am at work and can't try it out yet:

I want to work out the angle and length of a swipe (approximated to a straight line).
To get the x and y coordinates can I do:


Code: [Select]
int OnTouchArea(int id, int event, int x, int y)
 
if event==1
TouchGetxy(...etc

if event==3
TouchGetxy(...etc

Will this give me two sets of x and y co-ordinates with which I can then use to work out the line and angles?

Many thanks,

Jon


nednones

  • Guest
Re: swiping
« Reply #1 on: May 23, 2012, 08:53:44 am »
Hi JB,

Yes it will, if you create two variables Xinitial, Yinitial and assign them the value of x,y in the event == 1 loop they will be hold the initial touch coords. Then when in the event == 3 loop, whatever the x,y coords are, are the coords when the finger left the screen.

JB

  • Guest
Re: swiping
« Reply #2 on: May 23, 2012, 09:03:19 am »
Hi Nednones,
that's great, thanks for your reply - just wanted to make sure I hadn't totally missed the point of that part of the API.
Regards,
Jon

stuckerj

  • Guest
Re: swiping
« Reply #3 on: June 17, 2012, 10:47:26 am »
I've used the basic swiping as described in the tutorial and this thread, which works well, but would like to add some more interesting physics to it.

What's the best way to link a swipe to Box2D (assuming that's the best way to implement this)?  I want the user to be able to move around an object with a finger, and then "flick" it off the screen.   But if they stop and release, it should snap back to center. 

nednones

  • Guest
Re: swiping
« Reply #4 on: June 17, 2012, 02:38:23 pm »
The swipe as described above will give you a set of coords to calculate a trial of a line in any direction. The force of essentially flicking an object would be based on the swipe, e.g. if you swipe by 25 pixels, this might equate to a force of say 2 newtons. You could build a table where the magnitude of the swipe is equal to some force. Once a swipe occurs you could then apply an impulse to the object using the impulse class built within the Box 2D framework. The direction of the object would also come from the swipe method. If you use the swipe (onTouch method) to move the object and then define a threshold to what is a move and what is an "Object flick". This way you could move your object around without it flicking off the screen, but then once a swipe over the object occurs it would project the object at a velocity and angle/direction

stuckerj

  • Guest
Re: swiping
« Reply #5 on: June 17, 2012, 03:30:47 pm »
nednones, you touched on the key word there -- velocity.  I'm wondering if there is an easy way to determine the velocity of swipe at release.  Picture someone randomly dragging an item around slowly, and then flicking it as they lift off the screen -- I want it to fly off the screen with the velocity and direction of the flick.   Alternatively, picture someone dragging the item around quickly, or a long ways, then stopping then releasing -- because the item's not moving, I want it to snap back to center. 

(Like a ball being carried around in an inverted cone; when dropped it naturally rolls to the middle unless it's thrown completely out of the area.)

stuckerj

  • Guest
Re: swiping
« Reply #6 on: June 17, 2012, 08:59:34 pm »
Update:  I just extended the original swipe example to capture a history and calculated direction and velocity from that.  I decided for the time being not to use Box2D for this app, because the flick off-screen is the only physics-like functionality I need.

jjsanchezramirez

  • Guest
Re: swiping
« Reply #7 on: September 21, 2012, 12:59:02 pm »
Could you provide code for that? I want to create containers with frictions for menus and objects of the sort.

jjsanchezramirez

  • Guest
Re: swiping
« Reply #8 on: September 24, 2012, 11:04:21 am »
This is the first version of a container written by Nico91 and myself. It has both elasticity (recoil), written by me, and friction, written by Nico91 and modified by me. It definitely has room for upgrade. You can make the friction disappear more slowly by calling the function only a few times per frame instead of 30 times per second, as it currently is. This would give the sliding container more momentum.

Code: [Select]
/* Copyright 2012 Juan José Sánchez Ramírez

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

   Author Juan José Sánchez Ramírez
   Co-author Nico91 at www.DragonFireSDK.net/forums
   Version 2.0
*/

#ifndef DYNAMIC_SCROLLER
#define DYNAMIC_SCROLLER

int nOldX;
int nOldY;
int nNewX;
int nNewY;

int nTouchId;
int nTouchEvent;

// This function will be called when a scroller is activated
int OnTouch(int id, int event, int x, int y)
{
// Get the ID of the container
nTouchId = id;

// Get the event of the container
nTouchEvent = event;

// Record initial coordinates when pressed down
if (event == 1)
{
nOldX = x;
nOldY = y;
nNewX = x;
nNewY = y;
}

// Record new coordinates when moving
if (event == 2)
{
nNewX = x;
nNewY = y;
}

// Erase coordinates when released
if (event == 3)
{
nOldX = 0;
nOldY = 0;
nNewX = 0;
nNewY = 0;
}

return id;
}

// This function approximates a container to it's target position.
void SlideContainer(int container, int targetX, int targetY, int speed)
{
/* To approximate the container, we're going to do the following:

   1. We get the container's x and y positions on the screen.
   2. If the value is less than the target value, we substract the
      value from the target value. If the value is more than the
  target value, we substract the target value from the value.
   3. We divide the difference by the speed.
   4. If the result equals 0, we make it equal to 1.
   5. If the value is less than the target value, we add the result
      to the value. If the value is more than the target value, we
  substract the result from the value.
   6. Finally, we set the container's position to our x and y values.
*/

int x = ContainerGetx(container);
int y = ContainerGety(container);

if (x < targetX)
{
int n = (targetX - x) / speed;
if (n == 0) n = 1;
x += n;
}
else if (x > targetX)
{
int n = (x - targetX) / speed;
if (n == 0) n = 1;
x -= n;
}

if (y < targetY)
{
int n = (targetY - y) / speed;
if (n == 0) n = 1;
y += n;
}
else if (y > targetY)
{
int n = (y - targetY) / speed;
if (n == 0) n = 1;
y -= n;
}

ContainerSetxy(container, x, y);
}

// This class creates a simple scroller for containers
class DynamicScroller
{
/* A scroller lets a container slide upon a portion of the screen.
   It's designed to move containers that are too big for the screen,
   both vertically and horizontally, but it can be modified to move
   smaller objects too, such as sliders. This can be achieved by
   modifying minimum and maximum ranges, using the SetMinX, SetMinY,
   SetMaxX, and SetMaxY functions, or alternatively, using the
   SetBoundaries function, which modifies all of these values at once.

   The scroller uses the following components:

   1. A container which contains all of the elements in the scroller.
   2. A touch component which must be at least the size of the
      entire container, which records the drag and drop actions.
   3. An ID number that allows to differentiate among scrollers,
      since all scrollers use the same OnTouch function.
   
   The recoil component uses the following variables:

   1. Elasticity, defined here as the property of an object to return
      to its original state after a stress. In this particular context,
  elasticity can be thought of as how fast the container returns to
  its position.
 
  Note: The lower the value, the higher the elasticity!

   2. Compliance, defined here as the inverse of elasticity. In this
      particular context, compliance can be thought of as the resistance
  of a container to move out of position.

  Note: The higher the value, the higher the compliance!
   
   The friction component uses the following variables:

   1. Max Speed, defined here as the maximum sliding speed between two
      bodies, independent of the acceleration.

   2. Friction Coefficient, defined here as an empirical property of the
      containers which describes the force of friction between two bodies
  and the force pressing them together. For example, ice on steel has
  a low coefficient of friction, while rubber on pavement has a high
  coefficient of friction.

  Note: The higher the value, the higher the coefficient!
*/

private:

int m_nContainer;
int m_nTouch;

int m_nX;
int m_nY;

int m_nMinX;
int m_nMinY;

int m_nMaxX;
int m_nMaxY;

int m_nCompliance;
int m_nElasticity;

int m_nSpeedX;
int m_nSpeedY;

int m_nMaxSpeed;
int m_nFrictionCoef;

int i;

int m_anTouchX[10000];
int m_anTouchY[10000];

bool m_bHorizontalScroll;
bool m_bVerticalScroll;

bool m_bRecoil;
bool m_bFriction;

bool m_bHorizontalSliding;
bool m_bVerticalSliding;

public:

// Constructor
DynamicScroller()
{

}

// This function initiates the scroller and all of its components
void Init(int& container, int x, int y, int touchWidth, int touchHeight, int id)
{
m_nContainer = container;
m_nTouch = TouchAdd(container, x, y, touchWidth, touchHeight, OnTouch, id);

m_nX = ContainerGetx(container);
m_nY = ContainerGety(container);

m_nMinX = x-touchWidth+320;
m_nMinY = y-touchHeight+480;

m_nMaxX = 0;
m_nMaxY = 0;

m_nCompliance = 10;
m_nElasticity = 2;

m_nSpeedX = 0;
m_nSpeedY = 0;

m_nMaxSpeed = 10;
m_nFrictionCoef = 2;

m_bHorizontalScroll = true;
m_bVerticalScroll = true;

m_bRecoil = true;
m_bFriction = true;

m_bHorizontalSliding = false;
m_bVerticalSliding = false;
}

// This function updates the scroller
void Update()
{
/* To update the scroller we're going to:

   1. Check if the x coordinate has changed. If it has, and
      if horizontal scrolling is allowed, move the container.
  If the container is out of bounds, and recoil is allowed,
  move the container using compliance. If the container is
  out of bounds, and recoil is not allowed, move the
  container within bounds.

   2. Repeat for the y coordinate.

   3. If nothing has changed, then make the scroller x and y
      coordinates equal to the container's coordinates. This
  is necessary to start scrolling again. If the container
  is out of bounds, slide the container within bounds using
  elasticty.

   4. If friction is allowed, depending on the Touch Id, gather
      speed and acceleration data. If there is acceleration and
  the acceleration surpasses the coefficient of friction,
  then use the last recorded speed. Activate scrolling.

   5. Substract the speed from the current coordinate, depending
      if it's vertical or horizontal scrolling. Then terminate
  scrolling. If the container is out of boundes, slide the
  container within bounds using elasticity and set the speed
  to zero.
*/

if (nOldX != nNewX && m_bHorizontalScroll)
{
ContainerSetx(m_nContainer, m_nX+nNewX-nOldX);

if (ContainerGetx(m_nContainer) < m_nMinX)
{
if (m_bRecoil)
ContainerSetx(m_nContainer, m_nMinX-(m_nMinX-(m_nX+nNewX-nOldX))/m_nCompliance);
else
ContainerSetx(m_nContainer, m_nMinX);
}

if (ContainerGetx(m_nContainer) > m_nMaxX)
{
if (m_bRecoil)
ContainerSetx(m_nContainer, m_nMaxX-(m_nMaxX-(m_nX+nNewX-nOldX))/m_nCompliance);
else
ContainerSetx(m_nContainer, m_nMaxX);
}
}

if (nOldY != nNewY && m_bVerticalScroll)
{
ContainerSety(m_nContainer, m_nY+nNewY-nOldY);

if (ContainerGety(m_nContainer) < m_nMinY)
{
if (m_bRecoil)
ContainerSety(m_nContainer, m_nMinY-(m_nMinY-(m_nY+nNewY-nOldY))/m_nCompliance);
else
ContainerSety(m_nContainer, m_nMinY);
}

if (ContainerGety(m_nContainer) > m_nMaxY)
{
if (m_bRecoil)
ContainerSety(m_nContainer, m_nMaxY-(m_nMaxY-(m_nY+nNewY-nOldY))/m_nCompliance);
else
ContainerSety(m_nContainer, m_nMaxY);
}
}

if (nOldX == nNewX && nOldY == nNewY)
{
m_nX = ContainerGetx(m_nContainer);
m_nY = ContainerGety(m_nContainer);

if (m_nX < m_nMinX)
SlideContainer(m_nContainer, m_nMinX, m_nY, m_nElasticity);
if (m_nY < m_nMinY)
SlideContainer(m_nContainer, m_nX, m_nMinY, m_nElasticity);
if (m_nX > m_nMaxX)
SlideContainer(m_nContainer, m_nMaxX, m_nY, m_nElasticity);
if (m_nY > m_nMaxY)
SlideContainer(m_nContainer, m_nX, m_nMaxY, m_nElasticity);
}

if (m_bFriction)
{
if (nTouchEvent == 1)
{
i = 0;
m_bHorizontalSliding = false;
m_bVerticalSliding = false;
}

if (nTouchEvent == 2)
{
i++;
m_anTouchX[i] = nNewX;
m_anTouchY[i] = nNewY;
}

if (nTouchEvent == 3)
{
if ((m_anTouchX[i] > m_anTouchX[i-1] && m_anTouchX[i] - m_anTouchX[i-1] > m_nFrictionCoef) ||
(m_anTouchX[i] < m_anTouchX[i-1] && m_anTouchX[i-1] - m_anTouchX[i] > m_nFrictionCoef))
m_bHorizontalSliding = true;

if ((m_anTouchY[i] > m_anTouchY[i-1] && m_anTouchY[i] - m_anTouchY[i-1] > m_nFrictionCoef) ||
(m_anTouchY[i] < m_anTouchY[i-1] && m_anTouchY[i-1] - m_anTouchY[i] > m_nFrictionCoef))
m_bVerticalSliding = true;

m_nSpeedX = m_anTouchX[i-1] - m_anTouchX[i];
m_nSpeedY = m_anTouchY[i-1] - m_anTouchY[i];

if (m_nSpeedX >= m_nMaxSpeed)
m_nSpeedX = m_nMaxSpeed;

if (m_nSpeedX <= -m_nMaxSpeed)
m_nSpeedX = -m_nMaxSpeed;

if (m_nSpeedY >= m_nMaxSpeed)
m_nSpeedY = m_nMaxSpeed;

if (m_nSpeedY <= -m_nMaxSpeed)
m_nSpeedY = -m_nMaxSpeed;

nTouchEvent = -1;
}

if (m_bHorizontalSliding && m_bHorizontalScroll)
{
m_nX -= m_nSpeedX;

if (m_nX < m_nMinX)
m_nSpeedX = 0;

if (m_nX > m_nMaxX)
m_nSpeedX = 0;

ContainerSetx(m_nContainer, m_nX);

if (m_nSpeedX > 0)
m_nSpeedX--;

if (m_nSpeedX < 0)
m_nSpeedX++;

if (m_nSpeedX == 0)
m_bHorizontalSliding = false;
}

if (m_bVerticalSliding && m_bVerticalScroll)
{
m_nY -= m_nSpeedY;

if (m_nY < m_nMinY)
m_nSpeedY = 0;

if (m_nY > m_nMaxY)
m_nSpeedY = 0;

ContainerSety(m_nContainer, m_nY);

if (m_nSpeedY > 0)
m_nSpeedY--;

if (m_nSpeedY < 0)
m_nSpeedY++;

if (m_nSpeedY == 0)
m_bVerticalSliding = false;
}
}
}

// This function sets the minimum x range
void SetMinX(int x)
{
m_nMinX = x;
}

// This function sets the minimum y range
void SetMinY(int y)
{
m_nMinY = y;
}

// This function sets the maximum x range
void SetMaxX(int x)
{
m_nMaxX = x;
}

// This function sets the maximum y range
void SetMaxY(int y)
{
m_nMaxY = y;
}

// This function sets the minimum and maximum x and y ranges
void SetBoundaries(int minX, int minY, int maxX, int maxY)
{
SetMinX(minX);
SetMinY(minY);
SetMaxX(maxX);
SetMaxY(maxY);
}

// This function sets the horizontal scroll
void SetHorizontalScroll(bool flag)
{
m_bHorizontalScroll = flag;
}

// This function sets the vertical scroll
void SetVerticalScroll(bool flag)
{
m_bVerticalScroll = flag;
}

// This function sets the recoil
void SetRecoil(bool flag)
{
m_bRecoil = flag;
}

// This function sets the friction
void SetFriction(bool flag)
{
m_bFriction = flag;
}
};

#endif

stuckerj

  • Guest
Re: swiping
« Reply #9 on: September 24, 2012, 01:33:34 pm »
Could you provide code for that? I want to create containers with frictions for menus and objects of the sort.

jj, your code is more sophisticated than mine, so I don't think it would add any value for you.

By the way, thanks for posting your stuff here.  It's very useful.  Cheers!

jjsanchezramirez

  • Guest
Re: swiping
« Reply #10 on: September 24, 2012, 10:03:20 pm »
Thanks, anyhow. In the end, it was really Nico91's code that allowed me to finish the scroller. I can definitely see potential in the scroller to develop more complex things, like menus for the iPhone and iPad. DragonFireSDK definitely gives you the tools necessary to create a native look and feel.

Nico91

  • Guest
Re: swiping
« Reply #11 on: October 04, 2012, 01:33:56 pm »
I did a code easier but not perfect. The jj's code is really perfect.

Code: [Select]
i added the recoil :
Code: [Select]
#include "DragonFireSDK.h"

int OnTouchArea(int id, int event, int x, int y);
int scroll=0,speed,recoil=0,ymove[10000],i,h=0,friction=0,container,containery,delta,containertwo;


void Friction()
{
if(speed>=40) //set the speed range 0 - 40 ,  -40 - 0
speed=40;
if(speed<=-40)
speed=-40;

//if(h==0)
//speed=-40;

h++;
 

  if(containery<-speed/2)                         
  {

ContainerSety(container,containery-=speed);  // move the container
if(h%1==0 && speed>0)  // decrease the speed, with h%1 you can set the speed of decreasing, for example h%1 means 30 time for second, h%2 15 time h%3 10 time
    speed-=1;
     if(h%1==0 && speed<0)
    speed+=1;
  }
  else          // if the position of the container is smaller than the speed, so you can't move it without go over the zero,
  { // start the recoil

  printf("recoil %d",speed);
  speed=5;

  if(containery<3 )
  speed=1;

  ContainerSety(container,containery-=speed);

  if(containery<=0 )  // stop friction
  {

  friction=0;
  }
 
  }
   
if(speed==0)   // stop friction
friction=0;
 }


void AppMain()

{

container=ContainerAdd(0,0,containery=0);
containertwo=ContainerAdd(0,0,0);
for(i=0;i<=6;i++)
ViewAdd(container,"Images/M.png",0,0+(490*i));
    TouchAdd(containertwo,0, 0, 320, 480, OnTouchArea, 0);
 
}

void frictionON()
{
friction=1;
}
 

int OnTouchArea(int id, int event, int x, int y)     //event: 1=down, 2=move, 3=up

{

if(event==1)
{
scroll=0;
delta=y-ContainerGety(container);
i=-1;
friction=0;
}
  if (event == 2)

  {   
  scroll=1;
  if(y-delta<=0)
  ContainerSety(container,containery=y-delta);

  i++;
  ymove[i]=y;
   
  if(containery >=-10 && containery<=30 &&  ymove[i]> ymove[i-1])   // if the cointainer is over the edge move it with a speed of 2, when release look at event==3
{
recoil=1;  // call recoil
ContainerSety(container,containery+=2);
}
  if( containery >=-10 && containery<=32 && ymove[i]<ymove[i-1])
{

ContainerSety(container,containery-=2);
}





    return 0;

  }

  if (event == 3)

  {   
  h=0;
                     //if the difference between the last and the previous shift is sufficiently great (then there
                         //was a quick movement ) , start the  Friction.
  if(scroll==1)   
    if( (ymove[i]>ymove[i-1] && ymove[i]-ymove[i-1]>3 )|| (ymove[i]<ymove[i-1] && ymove[i-1]-ymove[i]>3 ))
          frictionON();


   speed=ymove[i-1]-ymove[i];

   if(scroll==1)   // start recoil when you release and the recoil and scroll is  called
     if(recoil==1)
  frictionON();

    recoil=0;
scroll=0;
    return 0;

  }

}

 

void AppExit()

{

 

}

 

void OnTimer()

{
if(friction==1)
Friction();


}
« Last Edit: October 04, 2012, 01:36:50 pm by Nico91 »