mirror of
https://github.com/SK8-ENGINE/skate-3-rust-engine.git
synced 2026-10-26 19:47:44 +00:00
Add generalized engine access and challenge mods, repair SKATE turn handling, and improve collision prediction and physics transitions. Reduce mod snapshot and material update overhead, preserve authored GLB materials with lighting and shadows, and improve CPU profiling.
186 lines
4.7 KiB
Lua
186 lines
4.7 KiB
Lua
local box_key = "crate"
|
|
local mass = 25
|
|
local friction = 0.35
|
|
local spawned = false
|
|
local attached = false
|
|
local prev = { e = false, r = false }
|
|
local log_cooldown = 0
|
|
local peak_speed = 0
|
|
local samples = 0
|
|
|
|
local function breakaway_newtons()
|
|
return friction * mass * 9.81
|
|
end
|
|
|
|
local function push_newtons()
|
|
return sdk.settings.push_newtons or 350
|
|
end
|
|
|
|
local function ground_y(x, z)
|
|
local hit = sdk.physics.raycast(
|
|
{ x, 500, z },
|
|
{ 0, -1, 0 },
|
|
{ max_distance = 1000, filter = "ground" }
|
|
)
|
|
if hit and hit.point then return hit.point[2] end
|
|
return 0
|
|
end
|
|
|
|
local function touching_ground(key)
|
|
for _, t in ipairs(sdk.physics.touching() or {}) do
|
|
if (t.a == key and t.b == "ground") or (t.b == key and t.a == "ground") then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function spawn_box()
|
|
if spawned then return end
|
|
local p = sdk.player.read().position
|
|
local gy = ground_y(p[1] + 3, p[3] + 3)
|
|
sdk.physics.spawn(box_key, {
|
|
shape = { type = "box", half_extents = { 0.5, 0.5, 0.5 } },
|
|
body_type = "dynamic",
|
|
mass = mass,
|
|
position = { p[1] + 3, gy + 0.55, p[3] + 3 },
|
|
heading = 0,
|
|
friction = friction,
|
|
ccd = true,
|
|
})
|
|
sdk.graphics.mesh("crate_vis", {
|
|
body = box_key,
|
|
scale = { 1, 1, 1 },
|
|
color = { 0.2, 0.65, 0.95 },
|
|
})
|
|
sdk.camera.follow(box_key, { 0, 3, -7 })
|
|
sdk.log(string.format(
|
|
"physics-sandbox: crate mass=%.0fkg friction=%.2f breakaway≈%.0fN push=%dN",
|
|
mass, friction, breakaway_newtons(), push_newtons()
|
|
))
|
|
spawned = true
|
|
peak_speed = 0
|
|
samples = 0
|
|
end
|
|
|
|
local function reset_box()
|
|
sdk.physics.remove(box_key)
|
|
sdk.graphics.remove("crate_vis")
|
|
if attached then
|
|
sdk.player.detach()
|
|
attached = false
|
|
end
|
|
spawned = false
|
|
spawn_box()
|
|
end
|
|
|
|
local function cmd_force()
|
|
local force = push_newtons()
|
|
local f = { 0, 0, 0 }
|
|
local keys = {}
|
|
if sdk.input.down("KeyW") then f[3] = f[3] + force; keys[#keys + 1] = "W" end
|
|
if sdk.input.down("KeyS") then f[3] = f[3] - force; keys[#keys + 1] = "S" end
|
|
if sdk.input.down("KeyA") then f[1] = f[1] - force; keys[#keys + 1] = "A" end
|
|
if sdk.input.down("KeyD") then f[1] = f[1] + force; keys[#keys + 1] = "D" end
|
|
return f, table.concat(keys, "")
|
|
end
|
|
|
|
return {
|
|
on_load = function()
|
|
sdk.ui.text("help", "Physics Sandbox — WASD push · E attach/detach · R reset")
|
|
spawn_box()
|
|
end,
|
|
|
|
on_fixed_update = function(ev)
|
|
if not spawned then
|
|
spawn_box()
|
|
end
|
|
|
|
local f, keys = cmd_force()
|
|
local driving = f[1] ~= 0 or f[3] ~= 0
|
|
if driving then
|
|
sdk.physics.force(box_key, f)
|
|
end
|
|
|
|
local e = sdk.input.down("KeyE")
|
|
if e and not prev.e then
|
|
if attached then
|
|
sdk.player.detach()
|
|
attached = false
|
|
sdk.log("detached")
|
|
else
|
|
sdk.player.attach(box_key, { 0, 1.1, 0 })
|
|
attached = true
|
|
sdk.log("attached to crate")
|
|
end
|
|
end
|
|
prev.e = e
|
|
|
|
local r = sdk.input.down("KeyR")
|
|
if r and not prev.r then
|
|
reset_box()
|
|
end
|
|
prev.r = r
|
|
|
|
local body = sdk.physics.read(box_key)
|
|
if not body then
|
|
return
|
|
end
|
|
|
|
samples = samples + 1
|
|
local speed = body.speed or 0
|
|
if speed > peak_speed then
|
|
peak_speed = speed
|
|
end
|
|
local rf = body.force or { 0, 0, 0 }
|
|
local p = body.position
|
|
local v = body.linvel
|
|
local need = breakaway_newtons()
|
|
local stuck = driving and speed < 0.05 and push_newtons() < need
|
|
|
|
sdk.ui.text(
|
|
"status",
|
|
string.format(
|
|
"pos %.1f %.1f %.1f | vel %.2f %.2f %.2f | speed %.2f (peak %.2f)\ncmd force %.0f %.0f %.0f | read force %.0f %.0f %.0f | keys %s | μmg≈%.0fN | gnd %s%s",
|
|
p[1], p[2], p[3],
|
|
v[1], v[2], v[3],
|
|
speed, peak_speed,
|
|
f[1], f[2], f[3],
|
|
rf[1], rf[2], rf[3],
|
|
keys ~= "" and keys or "-",
|
|
need,
|
|
touching_ground(box_key) and "yes" or "no",
|
|
stuck and " | STUCK: raise Push force" or ""
|
|
)
|
|
)
|
|
|
|
log_cooldown = log_cooldown - (ev and ev.dt or (1 / 60))
|
|
local runaway = (not driving) and speed > 1.5 and speed >= peak_speed * 0.98
|
|
if log_cooldown <= 0 or runaway or stuck then
|
|
log_cooldown = (runaway or stuck) and 0.25 or 1.0
|
|
sdk.log(string.format(
|
|
"crate tick=%d pos=(%.2f,%.2f,%.2f) vel=(%.2f,%.2f,%.2f) speed=%.2f cmdF=(%.0f,%.0f,%.0f) readF=(%.0f,%.0f,%.0f) keys=%s stuck=%s",
|
|
samples,
|
|
p[1], p[2], p[3],
|
|
v[1], v[2], v[3],
|
|
speed,
|
|
f[1], f[2], f[3],
|
|
rf[1], rf[2], rf[3],
|
|
keys ~= "" and keys or "-",
|
|
stuck and "yes" or "no"
|
|
))
|
|
end
|
|
end,
|
|
|
|
on_event = function(ev)
|
|
if ev.name == "world_changed" then
|
|
spawned = false
|
|
attached = false
|
|
prev.e = false
|
|
prev.r = false
|
|
peak_speed = 0
|
|
samples = 0
|
|
end
|
|
end,
|
|
}
|