| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- -- This example compares two render paths when physics runs in fixed timestep mode:
- -- 1) not_interpolated_block: visual representation copies physics representation transform directly
- local not_interpolated_block = {
- physics_go = "/block1",
- sprite_go = "/block1_sprite",
- }
- -- 2) interpolated_block: visual representation is interpolated between previous and current fixed states
- local interpolated_block = {
- physics_go = "/block2",
- sprite_go = "/block2_sprite",
- }
- -- Store fixed update interval in seconds from game.project Fixed Update Frequency.
- local fixed_dt = 1 / (sys.get_config_number("engine.fixed_update_frequency") or 20)
- function init(self)
- -- Render-time remainder inside the current fixed-step interval.
- self.render_accumulator = 0
- -- Two-sample buffer for interpolation:
- -- previous_* = transform from previous fixed update
- -- current_* = transform from current fixed update
- -- Initialize both from real physics representation state.
- self.previous_fixed_position = go.get_position(interpolated_block.physics_go)
- self.current_fixed_position = self.previous_fixed_position
- self.previous_fixed_rotation = go.get_rotation(interpolated_block.physics_go)
- self.current_fixed_rotation = self.previous_fixed_rotation
- end
- function fixed_update(self, dt)
- -- Shift the transform data from current state to previous state
- -- and sample new fixed state from the game object with the dynamic collision object component.
- self.previous_fixed_position = self.current_fixed_position
- self.previous_fixed_rotation = self.current_fixed_rotation
- self.current_fixed_position = go.get_position(interpolated_block.physics_go)
- self.current_fixed_rotation = go.get_rotation(interpolated_block.physics_go)
- end
- function update(self, dt)
- -------------------------------------------------------------------------------------
- -- For not interpolated object:
- -------------------------------------------------------------------------------------
- -- Copy physics transform directly to the visual representation.
- local not_interpolated_position = go.get_position(not_interpolated_block.physics_go)
- local not_interpolated_rotation = go.get_rotation(not_interpolated_block.physics_go)
- go.set_position(not_interpolated_position, not_interpolated_block.sprite_go)
- go.set_rotation(not_interpolated_rotation, not_interpolated_block.sprite_go)
- -------------------------------------------------------------------------------------
- -- For interpolated object:
- -------------------------------------------------------------------------------------
- -- Keep accumulator inside [0, fixed_dt) using modulo wrap.
- self.render_accumulator = math.fmod(self.render_accumulator + dt, fixed_dt)
- -- Base alpha from render progress between fixed samples:
- -- alpha=0 -> previous sample, alpha=1 -> current sample.
- local alpha = self.render_accumulator / fixed_dt
- -- Calculate the difference between the current and previous fixed positions.
- local position_difference = self.current_fixed_position - self.previous_fixed_position
- -- Position interpolation is linear (lerp).
- local interpolated_position = self.previous_fixed_position + position_difference * alpha
- -- Rotation interpolation is spherical (slerp).
- local interpolated_rotation = vmath.slerp(alpha, self.previous_fixed_rotation, self.current_fixed_rotation)
- -- Render blended transform.
- go.set_position(interpolated_position, interpolated_block.sprite_go)
- go.set_rotation(interpolated_rotation, interpolated_block.sprite_go)
- end
|