#include "parameters.h" #include "level.h" #include "player.h" #include #include #include #include "utilities.h" #include #include #include "player.h" #define TILESIZE 16 extern struct Map map_level0; extern struct Map map_level1; extern struct Map map_level2; extern struct Map map_level3; extern struct Map map_level4; extern struct Map map_level5; extern bool drawbackground; extern bool drawforeground; extern bool drawnormals; extern bool drawborders; extern bool textbacktile; extern bool textforetile; extern uint16_t tilecolor; extern std::vector MyLevelBorders; extern Player MyPlayer; struct Map *map_level; int tileXmin, tileXmax; int tileYmin, tileYmax; int XinTile, YinTile; extern bopti_image_t img_selected; Level::Level( ) { map_level = &map_level0; this->UpdateDataMap( ); } Level::~Level( ) { } void Level::ChangeMap( int level ) { if(level==0) map_level = &map_level0; else if(level==1) map_level = &map_level1; else if(level==2) map_level = &map_level2; else if(level==3) map_level = &map_level3; else if(level==4) map_level = &map_level4; else if(level==5) map_level = &map_level5; else map_level = &map_level0; this->UpdateDataMap( ); } void Level::UpdateDataMap( void ) { for(int i=0; iw; i++) { for(int j=0; jh; j++) { uint16_t index = j * map_level->w + i; uint16_t currentTile = map_level->layers[1][ index ]; if (currentTile==31) { MyPlayer.currx = ((float) (i + 0.5f))*16.0f; MyPlayer.curry = ((float) (j + 0.5f))*16.0f; MyPlayer.vx = 0.0f; MyPlayer.vy = 0.0f; MyPlayer.Update( 0.0f ); } } } } void Level::Render( void ) { for(int u=!drawbackground; unblayers-!drawforeground;u++) { for(int i=0; iw; i++) { for(int j=0; jh; j++) { uint16_t index = j * map_level->w + i; int16_t currentTile = map_level->layers[u][ index ]; if (currentTile!=-1) { uint16_t xtile = (currentTile % map_level->tileset_size) * 16; uint16_t ytile = (currentTile / map_level->tileset_size) * 16; if (u==0) azrp_subimage_rgb16_dye( i*16, j*16, map_level->tileset, xtile, ytile, 16, 16, IMAGE_DYE | IMAGE_NOCLIP_INPUT, tilecolor ); else azrp_subimage_rgb16( i*16, j*16, map_level->tileset, xtile, ytile, 16, 16, DIMAGE_NONE | IMAGE_NOCLIP_INPUT ); #if(DEBUG_MODE) if (textbacktile) azrp_draw_text( i*16, j*16, "%d", GetTileBackgroundINT( i, j ) ); if (textforetile) azrp_draw_text( i*16+8, j*16+8, "%d", GetTileForegroundINT( i, j ) ); #endif } } } } #if(DEBUG_MODE) if (drawborders) for( unsigned int i=0; iA.x, (int) MyLevelBorders[i]->A.y, (int) MyLevelBorders[i]->B.x, (int) MyLevelBorders[i]->B.y, MyLevelBorders[i]->color ); if (drawnormals) for( unsigned int i=0; iA.x+(int) MyLevelBorders[i]->B.x)/2, ((int) MyLevelBorders[i]->A.y+(int) MyLevelBorders[i]->B.y)/2, ((int) MyLevelBorders[i]->A.x+(int) MyLevelBorders[i]->B.x)/2 + (int) MyLevelBorders[i]->N.x/2, ((int) MyLevelBorders[i]->A.y+(int) MyLevelBorders[i]->B.y)/2 + (int) MyLevelBorders[i]->N.y/2, C_BLUE ); #endif } void Level::RenderSelected( uint8_t i, uint8_t j ) { } void Level::Update( float dt ) { UpdateBorders( ); } /*RETURN the type of tile located in the background for the point x, y using player coordinates (x=[0..25], y=[0..14]) */ /*the x and y correspond to hte integer part of MyPlayer.x and MyPlayer.y*/ int Level::GetTileBackgroundINT( uint8_t x, uint8_t y ) { uint16_t index = y * map_level->w + x; uint16_t currentTile = map_level->layers[0][ index ]; return currentTile; } /*RETURN the type of tile located in the foreground for the point x, y using player coordinates (x=[0..25], y=[0..14]) */ /*the x and y correspond to hte integer part of MyPlayer.x and MyPlayer.y*/ int Level::GetTileForegroundINT( uint8_t x, uint8_t y ) { uint16_t index = y * map_level->w + x; uint16_t currentTile = map_level->layers[1][ index ]; return currentTile; } /*RETURN the type of tile located in the background for the point x, y using screen coordinates (x=[0..396], y=[0..223]) */ int Level::GetTileBackground( uint16_t x, uint16_t y ) { uint8_t tileX = x >> 4; uint8_t tileY = y >> 4; uint16_t index = tileY * map_level->w + tileX; uint16_t currentTile = map_level->layers[0][ index ]; return currentTile; } /*RETURN the type of tile located in the foreground for the point x, y using screen coordinates (x=[0..396], y=[0..223]) */ int Level::GetTileForeground( uint16_t x, uint16_t y ) { uint8_t tileX = x >> 4; uint8_t tileY = y >> 4 ; uint16_t index = tileY * map_level->w + tileX; uint16_t currentTile = map_level->layers[1][ index ]; return currentTile; } bool CollisionSegSeg( Point2D A, Point2D B, Point2D C, Point2D D, Point2D *R ) { Vector2D I, J; I.x = B.x - A.x; I.y = B.y - A.y; if (I.x==0 && I.y==0) return false; J.x = D.x - C.x; J.y = D.y - C.y; if (J.x==0 && J.y==0) return false; libnum::num32 det; det = I.x*J.y-I.y*J.x; if (det==0) return false; // the segments are parallel libnum::num32 m; m = (I.x*A.y - I.x*C.y - I.y*A.x + I.y*C.x) / det; libnum::num32 k; k = (J.x*A.y - J.x*C.y - J.y*A.x + J.y*C.x) / det; if ((mlibnum::num32(1) || klibnum::num32(1))) return false; // intersection of the lines, but not of the segments (*R).x = C.x + k*J.x; (*R).y = C.y + k*J.y; return true; } /*RETURN true if the player can go in the target position*/ bool Level::CanGo( void ) { Point2D PlayerOrigin, PlayerTarget; PlayerOrigin.x = MyPlayer.currx; PlayerOrigin.y = MyPlayer.curry; PlayerTarget.x = MyPlayer.nextx; PlayerTarget.y = MyPlayer.nexty; if (PlayerTarget.x == PlayerOrigin.x && PlayerTarget.y == PlayerOrigin.y) return true; // velocity is 0 so Player.next = Player.Curr so we can stay here, that's obvious if (MyLevelBorders.size() == 0) return true; // there is no surrounding border so no need to check if there are collisions (also obvious) for (unsigned int i=0; iA.x; A.y = MyLevelBorders[i]->A.y; B.x = MyLevelBorders[i]->B.x; B.y = MyLevelBorders[i]->B.y; // Detection de collision entre [A,B] et [Player.Curr, Player.Next] if (CollisionSegSeg( A, B, PlayerOrigin, PlayerTarget, &I )) { MyLevelBorders[i]->color = C_RED; MyPlayer.nextx = I.x; MyPlayer.nexty = I.y; MyPlayer.vx = libnum::num32(0); MyPlayer.vy = libnum::num32(0); return false; } } return true; } Border* Level::MakeBorder( libnum::num DX, libnum::num DY, float x1, float y1, float x2, float y2 ) { Border *Bord = new Border(); Bord->A.x = DX + libnum::num(x1*15.0); Bord->A.y = DY + libnum::num(y1*15.0); Bord->B.x = DX + libnum::num(x2*15.0); Bord->B.y = DY + libnum::num(y2*15.0); Bord->N.x = Bord->A.y - Bord->B.y; Bord->N.y = Bord->B.x - Bord->A.x; Bord->color = C_GREEN; return Bord; } void Level::ConvertTileToBorder( int16_t currentTile, libnum::num DeltaX, libnum::num DeltaY ) { Border *B1; switch(currentTile) { case -1: break; // Empty background case 0: break; // No borders (filling tile) case 1: B1 = MakeBorder( DeltaX, DeltaY, 0.0,0.0, 0.0,1.0 ); MyLevelBorders.push_back(B1); B1 = MakeBorder( DeltaX, DeltaY, 0.0,1.0, 1.0,1.0 ); MyLevelBorders.push_back(B1); B1 = MakeBorder( DeltaX, DeltaY, 1.0,1.0, 1.0,0.0 ); MyLevelBorders.push_back(B1); B1 = MakeBorder( DeltaX, DeltaY, 1.0,0.0, 0.0,0.0 ); MyLevelBorders.push_back(B1); break; //45° diagonals case 2: B1 = MakeBorder( DeltaX, DeltaY, 0.0,1.0, 1.0,0.0 ); MyLevelBorders.push_back(B1); break; case 3: B1 = MakeBorder( DeltaX, DeltaY, 0.0,0.0, 1.0,1.0 ); MyLevelBorders.push_back(B1); break; case 12: B1 = MakeBorder( DeltaX, DeltaY, 1.0,1.0, 0.0,0.0 ); MyLevelBorders.push_back(B1); break; case 13: B1 = MakeBorder( DeltaX, DeltaY, 1.0,0.0, 0.0,1.0 ); MyLevelBorders.push_back(B1); break; //22.5° diagonals case 4: B1 = MakeBorder( DeltaX, DeltaY, 0.0,1.0, 1.0,0.5 ); MyLevelBorders.push_back(B1); break; case 5: B1 = MakeBorder( DeltaX, DeltaY, 0.0,0.5, 1.0,0.0 ); MyLevelBorders.push_back(B1); break; case 6: B1 = MakeBorder( DeltaX, DeltaY, 0.0,0.0, 1.0,0.5 ); MyLevelBorders.push_back(B1); break; case 7: B1 = MakeBorder( DeltaX, DeltaY, 0.0,0.5, 1.0,1.0 ); MyLevelBorders.push_back(B1); break; case 14: B1 = MakeBorder( DeltaX, DeltaY, 1.0,0.5, 0.0,0.0 ); MyLevelBorders.push_back(B1); break; case 15: B1 = MakeBorder( DeltaX, DeltaY, 1.0,1.0, 0.0,0.5 ); MyLevelBorders.push_back(B1); break; case 16: B1 = MakeBorder( DeltaX, DeltaY, 1.0,0.5, 0.0,1.0 ); MyLevelBorders.push_back(B1); break; case 17: B1 = MakeBorder( DeltaX, DeltaY, 1.0,0.0, 0.0,0.5 ); MyLevelBorders.push_back(B1); break; // 67.5° Diagonals case 24: B1 = MakeBorder( DeltaX, DeltaY, 0.5,1.0, 1.0,0.0 ); MyLevelBorders.push_back(B1); break; case 34: B1 = MakeBorder( DeltaX, DeltaY, 0.0,1.0, 0.5,0.0 ); MyLevelBorders.push_back(B1); break; case 25: B1 = MakeBorder( DeltaX, DeltaY, 0.0,0.0, 0.5,1.0 ); MyLevelBorders.push_back(B1); break; case 35: B1 = MakeBorder( DeltaX, DeltaY, 0.5,0.0, 1.0,1.0 ); MyLevelBorders.push_back(B1); break; case 26: B1 = MakeBorder( DeltaX, DeltaY, 0.5,1.0, 0.0,0.0 ); MyLevelBorders.push_back(B1); break; case 36: B1 = MakeBorder( DeltaX, DeltaY, 1.0,1.0, 0.5,0.0 ); MyLevelBorders.push_back(B1); break; case 27: B1 = MakeBorder( DeltaX, DeltaY, 1.0,0.0, 0.5,1.0 ); MyLevelBorders.push_back(B1); break; case 37: B1 = MakeBorder( DeltaX, DeltaY, 0.5,0.0, 0.0,1.0 ); MyLevelBorders.push_back(B1); break; // Blocks with 3 sides case 8: B1 = MakeBorder( DeltaX, DeltaY, 0.0,1.0, 1.0,1.0 ); MyLevelBorders.push_back(B1); B1 = MakeBorder( DeltaX, DeltaY, 1.0,1.0, 1.0,0.0 ); MyLevelBorders.push_back(B1); B1 = MakeBorder( DeltaX, DeltaY, 1.0,0.0, 0.0,0.0 ); MyLevelBorders.push_back(B1); break; case 9: B1 = MakeBorder( DeltaX, DeltaY, 0.0,0.0, 0.0,1.0 ); MyLevelBorders.push_back(B1); B1 = MakeBorder( DeltaX, DeltaY, 1.0,1.0, 1.0,0.0 ); MyLevelBorders.push_back(B1); B1 = MakeBorder( DeltaX, DeltaY, 1.0,0.0, 0.0,0.0 ); MyLevelBorders.push_back(B1); break; case 18: B1 = MakeBorder( DeltaX, DeltaY, 0.0,0.0, 0.0,1.0 ); MyLevelBorders.push_back(B1); B1 = MakeBorder( DeltaX, DeltaY, 0.0,1.0, 1.0,1.0 ); MyLevelBorders.push_back(B1); B1 = MakeBorder( DeltaX, DeltaY, 1.0,1.0, 1.0,0.0 ); MyLevelBorders.push_back(B1); break; case 19: B1 = MakeBorder( DeltaX, DeltaY, 0.0,0.0, 0.0,1.0 ); MyLevelBorders.push_back(B1); B1 = MakeBorder( DeltaX, DeltaY, 0.0,1.0, 1.0,1.0 ); MyLevelBorders.push_back(B1); B1 = MakeBorder( DeltaX, DeltaY, 1.0,0.0, 0.0,0.0 ); MyLevelBorders.push_back(B1); break; // Blocks with 2 sides case 28: B1 = MakeBorder( DeltaX, DeltaY, 0.0,1.0, 1.0,1.0 ); MyLevelBorders.push_back(B1); B1 = MakeBorder( DeltaX, DeltaY, 1.0,0.0, 0.0,0.0 ); MyLevelBorders.push_back(B1); break; case 29: B1 = MakeBorder( DeltaX, DeltaY, 0.0,0.0, 0.0,1.0 ); MyLevelBorders.push_back(B1); B1 = MakeBorder( DeltaX, DeltaY, 1.0,1.0, 1.0,0.0 ); MyLevelBorders.push_back(B1); break; case 38: B1 = MakeBorder( DeltaX, DeltaY, 0.0,0.0, 0.0,1.0 ); MyLevelBorders.push_back(B1); B1 = MakeBorder( DeltaX, DeltaY, 1.0,0.0, 0.0,0.0 ); MyLevelBorders.push_back(B1); break; case 39: B1 = MakeBorder( DeltaX, DeltaY, 1.0,1.0, 1.0,0.0 ); MyLevelBorders.push_back(B1); B1 = MakeBorder( DeltaX, DeltaY, 1.0,0.0, 0.0,0.0 ); MyLevelBorders.push_back(B1); break; case 48: B1 = MakeBorder( DeltaX, DeltaY, 0.0,0.0, 0.0,1.0 ); MyLevelBorders.push_back(B1); B1 = MakeBorder( DeltaX, DeltaY, 0.0,1.0, 1.0,1.0 ); MyLevelBorders.push_back(B1); break; case 49: B1 = MakeBorder( DeltaX, DeltaY, 0.0,1.0, 1.0,1.0 ); MyLevelBorders.push_back(B1); B1 = MakeBorder( DeltaX, DeltaY, 1.0,1.0, 1.0,0.0 ); MyLevelBorders.push_back(B1); break; // Blocks with one single side case 10: case 44: B1 = MakeBorder( DeltaX, DeltaY, 1.0,0.0, 0.0,0.0 ); MyLevelBorders.push_back(B1); break; case 11: case 46: B1 = MakeBorder( DeltaX, DeltaY, 0.0,1.0, 1.0,1.0 ); MyLevelBorders.push_back(B1); break; case 20: case 47: B1 = MakeBorder( DeltaX, DeltaY, 0.0,0.0, 0.0,1.0 ); MyLevelBorders.push_back(B1); break; case 21: case 45: B1 = MakeBorder( DeltaX, DeltaY, 1.0,1.0, 1.0,0.0 ); MyLevelBorders.push_back(B1); break; default: break; } } void Level::UpdateBorders( void ) { for(unsigned int i=0; iw-1 ); uint16_t ymin = max( yp - 1, 0 ); uint16_t ymax = min( yp + 1, map_level->h-1 ); // for( int i=10; iw; i++) for( int i=xmin; i<=xmax; i++) { //for( int j=10; jh; j++) for( int j=ymin; j<=ymax; j++) { uint16_t index = j * map_level->w + i; int16_t currentTile = map_level->layers[0][ index ]; libnum::num DeltaX = libnum::num( i*16 ); libnum::num DeltaY = libnum::num( j*16 ); ConvertTileToBorder( currentTile, DeltaX, DeltaY ); } } }