diff --git a/class/boids/controls/HybridControls.lua b/class/boids/controls/HybridControls.lua index cb50c30..5f5c3a2 100644 --- a/class/boids/controls/HybridControls.lua +++ b/class/boids/controls/HybridControls.lua @@ -1,63 +1,73 @@ --[[ * Hybrid control scheme Cellulo acts like a joystick position-wise, and goes back to the center when it's released. Rotation-wise, it acts like the absolute control scheme. ]]-- local global = require "global" local util = include "util" local HybridControls = (class "boids.controls.Controls"):subclass("HybridControls") local CELLULO_RELATIVE_SPEED = 5 local CELLULO_RELATIVE_ROTATION_SPEED = 2 local CELLULO_MAX_HAPTIC_FORCE = 20 local CELLULO_HAPTIC_FACTOR = 10 local CELLULO_RELATIVE_TARGET = { x = 0, y = 0 } function HybridControls.static:applyMovement(boid, dt) + local kidnapped = boid:getCellulo():getKidnapped() + if kidnapped then + boid.oa = nil + end + -- move like the cellulo was a joystick thumb, origin of the paper acting as neutral if not kidnapped then - -- relative position - local x, y, z = boid:getCollider():getPosition() - local dx, dy = boid:getCelluloPlane():normalizedRelative(boid:getCellulo():getX(), boid: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 - boid:setPosition(x, y, z) - boid:getCollider():setPosition(x, y, z) - - -- absolute rotation - local da = boid:getCellulo():getTheta() - boid.oa - da = math.atan2(math.sin(da), math.cos(da)) - local angle = boid:getAngle() - angle = angle - da -- no need for dt? - boid:setAngle(angle) - - -- force cellulo back to center (haptic) - local tx, ty = boid:getCelluloPlane():normalizedRelativeToAbsolute(CELLULO_RELATIVE_TARGET.x, CELLULO_RELATIVE_TARGET.y) - boid:getCellulo():setGoalPosition(tx, ty, 100) + if boid.oa then + -- relative position + local x, y, z = boid:getCollider():getPosition() + local dx, dy = boid:getCelluloPlane():normalizedRelative(boid:getCellulo():getX(), boid: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 + boid:setPosition(x, y, z) + boid:getCollider():setPosition(x, y, z) + + -- absolute rotation + local da = boid:getCellulo():getTheta() - boid.oa + da = math.atan2(math.sin(da), math.cos(da)) + local angle = boid:getAngle() + angle = angle - da -- no need for dt? + boid:setAngle(angle) + + -- force cellulo back to center (haptic) + local tx, ty = boid:getCelluloPlane():normalizedRelativeToAbsolute(CELLULO_RELATIVE_TARGET.x, CELLULO_RELATIVE_TARGET.y) + boid:getCellulo():setGoalPosition(tx, ty, 100) + end + + -- set origin angle + boid.oa = boid:getCellulo():getTheta() end end function HybridControls.static:applyHapticFeedback(boid, dt, dir) 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 = boid:getCelluloPlane():normalizedRelativeToAbsolute(dx, dz) boid:getCellulo():setGoalPosition(dx, dz, 100) end end return HybridControls \ No newline at end of file diff --git a/class/boids/controls/RelativeControls.lua b/class/boids/controls/RelativeControls.lua index 79c9a5d..4af6165 100644 --- a/class/boids/controls/RelativeControls.lua +++ b/class/boids/controls/RelativeControls.lua @@ -1,53 +1,55 @@ --[[ * Relative control scheme Cellulo acts like a joystick ]]-- local global = require "global" local util = include "util" local RelativeControls = (class "boids.controls.Controls"):subclass("RelativeControls") local CELLULO_RELATIVE_SPEED = 5 local CELLULO_RELATIVE_ROTATION_SPEED = 2 local CELLULO_MAX_HAPTIC_FORCE = 20 local CELLULO_HAPTIC_FACTOR = 10 function RelativeControls.static:applyMovement(boid, dt) + local kidnapped = boid:getCellulo():getKidnapped() + -- move like the cellulo was a joystick thumb, origin of the paper acting as neutral if not kidnapped then local x, y, z = boid:getCollider():getPosition() local dx, dy = boid:getCelluloPlane():normalizedRelative(boid:getCellulo():getX(), boid: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 = boid:getAngle() local da = boid:getCellulo():getAngle() if da > math.pi then da = -2*math.pi + da end angle = angle + (-da) * CELLULO_RELATIVE_ROTATION_SPEED * dt boid:setPosition(x, y, z) boid:getCollider():setPosition(x, y, z) boid:setAngle(angle) end end function RelativeControls.static:applyHapticFeedback(boid, dt, dir) 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 = boid:getCelluloPlane():normalizedRelativeToAbsolute(dx, dz) boid:getCellulo():setGoalPose(dx, dz, 0, 100, 10) end end return RelativeControls \ No newline at end of file