摘要:一种基于 ComputerCraft 和 Create 的瓦尔基里车辆控制变速系统,包含 模拟声浪 仪表台 自动 / 手动变速箱 等功能

食用方法

  • 准备:高级电脑转速控制器高级显示器扬声器无线红石信号终端高级遥控器 (tweaked_linked_controller)、讲台

1. 将硬件连接(如下图)

技巧: 在载具上放置一个横着的物理结构让转速控制器变成一格高的方块
注意:请先用高级遥控器无线红石信号终端连接转向轮后再放上讲台

接线示意图
连接完成

2. 安装控制程序

在电脑中输入 wget https://raw.githubusercontent.com/NDSSTUDIO/computercraft-AT-system/refs/heads/main/startup.lua
如果确认无误,显示器上将显示仪表画面

3. 控制车辆

  • 见下图
  • 推荐使用手柄
    蓝色:手动模式独有功能 红色:需要外部红石连接
    默认配置:电脑启动时启动车辆、自动档舒适、空挡、手刹 若需要不同启动参数可修改配置文件(配置修改 UI 咕咕咕)

更新日志

2025/6/9
提供齿轮比基数修改(在 config.lua)
2025/6/8
多种变速箱模式、配置文件、手刹、发动机点火开关
2025/6/5
运动、休闲模式变速箱、LTRT 刹车油门

TODO

  • 手动变速
  • 配置 页面
  • 多种仪表样式
  • 手刹
  • 发动机点火开关
  • 多种变速箱模式
  • LTRT 刹车油门
  • .... 评论区搜寻意见.jpg

图集

全地形皮卡
全地形皮卡
全地形皮卡
全地形皮卡
全地形皮卡
全地形皮卡

源代码

注意:本代码可能包含过期内容,最新版见 Github

-- startup.lua  版本2025/6/9 11:28
-- 修改初始配置请第一次启动后查看config.lua
ver = 1.1 -- 配置文件版本请勿更改
 


-- 配置文件
configfile = "ConfigVer = 1.1\n-- 配置文件版本请勿更改\nhud_type = 0 -- 为自定义hud做准备\nparking_brake = 1 -- 手刹\n-- 初始化变速箱\ngear = 0\nspeed = 0\ngearbox_type = 0\n-- 0 = MT\n-- 1 = auto_snug\n-- 2 = auto_sports\n-- 3 = auto_overload\n-- 初始化引擎\nengine_speed = 0 -- 启动转速\nmaxSpeed = 80 -- 最大转速(此处仅为启动时最大转速)\nacceleration = 3 -- 加速率(同上)\ndeceleration = 2 -- 减速率(同上)\nthrottle = 0.0 -- 油门\nload = 0 -- 负载(负载=车重*一个很迷的数?)\nmass = 0.6 -- 车重(负载基数)\nstartup = 1.6 -- 引擎启动参数 -1:待命 0.9:启动 1.6:执行启动动作\n-- 初始化其他参数\nrelspeed = 0 -- 真实速度(m/s)\n\n-- 变速箱基数(齿轮比)引擎速度 * 基数 = 轮速\ngearr = -1\ngearn = 0\ngear1 = 1\ngear2 = 2\ngear3 = 3\ngear4 = 4\ngear5 = 5"


--- 初始化
-- 显示器
local monitor = peripheral.find("monitor")
if not monitor then
    print("NOT FOUND MONITOR")
end

-- 初始化HUD参数
monitor.clear()
monitor.setTextScale(0.5)
monitor.setCursorPos(1,1)
local hud_scale = monitor.getSize()


-- 配置文件
local config = io.open("config.lua","r")
if config then
    -- 打开配置文件
    io.input(config)
    -- 执行配置文件
    dofile("config.lua")
    
    if ConfigVer then
    monitor.setCursorPos(1,1)
    monitor.write("ConfigVer:"..ConfigVer.."  ProgramVer:"..ver)
    end
    if ConfigVer ~= ver or not ConfigVer then
        monitor.setCursorPos(1,2)
        monitor.write("updConfig")
        os.sleep(0.1)
        local config = io.open("config.lua","w")
        io.output(config)
        io.write(configfile)
        io.close(config)
        monitor.setCursorPos(1,3)
        monitor.write("reboot...")
        os.sleep(1)
        os.reboot()
    end
    monitor.setCursorPos(1,1)
    monitor.write("configOK")
    monitor.setCursorPos(1,1)
    monitor.write(config)
    
    io.close(config)
else
    monitor.setCursorPos(1,1)
    monitor.write("createConfig")
    os.sleep(0.1)
    local config = io.open("config.lua","w")
    io.close(config)
    local config = io.open("config.lua","a")
    io.output(config)
    io.write(configfile)
    io.close(config)
    monitor.setCursorPos(1,1)
    monitor.write("reboot...        ")
    os.sleep(1)
    os.reboot()
end


-- 转速控制器
local speedcontroller = peripheral.find("Create_RotationSpeedController")
if not speedcontroller then
    monitor.setCursorPos(1,1)
    monitor.write("NOT FOUND SPEEDCONTROLLER       ")
    return
end

-- 放在书架上的Create:Tweaked Controller
local joy = peripheral.find("tweaked_controller")
if not joy then
    monitor.setCursorPos(1,1)
    monitor.write("NOT FOUND JOY                 ")
end

-- 扬声器
local speaker = peripheral.find("speaker")
if not speaker then
    monitor.setCursorPos(1,1)
    monitor.write("NOT FOUND SPEAKER               ")
end

-- 启动引擎
function startengine()
    if startup == -1 then
        local joy_start = joy.getButton(7)
        if joy_start == true then
            startup = 1.6
        end
    end
    if startup > 1 then
        hud(speed,gear,rpm,relspeed)
        startup = math.max((startup - 0.05),1)
        engine_speed = math.min((engine_speed + 5),12)
        speaker.playNote("didgeridoo",(math.max(engine_speed / 26, 2)),(engine_speed / 3))
        speaker.playNote("bit",(math.max(engine_speed / 26, 2)),(engine_speed / 2))
        os.sleep(0.15)
    elseif startup == 1 and startup > 0.9 then
        speaker.playNote("didgeridoo",(math.max(engine_speed / 26, 3)),(engine_speed / 3))
        
        engine_speed = 15
        startup = 0.9
    end
end

-- HUD
function hud(speed,gear,rpm,relspeed)
    if hud_type == 0 then
        hud_0(speed,gear,rpm,relspeed)
    end
end

function hud_0(speed,gear,rpm,relspeed)
    monitor.clear()
    monitor.setTextScale(0.5)
    monitor.setCursorPos(1,1)
    local speedstr = tostring(math.floor(relspeed * 3.6))  --0.987 math.floor(relspeed * 3.6) (speed * 0.987)
    local rpmstr = (math.max((math.min((math.floor(engine_speed)+4),100)),0) / 10) -- 转速=1000*rpmstr

    -- 迈速表(KMH)
    if #speedstr == 1 then -- 1位数 1-3位数的居中显示
        monitor.setCursorPos((hud_scale + 1) / 2,(hud_scale / 2) - 2)
        monitor.write(speedstr)
    elseif #speedstr == 2 then -- 2位数
        monitor.setCursorPos(hud_scale / 2,(hud_scale / 2) - 2)
        monitor.write(speedstr:gsub(".", "%1 "):sub(1,-2))
    elseif #speedstr == 3 then -- 3位数
        monitor.setCursorPos(hud_scale / 2,(hud_scale / 2) - 2)
        monitor.write(speedstr)
    end
    monitor.setCursorPos(hud_scale / 2,(hud_scale / 2) - 1)
    monitor.write("KMH")
    
    -- 转速表
    monitor.setCursorPos(1,(hud_scale / 2) + 2)
    monitor.write("-----------------------------------------------------------")
    monitor.setCursorPos(((hud_scale / 2 - 7) - rpmstr*5) + 2,(hud_scale / 2) + 2)
    monitor.write("-----+----+----+----+----+----+----+----+----+----+----+----+----+----")
    monitor.setCursorPos(((hud_scale / 2 - 7) - rpmstr*5) + 2,(hud_scale / 2) + 3)
    monitor.write("     0    1    2    3    4    5    6    7    8    9   10   11   12")
    monitor.setCursorPos((hud_scale / 2) + 1,(hud_scale / 2) + 2)
    monitor.write("|")

    -- 挡位指示器
    monitor.setCursorPos((hud_scale / 2) - 5,1)
    monitor.write("R ")
    monitor.write("N ")
    monitor.write("1 ")
    monitor.write("2 ")
    monitor.write("3 ")
    monitor.write("4 ")
    monitor.write("5")
    monitor.setCursorPos((gear + 1 ) * 2 + 2    ,2)
    monitor.write("=")

   
    if gearbox_type == 3 then
    monitor.setCursorPos((hud_scale / 2) - 3,3)
    monitor.write("OVERLOAD")
    elseif gearbox_type == 2 then
    monitor.setCursorPos((hud_scale / 2) - 1,3)
    monitor.write("SPORT")
    end
    
    
    if parking_brake == 1 then
        monitor.setCursorPos(1,3)
        monitor.write("                     ")
        monitor.setCursorPos((hud_scale / 2) - 1,3)
        monitor.write("BREAK")
    end
end

-- 变速箱模式(自动)
function gearbox(gearbox_type)
    if gearbox_type == 1 then
        auto_snug()
    elseif gearbox_type == 2 then
        auto_sports()
    elseif gearbox_type == 3 then
        auto_overload()
    end
end   


-- 变速箱:MT手动
function mt()
    local joy_a = (joy.getButton(1)) -- 获取A按键(XBOX)
    local joy_b = (joy.getButton(2)) -- 获取B按键(XBOX)
    if joy_b == true then -- B加档
        gear = math.min((gear + 1),5)
        os.sleep(0.05)
    end
    if joy_a == true then -- A减档
        gear = math.max((gear - 1),-1)
        os.sleep(0.05)
    end
end

-- 变速箱:AT运动模式

function auto_sports()
    mass = 0.6
    acceleration = 3 -- 加速率
    deceleration = 2 -- 减速率
    maxSpeed = 80 -- 最大引擎转速:8000RPM
    if relspeed < 0.3 then -- 如果真实速度小于0.3则自动空档
        gear = 0
    end

    if speed < 2 then
        gear = 1
    end
    if engine_speed > 75 then
        gear = math.min(gear + 1,5)
    elseif engine_speed < 30 then
        gear = math.max(gear -1,1)
    end  
end

-- 变速箱:AT舒适模式

function auto_snug()
    mass = 0.45
    acceleration = 2.3 -- 加速率
    deceleration = 1.5 -- 减速率
    maxSpeed = 50 -- 最大引擎转速:5000RPM
    if speed < 2 then
        gear = 1
    end
    if engine_speed > 40 then
        gear = math.min(gear + 1,5)
    elseif engine_speed < 10 then
        gear = math.max(gear -1,1)
    end  
end

-- 变速箱:AT过载
function auto_overload()
    mass = 0.6
    acceleration = 3 -- 加速率
    deceleration = 2 -- 减速率
    maxSpeed = 120 -- 最大引擎转速:8000RPM
    if speed < 2 then
        gear = 1
    end
    if engine_speed > 100 then
        gear = math.min(gear + 1,5)
    elseif engine_speed < 30 then
        gear = math.max(gear -1,1)
    end  
end    

-- 轮速度(引擎速度->齿轮比->轮速)
function speed_ctl()
    if gear == 1 then -- AT1档
        speed = engine_speed * gear1 -- 轮速
    elseif gear == 2 then -- AT2档 *2
        speed = engine_speed * gear2
    elseif gear == 3 then -- AT3档 *3
        speed = engine_speed * gear3
    elseif gear == 4 then -- AT4档 *4
        speed = engine_speed * gear4
    elseif gear == 5 then -- AT5档 *5
        speed = engine_speed * gear5
    elseif gear == 0 then -- 空档(模拟惯性)
        if relspeed < 2 then -- 模拟惯性停车 
            speed = 0
        elseif relspeed < 6 and relspeed >= 4 then -- 模拟惯性1档
            speed = 30
        elseif relspeed < 12 and relspeed >= 6 then -- 模拟惯性2档
            speed = 51.2
        elseif relspeed < 19 and relspeed >= 12 then -- 模拟惯性3档
            speed = 102.4
        elseif relspeed < 22 and relspeed >= 19 then -- 模拟惯性4档
            speed = 153.6
        elseif relspeed >= 22 then -- 模拟惯性5档
            speed = 204.8
        end
    elseif gear == -1 then -- 倒挡
        speed = engine_speed * gearr
    end
end

-- 引擎速度(轮速->齿轮比->引擎速度)
function engine_speed_ctl() 
    if gear == 1 then -- AT1档
        load = 1.2 * mass -- 负载
        engine_speed = speed / gear1
    elseif gear == 2 then -- AT2档 *2
        load = 2.0 * mass -- 负载
        engine_speed = speed / gear2
    elseif gear == 3 then -- AT3档 *3
        load = 2.5 * mass -- 负载
        engine_speed = speed / gear3
    elseif gear == 4 then -- AT4档 *4
        load = 3 * mass -- 负载
        engine_speed = speed / gear4
    elseif gear == 5 then -- AT5档 *5
        load = 4.5 * mass -- 负载
        engine_speed = speed /gear5
    elseif gear == 0 then
        load = 0 * mass -- 负载
        engine_speed = engine_speed
    elseif gear == -1 then -- 倒挡
        if joy_y ~= -1  then -- 排除刹车
            load = 1.2 * mass -- 负载
            engine_speed = speed / gearr
        end
    end
end

-- 引擎油门(节气门)
function engine_accelerator()
    if throttle > 0 then -- 加速
        engine_speed = math.min((engine_speed + acceleration * throttle) - load, maxSpeed)  -- 加速
        -- (引擎速度+加速率*油门开度)- 负载 小于最大速度
    else -- 减速
        engine_speed = math.max(engine_speed - deceleration, 2)  
        -- 引擎速度-减速率 最小0rpm
    end
end

-- 控制器(前进/后退)(自动)
function car_ctl_auto()
    if joy_y < 0 or joy_rt > 0.1 then -- 油门
        
    if gear == -1 and relspeed > 3 then
        -- 倒车时的刹车按键
        -- 引擎减速率=5
        deceleration = 5
        else
            deceleration = 2 -- 引擎减速率=2
            if joy_rt > 0.1 then
                throttle = joy_rt
            else
                throttle = math.abs(joy_y)
            end
            gearbox(gearbox_type)   
        end
    elseif joy_y > 0 or joy_lt > 0.1 then -- 油门:倒挡/刹车
        
        if relspeed < 5 then -- <5m/s 倒挡
            if joy_rt > 0.1 then
                throttle = joy_rt
            else
                throttle = math.abs(joy_y)
            end
            load = 1.5-- 负载1.0*重量
            throttle = 1 -- 油门开度:30%
            maxSpeed = 35 -- 最大引擎转速:3500RPM
            gear = -1
        elseif gear ~= -1 then -- >5m/s 刹车
            maxSpeed = 80 -- 最大引擎转速:8000RPM
            -- 前进时的刹车按键
            -- 引擎减速率=5
            deceleration = 5
        end
    elseif joy_y == 0 then -- 油门:空
        throttle = 0 -- 油门开度:0%
        maxSpeed = 80 -- 最大引擎转速:8000RPM
    end
end

-- 控制器(油门/刹车/离合)(手动)
function car_ctl_mt()
    local joy_lb = (joy.getButton(5)) -- 获取L按键(XBOX)

    if joy_y < 0 or joy_rt > 0.1 then -- 油门
            deceleration = 2 -- 引擎减速率=2
            if joy_rt > 0.1 then
                throttle = joy_rt
            else
                throttle = math.abs(joy_y)
            end     
    elseif joy_y < 0.1 then
        throttle = 0
        -- 减速
    elseif joy_y > 0 or joy_lb == true then -- 刹车
        throttle = 0
        -- 减速
        brake = 1
        speed = speed * (1 - brake) -- 减速
    end
    if joy_lt > 0.1 then -- 离合器
        mt()
    else
        speed_ctl()
        engine_speed_ctl()
    end
    engine_accelerator()
end

function main()
    -- 通用
    joy_add = joy.getButton(8) -- 获取+/菜单按键/开始(XBOX)
    joy_x = joy.getButton(3) -- 获取X按键(XBOX)
    joy_start = joy.getButton(7) -- 获取返回按键(XBOX)
    joy_y = joy.getAxis(2) -- 获取手柄左摇杆Y轴
    joy_rt = joy.getAxis(6) -- 获取手柄右扳机
    joy_lt = joy.getAxis(5) -- 获取手柄左扳机


    local truespeed = ship.getVelocity() -- 获取速度分量
    relspeed = math.sqrt(truespeed.x^2 + truespeed.z^2) -- 计算真实速度(m/s)
    
    -- 关闭引擎
    if joy_start == true then
        startup = -1
    end

    -- 变速箱模式切换
    if joy_add == true then
        if gear ~= 5 then
            engine_speed = 0
            gearbox_type = gearbox_type + 1
            if gearbox_type == 4 then
                gearbox_type = 0
            end
        end
        os.sleep(0.2)
    end
    
    

    -- 手刹
    if joy_x == true then
        if parking_brake == 1 then
            parking_brake = 0
            
        else
            parking_brake = 1
        end
        os.sleep(0.1)
    end

    if parking_brake == 1 then
        speed = 0

    end

    
    if gearbox_type ~= 0 then
        if parking_brake == 0 then
            -- 引擎速度(轮速->齿轮比->引擎速度)
            engine_speed_ctl()
        end
        -- 引擎油门(节气门)
        engine_accelerator()

        if parking_brake == 0 then
        -- 轮速度(引擎速度->齿轮比->轮速)
        speed_ctl()
        end
    end

    speedcontroller.setTargetSpeed(speed) -- 这东西不放这会出问题=-=

    if gearbox_type ~= 0 then
        car_ctl_auto()
    else
        car_ctl_mt()
    end

    speedcontroller.setTargetSpeed(speed) -- 将轮速更改实施
    
    -- 模拟声浪
    speaker.playNote("didgeridoo",(math.max(engine_speed / 26, 0.5)),(engine_speed / 8))

    -- hud渲染
    hud(speed,gear,rpm,relspeed)    
end





-- 主循环(有很多东西可以简化成funciton)
while true do
    
    startengine()
    if startup == 0.9 then
        main()
    end
end

配置文件

ConfigVer = 1.1
-- 配置文件版本请勿更改
hud_type = 0 -- 为自定义hud做准备
parking_brake = 1 -- 手刹
-- 初始化变速箱
gear = 0
speed = 0
gearbox_type = 0
-- 0 = MT
-- 1 = auto_snug
-- 2 = auto_sports
-- 3 = auto_overload
-- 初始化引擎
engine_speed = 0 -- 启动转速
maxSpeed = 80 -- 最大转速(此处仅为启动时最大转速)
acceleration = 3 -- 加速率(同上)
deceleration = 2 -- 减速率(同上)
throttle = 0.0 -- 油门
load = 0 -- 负载(负载=车重*一个很迷的数?)
mass = 0.6 -- 车重(负载基数)
startup = 1.6 -- 引擎启动参数 -1:待命 0.9:启动 1.6:执行启动动作
-- 初始化其他参数
relspeed = 0 -- 真实速度(m/s)

-- 变速箱基数(齿轮比)引擎速度 * 基数 = 轮速
gearr = -1
gearn = 0
gear1 = 1
gear2 = 2
gear3 = 3
gear4 = 4
gear5 = 5