A simple OutRun on Casio Graph 90+E
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
OutRun/src/src/circuit.cc

925 lines
27 KiB

#include "../include/circuit.h"
#include "../include/segment.h"
#include "../include/camera.h"
#include "../include/clouds.h"
#include "../include/cars.h"
#include "../parameters.h"
#include <gint/display.h>
#include <gint/std/stdlib.h>
#include <gint/rtc.h>
#include "../include/drawstuff.h"
#include "../colors.h"
extern std::vector<Segment*> circuit;
extern std::vector<Clouds*> nuages;
extern std::vector<Cars*> traffic;
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, 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 checkpoint, startlights, stoplights, waitlights;
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)
{
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(0.0f);
}
void createCircuit( void )
{
addStartLine( PLAINS );
addStraightLine( L_VERYSHORT, PLAINS );
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 );
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 );
addStraightLine( L_VERYLONG, PLAINS );
addCurve( L_SHORT, C_HARD, LEFT_CURVE, PLAINS );
addStraightLine( L_VERYLONG, DESERT );
addCurve( L_SHORT, C_EASY, LEFT_CURVE, DESERT );
addCheckPoint( PLAINS );
addFinishLine( DESERT );
addStraightLine( L_VERYSHORT, PLAINS );
};
void putBillBoards( void )
{
for (int k = 0; k<circuit.size()-3; k++ )
{
int nextcurve = circuit[k+3]->Curve;
int currentcurve = circuit[k]->Curve;
int nextslope = circuit[k+3]->Slope;
int currentslope = circuit[k]->Slope;
if (nextcurve==currentcurve && nextslope==currentslope)
{
// no turn and no hill
}
else if (nextcurve==currentcurve && nextslope!=currentslope)
{
// no turn but hill
if (nextslope>0) //uphill
{
circuit[k]->RDeco=UPHILL;
circuit[k]->LDeco=UPHILL;
}
else if (nextslope<0) //downhill
{
circuit[k]->RDeco=DOWNHILL;
circuit[k]->LDeco=DOWNHILL;
}
}
else if (nextcurve!=currentcurve && nextslope==currentslope)
{
// no turn but hill
if (nextcurve<0) //uphill
{
circuit[k]->RDeco=LEFTTURN;
circuit[k]->LDeco=LEFTTURN;
}
else if (nextcurve>0) //downhill
{
circuit[k]->RDeco=RIGHTTURN;
circuit[k]->LDeco=RIGHTTURN;
}
}
else if (nextcurve!=currentcurve && nextslope!=currentslope)
{
// no turn but hill
if (nextcurve<0) //uphill
{
circuit[k]->RDeco=LEFTTURN;
if (nextslope>0) circuit[k]->LDeco=UPHILL;
else if (nextslope<0) circuit[k]->LDeco=DOWNHILL;
}
else if (nextcurve>0) //downhill
{
circuit[k]->LDeco=RIGHTTURN;
if (nextslope>0) circuit[k]->RDeco=UPHILL;
else if (nextslope<0) circuit[k]->RDeco=DOWNHILL;
}
}
if (nextcurve<0 && currentcurve!=nextcurve) circuit[k]->RDeco=LEFTTURN;
if (nextcurve>0 && currentcurve!=nextcurve) circuit[k]->LDeco=RIGHTTURN;
}
}
void createClouds( void )
{
srand( rtc_ticks() );
for( int k = 0; k < NB_CLOUDS_SKY; k++)
{
int X = (rand() % 792);
int Y = rand() % 60;
int T = rand() % 3;
Clouds* cl=new Clouds( X, Y, T );
if (cl!=nullptr) nuages.push_back( cl );
}
}
void createTraffic( void )
{
srand( rtc_ticks() );
for( int k = 0; k < NB_CARS_TRAFFIC; k++)
{
int8_t X = rand() % 4;
//double Z = (double) (rand() % 4000);
//int8_t X = 0;
double Z = (k+1)*SEGMENT_LENGTH;
uint8_t S = 4 + (rand() % 2);
uint8_t T = rand() % 8;
Cars* car;
// Depending on which line the car is placed, we choose the right fraction of W
if (X==0) car = new Cars( -0.75, (double) Z, S, T );
else if (X==1) car = new Cars( -0.25, (double) Z, S, T );
else if (X==2) car = new Cars( 0.25, (double) Z, S, T );
else if (X==3) car = new Cars( 0.75, (double) Z, S, T );
if (car!=nullptr)
traffic.push_back( car );
}
}
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 addStartLine( 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, STARTLIGHT, STARTLIGHT );
if (seg!=nullptr)
{
seg->Environment = biome;
if (i==7) seg->Special = START;
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 addFinishLine( 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, STOPLIGHT, STOPLIGHT );
if (seg!=nullptr)
{
seg->Environment = biome;
if (i==7) seg->Special = FINISH;
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 )
{
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; i<l; i++)
{
//Segment *s=new Segment( i );
int deco = rand() % 4;
Segment *seg;
if (deco==0) seg=new Segment( 0, lastY, lastZ + i*SEGMENT_LENGTH, 0, 0, SMALLLEAF, -1 );
else if (deco==1) seg=new Segment( 0, lastY, lastZ + i*SEGMENT_LENGTH, 0, 0, -1, DEADTREE );
else if (deco==2) seg=new Segment( 0, lastY, lastZ + i*SEGMENT_LENGTH, 0, 0, PALMTREE, -1 );
else if (deco==3) seg=new Segment( 0, lastY, lastZ + i*SEGMENT_LENGTH, 0, 0, CACTUS, BIGLEAF );
if (seg!=nullptr)
{
seg->Environment = 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; i<l; i++)
{
//Segment *s=new Segment( i );
int deco = rand() % 4;
Segment *seg;
if (deco==0) seg=new Segment( 0, lastY, lastZ+i*SEGMENT_LENGTH, s*t, 0, -1, -1 );
else if (deco==1) seg=new Segment( 0, lastY, lastZ+i*SEGMENT_LENGTH, s*t, 0, -1, OAKTREE );
else if (deco==2) seg=new Segment( 0, lastY, lastZ+i*SEGMENT_LENGTH, s*t, 0, DEADTREE, -1 );
else if (deco==3) seg=new Segment( 0, lastY, lastZ+i*SEGMENT_LENGTH, s*t, 0, DEADTREE, OAKTREE );
if (seg!=nullptr)
{
seg->Environment = 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; i<l; i++)
{
//Segment *s=new Segment( i );
int deco = rand() % 4;
Segment *seg;
if (deco==0) seg=new Segment( 0, lastY+i*t*s, lastZ+i*SEGMENT_LENGTH, 0, s*t, -1, -1 );
else if (deco==1) seg=new Segment( 0, lastY+i*t*s, lastZ+i*SEGMENT_LENGTH, 0, s*t, -1, PALMTREE );
else if (deco==2) seg=new Segment( 0, lastY+i*t*s, lastZ+i*SEGMENT_LENGTH, 0, s*t, OAKTREE, -1 );
else if (deco==3) seg=new Segment( 0, lastY+i*t*s, lastZ+i*SEGMENT_LENGTH, 0, s*t, OAKTREE, PALMTREE );
if (seg!=nullptr)
{
seg->Environment = biome;
circuit.push_back( seg );
}
}
}
void addCurvyHill( Length l, HillSize s, HillType t, CurveStrength cs, CurveType ct, 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; i<l; i++)
{
//Segment *s=new Segment( i );
int deco = rand() % 4;
Segment *seg;
if (deco==0) seg=new Segment( 0, lastY+i*t*s, lastZ+i*SEGMENT_LENGTH, cs*ct, s*t, -1, -1 );
else if (deco==1) seg=new Segment( 0, lastY+i*t*s, lastZ+i*SEGMENT_LENGTH, cs*ct, s*t, -1, PALMTREE );
else if (deco==2) seg=new Segment( 0, lastY+i*t*s, lastZ+i*SEGMENT_LENGTH, cs*ct, s*t, OAKTREE, -1 );
else if (deco==3) seg=new Segment( 0, lastY+i*t*s, lastZ+i*SEGMENT_LENGTH, cs*ct, s*t, OAKTREE, PALMTREE );
if (seg!=nullptr)
{
seg->Environment = biome;
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==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, C_RED );
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 );
return;
}
*/
if (circuit[index]->Environment == PLAINS)
{
if (index%2==0)
{
//drawGrass( Y2, Y1, DARK_GREEN_GRASS );
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, 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 );
}
}
}
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;
}
uint16_t findIndex( double currentZ )
{
return (uint16_t) (currentZ / SEGMENT_LENGTH);
}
void prepareDecoration( void )
{
bopti_image_t const *src;
for( int k=0; k<NB_TREES_TYPES; k++)
{
float scale=1.0f;
for( int i=0; i<MAX_SUBIMAGES_TREES; i++)
{
scale=3.0f/((float) (i+2));
if(k==0) src = &tree1;
else if (k==1) src = &tree2;
else if (k==2) src = &tree3;
else if (k==3) src = &tree4;
else if (k==4) src = &tree5;
else if (k==5) src = &tree6;
else if (k==6) src = &leftturn;
else if (k==7) src = &rightturn;
else if (k==8) src = &uphill;
else if (k==9) src = &downhill;
else if (k==10) src = &checkpoint;
else if (k==11) src = &startlights;
else if (k==12) src = &stoplights;
else if (k==13) src = &waitlights;
int width = (int) ((float) src->width * scale);
int height = (int) ((float) src->height * scale);
scaledTrees[k][i] = resize(src, width, height);
//scale*=0.82;
}
}
}
void prepareTraffic( void )
{
bopti_image_t const *src;
for( int k=0; k<NB_CARS_TYPES; k++)
{
float scale=1.0f;
for( int i=0; i<MAX_SUBIMAGES_CARS; i++)
{
//scale=1.0f/((float) (i+1));
if(k==0) src = &car1;
else if(k==1) src = &car2;
else if(k==2) src = &car3;
else if(k==3) src = &car4;
else if(k==4) src = &car5;
else if(k==5) src = &car6;
else if(k==6) src = &car7;
else src = &car8;
int width = (int) ((float) src->width * scale);
int height = (int) ((float) src->height * scale);
scaledCars[k][i] = resize(src, width, height);
scale*=0.82;
}
}
}
void freeDecoration( void )
{
for( int k=0; k<NB_TREES_TYPES; k++)
for( int i=0; i<MAX_SUBIMAGES_TREES; i++)
free(scaledTrees[k][i]);
}
void freeTraffic( void )
{
for( int k=0; k<NB_CARS_TYPES; k++)
for( int i=0; i<MAX_SUBIMAGES_CARS; i++)
free(scaledCars[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>(MAX_SUBIMAGES_TREES-1)) distance = (MAX_SUBIMAGES_TREES-1);
//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 updateTraffic( float dt, uint32_t maxdistance )
{
for(int k=0; k<traffic.size(); k++)
{
traffic[k]->wZ += traffic[k]->Speed*dt;
if (traffic[k]->wZ>maxdistance) traffic[k]->wZ-=maxdistance;
}
}
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; k<nuages.size(); k++ )
{
if (nuages[k]->Type==0) cloud=&sky1;
else if (nuages[k]->Type==1) cloud=&sky2;
else cloud=&sky3;
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(X<SCREEN_WIDTH+DX);
}
void drawNearBackground( int offset )
{
int X = offset;
int DX = treeline.width;
while (X>0)
{
X-=DX;
}
do
{
if (X>-1*DX) dimage(X, 90, &treeline);
X+=DX;
}
while(X<SCREEN_WIDTH+DX);
}