Jump to content

ropes like in source engine ?


Slastraf
 Share

Recommended Posts

Cables provide a simple method for adding movement and complexity to a scene for a relatively low cost. Cables can be strung between moving objects and used as a visual representation between physical constraints (springs, length constraints, etc). Cables can also dynamically be shaken or broken by level events.

-> https://developer.valvesoftware.com/wiki/Cables_and_Ropes

 

How do you make a script that automatically connects two pivots with ropes ?

 

I taught of a billboard plane that is stretched so it looks like a rope with its textures,

and connected as childs to bones that are as same as ragdolls.

post-12189-0-21712800-1440086933.jpg

  • Upvote 1
Link to comment
Share on other sites

A pivot for each point in the rope and a sprite between them will do it. Ball joints can be used to connect the entities.

function Script:Start()
self.camera = Camera:Create()
self.camera:Move(0,0,-4)
local light = DirectionalLight:Create()
light:SetRotation(-35,35,0)
local parent = nil
local child = nil

parent = Model:Box()
parent:SetPosition(0,0,0)
parent:SetColor(1,1,1)
parent:SetMass(0)
parent:SetGravityMode(false)


child = Model:Box()
child:SetColor(0,0,1)
child:SetMass(1)
child:SetPosition(2,0,0)
child:AddTorque(0,0,0)

local sprite =Sprite:Create(child)
sprite:SetSize(5,.1)

local joint = Joint:Ball(0,0,0, child, parent)

end

so how do you make a sprite connect / or look like connected between two points ?

Also why is there added a force to the blue box ? i dont see it. When i put this script on a pivot in an empty scene the blue box begins to move

Link to comment
Share on other sites

Add the two positions and divide by two for the point between them.

 

Subtract one position from the other and normalize to get the vector between them.

 

Use Entity::AlignToVector to align the sprite. Check the sprite view modes to find one that makes it rotate around the axis you want. I would test with a scaled box first.

  • Upvote 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

function Script:Start()  
 self.camera = Camera:Create()
    self.camera:Move(0,0,-4)
    local light = DirectionalLight:Create()
    light:SetRotation(-35,35,0)
    self.parent = nil
       self.parent2 = nil
       self.positionbetween= nil
       self.sprite = nil
       self.child = nil
       self.child2 = nil
       self.allignvector = Vec3
       self.parent = Model:Box()
    self.parent:SetPosition(-2,0,0)
    self.parent:SetColor(1,1,1)
    self.parent:SetMass(0)
    self.parent:SetGravityMode(false)

       self.parent2 = Model:Box()
    self.parent2:SetPosition(2,0,0)
    self.parent2:SetColor(1,1,1)
    self.parent2:SetMass(0)
    self.parent2:SetGravityMode(false)

       self.positionbetween=Pivot:Create()


    self.child2 = Model:Box()
    self.child2:SetColor(0,0,1)
    self.child2:SetMass(1)
    self.child2:SetPosition(1,-1,0)


    self.child = Model:Box()
    self.child:SetColor(0,0,1)
    self.child:SetMass(1)
    self.child:SetPosition(-1,-1,0)


    self.sprite =Sprite:Create(self.child)
    self.sprite:SetSize(5,.1)

    local joint = Joint:Ball(-2,0,0, self.child, self.parent)
       local joint2 = Joint:Ball(0,0,0, self.child, self.child2)
       local joint2 = Joint:Ball(2,0,0, self.child2, self.parent2)
end
function Script:UpdatePhysics()
       self.positionbetween:SetPosition((self.parent:GetPosition()+self.child:GetPosition())/2)
       self.sprite:SetPosition(self.positionbetween:GetPosition())
       self.allignvector=self.parent:GetPosition()-self.child:GetPosition()
       self.sprite:AlignToVector(self.allignvector:Normalize(),2)
end

My Idea here was that there were two white boxes that are the start and the end of the cable, and two boxes inbetween them that are the cable itself. So what is happening here ?

I htink that the blue boxes itself are already kind of done, but my questions are:

What is wrong with the sprite?

How can I later optimize the script that I dont need to make all the cable parts by hand?-> for loop that makes as much boxes needed for a space between two white boxes?

Link to comment
Share on other sites

  • 1 month later...

Here's what a night of no sleep accomplishes.

 

So this is an almost complete dynamic rope creation system. You create 2 pivots, one start, one end. You attach this script to the start and drop the end entity on the end point box. It will then string joints between the 2 points. You can set the amount of slack there is in the rope.

 

To make it hang from the ceiling like a gymnasium rope or a broken power-line, just add mass to 1 of the ends.

 

There is a debug mode that will show the actual pivot/joint locations. The start is green and the end is blue. The rope goes from black to red as it reaches the end.

 

WHAT NEEDS TO BE DONE:

Sprites need to be added to make it look like an actual rope. The rope is invisible when not in debug mode so not much use yet...

 

 


 
--[[
Dynamic Rope Alpha
By Einlander
Description: Creates a rope between 2 points
Instructions: Create 2 pivots, attach this script to the start, and drop the end on the End point box, adjust settings and go.

TODO: Add sprites to actually draw the rope.
]]--

Script.EndEntity = nil -- entity "End Point"
Script.Sections = 8 -- int "Sections"
Script.Mass = 5 -- float "Mass"
Script.Slack = 0 -- float "Slack"
Script.Debug = false -- bool "Debug Mode"
Script.Info = 0 --choice "Info" "Dynamic Rope Alpha,VERSION .01, By Einlander"


function Script:Start()
	if self.EndEntity == nil then
		Debug:Error("End Point Entity Empty")
	end
	if self.Sections < 2 then
		Debug:Error("Sections must be 2 or greater")
	end
	
	-- Create boxes at start and finish
	if self.Debug == true then
		self.startpoint = Model:Sphere(3,self.entity)
		self.startpoint:SetScale(.1,.1,.1)
		self.startpoint:SetColor(0,1,0)

		self.endpoint = Model:Box(self.EndEntity)
		self.endpoint:SetScale(.1,.1,.1)
		self.endpoint:SetColor(0,0,1)
	else
		self.startpoint = Pivot:Create(self.entity)
		self.endpoint = Pivot:Create(self.EndEntity)
	end

	start1 = self.entity:GetPosition(true)
	end1 = self.EndEntity:GetPosition(true)

	-- place midpoints
	local i
	self.midpoints = {}
	local midpoint = self.entity
	table.insert(self.midpoints, midpoint)
	self.joints= {}

	for i = 1, self.Sections do
		if self.Debug == true then
			print(i/self.Sections)
		end
	-- Math formula from
	--http://stackoverflow.com/questions/2886092/finding-coordinates-of-a-point-between-two-points
	--https://archive.is/ME00H [ archive just in case]
		result = Vec3()
		result.x = (start1.x + (i/(self.Sections)) *(end1.x - start1.x))
		result.y = (start1.y + (i/(self.Sections)) *(end1.y - start1.y))
		if (i~= self.Sections) then
			if self:IsEven(i) == true then
				result.y = result.y + self.Slack
			else
				result.y = result.y + (self.Slack * -1 )
			end
		end

		result.z = (start1.z + (i/(self.Sections)) *(end1.z - start1.z))
		if self.Debug == true then
			local midpoint = Model:Box()
			midpoint:SetScale(.1,.1,.1)
			midpoint:SetColor((i/(self.Sections)),0,0)
			midpoint:SetPosition((result),true)
			midpoint:SetMass(self.Mass)
			table.insert(self.midpoints, midpoint)
		else
			local midpoint = Pivot:Create()
			midpoint:SetPosition((result),true)
			midpoint:SetMass(self.Mass)
			table.insert(self.midpoints, midpoint)
		end
	end
	local midpoint2 = self.EndEntity
	table.insert(self.midpoints, midpoint2)

	--set joint physics

	--start anchor
	local temppos = self.midpoints[1]:GetPosition(true)
	local tempjoint = Joint:Ball(temppos.x,temppos.y,temppos.z,self.midpoints[2] ,self.midpoints[1])
	tempjoint:DisableLimits()
	table.insert(self.joints, tempjoint)
	--middle points
	for i = 2, #self.midpoints do
		local temppos = self.midpoints[i-1]:GetPosition(true)
		local tempjoint = Joint:Ball(temppos.x,temppos.y,temppos.z, self.midpoints, self.midpoints[i-1])
		tempjoint:DisableLimits()
		table.insert(self.joints, tempjoint)
	end
	--end anchor
	local temppos = self.midpoints[#self.midpoints]:GetPosition(true)
	local tempjoint = Joint:Ball(temppos.x,temppos.y,temppos.z, self.midpoints[#self.midpoints],self.midpoints[#self.midpoints])
	tempjoint:DisableLimits()
	table.insert(self.joints, tempjoint)
end
 
function Script:IsEven(number)
	if (number % 2 == 0) then
		return true
	end
	return false
end

 

 

Q3XzScA.png

  • Upvote 3
Link to comment
Share on other sites

So I worked on this some more and ran into a few issues and some questions. Can sprites cast shadows? If no then it will cause problems with immersion. For example power lines outside in the day. I would expect those to have shadows. Next is you can't attach joint's to a mesh without bones as far as I know. So since we are generating the rope on the fly this is a no go. Finally slack in a rope. You can define the number of control points and how much slack they have from the next point. This is done by offsetting the control points by the slack amount on the z axis. This is a recipe for disaster.

 

My solution that I'm going explore something that I found n some unity forums. They simply create a mesh with vertexes at each joint location and deform it to match the joints location as it moves.

 

I have some family business to attend to so the next presentation may take a while.

  • Upvote 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...