; Deterministic avenue traffic; stationary cars stay near the curb. AnimateCityCars3D PROC uses ebx esi edi local trafficClock:DWORD mov eax, cityClock3D ; A red-light interval lets the protagonist cross from the alley. ; Resume from the stopped position instead of jumping forward in world space. cmp eax,7000 jb city_traffic_clock_ready cmp eax,8400 jae city_traffic_wait sub eax,7000 mov ebx,eax imul eax,eax xor edx,edx mov ecx,2800 div ecx sub ebx,eax lea eax,[ebx+7000] jmp city_traffic_clock_ready city_traffic_wait: cmp eax,14300 jae city_traffic_resume mov eax,7700 jmp city_traffic_clock_ready city_traffic_resume: cmp eax,15700 jae city_traffic_cruise sub eax,14300 imul eax,eax xor edx,edx mov ecx,2800 div ecx add eax,7700 jmp city_traffic_clock_ready city_traffic_cruise: sub eax,7300 city_traffic_clock_ready: mov trafficClock,eax mov ecx, FP_1/2500 mul ecx mov ecx, 26*FP_1 div ecx add edx, 3*FP_1 mov cityObjects3D[CITY_TRAFFIC_EAST*SIZEOF CityProp3D].posX, edx mov eax, trafficClock mov ecx, FP_1/2900 mul ecx mov ecx, 26*FP_1 div ecx mov eax, 29*FP_1 sub eax, edx mov cityObjects3D[CITY_TRAFFIC_WEST*SIZEOF CityProp3D].posX, eax mov esi, CITY_FIRST_CAR city_car_view: cmp esi, 12 je city_car_next cmp esi, 13 je city_car_next imul edi, esi, SIZEOF CityProp3D mov eax, playerX sub eax, cityObjects3D[edi].posX mov edx, playerY sub edx, cityObjects3D[edi].posY cmp esi, CITY_TRAFFIC_WEST jne @F neg eax neg edx @@: push eax push edx test eax, eax jns @F neg eax @@: test edx, edx jns @F neg edx @@: lea ebx, [edx*2] cmp eax, ebx ja city_car_longitudinal lea ebx, [eax*2] cmp edx, ebx ja city_car_lateral pop edx pop eax mov ebx, 1 test eax, eax jle @F mov ebx, 3 @@: test edx, edx jns city_car_set mov ebx, 7 test eax, eax jle city_car_set mov ebx, 5 jmp city_car_set city_car_longitudinal: pop edx pop eax xor ebx, ebx test eax, eax jle city_car_set mov ebx, 4 jmp city_car_set city_car_lateral: pop edx pop eax mov ebx, 2 test edx, edx jns city_car_set mov ebx, 6 city_car_set: mov eax, cityObjects3D[edi].frame and eax, 8 add eax, ebx mov cityObjects3D[edi].frame, eax city_car_next: inc esi cmp esi, CITY_TRAFFIC_WEST+1 jb city_car_view ret AnimateCityCars3D ENDP ; Pedestrians follow continuous curb routes, independently of rendering FPS. AnimateCityPedestrians3D PROC uses ebx esi edi local walkingFrame:DWORD xor esi, esi city_ped_route: imul ebx, esi, SIZEOF CityWalkRoute3D add ebx, OFFSET cityWalkRoutes3D mov eax, cityClock3D add eax, [ebx].CityWalkRoute3D.phaseOffset xor edx, edx mov ecx, [ebx].CityWalkRoute3D.halfPeriod shl ecx, 1 div ecx mov eax, edx mov edx, [ebx].CityWalkRoute3D.firstFrame mov walkingFrame, edx cmp eax, [ebx].CityWalkRoute3D.halfPeriod jb city_ped_forward sub eax, [ebx].CityWalkRoute3D.halfPeriod add walkingFrame, 8 mov ecx, [ebx].CityWalkRoute3D.maxX sub ecx, [ebx].CityWalkRoute3D.minX mul ecx div [ebx].CityWalkRoute3D.halfPeriod neg eax add eax, [ebx].CityWalkRoute3D.maxX jmp city_ped_position city_ped_forward: mov ecx, [ebx].CityWalkRoute3D.maxX sub ecx, [ebx].CityWalkRoute3D.minX ; Keep the high product: route distance * milliseconds exceeds 32 bits. mul ecx div [ebx].CityWalkRoute3D.halfPeriod add eax, [ebx].CityWalkRoute3D.minX city_ped_position: imul edi, [ebx].CityWalkRoute3D.objectIndex, SIZEOF CityProp3D mov cityObjects3D[edi].posX, eax mov eax, [ebx].CityWalkRoute3D.curbY mov cityObjects3D[edi].posY, eax mov eax, cityClock3D add eax, [ebx].CityWalkRoute3D.phaseOffset xor edx, edx div [ebx].CityWalkRoute3D.poseMs and eax, 7 add eax, walkingFrame mov cityObjects3D[edi].frame, eax inc esi cmp esi, CITY_PEDESTRIAN_COUNT jb city_ped_route ret AnimateCityPedestrians3D ENDP