Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Rope = {}
- Rope.__index = Rope
- --[[
- Basic Usage:
- local Rope = require 'rope'
- .load()
- Rope:load()
- Rope:createRope()
- Rope:attachToObject(body_to_attach{body, shape, fixture)
- .update()
- Rope:update()
- .draw()
- Rope:draw()
- Uses key q and e to handle rope length
- --]]
- function Rope:load()
- rope = {
- x = 300,
- y = 100,
- segmentLength = 5,
- maxLength = 5, -- length between joints
- segmentCount = 20,
- minLength = 4,
- attachedObject = nil
- }
- setmetatable(rope, Rope)
- return rope
- end
- local delay = 0.09 -- rope extension delay
- local timer = 0
- function Rope:update(dt)
- Rope:fixRopePosition()
- timer = timer + dt
- -- Add a segment
- if love.keyboard.isDown("e") and timer > delay then
- timer = 0
- print("Current rope length:" , #ropeSegments)
- rope.segmentCount = rope.segmentCount + 1
- -- Remove the first joint
- if not rope.mainJoint:isDestroyed() then
- rope.mainJoint:destroy()
- end
- -- Create new segment then attach to the object
- local newY = ropeSegments[1].body:getY() + 10
- local newX = ropeSegments[1].body:getX()
- newSegment = Rope:createRopeSegment(newX, newY)
- local joint = Rope:connectRopeSegment(ropeSegments[1].body, newSegment.body)
- table.insert(ropeSegments, 1, newSegment)
- table.insert(ropeJoints, 1, joint)
- if rope.attachedObject then
- rope.mainJoint = Rope:attachToObject(rope.attachedObject)
- end
- -- Remove a segment
- elseif love.keyboard.isDown("q") and timer > delay then
- timer = 0
- print("Current rope length:", #ropeSegments)
- rope.segmentCount = rope.segmentCount - 1
- if #ropeJoints == rope.minLength then return end
- -- Remove the first joint and segment then attach to the object
- joint_to_delete = table.remove(ropeJoints, 1)
- joint_to_delete:destroy()
- first = ropeSegments[1]
- first.body:destroy()
- table.remove(ropeSegments, 1)
- if rope.attachedObject then
- rope.mainJoint = Rope:attachToObject(rope.attachedObject)
- end
- end
- end
- function Rope:removeSegment()
- if ropeSegments > 1 then
- local joint_to_delete = table.remove(ropeJoints, #ropeJoints)
- joint_to_delete:destroy()
- local segment_to_delete = table.remove(ropeSegments, #ropeSegments)
- segment_to_delete.body:destroy()
- end
- end
- function Rope:unDockHookObject()
- if hook.dockJoint and hook.docking then
- hook.dockJoint:destroy()
- hook.docking = false
- hook.dockJoint = nil
- end
- end
- function Rope:dockHookObject()
- if hook.readyToDock then
- hook.dockJoint = love.physics.newRevoluteJoint(
- hook.body,
- hook.contactBody,
- hook.body:getX(),
- hook.body:getY(), false
- )
- hook.readyToDock = false
- hook.docking = true
- end
- end
- function Rope:mousepressed(key)
- if key == 1 then -- left click
- Rope:toggleHook()
- end
- end
- function Rope:toggleHook()
- if hook.docking then
- print("Undocking..")
- Rope:unDockHookObject()
- elseif hook.readyToDock then
- print("Docking Object to Rope Hook")
- Rope:dockHookObject()
- end
- end
- function Rope:createRopeSegment(x, y)
- newSegment = {}
- newSegment.body = love.physics.newBody(world, x, y, "dynamic")
- newSegment.shape = love.physics.newCircleShape(5)
- newSegment.fixture = love.physics.newFixture(newSegment.body, newSegment.shape, 0.2)
- newSegment.body:setLinearDamping(2)
- return newSegment
- end
- function Rope:connectRopeSegment(segmentA, segmentB)
- local joint = love.physics.newRopeJoint(
- segmentA, segmentB,
- segmentA:getX(), segmentA:getY(),
- segmentB:getX(), segmentB:getY(),
- rope.maxLength,
- false
- )
- return joint
- end
- function Rope:attachToObject(object)
- firstSegment = ropeSegments[1]
- newJoint = love.physics.newRopeJoint(
- firstSegment.body, object.body,
- firstSegment.body:getX(), firstSegment.body:getY(),
- object.body:getX(), object.body:getY()+10,
- 10
- )
- rope.attachedObject = object
- return newJoint
- end
- function Rope:createRope()
- ropeSegments = {}
- ropeJoints = {}
- -- create all the segments
- for segment = 1, rope.segmentCount do
- newSegment = Rope:createRopeSegment(rope.x, rope.y + (segment - 1) * rope.segmentLength)
- table.insert(ropeSegments, {
- body = newSegment.body,
- shape = newSegment.shape,
- fixture = newSegment.fixture
- })
- end
- -- connect all segments
- for segment = 1, #ropeSegments - 1 do
- local bodyA = ropeSegments[segment].body
- local bodyB = ropeSegments[segment + 1].body
- newJoint = Rope:connectRopeSegment(bodyA, bodyB)
- table.insert(ropeJoints, newJoint)
- end
- -- hook configuration
- hook = ropeSegments[#ropeSegments]
- hook.fixture:setUserData("hook")
- hook.docking = false -- is holding an object?
- hook.dockJoint = nil -- the joint
- hook.contactBody = nil -- the body that is holding or contacting
- end
- function Rope:fixRopePosition()
- for i = 1, #ropeSegments - 1 do
- local segmentA = ropeSegments[i]
- local segmentB = ropeSegments[i + 1]
- local dx = segmentB.body:getX() - segmentA.body:getX()
- local dy = segmentB.body:getY() - segmentA.body:getY()
- local distance = math.sqrt(dx * dx + dy * dy)
- local desiredDistance = 10
- local correctionFactor = 0.5
- if distance > desiredDistance then
- local offsetX = (dx / distance) * (distance - desiredDistance) * correctionFactor
- local offsetY = (dy / distance) * (distance - desiredDistance) * correctionFactor
- segmentB.body:setPosition(
- segmentB.body:getX() - offsetX,
- segmentB.body:getY() - offsetY
- )
- end
- end
- end
- function Rope:draw()
- drawSegments = true
- love.graphics.push()
- if drawSegments then
- for _, segment in ipairs(ropeSegments) do
- line = love.graphics.line(
- segment.body:getX(),
- segment.body:getX(),
- segment.body:getX(),
- segment.body:getX())
- love.graphics.setLineWidth(6)
- love.graphics.setLineStyle("smooth")
- end
- end
- love.graphics.pop()
- for _, joint in ipairs(ropeJoints) do
- love.graphics.line(joint:getAnchors())
- end
- end
- return Rope
Advertisement
Add Comment
Please, Sign In to add comment