Beginner's Guide: How to Click and Drag Objects in Your P5js Sketch
Vložit
- čas přidán 5. 08. 2024
- Code from video: editor.p5js.org/BarneyCodes/s...
Having the ability to drag and drop/click and drag in your P5js projects is a really great way to add interactivity and it's simple to do! It can be used in a variety of different contexts from interacting with art to dragging items around in a game.
Follow me:
Support the channel: www.youtube.com/@BarneyCodes/...
Twitter: / barneycodes
Reddit: / barneycodes
0:00 Generating random points to drag
1:02 Drawing the points on the screen
1:24 Dragging things that aren't red points
1:38 Detecting if we've clicked an object
2:50 Backwards through the points array??
3:30 Setting the current drag point
4:02 Mouse drag and release
5:05 Limitations and possible optimisations
5:56 Final product
#creativecoding #p5js #javascript
Hey, hope you enjoyed the video!
I’m curious, what project are you using click and drag for? Let me know!
Awesome video! I would definitely love a follow-up with quadtrees for more complex structures to drag-and-drop👍
Thank you! I've got a few other videos planned, but I'll add quadtree drag and drop to the queue!
Super helpful. Thanks a lot!
No worries, glad it helped!
Your description for line 26 may be suprifulus. The visiting order in reverse would help if the circles are randomly drawn on top of each other. Which may occur.
I think it just helps to avoid visual weirdness if you click on circles that are overlapping. Going through the array backwards just means that we'll select the circle that's "on top" (drawn last)
great video and great channel!
Thanks, glad you enjoyed it!
I have to make that user can with mouse draw shapes (circle, triangle and rectangle) and also drag them... I have a problem how to drag them, but i hope this video will helps me 🙃
Sounds like an interesting project! If you have any questions feel free to ask, and good luck!
cool, but in this case a better approach would be in OOP, and yes we want to see the quad Tree please ☺
I agree that for more complex scenarios, you're probably better off using a Draggable" interface and implementing an "isClicked" method, but I think for a lot of use cases (especially in simple sketches) this will do the trick. Great suggestion though, I'll have to look more into OOP in JavaScript.
QuadTree drag and drop has been added to the video queue! I've got some other QuadTree ideas too so stay tuned for that
This is very cool - I didn't realize I could use a vector to randomize initial starting locations of different shapes. I'm creating a shape matching game and was able to use this code to generate different shapes of different colors into the randomized vector locations. However, when I click the shape to drag it the console re-randomizes vector locations. Also - I have to figure out the trick to move around my triangle.
Did you notice that the randomized vector locations reset when clicking?
Glad the video was helpful!
It sounds like you might be randomising the locations of your objects inside the mousePressed event or something similar? It sounds like you only want them randomised right at the start (inside the setup function).
For clicking on a triangle, take a look at this article: www.jeffreythompson.org/collision-detection/tri-point.php
That website is a treasure trove of all sorts of collision algorithms so if you have any other shapes you're wanting to click and drag, I'm sure you can find it on there!
Good luck, and let me know if you have any more questions!
@@BarneyCodes Oh hey, Barney! I've re-written this code several times for my little game. I think I figured out a possible bug with your code- it seems to swap one of your circles with the next one you click. When using different shapes this is more apparent. When I clicked a shape to move it, the shapes would swap but be in the same location spots as X and Y defines.
Anyhow - I do still have an issue with my code. I ended up making two arrays for X and Y coordinate for each shape because I have to match each shape to a specific location. Comparing the proximity of the X and Y with the specific location X and Y get's me to completion.
However, because of this I can't cycle through my array and change the indexes. My circle is at index 0 for all my arrays, my square at 1, and so on.
The code lags something fierce. It's painful. Sometimes the code sees that my mouse is over the shape and sometimes it does not. Sometimes my boolean for mouseClicked() confirms false but when I go to click on a different shape, the previous shape moueClicked boolean reads true and a shape from across the page engages with my mouse. Do you have a different dragging method idea so that this code isn't painful to play with in the game setting?
Last random thing I am trying to figure out - When all my shapes are in specific locations I want the game to auto-restart with new randomly generated locations. Same idea as if I were to click stop and play again. I am struggling to say the least.
Ahhh so I think what is going on with that is I move the point that is being dragged to the end of the points array (this is so that the item you're dragging is always displayed "on top" of the other items, ie it's the last thing drawn so it's not obscured). This will mean that your array of target points will be out of sync with the drag points!
To fix this, you can either move the items in your target points array the same way that we move the drag points, or the more simple option would be to stop the points from changing location in the array at all.
To do this, you'll need to remove these lines from the mousePressed() function:
dragPoint = points.splice(i, 1)[0];
points.push(dragPoint);
And replace them with:
dragPoint = points[i];
This way your two arrays will stay in sync
To check for the end game condition, it sounds like you could loop through all of the points and their target locations and if all of them are close enough, then the game is won!
This would look something like this (you'll have to adapt slightly to fit your code):
function checkGameWon() {
const minDist = 10;
for(let i = 0; i < points.length; i ++) {
// The distance is too great between points
// so the game is not over yet!
if(points[i].dist(targetPoints.[i]) > minDist) {
return false;
}
}
// All points are close enough, the game is won!
return true;
}
Hopefully that helps!
What if for example you want to collect them in a box. How can they disappear?
Great question! The code in the description has a "mouseInBox" function which you could use for this! What you'll need to do is, in the mouseReleased function, instead of simply setting the dragPoint to null, check if the mouse is inside your box and, if it is, remove the point you're dragging from the points array. This would look something like:
if(dragPoint && mouseInBox(boxX, boxY, boxW, boxH)) { // if we are dragging a point and inside our box
points.splice(points.indexOf(dragPoint), 1); // remove dragPoint from points array
dragPoint = null; // clear the point we're dragging
}
Hope that helps, let me know if you have any issues!
Is there a way to use a sprite in place of the circle?
Absolutely! If you have a look at the code linked in the description there are classes for TextDragObjects and ImageDragObjects at the bottom.
The way to use the image drag object is very similar to the text one (which is shown in the code but commented out). For the ImageDragObject, the constructor takes an x and y location, as well as an image, which can be loaded using the loadImage() method in the preload() function.
You can read more about loading images here: p5js.org/reference/#/p5/loadImage
Hope that helps, let me know if you have any questions!
How could I use this with text?
Great question! I've just updated the code (still the same link as in the description) to have a TextDragObject and an ImageDragObject (scroll down to the bottom of the file to see these objects, they're pretty straight forward, just needing an x & y location as well as any data they need, ie a string or an image).
In the setup, draw, and mousePressed functions you'll have to comment out the lines under the // Point comment and uncomment the lines under the // Text comment.
I've also added a "mouseInBox" function to properly collide with a rectangular shape.
I hope that helps, and if you've got any more questions, feel free to ask!
@@BarneyCodes thanks a lot, will test asap and get back to you. :)
No worries, hope it works for you!
@@BarneyCodes is there a way to make it work in phones?
I think this should work on a phone, I just did some testing then and it does seem to work (kinda..). I think the main issue is that the online editor isn't really mobile friendly, when I was dragging the points I was also scrolling the entire page which made it a bit glitchy. Are you able to use touch at all?
There's also a bit of documentation on touch events, touchStarted, touchMoved, and touchEnded (p5js.org/reference/#/p5/touchStarted), but the touch events all default to the mousePressed, mouseDragged, and mouseReleased functions respectively if the touch equivalents aren't defined.