Posted: 5th Mar 2021 3:59
For a few days I have been trying to make a rope system
at first I thought it was going to be easy, I could simply join several sprites in a row with a distance or weld joint, but apparently this is far from enough, i think it can be a little challenging and hard to get the result i want

I did a little research on the forum to see if anyone ever tried to do something like this, and it looks like there isn?t


this is the result I wanted
https://www.youtube.com/watch?v=rxNIsHSbMOg
https://youtu.be/YNhjAPZNzxI?t=39 (after 39 seconds)

this is what i have
https://streamable.com/kezh6x

+ Code Snippet
SetWindowTitle("Prjkt Hook")
SetErrorMode(2)
SetVirtualResolution(320, 180)
SetWindowSize(1280, 720, 0)
SetClearColor(151, 170, 204)
SetScissor(0, 0, 0, 0)
UseNewDefaultFonts(1)
SetDisplayAspect(180/320)
SetDefaultMinFilter(0)
SetDefaultMagFilter(0)
SetPhysicsScale(0.2)
SetPhysicsGravity(0, 276)
SetSyncRate(60, 1)
//SetPhysicsDebugOn()

ropeSpr as integer[]

box = CreateSprite(0)
SetSpritePhysicsOn(box, 1)
SetSpritePosition(box, 15, 15)
SetSpritePosition(box, 150, 80)

char = CreateSprite(0)
SetSpriteSize(char, 10, 20)
SetSpritePhysicsOn(char, 2)
SetSpritePhysicsCanRotate(char, 0)
SetSpritePosition(char, 50, 50)


global x = 0
global y = 0
global angle as float
global angle2 as float

do

	if GetRawMouseLeftPressed()
		// Get Direction
		x = GetPointerX()
		y = GetPointerY()
		dirx = x - GetSpriteXByOffset(char)
		diry =  GetSpriteY(char) - y
		angle = atanfull(dirx, diry)

		// If there is a rope, erase it to create another
		if ropeSpr.length > -1
			for i = 0 to ropeSpr.length
				DeleteSprite(ropeSpr[i])
			next i
			ropeSpr.length = -1
		endif

		//Make Rope with hook
		for i = 0 to 30
			spr = CreateSprite(0)
			setspritephysicsOn(spr, 2)
			SetSpritePhysicsMass(spr, 0)
			SetSpriteSize(spr, 5, 2)
			
			dirx = x - GetSpriteXByOffset(char)
			diry =  GetSpriteY(char) - y
			angle2 = atanfull(diry, dirx)
			SetSpriteAngle(spr, angle2)
			
			
			SetSpritePositionByOffset(spr, GetSpriteXByOffset(char), GetSpriteY(char))
			
			//SetSpriteShapeCircle(spr, 0, 0, 2)
			if ropeSpr.length = -1
				SetSpritePositionByOffset(spr, GetSpriteXByOffset(spr) + (1*sin(angle)), GetSpriteYByOffset(spr) + (1*cos(angle)))
				CreateDistanceJoint(spr, char, GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), GetSpriteXByOffset(char), GetSpriteY(char), 1)
			else
				SetSpritePositionByOffset(spr, GetSpriteXByOffset(ropeSpr[ropeSpr.length]) + (5*sin(angle)), GetSpriteYByOffset(ropeSpr[ropeSpr.length]) + (5*cos(angle)))
				//CreateDistanceJoint(ropeSpr[ropeSpr.length], spr, GetSpriteXByOffset(ropeSpr[ropeSpr.length]), GetSpriteYByOffset(ropeSpr[ropeSpr.length]), GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), 1)
				CreateWeldJoint(ropeSpr[ropeSpr.length], spr, GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), 1)
				//CreateRopeJoint(ropeSpr[ropeSpr.length], spr, GetSpriteXByOffset(ropeSpr[ropeSpr.length]), GetSpriteYByOffset(ropeSpr[ropeSpr.length]), GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), 8, 1)
				//CreateRevoluteJoint(ropeSpr[ropeSpr.length], spr, GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), 1)
			endif
			ropeSpr.insert(spr)

			// If this finds any object that can be grabbed, grab it now
			if GetSpriteCollision(ropeSpr[ropeSpr.length], box)
				CreateDistanceJoint(ropeSpr[ropeSpr.length], box, GetSpriteXByOffset(ropeSpr[ropeSpr.length]), GetSpriteYByOffset(ropeSpr[ropeSpr.length]), GetSpriteXByOffset(box), GetSpriteYByOffset(box), 0)
				exit
			endif
		next i

	endif

	if GetRawMouseRightPressed()
		if ropeSpr.length > -1
			for i = 0 to ropeSpr.length
				DeleteSprite(ropeSpr[i])
			next i
			ropeSpr.length = -1
		endif
	endif


	//Move
	if GetRawKeyState(KEY_D)
		if not GetSpritePhysicsVelocityX(char) >= 75
			SetSpritePhysicsVelocity(char, 70, GetSpritePhysicsVelocityY(char)) : SetSpriteFlip(char, 0, 0)
		endif
	elseif GetRawKeyState(KEY_A)
		if not GetSpritePhysicsVelocityX(char) =< -75
			SetSpritePhysicsVelocity(char, -70, GetSpritePhysicsVelocityY(char)) : SetSpriteFlip(char, 1, 0)
		endif
	endif

	//Jump
	if GetRawKeyPressed(KEY_W)
		SetSpritePhysicsImpulse(char, GetSpriteXByOffset(char),  GetSpriteYByOffset(char), 0, -1500)
	endif

    Print(ScreenFPS())
    Sync()
loop

#constant    KEY_D            68
#constant    KEY_W            87
#constant    KEY_A            65


I was currently following this tutorial.
https://www.emanueleferonato.com/2012/03/19/basic-box2d-rope-chain-2-1a-version/

I also read this one, which comes from the second video
http://antonior-software.blogspot.com/2016/12/box2d-ninja-rope.html


what do you think i should do better to get the desired effect?
Posted: 5th Mar 2021 4:58
SetJointDamping()

+ Code Snippet
SetWindowTitle("Prjkt Hook")
SetErrorMode(2)

SetWindowSize(1280, 720, 0)
SetVirtualResolution(1280/4, 720/4)
SetClearColor(151, 170, 204)
SetScissor(0, 0, 0, 0)
UseNewDefaultFonts(1)
SetDisplayAspect(180/320)
SetDefaultMinFilter(0)
SetDefaultMagFilter(0)
SetPhysicsScale(0.2)
SetPhysicsGravity(0, 276)
SetSyncRate(30, 0)
SetPhysicsDebugOn()

ropeSpr as integer[]


box = CreateSprite(0)
SetSpritePhysicsOn(box, 1)
SetSpriteSize(box, 15, 15)
SetSpritePosition(box, 150, 80)
SetSpriteGroup( box, 100 )

char = CreateSprite(0)
SetSpriteSize(char, 10, 10)
SetSpritePhysicsOn(char, 2)
SetSpritePhysicsCanRotate(char, 1)
SetSpritePosition(char, 50, 50)
SetSpriteGroup( char, 100 )


global x = 0
global y = 0
global angle as float
joint as integer

do

	if GetRawMouseLeftPressed()
		// Get Direction
		x = GetPointerX()
		y = GetPointerY()
		dirx = x - GetSpriteXByOffset(char)
		diry =  GetSpriteY(char) - y
		angle = atanfull(dirx, diry)

		// If there is a rope, erase it to create another
		if ropeSpr.length > -1
			for i = 0 to ropeSpr.length
				DeleteSprite(ropeSpr[i])
			next i
			ropeSpr.length = -1
		endif

		//Make Rope with hook
		for i = 0 to 30
			spr = CreateSprite(0)
			SetSpriteGroup( spr, 200	)
			setspritephysicsOn(spr, 2)
			SetSpritePhysicsMass(spr, 0)
			SetSpritePositionByOffset(spr, GetSpriteXByOffset(char), GetSpriteYByOffset(char))
			SetSpriteSize(spr, 3, 3)
			SetSpriteShapeCircle(spr, 0, 0, 2)
			if ropeSpr.length = -1
				SetSpritePositionByOffset(spr, GetSpriteXByOffset(spr) + (1*sin(angle)), GetSpriteYByOffset(spr) + (1*cos(angle)))
				CreateDistanceJoint(spr, char, GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), GetSpriteXByOffset(char), GetSpriteY(char), 0)
			else
				SetSpritePositionByOffset(spr, GetSpriteXByOffset(ropeSpr[ropeSpr.length]) + (10*sin(angle)), GetSpriteYByOffset(ropeSpr[ropeSpr.length]) + (10*cos(angle)))
				joint = CreateDistanceJoint(ropeSpr[ropeSpr.length], spr, GetSpriteXByOffset(ropeSpr[ropeSpr.length]), GetSpriteYByOffset(ropeSpr[ropeSpr.length]), GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), 0)
				SetJointDamping( joint, 10, 0 )
				//CreateWeldJoint(ropeSpr[ropeSpr.length], spr, GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), 0)
			endif
			ropeSpr.insert(spr)

			// If this finds any object that can be grabbed, grab it now
			if GetSpriteCollision(ropeSpr[ropeSpr.length], box)
				CreateDistanceJoint(ropeSpr[ropeSpr.length], box, GetSpriteXByOffset(ropeSpr[ropeSpr.length]), GetSpriteYByOffset(ropeSpr[ropeSpr.length]), GetSpriteXByOffset(box), GetSpriteYByOffset(box), 0)
				exit
			endif
		next i

	endif

	if GetRawMouseRightPressed()
		if ropeSpr.length > -1
			for i = 0 to ropeSpr.length
				DeleteSprite(ropeSpr[i])
			next i
			ropeSpr.length = -1
		endif
	endif


	//Move
	if GetRawKeyState(KEY_D)
		SetSpritePhysicsImpulse(char, GetSpriteXByOffset(char),  GetSpriteYByOffset(char), 100, 0)
	elseif GetRawKeyState(KEY_A)
		SetSpritePhysicsImpulse(char, GetSpriteXByOffset(char),  GetSpriteYByOffset(char), -100, 0)
	endif

	//Jump
	if GetRawKeyPressed(KEY_W)
		SetSpritePhysicsImpulse(char, GetSpriteXByOffset(char),  GetSpriteYByOffset(char), 0, -1500)
	endif

    Print(ScreenFPS())
    Sync()
loop

#constant    KEY_D            68
#constant    KEY_W            87
#constant    KEY_A            65
Posted: 5th Mar 2021 13:57
adding damping definitely produces a better effect

but the biggest problem is making the rope look like an entire foldable line, just like in the videos
my idea was to make small rectangles and join them together, but it doesn't seem to work very well
Posted: 6th Mar 2021 15:48


this still happens and i have an idea why

+ Code Snippet
SetWindowTitle("Prjkt Hook")
SetErrorMode(2)
SetVirtualResolution(320, 180)
SetWindowSize(1280, 720, 0)
SetClearColor(151, 170, 204)
SetScissor(0, 0, 0, 0)
UseNewDefaultFonts(1)
SetDisplayAspect(180/320)
SetDefaultMinFilter(0)
SetDefaultMagFilter(0)
SetPhysicsScale(0.2)
SetPhysicsGravity(0, 276)
SetSyncRate(60, 1)
SetPhysicsDebugOn()

ropeSpr as integer[]

box = CreateSprite(0)
SetSpritePhysicsOn(box, 1)
SetSpritePosition(box, 15, 15)
SetSpritePosition(box, 150, 80)

char = CreateSprite(0)
SetSpriteSize(char, 10, 20)
SetSpritePhysicsOn(char, 2)
SetSpritePhysicsCanRotate(char, 0)
SetSpritePosition(char, 50, 50)


global x = 0
global y = 0
global angle as float
global angle2 as float

do

	if GetRawMouseLeftPressed()
		// Get Direction
		x = GetPointerX()
		y = GetPointerY()
		dirx = x - GetSpriteXByOffset(char)
		diry =  GetSpriteY(char) - y
		angle = atanfull(dirx, diry)

		// If there is a rope, erase it to create another
		if ropeSpr.length > -1
			for i = 0 to ropeSpr.length
				DeleteSprite(ropeSpr[i])
			next i
			ropeSpr.length = -1
		endif

		//Make Rope with hook
		for i = 0 to 30
			spr = CreateSprite(0)
			setspritephysicsOn(spr, 2)
			SetSpritePhysicsMass(spr, 0)
			SetSpriteSize(spr, 2, 1)
			SetSpriteVisible(spr, 1)
			
			dirx = x - GetSpriteXByOffset(char)
			diry =  GetSpriteY(char) - y
			angle2 = atanfull(diry, dirx)
			SetSpriteAngle(spr, angle2)
			
			
			SetSpritePositionByOffset(spr, GetSpriteXByOffset(char), GetSpriteY(char))
			
			//SetSpriteShapeCircle(spr, 0, 0, 2)
			if ropeSpr.length = -1
				SetSpritePositionByOffset(spr, GetSpriteXByOffset(spr) + (1*sin(angle)), GetSpriteYByOffset(spr) + (1*cos(angle)))
				CreateDistanceJoint(spr, char, GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), GetSpriteXByOffset(char), GetSpriteY(char), 0)
				//CreateRevoluteJoint(char, spr, GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), 0)
			else
				SetSpritePositionByOffset(spr, GetSpriteXByOffset(ropeSpr[ropeSpr.length]) + (10*sin(angle)), GetSpriteYByOffset(ropeSpr[ropeSpr.length]) + (10*cos(angle)))
				j = CreateDistanceJoint(ropeSpr[ropeSpr.length], spr, GetSpriteXByOffset(ropeSpr[ropeSpr.length]), GetSpriteYByOffset(ropeSpr[ropeSpr.length]), GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), 1)
				//CreateWeldJoint(ropeSpr[ropeSpr.length], spr, GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), 1)
				//CreateRopeJoint(ropeSpr[ropeSpr.length], spr, GetSpriteXByOffset(ropeSpr[ropeSpr.length]), GetSpriteYByOffset(ropeSpr[ropeSpr.length]), GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), 3, 1)
				//CreateRevoluteJoint(ropeSpr[ropeSpr.length], spr, GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), 1)
				SetJointDamping( j, 10, 0)
				
			endif
			ropeSpr.insert(spr)

			// If this finds any object that can be grabbed, grab it now
			if GetSpriteCollision(ropeSpr[ropeSpr.length], box)
				CreateDistanceJoint(ropeSpr[ropeSpr.length], box, GetSpriteXByOffset(ropeSpr[ropeSpr.length]), GetSpriteYByOffset(ropeSpr[ropeSpr.length]), GetSpriteXByOffset(box), GetSpriteYByOffset(box), 0)
				//CreateRopeJoint(ropeSpr[ropeSpr.length], spr, GetSpriteXByOffset(ropeSpr[ropeSpr.length]), GetSpriteYByOffset(ropeSpr[ropeSpr.length]), GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), 3, 1)
				exit
			endif
		next i
		
		

	endif
	
	// Draw string
	for i = 0 to ropeSpr.length - 1
		c = MakeColor(255, 255, 255)
		DrawLine(GetSpriteXByOffset(ropeSpr[i]), GetSpriteYByOffset(ropeSpr[i]), GetSpriteXByOffset(ropeSpr[i + 1]), GetSpriteYByOffset(ropeSpr[i + 1]), c, c)
	next i
	

	if GetRawMouseRightPressed()
		if ropeSpr.length > -1
			for i = 0 to ropeSpr.length
				DeleteSprite(ropeSpr[i])
			next i
			ropeSpr.length = -1
		endif
	endif


	//Move
	if GetRawKeyState(KEY_D)  
		if not GetSpritePhysicsVelocityX(char) >= 75
			SetSpritePhysicsVelocity(char, 70, GetSpritePhysicsVelocityY(char)) : SetSpriteFlip(char, 0, 0)
		endif
	elseif GetRawKeyState(KEY_A)
		if not GetSpritePhysicsVelocityX(char) =< -75
			SetSpritePhysicsVelocity(char, -70, GetSpritePhysicsVelocityY(char)) : SetSpriteFlip(char, 1, 0)
		endif
	endif

	//Jump
	if GetRawKeyPressed(KEY_W)
		SetSpritePhysicsImpulse(char, GetSpriteXByOffset(char),  GetSpriteYByOffset(char), 0, -1500)
	endif

    Print(ScreenFPS())
    Sync()
loop

#constant    KEY_D            68
#constant    KEY_W            87
#constant    KEY_A            65
Posted: 6th Mar 2021 19:13
https://streamable.com/yq957m

I already have some improvements

+ Code Snippet
SetWindowTitle("Prjkt Hook")
SetErrorMode(2)
SetVirtualResolution(320, 180)
SetWindowSize(1280, 720, 0)
SetClearColor(151, 170, 204)
SetScissor(0, 0, 0, 0)
UseNewDefaultFonts(1)
SetDisplayAspect(180/320)
SetDefaultMinFilter(0)
SetDefaultMagFilter(0)
SetPhysicsScale(0.2)
SetPhysicsGravity(0, 276)
SetSyncRate(60, 1)
//SetPhysicsDebugOn()

ropeSpr as integer[]

box = CreateSprite(0)
SetSpritePhysicsOn(box, 1)
SetSpritePosition(box, 15, 15)
SetSpritePosition(box, 150, 80)

char = CreateSprite(0)
SetSpriteSize(char, 10, 20)
SetSpritePhysicsOn(char, 2)
SetSpritePhysicsCanRotate(char, 0)
SetSpritePosition(char, 50, 50)


global x = 0
global y = 0
global angle as float
global angle2 as float

do

	if GetRawMouseLeftPressed()
		// Get Direction
		x = GetPointerX()
		y = GetPointerY()
		dirx = x - GetSpriteXByOffset(char)
		diry =  GetSpriteY(char) - y
		angle = atanfull(dirx, diry)

		// If there is a rope, erase it to create another
		if ropeSpr.length > -1
			for i = 0 to ropeSpr.length
				DeleteSprite(ropeSpr[i])
			next i
			ropeSpr.length = -1
		endif

		//Make Rope with hook
		for i = 0 to 50
			spr = CreateSprite(0)
			setspritephysicsOn(spr, 2)
			SetSpritePhysicsMass(spr, 0)
			SetSpriteSize(spr, 2, 2)
			SetSpriteVisible(spr, 0)
			
			/*
			dirx = x - GetSpriteXByOffset(char)
			diry =  GetSpriteY(char) - y
			angle2 = atanfull(diry, dirx)
			SetSpriteAngle(spr, angle2)
			*/
			
			SetSpritePositionByOffset(spr, GetSpriteXByOffset(char), GetSpriteY(char))
			
			//SetSpriteShapeCircle(spr, 0, 0, 2)
			if ropeSpr.length = -1
				SetSpritePositionByOffset(spr, GetSpriteXByOffset(spr) + (1*sin(angle)), GetSpriteYByOffset(spr) + (1*cos(angle)))
				CreateDistanceJoint(spr, char, GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), GetSpriteXByOffset(char), GetSpriteY(char), 0)
				//CreateRevoluteJoint(char, spr, GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), 0)
			else
				SetSpritePositionByOffset(spr, GetSpriteXByOffset(ropeSpr[ropeSpr.length]) + (2*sin(angle)), GetSpriteYByOffset(ropeSpr[ropeSpr.length]) + (2*cos(angle)))
				//j = CreateDistanceJoint(ropeSpr[ropeSpr.length], spr, GetSpriteXByOffset(ropeSpr[ropeSpr.length]), GetSpriteYByOffset(ropeSpr[ropeSpr.length]), GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), 1)
				//CreateWeldJoint(ropeSpr[ropeSpr.length], spr, GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), 1)
				CreateRopeJoint(ropeSpr[ropeSpr.length], spr, GetSpriteXByOffset(ropeSpr[ropeSpr.length]), GetSpriteYByOffset(ropeSpr[ropeSpr.length]), GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), 3, 1)
				//CreateRevoluteJoint(ropeSpr[ropeSpr.length], spr, GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), 1)
				//SetJointDamping( j, 10, 0)
				
			endif
			ropeSpr.insert(spr)

			// If this finds any object that can be grabbed, grab it now
			if GetSpriteCollision(ropeSpr[ropeSpr.length], box)
				CreateDistanceJoint(ropeSpr[ropeSpr.length], box, GetSpriteXByOffset(ropeSpr[ropeSpr.length]), GetSpriteYByOffset(ropeSpr[ropeSpr.length]), GetSpriteXByOffset(box), GetSpriteYByOffset(box), 0)
				//CreateRopeJoint(ropeSpr[ropeSpr.length], spr, GetSpriteXByOffset(ropeSpr[ropeSpr.length]), GetSpriteYByOffset(ropeSpr[ropeSpr.length]), GetSpriteXByOffset(spr), GetSpriteYByOffset(spr), 3, 1)
				exit
			endif
		next i
		
		

	endif
	
	// Draw string
	for i = 0 to ropeSpr.length - 1
		c = MakeColor(255, 255, 255)
		DrawLine(GetSpriteXByOffset(ropeSpr[i]), GetSpriteYByOffset(ropeSpr[i]), GetSpriteXByOffset(ropeSpr[i + 1]), GetSpriteYByOffset(ropeSpr[i + 1]), c, c)
	next i
	

	if GetRawMouseRightPressed()
		if ropeSpr.length > -1
			for i = 0 to ropeSpr.length
				DeleteSprite(ropeSpr[i])
			next i
			ropeSpr.length = -1
		endif
	endif


	//Move
	if GetRawKeyPressed(KEY_D)  
		if not GetSpritePhysicsVelocityX(char) >= 10
			SetSpritePhysicsVelocity(char, 70, GetSpritePhysicsVelocityY(char)) : SetSpriteFlip(char, 0, 0)
		endif
	elseif GetRawKeyPressed(KEY_A)
		if not GetSpritePhysicsVelocityX(char) =< -10
			SetSpritePhysicsVelocity(char, -70, GetSpritePhysicsVelocityY(char)) : SetSpriteFlip(char, 1, 0)
		endif
	endif

	//Jump
	if GetRawKeyPressed(KEY_W)
		SetSpritePhysicsImpulse(char, GetSpriteXByOffset(char),  GetSpriteYByOffset(char), 0, -1500)
	endif

    Print(ScreenFPS())
    Sync()
loop

#constant    KEY_D            68
#constant    KEY_W            87
#constant    KEY_A            65