Flying Dutchmen Pirate Ship with Animated Anchor Physics, Door, Alpha-Channel [Open Source] Boat Library

Flying Dutchmen Pirate Ship Boat
create.roblox.com/store/asset/16433707385

image
image


image
Boat with Retractable Anchor
Here is the code that powers the boat!
The main goal was to make a boat template that can be easily modified :slight_smile:
This was done by requiring the only object to make the boat is the Buoy mainly. But I added the anchor because I really wanted it. :slight_smile: I learned a lot about rope constraints and maybe next Iโ€™ll make a fishing pole!

local console = script.Parent
local boat = console.Parent
local Seat = console.Parent.VehicleSeat
 --.VehicleSeat
local params = RaycastParams.new()
params.FilterDescendantsInstances = {workspace.Terrain}
params.FilterType = Enum.RaycastFilterType.Whitelist
local AngularVelocity = script.AngularVelocity
local LinearVelocity = script.LinearVelocity
--// Sail the Boat
local CurA = 1
local MaxA = 12
local Boater = boat["Buoy"]
local function unachor(bool)
    for i, v in boat:GetDescendants() do
        if v:IsA("BasePart") then
            v.Anchored = bool
            v.AssemblyLinearVelocity = Vector3.new(0, 0, 0)
            --Anchor.AssemblyLinearVelocity=Vector3.new(0,0,0)
            v.AssemblyAngularVelocity = Vector3.new(0, 0, 0)
        end
    end
end
unachor(true)
local floatmaterial = Enum.Material.Water
local eposoffset = Vector3.new(0, 15, 0)
local sposoffset = Vector3.new(0, 5, 0)
--local eposoffset= Vector3.new(0, 0, -(Boater.Size.Z/2))
local function CheckFront()
    local BoaterP = Boater.CFrame:ToWorldSpace(CFrame.new(Vector3.new(0, 0, -Boater.Size.Z / 2)))
    local seatpos = BoaterP.Position - Vector3.new(0, 5, 0)
    --local sPos = BoaterP:ToWorldSpace(sposoffset).Position
    local ePos = BoaterP:ToWorldSpace(CFrame.new(eposoffset)).Position
    local ray = workspace:Raycast(seatpos, ePos - seatpos, params)
    if ray and ray.Material == floatmaterial then
        --print("Check Front Passed")
        return true
    end
    --print("Check Front Failed")
    return nil
end

-- Get the rope constraint object
local rope = boat.Winch.Winch.RopeConstraint
local Anchor = boat.Winch["Metal Anchor"]
-- Store the original length of the rope
local originalLength = rope.Length

-- Define a function to check the tension of the rope
local function checkTension()
    -- Get the current length of the rope
    local currentLength = rope.Length

    -- Get the current distance between the attachments
    local currentDistance =
        ((Anchor.CFrame:ToWorldSpace(Anchor.Attachment1.CFrame)).Position - rope.Parent.Position).Magnitude + 1

    --local currentDistance = ((Anchor.CFrame).Position-rope.Parent.Position).Magnitude

    -- Compare the current length with the original length
    if currentLength <= currentDistance then
        -- The rope is stretched and has tension
        return true
    else
        -- The rope is slack or coiled and has no tension
        --print("The rope has no tension")
    end

    -- Compare the current distance with the current length
    if currentDistance < currentLength then
        -- The rope is coiled and has extra length
        --  print("The rope is coiled")
    elseif currentDistance > currentLength then
        -- The rope is slack and has less length
        -- print("The rope is slack")
    else
        -- The rope is neither coiled nor slack and has the same length as the distance
        -- print("The rope is neither coiled nor slack")
    end
    return false
end
-- Define a function that takes an object and a density as parameters
local function setCustomPhysicalProperties(object, density)
    -- Check if the object is a valid BasePart
    if object:IsA("BasePart") then
        -- Get the current physical properties of the object
        local currentProperties = object.CustomPhysicalProperties

        -- Create a new PhysicalProperties object with the given density and the same friction, elasticity, frictionWeight, and elasticityWeight as the current properties
        local newProperties =
            PhysicalProperties.new(
            density,
            currentProperties.Friction,
            currentProperties.Elasticity,
            currentProperties.FrictionWeight,
            currentProperties.ElasticityWeight
        )

        -- Set the CustomPhysicalProperties of the object to the new properties
        object.CustomPhysicalProperties = newProperties
    else
        -- Print an error message if the object is not a valid BasePart
        print("Invalid object. Please provide a BasePart.")
    end
end

-- Call the function to check the tension of the rope
local function DropAnchor()
    rope.WinchEnabled = false
    rope.WinchResponsiveness = 45
    rope.WinchForce = 10000
    setCustomPhysicalProperties(Anchor, 100)
    Anchor.Massless = false
    Anchor.Anchored = false
    boat.Winch.RopeProp.Anchored = false
    Anchor.AssemblyLinearVelocity = Vector3.new(0, -10, 0)
    rope.Length = 100

    task.wait(4)
    rope.WinchTarget = 10
    rope.WinchEnabled = true
    rope.WinchSpeed = 2
    repeat
        task.wait(1)
    until checkTension() == true
    Anchor.AssemblyLinearVelocity = Vector3.new(0, 0, 0)
    Anchor.AssemblyAngularVelocity = Vector3.new(0, 0, 0)
    rope.WinchEnabled = false
    Anchor.Anchored = true
    boat.Winch.RopeProp.Anchored = true
end
local tweenservice = game:GetService("TweenService")
local goal = {}
local tweeni = TweenInfo.new(.0666)

local function RetractAnchor()
    Anchor.Massless = true
    Anchor.CanCollide = false
    boat.Winch.RopeProp.Anchored = false
    setCustomPhysicalProperties(Anchor, .1)
    Anchor.Anchored = false

    --task.wait(3)
    rope.WinchSpeed = 25
    rope.WinchEnabled = true
    Anchor.AssemblyLinearVelocity = Vector3.new(0, 0, 0)
    Anchor.AssemblyAngularVelocity = Vector3.new(0, 0, 0)
    rope.WinchTarget = .25
    rope.WinchResponsiveness = 90
    rope.WinchForce = 20000
    local twe = tweenservice:Create(rope, TweenInfo.new(3), {Length = .25})
    twe:Play()
    twe.Completed:Wait()
    rope.WinchForce = 10000
    Anchor.AssemblyLinearVelocity = Vector3.new(0, 0, 0)
    Anchor.AssemblyAngularVelocity = Vector3.new(0, 0, 0)
    repeat
        task.wait(.5)
        rope.WinchForce = math.max(3000, rope.WinchForce - 1000)
        Anchor.AssemblyLinearVelocity = Vector3.new(0, 0, 0)
        Anchor.AssemblyAngularVelocity = Vector3.new(0, 0, 0)
    until checkTension() == true
    rope.WinchEnabled = false
    Anchor.AssemblyLinearVelocity = Vector3.new(0, 0, 0)
    Anchor.AssemblyAngularVelocity = Vector3.new(0, 0, 0)
    task.delay(
        3,
        function()
            Anchor.CanCollide = true
        end
    )
end

local doing = false
Seat.Changed:Connect(
    function()
        --// Only sail on water
        if Seat.Occupant ~= nil and doing == false then
            AngularVelocity.AngularVelocity = Vector3.new(0, -1 * Seat.Steer, 0)
            LinearVelocity.LineVelocity = 50 * Seat.Throttle
            doing = true

            RetractAnchor()
            task.wait()
            unachor(false)
            AngularVelocity.Enabled = true
            local Occupant = Seat.Occupant
            LinearVelocity.Enabled = true

            while Occupant == Seat.Occupant do
                task.wait()
                local seatpos = Boater.Position
                local sPos = seatpos + sposoffset
                local ePos = seatpos - eposoffset
                local ray = workspace:Raycast(sPos, ePos - sPos, params)
                -- print(Seat.Steer)

                if ray and ray.Material == floatmaterial then
                    print("Query successful")
                    task.wait()
                    if Seat.Throttle ~= 0 then
                        CurA = math.min(MaxA, CurA + .01)
                        Seat.Torque = (10 * CurA)
                        Seat.MaxSpeed = (10 * CurA)
                    else
                        task.wait()
                        CurA = math.max(1, CurA - .01)
                    end
                    LinearVelocity.LineVelocity = 50 * (Seat.Throttle * CurA)
                    LinearVelocity.MaxForce = 10000 + (1000 * math.abs(Seat.Throttle) * CurA)
                    AngularVelocity.MaxTorque = 10000 + (1000 * math.abs(Seat.Throttle) * CurA)
                    --- local tween=tweenservice:Create(LinearVelocity,tweeni,{LineVelocity= 50 * (Seat.Throttle*CurA),MaxForce =  10000 + (1000*math.abs(Seat.Throttle)*CurA)})
                    -- tween:Play()
                    ---    local tween=tweenservice:Create(AngularVelocity,tweeni,{AngularVelocity = Vector3.new(0, -1 * Seat.Steer*math.min(2,CurA), 0),MaxTorque=10000 + (1000*math.abs(Seat.Throttle)*CurA)})
                    -- tween:Play()
                    AngularVelocity.AngularVelocity = Vector3.new(0, -.5 * Seat.Steer * math.min(3, CurA), 0)
                    task.wait()
                else
                    -- task.wait(.3)
                    --   LinearVelocity.LineVelocity = 50 * (-1*CurA)
                    --    task.wait(3)
                    --
                end
                if Occupant ~= Seat.Occupant then
                    break
                end
            end
            Occupant = nil
            AngularVelocity.Enabled = false
            LinearVelocity.Enabled = false
            unachor(true)
            DropAnchor()
            --task.wait()
            --unachor(false)--I tried to make it unachored but it gets yeeted :(
            Anchor.Anchored = true
            doing = false
        end
    end
)

This is the first iteration so stay tuned for updates! Iโ€™m going to add cannons and perhaps hitpoints

Boat with Retractable Anchor

13 Likes

Introducing V2! I added Cannons, Retextured and Upscaled the texture of the ship added some stairs! Retextured those as well to match the wood of the ship! Then did some rigging with the rope constraints! :slight_smile:



Here is Version 2! This one has the same function except now with cannons! In addition some aesthetic improvements!

Pirate Ship with Anchor

5 Likes

I have something new to share! I have recently learned about alpha channels so I updated the Fyling Dutchmen! I have AI upscaled the Texture, added Alpha channels to make the doors and windows and added the anchor ladders to make it fully traversable and functional!


This is a Spongebob Reference so I would like to Open Source this as a Free Model!
create.roblox.com/store/asset/16433707385

  1. What is an Alpha Channel?
  • An alpha channel is a transparency channel associated with an image. It represents the opacity or translucency of each pixel.
  • In a standard RGB image, each pixel has three color channels: red, green, and blue. An additional fourth channel, the alpha channel, is used to control the pixelโ€™s transparency.
2 Likes