Comments

Log in with itch.io to leave a comment.

As mentioned by others, this is an excellent example. Three things though:

1. I tried attaching the last vertex of rope1 to an instance of oDrag, just like how the example attaches the first vertex of rope1 to an oDrag intances. While this works, I note the last vertex is not able to properly connect to the other oDrag instance - there is always a gap, unless both oDrag instances are very close to each other:



I tried fixing this by changing the stiffness, segments, and segments length, but I keep getting a gap. What I was hoping for was that the last vertex of the rope is connected to oDrag exactly like the first vertex. You can see this below, where green is for the first vertex, and red is for the last vertex: 



Is this just default behavior, or is it possible to make the last vertex's connection be just like the first vertex's?

2. Any stiffness under 1 (0.9 for example), causes the rope to droop drastically. Not sure if this is a bug (interestingly, when the rope droops like this, the last vertex seems to attach the way I want it to as I mentioned in point 1)?



3. Lets say I wanted to make something like a fishing line where the user is able to reel-in/retract the rope. Is there a way to do this? My assumption was that the rope properties, namely the number of segments and stiffness, would need to be changed, but those properties are called for creating the rope only, not to update it. Do you have a recommended approach? 

Thanks for any input you can provide!

(4 edits) (+1)

(Seems like I can't upload screenshots for some reason.. :c)

Problem 1:

The verlet system works by having a list of vertices and a list of sticks. Every update, we iterate through the list of vertices from the start, forcing the sticks to their original length. Since we're starting at the first vertex, its position will always be correct, but the rope will drag away from the last point as a result. One way to solve that might be to rewrite how we iterate through the list every update. So update the first vertex, then the last, then the second, second from last, etc. until we reach the center. I'm not sure if this will result in other unwanted behaviour though.

I'd manipulate this for loop and see what happens:

verletFunctions line 299:
for (var i = 0; i < stickAmount; i++) {
    currentStick = stickList[| i]; 

A simple and dirty "fix" would be to rewrite the draw function and draw another line from the last vertex to the point where it is supposed to be attached. It won't be perfect but it will look like it's attached.

verletFunctions line 497:
draw_vertex(currentStick.v2.x + lengthdir_x(wHalf, stickDir - 90), currentStick.v2.y + lengthdir_y(wHalf, stickDir - 90));
draw_vertex(currentStick.v2.x + lengthdir_x(wHalf, stickDir + 90), currentStick.v2.y + lengthdir_y(wHalf, stickDir + 90));
// Draw another line here
draw_primitive_end(); 

Problem 2:

When the verlet system updates, the "stiffness" is simply the amount of times we do the update. The more updates per frame, the more correct the simulation will be, but the more performace we draw.

verletFunctions line 294:
repeat (stiffness) {
    #region Update sticks
    #region Update vertices
} 

A stiffness value below 1 would therefore result in errors.

Problem 3:

That will be a difficult one.. I didn't think of a use case like this.

The sticks already have an individual length value. To retract the rope, you probably want to create some function that retracts the rope by one pixel. It would decrease the length of the first stick by 1 as long as the stick's length is greater than 1. A length of 0 would probably create errors. Otherwise delete the first stick and the first vertex, then continue with the next stick until the rope is gone.

New function for the rope group:
function retractRopeByOnePixel() {
    if (<amount of vertices> > 2 AND <amount of sticks> > 1) {
        var currentStick = <first stick>
        if (currentStick.length > 1) {
            currentStick.length --;
        } else {
            <delete first stick>
            <delete first vertex>
        }
    } else {
        return false;
    }
    return true;
} 

Something like that maybe. You'll need to figure out where to get the amount of ropes/sticks and where to delete them. Call the function until it returns false, then delete the rope.

Hope I could help :)

Thanks for the reply! I'll have to keep working with it to get a better grasp of it, but the info you've provided is much appreciated!

Great plugin! Is there any way to stop the textured rope from stretching the image (instead just spacing out the individual sprites)? I was trying to use a rope in the style of the example chain, but with the two objects moving quite far from each other, the texture can get very stretched. I've done some looking around in the functions and it seems like it could be quite a difficult change. Either way, great work!

Thank you! I think I added an option to change the 'stiffness' of the verlet system so it doesn't stretch so much. You should be able to manipulate it either in the rope function or the function which sets up the verlet system. But do note that increasing the stiffness draws a lot of performance, as this basically multiplies how many times per frame the whole physics simulation gets updated.

Thanks for the quick response! I did mess around with stiffness, but I realized I was straying to far from the intended purpose of verlets. So instead I just break the verlet chain and replace it with a line renderer in some edge cases lol

Whatever works :D Glad you found a workaround!

Works great, great work. One question, is there any way to adjust the depth?

Thank you :) The verlet system is drawn using the VerletSystem() struct's Draw() function. The depth would be equal to the object which calls the Draw() function. By changing either that object's layer, or where you call the Draw() function (depending on your case), you can control the depth at which it is drawn. There is however no functionality to sort different verlet groups within the same verlet system after they are created. Groups within a system will be drawn in the order in which you added them with the VerletGroupCreateRope() or other functions. If you need to change them dynamically, you could either create multiple verlet systems, or write a new function inside the VerletSystem() constructor, which rearanges the "verletGroups" ds_list. Hope this helps!

(+1)

Thank you for the quick and detailed answer! It works perfectly now. I didn't even think of that :D