BallisticCalc = require("BallisticCalc")
Basalt = require("basalt")
CoordTransformer = require("CoordTransformer")
Quaternion = require("Quaternion")
Track = require("Track")
Util = require("Util")
Vector3d = require("Vector3d")
-- 系统初始化 --
local targetpos = { x = 0, y = 0, z = 0 }
local Cannon_Config = { Charge = 6, length = 18, G = -0.05, Drag = 0.01, Dep = -5, Ele = 90, Tol = 0.01, Mode = 3 }
local selfpos = coord.getCoord()
local q = peripheral.wrap("front").getRotation()
local vel = ship.getVelocity()
local i = 1
local rotation_matrix = {
x = Vector3d:new(1, 0, 0),
y = Vector3d:new(0, 1, 0),
z = Vector3d:new(0, 0, 1)
}
local cannon = peripheral.wrap("back")
local getPlayers = coord.getPlayersAll(50)
local players = {}
cannon.assemble()
local hasTargrt = false
local current_position = Vector3d:new(-1, 0, 0)
local err_yaw, err_pitch
local yaw_control = peripheral.wrap("Create_RotationSpeedController_0")
local pitch_control = peripheral.wrap("Create_RotationSpeedController_1")
local yaw_speed, pitch_speed = 0, 0
local mode = 1
local controller = "AkashiSCO"
-- GUI初始化函数 --
local function createGUI()
local MainFrame = Basalt.getMainFrame()
-- 目标坐标显示组件
local targetXGui = MainFrame:addTextBox({ editable = false, background = colors.white, foreground = colors.red }):setPosition(4, 1):setSize(13, 1):setText(" TargetX");
local targetYGui = MainFrame:addTextBox({ editable = false, background = colors.white, foreground = colors.green }):setPosition(20, 1):setSize(13, 1):setText(" TargetY");
local targetZGui = MainFrame:addTextBox({ editable = false, background = colors.white, foreground = colors.blue }):setPosition(36, 1):setSize(13, 1):setText(" TargetZ");
-- 玩家选择控制组件
local TargetController = MainFrame:addTextBox({ editable = false, background = colors.white, foreground = colors.black }):setPosition(16, 2):setSize(20, 1):setText(" control_player");
local buttomleft = MainFrame:addButton({ text = "<<--", background = colors.white, foreground = colors.black }):setPosition(11, 2):setSize(4, 1)
local buttomright = MainFrame:addButton({ text = "-->>", background = colors.white, foreground = colors.black }):setPosition(36, 2):setSize(4, 1)
-- 火炮配置组件
local Charge_text = MainFrame:addTextBox():setPosition(2, 4):setSize(10, 1):setText("Charge:" .. Cannon_Config.Charge)
local length_text = MainFrame:addTextBox():setPosition(15, 4):setSize(10, 1):setText("length:" ..Cannon_Config.length)
local Dep_text = MainFrame:addTextBox():setPosition(27, 4):setSize(10, 1):setText("Dep:" .. Cannon_Config.Dep)
local Ele_text = MainFrame:addTextBox():setPosition(40, 4):setSize(10, 1):setText("Ele:" .. Cannon_Config.Ele)
local G_text = MainFrame:addTextBox():setPosition(27, 5):setSize(10, 1):setText("G:" .. Cannon_Config.G)
local Drag_text = MainFrame:addTextBox():setPosition(15, 5):setSize(10, 1):setText("Drag:" .. Cannon_Config.Drag)
local reload_buttom = MainFrame:addButton({ text = "Apply Setting" }):setPosition(18, 6):setSize(13, 1)
--速度监控组件
--local speed_x = MainFrame.addTextBox({text = "114"}):setPosition(0 , 10):setSize(10,1)
return {
targetXGui = targetXGui,
targetYGui = targetYGui,
targetZGui = targetZGui,
TargetController = TargetController,
buttomleft = buttomleft,
buttomright = buttomright,
reload_buttom = reload_buttom,
Charge_text = Charge_text,
length_text = length_text,
Dep_text = Dep_text,
Ele_text = Ele_text,
G_text = G_text,
Drag_text = Drag_text
--speed_x = speed_x
}
end
-- 初始化GUI并获取组件引用 --
local guiElements = createGUI()
-- 玩家列表处理 --
local function getPlayerslist()
i = 1
for _, v1 in pairs(getPlayers) do
for k, v2 in pairs(v1) do
if k == "name" then
players[i] = v2
i = i + 1
end
end
end
i = 1
end
getPlayerslist()
-- 工具函数 --
local function calcuspaces(max_length, text)
local text_length = string.len(text)
if text_length >= max_length then return "" end
local total_spaces = max_length - text_length
local left_spaces = math.floor(total_spaces / 2)
return string.rep(" ", left_spaces) .. text
end
local function getChatBoxContent(chatMessage)
if string.find(chatMessage, "xaero%-waypoint") then
local chatLocation = {}
for word in string.gmatch(chatMessage, "[%~%-%d]+") do
table.insert(chatLocation, word)
end
if chatLocation[3] == nil then chatLocation[3] = 69 end
if #chatLocation >= 4 then
return {
x = tonumber(chatLocation[2]),
y = tonumber(chatLocation[3]),
z = tonumber(chatLocation[4])
}
end
end
return nil
end
local function normalize_angle_diff(angle)
local normalized = angle % 360
if normalized > 180 then
normalized = normalized - 360
elseif normalized < -180 then
normalized = normalized + 360
end
return normalized
end
local function extract_number(input_str)
-- 匹配字符串中任意位置的第一个连续数字
local number_str = input_str:match("[-+]?%d*%.?%d+")
-- 加强类型转换校验
return tonumber(number_str) or 0
end
--计算目标相对于自身的速度
local function calculate_relative_velocity(
self_world_velocity, -- 自身世界速度 (Vector3d)
self_quaternion, -- 自身四元数 (Quaternion)
target_world_velocity -- 目标世界速度 (Vector3d)
)
-- 步骤1:计算相对世界速度
local relative_world_vel = target_world_velocity - self_world_velocity
-- 步骤2:应用四元数旋转
local rotated_velocity = self_quaternion:conj():rotate(relative_world_vel)
return rotated_velocity
end
-- 按钮事件处理 --
guiElements.buttomleft:onClick(function()
i = i - 1
if i < 1 then
i = #players
end
local len = #players[i]
local SpaceRep = string.rep(" ", math.floor((19 - len) / 2))
guiElements.TargetController:setText(SpaceRep .. players[i])
controller = players[i]
end)
guiElements.buttomright:onClick(function()
i = i + 1
if i > #players then
i = 1
end
local len = #players[i]
local SpaceRep = string.rep(" ", math.floor((19 - len) / 2))
guiElements.TargetController:setText(SpaceRep .. players[i])
controller = players[i]
end)
guiElements.reload_buttom:onClick(function()
Cannon_Config.Charge = extract_number(guiElements.Charge_text:getText())
Cannon_Config.length = extract_number(guiElements.length_text:getText())
Cannon_Config.Drag = extract_number(guiElements.Drag_text:getText())
Cannon_Config.Dep = extract_number(guiElements.Dep_text:getText())
Cannon_Config.Ele = extract_number(guiElements.Ele_text:getText())
Cannon_Config.G = extract_number(guiElements.G_text:getText())
end)
-- 目标获取函数 --
local function getTarget()
while true do
local _, user, msg = os.pullEvent("chat")
local target = getChatBoxContent(msg)
if target ~= nil and user == controller then
targetpos = Vector3d:new(target.x, target.y or 69, target.z)
hasTargrt = true
local x_text = calcuspaces(13, "X=" .. targetpos.x)
local y_text = calcuspaces(13, "Y=" .. targetpos.y)
local z_text = calcuspaces(13, "Z=" .. targetpos.z)
guiElements.targetXGui:setText(x_text)
guiElements.targetYGui:setText(y_text)
guiElements.targetZGui:setText(z_text)
end
end
end
-- 控制逻辑函数 --
local function calc_speed_t(target)
local speed = target / 0.32222222222222222
return math.min(math.max(speed, -48), 48)
end
local function isdisassemble()
while true do
os.pullEvent("redstone")
if redstone.getInput("top") then
cannon.disassemble()
else
cannon.assemble()
end
end
end
-- 主控制逻辑 --
local function Main()
repeat os.sleep(0.5) until hasTargrt == true
while true do
selfpos = coord.getCoord()
q = peripheral.wrap("front").getRotation()
q = Quaternion:new( q.x , q.y , q.z , q.w )
vel = ship.getVelocity()
local speed = Vector3d:new(vel.x, vel.y, vel.z)
local targetspeed = Vector3d:new(0, 0, 0) -- 目标静止
local target_local_speed = calculate_relative_velocity(speed , q , targetspeed) -- 将目标速度转换到自身坐标系
-- 计算初始弹道
local target_relative = CoordTransformer.InverseCoord(selfpos, targetpos, q)
local Yaw, Dist_xz = BallisticCalc.calc_Yaw_and_Dist_xz(target_relative, rotation_matrix, 90)
Yaw = Util:setInScope(Yaw)
local t_y = targetpos.y - selfpos.y - 1
local Pitch, time = BallisticCalc.customcalc(
Dist_xz, t_y,
Cannon_Config.Charge, Cannon_Config.length,
Cannon_Config.G, Cannon_Config.Drag,
Cannon_Config.Dep, Cannon_Config.Ele,
Cannon_Config.Tol, mode
)
local calc_return = BallisticCalc.calc_leading_shot(
target_relative,
target_local_speed,
{ n = Cannon_Config.Charge , k = Cannon_Config.length , g = Cannon_Config.G , drag = Cannon_Config.Drag },
{ a_min = Cannon_Config.Dep , a_max = Cannon_Config.Ele},
30,0.001,-90
)
Pitch = calc_return.pitch or 0
Yaw = calc_return.yaw or 0
local now_yaw = cannon.getYaw()
local now_pitch = cannon.getPitch()
err_yaw = normalize_angle_diff(Yaw - now_yaw)
err_pitch = normalize_angle_diff(Pitch - (now_pitch or 0))
yaw_speed = calc_speed_t(err_yaw) or 0
pitch_speed = -calc_speed_t(err_pitch) or 0
os.sleep(0.05)
end
end
-- 执行函数 --
local function setYawspeed()
repeat os.sleep(0.5) until hasTargrt == true
while true do
os.sleep(0.05)
if math.abs(yaw_speed) > 1 or math.abs(err_yaw) > 1 then
yaw_control.setTargetSpeed(yaw_speed)
else
yaw_control.setTargetSpeed(0)
if Yaw then
cannon.setYaw(Yaw)
end
end
end
end
local function setpitchspeed()
repeat os.sleep(0.5) until hasTargrt == true
while true do
os.sleep(0.05)
if math.abs(pitch_speed) > 1 or math.abs(err_pitch) > 1 then
pitch_control.setTargetSpeed(pitch_speed)
else
pitch_control.setTargetSpeed(0)
if Pitch then
cannon.setPitch(Pitch)
end
end
end
end
-- 启动所有并行任务 --
parallel.waitForAll(
Main,
setYawspeed,
setpitchspeed,
getTarget,
isdisassemble,
Basalt.run
)
这是我的代码
Vector3d = {}
Vector3d.__index = Vector3d
-- 构造函数
function Vector3d:new(x, y, z)
local instance = { x = x or 0, y = y or 0, z = z or 0 }
setmetatable(instance, self)
return instance
end
function Vector3d:copy(cpyVector)
return Vector3d:new(cpyVector.x, cpyVector.y, cpyVector.z)
end
-- 加法
function Vector3d:add(other)
return Vector3d:new(self.x + other.x, self.y + other.y, self.z + other.z)
end
function Vector3d.__add(a, b)
return a:add(b)
end
-- 减法
function Vector3d:subtract(other)
return Vector3d:new(self.x - other.x, self.y - other.y, self.z - other.z)
end
function Vector3d.__sub(a, b)
return a:subtract(b)
end
-- 点积
function Vector3d:dot(other)
return self.x * other.x + self.y * other.y + self.z * other.z
end
function Vector3d:operate(func)
return Vector3d:new(func(self.x), func(self.y), func(self.z))
end
-- 叉积
function Vector3d:cross(other)
local x = self.y * other.z - self.z * other.y
local y = self.z * other.x - self.x * other.z
local z = self.x * other.y - self.y * other.x
return Vector3d:new(x, y, z)
end
function Vector3d:scale(scalar)
return Vector3d:new(
self.x * scalar,
self.y * scalar,
self.z * scalar
)
end
function Vector3d.__mul(a, b)
if type(a) == "number" then
return b:scale(a)
elseif type(b) == "number" then
return a:scale(b)
end
--error("Vector multiplication requires explicit cross/dot")
return a:scale(b)
--return a:cross(b)
end
function Vector3d:magnitude()
return math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
end
function Vector3d:magnitudesq()
return (self.x * self.x + self.y * self.y + self.z * self.z)
end
function Vector3d:multiply(scale)
return Vector3d:new(self.x * scale, self.y * scale, self.z * scale)
end
function Vector3d:multiplyByMatrix(m)
local v_x = m.x:multiply(self.x)
local v_y = m.y:multiply(self.y)
local v_z = m.z:multiply(self.z)
return v_x + v_y + v_z
end
-- 归一化
function Vector3d:normalize()
local magnitude = math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
return Vector3d:new(self.x / magnitude, self.y / magnitude, self.z / magnitude)
end
return Vector3d
这是我的库,当我移动的时候他提前量明显过于大了,而且速度高于一定的时候,他在调用我的库的__mul(a,b)的时候,b会为nil
最新发布