예제 #1
0
void
update_explosions(void)
{
	struct explosion *p;

	for (p = explosions; p != &explosions[MAX_EXPLOSIONS]; p++) {
		if (p->used) {
			if (++p->t >= p->ttl)
				p->used = 0;
			else
				update_explosion(p);
		}
	}
}
예제 #2
0
int main(int argc, char const *argv[])
{
	const int FPS = 60;
	const int MAX_BULLETS = 10;
	const int MAX_ASTEROIDS = 10;
	const int MAX_EXPLOSIONS = 10;
	srand(time(NULL));
	int done = 0;
	int redraw = 1;

	if(!al_init())
	{
		al_show_native_message_box(NULL, "Error", "Error", 
			"Could not initialize Allegro 5.", 0, ALLEGRO_MESSAGEBOX_ERROR);
		return -1;
	}

	ALLEGRO_DISPLAY *display = al_create_display(screen_width, screen_height);
	if(!display)
	{
		al_show_native_message_box(NULL, "Error", "Error", 
			"Could not create display.", 0, ALLEGRO_MESSAGEBOX_ERROR);
		return -1;
	}

	ALLEGRO_EVENT_QUEUE *event_queue = al_create_event_queue();
	if(!event_queue)
	{
		al_show_native_message_box(display, "Error", "Error", 
			"Could not create event queue.", 0, ALLEGRO_MESSAGEBOX_ERROR);
		return -1;
	}

	ALLEGRO_TIMER *timer = al_create_timer(1.0/FPS);
	if(!timer)
	{
		al_show_native_message_box(display, "Error", "Error", 
			"Could not create timer.", 0, ALLEGRO_MESSAGEBOX_ERROR);
		return -1;
	}

	if(!al_install_keyboard())
	{
		al_show_native_message_box(display, "Error", "Error", 
			"Could not install keyboard.", 0, ALLEGRO_MESSAGEBOX_ERROR);
		return -1;
	}

	if(!al_install_mouse())
	{
		al_show_native_message_box(display, "Error", "Error", 
			"Could not install mouse.", 0, ALLEGRO_MESSAGEBOX_ERROR);
		return -1;
	}

	if(!al_init_image_addon())
	{
		al_show_native_message_box(display, "Error", "Error", 
			"Could not initialize image addon.", 0, ALLEGRO_MESSAGEBOX_ERROR);
		return -1;
	}

	if(!al_init_primitives_addon())
	{
		al_show_native_message_box(display, "Error", "Error", 
			"Could not initialize primitives addon.", 0, ALLEGRO_MESSAGEBOX_ERROR);
	}

	al_init_font_addon(); // for whatever reason this function is void returning

	if(!al_init_ttf_addon())
	{
		al_show_native_message_box(display, "Error", "Error", 
			"Could not initialize ttf addon.", 0, ALLEGRO_MESSAGEBOX_ERROR);
	}
	
	al_hide_mouse_cursor(display);

	al_register_event_source(event_queue, al_get_mouse_event_source());
	al_register_event_source(event_queue, al_get_keyboard_event_source());
	al_register_event_source(event_queue, al_get_display_event_source(display));
	al_register_event_source(event_queue, al_get_timer_event_source(timer));

	ALLEGRO_FONT *font18 = al_load_font("Arial.ttf", 18, 0);

	int prev_x = screen_width, prev_y = screen_height;
	int fps_counter = 0;
	int fps_counter2 = 0;
	int i, j, k;

	struct spaceship ship;
	init_ship(&ship);

	struct bullet bullets[MAX_BULLETS];
	for(i = 0; i < MAX_BULLETS; i++)
	{
		init_bullet(&bullets[i]);
	}

	struct asteroid asteroids[MAX_ASTEROIDS];
	for(i = 0; i < MAX_ASTEROIDS; i++)
	{
		init_asteroid(&asteroids[i]);
	}

	struct explosion explosions[MAX_EXPLOSIONS];
	for(i = 0; i < MAX_EXPLOSIONS; i++)
	{
		init_explosion(&explosions[i]);
	}

	al_start_timer(timer);

	while(!done)
	{
		ALLEGRO_EVENT event;
		al_wait_for_event(event_queue, &event);

		if(event.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
		{
			done = 1;
		}
		if(event.type == ALLEGRO_EVENT_KEY_DOWN)
		{
			switch(event.keyboard.keycode)
			{
				case ALLEGRO_KEY_Q: 
					done = 1;
					break;
				case ALLEGRO_KEY_ESCAPE:
					done = 1;
					break;
			}
		}
		if(event.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN)
		{
			if(event.mouse.button & 1)
			{
				for(i = 0; i < MAX_BULLETS; i++)
				{
					if(!bullets[i].live)
					{
						fire_bullet(&bullets[i], ship);
						break;
					}
				}
			}
		}
		if(event.type == ALLEGRO_EVENT_MOUSE_AXES ||
              event.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY)
		{
			set_ship_coordinates(&ship, event.mouse.x, event.mouse.y);
		}
		if(event.type == ALLEGRO_EVENT_TIMER)
		{	
			if(ship.x > prev_x)
			{	
				ship.sprite.dir_horizontal = RIGHT;
			}
			else if(ship.x == prev_x)
			{
				ship.sprite.dir_horizontal = CENTER;
			}
			else if(ship.x < prev_x) 
			{
				ship.sprite.dir_horizontal = LEFT;
			}

			if(ship.y > prev_y)
			{
				ship.sprite.dir_vertical = BACK;
			}
			else if(ship.y == prev_y)
			{
				ship.sprite.dir_vertical = NEUTRAL;
			}
			else if(ship.y < prev_y)
			{
				ship.sprite.dir_vertical = FORWARD;
			}

			if(++fps_counter >= FPS / 5)
			{
				fps_counter = 0;
				prev_x = ship.x;
				prev_y = ship.y;	
			}

			if(++fps_counter2 >= 2 * FPS)
			{
				for(i = 0; i < MAX_ASTEROIDS; i++)
				{
					if(!asteroids[i].live)
					{
						start_asteroid(&asteroids[i]);
						break;
					}
				}
				fps_counter2 = 0;
			}

			for(i = 0; i < MAX_BULLETS; i++)
			{
				if(bullets[i].live)
				{
					update_bullet(&bullets[i]);
				}
			}

			for(i = 0; i < MAX_ASTEROIDS; i++)
			{
				if(asteroids[i].live)
				{
					update_asteroid(&asteroids[i], &ship);
				}
			}

			for(i = 0; i < MAX_EXPLOSIONS; i++)
			{
				if(explosions[i].live)
				{
					update_explosion(&explosions[i]);
				}
			}

			update_ship_boundaries(&ship);

			for(i = 0; i < MAX_BULLETS; i++)
			{
				if(bullets[i].live)
				{
					for(j = 0; j < MAX_ASTEROIDS; j++)
					{
						if(asteroids[j].live)
						{
							if(bullet_and_asteroid_collision(bullets[i], asteroids[j]))
							{
								bullets[i].live = 0;
								asteroids[j].live = 0;
								ship.score += 20;
								for(k = 0; k < MAX_EXPLOSIONS; k++)
								{
									if(!explosions[k].live)
									{
										start_explosion(&explosions[k], bullets[i].x, bullets[i].y);
										break;
									}
								}
							}
						}
					}
				}
			}

			for(i = 0; i < MAX_ASTEROIDS; i++)
			{
				if(asteroids[i].live)
				{
					if(ship_and_asteroid_collision(ship, asteroids[i]))
					{
						asteroids[i].live = 0;
						for(k = 0; k < MAX_EXPLOSIONS; k++)
						{
							if(!explosions[k].live)
							{
								start_explosion(&explosions[k], ship.x, ship.y);
								break;
							}
						}
						
						ship.lives--;
					}
				}
			}

			if(!ship.lives)
			{
				done = true;
			}

			redraw = 1;
		}

		if(redraw)
		{
			redraw = 0;
			draw_ship_sprite(ship.sprite, ship.x, ship.y);
			for(i = 0; i < MAX_BULLETS; i++)
			{
				if(bullets[i].live)
				{
					draw_bullet(bullets[i]);
				}
			}
			for(i = 0; i < MAX_ASTEROIDS; i++)
			{
				if(asteroids[i].live)
				{
					draw_asteroid(asteroids[i]);
				}
			}
			for(i = 0; i < MAX_EXPLOSIONS; i++)
			{
				if(explosions[i].live)
				{
					draw_explosion(explosions[i]);
				}
			}
			al_draw_textf(font18, al_map_rgb(255, 255, 255), 50, 5, 0, 
				"Score: %d ", ship.score); // I have no idea why it doesn't print the S...
			al_draw_textf(font18, al_map_rgb(255, 255, 255), 50, 25, 0, 
				"Lives: %d", ship.lives);
			al_flip_display();
			al_clear_to_color(al_map_rgb(0, 0, 0));
		}
	}

	for(i = 0; i < MAX_ASTEROIDS; i++)
	{
		destroy_asteroid(&asteroids[i]);
	}
	for(i = 0; i < MAX_EXPLOSIONS; i++)
	{
		destroy_explosion(&explosions[i]);
	}
	destroy_sprite(&ship.sprite);
	al_destroy_display(display);
	al_destroy_event_queue(event_queue);
	al_destroy_timer(timer);
	al_destroy_font(font18);

	return 0;
}
예제 #3
0
파일: sx3_engine.c 프로젝트: cout/sx3
// modify_scene modifies the global variables g_projectiles and g_explosions
// during the course of an attack sequence.  It takes a parameter dt which
// represents the amount of time between frames.
// Return: the number of items left to animate.
int modify_scene(float dt)
{
    int i, j, num_impacted;
    float t;
    struct Projectile *p;
    struct Explosion *e;
    struct Tank *tank;
    Vector v;
    float d;

    // Go through all the explosions and update them according to the
    // amount of time passed.
    for(j = 0; j < g_num_explosions; j++)
    {
        e = &g_explosions[j];
        t = update_explosion(e, dt);
    }

    // Go through all the projectiles and handle the ones that have not yet
    // been impacted.
    for(j = 0, num_impacted = 0; j < g_num_projectiles; j++)
    {
        p = &g_projectiles[j];
        if(p->o.state != STATE_IMPACTED)
        {
            t = update_projectile(p, dt);
            if(p->o.state == STATE_IMPACTED)
            {
                printf("Projectile %d has impacted.\n", j);
                // If the projectile has impacted, an explosion needs to be
                // created which is appropriate to the projectile which has
                // impacted, and which takes on properties of the former
                // projectile.
                e = new_explosion(p);

                // Now, using the remaining time that did not get used on the
                // projectile, update the new explosion.
                t = update_explosion(e, dt - t);

                // And play a sound to match
                sx3_play_sound(SX3_AUDIO_EXPLOSION);
            }
        }
        if(p->o.state == STATE_IMPACTED) num_impacted++;
    }

    // FIX ME!! These two checks don't work properly if we have a low
    // framerate.
    for(j = 0; j < g_num_explosions; j++)
    {
        e = &g_explosions[j];
        for(i = 0; i < g_num_tanks; i++)
        {
            tank = &g_tanks[i];
            // Don't check this tank if it's already been hit
            // FIX ME!! This should be on a per-projectile/explosion basis
            if(tank->s.temp_damage != 0.0) continue;

            // Find the distance between the tank and the explosion, and test
            vv_cpy(v, tank->o.props.position);
            vv_sub(v, e->props.position);
            d = v_mag(v);

            if(d < tank->o.props.radius + e->props.radius)
            {
                // A tank has been hit!
                sx3_play_sound(SX3_AUDIO_HIT);
                printf("Tank %d hit by explosion %d\n", i, j);
                // FIX ME!! This should not be constant damage.
                tank->s.temp_damage = 20.0;
            }
        }
    }

    for(j = 0; j < g_num_projectiles; j++)
    {
        p = &g_projectiles[j];
        if(p->o.state == STATE_IMPACTED) continue;
        for(i = 0; i < g_num_tanks; i++)
        {
            tank = &g_tanks[i];
            // Don't check this tank if it's already been hit
            // FIX ME!! This should be on a per-projectile/explosion basis
            if(tank->s.temp_damage != 0.0) continue;

            // Find the distance between the tank and the projectiles, and test
            vv_cpy(v, tank->o.props.position);
            vv_sub(v, p->o.props.position);
            d = v_mag(v);

            if(d < tank->o.props.radius + p->o.props.radius)
            {
                // A tank has been hit!
                sx3_play_sound(SX3_AUDIO_HIT);
                printf("Tank %d hit by projectile %d\n", i, j);
                // FIX ME!! This should not be constant damage.
                tank->s.temp_damage = 40.0;
            }
        }
    }
    return g_num_explosions + g_num_projectiles - num_impacted;
}