Simutrans Wiki Manual
The official on-line manual for Simutrans. Read and contribute.

When a road vehicle stops, then overtakes it leaves pixel garbage behind

Started by iv5343, December 06, 2023, 09:50:03 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.


This is a bug in Simutrans r11015 and earlier.  It can be observed when a road vehicle stops because another loading vehicle blocks the road and the conditions for overtaking are not met.  When the conditions change the overtaking convoi_t jumps to the other lane and parts of its images remain on screen in the old position.  It does not depend on the number of vehicles in the convoi, their size, or driving direction.  The stale pixels disappear when another object is later displayed at the old position.

The cause is that convoi_t::step() indirectly calls can_overtake() which enables overtaking, then changes the state to driving, and sync_step() calls do_drive() for the vehicles of the convoi_t.  mark_image_dirty() fails to mark the old position in the flush buffer because road_vehicle_t::get_screen_offset() adds a lane offset if the convoi_t is overtaking and already points at the new position.

The same problem exists when a moving convoi_t overtakes:  The leading vehicle enables or disables overtaking, then do_drive() runs for the trailing vehicles and mark_image_dirty() uses the wrong offset.  However no glitch is visible in this case, in fact if mark_image_dirty() runs seems inconsequential, that puzzled me for a while.  Well the answer is the bug has an accomplice in display_flush_buffer() which copies dirty pixels twice to the screen.  The old position was marked when the trailing vehicles moved there and these bits are still in the tile_dirty_old buffer.  When the convoi_t stops for more than one display cycle they are evicted and the cover-up fails.

I suppose get_screen_offset() should check if this vehicle is overtaking or overtaken, not the state of the convoi_t, and the vehicle state is updated after mark_image_dirty().

I didn't test private cars, the similarity of private_car_t::get_screen_offset() suggests they are also affected.


That situation seems quite rare. get_screen_offset() is one of the few functions that are called very often and are performance critical. As I had trouble to generate a case to reproduce it, I am almost tempted to put this under "known bug".


Actually I'd prefer if overtaking looked more like this, no lane hopping at all, except it needs to start earlier.



Isaac Eiland-Hall

Maybe a way of specifying new images to be used if they are added to the pak (vehicle pak), but it reverts to using a diagonal if they're not included (for backwards compatibility)?