diff --git a/class/boids/CelluloControlledBoid.lua b/class/boids/CelluloControlledBoid.lua index 6542d94..bb12df1 100644 --- a/class/boids/CelluloControlledBoid.lua +++ b/class/boids/CelluloControlledBoid.lua @@ -1,137 +1,64 @@ local assertArgs = include "assertArgs" local util = include "util" local global = require "global" local Boid = class "boids.Boid" local CelluloControlledBoid = lib "class" ("CelluloControlledBoid", Boid) local mixinHasCellulo = mixin "_has" ("Cellulo") CelluloControlledBoid:include(mixinHasCellulo) -CelluloControlledBoid:include(mixin "_has" ("ControlMethod")) +CelluloControlledBoid:include(mixin "_has" ("Controls")) CelluloControlledBoid:include(mixin "_has" ("CelluloPlane")) CelluloControlledBoid:include(mixin "_has" ("HapticFeedbackEnabled")) -local CELLULO_ABSOLUTE_SPEED = 0.04 -local CELLULO_RELATIVE_SPEED = 5 -local CELLULO_RELATIVE_ROTATION_SPEED = 2 - -local CELLULO_MAX_HAPTIC_FORCE = 20 -local CELLULO_HAPTIC_FACTOR = 10 - function CelluloControlledBoid:initialize(args) - assertArgs(args, "cellulo", "controlMethod", "celluloPlane", "hapticFeedbackEnabled") + assertArgs(args, "cellulo", "controls", "celluloPlane", "hapticFeedbackEnabled") Boid.initialize(self, args) self:setCellulo(args.cellulo) - self:setControlMethod(args.controlMethod) + self:setControls(args.controls) self:setCelluloPlane(args.celluloPlane) self:setHapticFeedbackEnabled(args.hapticFeedbackEnabled) self.ox, self.oy, self.oz = nil, nil, nil return self end function CelluloControlledBoid:setCellulo(cellulo) self.cellulo = cellulo if cellulo ~= -1 then cellulo:setHapticBackdriveAssist(0.8, 0.8, 0.8) cellulo:setGoalVelocity(0, 0, 0) end end function CelluloControlledBoid:update(dt) - -- implement boid behaviour - local controlMethod = self:getControlMethod() + + self:getControls():applyMovement(self, dt) if self:getHapticFeedbackEnabled() then self:applyHapticFeedback(dt) end - if controlMethod == "absolute" then - -- move continuously - local kidnapped = self:getCellulo():getKidnapped() - if kidnapped then - self.ox, self.oy, self.oa = nil, nil, nil - end - - if not kidnapped then - if self.ox and self.oy and self.oa then - - local da = self:getCellulo():getTheta() - self.oa - da = math.atan2(math.sin(da), math.cos(da)) - local angle = self:getAngle() - angle = angle - da -- no need for dt? - self:setAngle(angle) - - local dx, dy = self:getCellulo():getX() - self.ox, self:getCellulo():getY() - self.oy - local x, y, z = self:getCollider():getPosition() - dx, dy = util.rotateVector(dx, dy, -global.camera:getAngle()) - x, z = x + dx * CELLULO_ABSOLUTE_SPEED, z + dy * CELLULO_ABSOLUTE_SPEED - self:setPosition(x, y, z) - self:getCollider():setPosition(x, y, z) - end - - -- set origin - self.ox, self.oy, self.oa = self:getCellulo():getX(), self:getCellulo():getY(), self:getCellulo():getTheta() - end - elseif controlMethod == "relative" then - -- move like the cellulo was a joystick thumb, origin of the paper acting as neutral - if not kidnapped then - local x, y, z = self:getCollider():getPosition() - local dx, dy = self:getCelluloPlane():normalizedRelative(self:getCellulo():getX(), self:getCellulo():getY()) - dx, dy = util.rotateVector(dx, dy, -global.camera:getAngle()) - x, z = x + dx * CELLULO_RELATIVE_SPEED * dt, z + dy * CELLULO_RELATIVE_SPEED * dt - local angle = self:getAngle() - local da = self:getCellulo():getAngle() - if da > math.pi then da = -2*math.pi + da end - angle = angle + (-da) * CELLULO_RELATIVE_ROTATION_SPEED * dt - self:setPosition(x, y, z) - self:getCollider():setPosition(x, y, z) - self:setAngle(angle) - end - end end function CelluloControlledBoid:draw() + -- TODO: toggle for bird-view mode (need to show the player fish) return -- don't draw anything end function CelluloControlledBoid:applyHapticFeedback(dt) local dir = lovr.math.vec3(0, 0, 0) local n = self:getSwarm():forAllNeighbours(self, function (boid) dir = dir:add(lovr.math.vec3(boid:getCollider():getPosition())) end) dir:div(n) -- center of mass dir:sub(lovr.math.vec3(self:getCollider():getPosition())) - local controlMethod = self:getControlMethod() - if controlMethod == "absolute" then - dir:mul(CELLULO_HAPTIC_FACTOR) - if dir:length() > CELLULO_MAX_HAPTIC_FORCE then - dir:normalize() - dir:mul(CELLULO_MAX_HAPTIC_FORCE) - end - local dx, dy, dz = dir:unpack() - dx, dz = util.rotateVector(dx, dz, global.camera:getAngle()) - self:getCellulo():setGoalVelocity(dx, dz, 0) - elseif controlMethod == "relative" then - if dir:length() > 1 then - dir:mul(CELLULO_HAPTIC_FACTOR) - if dir:length() > CELLULO_MAX_HAPTIC_FORCE then - dir:normalize() - dir:mul(CELLULO_MAX_HAPTIC_FORCE) - end - dir:div(CELLULO_MAX_HAPTIC_FORCE) - local dx, dy, dz = dir:unpack() - dx, dz = util.rotateVector(dx, dz, global.camera:getAngle()) - dx, dz = dx / 2, dz / 2 - dx, dz = self:getCelluloPlane():normalizedRelativeToAbsolute(dx, dz) - self:getCellulo():setGoalPose(dx, dz, 0, 100, 10) - end - end + self:getControls():applyHapticFeedback(self, dt, dir) end return CelluloControlledBoid \ No newline at end of file