#include #include #include #include #include #include #include #include #include #include #include #include "parameters.h" #include "colors.h" #include "include/camera.h" #include "include/segment.h" #include "include/circuit.h" #include "include/drawstuff.h" #include "include/clouds.h" #include "include/cars.h" #include "include/menus.h" //extern bopti_image_t car1, car2, car3, car4, car5, car6, car7, car8; //extern bopti_image_t tree1, tree2, tree3, tree4, tree5, tree6; //extern bopti_image_t leftturn, rightturn, uphill, downhill; //extern bopti_image_t checkpoint, startlights, stoplights, waitlights; extern bopti_image_t player; //extern bopti_image_t sky1, sky2, sky3; //extern bopti_image_t mountain, treeline; //extern bopti_image_t mainscreen; extern font_t speedfont; extern bopti_image_t speedhud; int CurrentCircuitBiome = PLAINS; std::vector circuit; int MAX_SEGMENT=0; camera *cam; std::vector nuages; std::vector traffic; bool stop = false; bool record = false; bool screenshot = false; bool ShowDebug1 = false; bool ShowDebug2 = false; bool ShowDebug3 = false; bool BDrawDeco = true; bool BDrawClds = true; bool BDrawCars = true; bool BDrawRoad = true; uint16_t currentcurve=0; uint8_t shiftcolor=0; float speed = 0.0; float maxspeedforward = 5.0; float maxspeedbackward = 2.0; int direction = 1; bool speedcontrol = false; uint8_t minYRoad = 224; // We will track the upper Y (in fact the minimum Y during the RoadDrawing to optimize the rendering of the Sky int8_t viewside = 0; int deltaFarbackground = 0; int deltaNearbackground = 0; int lastindex=0; int CC=0; // current curve int CS=0; static void get_inputs( float dt, int index ) { CC = circuit[index]->Curve; CS = circuit[index]->Slope; key_event_t ev; while((ev = pollevent()).type != KEYEV_NONE) { } speedcontrol = false; viewside=0; if (CC<0) { viewside=-1; cam->decX( CC*dt*speed/100 ); } else if (CC>0) { viewside=+1; cam->decX( CC*dt*speed/100 ); } if(keydown(KEY_LEFT)) { cam->decX(25.0); viewside=-1; if (CC<0) viewside=-2; // We are in a curve and turning if (CC>0) viewside=0; } if(keydown(KEY_RIGHT)) { cam->incX(25.0); viewside=1; if (CC>0) viewside=+2; if (CC<0) viewside=0; } if(keydown(KEY_SHIFT)) { if (direction==-1 && speed > 0) { direction = -1; speed -= 0.5; if (speed<0) speed=0; cam->decZ(speed*dt); } else { direction = 1; speed+=0.05; if (speed>maxspeedforward) speed=maxspeedforward; cam->incZ(speed*dt); } speedcontrol = true; } if(keydown(KEY_ALPHA)) { if (direction==1 && speed > 0) { direction = 1; speed -= 0.5; if (speed<0) speed=0; cam->incZ(speed*dt); } else { direction = -1; speed+=0.025; if (speed>maxspeedbackward) speed=maxspeedbackward; cam->decZ(speed*dt); } speedcontrol = true; } if(keydown(KEY_EXIT)) stop = true; #if IS_FXLIB==1 if(keydown(KEY_XOT)) { ShowDebug1 = false; ShowDebug2 = false; ShowDebug3 = false; } if(keydown(KEY_LOG)) { ShowDebug1 = true; ShowDebug2 = false; ShowDebug3 = false; } if(keydown(KEY_LN)) { ShowDebug1 = false; ShowDebug2 = true; ShowDebug3 = false; } if(keydown(KEY_SIN)) { ShowDebug1 = false; ShowDebug2 = false; ShowDebug3 = true; } if(keydown(KEY_F1)) BDrawDeco = !BDrawDeco; if(keydown(KEY_F2)) BDrawClds = !BDrawClds; if(keydown(KEY_F3)) BDrawCars = !BDrawCars; if(keydown(KEY_F4)) BDrawRoad = !BDrawRoad; if(keydown(KEY_F5)) screenshot = true; if(keydown(KEY_F6)) record = !record; #endif // IS_FXLIB if (speedcontrol==false) { speed-=0.3; if (speed<0) speed=0; if (direction==1) cam->incZ(speed*dt); else cam->decZ(speed*dt); } /* Adjust position of the background */ if (lastindex!=index) { deltaFarbackground -= CC*speed*dt/250; deltaNearbackground -= CC*speed*dt/100; } lastindex = index; /* adjust speed if we drive on the side of the road */ if (fround(cam->cX)<-1*ROAD_WIDTH && speed>2.0) speed=2.0; if (fround(cam->cX)>ROAD_WIDTH && speed>2.0) speed=2.0; if (fround(cam->cX)<-1.35*ROAD_WIDTH && speed>0.0) { speed=0.0; cam->cX=fix(-0.75*ROAD_WIDTH); } if (fround(cam->cX)>1.35*ROAD_WIDTH && speed>0.0) { speed=0.0; cam->cX=fix(0.75*ROAD_WIDTH); } } int main(void) { __printf_enable_fp(); __printf_enable_fixed(); #if IS_FXLIB==1 usb_interface_t const *interfaces[] = { &usb_ff_bulk, NULL }; usb_open(interfaces, GINT_CALL_NULL); #endif prof_t perf_update, perf_create, perf_project, perf_render; int32_t start_time = 99000000; uint32_t score=99999; uint8_t stage=0; uint8_t selectedCircuit=0; uint32_t time_update=0, time_create=0, time_project=0, time_render=0; prof_init(); drawStartTitle(); bool exitflag = false; do { exitflag = false; stage = drawMainMenu(); if (stage==0 || stage==1) { selectedCircuit = drawMenuCircuitSelect(); if (selectedCircuit != -1) exitflag=true; } else if (stage==3) { drawCredit(); } } while (!exitflag); stage = selectedCircuit; if (selectedCircuit==0) CurrentCircuitBiome = PLAINS; else if (selectedCircuit==1) CurrentCircuitBiome = DESERT; else if (selectedCircuit==2) CurrentCircuitBiome = USA; else if (selectedCircuit==3) CurrentCircuitBiome = FINLAND; else if (selectedCircuit==4) CurrentCircuitBiome = AFRICA; else if (selectedCircuit==5) CurrentCircuitBiome = PLAINS; else if (selectedCircuit==6) CurrentCircuitBiome = DESERT; else if (selectedCircuit==7) CurrentCircuitBiome = USA; else if (selectedCircuit==8) CurrentCircuitBiome = FINLAND; else if (selectedCircuit==9) CurrentCircuitBiome = AFRICA; else CurrentCircuitBiome = PLAINS; int nbInterestingSegments = (MAX_RENDER_DISTANCE / SEGMENT_LENGTH); // the number of segments to be projected considering the rendering distance perf_create = prof_make(); prof_enter(perf_create); initData( ); // Positioning of the Camera createCircuit(); // Creates the circuit putBillBoards(); createClouds(); // Creates the Sky and Clouds createTraffic(); // Creates the cas prepareDecoration( CurrentCircuitBiome ); // Prepares the multiple variations of Decoration (image scaling) prepareTraffic(); // Prepares the multiple variations of Cars (image scaling) prof_leave(perf_create); time_create = prof_time(perf_create); //-------------- MAX_SEGMENT = circuit.size(); int indexstart = 0; int indexend = 0; uint32_t maxDistance = (MAX_SEGMENT-nbInterestingSegments-5)*SEGMENT_LENGTH; uint32_t dt=0; uint16_t l=0; uint32_t remaining_time; while (!stop) { perf_update = prof_make(); prof_enter(perf_update); get_inputs( dt, indexstart ); dt = ((float) (time_update+time_render+time_project) / 1000.0); start_time -= (time_update+time_render+time_project); if (start_time<0) start_time=0; remaining_time = ((float) (start_time) / 1000000.0); //-------------- if (fround(cam->cZ)<=0) cam->cZ=fixdouble(0.0); if (fround(cam->cZ)>=maxDistance) cam->cZ=fixdouble(maxDistance); indexstart = fround(cam->cZ) / SEGMENT_LENGTH; if (indexstart<0) indexstart=0; indexend = indexstart+nbInterestingSegments+1; if (indexstart>MAX_SEGMENT-nbInterestingSegments-2) indexstart=MAX_SEGMENT-nbInterestingSegments-2; prof_leave(perf_update); time_update = prof_time(perf_update); //-------------- perf_project = prof_make(); prof_enter(perf_project); if (BDrawCars) { updateTraffic( dt, maxDistance ); for (int k=0; kwZ / SEGMENT_LENGTH; if (CarSegment>=indexstart && CarSegmentvisible = true; circuit[CarSegment]->CarList.push_back(k); } //else //traffic[k]->visible = false; } } minYRoad = SCREEN_HEIGHT; float roadpart = f2float(cam->cX)/(float) ROAD_WIDTH; // Update car positions : car with higher speed change line not to collide with player if (BDrawCars) for( int l=0; lCarList.size(); l++ ) // For all cars inside that road segment { uint8_t indexCar = circuit[indexstart]->CarList[l]; if (traffic[indexCar]->wX>(roadpart-0.25f) && traffic[indexCar]->wX<(roadpart+0.25f) && traffic[indexCar]->Speed>speed) { if (traffic[indexCar]->wX>-0.25) traffic[indexCar]->wX-=0.5; // if we are on one of the most right lanes, we overtake by the left else traffic[indexCar]->wX=-0.25; // else we change to the lane on the right } } if (BDrawCars) for( int l=0; lCarList.size(); l++ ) // For all cars inside that road segment { uint8_t indexCar = circuit[indexstart+1]->CarList[l]; if (traffic[indexCar]->wX>(roadpart-0.15f) && traffic[indexCar]->wX<(roadpart+0.15f) && traffic[indexCar]->SpeedY < minYRoad) // This is a trick to save precious time while drawing the Sky minYRoad = circuit[k]->Y; circuit[k]->CumulatedCurve = cumulCurve; // This is the curve accumulated when we are drawing curves cumulCurve += circuit[k]->Curve; if (BDrawCars) for( int l=0; lCarList.size(); l++ ) // For all cars inside that road segment { uint8_t indexCar = circuit[k]->CarList[l]; traffic[indexCar]->Project3DFP( cam, k ); } } prof_leave(perf_project); time_project = prof_time(perf_project); //-------------- perf_render = prof_make(); prof_enter(perf_render); drawSky( DAY_BLUE_SKY ); if (BDrawClds) drawClouds( l % 396 ); drawFarBackground( deltaFarbackground ); drawNearBackground( deltaNearbackground ); cam->cY = fix( 300+2*CS ) + interpolatePositionY(fround(cam->cZ) ); for( int k=indexend-1; k>=indexstart; k--) { currentcurve = circuit[k]->CumulatedCurve; if (BDrawRoad) drawCircuitSegment( k ); if (BDrawDeco) drawDecoration( k ); if (BDrawCars) for( int l=0; lCarList.size(); l++ ) // For all cars inside that road segment { uint8_t indexCar = circuit[k]->CarList[l]; drawTraffic( indexCar ); } circuit[k]->CarList.clear(); } int mod_base=20; int mod_comp=10; if (abs(speed)<1.0) mod_base = 30, mod_comp = 15; else if (abs(speed)<2.0) mod_base = 20, mod_comp = 10; else if (abs(speed)<3.0) mod_base = 16, mod_comp = 8; else if (abs(speed)<4.0) mod_base = 12, mod_comp = 6; else if (abs(speed)<5.0) mod_base = 8, mod_comp = 4; else mod_base = 4, mod_comp = 2; if ((speed==0) || (l%mod_base<=mod_comp)) // the small rick to have the speed impression on wheels and to have the correct view of the car during turns { if (viewside==-2) dsubimage( SCREEN_CX-40, SCREEN_HEIGHT-46, &player, 99,1,80,46, DIMAGE_NONE); else if (viewside==-1) dsubimage( SCREEN_CX-37, SCREEN_HEIGHT-46, &player, 181,1,74,46, DIMAGE_NONE); else if (viewside==0) dsubimage( SCREEN_CX-36, SCREEN_HEIGHT-46, &player, 257,1,72,46, DIMAGE_NONE); else if (viewside==1) dsubimage( SCREEN_CX-37, SCREEN_HEIGHT-46, &player, 331,1,74,46, DIMAGE_NONE); else if (viewside==2) dsubimage( SCREEN_CX-40, SCREEN_HEIGHT-46, &player, 407,1,80,46, DIMAGE_NONE); } else { if (viewside==-2) dsubimage( SCREEN_CX-40, SCREEN_HEIGHT-46, &player, 99,49,80,46, DIMAGE_NONE); else if (viewside==-1) dsubimage( SCREEN_CX-37, SCREEN_HEIGHT-46, &player, 181,49,74,46, DIMAGE_NONE); else if (viewside==0) dsubimage( SCREEN_CX-36, SCREEN_HEIGHT-46, &player, 257,49,72,46, DIMAGE_NONE); else if (viewside==1) dsubimage( SCREEN_CX-37, SCREEN_HEIGHT-46, &player, 331,49,74,46, DIMAGE_NONE); else if (viewside==2) dsubimage( SCREEN_CX-40, SCREEN_HEIGHT-46, &player, 407,49,80,46, DIMAGE_NONE); } score = fround(cam->cZ)/100; //dprint( 1, 1, C_BLACK, "Crt=%.3D ms", time_create ); //dprint( 1, 15, C_RED, "Prj=%.3D ms", time_project ); //dprint( 1, 30, C_RED, "Rdr=%.3D ms", time_render ); //dprint( 1, 45, C_RED, "Upd=%.3D ms", time_update ); //dprint( 1, 1, C_BLACK, "Dt=%.3D ms", dt ); float drawspeed = (float) (speed*5.0f); dsubimage( 5, 5, &speedhud, 0, 117, 37, 13, DIMAGE_NONE); // speed logo dsubimage( 135, 5, &speedhud, 0, 130, 37, 13, DIMAGE_NONE); // timer logo dsubimage( 245, 5, &speedhud, 37, 117, 38, 13, DIMAGE_NONE); // speed logo dsubimage( 245, 25, &speedhud, 37, 130, 38, 13, DIMAGE_NONE); // timer logo dfont(&speedfont); if (drawspeed==0.0) { dprint_opt(122,3, C_RGB(0,0,0), C_NONE, DTEXT_RIGHT, DTEXT_TOP, "0 :", drawspeed ); dprint_opt(120,1, C_RGB(255,0,0), C_NONE, DTEXT_RIGHT, DTEXT_TOP, "0 :", drawspeed ); } else { dprint_opt(122,3, C_RGB(0,0,0), C_NONE, DTEXT_RIGHT, DTEXT_TOP, "%.1f :", drawspeed ); dprint_opt(120,1, C_RGB(255,0,0), C_NONE, DTEXT_RIGHT, DTEXT_TOP, "%.1f :", drawspeed ); //the ':' char corresponds to "Km/h" } dprint_opt(233,3, C_RGB(0,0,0), C_NONE, DTEXT_RIGHT, DTEXT_TOP, "%.3D ;", remaining_time ); dprint_opt(230,1, C_RGB(255,255,0), C_NONE, DTEXT_RIGHT, DTEXT_TOP, "%.3D ;", remaining_time ); // the ';' char corresponds to "s" dprint_opt(390,3, C_RGB(0,0,0), C_NONE, DTEXT_RIGHT, DTEXT_TOP, "%.3D", score ); dprint_opt(388,1, C_RGB(255,255,0), C_NONE, DTEXT_RIGHT, DTEXT_TOP, "%.3D", score ); // the ';' char corresponds to "s" dprint_opt(390,23, C_RGB(0,0,0), C_NONE, DTEXT_RIGHT, DTEXT_TOP, "%.3D", stage ); dprint_opt(388,21, C_RGB(255,255,0), C_NONE, DTEXT_RIGHT, DTEXT_TOP, "%.3D", stage ); // the ';' char corresponds to "s" if (drawspeed==0.0) dsubimage( 48, 25, &speedhud, 0, 0, 76, 13, DIMAGE_NONE); else if (drawspeed<3.30) dsubimage( 48, 25, &speedhud, 0, 13, 76, 13, DIMAGE_NONE); else if (drawspeed<6.70) dsubimage( 48, 25, &speedhud, 0, 26, 76, 13, DIMAGE_NONE); else if (drawspeed<10.0) dsubimage( 48, 25, &speedhud, 0, 39, 76, 13, DIMAGE_NONE); else if (drawspeed<13.3) dsubimage( 48, 25, &speedhud, 0, 52, 76, 13, DIMAGE_NONE); else if (drawspeed<16.7) dsubimage( 48, 25, &speedhud, 0, 65, 76, 13, DIMAGE_NONE); else if (drawspeed<20.0) dsubimage( 48, 25, &speedhud, 0, 78, 76, 13, DIMAGE_NONE); else if (drawspeed<23.3) dsubimage( 48, 25, &speedhud, 0, 91, 76, 13, DIMAGE_NONE); else dsubimage( 48, 25, &speedhud, 0, 104, 76, 13, DIMAGE_NONE); //dprint( 1, 1, C_BLACK, "FPS=%.3D ms", 1000/dt ); /* #if 0 dprint( 1, 210, C_WHITE, "Decs: %c", BDrawDeco==true?'Y':'N' ); // Key F1 dprint( 67, 210, C_WHITE, "Clds: %c", BDrawClds==true?'Y':'N' ); // Key F2 dprint( 133, 210, C_WHITE, "Cars: %c", BDrawCars==true?'Y':'N' ); // Key F3 dprint( 199, 210, C_WHITE, "DtR: %.1f", ((float) (time_render) / 1000.0) ); // Key F4 dprint( 265, 210, C_WHITE, "ScrSht" ); // Key F5 dprint( 331, 210, C_WHITE, "RecVid" ); // Key F6 #endif // 1 #if 0 if (ShowDebug1) { Segment* currentSeg = circuit[indexstart]; dprint( 1, 1, C_RED, "Crt=%.3D ms", time_create ); dprint( 1, 15, C_RED, "Prj=%.3D ms", time_project ); dprint( 1, 29, C_RED, "Rdr=%.3D ms", time_render ); dprint( 1, 55, C_WHITE, "It=%d", l); dprint( 1, 69, C_GREEN, "St=%d ", indexstart ); dprint( 1, 83, C_GREEN, "En=%d", indexend ); dprint( 1, 97, C_RED, "Sz= %d", circuit.size() ); dprint( 100, 55, C_WHITE, "SzSgmt=%d bytes", sizeof(Segment) ); dprint( 100, 69, C_WHITE, ">XYZc=(%d,%d,%.0lf,%d)", circuit[indexstart]->wX, circuit[indexstart]->wY, circuit[indexstart]->wZ, circuit[indexstart]->Curve ); dprint( 100, 83, C_WHITE, ">XYZc=(%d,%d,%.0lf,%d)", circuit[indexend]->wX, circuit[indexend]->wY, circuit[indexend]->wZ, circuit[indexstart]->Curve ); dprint( 100, 97, C_WHITE, "C[i]Adr= %p", ¤tSeg), dprint( 320, 1, C_WHITE, "CamX=%d", fround( cam->cX ) ); dprint( 320, 15, C_WHITE, "CamY=%d", fround( cam->cY ) ); dprint( 320, 29, C_WHITE, "CamZ=%d", fround( cam->cZ ) ); dprint( 320, 55, C_WHITE, "Dir=%d", direction ); dprint( 320, 69, C_WHITE, "Spd=%.1f", speed ); dprint( 320, 83, C_WHITE, "Dz =%.1f", speed*dt ); dprint( 320, 97, C_WHITE, "dt =%.3D ms", dt ); } if (ShowDebug2) { #if 0 dprint( 1, 1, C_RED, "Crt=%.3D ms", time_create ); dprint( 1, 15, C_RED, "Prj=%.3D ms", time_project ); dprint( 1, 29, C_RED, "Rdr=%.3D ms", time_render ); dprint( 1, 50, C_BLACK, "ISt_Z=%.1lf", circuit[indexstart]->wZ); dprint( 1, 65, C_BLACK, "IEd_Z=%.1lf", circuit[indexend]->wZ); for( int k=indexend-1; k>=indexstart; k--) { dprint( 100, 1+10*k-indexstart, C_WHITE, "S[%d]=%d", k, circuit[k]->DScale ); } for( int k=0; kX, nuages[k]->Y, nuages[k]->type ); } #endif // 0 for( int k=0; kvisible == true) dprint( 1, 1+10*k, C_GREEN, "Car %d Sc=%d wZ=%.0lf / Seg=%d X=%d Y=%d", k, traffic[k]->DScale, traffic[k]->wZ, traffic[k]->segnum, traffic[k]->X, traffic[k]->Y, traffic[k]->S ); else dprint( 1, 1+10*k, C_RED, "Car %d Sc=%d wZ=%.0lf / Seg=%d X=%d Y=%d", k, traffic[k]->DScale, traffic[k]->wZ, traffic[k]->segnum, traffic[k]->X, traffic[k]->Y, traffic[k]->S ); } } if (ShowDebug3) { dprint( 1, 1, C_BLACK, "S"); for( int k=0; k<=indexend-indexstart; k++) { int nbCars=circuit[indexstart+k]->CarList.size(); dprint( 25+k*25, 1, C_BLACK, "%d", indexstart+k ); dprint( 25+k*25, 11, C_RED, "%d", nbCars ); for( int l=0; lCarList[l]); } } } #endif */ /* for( int k=indexend-1; k>=indexstart; k--) { circuit[k]->CarList.clear(); } */ //dupdate(); r61524_display(gint_vram, 0, DHEIGHT, R61524_DMA_WAIT); prof_leave(perf_render); time_render = prof_time(perf_render); #if IS_FXLIB==1 if (screenshot && usb_is_open()) { usb_fxlink_screenshot(false); screenshot = false; } if(record && usb_is_open()) { usb_fxlink_videocapture(false); } #endif l++; } prof_quit(); #if IS_FXLIB==1 usb_close(); #endif circuit.clear(); nuages.clear(); delete cam; freeDecoration(); freeTraffic(); return 1; }