diff --git a/CMakeLists.txt b/CMakeLists.txt index 50b73d8..36320a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ set(SOURCES src/src/drawstuff.cc src/src/clouds.cc src/src/cars.cc + src/src/menus.cc ) set(ASSETS_cg @@ -44,8 +45,13 @@ set(ASSETS_cg assets-cg/billboard/rightturn.png assets-cg/billboard/uphill.png assets-cg/billboard/downhill.png + assets-cg/billboard/checkpoint.png assets-cg/fonts/speedfont.png + assets-cg/fonts/auto15.png + assets-cg/fonts/auto20.png + assets-cg/menus/flag.png assets-cg/hud/speedhud.png + assets-cg/screens/mainscreen.png ) fxconv_declare_assets(${ASSETS_cg} WITH_METADATA) diff --git a/CppOutRun.cbp b/CppOutRun.cbp index 6a04d9f..200dd18 100644 --- a/CppOutRun.cbp +++ b/CppOutRun.cbp @@ -26,6 +26,7 @@ + @@ -35,6 +36,7 @@ + @@ -43,6 +45,7 @@ + diff --git a/CppOutRun.layout b/CppOutRun.layout index e429c85..c79b1f2 100644 --- a/CppOutRun.layout +++ b/CppOutRun.layout @@ -2,6 +2,26 @@ + + + + + + + + + + + + + + + + + + + + @@ -12,24 +32,54 @@ - + - - - - - - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -37,9 +87,14 @@ - + - + + + + + + @@ -49,7 +104,12 @@ - + + + + + + @@ -57,39 +117,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 0000000..f24443e --- /dev/null +++ b/TODO.txt @@ -0,0 +1,22 @@ + +Add Start line with green/orange/red lights for start +Add Finish line +Add Checkpoints + + +Menus and Options + +Add Player name (3 letters on car plate) + + +Traffic AI + +Circuit editor ? + +Various circuit + +Additional landscapes / sprites / biomes + + + +Color Palet transformation for vegetation depending on biomes (plains = greenish / desert = yellowish / ... ) diff --git a/assets-cg/billboard/checkpoint.png b/assets-cg/billboard/checkpoint.png new file mode 100644 index 0000000..f8f283e Binary files /dev/null and b/assets-cg/billboard/checkpoint.png differ diff --git a/assets-cg/billboard/startlights.png b/assets-cg/billboard/startlights.png new file mode 100644 index 0000000..83fb08c Binary files /dev/null and b/assets-cg/billboard/startlights.png differ diff --git a/assets-cg/billboard/stoplights.png b/assets-cg/billboard/stoplights.png new file mode 100644 index 0000000..a6a74de Binary files /dev/null and b/assets-cg/billboard/stoplights.png differ diff --git a/assets-cg/billboard/waitlights.png b/assets-cg/billboard/waitlights.png new file mode 100644 index 0000000..d80f173 Binary files /dev/null and b/assets-cg/billboard/waitlights.png differ diff --git a/assets-cg/fonts/auto15.png b/assets-cg/fonts/auto15.png new file mode 100644 index 0000000..cd55c7a Binary files /dev/null and b/assets-cg/fonts/auto15.png differ diff --git a/assets-cg/fonts/auto20.png b/assets-cg/fonts/auto20.png new file mode 100644 index 0000000..2dc5192 Binary files /dev/null and b/assets-cg/fonts/auto20.png differ diff --git a/assets-cg/fonts/auto_digital.ttf b/assets-cg/fonts/auto_digital.ttf new file mode 100644 index 0000000..c778131 Binary files /dev/null and b/assets-cg/fonts/auto_digital.ttf differ diff --git a/assets-cg/fonts/fxconv-metadata.txt b/assets-cg/fonts/fxconv-metadata.txt index c2fc03c..7f4df51 100644 --- a/assets-cg/fonts/fxconv-metadata.txt +++ b/assets-cg/fonts/fxconv-metadata.txt @@ -7,3 +7,17 @@ speedfont.png: grid.border: 0 proportional: true height: 18 + +auto15.png: + name: autofont + type: font + charset: print + grid.size: 21x28 + +auto20.png: + name: autofontsmall + type: font + charset: print + grid.size: 14x20 + + diff --git a/assets-cg/fonts/gff b/assets-cg/fonts/gff new file mode 100644 index 0000000..bce4402 --- /dev/null +++ b/assets-cg/fonts/gff @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +from math import ceil +from sys import argv +from PIL import Image, ImageDraw, ImageFont + +if (len(argv) < 4): + raise BaseException("At least three arguments expected: " + \ + " " + \ + "[initial char index] [char range]") + +font_path = argv[1] +font_size = int(argv[2]) +image_out = argv[3] +initial_char_index = int(argv[4]) if len(argv) > 4 else 0x20 +char_range = int(argv[5]) if len(argv) > 5 else 96 +line_count = ceil(char_range / 16) +scan_index = 0x20 if len(argv) > 4 else initial_char_index +scan_range = 0x30ff - 0x20 if len(argv) > 4 else char_range + +assert char_range > 1 + +mode = '1' # 1-bit depth +background_color = (1) # white +foreground_color = (0) # black + +# load font +font = ImageFont.truetype(font_path, font_size) + +# find max char size +char_width = 0 +char_height = 0 +for i in range(scan_range): + bbox = list(font.getbbox(chr(scan_index + i))) + # don't you dare overlap + if (bbox[0] < 0): + bbox[2] = -bbox[0] + if (bbox[1] < 0): + bbox[3] -= bbox[1] + if bbox[2] > char_width: + char_width = bbox[2] + if bbox[3] > char_height: + char_height = bbox[3] + +image_out_width = char_width * 16 +image_out_height = char_height * line_count + +# fxconv metadata +print(f"{image_out.split('/')[-1]}:") +print(" type: font") +print(" charset: print") +print(f" grid.size: {char_width}x{char_height}") + +# create image +im = Image.new(mode, (image_out_width, image_out_height)) + +# draw +draw = ImageDraw.Draw(im) +draw.rectangle((0, 0, image_out_width, image_out_height), fill=background_color) + +x = -char_width +y = 0 +for i in range(char_range): + x += char_width + char = chr(initial_char_index + i) + bbox = font.getbbox(char) + x_mod = 0 + y_mod = 0 + # don't you dare overlap + if (bbox[0] < 0): + x_mod = -bbox[0] + if (bbox[1] < 0): + y_mod = -bbox[1] + if i != 0 and i % 16 == 0: + x = 0 + y += char_height + draw.text((x + x_mod, y + y_mod), char, fill=foreground_color, font=font) + +# save +im.save(image_out) + diff --git a/assets-cg/hud/speedhud.png b/assets-cg/hud/speedhud.png index dd6ab4a..a997b2e 100644 Binary files a/assets-cg/hud/speedhud.png and b/assets-cg/hud/speedhud.png differ diff --git a/assets-cg/menus/flag.png b/assets-cg/menus/flag.png new file mode 100644 index 0000000..2aed57d Binary files /dev/null and b/assets-cg/menus/flag.png differ diff --git a/assets-cg/menus/fxconv-metadata.txt b/assets-cg/menus/fxconv-metadata.txt new file mode 100644 index 0000000..7e05b58 --- /dev/null +++ b/assets-cg/menus/fxconv-metadata.txt @@ -0,0 +1,5 @@ +*.png: + type: bopti-image + profile: p4 + name_regex: (.*)\.png \1 + diff --git a/assets-cg/screens/fxconv-metadata.txt b/assets-cg/screens/fxconv-metadata.txt new file mode 100644 index 0000000..ac7543f --- /dev/null +++ b/assets-cg/screens/fxconv-metadata.txt @@ -0,0 +1,5 @@ +*.png: + type: bopti-image + profile: p8 + name_regex: (.*)\.png \1 + diff --git a/assets-cg/screens/mainscreen.png b/assets-cg/screens/mainscreen.png new file mode 100644 index 0000000..de7a3ef Binary files /dev/null and b/assets-cg/screens/mainscreen.png differ diff --git a/src/include/circuit.h b/src/include/circuit.h index e8b04cf..03ece9e 100644 --- a/src/include/circuit.h +++ b/src/include/circuit.h @@ -51,7 +51,8 @@ enum Decoration LEFTTURN = 6, RIGHTTURN = 7, UPHILL = 8, - DOWNHILL = 9 + DOWNHILL = 9, + CHECK = 10 }; void initData( void ); @@ -81,6 +82,7 @@ void prepareDecoration( void ); void freeTraffic( void ); void prepareTraffic( void ); +void addCheckPoint( int8_t biome ); 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 ); diff --git a/src/include/menus.h b/src/include/menus.h new file mode 100644 index 0000000..3b6a9ac --- /dev/null +++ b/src/include/menus.h @@ -0,0 +1,17 @@ +#ifndef MENUS_H +#define MENUS_H + + +void drawStartTitle( void ); +void getInputStartTitle( void ); + +int drawMainMenu( void ); +void getInputMainMenu( void ); + +int drawMenuCircuitSelect( void ); +void getInputCircuitSelect( void ); + +void drawCredit( void ); +void getInputCredit( void ); + +#endif // MENUS_H diff --git a/src/include/segment.h b/src/include/segment.h index 7c83c1e..17343f4 100644 --- a/src/include/segment.h +++ b/src/include/segment.h @@ -15,6 +15,12 @@ enum BiomeType DESERT = 1 }; +enum Specialty +{ + START = 0, + CHECKPOINT = 1, + FINISH = 2 +}; class Segment { @@ -27,7 +33,8 @@ class Segment void Project3DFP( camera* c ); - int8_t environment = PLAINS; + int8_t Environment = PLAINS; + int8_t Special = 0; int8_t Curve=0; int8_t Slope=0; diff --git a/src/main.cc b/src/main.cc index b83098b..e2e42d4 100644 --- a/src/main.cc +++ b/src/main.cc @@ -22,14 +22,16 @@ #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 leftturn, rightturn, uphill, downhill, checkpoint; 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; @@ -240,31 +242,59 @@ int main(void) __printf_enable_fp(); __printf_enable_fixed(); - #if IS_FXLIB==1 +#if IS_FXLIB==1 usb_interface_t const *interfaces[] = { &usb_ff_bulk, NULL }; usb_open(interfaces, GINT_CALL_NULL); - #endif +#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); + + 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 + initData( ); // Positioning of the Camera + createCircuit(); // Creates the circuit - putBillBoards(); + putBillBoards(); - 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) + 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); @@ -315,43 +345,43 @@ int main(void) prof_enter(perf_project); - if (BDrawCars) - { - updateTraffic( dt ); + if (BDrawCars) + { + updateTraffic( dt ); - for (int k=0; kwZ / SEGMENT_LENGTH; + if (CarSegment>=indexstart && CarSegmentwZ / SEGMENT_LENGTH; - if (CarSegment>=indexstart && CarSegmentvisible = true; - circuit[CarSegment]->CarList.push_back(k); - } - else - traffic[k]->visible = false; + traffic[k]->visible = true; + circuit[CarSegment]->CarList.push_back(k); } + else + traffic[k]->visible = false; } + } - minYRoad = SCREEN_HEIGHT; + 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 + 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; + 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; + 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 ); - } - } + 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); @@ -383,11 +413,11 @@ int main(void) drawDecoration( k ); if (BDrawCars) - for( int l=0; lCarList.size(); l++ ) // For all cars inside that road segment - { + 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(); } @@ -423,6 +453,9 @@ int main(void) } + 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 ); @@ -434,16 +467,34 @@ int main(void) float drawspeed = (float) (speed*5.0f); + dsubimage( 5, 5, &speedhud, 0, 117, 37, 13, DIMAGE_NONE); // speed logo - dsubimage( 155, 5, &speedhud, 0, 130, 37, 13, DIMAGE_NONE); // timer 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); - 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" + 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(253,3, C_RGB(0,0,0), C_NONE, DTEXT_RIGHT, DTEXT_TOP, "%.3D ;", remaining_time ); - dprint_opt(250,1, C_RGB(255,255,0), C_NONE, DTEXT_RIGHT, DTEXT_TOP, "%.3D ;", remaining_time ); // the ';' char corresponds to "s" + 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); @@ -458,101 +509,101 @@ int main(void) //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 + /* + #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 + 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 -*/ + Segment* currentSeg = circuit[indexstart]; -/* - for( int k=indexend-1; k>=indexstart; k--) - { - circuit[k]->CarList.clear(); - } -*/ + 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); diff --git a/src/parameters.h b/src/parameters.h index 20ca50f..4b9cae6 100644 --- a/src/parameters.h +++ b/src/parameters.h @@ -22,7 +22,7 @@ #define NB_CARS_TRAFFIC 100 #define MAX_SUBIMAGES_TREES 12 -#define NB_TREES_TYPES 10 +#define NB_TREES_TYPES 11 #define MAX_SUBIMAGES_CARS 12 #define NB_CARS_TYPES 8 diff --git a/src/src/circuit.cc b/src/src/circuit.cc index af7a8e6..8595570 100644 --- a/src/src/circuit.cc +++ b/src/src/circuit.cc @@ -30,7 +30,7 @@ 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; -extern bopti_image_t leftturn, rightturn, uphill, downhill; +extern bopti_image_t leftturn, rightturn, uphill, downhill, checkpoint; bopti_image_t *scaledTrees[NB_TREES_TYPES][MAX_SUBIMAGES_TREES] = { 0 }; @@ -152,6 +152,9 @@ void createCircuit( void ) addCurvyHill( L_MEDIUM, H_BIG, UP_HILL, C_HARD, LEFT_CURVE, DESERT ); addStraightLine( L_VERYSHORT, DESERT ); addCurvyHill( L_MEDIUM, H_BIG, DOWN_HILL, C_HARD, RIGHT_CURVE, DESERT ); + addCheckPoint( PLAINS ); + addStraightLine( L_VERYSHORT, PLAINS ); + addCheckPoint( DESERT ); //addStraightLine( L_VERYSHORT, PLAINS ); //addStraightLine( L_VERYSHORT, DESERT ); addCurve( L_SHORT, C_HARD, LEFT_CURVE, DESERT ); @@ -285,6 +288,50 @@ void createTraffic( void ) } } +void addCheckPoint( 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; + } + + for( int i=0; i<5; i++) + { + Segment *seg=new Segment( 0, lastY, lastZ + i*SEGMENT_LENGTH, 0, 0, -1, -1 ); + if (seg!=nullptr) + { + seg->Environment = biome; + circuit.push_back( seg ); + } + } + + for( int i=5; i<10; i++) + { + Segment *seg=new Segment( 0, lastY, lastZ + i*SEGMENT_LENGTH, 0, 0, CHECK, CHECK ); + if (seg!=nullptr) + { + seg->Environment = biome; + if (i==7) seg->Special = CHECKPOINT; + circuit.push_back( seg ); + } + } + + for( int i=10; i<15; i++) + { + Segment *seg=new Segment( 0, lastY, lastZ + i*SEGMENT_LENGTH, 0, 0, -1, -1 ); + if (seg!=nullptr) + { + seg->Environment = biome; + circuit.push_back( seg ); + } + } +} + void addStraightLine( Length l, int8_t biome ) { @@ -313,7 +360,7 @@ void addStraightLine( Length l, int8_t biome ) if (seg!=nullptr) { - seg->environment = biome; + seg->Environment = biome; circuit.push_back( seg ); } } @@ -347,7 +394,7 @@ void addCurve( Length l, CurveStrength s, CurveType t, int8_t biome ) if (seg!=nullptr) { - seg->environment = biome; + seg->Environment = biome; circuit.push_back( seg ); } } @@ -381,7 +428,7 @@ void addHill( Length l, HillSize s, HillType t, int8_t biome ) if (seg!=nullptr) { - seg->environment = biome; + seg->Environment = biome; circuit.push_back( seg ); } } @@ -415,7 +462,7 @@ void addCurvyHill( Length l, HillSize s, HillType t, CurveStrength cs, CurveType if (seg!=nullptr) { - seg->environment = biome; + seg->Environment = biome; circuit.push_back( seg ); } } @@ -486,7 +533,7 @@ void drawCircuitSegment( uint16_t index ) } */ - if (circuit[index]->environment == PLAINS) + if (circuit[index]->Environment == PLAINS) { if (index%2==0) { @@ -517,7 +564,7 @@ void drawCircuitSegment( uint16_t index ) drawPolygon( X2+W2/16+W2+currentcurve, 396, Y2, X1+W1/16+W1+currentcurve, 396, Y1, LIGHT_GREEN_GRASS ); } } - else if (circuit[index]->environment == DESERT) + else if (circuit[index]->Environment == DESERT) { if (index%2==0) { @@ -614,7 +661,8 @@ void prepareDecoration( void ) else if (k==6) src = &leftturn; else if (k==7) src = &rightturn; else if (k==8) src = &uphill; - else src = &downhill; + else if (k==9) src = &downhill; + else src = &checkpoint; int width = (int) ((float) src->width * scale); diff --git a/src/src/menus.cc b/src/src/menus.cc new file mode 100644 index 0000000..401149a --- /dev/null +++ b/src/src/menus.cc @@ -0,0 +1,368 @@ +#include "../include/menus.h" +#include +#include + + +extern bopti_image_t mainscreen; +extern bopti_image_t flag; +extern font_t autofont, autofontsmall; + + +bool doneTitle = false; + +bool doneMainMenu = false; +uint8_t MainMenuSelection=0; + +bool doneMenuCircuit = false; +uint8_t CircuitSelection=0; + +bool doneMenuCredit = false; + + + + +void drawStartTitle( void ) +{ + uint16_t pulse=0; + doneTitle = false; + while (!doneTitle) + { + + dclear( C_BLACK ); + dsubimage( 0, 32, &mainscreen, 0, 32, 396, 160, DIMAGE_NONE); + + dfont(&autofont); + + dprint_opt(198, 2, C_RGB(255,255,255), C_NONE, DTEXT_CENTER, DTEXT_TOP, "OUTRUN FOR GRAPH90" ); + + dprint_opt(198, 222, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_CENTER, DTEXT_BOTTOM, "PRESS EXE TO START" ); + + // CODE HERE TO PRINT WELCOME MENU + + dupdate(); + + pulse++; + getInputStartTitle(); + } +} + +void getInputStartTitle( void ) +{ + int opt = GETKEY_DEFAULT & ~GETKEY_REP_ARROWS; + int timeout = 1; + + while(1) + { + key_event_t ev = getkey_opt(opt, &timeout); + if(ev.type == KEYEV_NONE) return -1; + + int key = ev.key; + + if (key==KEY_EXE) + doneTitle = true; + } +} + + + + +int drawMainMenu( void ) +{ + uint16_t pulse=0; + doneMainMenu = false; + + MainMenuSelection=0; + + while (!doneMainMenu) + { + + dimage( 0, 0, &mainscreen); + + dfont(&autofont); + + if (MainMenuSelection!=0) dprint_opt(100, 20, C_RGB(255,255,255), C_NONE, DTEXT_LEFT, DTEXT_TOP, "ARCADE GAME" ); + else dprint_opt(100, 20, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_LEFT, DTEXT_TOP, "ARCADE GAME" ); + + if (MainMenuSelection!=1) dprint_opt(100, 60, C_RGB(255,255,255), C_NONE, DTEXT_LEFT, DTEXT_TOP, "TIME ATTACK" ); + else dprint_opt(100, 60, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_LEFT, DTEXT_TOP, "TIME ATTACK" ); + + if (MainMenuSelection!=2) dprint_opt(100, 100, C_RGB(255,255,255), C_NONE, DTEXT_LEFT, DTEXT_TOP, "OPTIONS" ); + else dprint_opt(100, 100, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_LEFT, DTEXT_TOP, "OPTIONS" ); + + if (MainMenuSelection!=3) dprint_opt(100, 140, C_RGB(255,255,255), C_NONE, DTEXT_LEFT, DTEXT_TOP, "CREDITS" ); + else dprint_opt(100, 140, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_LEFT, DTEXT_TOP, "CREDITS" ); + + if (MainMenuSelection!=4) dprint_opt(100, 180, C_RGB(255,255,255), C_NONE, DTEXT_LEFT, DTEXT_TOP, "QUIT TO OS" ); + else dprint_opt(100, 180, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_LEFT, DTEXT_TOP, "QUIT TO OS" ); + + dimage( 10, 10+40*MainMenuSelection, &flag ); + + // CODE HERE TO PRINT WELCOME MENU + + dupdate(); + + pulse++; + getInputMainMenu(); + } + + return MainMenuSelection; +} + +void getInputMainMenu( void ) +{ + int opt = GETKEY_DEFAULT & ~GETKEY_REP_ARROWS; + int timeout = 1; + + while(1) + { + key_event_t ev = getkey_opt(opt, &timeout); + if(ev.type == KEYEV_NONE) return -1; + + int key = ev.key; + + if (key==KEY_EXE) + doneMainMenu = true; + + if (key==KEY_UP) + { + if (MainMenuSelection==0) MainMenuSelection=4; + else MainMenuSelection--; + } + + if (key==KEY_DOWN) + { + if (MainMenuSelection==4) MainMenuSelection=0; + else MainMenuSelection++; + } + } +} + + + + +void drawRectangle( uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color, uint8_t thick ) +{ + for(int u=0; u<=thick; u++) + { + dline( x, y+u, x+w, y+u, color ); + dline( x, y+h-u, x+w, y+h-u, color ); + dline( x+u, y, x+u, y+h, color ); + dline( x+w-u, y, x+w-u, y+h, color ); + } + +} + +int drawMenuCircuitSelect( void ) +{ + uint16_t pulse=0; + doneMenuCircuit = false; + + CircuitSelection=0; + + while (!doneMenuCircuit) + { + + dclear( C_BLACK ); + dsubimage( 0, 32, &mainscreen, 0, 32, 396, 160, DIMAGE_NONE); + + dfont(&autofont); + + dprint_opt(198, 2, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_CENTER, DTEXT_TOP, "SELECT A CIRCUIT" ); + + if (CircuitSelection!=0) drawRectangle( 16, 45, 60, 60, C_WHITE, 3 ); + else + { + drawRectangle( 16, 45, 60, 60, C_RGB(pulse%256,0,pulse%256), 3 ); + dprint_opt(198, 222, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_CENTER, DTEXT_BOTTOM, ">> CIRCUIT #1" ); + } + + if (CircuitSelection!=1) drawRectangle( 92, 45, 60, 60, C_WHITE, 3 ); + else + { + drawRectangle( 92, 45, 60, 60, C_RGB(pulse%256,0,pulse%256), 3 ); + dprint_opt(198, 222, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_CENTER, DTEXT_BOTTOM, ">> CIRCUIT #2" ); + } + + if (CircuitSelection!=2) drawRectangle( 168, 45, 60, 60, C_WHITE, 3 ); + else + { + drawRectangle( 168, 45, 60, 60, C_RGB(pulse%256,0,pulse%256), 3 ); + dprint_opt(198, 222, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_CENTER, DTEXT_BOTTOM, ">> CIRCUIT #3" ); + } + + if (CircuitSelection!=3) drawRectangle( 244, 45, 60, 60, C_WHITE, 3 ); + else + { + drawRectangle( 244, 45, 60, 60, C_RGB(pulse%256,0,pulse%256), 3 ); + dprint_opt(198, 222, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_CENTER, DTEXT_BOTTOM, ">> CIRCUIT #4" ); + } + + if (CircuitSelection!=4) drawRectangle( 320, 45, 60, 60, C_WHITE, 3 ); + else + { + drawRectangle( 320, 45, 60, 60, C_RGB(pulse%256,0,pulse%256), 3 ); + dprint_opt(198, 222, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_CENTER, DTEXT_BOTTOM, ">> CIRCUIT #5" ); + } + + + if (CircuitSelection!=5) drawRectangle( 16, 120, 60, 60, C_WHITE, 3 ); + else + { + drawRectangle( 16, 120, 60, 60, C_RGB(pulse%256,0,pulse%256), 3 ); + dprint_opt(198, 222, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_CENTER, DTEXT_BOTTOM, ">> CIRCUIT #6" ); + } + + if (CircuitSelection!=6) drawRectangle( 92, 120, 60, 60, C_WHITE, 3 ); + else + { + drawRectangle( 92, 120, 60, 60, C_RGB(pulse%256,0,pulse%256), 3 ); + dprint_opt(198, 222, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_CENTER, DTEXT_BOTTOM, ">> CIRCUIT #7" ); + } + + if (CircuitSelection!=7) drawRectangle( 168, 120, 60, 60, C_WHITE, 3 ); + else + { + drawRectangle( 168, 120, 60, 60, C_RGB(pulse%256,0,pulse%256), 3 ); + dprint_opt(198, 222, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_CENTER, DTEXT_BOTTOM, ">> CIRCUIT #8" ); + } + + if (CircuitSelection!=8) drawRectangle( 244, 120, 60, 60, C_WHITE, 3 ); + else + { + drawRectangle( 244, 120, 60, 60, C_RGB(pulse%256,0,pulse%256), 3 ); + dprint_opt(198, 222, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_CENTER, DTEXT_BOTTOM, ">> CIRCUIT #9" ); + } + + if (CircuitSelection!=9) drawRectangle( 320, 120, 60, 60, C_WHITE, 3 ); + else + { + drawRectangle( 320, 120, 60, 60, C_RGB(pulse%256,0,pulse%256), 3 ); + dprint_opt(198, 222, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_CENTER, DTEXT_BOTTOM, ">> CIRCUIT #10" ); + } + + + + //dimage( 10, 10+40*CircuitSelection, &flag ); + + // CODE HERE TO PRINT WELCOME MENU + + dupdate(); + + pulse++; + getInputCircuitSelect(); + } + + return MainMenuSelection; +} + +void getInputCircuitSelect( void ) +{ + int opt = GETKEY_DEFAULT & ~GETKEY_REP_ARROWS; + int timeout = 1; + + while(1) + { + key_event_t ev = getkey_opt(opt, &timeout); + if(ev.type == KEYEV_NONE) return -1; + + int key = ev.key; + + if (key==KEY_EXE) + doneMenuCircuit = true; + + if (key==KEY_UP || key==KEY_LEFT) + { + if (CircuitSelection==0) CircuitSelection=9; + else CircuitSelection--; + } + + if (key==KEY_DOWN || key==KEY_RIGHT) + { + if (CircuitSelection==9) CircuitSelection=0; + else CircuitSelection++; + } + } +} + + + + + +void drawCredit( void ) +{ + uint16_t pulse=0; + int16_t offset=240; + + doneMenuCredit = false; + + while (!doneMenuCredit) + { + + dclear( 0x0000 ); + dimage( 0, 0, &mainscreen ); + + dfont(&autofont); + dprint_opt(202, offset + 4, C_RGB(0,0,0), C_NONE, DTEXT_CENTER, DTEXT_TOP, "OUTRUN FOR GRAPH90" ); + dprint_opt(200, offset + 2, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_CENTER, DTEXT_TOP, "OUTRUN FOR GRAPH90" ); + dfont(&autofontsmall); + dprint_opt(200, offset + 32, C_RGB(255,255,255), C_NONE, DTEXT_CENTER, DTEXT_TOP, "PROUDLY CODED BY" ); + dprint_opt(200, offset + 62, C_RGB(255,255,255), C_NONE, DTEXT_CENTER, DTEXT_TOP, "SLYVTT / MARCH 2022" ); + + dfont(&autofont); + dprint_opt(202, offset + 124, C_RGB(0,0,0), C_NONE, DTEXT_CENTER, DTEXT_TOP, "CODE :" ); + dprint_opt(200, offset + 122, C_RGB(255,0,255), C_NONE, DTEXT_CENTER, DTEXT_TOP, "CODE :" ); + dfont(&autofontsmall); + dprint_opt(200, offset + 162, C_RGB(255,255,255), C_NONE, DTEXT_CENTER, DTEXT_TOP, "SLYVTT" ); + dprint_opt(200, offset + 192, C_RGB(255,255,255), C_NONE, DTEXT_CENTER, DTEXT_TOP, "WITH SUPPORT FROM LEPHE" ); + + dfont(&autofont); + dprint_opt(202, offset + 254, C_RGB(0,0,0), C_NONE, DTEXT_CENTER, DTEXT_TOP, "VISUALS" ); + dprint_opt(200, offset + 252, C_RGB(255,0,255), C_NONE, DTEXT_CENTER, DTEXT_TOP, "VISUALS" ); + dfont(&autofontsmall); + dprint_opt(200, offset + 292, C_RGB(255,255,255), C_NONE, DTEXT_CENTER, DTEXT_TOP, "SLYVTT" ); + dprint_opt(200, offset + 322, C_RGB(255,255,255), C_NONE, DTEXT_CENTER, DTEXT_TOP, "WITH SUPPORT FROM INTERNET" ); + dprint_opt(200, offset + 352, C_RGB(255,255,255), C_NONE, DTEXT_CENTER, DTEXT_TOP, "GOOGLE IS MY BEST FRIEND" ); + + dfont(&autofont); + dprint_opt(202, offset + 414, C_RGB(0,0,0), C_NONE, DTEXT_CENTER, DTEXT_TOP, "MUSIC" ); + dprint_opt(200, offset + 412, C_RGB(255,0,255), C_NONE, DTEXT_CENTER, DTEXT_TOP, "MUSIC" ); + dfont(&autofontsmall); + dprint_opt(200, offset + 452, C_RGB(255,255,255), C_NONE, DTEXT_CENTER, DTEXT_TOP, "SORRY, NO MUSIC ..." ); + dprint_opt(200, offset + 482, C_RGB(255,255,255), C_NONE, DTEXT_CENTER, DTEXT_TOP, "... MAYBE ONE DAY !!!" ); + + dfont(&autofont); + dprint_opt(202, offset + 544, C_RGB(0,0,0), C_NONE, DTEXT_CENTER, DTEXT_TOP, "THANKS FOR PLAYING" ); + dprint_opt(202, offset + 574, C_RGB(0,0,0), C_NONE, DTEXT_CENTER, DTEXT_TOP, "HOPE YOU ENJOYED" ); + dprint_opt(200, offset + 542, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_CENTER, DTEXT_TOP, "THANKS FOR PLAYING" ); + dprint_opt(200, offset + 572, C_RGB(pulse%256,0,pulse%256), C_NONE, DTEXT_CENTER, DTEXT_TOP, "HOPE YOU ENJOYED" ); + + dupdate(); + + pulse++; + offset--; + getInputCredit(); + } + + return; +} + +void getInputCredit( void ) +{ + int opt = GETKEY_DEFAULT & ~GETKEY_REP_ARROWS; + int timeout = 1; + + while(1) + { + key_event_t ev = getkey_opt(opt, &timeout); + if(ev.type == KEYEV_NONE) return -1; + + int key = ev.key; + + if (key==KEY_EXE) + doneMenuCredit = true; + } +} + + + +