diff --git a/CMakeLists.txt b/CMakeLists.txt index 840f4d8..9376c52 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ set(SOURCES src/src/circuit.cc src/src/drawstuff.cc src/src/clouds.cc - # ... + src/src/cars.cc ) set(ASSETS_cg @@ -31,10 +31,15 @@ set(ASSETS_cg assets-cg/trees/tree1.png assets-cg/trees/tree2.png assets-cg/trees/tree3.png + assets-cg/trees/tree4.png + assets-cg/trees/tree5.png + assets-cg/trees/tree6.png assets-cg/player/player.png assets-cg/clouds/sky1.png assets-cg/clouds/sky2.png assets-cg/clouds/sky3.png + assets-cg/backgrnd/mountain.png + assets-cg/backgrnd/treeline.png ) fxconv_declare_assets(${ASSETS_cg} WITH_METADATA) diff --git a/CppOutRun.cbp b/CppOutRun.cbp index 70e132b..6a04d9f 100644 --- a/CppOutRun.cbp +++ b/CppOutRun.cbp @@ -28,8 +28,10 @@ + + @@ -37,6 +39,7 @@ + diff --git a/CppOutRun.layout b/CppOutRun.layout index ad57dc2..7aa6b18 100644 --- a/CppOutRun.layout +++ b/CppOutRun.layout @@ -2,49 +2,19 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + @@ -52,14 +22,74 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + diff --git a/assets-cg/backgrnd/fxconv-metadata.txt b/assets-cg/backgrnd/fxconv-metadata.txt new file mode 100644 index 0000000..7e05b58 --- /dev/null +++ b/assets-cg/backgrnd/fxconv-metadata.txt @@ -0,0 +1,5 @@ +*.png: + type: bopti-image + profile: p4 + name_regex: (.*)\.png \1 + diff --git a/assets-cg/backgrnd/mountain.png b/assets-cg/backgrnd/mountain.png new file mode 100644 index 0000000..90a6c1f Binary files /dev/null and b/assets-cg/backgrnd/mountain.png differ diff --git a/assets-cg/backgrnd/treeline.png b/assets-cg/backgrnd/treeline.png new file mode 100644 index 0000000..5ebb725 Binary files /dev/null and b/assets-cg/backgrnd/treeline.png differ diff --git a/assets-cg/trees/tree4.png b/assets-cg/trees/tree4.png new file mode 100644 index 0000000..54ec506 Binary files /dev/null and b/assets-cg/trees/tree4.png differ diff --git a/assets-cg/trees/tree5.png b/assets-cg/trees/tree5.png new file mode 100644 index 0000000..7cdb96c Binary files /dev/null and b/assets-cg/trees/tree5.png differ diff --git a/assets-cg/trees/tree6.png b/assets-cg/trees/tree6.png new file mode 100644 index 0000000..3d049e7 Binary files /dev/null and b/assets-cg/trees/tree6.png differ diff --git a/src/colors.h b/src/colors.h new file mode 100644 index 0000000..9eb8c39 --- /dev/null +++ b/src/colors.h @@ -0,0 +1,19 @@ +#ifndef COLORS_H +#define COLORS_H + + +#define LIGHT_GREY_ROAD 0xC638 +#define DARK_GREY_ROAD 0xBDD7 //0xB5B6 + +#define WHITE_STRIPE 0xFFFF +#define RED_STRIPE 0xF800 + +#define LIGHT_GREEN_GRASS 0x07E5 +#define DARK_GREEN_GRASS 0x0680 + +#define LIGHT_YELLOW_GRASS 0xFFE0 +#define DARK_YELLOW_GRASS 0xD6A0 + +#define DAY_BLUE_SKY 0x017F + +#endif // PARAMETERS_H diff --git a/src/include/cars.h b/src/include/cars.h new file mode 100644 index 0000000..92fa02b --- /dev/null +++ b/src/include/cars.h @@ -0,0 +1,35 @@ +#ifndef CARS_H +#define CARS_H + +#include +#include "camera.h" + + +class Cars +{ + public: + Cars(); + Cars( float x, double z, uint8_t s, uint8_t t ); + ~Cars(); + + void Project3DFP( camera* c, uint16_t index ); + + + float wX; + double wZ; + + int16_t X; + int16_t Y; + uint8_t S; + + uint8_t Speed; + uint8_t Type; + + uint8_t DScale; + + // for debugging only + bool visible; + uint16_t segnum; +}; + +#endif // CARS_H diff --git a/src/include/circuit.h b/src/include/circuit.h index 752ac86..332d530 100644 --- a/src/include/circuit.h +++ b/src/include/circuit.h @@ -12,9 +12,11 @@ enum Length enum HillSize { - H_SMALL = 10, - H_MEDIUM = 20, - H_BIG = 40 + H_VERYSMALL = 20, + H_SMALL = 40, + H_MEDIUM = 60, + H_BIG = 80, + H_VERYBIG = 100 }; enum HillType @@ -25,9 +27,11 @@ enum HillType enum CurveStrength { - C_EASY = 2, - C_MEDIUM = 4, - C_HARD = 6 + C_VERYEASY = 2, + C_EASY = 4, + C_MEDIUM = 6, + C_HARD = 8, + C_VERYHARD = 10 }; enum CurveType @@ -40,30 +44,42 @@ enum Decoration { PALMTREE = 0, DEADTREE = 1, - OAKTREE = 2 + OAKTREE = 2, + CACTUS = 3, + BIGLEAF = 4, + SMALLLEAF = 5 }; void initData( void ); void createCircuit( void ); void createClouds( void ); +void createTraffic( void ); void projectCircuitFP( void ); void projectCircuitFP( uint16_t index ); +void updateTraffic( float dt ); + void printCircuit( void ); void printCircuit( int i ); void drawCircuitSegment( uint16_t index ); void drawDecoration( uint16_t index ); +void drawTraffic( uint16_t index ); void drawClouds( int offset ); +void drawFarBackground( int offset ); +void drawNearBackground( int offset ); void freeDecoration( void ); void prepareDecoration( void ); -void addStraightLine( Length l ); -void addCurve( Length l, CurveStrength s, CurveType t ); -void addHill( Length l, HillSize s, HillType t ); +void freeTraffic( void ); +void prepareTraffic( void ); + +void addStraightLine( Length l, int8_t biome ); +void addCurve( Length l, CurveStrength s, CurveType t, int8_t biome ); +void addHill( Length l, HillSize s, HillType t, int8_t biome ); fixed_t interpolatePositionX( double currentZ ); fixed_t interpolatePositionY( double currentZ ); - +uint16_t findIndex( double currentZ ); diff --git a/src/include/clouds.h b/src/include/clouds.h index 1f8158a..3ea27d4 100644 --- a/src/include/clouds.h +++ b/src/include/clouds.h @@ -21,7 +21,7 @@ class Clouds int16_t X; int16_t Y; - int8_t type; + int8_t Type; }; #endif // CLOUDS_H diff --git a/src/include/drawstuff.h b/src/include/drawstuff.h index dff6916..43f1385 100644 --- a/src/include/drawstuff.h +++ b/src/include/drawstuff.h @@ -3,8 +3,13 @@ void gint_dhline(int x1, int x2, int y, uint16_t color); void drawPolygon( int x1min, int x1max, int y1, int x2min, int x2max, int y2, uint8_t R, uint8_t G, uint8_t B ); +void drawPolygon( int x1min, int x1max, int y1, int x2min, int x2max, int y2, uint16_t color ); void drawGrass( int y1, int y2, uint8_t R, uint8_t G, uint8_t B ); +void drawGrass( int y1, int y2, uint16_t color ); void drawSky( void ); +void drawSky( uint16_t color ); +void drawSky( uint8_t R, uint8_t G, uint8_t B ); void drawSky( int ymin, int ymax ); +void drawSkyOptimised( uint16_t color ); diff --git a/src/include/segment.h b/src/include/segment.h index c64779a..7c83c1e 100644 --- a/src/include/segment.h +++ b/src/include/segment.h @@ -5,19 +5,32 @@ #include #include "camera.h" +#include + +#define std ustl + +enum BiomeType +{ + PLAINS = 0, + DESERT = 1 +}; + + class Segment { public: Segment(); Segment( uint16_t n_seg ); - Segment( int16_t x, int16_t y, double z, int8_t c ); - Segment( int16_t x, int16_t y, double z, int8_t c, int8_t left, int8_t right ); + Segment( int16_t x, int16_t y, double z, int8_t c, int8_t s ); + Segment( int16_t x, int16_t y, double z, int8_t c, int8_t s, int8_t left, int8_t right ); ~Segment(); void Project3DFP( camera* c ); + int8_t environment = PLAINS; int8_t Curve=0; + int8_t Slope=0; int16_t CumulatedCurve=0; // World Coordinates (X,Y,Z) @@ -34,6 +47,8 @@ class Segment int8_t LDeco=-1; int8_t RDeco=-1; int8_t DScale=0; + + std::vector CarList; }; #endif // SEGMENT_H diff --git a/src/main.cc b/src/main.cc index 09e3fa7..80648d8 100644 --- a/src/main.cc +++ b/src/main.cc @@ -13,19 +13,23 @@ #include #include +#include "parameters.h" +#include "colors.h" #include "include/camera.h" #include "include/segment.h" -#include "parameters.h" #include "include/circuit.h" #include "include/drawstuff.h" #include "include/clouds.h" +#include "include/cars.h" extern bopti_image_t car1, car2, car3, car4, car5, car6, car7, car8; -extern bopti_image_t tree1, tree2, tree3; +extern bopti_image_t tree1, tree2, tree3, tree4, tree5, tree6; extern bopti_image_t player; extern bopti_image_t sky1, sky2, sky3; +extern bopti_image_t mountain; +extern bopti_image_t treeline; std::vector circuit; @@ -33,26 +37,48 @@ 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; -float maxspeedforward = 8; -float maxspeedbackward = 4; +float maxspeedforward = 5; +float maxspeedbackward = 2; int direction = 1; bool speedcontrol = false; -static void get_inputs( float dt ) +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) { @@ -60,8 +86,35 @@ static void get_inputs( float dt ) } speedcontrol = false; - if(keydown(KEY_LEFT)) cam->decX(25.0); - if(keydown(KEY_RIGHT)) cam->incX(25.0); + + 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)) { @@ -108,19 +161,41 @@ static void get_inputs( float dt ) if(keydown(KEY_EXIT)) stop = true; - if(keydown(KEY_F1)) +#if IS_FXLIB==1 + if(keydown(KEY_XOT)) { - ShowDebug1 = !ShowDebug1; - ShowDebug2 = false; - } - if(keydown(KEY_F2)) - { - ShowDebug2 = !ShowDebug2; 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; - if(keydown(KEY_F4)) screenshot = true; + +#endif // IS_FXLIB if (speedcontrol==false) { @@ -132,6 +207,30 @@ static void get_inputs( float 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); + } } @@ -140,27 +239,27 @@ 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_create, perf_project, perf_render; - uint32_t time_create=0, time_project=0, time_render=0; + prof_t perf_update, perf_create, perf_project, perf_render; + uint32_t time_update=0, time_create=0, time_project=0, time_render=0; prof_init(); - int nbInterestingSegments = (MAX_RENDER_DISTANCE / SEGMENT_LENGTH) + 10; // the number of segments to be projected considering the rendering distance + int nbInterestingSegments = (MAX_RENDER_DISTANCE / SEGMENT_LENGTH); // the number of segments to be projected considering the rendering distance - //-------------- - - initData( ); - - //-------------- perf_create = prof_make(); prof_enter(perf_create); - createCircuit(); - createClouds(); - prepareDecoration(); + initData( ); // Positioning of the Camera + createCircuit(); // Creates the circuit + createClouds(); // Creates the Sky and Clouds + createTraffic(); // Creates the cas + prepareDecoration(); // 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); @@ -171,44 +270,77 @@ int main(void) int indexstart = 0; int indexend = 0; - uint32_t maxDistance = (MAX_SEGMENT-nbInterestingSegments-5)*SEGMENT_LENGTH; + uint32_t maxDistance = (MAX_SEGMENT-nbInterestingSegments-1)*SEGMENT_LENGTH; uint32_t dt=0; uint16_t l=0; while (!stop) { - get_inputs( dt ); - dt = ((float) (time_render+time_project) / 1000.0); + + perf_update = prof_make(); + prof_enter(perf_update); + + get_inputs( dt, indexstart ); + dt = ((float) (time_update+time_render+time_project) / 1000.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; - indexend = indexstart+nbInterestingSegments+1; - - // there is an offset equals to 400 on z position - // this is to compute the first index of segment to be projected to screen - if (indexstart<0) indexstart=0; - if (indexstart>MAX_SEGMENT-nbInterestingSegments-1-2) indexstart=MAX_SEGMENT-nbInterestingSegments-1-2; + 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); - //cam->cY = fix( 300 + interpolatePositionY(fround(cam->cZ)) ); - uint16_t cumulCurve=0; - for (int k=indexstart; k<=indexend; k++) // Need to project 1 more segment than actual drawing - { - projectCircuitFP( k ); - circuit[k]->CumulatedCurve = cumulCurve; - cumulCurve += circuit[k]->Curve; - } + if (BDrawCars) + { + updateTraffic( dt ); + + 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; + + uint16_t cumulCurve=0; + for (int k=indexstart; k<=indexend; k++) // Need to project 1 more segment than actual drawing + { + projectCircuitFP( k ); // We project the current segment + + if (circuit[k]->Y < 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); @@ -218,20 +350,90 @@ int main(void) perf_render = prof_make(); prof_enter(perf_render); - drawSky( ); - drawClouds( l % 396 ); - cam->cY = fix( 300 ) + interpolatePositionY(fround(cam->cZ)); + 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; - drawCircuitSegment( k ); - drawDecoration( k ); + + 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); + } + + + //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 ); + + //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]; @@ -261,34 +463,72 @@ int main(void) } 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 ); - dsubimage( SCREEN_CX-36, SCREEN_HEIGHT-48, &player, 257,1,72,46, DIMAGE_NONE); + for( int l=0; lCarList[l]); + } + } + } + #endif +*/ - dupdate(); - //r61524_display(gint_vram, 0, DHEIGHT, R61524_DMA_WAIT); +/* + 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(true); + usb_fxlink_screenshot(false); screenshot = false; } @@ -296,19 +536,23 @@ int main(void) { usb_fxlink_videocapture(false); } +#endif l++; } prof_quit(); - usb_close(); +#if IS_FXLIB==1 + usb_close(); +#endif circuit.clear(); nuages.clear(); delete cam; freeDecoration(); + freeTraffic(); return 1; } diff --git a/src/parameters.h b/src/parameters.h index 0722682..0d435b5 100644 --- a/src/parameters.h +++ b/src/parameters.h @@ -14,9 +14,22 @@ #define ASPECT_RATIO 1.767 #define DISTANCE_SCREEN 0.83444 + #define MAX_RENDER_DISTANCE 3000 + +#define NB_CLOUDS_SKY 10 +#define NB_CARS_TRAFFIC 100 + +#define MAX_SUBIMAGES_TREES 12 +#define NB_TREES_TYPES 6 + +#define MAX_SUBIMAGES_CARS 12 +#define NB_CARS_TYPES 8 + #define std ustl +#define IS_FXLIB 1 + #endif // PARAMETERS_H diff --git a/src/src/cars.cc b/src/src/cars.cc new file mode 100644 index 0000000..79853b8 --- /dev/null +++ b/src/src/cars.cc @@ -0,0 +1,53 @@ +#include "../include/cars.h" +#include "../include/camera.h" + +#include +#include +#include "../include/segment.h" +#include "../parameters.h" +#include "../include/circuit.h" + + +extern std::vector circuit; + + +Cars::Cars() +{ + //ctor +} + +Cars::~Cars() +{ + //dtor +} + +Cars::Cars( float x, double z, uint8_t s, uint8_t t ) +{ + wX = x; + wZ = z; + Speed = s; + Type = t; + X = 0; +} + + +void Cars::Project3DFP( camera* c, uint16_t index ) +{ + fixed_t DX = fix(wX*ROAD_WIDTH) - c->cX; + fixed_t DY = interpolatePositionY(wZ) - c->cY; + + fixed_t divDZ = fdiv( fix(1), (fixdouble(wZ) - c->cZ)); + fixed_t divAR = fdiv(fix(1), fixdouble(ASPECT_RATIO)); + fixed_t Scale = fmul(fixdouble(DISTANCE_SCREEN), divDZ); + + fixed_t tempx = fmul(fmul(DX,Scale), divAR); + fixed_t tempy = fmul(DY, Scale); + + fixed_t sX=fmul(fix(SCREEN_CX), (fix(1)+tempx)); + fixed_t sY=fmul(fix(SCREEN_CY), (fix(1)-tempy)); + + X = fround(sX) + circuit[ index ]->CumulatedCurve; + Y = fround(sY); +} + + diff --git a/src/src/circuit.cc b/src/src/circuit.cc index 7a5fe64..8893572 100644 --- a/src/src/circuit.cc +++ b/src/src/circuit.cc @@ -2,6 +2,8 @@ #include "../include/segment.h" #include "../include/camera.h" #include "../include/clouds.h" +#include "../include/cars.h" + #include "../parameters.h" #include @@ -9,10 +11,13 @@ #include #include "../include/drawstuff.h" +#include "../colors.h" extern std::vector circuit; extern std::vector nuages; +extern std::vector traffic; + extern camera *cam; extern uint16_t currentcurve; extern uint8_t shiftcolor; @@ -21,11 +26,13 @@ extern bool ShowDebug1; extern bopti_image_t car1, car2, car3, car4, car5, car6, car7, car8; -extern bopti_image_t tree1, tree2, tree3; +extern bopti_image_t tree1, tree2, tree3, tree4, tree5, tree6; extern bopti_image_t sky1, sky2, sky3; +extern bopti_image_t mountain; +extern bopti_image_t treeline; -bopti_image_t *scaledTrees[3][25] = { 0 }; - +bopti_image_t *scaledTrees[NB_TREES_TYPES][MAX_SUBIMAGES_TREES] = { 0 }; +bopti_image_t *scaledCars[NB_CARS_TYPES][MAX_SUBIMAGES_CARS] = { 0 }; size_t image_size_profile(int profile, int width, int height) @@ -121,15 +128,12 @@ bopti_image_t *resize(bopti_image_t const *src, int w, int h) } - - - void initData( void ) { cam = new camera(); cam->cX = fixdouble(0.0f); cam->cY = fixdouble(300.0f); - cam->cZ = fixdouble(260.0f); + cam->cZ = fixdouble(0.0f); } @@ -142,33 +146,29 @@ void createCircuit( void ) } */ - addStraightLine( L_VERYSHORT ); - addStraightLine( L_VERYSHORT ); - addCurve( L_SHORT, C_EASY, LEFT_CURVE ); - addHill( L_MEDIUM, H_BIG, UP_HILL ); - addHill( L_MEDIUM, H_BIG, DOWN_HILL ); - addCurve( L_SHORT, C_HARD, RIGHT_CURVE ); - addStraightLine( L_VERYLONG ); - addCurve( L_SHORT, C_HARD, LEFT_CURVE ); - addStraightLine( L_VERYLONG ); - addCurve( L_SHORT, C_EASY, LEFT_CURVE ); - addHill( L_MEDIUM, H_BIG, UP_HILL ); - addHill( L_MEDIUM, H_BIG, DOWN_HILL ); - addCurve( L_SHORT, C_HARD, RIGHT_CURVE ); - addStraightLine( L_VERYLONG ); - addCurve( L_SHORT, C_HARD, LEFT_CURVE ); - addHill( L_MEDIUM, H_BIG, UP_HILL ); - addHill( L_MEDIUM, H_BIG, DOWN_HILL ); - addCurve( L_SHORT, C_HARD, RIGHT_CURVE ); - addStraightLine( L_VERYLONG ); - addCurve( L_SHORT, C_HARD, LEFT_CURVE ); - addStraightLine( L_VERYLONG ); - addCurve( L_SHORT, C_EASY, LEFT_CURVE ); - addHill( L_MEDIUM, H_BIG, UP_HILL ); - addHill( L_MEDIUM, H_BIG, DOWN_HILL ); - addCurve( L_SHORT, C_HARD, RIGHT_CURVE ); - addStraightLine( L_VERYLONG ); - addCurve( L_SHORT, C_HARD, LEFT_CURVE ); + addStraightLine( L_VERYSHORT, PLAINS ); + addStraightLine( L_VERYSHORT, DESERT ); + //addStraightLine( L_VERYSHORT, PLAINS ); + //addStraightLine( L_VERYSHORT, DESERT ); + addCurve( L_SHORT, C_HARD, LEFT_CURVE, DESERT ); + addCurve( L_SHORT, C_HARD, RIGHT_CURVE, DESERT ); + addStraightLine( L_LONG, DESERT ); + addHill( L_MEDIUM, H_BIG, UP_HILL, DESERT ); + addHill( L_MEDIUM, H_BIG, DOWN_HILL, PLAINS ); + //addCurve( L_SHORT, C_HARD, RIGHT_CURVE, PLAINS ); + addStraightLine( L_VERYLONG, PLAINS ); + addCurve( L_SHORT, C_HARD, LEFT_CURVE, PLAINS ); + addStraightLine( L_VERYLONG, DESERT ); + addCurve( L_SHORT, C_EASY, LEFT_CURVE, DESERT ); + //addHill( L_MEDIUM, H_BIG, UP_HILL, DESERT ); + //addHill( L_MEDIUM, H_BIG, DOWN_HILL, DESERT ); + //addCurve( L_SHORT, C_HARD, RIGHT_CURVE, PLAINS ); + //addStraightLine( L_VERYLONG, PLAINS ); + //addCurve( L_SHORT, C_HARD, LEFT_CURVE, PLAINS ); + //addHill( L_MEDIUM, H_BIG, UP_HILL, PLAINS ); + //addHill( L_MEDIUM, H_BIG, DOWN_HILL, PLAINS ); + //addCurve( L_SHORT, C_HARD, RIGHT_CURVE, DESERT ); + //addStraightLine( L_VERYLONG, DESERT ); }; @@ -176,10 +176,10 @@ void createClouds( void ) { srand( rtc_ticks() ); - for( int k = 0; k < 10; k++) + for( int k = 0; k < NB_CLOUDS_SKY; k++) { - int X = (rand() % 1188) - 396; - int Y = rand() % 80; + int X = (rand() % 792); + int Y = rand() % 60; int T = rand() % 3; Clouds* cl=new Clouds( X, Y, T ); @@ -188,73 +188,45 @@ void createClouds( void ) } -void addStraightLine( Length l ) +void createTraffic( void ) { - double lastZ=0; - int16_t lastY=0; - - if (circuit.size()!=0) - { - lastY=circuit[circuit.size()-1]->wY; - lastZ=circuit[circuit.size()-1]->wZ; - } - srand( rtc_ticks() ); - for( int i=0; iwY; - lastZ=circuit[circuit.size()-1]->wZ; - } - srand( rtc_ticks() ); - - for( int i=0; iwY; - lastZ=circuit[circuit.size()-1]->wZ; + lastY=circuit[lastIndex-1]->wY; + lastZ=circuit[lastIndex-1]->wZ+SEGMENT_LENGTH; } + srand( rtc_ticks() ); for( int i=0; ienvironment = biome; + circuit.push_back( seg ); + } + } +} + +void addCurve( Length l, CurveStrength s, CurveType t, int8_t biome ) +{ + double lastZ=0; + int16_t lastY=0; + + uint16_t lastIndex = circuit.size(); + if (lastIndex!=0) + { + lastY=circuit[lastIndex-1]->wY; + lastZ=circuit[lastIndex-1]->wZ+SEGMENT_LENGTH; + } + + srand( rtc_ticks() ); + + for( int i=0; ienvironment = biome; + circuit.push_back( seg ); + } + } +} + + +void addHill( Length l, HillSize s, HillType t, int8_t biome ) +{ + double lastZ=0; + int16_t lastY=0; + + uint16_t lastIndex = circuit.size(); + if (lastIndex!=0) + { + lastY=circuit[lastIndex-1]->wY; + lastZ=circuit[lastIndex-1]->wZ+SEGMENT_LENGTH; + } + + srand( rtc_ticks() ); + + for( int i=0; ienvironment = biome; + circuit.push_back( seg ); + } } } @@ -317,43 +361,79 @@ void drawCircuitSegment( uint16_t index ) if (Y1==Y2) return; - if (index%2==0) + /* + if (index==0) { - drawGrass( Y2, Y1, 0, 255-shiftcolor, 45-shiftcolor ); + drawPolygon( 0, X2-W2/16-W2+currentcurve, Y2, 0, X1-W1/16-W1+currentcurve, Y1, DARK_GREEN_GRASS ); - // route - drawPolygon( X2-W2+currentcurve, X2+W2+currentcurve, Y2, X1-W1+currentcurve, X1+W1+currentcurve, Y1, 196-shiftcolor, 196-shiftcolor, 196-shiftcolor ); + drawPolygon( X2-W2+currentcurve, X2+W2+currentcurve, Y2, X1-W1+currentcurve, X1+W1+currentcurve, Y1, C_RED ); - // ligne blanche centrale - drawPolygon( X2-W2/50+currentcurve, X2+W2/50+currentcurve, Y2, X1-W1/50+currentcurve, X1+W1/50+currentcurve, Y1, 255-shiftcolor, 255-shiftcolor, 255-shiftcolor ); - // ligne blanche gauche - drawPolygon( X2-W2/16-W2+currentcurve, X2-W2+currentcurve, Y2, X1-W1/16-W1+currentcurve, X1-W1+currentcurve, Y1, 255-shiftcolor, 255-shiftcolor, 255-shiftcolor ); + drawPolygon( X2-W2/16-W2+currentcurve, X2-W2+currentcurve, Y2, X1-W1/16-W1+currentcurve, X1-W1+currentcurve, Y1, WHITE_STRIPE ); + drawPolygon( X2-W2/50+currentcurve, X2+W2/50+currentcurve, Y2, X1-W1/50+currentcurve, X1+W1/50+currentcurve, Y1, WHITE_STRIPE ); + drawPolygon( X2-W2/50-W2/2+currentcurve, X2+W2/50-W2/2+currentcurve, Y2, X1-W1/50-W1/2+currentcurve, X1+W1/50-W1/2+currentcurve, Y1, WHITE_STRIPE ); + drawPolygon( X2-W2/50+currentcurve, X2+W2/50+currentcurve, Y2, X1-W1/50+currentcurve, X1+W1/50+currentcurve, Y1, WHITE_STRIPE ); + drawPolygon( X2-W2/50+W2/2+currentcurve, X2+W2/50+W2/2+currentcurve, Y2, X1-W1/50+W1/2+currentcurve, X1+W1/50+W1/2+currentcurve, Y1, WHITE_STRIPE ); + drawPolygon( X2+W2+currentcurve, X2+W2+W2/16+currentcurve, Y2, X1+W1+currentcurve, X1+W1+W1/16+currentcurve, Y1, WHITE_STRIPE ); - // ligne blanche centrale gauche - drawPolygon( X2-W2/50-W2/2+currentcurve, X2+W2/50-W2/2+currentcurve, Y2, X1-W1/50-W1/2+currentcurve, X1+W1/50-W1/2+currentcurve, Y1, 255-shiftcolor, 255-shiftcolor, 255-shiftcolor ); - - // ligne blanche centrale - drawPolygon( X2-W2/50+currentcurve, X2+W2/50+currentcurve, Y2, X1-W1/50+currentcurve, X1+W1/50+currentcurve, Y1, 255-shiftcolor, 255-shiftcolor, 255-shiftcolor ); - - // ligne blanche centrale droite - drawPolygon( X2-W2/50+W2/2+currentcurve, X2+W2/50+W2/2+currentcurve, Y2, X1-W1/50+W1/2+currentcurve, X1+W1/50+W1/2+currentcurve, Y1, 255-shiftcolor, 255-shiftcolor, 255-shiftcolor ); - - // ligne blanche droite - drawPolygon( X2+W2+currentcurve, X2+W2+W2/16+currentcurve, Y2, X1+W1+currentcurve, X1+W1+W1/16+currentcurve, Y1, 255-shiftcolor, 255-shiftcolor, 255-shiftcolor ); + drawPolygon( X2+W2/16+W2+currentcurve, 396, Y2, X1+W1/16+W1+currentcurve, 396, Y1, DARK_GREEN_GRASS ); + return; } - else + */ + + if (circuit[index]->environment == PLAINS) { + if (index%2==0) + { + //drawGrass( Y2, Y1, DARK_GREEN_GRASS ); - drawGrass( Y2, Y1, 0, 255-shiftcolor, 0 ); + drawPolygon( 0, X2-W2/16-W2+currentcurve, Y2, 0, X1-W1/16-W1+currentcurve, Y1, DARK_GREEN_GRASS ); - drawPolygon( X2-W2+currentcurve, X2+W2+currentcurve, Y2, X1-W1+currentcurve, X1+W1+currentcurve, Y1, 180-shiftcolor, 180-shiftcolor, 180-shiftcolor ); - // ligne rouge gauche - drawPolygon( X2-W2/16-W2+currentcurve, X2-W2+currentcurve, Y2, X1-W1/16-W1+currentcurve, X1-W1+currentcurve, Y1, 255-shiftcolor, 0, 0 ); - // ligne rouge droite - drawPolygon( X2+W2+currentcurve, X2+W2+W2/16+currentcurve, Y2, X1+W1+currentcurve, X1+W1+W1/16+currentcurve, Y1, 255-shiftcolor, 0, 0 ); + drawPolygon( X2-W2+currentcurve, X2+W2+currentcurve, Y2, X1-W1+currentcurve, X1+W1+currentcurve, Y1, LIGHT_GREY_ROAD ); + drawPolygon( X2-W2/16-W2+currentcurve, X2-W2+currentcurve, Y2, X1-W1/16-W1+currentcurve, X1-W1+currentcurve, Y1, WHITE_STRIPE ); + drawPolygon( X2-W2/50+currentcurve, X2+W2/50+currentcurve, Y2, X1-W1/50+currentcurve, X1+W1/50+currentcurve, Y1, WHITE_STRIPE ); + drawPolygon( X2-W2/50-W2/2+currentcurve, X2+W2/50-W2/2+currentcurve, Y2, X1-W1/50-W1/2+currentcurve, X1+W1/50-W1/2+currentcurve, Y1, WHITE_STRIPE ); + drawPolygon( X2-W2/50+currentcurve, X2+W2/50+currentcurve, Y2, X1-W1/50+currentcurve, X1+W1/50+currentcurve, Y1, WHITE_STRIPE ); + drawPolygon( X2-W2/50+W2/2+currentcurve, X2+W2/50+W2/2+currentcurve, Y2, X1-W1/50+W1/2+currentcurve, X1+W1/50+W1/2+currentcurve, Y1, WHITE_STRIPE ); + drawPolygon( X2+W2+currentcurve, X2+W2+W2/16+currentcurve, Y2, X1+W1+currentcurve, X1+W1+W1/16+currentcurve, Y1, WHITE_STRIPE ); + + drawPolygon( X2+W2/16+W2+currentcurve, 396, Y2, X1+W1/16+W1+currentcurve, 396, Y1, DARK_GREEN_GRASS ); + } + else + { + //drawGrass( Y2, Y1, LIGHT_GREEN_GRASS ); + drawPolygon( 0, X2-W2/16-W2+currentcurve, Y2, 0, X1-W1/16-W1+currentcurve, Y1, LIGHT_GREEN_GRASS ); + + drawPolygon( X2-W2+currentcurve, X2+W2+currentcurve, Y2, X1-W1+currentcurve, X1+W1+currentcurve, Y1, DARK_GREY_ROAD ); + drawPolygon( X2-W2/16-W2+currentcurve, X2-W2+currentcurve, Y2, X1-W1/16-W1+currentcurve, X1-W1+currentcurve, Y1, RED_STRIPE ); + drawPolygon( X2+W2+currentcurve, X2+W2+W2/16+currentcurve, Y2, X1+W1+currentcurve, X1+W1+W1/16+currentcurve, Y1, RED_STRIPE ); + + drawPolygon( X2+W2/16+W2+currentcurve, 396, Y2, X1+W1/16+W1+currentcurve, 396, Y1, LIGHT_GREEN_GRASS ); + } } + else if (circuit[index]->environment == DESERT) + { + if (index%2==0) + { + drawGrass( Y2, Y1, DARK_YELLOW_GRASS ); + drawPolygon( X2-W2+currentcurve, X2+W2+currentcurve, Y2, X1-W1+currentcurve, X1+W1+currentcurve, Y1, LIGHT_GREY_ROAD ); + drawPolygon( X2-W2/50+currentcurve, X2+W2/50+currentcurve, Y2, X1-W1/50+currentcurve, X1+W1/50+currentcurve, Y1, WHITE_STRIPE ); + drawPolygon( X2-W2/16-W2+currentcurve, X2-W2+currentcurve, Y2, X1-W1/16-W1+currentcurve, X1-W1+currentcurve, Y1, WHITE_STRIPE ); + drawPolygon( X2-W2/50-W2/2+currentcurve, X2+W2/50-W2/2+currentcurve, Y2, X1-W1/50-W1/2+currentcurve, X1+W1/50-W1/2+currentcurve, Y1, WHITE_STRIPE ); + drawPolygon( X2-W2/50+currentcurve, X2+W2/50+currentcurve, Y2, X1-W1/50+currentcurve, X1+W1/50+currentcurve, Y1, WHITE_STRIPE ); + drawPolygon( X2-W2/50+W2/2+currentcurve, X2+W2/50+W2/2+currentcurve, Y2, X1-W1/50+W1/2+currentcurve, X1+W1/50+W1/2+currentcurve, Y1, WHITE_STRIPE ); + drawPolygon( X2+W2+currentcurve, X2+W2+W2/16+currentcurve, Y2, X1+W1+currentcurve, X1+W1+W1/16+currentcurve, Y1, WHITE_STRIPE ); + } + else + { + drawGrass( Y2, Y1, LIGHT_YELLOW_GRASS ); + drawPolygon( X2-W2+currentcurve, X2+W2+currentcurve, Y2, X1-W1+currentcurve, X1+W1+currentcurve, Y1, DARK_GREY_ROAD ); + drawPolygon( X2-W2/16-W2+currentcurve, X2-W2+currentcurve, Y2, X1-W1/16-W1+currentcurve, X1-W1+currentcurve, Y1, RED_STRIPE ); + drawPolygon( X2+W2+currentcurve, X2+W2+W2/16+currentcurve, Y2, X1+W1+currentcurve, X1+W1+W1/16+currentcurve, Y1, RED_STRIPE ); + } + } + } @@ -403,24 +483,61 @@ fixed_t interpolatePositionY( double currentZ ) } +uint16_t findIndex( double currentZ ) +{ + return (uint16_t) (currentZ / SEGMENT_LENGTH); +} + + void prepareDecoration( void ) { bopti_image_t const *src; - for( int k=0; k<3; k++) + for( int k=0; kwidth * scale); int height = (int) ((float) src->height * scale); scaledTrees[k][i] = resize(src, width, height); - //scale*=0.85f; + //scale*=0.82; + } + } +} + +void prepareTraffic( void ) +{ + bopti_image_t const *src; + + for( int k=0; kwidth * scale); + int height = (int) ((float) src->height * scale); + scaledCars[k][i] = resize(src, width, height); + scale*=0.82; } } } @@ -428,12 +545,20 @@ void prepareDecoration( void ) void freeDecoration( void ) { - for( int k=0; k<3; k++) - for( int i=0; i<25; i++) + for( int k=0; kwZ) - cam->cZ), fix(SEGMENT_LENGTH) )) - 1; if (distance<0) distance = 0; - else if (distance>24) distance = 24; + else if (distance>(MAX_SUBIMAGES_TREES-1)) distance = (MAX_SUBIMAGES_TREES-1); circuit[index]->DScale = distance; @@ -471,16 +596,87 @@ void drawDecoration( uint16_t index ) } +void updateTraffic( float dt ) +{ + for(int k=0; kwZ += traffic[k]->Speed*dt; +} + + +void drawTraffic( uint16_t index ) +{ + bopti_image_t *image; + + int distance = fround(fdiv( (fixdouble(traffic[index]->wZ) - cam->cZ), fix(SEGMENT_LENGTH/2) ))-2; + if (distance<0) distance = 0; + else if (distance>(MAX_SUBIMAGES_CARS-1)) distance = (MAX_SUBIMAGES_CARS-1); + + int segnumber = findIndex( traffic[index]->wZ ); + traffic[index]->segnum = segnumber; + traffic[index]->DScale = distance; + + image = scaledCars[traffic[index]->Type][distance]; + + int X = traffic[index]->X - image->width/2; + int Y = traffic[index]->Y - image->height; + + dimage( X, Y, image ); +} + + void drawClouds( int offset ) { bopti_image_t *cloud; for( int k =0; ktype==0) cloud=&sky1; - else if (nuages[k]->type==1) cloud=&sky2; - else if (nuages[k]->type==2) cloud=&sky3; + if (nuages[k]->Type==0) cloud=&sky1; + else if (nuages[k]->Type==1) cloud=&sky2; + else cloud=&sky3; - dimage( nuages[k]->X-offset, nuages[k]->Y, cloud ); + nuages[k]->X--; + + if (nuages[k]->X>792) nuages[k]->X-=396*3; + else if (nuages[k]->X<-396) nuages[k]->X+=396*3; + + dimage( nuages[k]->X, nuages[k]->Y, cloud ); } } + + +void drawFarBackground( int offset ) +{ + int X = offset; + int DX = mountain.width; + + while (X>0) + { + X-=DX; + } + + do + { + if (X>-1*DX) dimage(X, 60, &mountain); + X+=DX; + } + while(X0) + { + X-=DX; + } + + do + { + if (X>-1*DX) dimage(X, 90, &treeline); + X+=DX; + } + while(X +#include #include "../fixed.h" +extern uint8_t minYRoad; + void gint_dhline(int x1, int x2, int y, uint16_t color) { if((uint)y >= 224) return; @@ -34,6 +37,12 @@ void drawGrass( int y1, int y2, uint8_t R, uint8_t G, uint8_t B ) }; +void drawGrass( int y1, int y2, uint16_t color ) +{ + for (int y=y1; y<=y2; y++) gint_dhline( 0, SCREEN_WIDTH, y, color ); +}; + + void drawPolygon( int x1min, int x1max, int y1, int x2min, int x2max, int y2, uint8_t R, uint8_t G, uint8_t B ) { @@ -63,11 +72,56 @@ void drawPolygon( int x1min, int x1max, int y1, int x2min, int x2max, int y2, ui } }; + +void drawPolygon( int x1min, int x1max, int y1, int x2min, int x2max, int y2, uint16_t color ) +{ + if (y1==y2) + { + gint_dhline( x1min, x1max, y1, color ); + return; + } + + fixed_t deltay = fdiv(fix(1), fix(y2-y1)); + + fixed_t xmin = fix(x1min); + fixed_t xmax = fix(x1max); + fixed_t dxmin = fix(x2min-x1min); + fixed_t dxmax = fix(x2max-x1max); + + for (int y=y1; y<=y2; y++) + { + if (y>0 && y