need to identify bug in the line vs triangle/rectangle collision routines

This commit is contained in:
Sylvain PILLOT 2023-09-04 22:25:25 +02:00
parent c9f5807205
commit 642c2e9877
5 changed files with 96 additions and 72 deletions

View File

@ -246,7 +246,9 @@ static void update( float dt )
if(MyBoss->Test_Impact(MyPlayer->Lasers[u])==true)
{
//TODO : we can create a list of impacts here, to be rendered later on
Create_Impact( (int) MyBoss->x, (int) MyBoss->y );
//Create_Impact( (int) MyBoss->x, (int) MyBoss->y );
}
}
}
@ -332,18 +334,18 @@ static void render( void )
}
#if(BIAS)
if (texttodraw>=1) Azur_draw_text_shmup(1,01, "FPS = %.0f", (float) (1000000.0f / elapsedTime) );
//if (texttodraw>=1) Azur_draw_text(1,11, "Part.= %d - Bull.= %d", MyParticles.size(), MyPlayerBullets.size() );
//if (texttodraw>=1 && !MyEnemies.empty()) Azur_draw_text(1,21, "Ennmy Life= %d", MyEnemies[0]->life );
if (texttodraw>=2) Azur_draw_text_shmup(1,30, "Update = %.3f ms", (float) time_update / 1000.0f );
if (texttodraw>=2) Azur_draw_text_shmup(1,45, "Render = %.3f ms", (float) time_render / 1000.0f );
if (texttodraw>=2) Azur_draw_text_shmup(1,60, ">Total = %.0f ms", (float) elapsedTime / 1000.0f );
if (texttodraw>=1) Azur_draw_text_shmup(0, 0, "FPS = %.0f", (float) (1000000.0f / elapsedTime) );
if (texttodraw>=1) Azur_draw_text_shmup(0, 15, "LAZ = %d", MyPlayer->Lasers.size() );
if (texttodraw>=1) Azur_draw_text_shmup(0, 30, "Part.= %d - Bull.= %d", MyParticles.size(), MyPlayerBullets.size() );
if (texttodraw>=2) Azur_draw_text_shmup(0,45, "Update = %.3f ms", (float) time_update / 1000.0f );
if (texttodraw>=2) Azur_draw_text_shmup(0,60, "Render = %.3f ms", (float) time_render / 1000.0f );
if (texttodraw>=2) Azur_draw_text_shmup(0,75, ">Total = %.0f ms", (float) elapsedTime / 1000.0f );
#if(MORE_RAM)
if (texttodraw>=3) Azur_draw_text_shmup(1,75, "Mem Used : %d", _uram_stats->used_memory + extram_stats->used_memory);
if (texttodraw>=3) Azur_draw_text_shmup(1,90, "Mem Free : %d", _uram_stats->free_memory + extram_stats->free_memory);
if (texttodraw>=3) Azur_draw_text_shmup(1,105, "Mem Peak Used : %d", _uram_stats->peak_used_memory + extram_stats->peak_used_memory );
if (texttodraw>=3) Azur_draw_text_shmup(0,90, "Mem Used : %d", _uram_stats->used_memory + extram_stats->used_memory);
if (texttodraw>=3) Azur_draw_text_shmup(0,105, "Mem Free : %d", _uram_stats->free_memory + extram_stats->free_memory);
if (texttodraw>=3) Azur_draw_text_shmup(0,120, "Mem Peak Used : %d", _uram_stats->peak_used_memory + extram_stats->peak_used_memory );
#endif
#endif

View File

@ -413,18 +413,19 @@ bool Boss::Test_Impact( Laser *projectile )
bool hit = false;
/* We check if the bullet collides with teh shield of the boss */
/* We check if the laser collides with the shield of the boss */
for( int i=0; i< NB_PIECES_BOSS; i++ )
{
if (Pieces[i*2].toberemoved == false)
{
Vector2D A((int) XdataBossExternal[ Pieces[i*2].P1 ], (int) YdataBossExternal[ Pieces[i*2].P1 ]);
Vector2D B((int) XdataBossExternal[ Pieces[i*2].P2 ], (int) YdataBossExternal[ Pieces[i*2].P2 ]);
Vector2D C((int) XdataBossInternal[ Pieces[i*2].P3 ], (int) YdataBossInternal[ Pieces[i*2].P3 ]);
Vector2D A( XdataBossExternal[ Pieces[i*2].P1 ], YdataBossExternal[ Pieces[i*2].P1 ]);
Vector2D B( XdataBossExternal[ Pieces[i*2].P2 ], YdataBossExternal[ Pieces[i*2].P2 ]);
Vector2D C( XdataBossInternal[ Pieces[i*2].P3 ], YdataBossInternal[ Pieces[i*2].P3 ]);
if (LineTriangle_Collision( Start, Direction, A, B, C))
{
Pieces[i*2].life -= projectile->strength;
Create_Impact(((int) (A.x + B.x + C.x))/3, ((int) (A.y + B.y + C.y))/3 );
if (Pieces[i*2].life<=0)
{
Pieces[i*2].toberemoved = true;
@ -437,13 +438,14 @@ bool Boss::Test_Impact( Laser *projectile )
if (Pieces[i*2+1].toberemoved == false)
{
Vector2D A((int) XdataBossInternal[ Pieces[i*2+1].P1 ], (int) YdataBossInternal[ Pieces[i*2+1].P1 ]);
Vector2D B((int) XdataBossInternal[ Pieces[i*2+1].P2 ], (int) YdataBossInternal[ Pieces[i*2+1].P2 ]);
Vector2D C((int) XdataBossExternal[ Pieces[i*2+1].P3 ], (int) YdataBossExternal[ Pieces[i*2+1].P3 ]);
Vector2D A( XdataBossInternal[ Pieces[i*2+1].P1 ], YdataBossInternal[ Pieces[i*2+1].P1 ]);
Vector2D B( XdataBossInternal[ Pieces[i*2+1].P2 ], YdataBossInternal[ Pieces[i*2+1].P2 ]);
Vector2D C( XdataBossExternal[ Pieces[i*2+1].P3 ], YdataBossExternal[ Pieces[i*2+1].P3 ]);
if (LineTriangle_Collision( Start, Direction, A, B, C))
{
Pieces[i*2+1].life -= projectile->strength;
Create_Impact(((int) (A.x + B.x + C.x))/3, ((int) (A.y + B.y + C.y))/3 );
if (Pieces[i*2+1].life<=0)
{
Pieces[i*2+1].toberemoved = true;
@ -454,17 +456,19 @@ bool Boss::Test_Impact( Laser *projectile )
}
}
/* We check if the bullet collides with the cannons of the boss */
/* We check if the laser collides with the cannons of the boss */
for( int i=0; i<NB_GUNS; i++ )
{
if (Guns[i].toberemoved == false)
{
Vector2D BoxMin((int) xGuns[i] - img_BossGun.width/2, (int) yGuns[i] - img_BossGun.height/2);
Vector2D BoxMax((int) xGuns[i] + img_BossGun.width/2, (int) yGuns[i] + img_BossGun.height/2);
Vector2D BoxMin( xGuns[i] - libnum::num(img_BossGun.width/2), yGuns[i] - libnum::num(img_BossGun.height/2) );
Vector2D BoxMax( xGuns[i] + libnum::num(img_BossGun.width/2), yGuns[i] + libnum::num(img_BossGun.height/2) );
if (LineRectangle_Collision( Start, Direction, BoxMin, BoxMax ))
{
Guns[i].life -= projectile->strength;
Create_Impact( (int) xGuns[i], (int) yGuns[i] );
if (Guns[i].life<0)
{
Guns[i].toberemoved = true;
@ -474,18 +478,20 @@ bool Boss::Test_Impact( Laser *projectile )
}
}
}
/* We check if the bullet collides with the main ship part of the boss */
Vector2D BoxMin(xmin, ymin);
Vector2D BoxMax(xmax, ymax);
/* We check if the laser collides with the main ship part of the boss */
Vector2D BoxMin( libnum::num(this->xmin), libnum::num(this->ymin) );
Vector2D BoxMax( libnum::num(this->xmax), libnum::num(this->ymax) );
if (LineRectangle_Collision( Start, Direction, BoxMin, BoxMax ))
{
life -= projectile->strength;
Create_Impact( (int) x, (int) y );
if (life<0)
{
this->toberemoved = true;
Create_Explosion( (int) x, (int) y );
Create_Explosion( (int) this->x, (int) this->y );
}
hit = true;
}

View File

@ -32,9 +32,9 @@ void Laser::Update( float dt )
void Laser::Render( void )
{
// TODO this is juste for quick implementation : a thick Line Shader will be needed to be able to plot lasers in every directions
azrp_line((int) sx , (int) sy , (int) (sx+dx*400) , (int) (sy+dy*400) , C_WHITE );
azrp_line((int) sx-1, (int) sy-1, (int) (sx+dx*400)-1, (int) (sy+dy*400)-1, C_WHITE );
azrp_line((int) sx-2, (int) sy-2, (int) (sx+dx*400)-2, (int) (sy+dy*400)-2, RGB565_AZURBLUE );
azrp_line((int) sx+1, (int) sy+1, (int) (sx+dx*400)+1, (int) (sy+dy*400)+1, C_WHITE );
azrp_line((int) sx+2, (int) sy+2, (int) (sx+dx*400)+2, (int) (sy+dy*400)+2, RGB565_AZURBLUE );
azrp_line((int) sx , (int) sy , (int) (sx+dx*1000) , (int) (sy+dy*1000) , C_WHITE );
azrp_line((int) sx-1, (int) sy-1, (int) (sx+dx*1000)-1, (int) (sy+dy*1000)-1, RGB565_OCEANBLUE );
azrp_line((int) sx-2, (int) sy-2, (int) (sx+dx*1000)-2, (int) (sy+dy*1000)-2, RGB565_AZURBLUE );
azrp_line((int) sx+1, (int) sy+1, (int) (sx+dx*1000)+1, (int) (sy+dy*1000)+1, RGB565_OCEANBLUE );
azrp_line((int) sx+2, (int) sy+2, (int) (sx+dx*1000)+2, (int) (sy+dy*1000)+2, RGB565_AZURBLUE );
}

View File

@ -270,7 +270,16 @@ void Player::Activate_Laser( void )
isLaser = true;
Laser *mylaser1 = new Laser( (int) xmax, (int) y, 1, 0, LASER );
Lasers.push_back( mylaser1 );
/*
Laser *mylaser2 = new Laser( (int) xmax, (int) y, 0, -1, LASER );
Lasers.push_back( mylaser2 );
Laser *mylaser3 = new Laser( (int) xmax, (int) y, 0, 1, LASER );
Lasers.push_back( mylaser3 );
*/
}
}
void Player::Desactivate_Laser( void )

View File

@ -222,45 +222,33 @@ bool Pixel_Perfect_Collision( SpriteLocator image1, SpriteLocator image2 )
}
/* NEW IMPLEMENTATION - TO TEST */
/* COHEN-SUTHERLAND Line/Rectangle intersection*/
typedef uint8_t OutCode;
const uint8_t INSIDE = 0; // 0000
const uint8_t LEFT = 1; // 0001
const uint8_t RIGHT = 2; // 0010
const uint8_t BOTTOM = 4; // 0100
const uint8_t TOP = 8; // 1000
OutCode ComputeOutCode( Vector2D Point, Vector2D Min, Vector2D Max )
bool get_line_intersection( Vector2D p0, Vector2D p1, Vector2D p2, Vector2D p3, Vector2D *pr)
{
OutCode code = INSIDE; // initialised as being inside of clip window
if (Point.x < Min.x) // to the left of clip window
code |= LEFT;
else if (Point.x > Max.x) // to the right of clip window
code |= RIGHT;
if (Point.y < Min.y) // below the clip window
code |= BOTTOM;
else if (Point.y > Max.y) // above the clip window
code |= TOP;
return code;
Vector2D s1, s2;
s1 = p1 - p0; s1 = p1 - p0;
s2 = p3 - p2; s2 = p3 - p2;
libnum::num s, t;
s = (-s1.y * (p0.x - p2.x) + s1.x * (p0.y - p2.y)) / (-s2.x * s1.y + s1.x * s2.y);
t = ( s2.x * (p0.y - p2.y) - s2.y * (p0.x - p2.x)) / (-s2.x * s1.y + s1.x * s2.y);
if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
{
// Collision detected
if (pr != NULL)
{
(*pr).x = p0.x + (t * s1.x);
(*pr).y = p0.y + (t * s1.y);
}
return true;
}
return false; // No collision
}
bool LineRectangle_Collision( Vector2D Start, Vector2D Direction, Vector2D Min, Vector2D Max )
{
Vector2D End = Start.Clone();
End.Add( Direction, libnum::num(1000));
OutCode outcode0 = ComputeOutCode( Start, Min, Max );
OutCode outcode1 = ComputeOutCode( End, Min, Max );
bool accept = false;
if (!(outcode0 | outcode1)) return true; // both point inside so it hits
else if (outcode0 & outcode1) return false; // both point on the same sides outoff the rectangle --> no hit possible
else return true; // cross at least on one segment
}
/* FIRST IMPLEMENTATION USING THE VECTOR2D.H CLASS */
/* O is the origin, dir is the direction of the half line, A and B are the locations of the segment ends*/
bool LineSegment_Collision( Vector2D O, Vector2D dir, Vector2D A, Vector2D B )
@ -268,7 +256,7 @@ bool LineSegment_Collision( Vector2D O, Vector2D dir, Vector2D A, Vector2D B )
Vector2D OA = A - O;
/* create the point P corresponding to the "end" of the infinite side of the hald line */
/* create the point P corresponding to the "end" of the infinite side of the half line */
/* line length chosen to 1000 units as is it bigger than the diagonal of the screen in pixels*/
Vector2D P = O.Clone();
P.Add(dir, libnum::num(1000));
@ -291,12 +279,31 @@ bool LineSegment_Collision( Vector2D O, Vector2D dir, Vector2D A, Vector2D B )
}
bool LineRectangle_Collision( Vector2D Start, Vector2D Direction, Vector2D Min, Vector2D Max )
{
Vector2D End = Start.Clone();
End.Add( Direction, libnum::num(1000));
Vector2D P1(Min.x, Min.y);
Vector2D P2(Max.x, Min.y);
Vector2D P3(Max.x, Max.y);
Vector2D P4(Min.x, Max.y);
return( get_line_intersection(Start, End, P1, P2, NULL)
|| get_line_intersection(Start, End, P2, P3, NULL)
|| get_line_intersection(Start, End, P3, P4, NULL)
|| get_line_intersection(Start, End, P4, P1, NULL));
}
bool LineTriangle_Collision( Vector2D Start, Vector2D Direction, Vector2D A, Vector2D B, Vector2D C )
{
if ( LineSegment_Collision( Start, Direction, A, B)
|| LineSegment_Collision( Start, Direction, A, C)
|| LineSegment_Collision( Start, Direction, B, C))
return true;
return false;
Vector2D End = Start.Clone();
End.Add( Direction, libnum::num(1000));
return( get_line_intersection(Start, End, A, B, NULL)
|| get_line_intersection(Start, End, B, C, NULL)
|| get_line_intersection(Start, End, C, A, NULL));
}