diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2023-09-26 17:52:55 +0200 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2023-09-26 17:52:55 +0200 |
commit | 1a7ea4ba50f57c424a5d5beb08c0a6b24d6b89ca (patch) | |
tree | 435ca4fc982a0f0119fdceac44094e2e305b52e6 /scene | |
parent | dc14f028925829c908acb96f087bcef51659f771 (diff) | |
parent | 20d6a9b2e1238a6304161a594302d35a078e9de3 (diff) | |
download | redot-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.cpp | 12 |
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); } |