2017-12-26 23:24:29 +01:00
# include <stdio.h>
# include <stdlib.h>
# include <time.h>
# include <stdbool.h>
# include <math.h>
# include <SDL2/SDL.h>
# include <SDL2/SDL_image.h>
# include <SDL2/SDL_ttf.h>
# ifndef __nullptr__
# define Nullptr(type) (type *)0
# endif // __nullptr__
# include "vector.h"
# include "asteroids.h"
// Properties
const double BULLET_Speed_Ally = 12.0f ;
const double BULLET_Speed_Enemy = 6.0f ;
const int BULLET_DecayTime_Ally = 60 ;
const int BULLET_DecayTime_Enemy = 100 ;
const double SHIP_RotationValue = 4.0f ;
const int SHIP_DeathAnimSpeed = 6 ;
const int SHIP_DeathAnimFrameCount = 5 ;
const double SHIP_MaxSpeed = 8.0f ;
const double SHIP_Acceleration = 0.15f ;
const double SHIP_ShootIntevale = 12 ; // Based on frame count
const double ASTEROID_MinimumSize = 50.0f ; // No asteroid under this size if split
// const int ENEMY_DeathAnimSpeed = 6;
// const int ENEMY_DeathAnimFrameCount = 5;
const double ENEMY_MaxSpeed = 5.0f ;
const int ENEMY_MaxTurnIntervale = 300 ;
const double ENEMY_Acceleration = 0.15f ;
const double ENEMY_ShootIntevale = 120 ; // Based on frame count
const SDL_Scancode SHIP_LeftButton = SDL_SCANCODE_A ;
const SDL_Scancode SHIP_RightButton = SDL_SCANCODE_D ;
const SDL_Scancode SHIP_ForwardButton = SDL_SCANCODE_W ;
const SDL_Scancode SHIP_ShootButton = SDL_SCANCODE_SPACE ;
// End Properties
// Vars
Bullet NULLET ;
2017-12-27 21:08:37 +01:00
int Asteroids_BoxWidth , Asteroids_BoxHeight , SHIP_MaxBulletCount , ENEMY_MaxBulletCount ; // TODO: Explosion Texture
2017-12-26 23:24:29 +01:00
SDL_Rect SHIP_SourceRect_Gliding , SHIP_SourceRect_Accelerating , * SHIP_SourceRect_Explosion , * ASTEROID_SourceRect_Size1 , * ASTEROID_SourceRect_Size2 , * ASTEROID_SourceRect_Size3 ;
SDL_Texture * SHIP_Texture_Gliding , * SHIP_Texture_Accelerating , * SHIP_Texture_Explosion , * ASTEROID_Texture , * BULLET_Texture_Ally , * BULLET_Texture_Enemy , * ENEMY_Texture ;
SDL_Point SHIP_RotationCenter_Flight , SHIP_RotationCenter_Explosion ;
Asteroid ASTEROIDULLET ;
bool ASTEROID_IsDestroyed = false ;
// End Vars
void BULLET_Initialize ( SDL_Renderer * renderer , int width , int height ) {
printf ( " Initializing Bullet... \n " ) ;
NULLET = ( Bullet ) {
. Rotation = 0.0f ,
. Location = ( Vector ) { . x = 0.0f , . y = 0.0f } ,
. Momentum = ( Vector ) { . x = 0.0f , . y = 0.0f } ,
. TargetRect = ( SDL_Rect ) { . x = 0 , . y = 0 , . w = 0 , . h = 0 } ,
. Lifetime = 0 ,
. IsDestroyed = true ,
. Type = AllyBullet
} ; // Default or null bullet
2017-12-27 21:08:37 +01:00
Asteroids_BoxWidth = width ;
Asteroids_BoxHeight = height ;
2017-12-27 00:29:20 +01:00
BULLET_Texture_Ally = IMG_LoadTexture ( renderer , " assets/images/bullet.png " ) ;
2017-12-26 23:24:29 +01:00
if ( ! BULLET_Texture_Ally ) printf ( " Ally bullet texture cannot be loaded! \n " ) ;
2017-12-27 00:29:20 +01:00
BULLET_Texture_Enemy = IMG_LoadTexture ( renderer , " assets/images/enemyBullet.png " ) ;
2017-12-26 23:24:29 +01:00
if ( ! BULLET_Texture_Enemy ) printf ( " Enemy bullet texture cannot be loaded! \n " ) ;
printf ( " Bullet initialized! \n " ) ;
}
void BULLET_Deinitialize ( ) {
printf ( " De-initializing Bullet... \n " ) ;
printf ( " De-initializing ally bullet texture... \n " ) ;
SDL_DestroyTexture ( BULLET_Texture_Ally ) ;
printf ( " De-initializing enemy bullet texture... \n " ) ;
SDL_DestroyTexture ( BULLET_Texture_Enemy ) ;
printf ( " De-initializing Bullet finished! \n " ) ;
}
Bullet BULLET_Fire ( Vector location , double direction , BulletType type ) {
return ( Bullet ) {
. Rotation = direction ,
. Location = location ,
. Momentum = getScaledDirectionalUnitVector ( direction , ( type = = AllyBullet ? BULLET_Speed_Ally : BULLET_Speed_Enemy ) ) ,
. TargetRect = ( type = = AllyBullet ? ( SDL_Rect ) { . x = 0 , . y = 0 , . w = 12 , . h = 35 } : ( SDL_Rect ) { . x = 0 , . y = 0 , . w = 30 , . h = 30 } ) ,
. Lifetime = ( type = = AllyBullet ? BULLET_DecayTime_Ally : BULLET_DecayTime_Enemy ) ,
. IsDestroyed = false ,
. Type = type
} ;
}
void BULLET_UpdateAlly ( Bullet * bul , Asteroid * asts , int * astCount , Enemy * enemies , int * enemyCount ) {
if ( ! ( bul - > IsDestroyed ) ) {
if ( ( bul - > Lifetime ) - - < = 0 ) { // Decay
( bul - > IsDestroyed ) = true ;
return ;
}
( bul - > Location ) = vectorAdd ( ( bul - > Location ) , ( bul - > Momentum ) ) ; // Move
2017-12-27 21:08:37 +01:00
if ( ( bul - > Location ) . x < 0.0f ) ( bul - > Location ) . x = Asteroids_BoxWidth ; // Check Boundaries
else if ( ( bul - > Location ) . x > Asteroids_BoxWidth ) ( bul - > Location ) . x = 0.0f ;
if ( ( bul - > Location ) . y < 0.0f ) ( bul - > Location ) . y = Asteroids_BoxHeight ;
else if ( ( bul - > Location ) . y > Asteroids_BoxHeight ) ( bul - > Location ) . y = 0.0f ;
2017-12-26 23:24:29 +01:00
( bul - > TargetRect ) . x = ( int ) round ( ( bul - > Location ) . x ) ; // Update render Target
( bul - > TargetRect ) . y = ( int ) round ( ( bul - > Location ) . y ) ;
int i ;
for ( i = 0 ; i < ( * astCount ) ; i + + ) { // Collide with Asteroids
if ( ! ( asts [ i ] . IsDestroyed ) ) {
if ( RECT_CircleCollide ( & ( asts [ i ] . TargetRect ) , & ( bul - > TargetRect ) ) ) {
printf ( " Bullet is destroyed by asteroid no. %d! \n " , i + 1 ) ;
ASTEROID_TryDestroy ( asts , astCount , i ) ;
if ( ( asts [ i ] . IsDestroyed ) ) printf ( " Bullet destroyed asteroid no. %d! \n " , i + 1 ) ;
( bul - > IsDestroyed ) = true ;
break ;
}
}
}
}
} // BULLET_Update
void BULLET_UpdateEnemy ( Bullet * bul , Ship * shp , int * shpCount ) {
if ( ! ( bul - > IsDestroyed ) ) {
if ( ( bul - > Lifetime ) - - < = 0 ) { // Decay
( bul - > IsDestroyed ) = true ;
return ;
}
2017-12-27 21:08:37 +01:00
// TODO: Export triple use of boundary check to method using pointers
2017-12-26 23:24:29 +01:00
( bul - > Location ) = vectorAdd ( ( bul - > Location ) , ( bul - > Momentum ) ) ; // Move
2017-12-27 21:08:37 +01:00
if ( ( bul - > Location ) . x < 0.0f ) ( bul - > Location ) . x = Asteroids_BoxWidth ; // Check Boundaries
else if ( ( bul - > Location ) . x > Asteroids_BoxWidth ) ( bul - > Location ) . x = 0.0f ;
if ( ( bul - > Location ) . y < 0.0f ) ( bul - > Location ) . y = Asteroids_BoxHeight ;
else if ( ( bul - > Location ) . y > Asteroids_BoxHeight ) ( bul - > Location ) . y = 0.0f ;
2017-12-26 23:24:29 +01:00
( bul - > TargetRect ) . x = ( int ) round ( ( bul - > Location ) . x ) ; // Update render Target
( bul - > TargetRect ) . y = ( int ) round ( ( bul - > Location ) . y ) ;
int i ;
for ( i = 0 ; i < ( * shpCount ) ; i + + ) { // Collide with Asteroids
if ( ! ( shp - > IsDead ) ) {
if ( RECT_CircleCollide ( & ( shp [ i ] . TargetRect_Gliding ) , & ( bul - > TargetRect ) ) ) {
printf ( " Player %d is destroyed by bullet! \n " , i + 1 ) ;
( bul - > IsDestroyed ) = true ;
( shp [ i ] . IsDead ) = true ;
break ;
}
}
}
}
} // BULLET_Update
void BULLET_Draw ( Bullet * bul , SDL_Renderer * renderer ) {
if ( ! ( bul - > IsDestroyed ) ) {
if ( ( bul - > Type ) = = AllyBullet ) {
SDL_RenderCopyEx ( renderer , BULLET_Texture_Ally , NULL , & ( bul - > TargetRect ) , ( bul - > Rotation ) , NULL , SDL_FLIP_NONE ) ;
} else {
SDL_RenderCopyEx ( renderer , BULLET_Texture_Enemy , NULL , & ( bul - > TargetRect ) , ( bul - > Rotation ) , NULL , SDL_FLIP_NONE ) ;
}
}
}
void ASTEROID_Initialize ( SDL_Renderer * renderer , int width , int height ) {
printf ( " Initializing Asteroid... \n " ) ;
2017-12-27 21:08:37 +01:00
Asteroids_BoxWidth = width ;
Asteroids_BoxHeight = height ;
2017-12-27 00:29:20 +01:00
ASTEROID_Texture = IMG_LoadTexture ( renderer , " assets/images/asteroid.png " ) ;
2017-12-26 23:24:29 +01:00
ASTEROIDULLET = ( Asteroid ) {
. Rotation = 0.0f ,
. Size = 0.0f ,
. RotationValue = 0.0f ,
. Location = ( Vector ) { . x = 0.0f , . y = 0.0f } ,
. Momentum = ( Vector ) { . x = 0.0f , . y = 0.0f } ,
. TargetRect = ( SDL_Rect ) { . x = 0 , . y = 0 , . w = 0 , . h = 0 } ,
. IsDestroyed = true ,
. Health = 0
} ;
if ( ! ASTEROID_Texture ) printf ( " Asteroid texture cannot be loaded! \n " ) ;
ASTEROID_SourceRect_Size1 = ( SDL_Rect * ) malloc ( 3 * sizeof ( SDL_Rect ) ) ;
ASTEROID_SourceRect_Size1 [ 0 ] = ( SDL_Rect ) { . x = 0 , . y = 0 , . w = 800 , . h = 800 } ;
ASTEROID_SourceRect_Size1 [ 1 ] = ( SDL_Rect ) { . x = 0 , . y = 800 , . w = 800 , . h = 800 } ;
ASTEROID_SourceRect_Size1 [ 2 ] = ( SDL_Rect ) { . x = 800 , . y = 0 , . w = 800 , . h = 800 } ;
ASTEROID_SourceRect_Size2 = ( SDL_Rect * ) malloc ( 3 * sizeof ( SDL_Rect ) ) ;
ASTEROID_SourceRect_Size2 [ 0 ] = ( SDL_Rect ) { . x = 800 , . y = 800 , . w = 400 , . h = 400 } ;
ASTEROID_SourceRect_Size2 [ 1 ] = ( SDL_Rect ) { . x = 800 , . y = 1200 , . w = 400 , . h = 400 } ;
ASTEROID_SourceRect_Size2 [ 2 ] = ( SDL_Rect ) { . x = 1200 , . y = 800 , . w = 400 , . h = 400 } ;
ASTEROID_SourceRect_Size3 = ( SDL_Rect * ) malloc ( 4 * sizeof ( SDL_Rect ) ) ;
ASTEROID_SourceRect_Size3 [ 0 ] = ( SDL_Rect ) { . x = 1200 , . y = 1200 , . w = 200 , . h = 200 } ;
ASTEROID_SourceRect_Size3 [ 1 ] = ( SDL_Rect ) { . x = 1200 , . y = 1400 , . w = 200 , . h = 200 } ;
ASTEROID_SourceRect_Size3 [ 2 ] = ( SDL_Rect ) { . x = 1400 , . y = 1200 , . w = 200 , . h = 200 } ;
ASTEROID_SourceRect_Size3 [ 3 ] = ( SDL_Rect ) { . x = 1400 , . y = 1400 , . w = 200 , . h = 200 } ;
printf ( " Asteroid initialized! \n " ) ;
} // ASTEROID_Initialize
Asteroid ASTEROID_CreateRandom ( ) {
return ( Asteroid ) {
. Rotation = ( double ) ( rand ( ) % 360 ) ,
. Size = 200 ,
. RotationValue = fmod ( ( double ) ( rand ( ) ) , 4.0f ) - 2.0f ,
2017-12-27 21:08:37 +01:00
// TODO: Reimplement random start pos here later
// .Location = (_vector) {.x = (double)(rand() % Asteroids_BoxWidth), .y = (double)(rand() % Asteroids_BoxHeight) },
2017-12-26 23:24:29 +01:00
. Location = ( Vector ) { . x = 0 , . y = 0 } ,
. Momentum = getScaledDirectionalUnitVector ( ( double ) ( rand ( ) % 360 ) , fmod ( ( double ) rand ( ) , 2.0f ) + 1.0f ) ,
. TargetRect = ( SDL_Rect ) { . x = 0 , . y = 0 , . w = 200 , . h = 200 } ,
. IsDestroyed = false ,
. SourceRect = ASTEROID_SourceRect_Size1 [ ( rand ( ) % 3 ) ] ,
. Health = 4
} ;
}
bool ASTEROID_TryDestroy ( Asteroid * asts , int * astCount , int index ) {
asts [ index ] . Health - - ;
if ( asts [ index ] . Health < = 0 ) {
if ( ASTEROID_CanSplit ( & ( asts [ index ] ) ) ) {
printf ( " Asteroid %d was split... \n " , index ) ;
asts [ ( * astCount ) + + ] = ASTEROID_CreateFromSplit ( & ( asts [ index ] ) ) ;
Asteroid tmp = ASTEROID_CreateFromSplit ( & ( asts [ index ] ) ) ;
asts [ index ] = tmp ;
} else {
printf ( " Asteroid %d was destroyed... \n " , index ) ;
asts [ index ] . IsDestroyed = true ;
}
return true ;
} else {
printf ( " Asteroid %d was hit... \n " , index ) ;
}
return false ;
}
Asteroid ASTEROID_CreateFromSplit ( Asteroid * creator ) {
Asteroid aster = ( Asteroid ) {
. Rotation = ( double ) ( rand ( ) % 360 ) ,
. Size = ( creator - > Size ) / 2.0f ,
. RotationValue = fmod ( ( double ) ( rand ( ) ) , 4.0f ) - 2.0f ,
. Location = creator - > Location ,
. Momentum = getScaledDirectionalUnitVector ( ( double ) ( rand ( ) % 360 ) , fmod ( ( double ) rand ( ) , 2.0f ) + 1.0f ) ,
. TargetRect = ( SDL_Rect ) { . x = 0 , . y = 0 , . w = ( int ) round ( ( creator - > Size ) / 2.0f ) , . h = ( int ) round ( ( creator - > Size ) / 2.0f ) } ,
. IsDestroyed = false ,
. SourceRect = ASTEROID_SourceRect_Size1 [ 0 ] ,
. Health = 0
} ;
aster . Health = ( int ) round ( aster . Size / 50.0f ) + ( ( rand ( ) % 2 ) ? ( 1 ) : ( - 1 ) ) ; // Bei 200 3 - 5 Hits
if ( aster . Health < = 1 ) aster . Health = 1 ;
if ( aster . Size > 150.0f ) aster . SourceRect = ASTEROID_SourceRect_Size1 [ ( rand ( ) % 3 ) ] ;
else if ( aster . Size > 75.0f ) aster . SourceRect = ASTEROID_SourceRect_Size2 [ ( rand ( ) % 3 ) ] ;
else aster . SourceRect = ASTEROID_SourceRect_Size3 [ ( rand ( ) % 4 ) ] ;
return aster ;
}
bool ASTEROID_CanSplit ( Asteroid * ast ) {
return ( ( ast - > Size ) > = ( 2 * ASTEROID_MinimumSize ) ) ;
}
bool RECT_CircleCollide ( SDL_Rect * rect1 , SDL_Rect * rect2 ) {
return ( distance ( rect1 , rect2 ) < round ( ( ( double ) ( rect1 - > w + rect2 - > w ) ) / 2.0f ) ) ;
}
double distance ( SDL_Rect * r1 , SDL_Rect * r2 ) {
double dx = ( ( ( double ) ( r2 - > x ) + ( ( double ) ( r2 - > w ) / 2.0f ) ) - ( ( double ) ( r1 - > x ) + ( ( double ) ( r1 - > w ) / 2.0f ) ) ) ;
double dy = ( ( ( double ) ( r2 - > y ) + ( ( double ) ( r2 - > h ) / 2.0f ) ) - ( ( double ) ( r1 - > y ) + ( ( double ) ( r1 - > h ) / 2.0f ) ) ) ;
return round ( sqrt ( ( dx * dx ) + ( dy * dy ) ) ) ;
}
void ASTEROID_Deinitialize ( ) {
printf ( " De-initializing Asteroid... \n " ) ;
printf ( " De-initializing Asteroid texture... \n " ) ;
SDL_DestroyTexture ( ASTEROID_Texture ) ;
free ( ASTEROID_SourceRect_Size1 ) ;
free ( ASTEROID_SourceRect_Size2 ) ;
free ( ASTEROID_SourceRect_Size3 ) ;
printf ( " De-initializing Asteroid finished! \n " ) ;
}
void ASTEROID_Update ( Asteroid * ast ) {
if ( ! ( ast - > IsDestroyed ) ) {
( ast - > Rotation ) + = ( ast - > RotationValue ) ; // Rotate
2017-12-27 21:08:37 +01:00
2017-12-26 23:24:29 +01:00
( ast - > Location ) = vectorAdd ( ast - > Location , ast - > Momentum ) ; // Update Position
2017-12-27 21:08:37 +01:00
if ( ( ast - > Location ) . x < - ( ast - > Size ) ) ( ast - > Location ) . x = Asteroids_BoxWidth ; // Check Boundaries
else if ( ( ast - > Location ) . x > Asteroids_BoxWidth ) ( ast - > Location ) . x = - ( ast - > Size ) ;
if ( ( ast - > Location ) . y < - ( ast - > Size ) ) ( ast - > Location ) . y = Asteroids_BoxHeight ;
else if ( ( ast - > Location ) . y > Asteroids_BoxHeight ) ( ast - > Location ) . y = - ( ast - > Size ) ;
2017-12-26 23:24:29 +01:00
( ast - > TargetRect ) . x = ( int ) round ( ( ast - > Location ) . x ) ;
( ast - > TargetRect ) . y = ( int ) round ( ( ast - > Location ) . y ) ;
}
} // ASTEROID_Update
void ASTEROID_Draw ( Asteroid * ast , SDL_Renderer * renderer ) {
if ( ! ( ast - > IsDestroyed ) ) {
SDL_RenderCopyEx ( renderer , ASTEROID_Texture , & ( ast - > SourceRect ) , & ( ast - > TargetRect ) , ast - > Rotation , NULL , SDL_FLIP_NONE ) ; // Draw Image
}
}
void ENEMY_Initialize ( SDL_Renderer * renderer , int width , int height ) {
printf ( " Initializing Enemy... \n " ) ;
BULLET_Initialize ( renderer , width , height ) ;
2017-12-27 21:08:37 +01:00
Asteroids_BoxWidth = width ;
Asteroids_BoxHeight = height ;
2017-12-27 00:29:20 +01:00
ENEMY_Texture = IMG_LoadTexture ( renderer , " assets/images/enemy.png " ) ;
2017-12-26 23:24:29 +01:00
if ( ! ENEMY_Texture ) printf ( " Enemy texture cannot be loaded! \n " ) ;
ENEMY_MaxBulletCount = ( ( BULLET_DecayTime_Ally / ENEMY_ShootIntevale ) + 10 ) ;
printf ( " Enemy initialized! \n " ) ;
} // ENEMY_Initialize
Enemy ENEMY_GetDefault ( ) {
Enemy temp ;
temp . Bullets = ( Bullet * ) malloc ( ENEMY_MaxBulletCount * sizeof ( Bullet ) ) ;
int i ;
for ( i = 0 ; i < ENEMY_MaxBulletCount ; i + + ) {
temp . Bullets [ i ] = NULLET ; // Nullet is set only if BULLET_Initialize() was called!
}
2017-12-27 21:08:37 +01:00
temp . Location = ( Vector ) { . x = ( double ) ( rand ( ) % Asteroids_BoxWidth ) , . y = ( double ) ( rand ( ) % Asteroids_BoxHeight ) } ;
2017-12-26 23:24:29 +01:00
temp . Momentum = getScaledDirectionalUnitVector ( ( rand ( ) % 360 ) , fmod ( ( double ) rand ( ) , ENEMY_MaxSpeed / 2.0f ) + ( ENEMY_MaxSpeed / 2.0f ) ) ;
temp . TargetRect = ( SDL_Rect ) { . x = 0 , . y = 0 , . w = 80 , . h = 40 } ;
temp . WeaponCooldown = ENEMY_ShootIntevale ;
temp . lastBulletIndex = 0 ;
temp . IsDead = false ;
temp . TurnCooldown = ( rand ( ) % ENEMY_MaxTurnIntervale ) ;
return temp ;
} // ENEMY_CreateDefault
void ENEMY_Deinitialize ( ) {
printf ( " De-initializing Enemy class... \n " ) ;
BULLET_Deinitialize ( ) ;
printf ( " De-initializing Enemy texture 1... \n " ) ;
SDL_DestroyTexture ( ENEMY_Texture ) ;
printf ( " De-initializing Enemy class finished! \n " ) ;
}
void ENEMY_DestroyObject ( Enemy * enm ) {
printf ( " De-initializing Enemy... \n " ) ;
printf ( " De-initializing Bullet-array... \n " ) ;
free ( ( enm - > Bullets ) ) ;
printf ( " De-initializing Enemy... \n " ) ;
}
void ENEMY_Update ( Enemy * enm , Ship * targets , int targetCount ) {
if ( ! ( enm - > IsDead ) ) {
int i ;
for ( i = 0 ; i < ENEMY_MaxBulletCount ; i + + ) { // Update Bullets
BULLET_UpdateEnemy ( & ( ( enm - > Bullets ) [ i ] ) , targets , & targetCount ) ;
}
2017-12-27 00:42:06 +01:00
if ( ( enm - > TurnCooldown ) - - < = 0 ) {
2017-12-26 23:24:29 +01:00
( enm - > TurnCooldown ) = ( rand ( ) % ENEMY_MaxTurnIntervale ) ;
( enm - > Momentum ) = getScaledDirectionalUnitVector ( ( rand ( ) % 360 ) , fmod ( ( double ) rand ( ) , ENEMY_MaxSpeed / 2.0f ) + ( ENEMY_MaxSpeed / 2.0f ) ) ;
}
( enm - > Location ) = vectorAdd ( ( enm - > Location ) , ( enm - > Momentum ) ) ; // Update Position
2017-12-27 21:08:37 +01:00
if ( ( enm - > Location ) . x < - ( enm - > TargetRect ) . w ) ( enm - > Location ) . x = Asteroids_BoxWidth ;
else if ( ( enm - > Location ) . x > Asteroids_BoxWidth + ( enm - > TargetRect ) . w ) ( enm - > Location ) . x = 0.0f ;
if ( ( enm - > Location ) . y < - ( enm - > TargetRect ) . h ) ( enm - > Location ) . y = Asteroids_BoxHeight ;
else if ( ( enm - > Location ) . y > Asteroids_BoxHeight + ( enm - > TargetRect ) . h ) ( enm - > Location ) . y = 0.0f ;
2017-12-26 23:24:29 +01:00
( enm - > TargetRect ) . x = ( int ) round ( ( enm - > Location ) . x ) ;
( enm - > TargetRect ) . y = ( int ) round ( ( enm - > Location ) . y ) ;
if ( ( enm - > WeaponCooldown ) < = 0 ) { // Shoot instantly if cooldown ends
( enm - > WeaponCooldown ) = ENEMY_ShootIntevale ;
( enm - > lastBulletIndex ) + + ;
if ( ( enm - > lastBulletIndex ) > = ENEMY_MaxBulletCount ) ( enm - > lastBulletIndex ) = 0 ;
Vector startPoint = vectorAdd ( ( enm - > Location ) , ( Vector ) { . x = ( double ) ( ( enm - > TargetRect ) . w ) / 2.0f , . y = ( double ) ( ( enm - > TargetRect ) . h ) / 2.0f } ) ;
( enm - > Bullets ) [ ( enm - > lastBulletIndex ) ] = BULLET_Fire ( startPoint , vectorRotation ( vectorSub ( ( targets [ rand ( ) % targetCount ] . Location ) , ( enm - > Location ) ) ) , EnemyBullet ) ; // Maybe check if bullet space is already taken from another bullet being fired...
}
( enm - > WeaponCooldown ) - - ;
} else {
( enm - > DeadTime ) + + ;
}
} // ENEMY_Update
void ENEMY_Draw ( Enemy * enm , SDL_Renderer * renderer ) {
if ( ! ( enm - > IsDead ) ) {
int i ;
for ( i = 0 ; i < ENEMY_MaxBulletCount ; i + + ) { // Draw Bullets
BULLET_Draw ( & ( ( enm - > Bullets ) [ i ] ) , renderer ) ;
}
SDL_RenderCopyEx ( renderer , ENEMY_Texture , NULL , & ( enm - > TargetRect ) , 0.0f , NULL , SDL_FLIP_NONE ) ; // Draw Image
}
}
void SHIP_Initialize ( SDL_Renderer * renderer , int width , int height ) {
printf ( " Initializing Ship... \n " ) ;
BULLET_Initialize ( renderer , width , height ) ;
2017-12-27 21:08:37 +01:00
Asteroids_BoxWidth = width ;
Asteroids_BoxHeight = height ;
2017-12-27 00:29:20 +01:00
SHIP_Texture_Gliding = IMG_LoadTexture ( renderer , " assets/images/ship.png " ) ;
2017-12-26 23:24:29 +01:00
if ( ! SHIP_Texture_Gliding ) printf ( " Ship texture 1 cannot be loaded! \n " ) ;
2017-12-27 00:29:20 +01:00
SHIP_Texture_Accelerating = IMG_LoadTexture ( renderer , " assets/images/shipAcc.png " ) ;
2017-12-26 23:24:29 +01:00
if ( ! SHIP_Texture_Accelerating ) printf ( " Ship texture 2 cannot be loaded! \n " ) ;
2017-12-27 00:29:20 +01:00
SHIP_Texture_Explosion = IMG_LoadTexture ( renderer , " assets/images/shipExpl.png " ) ;
2017-12-26 23:24:29 +01:00
if ( ! SHIP_Texture_Explosion ) printf ( " Ship texture explosion cannot be loaded! \n " ) ;
SHIP_SourceRect_Explosion = calloc ( 5 , sizeof ( SDL_Rect ) ) ;
if ( ! SHIP_SourceRect_Explosion ) printf ( " Memory for SDL_Rect (SHIP) cannot be allocated! \n " ) ;
int i ;
for ( i = 0 ; i < SHIP_DeathAnimFrameCount ; i + + ) {
SHIP_SourceRect_Explosion [ i ] = ( SDL_Rect ) { . x = 0 , . y = ( i * 1632 ) , . w = 1280 , . h = 1632 } ;
}
SHIP_SourceRect_Gliding = ( SDL_Rect ) { . x = 0 , . y = 0 , . w = 320 , . h = 408 } ;
SHIP_SourceRect_Accelerating = ( SDL_Rect ) { . x = 0 , . y = 0 , . w = 320 , . h = 576 } ;
SHIP_RotationCenter_Flight = ( SDL_Point ) { . x = 20 , . y = 25 } ;
SHIP_MaxBulletCount = ( ( BULLET_DecayTime_Ally / SHIP_ShootIntevale ) + 10 ) ;
printf ( " Ship initialized! \n " ) ;
} // SHIP_Initialize
Ship SHIP_CreateDefault ( ) {
Ship temp ;
temp . Bullets = ( Bullet * ) malloc ( SHIP_MaxBulletCount * sizeof ( Bullet ) ) ;
int i ;
for ( i = 0 ; i < SHIP_MaxBulletCount ; i + + ) {
temp . Bullets [ i ] = NULLET ; // Nullet is set only if BULLET_Initialize() was called!
}
temp . Rotation = 0.0f ;
temp . FacingDirection = ( Vector ) { . x = 0.0f , . y = 0.0f } ;
temp . Location = ( Vector ) { . x = 800.0f , . y = 450.0f } ;
temp . Momentum = ( Vector ) { . x = 0.0f , . y = 0.0f } ;
temp . TargetRect_Gliding = ( SDL_Rect ) { . x = 0 , . y = 0 , . w = 40 , . h = 51 } ;
temp . TargetRect_Accelerating = ( SDL_Rect ) { . x = 0 , . y = 0 , . w = 40 , . h = 74 } ;
temp . TargetRect_Explosion = ( SDL_Rect ) { . x = 0 , . y = 0 , . w = 160 , . h = 204 } ;
temp . WeaponCooldown = 0 ;
temp . DeadTime = 0 ;
temp . lastBulletIndex = 0 ;
temp . IsDead = false ;
return temp ;
} // SHIP_CreateDefault
void SHIP_Deinitialize ( ) {
printf ( " De-initializing Ship class... \n " ) ;
BULLET_Deinitialize ( ) ;
free ( SHIP_SourceRect_Explosion ) ;
printf ( " De-initializing Ship texture 1... \n " ) ;
SDL_DestroyTexture ( SHIP_Texture_Gliding ) ;
printf ( " De-initializing Ship texture 2... \n " ) ;
SDL_DestroyTexture ( SHIP_Texture_Accelerating ) ;
printf ( " De-initializing Ship texture 2... \n " ) ;
SDL_DestroyTexture ( SHIP_Texture_Explosion ) ;
printf ( " De-initializing Ship class finished! \n " ) ;
}
void SHIP_DestroyObject ( Ship * shp ) {
printf ( " De-initializing Ship... \n " ) ;
printf ( " De-initializing Bullet-array... \n " ) ;
free ( ( shp - > Bullets ) ) ;
printf ( " De-initializing Ship... \n " ) ;
}
void SHIP_Update ( Ship * shp , Uint8 * keystate , Asteroid * asts , int * astCount , Enemy * enemies , int * enemyCount ) {
if ( ! ( shp - > IsDead ) ) {
( shp - > TurnLeftButtonPressed ) = keystate [ SHIP_LeftButton ] ;
( shp - > TurnRightButtonPressed ) = keystate [ SHIP_RightButton ] ;
( shp - > ForwardButtonPressed ) = keystate [ SHIP_ForwardButton ] ;
( shp - > ShootButtonPressed ) = keystate [ SHIP_ShootButton ] ;
int i ;
for ( i = 0 ; i < SHIP_MaxBulletCount ; i + + ) { // Update Bullets
BULLET_UpdateAlly ( & ( ( shp - > Bullets ) [ i ] ) , asts , astCount , enemies , enemyCount ) ;
}
if ( ( ( shp - > TurnLeftButtonPressed ) + ( shp - > TurnRightButtonPressed ) ) = = 1 ) { // Handle rotation
if ( ( shp - > TurnLeftButtonPressed ) ) { // Rotate to the left
( shp - > Rotation ) - = SHIP_RotationValue ;
} else if ( ( shp - > TurnRightButtonPressed ) ) { // Rotate to the right
( shp - > Rotation ) + = SHIP_RotationValue ;
}
( shp - > FacingDirection ) = getScaledDirectionalUnitVector ( ( shp - > Rotation ) , SHIP_Acceleration ) ;
}
if ( ( shp - > ForwardButtonPressed ) ) { // Handle forward acceleration
( shp - > Momentum ) = vectorAdd ( ( shp - > FacingDirection ) , ( shp - > Momentum ) ) ;
if ( vectorMagnitude ( ( shp - > Momentum ) ) > SHIP_MaxSpeed ) {
( shp - > Momentum ) = vectorScaleTo ( ( shp - > Momentum ) , SHIP_MaxSpeed ) ;
}
}
( shp - > Location ) = vectorAdd ( ( shp - > Location ) , ( shp - > Momentum ) ) ; // Update Position
2017-12-27 21:08:37 +01:00
if ( ( shp - > Location ) . x < - ( shp - > TargetRect_Gliding ) . w ) ( shp - > Location ) . x = Asteroids_BoxWidth ;
else if ( ( shp - > Location ) . x > Asteroids_BoxWidth + ( shp - > TargetRect_Gliding ) . w ) ( shp - > Location ) . x = 0.0f ;
if ( ( shp - > Location ) . y < - ( shp - > TargetRect_Gliding ) . h ) ( shp - > Location ) . y = Asteroids_BoxHeight ;
else if ( ( shp - > Location ) . y > Asteroids_BoxHeight + ( shp - > TargetRect_Gliding ) . h ) ( shp - > Location ) . y = 0.0f ;
2017-12-26 23:24:29 +01:00
( shp - > TargetRect_Gliding ) . x = ( int ) round ( ( shp - > Location ) . x ) ;
( shp - > TargetRect_Gliding ) . y = ( int ) round ( ( shp - > Location ) . y ) ;
( shp - > TargetRect_Accelerating ) . x = ( shp - > TargetRect_Gliding ) . x ;
( shp - > TargetRect_Accelerating ) . y = ( shp - > TargetRect_Gliding ) . y ;
if ( ( shp - > ShootButtonPressed ) ) { // Fire bullet
if ( ( shp - > WeaponCooldown ) < = 0 ) {
( shp - > WeaponCooldown ) = SHIP_ShootIntevale ;
( shp - > lastBulletIndex ) + + ;
if ( ( shp - > lastBulletIndex ) > = SHIP_MaxBulletCount ) ( shp - > lastBulletIndex ) = 0 ;
( shp - > Bullets ) [ ( shp - > lastBulletIndex ) ] = BULLET_Fire ( vectorAdd ( ( shp - > Location ) , ( Vector ) { . x = ( double ) ( SHIP_RotationCenter_Flight . x ) / 2.0f , . y = ( double ) ( SHIP_RotationCenter_Flight . y ) / 2.0f } ) , ( shp - > Rotation ) , AllyBullet ) ; // Maybe check if bullet space is already taken from another bullet being fired...
}
}
( shp - > WeaponCooldown ) - - ;
for ( i = 0 ; i < ( * astCount ) ; i + + ) {
if ( RECT_CircleCollide ( & ( asts [ i ] . TargetRect ) , & ( shp - > TargetRect_Gliding ) ) ) {
printf ( " Ship is destroyed by asteroid no. %d! \n " , i + 1 ) ;
( shp - > IsDead ) = true ;
( shp - > TargetRect_Explosion ) . x = ( ( int ) round ( ( shp - > Location ) . x ) - ( ( shp - > TargetRect_Explosion ) . w / 4 ) ) ;
( shp - > TargetRect_Explosion ) . y = ( ( int ) round ( ( shp - > Location ) . y ) - ( ( shp - > TargetRect_Explosion ) . h / 4 ) ) ;
break ;
}
}
} else {
( shp - > DeadTime ) + + ;
}
} // SHIP_Update
void SHIP_Draw ( Ship * shp , SDL_Renderer * renderer ) {
if ( ! ( shp - > IsDead ) ) {
int i ;
for ( i = 0 ; i < SHIP_MaxBulletCount ; i + + ) { // Draw Bullets
BULLET_Draw ( & ( ( shp - > Bullets ) [ i ] ) , renderer ) ;
}
if ( ( shp - > ForwardButtonPressed ) )
SDL_RenderCopyEx ( renderer , SHIP_Texture_Accelerating , & SHIP_SourceRect_Accelerating , & ( shp - > TargetRect_Accelerating ) , ( shp - > Rotation ) , & SHIP_RotationCenter_Flight , SDL_FLIP_NONE ) ; // Draw Image
else
SDL_RenderCopyEx ( renderer , SHIP_Texture_Gliding , & SHIP_SourceRect_Gliding , & ( shp - > TargetRect_Gliding ) , ( shp - > Rotation ) , NULL , SDL_FLIP_NONE ) ; // Draw Image
} else if ( ( shp - > DeadTime ) < SHIP_DeathAnimSpeed * SHIP_DeathAnimFrameCount ) {
SDL_RenderCopyEx ( renderer , SHIP_Texture_Explosion , & ( SHIP_SourceRect_Explosion [ ( ( shp - > DeadTime ) / SHIP_DeathAnimSpeed ) ] ) , & ( shp - > TargetRect_Explosion ) , ( shp - > Rotation ) , NULL , SDL_FLIP_NONE ) ; // Draw Image
}
}