← index
JavaScript.Projects/source/apps/WebAssembly_Ports/space/ship.c
Source: JavaScript.Projects/source/apps/WebAssembly_Ports/space/ship.c
#include "ship.h"
#include "sdl.h"

#define MAX_PROJECTILES 50
#define MAX_ASTEROIDS 30
#define PROJECTILE_SPEED 5.0f
#define PROJECTILE_LIFETIME 60  
#define FIRE_COOLDOWN 5        
#define SHOTS_PER_BURST 5      
#define FIRE_DELAY 3           

#define EXPLOSION_DURATION 90     
#define RESPAWN_DELAY 120         
#define INVULNERABLE_TIME 180     

#define MIN_ASTEROID_RADIUS 8.0f  
#define LARGE_ASTEROID_POINTS 20
#define MEDIUM_ASTEROID_POINTS 50
#define SMALL_ASTEROID_POINTS 100

#define ASTEROID_VERTICES 8  

Ship the_ship;
bool keyLeft = false, keyRight = false, keyThrust = false;

Projectile projectiles[MAX_PROJECTILES];
Asteroid asteroids[MAX_ASTEROIDS];
Particle explosion_particles[MAX_PARTICLES];


void init_projectiles(void) {
    for (int i = 0; i < MAX_PROJECTILES; i++) {
        projectiles[i].active = false;
    }
}

void update_projectiles(void) {
    for (int i = 0; i < MAX_PROJECTILES; i++) {
        if (projectiles[i].active) {
            
            projectiles[i].x += projectiles[i].vx;
            projectiles[i].y += projectiles[i].vy;
            
            
            if (projectiles[i].x < 0 || projectiles[i].x >= SCALE_W || 
                projectiles[i].y < 0 || projectiles[i].y >= SCALE_H) {
                projectiles[i].active = false;
                continue;
            }
            
            
            projectiles[i].angle--;
            if (projectiles[i].angle <= 0) {
                projectiles[i].active = false;
            }
        }
    }
}

void draw_projectiles(void) {
    
    SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
    for (int i = 0; i < MAX_PROJECTILES; i++) {
        if (projectiles[i].active) {
    
            float endX = projectiles[i].x - projectiles[i].vx * 0.5;
            float endY = projectiles[i].y - projectiles[i].vy * 0.5;
            SDL_RenderDrawLine(renderer, 
                              (int)projectiles[i].x, (int)projectiles[i].y,
                              (int)endX, (int)endY);
        }
    }
}

void fire_projectile(float x, float y, float angle) {
    
    for (int i = 0; i < MAX_PROJECTILES; i++) {
        if (!projectiles[i].active) {
            
            float c = cosf(angle);
            float s = sinf(angle);
            float lx1 = 0, ly1 = -12;  
            
            
            projectiles[i].x = x + (lx1 * c - ly1 * s);
            projectiles[i].y = y + (lx1 * s + ly1 * c);
            
            projectiles[i].vx = sinf(angle) * PROJECTILE_SPEED;
            projectiles[i].vy = -cosf(angle) * PROJECTILE_SPEED; 
            projectiles[i].angle = PROJECTILE_LIFETIME;  
            projectiles[i].active = true;
            break;
        }
    }
}


void init_asteroids(void) {
    for (int i = 0; i < MAX_ASTEROIDS; i++) {
        asteroids[i].active = false;
    }

    for (int i = 0; i < 4; i++) {
        float x, y;
        
        do {
            x = rand() % SCALE_W;
            y = rand() % SCALE_H;
        } while (hypotf(x - the_ship.x, y - the_ship.y) < 100);
        
        float vx = ((rand() % 100) - 50) / 50.0f;  
        float vy = ((rand() % 100) - 50) / 50.0f;  
        float radius = 20.0f + (rand() % 20);      
        
        spawn_asteroid(x, y, vx, vy, radius);
    }
}

void update_asteroids(void) {
    for (int i = 0; i < MAX_ASTEROIDS; i++) {
        if (asteroids[i].active) {
            asteroids[i].x += asteroids[i].vx;
            asteroids[i].y += asteroids[i].vy;
            asteroids[i].rotation_angle += asteroids[i].rotation_speed;
            if (asteroids[i].x < 0) asteroids[i].x += SCALE_W;
            if (asteroids[i].x >= SCALE_W) asteroids[i].x -= SCALE_W;
            if (asteroids[i].y < 0) asteroids[i].y += SCALE_H;
            if (asteroids[i].y >= SCALE_H) asteroids[i].y -= SCALE_H;
        }
    }
}

void draw_asteroids(void) {
    for (int i = 0; i < MAX_ASTEROIDS; i++) {
        if (asteroids[i].active) {
            
            float cos_rot = cosf(asteroids[i].rotation_angle);
            float sin_rot = sinf(asteroids[i].rotation_angle);
            
            
            float rotated_vertices[ASTEROID_VERTICES][2];
            for (int j = 0; j < ASTEROID_VERTICES; j++) {
                float orig_x = asteroids[i].vertices[j][0];
                float orig_y = asteroids[i].vertices[j][1];
                
                rotated_vertices[j][0] = orig_x * cos_rot - orig_y * sin_rot;
                rotated_vertices[j][1] = orig_x * sin_rot + orig_y * cos_rot;
            }
            
            
            SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
            
            
            for (int j = 0; j < ASTEROID_VERTICES; j++) {
                int next = (j + 1) % ASTEROID_VERTICES;
                
                int x1 = (int)(asteroids[i].x + rotated_vertices[j][0]);
                int y1 = (int)(asteroids[i].y + rotated_vertices[j][1]);
                int x2 = (int)(asteroids[i].x + rotated_vertices[next][0]);
                int y2 = (int)(asteroids[i].y + rotated_vertices[next][1]);
                
                SDL_RenderDrawLine(renderer, x1, y1, x2, y2);
            }
            
            
            SDL_SetRenderDrawColor(renderer, 150, 150, 150, 255);
            
            float inner_vertices[ASTEROID_VERTICES][2];
            for (int j = 0; j < ASTEROID_VERTICES; j++) {
                inner_vertices[j][0] = rotated_vertices[j][0] * 0.6f;
                inner_vertices[j][1] = rotated_vertices[j][1] * 0.6f;
            }
            
            for (int j = 0; j < ASTEROID_VERTICES; j++) {
                int next = (j + 1) % ASTEROID_VERTICES;
                
                int x1 = (int)(asteroids[i].x + inner_vertices[j][0]);
                int y1 = (int)(asteroids[i].y + inner_vertices[j][1]);
                int x2 = (int)(asteroids[i].x + inner_vertices[next][0]);
                int y2 = (int)(asteroids[i].y + inner_vertices[next][1]);
                
                SDL_RenderDrawLine(renderer, x1, y1, x2, y2);
            }
            
            SDL_SetRenderDrawColor(renderer, 100, 100, 100, 255);
            
            for (int j = 0; j < ASTEROID_VERTICES; j += 2) {
                int outer_x = (int)(asteroids[i].x + rotated_vertices[j][0]);
                int outer_y = (int)(asteroids[i].y + rotated_vertices[j][1]);
                int inner_x = (int)(asteroids[i].x + inner_vertices[j][0]);
                int inner_y = (int)(asteroids[i].y + inner_vertices[j][1]);
                
                SDL_RenderDrawLine(renderer, outer_x, outer_y, inner_x, inner_y);
            }
            
            SDL_SetRenderDrawColor(renderer, 120, 120, 120, 255);
            
            int center_x = (int)asteroids[i].x;
            int center_y = (int)asteroids[i].y;
            
            for (int j = 0; j < ASTEROID_VERTICES; j += 4) {
                int vertex_x = (int)(asteroids[i].x + inner_vertices[j][0]);
                int vertex_y = (int)(asteroids[i].y + inner_vertices[j][1]);
                
                SDL_RenderDrawLine(renderer, center_x, center_y, vertex_x, vertex_y);
            }
            
            SDL_SetRenderDrawColor(renderer, 180, 180, 180, 255);
            
            for (int j = 0; j < ASTEROID_VERTICES; j += 2) {
                int next = (j + 1) % ASTEROID_VERTICES;
                
                int outer_x1 = (int)(asteroids[i].x + rotated_vertices[j][0]);
                int outer_y1 = (int)(asteroids[i].y + rotated_vertices[j][1]);
                int inner_x2 = (int)(asteroids[i].x + inner_vertices[next][0]);
                int inner_y2 = (int)(asteroids[i].y + inner_vertices[next][1]);
                
                SDL_RenderDrawLine(renderer, outer_x1, outer_y1, inner_x2, inner_y2);
            }
        }
    }
}

void spawn_asteroid(float x, float y, float vx, float vy, float radius) {
    for (int i = 0; i < MAX_ASTEROIDS; i++) {
        if (!asteroids[i].active) {
            asteroids[i].x = x;
            asteroids[i].y = y;
            asteroids[i].vx = vx;
            asteroids[i].vy = vy;
            asteroids[i].radius = radius;
            asteroids[i].active = true;
            
            asteroids[i].rotation_angle = 0.0f;
            asteroids[i].rotation_speed = ((rand() % 100) - 50) / 1000.0f; 
         

            for (int j = 0; j < ASTEROID_VERTICES; j++) {
                float angle = (float)j / ASTEROID_VERTICES * 2 * PI;
                
                float vertex_radius = radius * (0.7f + ((rand() % 30) / 100.0f));
                
                asteroids[i].vertices[j][0] = cosf(angle) * vertex_radius;
                asteroids[i].vertices[j][1] = sinf(angle) * vertex_radius;
            }
            
            break;
        }
    }
}

void init_ship(void) {
    the_ship.x = SCALE_W / 2.0f;
    the_ship.y = SCALE_H / 2.0f;
    the_ship.vx = 0.0f;
    the_ship.vy = 0.0f;
    the_ship.angle = 0.0f;
    the_ship.lives = 3;
    the_ship.fire_cooldown = 0;
    the_ship.burst_count = 0;
    the_ship.exploding = false;
    the_ship.explosion_timer = 0;
    the_ship.score = 0;
    the_ship.continuous_fire_timer = 0;
    the_ship.overheated = false;
    the_ship.overheat_cooldown = 0;
    
    for (int i = 0; i < MAX_PARTICLES; i++) {
        explosion_particles[i].active = false;
    }
}

void draw_ship(void) {
    if (the_ship.exploding) {
        draw_explosion();
        return;
    }
    
    
    float nose_x = 0, nose_y = -15;
    float left_wing_x = -12, left_wing_y = 8;
    float right_wing_x = 12, right_wing_y = 8;
    
    float left_engine_x = -8, left_engine_y = 12;
    float right_engine_x = 8, right_engine_y = 12;
    float center_engine_x = 0, center_engine_y = 10;
    
    float left_detail_x = -6, left_detail_y = 2;
    float right_detail_x = 6, right_detail_y = 2;
    
    float cockpit_left_x = -3, cockpit_left_y = -8;
    float cockpit_right_x = 3, cockpit_right_y = -8;
    float cockpit_center_x = 0, cockpit_center_y = -5;
    
    float c = cosf(the_ship.angle);
    float s = sinf(the_ship.angle);
    
    int vertices[11][2];
    
    vertices[0][0] = (int)(the_ship.x + (nose_x * c - nose_y * s));
    vertices[0][1] = (int)(the_ship.y + (nose_x * s + nose_y * c));
    
    vertices[1][0] = (int)(the_ship.x + (left_wing_x * c - left_wing_y * s));
    vertices[1][1] = (int)(the_ship.y + (left_wing_x * s + left_wing_y * c));
    
    vertices[2][0] = (int)(the_ship.x + (right_wing_x * c - right_wing_y * s));
    vertices[2][1] = (int)(the_ship.y + (right_wing_x * s + right_wing_y * c));
    
    vertices[3][0] = (int)(the_ship.x + (left_engine_x * c - left_engine_y * s));
    vertices[3][1] = (int)(the_ship.y + (left_engine_x * s + left_engine_y * c));
    
    vertices[4][0] = (int)(the_ship.x + (right_engine_x * c - right_engine_y * s));
    vertices[4][1] = (int)(the_ship.y + (right_engine_x * s + right_engine_y * c));
    
    vertices[5][0] = (int)(the_ship.x + (center_engine_x * c - center_engine_y * s));
    vertices[5][1] = (int)(the_ship.y + (center_engine_x * s + center_engine_y * c));
    
    vertices[6][0] = (int)(the_ship.x + (left_detail_x * c - left_detail_y * s));
    vertices[6][1] = (int)(the_ship.y + (left_detail_x * s + left_detail_y * c));
    
    vertices[7][0] = (int)(the_ship.x + (right_detail_x * c - right_detail_y * s));
    vertices[7][1] = (int)(the_ship.y + (right_detail_x * s + right_detail_y * c));
    
    vertices[8][0] = (int)(the_ship.x + (cockpit_left_x * c - cockpit_left_y * s));
    vertices[8][1] = (int)(the_ship.y + (cockpit_left_x * s + cockpit_left_y * c));
    
    vertices[9][0] = (int)(the_ship.x + (cockpit_right_x * c - cockpit_right_y * s));
    vertices[9][1] = (int)(the_ship.y + (cockpit_right_x * s + cockpit_right_y * c));
    
    vertices[10][0] = (int)(the_ship.x + (cockpit_center_x * c - cockpit_center_y * s));
    vertices[10][1] = (int)(the_ship.y + (cockpit_center_x * s + cockpit_center_y * c));
    
    
    if (the_ship.overheated) {
    
        SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
    } else if (the_ship.continuous_fire_timer > 120) {
    
        int heat_level = the_ship.continuous_fire_timer - 120;
        SDL_SetRenderDrawColor(renderer, 255, 255 - (heat_level * 4), 0, 255);
    } else {
    
        SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
    }
    
    
    SDL_RenderDrawLine(renderer, vertices[0][0], vertices[0][1], vertices[1][0], vertices[1][1]);
    SDL_RenderDrawLine(renderer, vertices[0][0], vertices[0][1], vertices[2][0], vertices[2][1]);
    SDL_RenderDrawLine(renderer, vertices[1][0], vertices[1][1], vertices[2][0], vertices[2][1]);
    
    SDL_RenderDrawLine(renderer, vertices[1][0], vertices[1][1], vertices[3][0], vertices[3][1]);
    SDL_RenderDrawLine(renderer, vertices[2][0], vertices[2][1], vertices[4][0], vertices[4][1]);
    SDL_RenderDrawLine(renderer, vertices[3][0], vertices[3][1], vertices[5][0], vertices[5][1]);
    SDL_RenderDrawLine(renderer, vertices[4][0], vertices[4][1], vertices[5][0], vertices[5][1]);
    
    
    if (the_ship.overheated) {
        SDL_SetRenderDrawColor(renderer, 200, 0, 0, 255);
    } else if (the_ship.continuous_fire_timer > 120) {
        int heat_level = the_ship.continuous_fire_timer - 120;
        SDL_SetRenderDrawColor(renderer, 200, 200 - (heat_level * 3), 0, 255);
    } else {
        SDL_SetRenderDrawColor(renderer, 200, 200, 200, 255);
    }
    
    SDL_RenderDrawLine(renderer, vertices[0][0], vertices[0][1], vertices[6][0], vertices[6][1]);
    SDL_RenderDrawLine(renderer, vertices[0][0], vertices[0][1], vertices[7][0], vertices[7][1]);
    SDL_RenderDrawLine(renderer, vertices[6][0], vertices[6][1], vertices[7][0], vertices[7][1]);
    SDL_RenderDrawLine(renderer, vertices[6][0], vertices[6][1], vertices[1][0], vertices[1][1]);
    SDL_RenderDrawLine(renderer, vertices[7][0], vertices[7][1], vertices[2][0], vertices[2][1]);
    
    
    if (the_ship.overheated) {
        SDL_SetRenderDrawColor(renderer, 0, 128, 128, 255);
    } else {
        SDL_SetRenderDrawColor(renderer, 0, 255, 255, 255);
    }
    SDL_RenderDrawLine(renderer, vertices[8][0], vertices[8][1], vertices[9][0], vertices[9][1]);
    SDL_RenderDrawLine(renderer, vertices[8][0], vertices[8][1], vertices[10][0], vertices[10][1]);
    SDL_RenderDrawLine(renderer, vertices[9][0], vertices[9][1], vertices[10][0], vertices[10][1]);
    
    
    if (the_ship.overheated) {
        SDL_SetRenderDrawColor(renderer, 100, 0, 0, 255);
    } else {
        SDL_SetRenderDrawColor(renderer, 150, 150, 150, 255);
    }
    SDL_RenderDrawLine(renderer, vertices[10][0], vertices[10][1], vertices[5][0], vertices[5][1]);
    
    
    if (keyThrust) {
        SDL_SetRenderDrawColor(renderer, 255, 100, 0, 255);
        
        int flame1_x = (int)(the_ship.x + ((-6) * c - 18 * s));
        int flame1_y = (int)(the_ship.y + ((-6) * s + 18 * c));
        int flame2_x = (int)(the_ship.x + (0 * c - 22 * s));
        int flame2_y = (int)(the_ship.y + (0 * s + 22 * c));
        int flame3_x = (int)(the_ship.x + (6 * c - 18 * s));
        int flame3_y = (int)(the_ship.y + (6 * s + 18 * c));
        
        SDL_RenderDrawLine(renderer, vertices[3][0], vertices[3][1], flame1_x, flame1_y);
        SDL_RenderDrawLine(renderer, vertices[5][0], vertices[5][1], flame2_x, flame2_y);
        SDL_RenderDrawLine(renderer, vertices[4][0], vertices[4][1], flame3_x, flame3_y);
        
        SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255);
        int inner_flame_x = (int)(the_ship.x + (0 * c - 20 * s));
        int inner_flame_y = (int)(the_ship.y + (0 * s + 20 * c));
        SDL_RenderDrawLine(renderer, vertices[5][0], vertices[5][1], inner_flame_x, inner_flame_y);
    }
}


void check_asteroid_collisions(void) {
    for (int i = 0; i < MAX_ASTEROIDS; i++) {
        if (!asteroids[i].active) continue;
        
        for (int j = i + 1; j < MAX_ASTEROIDS; j++) {
            if (!asteroids[j].active) continue;
            
            float dx = asteroids[i].x - asteroids[j].x;
            float dy = asteroids[i].y - asteroids[j].y;
            float distance = sqrtf(dx * dx + dy * dy);
            float min_distance = asteroids[i].radius + asteroids[j].radius;
            
            if (distance < min_distance && distance > 0) {
                float nx = dx / distance;
                float ny = dy / distance;
                
                float overlap = min_distance - distance;
                float separation = overlap * 0.5f;
                
                asteroids[i].x += nx * separation;
                asteroids[i].y += ny * separation;
                asteroids[j].x -= nx * separation;
                asteroids[j].y -= ny * separation;
                
                float rel_vx = asteroids[i].vx - asteroids[j].vx;
                float rel_vy = asteroids[i].vy - asteroids[j].vy;
                
                float vel_along_normal = rel_vx * nx + rel_vy * ny;
                
                if (vel_along_normal > 0) continue;
                
                float restitution = 0.8f;
                float impulse = -(1 + restitution) * vel_along_normal;
                
                float mass_ratio = 0.5f;
                
                asteroids[i].vx += impulse * mass_ratio * nx;
                asteroids[i].vy += impulse * mass_ratio * ny;
                asteroids[j].vx -= impulse * mass_ratio * nx;
                asteroids[j].vy -= impulse * mass_ratio * ny;
            }
        }
    }
}


void check_ship_asteroid_collision(void) {
    if (the_ship.exploding) return; 
    
    for (int i = 0; i < MAX_ASTEROIDS; i++) {
        if (asteroids[i].active) {
            float dx = the_ship.x - asteroids[i].x;
            float dy = the_ship.y - asteroids[i].y;
            float distance = sqrtf(dx * dx + dy * dy);
            
            float ship_radius = 8.0f;
            
            if (distance < asteroids[i].radius + ship_radius) {
                start_ship_explosion();
                
                float explosion_x = the_ship.x + dx * 0.5f;
                float explosion_y = the_ship.y + dy * 0.5f;
                create_asteroid_explosion(explosion_x, explosion_y);
                
                float bounce_force = 2.0f;
                float norm_x = -dx / distance;
                float norm_y = -dy / distance;
                
                asteroids[i].vx += norm_x * bounce_force;
                asteroids[i].vy += norm_y * bounce_force;
                
                break;
            }
        }
    }
}

void start_ship_explosion(void) {
    if (!the_ship.exploding) {
        the_ship.exploding = true;
        the_ship.explosion_timer = EXPLOSION_DURATION;
        the_ship.lives--; 
        
        
        the_ship.overheated = false;
        the_ship.overheat_cooldown = 0;
        the_ship.continuous_fire_timer = 0;
        the_ship.burst_count = 0;
        
        for (int i = 0; i < MAX_PARTICLES; i++) {
            explosion_particles[i].x = the_ship.x + ((rand() % 20) - 10);
            explosion_particles[i].y = the_ship.y + ((rand() % 20) - 10);
            
            float angle = (rand() % 628) / 100.0f;
            float speed = 0.5f + (rand() % 20) / 10.0f;
            
            explosion_particles[i].vx = cosf(angle) * speed;
            explosion_particles[i].vy = sinf(angle) * speed;
            
            explosion_particles[i].lifetime = 30 + (rand() % 60);
            explosion_particles[i].active = true;
        }
    }
}

void create_asteroid_explosion(float x, float y) {
    int particles_to_create = 15 + (rand() % 10); 
    int created = 0;
    
    for (int i = 0; i < MAX_PARTICLES && created < particles_to_create; i++) {
        if (!explosion_particles[i].active) {
            explosion_particles[i].x = x + ((rand() % 16) - 8);
            explosion_particles[i].y = y + ((rand() % 16) - 8);
            
            float angle = (rand() % 628) / 100.0f;
            float speed = 1.0f + (rand() % 20) / 10.0f; 
            
            explosion_particles[i].vx = cosf(angle) * speed;
            explosion_particles[i].vy = sinf(angle) * speed;
            
            explosion_particles[i].lifetime = 15 + (rand() % 25); 
            explosion_particles[i].active = true;
            created++;
        }
    }
}

void update_explosion(void) {
    for (int i = 0; i < MAX_PARTICLES; i++) {
        if (explosion_particles[i].active) {
            explosion_particles[i].x += explosion_particles[i].vx;
            explosion_particles[i].y += explosion_particles[i].vy;
            
            explosion_particles[i].vx *= 0.97f;
            explosion_particles[i].vy *= 0.97f;
            
            explosion_particles[i].lifetime--;
            if (explosion_particles[i].lifetime <= 0) {
                explosion_particles[i].active = false;
            }
            
            if (explosion_particles[i].x < 0) explosion_particles[i].x += SCALE_W;
            if (explosion_particles[i].x >= SCALE_W) explosion_particles[i].x -= SCALE_W;
            if (explosion_particles[i].y < 0) explosion_particles[i].y += SCALE_H;
            if (explosion_particles[i].y >= SCALE_H) explosion_particles[i].y -= SCALE_H;
        }
    }
    
    if (the_ship.exploding) {
        the_ship.explosion_timer--;
        if (the_ship.explosion_timer <= 0) {
            the_ship.exploding = false;
        }
    }
}

void draw_explosion(void) {
    for (int i = 0; i < MAX_PARTICLES; i++) {
        if (explosion_particles[i].active) {
            float life_percent = (float)explosion_particles[i].lifetime / 50.0f;
            
            if (life_percent > 0.7f) {
                SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); 
            } else if (life_percent > 0.5f) {
                SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255);   
            } else if (life_percent > 0.2f) {
                SDL_SetRenderDrawColor(renderer, 255, 128, 0, 255);   
            } else {
                SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);     
            }
            
            SDL_Rect particle = {
                (int)explosion_particles[i].x, 
                (int)explosion_particles[i].y,
                2, 
                2
            };
            SDL_RenderFillRect(renderer, &particle);
        }
    }
}

bool can_fire(void) {
    
    if (the_ship.overheated) {
        return false;
    }
    
    if (the_ship.fire_cooldown <= 0) {
        if (the_ship.burst_count < SHOTS_PER_BURST) {
            the_ship.fire_cooldown = FIRE_DELAY;  
            the_ship.burst_count++;
            return true;
        } else {
            the_ship.fire_cooldown = FIRE_COOLDOWN;
            the_ship.burst_count = 0;
            return false;
        }
    }
    return false;
}

void check_projectile_asteroid_collisions(void) {
    for (int i = 0; i < MAX_PROJECTILES; i++) {
        if (!projectiles[i].active) continue;
        
        for (int j = 0; j < MAX_ASTEROIDS; j++) {
            if (!asteroids[j].active) continue;
            
            float dx = projectiles[i].x - asteroids[j].x;
            float dy = projectiles[i].y - asteroids[j].y;
            float distance = sqrtf(dx * dx + dy * dy);
            
            if (distance < asteroids[j].radius) {
                projectiles[i].active = false;
                split_asteroid(j);
                if (asteroids[j].radius >= 20.0f) {
                    the_ship.score += LARGE_ASTEROID_POINTS;
                } else if (asteroids[j].radius >= MIN_ASTEROID_RADIUS) {
                    the_ship.score += MEDIUM_ASTEROID_POINTS;
                } else {
                    the_ship.score += SMALL_ASTEROID_POINTS;
                }
                
                break;
            }
        }
    }
}


void split_asteroid(int index) {
    float x = asteroids[index].x;
    float y = asteroids[index].y;
    float radius = asteroids[index].radius / 2.0f;
    
    if (radius < MIN_ASTEROID_RADIUS) {
        create_asteroid_explosion(x, y); 
        the_ship.score += SMALL_ASTEROID_POINTS;
        asteroids[index].active = false;
        return;
    }
    
    int num_splits = 2 + (rand() % 2); 
    for (int i = 0; i < num_splits; i++) {
        float angle = (rand() % 628) / 100.0f;
        float speed = 0.5f + (rand() % 15) / 10.0f;
        
        float vx = cosf(angle) * speed;
        float vy = sinf(angle) * speed;
        
        vx += asteroids[index].vx * 0.3f;
        vy += asteroids[index].vy * 0.3f;
        
        float offset = radius * 0.5f;
        float new_x = x + cosf(angle) * offset;
        float new_y = y + sinf(angle) * offset;
        
        spawn_asteroid(new_x, new_y, vx, vy, radius);
    }
    
    if (radius >= 25.0f) {
        the_ship.score += LARGE_ASTEROID_POINTS;
    } else {
        the_ship.score += MEDIUM_ASTEROID_POINTS;
    }
    
    create_asteroid_explosion(x, y);
    
    asteroids[index].active = false;
}

void check_and_spawn_asteroids(void) {
    int active_count = 0;
    for (int i = 0; i < MAX_ASTEROIDS; i++) {
        if (asteroids[i].active) {
            active_count++;
        }
    }
    
    
    int min_asteroids = 3; 
    if (active_count < min_asteroids) {
        int asteroids_to_spawn = min_asteroids - active_count;
        
        for (int spawn = 0; spawn < asteroids_to_spawn; spawn++) {
            float x, y;
            int attempts = 0;
            
            do {
                if (rand() % 2) {
                    x = (rand() % 2) ? -30.0f : SCALE_W + 30.0f;
                    y = rand() % SCALE_H;
                } else {
                    x = rand() % SCALE_W;
                    y = (rand() % 2) ? -30.0f : SCALE_H + 30.0f;
                }
                attempts++;
            } while (hypotf(x - the_ship.x, y - the_ship.y) < 100.0f && attempts < 10);
            
            float vx = ((rand() % 100) - 50) / 50.0f;
            float vy = ((rand() % 100) - 50) / 50.0f;
            
            float radius;
            int size_roll = rand() % 100;
            if (size_roll < 20) {
                radius = 30.0f + (rand() % 15); 
            } else if (size_roll < 60) {
                radius = 20.0f + (rand() % 10); 
            } else {
                radius = 12.0f + (rand() % 8);  
            }
            
            spawn_asteroid(x, y, vx, vy, radius);
        }
    }
}

void update_ship(void) {
    if (the_ship.exploding) return;
    
    if (keyLeft) {
        the_ship.angle -= 0.15f; 
    }
    if (keyRight) {
        the_ship.angle += 0.15f; 
    }
    
    if (keyThrust) {
        float thrust = 0.2f; 
        the_ship.vx += sinf(the_ship.angle) * thrust;
        the_ship.vy += -cosf(the_ship.angle) * thrust;
        
        float max_speed = 4.0f;
        float current_speed = sqrtf(the_ship.vx * the_ship.vx + the_ship.vy * the_ship.vy);
        if (current_speed > max_speed) {
            the_ship.vx = (the_ship.vx / current_speed) * max_speed;
            the_ship.vy = (the_ship.vy / current_speed) * max_speed;
        }
    }
    
    the_ship.vx *= 0.98f;
    the_ship.vy *= 0.98f;
    
    the_ship.x += the_ship.vx;
    the_ship.y += the_ship.vy;
    
    if (the_ship.x < 0) the_ship.x += SCALE_W;
    if (the_ship.x >= SCALE_W) the_ship.x -= SCALE_W;
    if (the_ship.y < 0) the_ship.y += SCALE_H;
    if (the_ship.y >= SCALE_H) the_ship.y -= SCALE_H;
    
    if (the_ship.fire_cooldown > 0) {
        the_ship.fire_cooldown--;
    }
}

void update_fire_timer(void) {
    const Uint8 *keys = SDL_GetKeyboardState(NULL);
    
    if (keys[SDL_SCANCODE_SPACE] && !the_ship.overheated) {
        the_ship.continuous_fire_timer++;
        the_ship.overheat_cooldown = 0;
        
        if (the_ship.continuous_fire_timer >= 180) {
            the_ship.overheated = true;
            the_ship.overheat_cooldown = 0; 
            the_ship.continuous_fire_timer = 0;
            the_ship.burst_count = 0;
        }
    } else if (keys[SDL_SCANCODE_SPACE] && the_ship.overheated) {
        the_ship.overheat_cooldown = 0;
    } else if (!keys[SDL_SCANCODE_SPACE]) {
        if (the_ship.overheated) {
            the_ship.overheat_cooldown++;
            
            if (the_ship.overheat_cooldown >= 180) {
                the_ship.overheated = false;
                the_ship.overheat_cooldown = 0;
                the_ship.continuous_fire_timer = 0;
            }
        } else {
            if (the_ship.continuous_fire_timer > 0) {
                the_ship.continuous_fire_timer--;
                if (the_ship.continuous_fire_timer < 0) {
                    the_ship.continuous_fire_timer = 0;
                }
            }
        }
    }
}