From b7112b32847a7e8296acb0ac307d4ce2b0c0bf4f Mon Sep 17 00:00:00 2001 From: dwachs Date: Thu, 30 Mar 2017 20:45:55 +0200 Subject: [PATCH 3/3] CHG: simple and better method to sort moving objects on tiles --- simutrans/trunk/dataobj/objlist.cc | 127 ++++++------------------------ simutrans/trunk/vehicle/simpeople.cc | 19 +++++ simutrans/trunk/vehicle/simpeople.h | 7 ++ simutrans/trunk/vehicle/simroadtraffic.cc | 16 +++- simutrans/trunk/vehicle/simroadtraffic.h | 4 + simutrans/trunk/vehicle/simvehicle.cc | 19 +++++ simutrans/trunk/vehicle/simvehicle.h | 19 +++++ 7 files changed, 107 insertions(+), 104 deletions(-) diff --git a/simutrans/trunk/dataobj/objlist.cc b/simutrans/trunk/dataobj/objlist.cc index 8aa3032..b7bed73 100644 --- a/simutrans/trunk/dataobj/objlist.cc +++ b/simutrans/trunk/dataobj/objlist.cc @@ -290,14 +290,17 @@ bool objlist_t::intern_add_moving(obj_t* new_obj) // vehicles types (number returned by get_typ()). However, this would increase // the calculation even further. :( + // insert at this lane + uint8 lane = ((vehicle_base_t*)new_obj)->get_disp_lane(); + // find out about the first car etc. moving thing. // We can start to insert between (start) and (end) uint8 start=0; - while(startis_moving() ) { + while(startis_moving() || ((vehicle_base_t*)obj.some[start])->get_disp_lane() < lane) ) { start ++; } uint8 end = top; - while( end>start && !obj.some[end-1]->is_moving() ) { + while( end>start && (!obj.some[end-1]->is_moving() || ((vehicle_base_t*)obj.some[end-1])->get_disp_lane() > lane) ) { end--; } if(start==end) { @@ -305,116 +308,34 @@ bool objlist_t::intern_add_moving(obj_t* new_obj) return true; } - // if we have two ways, the way at index 0 is ALWAYS the road! - // however ships and planes may be where not way is below ... - if(start!=0 && obj.some[0]->get_typ()==obj_t::way && ((weg_t *)obj.some[0])->get_waytype()==road_wt) { - - const uint8 fahrtrichtung = ((vehicle_base_t*)new_obj)->get_direction(); - - // this is very complicated: - // we may have many objects in two lanes (actually five with tram and pedestrians) - if(world()->get_settings().is_drive_left()) { - - // driving on left side - if(fahrtrichtung<4) { // north, northwest - - if((fahrtrichtung&(~ribi_t::southeast))==0) { - // if we are going east we must be drawn as the first in east direction - intern_insert_at(new_obj, start); - return true; - } - else { - // we must be drawn before south or west (thus insert after) - for(uint8 i=start; iget_direction()&ribi_t::southwest) != 0) { - intern_insert_at(new_obj, i); - return true; - } - } - // nothing going southwest - intern_insert_at(new_obj, end); - return true; - } + const uint8 direction = ((vehicle_base_t*)new_obj)->get_direction(); + switch(lane) { + // pedestrians or road vehicles, back: either w/sw/s or n/ne/e + case 0: + case 1: { + // on right side to w,sw; on left to n: insert last + // on right side to s; on left to ne,e: insert first + if (direction == ribi_t::south || (direction & ribi_t::east)) { + intern_insert_at(new_obj, start); } else { - // going south, west or the rest - if((fahrtrichtung&(~ribi_t::southeast))==0) { - // if we are going south or southeast we must be drawn as the first in east direction (after north and northeast) - for(uint8 i=start; i(dt)) { - if ((v->get_direction() & ribi_t::southwest) != 0) { - intern_insert_at(new_obj, i); - return true; - } - } - } - } - } - // nothing going southeast intern_insert_at(new_obj, end); - return true; } + return true; } - else { - // driving on right side - if(fahrtrichtung<4) { // north, east, northeast - - if((fahrtrichtung&(~ribi_t::southeast))==0) { - - // if we are going east we must be drawn as the first in east direction (after north and northeast) - for(uint8 i=start; iget_direction()&ribi_t::northeast) != 0) { - intern_insert_at(new_obj, i); - return true; - } - } - // nothing going to the east - } - // we must be drawn before south or west (thus append after) - intern_insert_at(new_obj, end); - return true; - + // middle land + case 2: + case 3: + // pedestrians, road vehicles, front lane + case 4: { + // going e/s: insert first, else last + if ( (direction & ribi_t::northwest)==0 ) { + intern_insert_at(new_obj, start); } else { - // going south, west or the rest - - if((fahrtrichtung&(~ribi_t::southeast))==0) { - // going south or southeast, insert as first in this dirs - intern_insert_at(new_obj, start); - return true; - } - else { - for(uint8 i=start; iget_direction()&ribi_t::southwest) == 0) { - intern_insert_at(new_obj, i); - return true; - } - } - // nothing going to northeast - intern_insert_at(new_obj, end); - return true; - } + intern_insert_at(new_obj, end); } - - } // right side/left side - - } - else { - // ok, we have to sort vehicles for correct overlapping, - // but all vehicles are of the same typ, since this is track/channel etc. ONLY! - - // => much simpler to handle - if((((vehicle_t*)new_obj)->get_direction()&(~ribi_t::southeast))==0) { - // if we are going east or south, we must be drawn before (i.e. put first) - intern_insert_at(new_obj, start); - return true; - } - else { - // for north east we must be draw last - intern_insert_at(new_obj, end); return true; } } diff --git a/simutrans/trunk/vehicle/simpeople.cc b/simutrans/trunk/vehicle/simpeople.cc index 3996a3a..c5659ed 100644 --- a/simutrans/trunk/vehicle/simpeople.cc +++ b/simutrans/trunk/vehicle/simpeople.cc @@ -72,6 +72,7 @@ pedestrian_t::pedestrian_t(loadsave_t *file) welt->sync.add(this); ped_offset = desc->get_offset(); } + calc_disp_lane(); } @@ -85,6 +86,7 @@ pedestrian_t::pedestrian_t(grund_t *gr) : time_to_life = pick_any(strecke); ped_offset = desc->get_offset(); calc_image(); + calc_disp_lane(); } @@ -142,10 +144,26 @@ void pedestrian_t::rdwr(loadsave_t *file) file->rdwr_short(steps_offset); file->rdwr_bool(on_left); } + + if (file->is_loading()) { + calc_disp_lane(); + } } +void pedestrian_t::calc_disp_lane() +{ + // walking in the back or the front + ribi_t::ribi test_dir = on_left ? ribi_t::northeast : ribi_t::southwest; + disp_lane = direction & test_dir ? 0 : 4; +} +void pedestrian_t::rotate90() +{ + road_user_t::rotate90(); + calc_disp_lane(); +} + // create a number (count) of pedestrians (if possible) void pedestrian_t::generate_pedestrians_at(const koord3d k, int &count) { @@ -287,6 +305,7 @@ void pedestrian_t::hop(grund_t *gr) on_left = !on_left; } + calc_disp_lane(); // carry over remainder to next tile for continuous animation during straight movement uint16 steps_per_animation = desc->get_steps_per_frame() * desc->get_animation_count(ribi_t::get_dir(direction)); if (steps_per_animation > 0) { diff --git a/simutrans/trunk/vehicle/simpeople.h b/simutrans/trunk/vehicle/simpeople.h index a77ab88..578a3e0 100644 --- a/simutrans/trunk/vehicle/simpeople.h +++ b/simutrans/trunk/vehicle/simpeople.h @@ -47,6 +47,13 @@ public: sync_result sync_step(uint32 delta_t); + ///@ returns true if pedestrian walks on the left side of the road + bool is_on_left() const { return on_left; } + + void calc_disp_lane(); + + virtual void rotate90(); + // overloaded to enable animations virtual image_id get_image() const; diff --git a/simutrans/trunk/vehicle/simroadtraffic.cc b/simutrans/trunk/vehicle/simroadtraffic.cc index a572ddb..3b828c6 100644 --- a/simutrans/trunk/vehicle/simroadtraffic.cc +++ b/simutrans/trunk/vehicle/simroadtraffic.cc @@ -329,6 +329,7 @@ private_car_t::private_car_t(loadsave_t *file) : { rdwr(file); ms_traffic_jam = 0; + calc_disp_lane(); if(desc) { welt->sync.add(this); } @@ -350,6 +351,7 @@ private_car_t::private_car_t(grund_t* gr, koord const target) : (void)target; #endif calc_image(); + calc_disp_lane(); welt->buche( +1, karte_t::WORLD_CITYCARS ); } @@ -460,7 +462,6 @@ void private_car_t::rdwr(loadsave_t *file) file->rdwr_byte(tiles_overtaking); set_tiles_overtaking( tiles_overtaking ); } - // do not start with zero speed! current_speed ++; } @@ -629,6 +630,7 @@ void private_car_t::enter_tile(grund_t* gr) } #endif vehicle_base_t::enter_tile(gr); + calc_disp_lane(); gr->get_weg(road_wt)->book(1, WAY_STAT_CONVOIS); } @@ -857,6 +859,18 @@ void private_car_t::get_screen_offset( int &xoff, int &yoff, const sint16 raster } +void private_car_t::calc_disp_lane() +{ + // driving in the back or the front + ribi_t::ribi test_dir = welt->get_settings().is_drive_left() ? ribi_t::northeast : ribi_t::southwest; + disp_lane = get_direction() & test_dir ? 1 : 3; +} + +void private_car_t::rotate90() +{ + road_user_t::rotate90(); + calc_disp_lane(); +} /** * conditions for a city car to overtake another overtaker. diff --git a/simutrans/trunk/vehicle/simroadtraffic.h b/simutrans/trunk/vehicle/simroadtraffic.h index 173cc69..c5f0372 100644 --- a/simutrans/trunk/vehicle/simroadtraffic.h +++ b/simutrans/trunk/vehicle/simroadtraffic.h @@ -95,6 +95,8 @@ private: grund_t* hop_check(); + void calc_disp_lane(); + protected: void rdwr(loadsave_t *file); @@ -111,6 +113,8 @@ public: virtual ~private_car_t(); + virtual void rotate90(); + const citycar_desc_t *get_desc() const { return desc; } sync_result sync_step(uint32 delta_t); diff --git a/simutrans/trunk/vehicle/simvehicle.cc b/simutrans/trunk/vehicle/simvehicle.cc index 53d0211..0016d89 100644 --- a/simutrans/trunk/vehicle/simvehicle.cc +++ b/simutrans/trunk/vehicle/simvehicle.cc @@ -185,6 +185,7 @@ vehicle_base_t::vehicle_base_t(): dx = 0; dy = 0; zoff_start = zoff_end = 0; + disp_lane = 2; } @@ -200,6 +201,7 @@ vehicle_base_t::vehicle_base_t(koord3d pos): dx = 0; dy = 0; zoff_start = zoff_end = 0; + disp_lane = 2; } @@ -219,6 +221,7 @@ void vehicle_base_t::rotate90() sint8 neu_yoff = get_xoff()/2; set_xoff( -get_yoff()*2 ); set_yoff( neu_yoff ); + // adjust disp_lane individually } @@ -1841,10 +1844,25 @@ road_vehicle_t::road_vehicle_t(loadsave_t *file, bool is_first, bool is_last) : if( desc ) { last_desc = desc; } + calc_disp_lane(); } } +void road_vehicle_t::rotate90() +{ + vehicle_t::rotate90(); + calc_disp_lane(); +} + + +void road_vehicle_t::calc_disp_lane() +{ + // driving in the back or the front + ribi_t::ribi test_dir = welt->get_settings().is_drive_left() ? ribi_t::northeast : ribi_t::southwest; + disp_lane = get_direction() & test_dir ? 1 : 3; +} + // need to reset halt reservation (if there was one) bool road_vehicle_t::calc_route(koord3d start, koord3d ziel, sint32 max_speed, route_t* route) { @@ -2282,6 +2300,7 @@ overtaker_t* road_vehicle_t::get_overtaker() void road_vehicle_t::enter_tile(grund_t* gr) { vehicle_t::enter_tile(gr); + calc_disp_lane(); const int cargo = get_total_cargo(); weg_t *str = gr->get_weg(road_wt); diff --git a/simutrans/trunk/vehicle/simvehicle.h b/simutrans/trunk/vehicle/simvehicle.h index 9cfe072..66db6b5 100644 --- a/simutrans/trunk/vehicle/simvehicle.h +++ b/simutrans/trunk/vehicle/simvehicle.h @@ -61,6 +61,19 @@ protected: // true on slope (make calc_height much faster) uint8 use_calc_height:1; + /** + * Thing is moving on this lane. + * Possible values: + * (Back) + * 0 - sidewalk (going on the right side to w/sw/s) + * 1 - road (going on the right side to w/sw/s) + * 2 - middle (everything with waytype != road) + * 3 - road (going on the right side to se/e/../nw) + * 4 - sidewalk (going on the right side to se/e/../nw) + * (Front) + */ + uint8 disp_lane:3; + sint8 dx, dy; // number of steps in this tile (255 per tile) @@ -121,6 +134,8 @@ public: sint16 get_hoff(const sint16 raster_width=1) const; uint8 get_steps() const {return steps;} + uint8 get_disp_lane() const { return disp_lane; } + // to make smaller steps than the tile granularity, we have to calculate our offsets ourselves! virtual void get_screen_offset( int &xoff, int &yoff, const sint16 raster_width ) const; @@ -486,6 +501,10 @@ protected: public: virtual void enter_tile(grund_t*); + virtual void rotate90(); + + void calc_disp_lane(); + virtual waytype_t get_waytype() const { return road_wt; } road_vehicle_t(loadsave_t *file, bool first, bool last); -- 1.8.4.5