We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › Dragging an image so that it locks into place.
Page Index Toggle Pages: 1
Dragging an image so that it locks into place. (Read 1116 times)
Dragging an image so that it locks into place.
Oct 28th, 2009, 5:50am
 
Hi

We're trying to create a program which will allow the user to click and drag multiple images separately and then drag them into a box onto the screen.

For example like a word game where the user is presented with different images of words and then they have to click and drag them into place to create a sentence on the screen.

Code:

Sprite[] sprites;      

int bx=500;
int by=600;

int s_size=30;
boolean spritesDragging;

PImage b;

void setup()
{
 size(798, 760);
 sprites = new Sprite[7];
 for(int i = 0; i < sprites.length; i++)
 {
   sprites[i] = new Sprite(loadImage(i + ".png"),s_size,random(bx), random(by));
 }
}


void draw()
{
   
   b = loadImage("EiffelTower.jpg");
   background(b);
   boolean bDragging = false;
   
   
   for (int i = 0; i < sprites.length; i++)
   {
// Check if the user tries to drag it
sprites[i].Update(spritesDragging);
// Ah, this one is indeed dragged!
if (sprites[i].IsDragged())
{
// We will remember a dragging is being done
bDragging = true;
// And move it to mouse position
sprites[i].Move();
}
// In all case, we redraw the sprite
sprites[i].Draw();
               }
    spritesDragging = bDragging;
}




class Sprite
{
 float x;
 float y;
 PImage img;
 float SpriteSize;
 int i;
 private boolean m_bIsHovered, m_bDragged;
 private float m_clickDX, m_clickDY;
 

 Sprite(PImage img, int SpriteSize,float x,float y)
 {
   this.x = x;
   this.y = y;
   this.img = img;
   
   this.SpriteSize=SpriteSize;
   
 }
 
 
 void Update(boolean bAlreadyDragging)
 {
     // Check if mouse is over the handle
m_bIsHovered = dist(mouseX, mouseY, x, y) <= SpriteSize ;

if (!bAlreadyDragging && mousePressed && mouseButton == LEFT && m_bIsHovered)
{
        // We record the state
m_bDragged = true;
       
m_clickDX = mouseX - x;
m_clickDY = mouseY - y;
}
     // If mouse isn't pressed
if (!mousePressed)
{
        // Any possible dragging is stopped
m_bDragged = false;
}
  }
 
 

boolean IsDragged()
{
return m_bDragged;
}


   void Move()
   {
if (m_bDragged)
{
x = mouseX - m_clickDX;
y = mouseY - m_clickDY;
}
   }
   
   void Draw()
   {
     image(img, x, y);
   }
   
 
 
}


Thanks in advance.
Re: Dragging an image so that it locks into place.
Reply #1 - Oct 28th, 2009, 6:52am
 
No code to give right now, but if I've understood correctly one approach would be to check the position of the image on mouseRelease and if it is within a certain distance of the 'target' use easing to animate it moving into place.

I remember writing a drag and drop application in Flash - quite a while back now - which basically took this approach and it worked well and depending on your use case you can make the 'target' as large or small as necessary.
Re: Dragging an image so that it locks into place.
Reply #2 - Oct 28th, 2009, 8:44am
 
So... what is the question?
Re: Dragging an image so that it locks into place.
Reply #3 - Nov 1st, 2009, 4:23pm
 
We actually managed to edit the code so that it draws an array of box on the right side of the screen. The problem is that it only locks an image when an image is over the last box.

Code:

Sprite[] sprites;      

Box[] boxes;

int bx=500;
int by=600;

int s_size=150;
boolean spritesDragging;

int boxX=640;
int boxY=100;

PImage b;

void setup()
{
 size(798, 760);
 
 boxes= new Box[7];
 
 sprites = new Sprite[7];
 
 
 for(int i = 0; i < sprites.length; i++)
 {
   sprites[i] = new Sprite(loadImage(i + ".png"),s_size,random(bx), random(by));
   
 }
 
 for(int i =0; i< boxes.length; i++)
 {
   boxY+=60;
   boxes[i] = new Box(boxX, boxY, 140, 30);
 }
}


void draw()
{
   
   b = loadImage("EiffelTower.jpg");
   background(b);
   boolean bDragging = false;
   
   //rectangle x, y, w , h
   //rect(boxX, boxY, 140, 30);
   
   
     for (int i=0; i <boxes.length; i++)
     {
       boxes[i].Draw();
     }
   
   for (int i = 0; i < sprites.length; i++)
   {
               
// Check if the user tries to drag it
sprites[i].Update(spritesDragging);
// Ah, this one is indeed dragged!
if (sprites[i].IsDragged())
{
// We will remember a dragging is being done
bDragging = true;
// And move it to mouse position
sprites[i].Move();
}
// In all case, we redraw the sprite

               sprites[i].Draw();
               
           
     }
   
    spritesDragging = bDragging;
   
}




class Sprite
{
 float x;
 float y;
 PImage img;
 float SpriteSize;
 int i;
 private boolean m_bIsHovered, m_bDragged;
 private float m_clickDX, m_clickDY;
 

 Sprite(PImage img, int SpriteSize,float x,float y)
 {
   this.x = x;
   this.y = y;
   this.img = img;
   
   this.SpriteSize=SpriteSize;
   
 }
 
 
 void Update(boolean bAlreadyDragging)
 {
     // Check if mouse is over the sprite
m_bIsHovered = mouseX > x && mouseX < x + SpriteSize && mouseY > y && mouseY < y + SpriteSize/10;

if (!bAlreadyDragging && mousePressed && mouseButton == LEFT && m_bIsHovered)
{
        // We record the state
m_bDragged = true;
       
m_clickDX = mouseX - x;
m_clickDY = mouseY - y;
}
     // If mouse isn't pressed
if (!mousePressed)
{
        // Any possible dragging is stopped
m_bDragged = false;
}

               //method for locking image in place
               if(x> boxX && x< (boxX+60) &&y <(boxY+10) && y >boxY)
               {
                   m_bDragged = false;
}
                 
  }
 
 

boolean IsDragged()
{
return m_bDragged;
}


   void Move()
   {
if (m_bDragged)
{
x = mouseX - m_clickDX;
y = mouseY - m_clickDY;
}
   }
   
   void Draw()
   {
     image(img, x, y);
     
   }
   
 
 
}


class Box
{
 float x;
 float y;
 
 float h;
 float w;
 
 Box(float x,float y, float h, float w)
 {
   this.x = x;
   this.y = y;
   this.h= h;
   this.w= w;
 }
 
  void Draw()
   {
     rect(x,y, h, w);
     
   }
}


I believe this is because we have a for loop which increases the boxY value so then boolean which stops the dragging of an image is only recognized at the bottom box as boxY has been updated to this bottom position.

Code:

//method for locking image in place
               if(x> boxX && x< (boxX+60) &&y <(boxY+10) && y >boxY)
               {
                   m_bDragged = false;
}


Any suggestions on how to edit this?

Thanks again.
Re: Dragging an image so that it locks into place.
Reply #4 - Nov 2nd, 2009, 3:40am
 
You've correctly identified the problem.

A question in response:  Since each box is an object and has x and y properties and the box objects are stored in an array - why do you check against the 'static' variables of BoxX and BoxY?

i.e. you need to iterate over your array of boxes and check the current sprite's x and y coordinates against each of the boxes in turn...
Re: Dragging an image so that it locks into place.
Reply #5 - Nov 2nd, 2009, 5:22am
 
Well we created the BoxX and BoxY values to be static, because we want to have a fixed array of boxes on the right side of the screen. With one displayed one after another.

"i.e. you need to iterate over your array of boxes and check the current sprite's x and y coordinates against each of the boxes in turn."

Could you elaborate a bit more on what you mean please?
Re: Dragging an image so that it locks into place.
Reply #6 - Nov 2nd, 2009, 6:46am
 
My point was that there's no need to check against those static variables when the boxes' positions are stored in the box objects (as are in fact their dimensions):

Code:
for(int i =0; i< boxes.length; i++)  {
   //method for locking image in place
   if(x> boxes[i].x && x< (boxes[i].x+boxes[i].w) &&y <(boxes[i].y+boxes[i].h) && y >boxes[i].y) {
       m_bDragged = false;
       
}
 }


To improve performance I'd be tempted to only run this check on mouseRelease rather than every frame; though obviously that may not match your needs...
Page Index Toggle Pages: 1