summaryrefslogtreecommitdiffstats
path: root/scene
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2023-09-26 17:52:55 +0200
committerRémi Verschelde <rverschelde@gmail.com>2023-09-26 17:52:55 +0200
commit1a7ea4ba50f57c424a5d5beb08c0a6b24d6b89ca (patch)
tree435ca4fc982a0f0119fdceac44094e2e305b52e6 /scene
parentdc14f028925829c908acb96f087bcef51659f771 (diff)
parent20d6a9b2e1238a6304161a594302d35a078e9de3 (diff)
downloadredot-engine-1a7ea4ba50f57c424a5d5beb08c0a6b24d6b89ca.tar.gz
Merge pull request #82360 from kleonc/tilemap-tile-animation-time-float-error
Fix animated tile time-slice calculation accumulating float errors
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/tile_map.cpp12
1 files changed, 8 insertions, 4 deletions
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index cbcd136438..7b0bd7e26c 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -3146,15 +3146,19 @@ void TileMap::draw_tile(RID p_canvas_item, const Vector2 &p_position, const Ref<
} else {
real_t speed = atlas_source->get_tile_animation_speed(p_atlas_coords);
real_t animation_duration = atlas_source->get_tile_animation_total_duration(p_atlas_coords) / speed;
- real_t time = 0.0;
+ // Accumulate durations unaffected by the speed to avoid accumulating floating point division errors.
+ // Aka do `sum(duration[i]) / speed` instead of `sum(duration[i] / speed)`.
+ real_t time_unscaled = 0.0;
for (int frame = 0; frame < atlas_source->get_tile_animation_frames_count(p_atlas_coords); frame++) {
- real_t frame_duration = atlas_source->get_tile_animation_frame_duration(p_atlas_coords, frame) / speed;
- RenderingServer::get_singleton()->canvas_item_add_animation_slice(p_canvas_item, animation_duration, time, time + frame_duration, p_animation_offset);
+ real_t frame_duration_unscaled = atlas_source->get_tile_animation_frame_duration(p_atlas_coords, frame);
+ real_t slice_start = time_unscaled / speed;
+ real_t slice_end = (time_unscaled + frame_duration_unscaled) / speed;
+ RenderingServer::get_singleton()->canvas_item_add_animation_slice(p_canvas_item, animation_duration, slice_start, slice_end, p_animation_offset);
Rect2i source_rect = atlas_source->get_runtime_tile_texture_region(p_atlas_coords, frame);
tex->draw_rect_region(p_canvas_item, dest_rect, source_rect, modulate, transpose, p_tile_set->is_uv_clipping());
- time += frame_duration;
+ time_unscaled += frame_duration_unscaled;
}
RenderingServer::get_singleton()->canvas_item_add_animation_slice(p_canvas_item, 1.0, 0.0, 1.0, 0.0);
}