How To Explode A Sprite In C

Hi,

As I am programming a paratrooper style game in Turbo C, i need a code to explode the helicopters when hit by a bullet in a realistic way. I am looking for the similar simulation as programmed by Mr. Greg Kuperberg in his game ‘paratrooper’ in 70s!. I have almost completed all other graphic routines but stuck up in this rendering. I am confused with all details available in the net for ‘particle explosion’ as they are either too complex to understand or have written in other languages which i am not comfortable with.

I have given an extract of sample code for illustration purpose. The purpose is to explode this array “SPRITE_IMAGE”. This image consists of three colours, Blue, Yellow and White. I know how to animate the sprite to different locations of screen but not sure how to code for exploding this spite so that it falls down with velocity and gravity. Any simple method to do this since its a 2D game?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//Mode 13h programming in C
//Particle Explosure / Sprite Explosion
//This is not a complete code.
#define SCREEN_WIDTH   320
#define SCREEN_HEIGHT  200
#define SCREEN_SEGMENT 0xA000

char SPRITE_IMAGE[] =
       //A Simple Array Image of Blue(11), Yellow(14) and White(15)
  {
                         //6 x 6 array.
    11,11,11,11,11,11,
    11,14,14,14,14,11,
    11,14,15,15,14,11,
    11,14,15,15,14,11,
    11,14,14,14,14,11,
    11,11,11,11,11,11,
  };

*MySpriteImage = SPRITE_IMAGE;    // pointer to sprite image.

  typedef struct
  {
    int  x, y, velocity, gravity etc.......; 
  } Sprite;
  
  // Please help to complete with code or suggest some idea.


Thanks.

Pramod
India

Edited by TP Pramod Kumar on
What does "explosion" mean for you? Do you want to split your sprite into smaller pieces that move independently?
If so, then just crate more smaller sprites from original sprite:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
char part1[] = {
  11, 11,
  11, 14,
};

char part2[] = {
  11, 11,
  14, 14,
};

char part3[] = {
  11, 11,
  14, 11,
}; 

... other parts


Then process these smaller sprites independently with position, velocity, gravity.

Edited by Mārtiņš Možeiko on
Hi mmozeiko,

I appreciate your response on my query. I was eagerly waiting for a reply :)

I have 8 helicopters created from one single array of 10 x 25 as below. Please watch the video clip of the original game to have an idea about the explosion i wanted to render. The explosion here is so realistic and i am excited to program in a similar way.
.

Below is the array data of my helicopter's body and is the exact replica as in the original game. Tail & Blade of the helicopter is rendered separately as that is the part of animation.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
char HELICOPTERIMAGE[] =
  {
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,15,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,15,15,15,15,15,15,15,-1,-1,-1,-1,
    -1,-1,15,15,15,15,15,15,15,15,15,15,15,-1,-1,-1,-1,15,15,15,15,15,-1,-1,-1,
    -1,-1,-1,-1,-1,15,15,15,15,15,15,-1,-1,-1,-1,-1,-1,-1,15,15,15,15,15,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,15,15,15,15,15,15,15,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,-1,-1,-1,-1,11,-1,-1,-1,-1,11,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,-1,
  };


Thanks a lot.

Pramod
India


Edited by TP Pramod Kumar on
There isn't one solution.

You can create a bunch of new sprite containing part of the helicopter (in the video they seems to be small 1 pixel height lines or a single pixel), apply some physics to each part and render them. To create the parts, you can either do it at random at runtime, or hardcode some parts (like mmozeiko said).

The physics step is just adding gravity on the y axis, computing the speed and position. You can add some variation on different part so that they will move differently.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
float gravity = -9.81f;
float time_step = 1.0f/60.0f; /* time_step should take your actual frame time into account. */
float y_velocity = 0;
float y = part_y;

while ( simulation ) {
    float y_acceleration = gravity * time_step;
    y_velocity += y_acceleration;
    y = y + ( velocity * time_step );
}


If a moderator comes here: this thread is in the wrong forum, maybe move it ?

Edited by Simon Anciaux on
Hi Simon. Thanks for the clarity with the code example.

So should I pull each value from the array and plot it on the screen after rendering the new x & y coordinates with velocity and gravity by using a separate simulation function? Actually I am not getting idea how to do this. Is there any quick way to do this task. I would appreciate it if you could help me with the code to do that.


Thanks

Pramod
In the long term it would benefit you more to figure it out yourself. Don't be afraid to try things, even if they don't work you'll learn a thing or two about the problem and get closer to a solution.

Here is an example, of what you could do. Since I know nothing about your code it might just not work for you (I didn't compile it).

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include <stdlib.h> /* NOTE: for srand() and rand() */

typedef struct helicopter_t {
    r32 x, y;
    r32 velocity_x;
    b32 active;
    b32 explode;
} helicopter_t;

typedef struct particle_t {
    r32 x, y;
    r32 velocity_x, velocity_y;
    u8 pixels[ 4 ];
} particle_t;

b32 g_game_running = true;
umm g_screen_width = 320;
umm g_screen_height = 200;
umm g_helicopter_width = 25;
umm g_helicopter_height = 10;

/* NOTE: adjust those values as they will probably not work by default (probably need to be a lot smaller) because they are in meter per second. */
r32 g_gravity = 9.81f;
r32 g_friction = 1.0f;

char HELICOPTERIMAGE[ ] = {
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,15,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,15,15,15,15,15,15,15,-1,-1,-1,-1,
    -1,-1,15,15,15,15,15,15,15,15,15,15,15,-1,-1,-1,-1,15,15,15,15,15,-1,-1,-1,
    -1,-1,-1,-1,-1,15,15,15,15,15,15,-1,-1,-1,-1,-1,-1,-1,15,15,15,15,15,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,15,15,15,15,15,15,15,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,-1,-1,-1,-1,11,-1,-1,-1,-1,11,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,-1,
};

helicopter_t g_helicopters[ 8 ] = { 0 };
particle_t g_particles[ 1024 ] = { 0 };
umm g_particle_count = 0;

void create_particles( helicopter_t* h ) {
    
    b32 particle_available = ( particle_count < array_count( g_particles ) );
    
    for ( umm y = 0; particle_available && y < g_helicopter_height; y++ ) {
        
        umm x = 0;
        
        while( particle_available && x < g_helicopter_width ) {
            
            char c = HELICOPTERIMAGE[ y * g_helicopter_width + x ];
            
            if ( c != -1 ) {
                
                particle_t* p = g_particles + g_particle_count;
                g_particle_count++;
                particle_available = ( particle_count < array_count( g_particles ) );
                
                /* NOTE: this needs to be adjusted:
                - it assume the helicopter position is the top left corner of the sprite;
                - it doesn't take into account the facing direction of the sprite;
                - it assume the the coordinate system of the sprite and game goes down when y increments. */
                p->x = h->x + ( r32 ) x;
                p->y = h->y + ( r32 ) y;
                /* NOTE: to avoid having all particles simulated the same way, we add a random velocity. */
                p->velocity_x = h->velocity_x +  ( r32 ) ( -10 + ( rand( ) % 21 ) ) );
                p->velocity_y = ( r32 ) ( -10 + ( rand( ) % 11 ) );
                
                for ( umm i = 0; i < array_count( p->pixels ); i++ ) {
                    p->pixels[ i ] = -1;
                }
                
                umm max_size = g_helicopter_width - x;
                
                if ( max_size > array_count( p->pixels ) ) {
                    max_size = array_count( p->pixels );
                }
                
                umm size = 1 + ( rand( ) % max_size );
                
                for ( umm i = 0; i < size; i++ ) {
                    
                    p->pixels[ i ] = c;
                    x++;
                    
                    c = HELICOPTERIMAGE[ y * g_helicopter_width + x ];
                    
                    if ( c == -1 ) {
                        break;
                    }
                }
            } else {
                
                x++;
            }
        }
    }
}

void simulate_particle( particle_t* p, r32 time_step ) {
    
    r32 acceleration = g_gravity * time_step;
    p->velocity_y += acceleration;
    
    if ( p->velocity_x > 0 ) {
        p->velocity_x -= g_friction * time_step;
        if ( p->velocity_x < 0 ) {
            p->velocity_x = 0;
        }
    } else if ( p->velocity_x < 0 ) {
        p->velocity_x += g_friction * time_step;
        if ( p->velocity_x > 0 ) {
            p->velocity_x = 0;
        }
    }
    
    p->y += ( p->velocity_y * time_step );
    p->x += ( p->velocity_x * time_step );
}

void render_particle( particle_t* p ) {
    
    for ( umm i = 0; i < array_count( p->pixels ); i++ ) {
        
        char c = p->pixels[ i ];
        
        if ( c != -1 ) {
            frame_buffer_set_pixel( p->x + i, p->y, c );
        } else {
            break;
        }
    }
}

int main( void ) {
    
    srand( time( 0 ) );
    
    while ( g_game_running ) {
        
        /* Game logic here */
        
        for ( umm i = 0; i < array_count( helicopters ); i++ ) {
            
            helicopter_t* h = helicopters + i;
            
            if ( h->explode ) {
                create_particles( h );
                h->active = false;
            }
        }
        
        for ( umm i = 0; i < particle_count; i++ ) {
            
            particle_t* p = particles + i;
            
            simulate_particle( p, time_step );
            render_particle( p );
        }
        
        /* NOTE: remove particles that are out of screen. */
        for ( umm i = 0; i < particle_count; i++ ) {
            
            particle_t* p = particles + i;
            
            if ( p->y > g_screen_width || p->x > g_screen_height || p->x + 4 < 0 ) {
                particle_t* last_particle = particles + ( particle_count - 1 );
                ( *p ) = ( *last_particle );
                particle_count--;
                i--; /* NOTE: to process the particle we just copied. */
            }
        }
    }
    
    return 0;
}