News:

Do you need help?
Simutrans Wiki Manual can help you to play and extend Simutrans. In 9 languages.

Overtaking road vehicles are displayed in wrong depth order

Started by iv5343, November 27, 2023, 11:24:49 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

iv5343

This is a bug in Simutrans r11010 and earlier, file road_vehicle.cc.

Symptoms: Overtaking vehicles are displayed in wrong depth order, i.e. a back lane vehicle in front of a front lane vehicle, depending on their heading.  The effect is not visible if the vehicles are too far apart and/or not tall enough to cover one another, I recommend verification with double-decker buses and trams.  There are also still other bugs which may interfere.

Cause: For road users Simutrans distinguishes five parallel lanes to draw vehicles on different lanes in correct back to front order.  Taking the driver's perspective they have ascending numbers from leftmost to rightmost, and vehicles are sorted in ascending order by that number for display.  That means for vehicles moving to the left side of the screen, i.e. with a heading between SE and NW clockwise, the lane number must be mirrored.  This is done by the calc_disp_lane() method.  It considers if this is a left or right side driving world, but not if the vehicle is temporarily on the opposite lane because it overtakes another vehicle.

Overtaking is considered and initiated before a vehicle enters a tile with a potential obstacle.  road_vehicle_t::enter_tile() calls calc_disp_lane() and later cnv->update_tiles_overtaking() which decrements a distance counter.  The overtaking process concludes when that counter drops to zero.  I propose the following changes:

void road_vehicle_t::calc_disp_lane()
{
        disp_lane = welt->get_settings().is_drive_left() ? 1 : 3;
        /* disp_lane is valid for vehicles moving to the right side of
           the screen, must be mirrored if SE < heading < NW, and also
           if overtaking. */
        bool heading_left = (get_direction() & ribi_t::southwest) != 0;
        if (heading_left ^ (cnv && cnv->is_overtaking()))
                disp_lane ^= 2;
}

Please don't delete the comment, ribi_t::southwest is confusing because that's a bit set (South and West), not the heading angle SW.

In road_vehicle_t::enter_tile(): Call update_tiles_overtaking() before calc_disp_lane().

private_car_t has similar code and these vehicles can also overtake, may need to be fixed too.

prissi


iv5343

Sorry, no cigar yet.  In road_vehicle_t::enter_tile() update_tiles_overtaking() needs to happen before calc_disp_lane() as I wrote, otherwise the vehicles of an overtaking convoi_t are displayed in wrong order when it jumps back to the original lane.

This is really the same bug as here: The leading vehicle of a convoi_t enters a tile, updates disp_lane with overtaking on, then cnv->update_tiles_overtaking() disables overtaking for the entire convoi_t.  The next vehicle enters the tile, updates disp_lane with overtaking off.  The vehicles are reversed now as far as objlist_t::intern_add_moving() can tell and you get a visual glitch until the leader's disp_lane is updated with a one tile delay.  I can attach a saved game which shows this clearly.

The remaining code in the function, vehicle_t::enter_tile() seems to ignore the overtaking state and I assumed the same about the statistics update.

prissi

This means also update the overking code first for the leading car, as otherwise trailers will overtake longer than the leading car. I hope I did what you intended to do. In my pak64 overtaking test game, there is absolutely no visual difference though.

iv5343

Thanks.  Here's my test game, pak128.  I use my own vehicles because the size, shape, and colors of the standard artwork tends to mask bugs.  If you want to compare before and after, the defect hits on tile 10,10 and 8,18.

overtake-test3.sve
test-vehicles.tar.gz