Jump to content

Recommended Posts

Posted

Hello,

long time no see ^^

at the moment i have a littel time and i try to learn more with lua. I need help  with my script. Maybe my thoughts completley wrong.

I have a simple map with two boxes.

One box is Main the second Box i made as a child

each box has the script

I'm trying to find out if the box is included in table.

and how i can store it. maybe i am compleatly wrong.. maybe someone can help me ;)

 

 

FlockEntity = {name = "FlockEntity"}

FlockEntity.maxforce = Vec3(0) --set to 20.005 then its hoovering (Mass = 1)
FlockEntity.pointforce = Vec3(0)

function FlockEntity:Start()
    self.tbl = {}
    self.entity:GetParent()
    self.entity:FindChild("Box*")

    print(index)
    print(self.tbl)
    print(name)

end

function FlockEntity:Update()
    
      ------ Hoover ----------------------
      self.entity:AddForce(self.maxforce)
      ------------------------------------

-----------------Flock.lua------------------------------------------------------------------------      
self.radius = 1
  

for i=1, #self.tbl do
    self.elem = self.tbl[i]     
     
    if (self.elem ~= self.entity) then

        self.vNeighborDelta = self.elem:GetPosition() - self.entity:GetPosition()

        self.dist = self.vNeighborDelta:Length()

        if (self.dist < self.radius * 2) then
            self.vNeighborDelta:Normalize()
            self.entity:GetPhysicsMode()
            self.entity:AddForce(self.pointforce)
        end
    end


end


end

RegisterComponent("Flock", FlockEntity)

return FlockEntity

 

  • 2 weeks later...
  • 2 weeks later...
Posted

i have fun with that .. now i have a flock of fishes with avoid collision and different movements. at the moment there is a flicker in  pitch or in avoid collision  . maybe i find a solution later or someone find a solution :)

Flock = {}
Flock.name = "Flock"

function Flock:Start()
    world = self.entity:GetWorld()
    self.boxes = {}
    self.boxProperties = {}
    self.offset = self.entity:GetPosition() -- Position of the pivot used as offset

    -- Define Y-axis limits
    self.minY = self.offset.y - 2.0 -- Minimum Y limit
    self.maxY = self.offset.y + 0.5 -- Maximum Y limit

    -- Initialize random seed (per instance)
    math.randomseed(os.time())
    
    InitializeBoxes(self)
end

-- Define constants
Flock.radius = 5.0
Flock.numBoxes = 8
minDistance = 3 -- Minimum distance to avoid collision
avoidanceStrength = 0.2 -- Strength of the avoidance force

-- Movement pattern functions
movementPatterns = {}

function movementPatterns.circular(self, angle)
    local x = self.offset.x + self.radius * math.cos(angle)
    local y = self.offset.y + self.radius * math.sin(angle * 0.5) -- y-movement added
    local z = self.offset.z + self.radius * math.sin(angle)
    y = math.max(math.min(y, self.maxY), self.minY) -- Clamp Y within limits
    return Vec3(x, y, z)
end

function movementPatterns.elliptical(self, angle)
    local a = self.radius
    local b = self.radius / 2
    local x = self.offset.x + a * math.cos(angle)
    local y = self.offset.y + b * math.sin(angle * 0.5) -- y-movement added
    local z = self.offset.z + b * math.sin(angle)
    y = math.max(math.min(y, self.maxY), self.minY) -- Clamp Y within limits
    return Vec3(x, y, z)
end

function movementPatterns.spiral(self, angle)
    local r = self.radius + angle * 0.5
    local x = self.offset.x + r * math.cos(angle)
    local y = self.offset.y + r * math.sin(angle * 0.5) -- y-movement added
    local z = self.offset.z + r * math.sin(angle)
    y = math.max(math.min(y, self.maxY), self.minY) -- Clamp Y within limits
    return Vec3(x, y, z)
end

function movementPatterns.zigzag(self, angle)
    local amplitude = 2.0
    local frequency = 2.0
    local x = self.offset.x + self.radius * math.cos(angle)
    local y = self.offset.y + amplitude * math.sin(frequency * angle) -- y-movement adjusted
    local z = self.offset.z + amplitude * math.sin(frequency * angle)
    y = math.max(math.min(y, self.maxY), self.minY) -- Clamp Y within limits
    return Vec3(x, y, z)
end

function AlignBoxWithMovement(box, previousPosition, newPosition)
    local direction = (newPosition - previousPosition):Normalize()

    -- Calculate yaw (rotation around Y-axis) and pitch (rotation around X-axis) to face the movement direction
    local yaw = ATan(direction.x, direction.z) -- Yaw around Y-axis
    local pitch = ATan(direction.y, (direction.x^2 + direction.z^2)^0.5) -- Pitch around X-axis
    
    -- Adjust yaw for model orientation if needed
    yaw = yaw + 180

    -- Ensure pitch and yaw are numeric types before setting rotation
    pitch = tonumber(pitch) or 0
    yaw = tonumber(yaw) or 0

    -- Set the rotation of the box (yaw and pitch )
    box:SetRotation(pitch, yaw, 0)
end

function InitializeBoxes(self)
    for i = 1, self.numBoxes do
        local patternNames = {"circular", "elliptical", "spiral", "zigzag"}
        local patternName = patternNames[math.random(#patternNames)]
        local movementFunction = movementPatterns[patternName]
        
        local speed = math.random() * 2 + 0.5
        local angle = math.random() * 2 * math.pi
        local position = movementFunction(self, angle)
        
        local box = LoadModel(world, "H:/UltraEngine/New Project/Models/Diverses/Fish.mdl") -- or CreateBox(world,1)
        box:SetPosition(position)
        
        self.boxes[i] = box
        self.boxProperties[box] = {
            movementFunction = movementFunction,
            speed = speed,
            angle = angle,
            patternName = patternName,
            lastPosition = position -- Store the initial position as last position
        }
    end
end

function AvoidCollisions(self, box, newPosition, otherPositions)
    local smoothingFactor = 0.1 -- The factor by which to smooth the Y-axis movement

    for _, otherBox in ipairs(self.boxes) do
        if box ~= otherBox then
            local otherPosition = otherPositions[otherBox] -- Use previous position instead of current position
            
            if otherPosition then
                local distance = newPosition:DistanceToPoint(otherPosition)
                if distance < minDistance then
                    local avoidanceDirection = (newPosition - otherPosition):Normalize()
                    local horizontalDistance = ((newPosition.x - otherPosition.x)^2 + (newPosition.z - otherPosition.z)^2)^0.5

                    if horizontalDistance < minDistance then
                        if newPosition.y < otherPosition.y then
                            newPosition.y = math.max(newPosition.y - smoothingFactor, self.minY) -- Smooth downward movement
                        else
                            newPosition.y = math.min(newPosition.y + smoothingFactor, self.maxY) -- Smooth upward movement
                        end
                    end

                    newPosition = newPosition + avoidanceDirection * ((minDistance - distance) / minDistance) * avoidanceStrength
                    newPosition.y = math.max(math.min(newPosition.y, self.maxY), self.minY) -- Clamp Y within limits
                end
            end
        end
    end
    return newPosition
end

function UpdateBoxes(self, deltaTime)
    local newPositions = {}
    
    for _, box in ipairs(self.boxes) do
        local props = self.boxProperties[box]
        props.angle = props.angle + props.speed * 0.003
        local newPosition = props.movementFunction(self, props.angle)

        if newPosition then
            newPosition = AvoidCollisions(self, box, newPosition, newPositions)
            newPositions[box] = newPosition
        end
    end
    
    for _, box in ipairs(self.boxes) do
        local newPosition = newPositions[box]
        local props = self.boxProperties[box]

        if newPosition then
            AlignBoxWithMovement(box, props.lastPosition, newPosition)
            box:SetPosition(newPosition)
            props.lastPosition = newPosition
        end
    end
end

function Flock:Update(deltaTime)
    UpdateBoxes(self, deltaTime)
end

RegisterComponent("Flock", Flock)

return Flock

 

Fischflock.jpg

  • Haha 1

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.

×
×
  • Create New...