Skip to content

Instantly share code, notes, and snippets.

@gnalvesteffer
Last active February 25, 2021 18:48
Show Gist options
  • Save gnalvesteffer/d56d6af2c966a76fc3d1a96a7a4547fa to your computer and use it in GitHub Desktop.
Save gnalvesteffer/d56d6af2c966a76fc3d1a96a7a4547fa to your computer and use it in GitHub Desktop.
Teardown | Actively Awaken Bodies Near Player
function init()
-- configuration
bodies_to_process_per_tick = 10 -- bodies to process per tick
chunk_refresh_interval = 10 -- the interval (in seconds) to refresh the chunk (only if current chunk has finished processing)
is_debug = true
-- chunk state
chunk_position = GetPlayerTransform().pos
chunk_bodies = {}
chunk_size = 50
chunk_tick = 0
chunk_last_refresh_time = 0
-- set up initial chunk
set_up_new_chunk()
end
function is_body_floating(body)
local min_bound, max_bound = GetBodyBounds(body)
local center_bottom_point = VecLerp(Vec(min_bound[1], min_bound[2], min_bound[3]), Vec(max_bound[1], min_bound[2], max_bound[3]), 0.5)
local did_ray_hit = QueryRaycast(center_bottom_point, Vec(0, -1, 0), 1)
return not did_ray_hit
end
function try_make_body_fall(body)
if not IsBodyDynamic(body) or not is_body_floating(body) then
return
end
local velocity = GetBodyVelocity(body)
local speed = VecLength(velocity)
if speed < 0.001 then
if is_debug then
DrawBodyOutline(body, 1)
end
SetBodyVelocity(body, VecAdd(velocity, Vec(0, -0.001, 0)))
end
end
function get_bodies_near_position(position, radius)
local min_point = VecAdd(position, Vec(-radius, -radius, -radius))
local max_point = VecAdd(position, Vec(radius, radius, radius))
return QueryAabbBodies(min_point, max_point)
end
function refresh_chunk_bodies()
chunk_last_refresh_time = GetTime()
chunk_bodies = {}
local bodies = get_bodies_near_position(chunk_position, chunk_size)
for i, body in ipairs(bodies) do
chunk_bodies[i] = body
end
end
function has_processed_all_bodies_and_requires_refresh()
local total_processed_bodies = math.min(chunk_tick * bodies_to_process_per_tick, #chunk_bodies)
return total_processed_bodies == #chunk_bodies and GetTime() - chunk_last_refresh_time >= chunk_refresh_interval
end
function needs_to_set_up_new_chunk()
local player_position = GetPlayerTransform().pos
local player_distance_from_current_chunk = VecLength(VecSub(player_position, chunk_position))
return player_distance_from_current_chunk >= chunk_size or has_processed_all_bodies_and_requires_refresh()
end
function set_up_new_chunk()
chunk_tick = 0
chunk_position = GetPlayerTransform().pos
refresh_chunk_bodies()
end
function process_chunk_bodies()
for i = chunk_tick * bodies_to_process_per_tick, math.min((chunk_tick + 1) * bodies_to_process_per_tick, #chunk_bodies) do
try_make_body_fall(chunk_bodies[i])
end
end
function update_current_chunk()
process_chunk_bodies()
chunk_tick = chunk_tick + 1
end
function tick(delta_time)
if needs_to_set_up_new_chunk() then
set_up_new_chunk()
else
update_current_chunk()
end
if is_debug then
DebugWatch("Total Chunk Bodies", #chunk_bodies)
-- highlight body/shape looked at
local hit, distance, normal, shape = QueryRaycast(GetCameraTransform().pos, TransformToParentVec(GetCameraTransform(), Vec(0, 0, -1)), 100)
if hit then
DrawBodyOutline(GetShapeBody(shape), 1, 0, 0, 0.5)
DrawShapeOutline(shape, 0, 1, 1, 0.5)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment