487 lines
14 KiB
C++
487 lines
14 KiB
C++
#include "../include/circuit.h"
|
|
#include "../include/segment.h"
|
|
#include "../include/camera.h"
|
|
#include "../include/clouds.h"
|
|
#include "../parameters.h"
|
|
|
|
#include <gint/display.h>
|
|
#include <gint/std/stdlib.h>
|
|
#include <gint/rtc.h>
|
|
|
|
#include "../include/drawstuff.h"
|
|
|
|
|
|
extern std::vector<Segment*> circuit;
|
|
extern std::vector<Clouds*> nuages;
|
|
extern camera *cam;
|
|
extern uint16_t currentcurve;
|
|
extern uint8_t shiftcolor;
|
|
extern int MAX_SEGMENT;
|
|
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 sky1, sky2, sky3;
|
|
|
|
bopti_image_t *scaledTrees[3][25] = { 0 };
|
|
|
|
|
|
|
|
size_t image_size_profile(int profile, int width, int height)
|
|
{
|
|
size_t size = sizeof(bopti_image_t);
|
|
|
|
if(profile == 0 || profile == 1) // PX_RGB565, PX_RGB565A
|
|
size += width * height * 2;
|
|
else if(profile == 2) // PX_P8
|
|
size += 512 + width * height;
|
|
else if(profile == 3) // PX_P4
|
|
size += 32 + ((width + 1) / 2) * height;
|
|
|
|
return size;
|
|
}
|
|
|
|
size_t image_size(bopti_image_t const *img)
|
|
{
|
|
return image_size_profile(img->profile, img->width, img->height);
|
|
}
|
|
|
|
int get_pixel(bopti_image_t const *img, int x, int y)
|
|
{
|
|
if((unsigned)x >= img->width || (unsigned)y >= img->height)
|
|
return 0;
|
|
|
|
uint8_t *bytes = (void *)img->data;
|
|
|
|
if(img->profile <= 1)
|
|
return img->data[y * img->width + x];
|
|
if(img->profile == 2)
|
|
return bytes[y * img->width + x + 512];
|
|
if(img->profile == 3)
|
|
{
|
|
int s = (img->width + 1) >> 1;
|
|
int i = y * s + (x >> 1) + 32;
|
|
if(x & 1)
|
|
return bytes[i] & 0x0f;
|
|
else
|
|
return bytes[i] >> 4;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void set_pixel(bopti_image_t *img, int x, int y, int color)
|
|
{
|
|
if((unsigned)x >= img->width || (unsigned)y >= img->height)
|
|
return;
|
|
|
|
uint8_t *bytes = (void *)img->data;
|
|
|
|
if(img->profile <= 1)
|
|
img->data[y * img->width + x] = color;
|
|
else if(img->profile == 2)
|
|
bytes[y * img->width + x + 512] = color;
|
|
else if(img->profile == 3)
|
|
{
|
|
int s = (img->width + 1) >> 1;
|
|
int i = y * s + (x >> 1) + 32;
|
|
if(x & 1)
|
|
bytes[i] = (bytes[i] & 0xf0) | (color & 0x0f);
|
|
else
|
|
bytes[i] = (bytes[i] & 0x0f) | ((color & 0x0f) << 4);
|
|
}
|
|
}
|
|
|
|
bopti_image_t *resize(bopti_image_t const *src, int w, int h)
|
|
{
|
|
size_t size = image_size_profile(src->profile, w, h);
|
|
bopti_image_t *img = malloc(size);
|
|
if(!img) return NULL;
|
|
|
|
size_t palette_size = 0;
|
|
if(src->profile == 2) // PX_P8
|
|
palette_size = 512;
|
|
else if(src->profile == 3) // PX_P4
|
|
palette_size = 32;
|
|
|
|
img->profile = src->profile;
|
|
img->alpha = src->alpha;
|
|
img->width = w;
|
|
img->height = h;
|
|
memcpy(img->data, src->data, palette_size);
|
|
|
|
for(int y = 0; y < h; y++)
|
|
for(int x = 0; x < w; x++)
|
|
{
|
|
int color = get_pixel(src, x * src->width / w, y * src->height / h);
|
|
set_pixel(img, x, y, color);
|
|
}
|
|
|
|
return img;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void initData( void )
|
|
{
|
|
cam = new camera();
|
|
cam->cX = fixdouble(0.0f);
|
|
cam->cY = fixdouble(300.0f);
|
|
cam->cZ = fixdouble(260.0f);
|
|
}
|
|
|
|
|
|
void createCircuit( void )
|
|
{
|
|
/* for( int i=0; i<MAX_SEGMENT; i++)
|
|
{
|
|
Segment *seg=new Segment( i );
|
|
if (seg!=nullptr) circuit.push_back( seg );
|
|
}
|
|
*/
|
|
|
|
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 );
|
|
};
|
|
|
|
|
|
void createClouds( void )
|
|
{
|
|
srand( rtc_ticks() );
|
|
|
|
for( int k = 0; k < 10; k++)
|
|
{
|
|
int X = (rand() % 1188) - 396;
|
|
int Y = rand() % 80;
|
|
int T = rand() % 3;
|
|
|
|
Clouds* cl=new Clouds( X, Y, T );
|
|
if (cl!=nullptr) nuages.push_back( cl );
|
|
}
|
|
}
|
|
|
|
|
|
void addStraightLine( Length l )
|
|
{
|
|
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; i<l; i++)
|
|
{
|
|
//Segment *s=new Segment( i );
|
|
int deco = rand() % 4;
|
|
Segment *seg;
|
|
|
|
if (deco==0) seg=new Segment( 0, lastY, lastZ + (i+1)*SEGMENT_LENGTH, 0, -1, -1 );
|
|
else if (deco==1) seg=new Segment( 0, lastY, lastZ + (i+1)*SEGMENT_LENGTH, 0, -1, DEADTREE );
|
|
else if (deco==2) seg=new Segment( 0, lastY, lastZ + (i+1)*SEGMENT_LENGTH, 0, PALMTREE, -1 );
|
|
else if (deco==3) seg=new Segment( 0, lastY, lastZ + (i+1)*SEGMENT_LENGTH, 0, PALMTREE, DEADTREE );
|
|
|
|
if (seg!=nullptr) circuit.push_back( seg );
|
|
}
|
|
}
|
|
|
|
void addCurve( Length l, CurveStrength s, CurveType t )
|
|
{
|
|
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; i<l; i++)
|
|
{
|
|
//Segment *s=new Segment( i );
|
|
int deco = rand() % 4;
|
|
|
|
Segment *seg;
|
|
|
|
if (deco==0) seg=new Segment( 0, lastY, lastZ+(i+1)*SEGMENT_LENGTH, s*t, -1, -1 );
|
|
else if (deco==1) seg=new Segment( 0, lastY, lastZ+(i+1)*SEGMENT_LENGTH, s*t, -1, OAKTREE );
|
|
else if (deco==2) seg=new Segment( 0, lastY, lastZ+(i+1)*SEGMENT_LENGTH, s*t, DEADTREE, -1 );
|
|
else if (deco==3) seg=new Segment( 0, lastY, lastZ+(i+1)*SEGMENT_LENGTH, s*t, DEADTREE, OAKTREE );
|
|
|
|
if (seg!=nullptr) circuit.push_back( seg );
|
|
}
|
|
}
|
|
|
|
|
|
void addHill( Length l, HillSize s, HillType t )
|
|
{
|
|
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; i<l; i++)
|
|
{
|
|
//Segment *s=new Segment( i );
|
|
int deco = rand() % 4;
|
|
Segment *seg;
|
|
|
|
if (deco==0) seg=new Segment( 0, lastY+(i+1)*t*s, lastZ+(i+1)*SEGMENT_LENGTH, 0, -1, -1 );
|
|
else if (deco==1) seg=new Segment( 0, lastY+(i+1)*t*s, lastZ+(i+1)*SEGMENT_LENGTH, 0, -1, PALMTREE );
|
|
else if (deco==2) seg=new Segment( 0, lastY+(i+1)*t*s, lastZ+(i+1)*SEGMENT_LENGTH, 0, OAKTREE, -1 );
|
|
else if (deco==3) seg=new Segment( 0, lastY+(i+1)*t*s, lastZ+(i+1)*SEGMENT_LENGTH, 0, OAKTREE, PALMTREE );
|
|
|
|
if (seg!=nullptr) circuit.push_back( seg );
|
|
}
|
|
}
|
|
|
|
|
|
void projectCircuitFP( void )
|
|
{
|
|
for( int i=0; i<circuit.size(); i++)
|
|
{
|
|
circuit[i]->Project3DFP( cam );
|
|
}
|
|
};
|
|
|
|
|
|
void projectCircuitFP( uint16_t index )
|
|
{
|
|
circuit[index]->Project3DFP( cam );
|
|
};
|
|
|
|
|
|
void printCircuit( void )
|
|
{
|
|
for( int i=0; i<20; i++)
|
|
{
|
|
dprint(198, 1+10*(i), C_RED, "%d-(sX,Y,W)=(%d,%d,%d)", i, circuit[i]->X, circuit[i]->Y, circuit[i]->W );
|
|
//dprint(1, 1+10*(i), C_GREEN, "%d-(_sY,Y,W)=(%.0f,%.0f,%.0f)", i, circuit[i]->_wX, circuit[i]->_wY, circuit[i]->_sW );
|
|
}
|
|
};
|
|
|
|
void printCircuit( int i )
|
|
{
|
|
dprint(1, 1+10*(i), C_RED, "%d-(wX,Y,Z)=(%d,%d,%d)", i, fround(circuit[i]->wX), fround(circuit[i]->wY), fround(circuit[i]->wZ) );
|
|
dprint(198, 1+10*(i), C_RED, "%d-(sX,Y,W)=(%d,%d,%d)", i, circuit[i]->X, circuit[i]->Y, circuit[i]->W );
|
|
};
|
|
|
|
|
|
void drawCircuitSegment( uint16_t index )
|
|
{
|
|
if (index>=circuit.size()-1) return;
|
|
|
|
int X1 = (int) circuit[index]->X;
|
|
int Y1 = (int) circuit[index]->Y;
|
|
int W1 = (int) circuit[index]->W;
|
|
int X2 = (int) circuit[(index+1)]->X + circuit[index]->Curve;
|
|
int Y2 = (int) circuit[(index+1)]->Y;
|
|
int W2 = (int) circuit[(index+1)]->W;
|
|
|
|
if (Y1==Y2) return;
|
|
|
|
if (index%2==0)
|
|
{
|
|
drawGrass( Y2, Y1, 0, 255-shiftcolor, 45-shiftcolor );
|
|
|
|
// route
|
|
drawPolygon( X2-W2+currentcurve, X2+W2+currentcurve, Y2, X1-W1+currentcurve, X1+W1+currentcurve, Y1, 196-shiftcolor, 196-shiftcolor, 196-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 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 );
|
|
|
|
// 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 );
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
drawGrass( Y2, Y1, 0, 255-shiftcolor, 0 );
|
|
|
|
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 );
|
|
|
|
}
|
|
}
|
|
|
|
|
|
fixed_t interpolatePositionX( double currentZ )
|
|
{
|
|
int index = (int) (currentZ / SEGMENT_LENGTH);
|
|
fixed_t x1 = fix(circuit[index]->wX);
|
|
fixed_t x2 = fix(circuit[index+1]->wX);
|
|
fixed_t dZ = fixdouble(currentZ-index*SEGMENT_LENGTH);
|
|
|
|
fixed_t result = x1 + fmul( x2-x1, fdiv( dZ, fix(SEGMENT_LENGTH)));
|
|
|
|
if(ShowDebug1)
|
|
{
|
|
dprint( 120, 1, C_WHITE, "CZ=%.0lf", f2double(currentZ) );
|
|
dprint( 120, 15, C_WHITE, "y1=%d", fround(x1) );
|
|
dprint( 120, 29, C_WHITE, "y2=%d", fround(x2) );
|
|
|
|
dprint( 240, 15, C_WHITE, "Dz=%d", fround(dZ) );
|
|
dprint( 240, 29, C_GREEN, "CX=%d", fround(result) );
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
fixed_t interpolatePositionY( double currentZ )
|
|
{
|
|
int index = (int) (currentZ / SEGMENT_LENGTH);
|
|
fixed_t y1 = fix(circuit[index]->wY);
|
|
fixed_t y2 = fix(circuit[index+1]->wY);
|
|
fixed_t dZ = fixdouble(currentZ-index*SEGMENT_LENGTH);
|
|
|
|
fixed_t result = y1 + fmul( y2-y1, fdiv( dZ, fix(SEGMENT_LENGTH)));
|
|
|
|
if(ShowDebug1)
|
|
{
|
|
dprint( 120, 1, C_WHITE, "CZ=%.0lf", f2double(currentZ) );
|
|
dprint( 120, 15, C_WHITE, "y1=%d", fround(y1) );
|
|
dprint( 120, 29, C_WHITE, "y2=%d", fround(y2) );
|
|
|
|
dprint( 240, 15, C_WHITE, "Dz=%d", fround(dZ) );
|
|
dprint( 240, 43, C_GREEN, "CY=%d", fround(result) );
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
void prepareDecoration( void )
|
|
{
|
|
bopti_image_t const *src;
|
|
|
|
for( int k=0; k<3; k++)
|
|
{
|
|
float scale=1.0f;
|
|
for( int i=0; i<25; i++)
|
|
{
|
|
scale=2.0f/((float) (i+1));
|
|
if(k==0) src = &tree1;
|
|
else if(k==1) src = &tree2;
|
|
else if(k==2) src = &tree3;
|
|
|
|
int width = (int) ((float) src->width * scale);
|
|
int height = (int) ((float) src->height * scale);
|
|
scaledTrees[k][i] = resize(src, width, height);
|
|
//scale*=0.85f;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void freeDecoration( void )
|
|
{
|
|
for( int k=0; k<3; k++)
|
|
for( int i=0; i<25; i++)
|
|
free(scaledTrees[k][i]);
|
|
}
|
|
|
|
|
|
void drawDecoration( uint16_t index )
|
|
{
|
|
bopti_image_t *image;
|
|
|
|
int distance = fround(fdiv( (fixdouble(circuit[index]->wZ) - cam->cZ), fix(SEGMENT_LENGTH) )) - 1;
|
|
|
|
if (distance<0) distance = 0;
|
|
else if (distance>24) distance = 24;
|
|
|
|
circuit[index]->DScale = distance;
|
|
|
|
int deco = circuit[index]->LDeco;
|
|
|
|
if (deco!=-1)
|
|
{
|
|
image = scaledTrees[deco][distance];
|
|
|
|
int X = circuit[index]->X + circuit[index]->CumulatedCurve - 1.5*circuit[index]->W - image->width/2;
|
|
int Y = circuit[index]->Y - image->height;
|
|
|
|
dimage( X, Y, image );
|
|
}
|
|
|
|
deco = circuit[index]->RDeco;
|
|
|
|
if (deco!=-1)
|
|
{
|
|
image = scaledTrees[deco][distance];
|
|
|
|
int X = circuit[index]->X + circuit[index]->CumulatedCurve + 1.5*circuit[index]->W - image->width/2;
|
|
int Y = circuit[index]->Y - image->height;
|
|
|
|
dimage( X, Y, image );
|
|
}
|
|
}
|
|
|
|
|
|
void drawClouds( int offset )
|
|
{
|
|
bopti_image_t *cloud;
|
|
|
|
for( int k =0; k<nuages.size(); k++ )
|
|
{
|
|
if (nuages[k]->type==0) cloud=&sky1;
|
|
else if (nuages[k]->type==1) cloud=&sky2;
|
|
else if (nuages[k]->type==2) cloud=&sky3;
|
|
|
|
dimage( nuages[k]->X-offset, nuages[k]->Y, cloud );
|
|
}
|
|
}
|