Ejemplo n.º 1
0
static void cleanup_title(struct game_title* title)
{
    destroy_sprite(title->sprite);
    destroy_animation(title->bling);
    destroy_image(title->spot);
    destroy_image(title->mask);
}
Ejemplo n.º 2
0
int animate_sprite(Sprite *fig, float delta , int hor){
	Sprite *sp2 = (Sprite *) malloc ( sizeof(Sprite));
	sp2 = fig;
	destroy_sprite(fig);
	if(hor) sp2->x += delta;
	else sp2->y +=delta;
	draw_sprite(sp2);
}
Ejemplo n.º 3
0
/* Destroying a wizard means destroying each and every
 * created resource in the **create\_wizard** function.
 * If we fail to do so, we will introduce a memory leak
 * to the game.
 */
static void destroy_wizard(struct wizard* wizard)
{
    if (wizard != NULL) {
        destroy_animation(wizard->walk_right);
        destroy_animation(wizard->spell);
        destroy_animation(wizard->stand);
        destroy_image(wizard->sprite->image);
        destroy_sprite(wizard->sprite);
        free(wizard);
    }
}
Ejemplo n.º 4
0
/* load_sprite: load all the sprites in SPRITE_INDEX and their graphics */
void load_sprites(void)
{
    size_t i, y;
    char bmpname[NAME_LN];
    scew_tree *t = NULL;
    scew_parser *p = NULL;
    scew_element *e = NULL;
    scew_element *r = NULL;
    SPRITE *s = NULL;

    /* setup the parser */
    p = scew_parser_create();
    scew_parser_ignore_whitespaces(p, 1);
    if (!scew_parser_load_file(p, SPRITE_INDEX)) {
        printf("%s\n", scew_error_expat_string(scew_error_code()));
        return;
    }
    t = scew_parser_tree(p);
    r = scew_tree_root(t);
    s = create_sprite();

    /* read all the sprites from SPRITE_INDEX */
    /* parse the SPRITE_INDEX file and outline the list with their names */
    e = scew_element_next(r, e);
    while (e) {
        strncpy(s->long_name, (char *) scew_element_name(e), LONG_NAME_LN);
        s->x = s->y = 0;
        sprite_list = append_sprite_list(s, sprite_list, &sprite_list_sz);
        e = scew_element_next(r, e);
    }

    /* load all their graphics and the sprite data */
    gfx_list = complete_sprite_list(sprite_list, sprite_list_sz, gfx_list,
                                    &gfx_list_sz);

    /* create a list_element for each of them and put them in a list */
    y = SPRITE_WIN.y;
    for (i = 0; i < sprite_list_sz; i++) {
        sprintf(bmpname, "%s0", sprite_list[i].name);
        spr_elem_lst = add_list_element(rec(SPRITE_WIN.x, y, LIST_ELEM_W,
                                            LIST_ELEM_H), 0, DEFAULT_COLOR,
                                        SEL_COLOR, sprite_list[i].name,
                                        search_gfx_list(bmpname, gfx_list,
                                                        gfx_list_sz),
                                        spr_elem_lst, &spr_elem_lst_sz);
        y += LIST_ELEM_H;
    }

    /* cleanup */
    scew_element_free(r);
    destroy_sprite(s);
    scew_element_free(e);
    scew_parser_free(p);
}
Ejemplo n.º 5
0
static int prepare_tree(struct tree* tree)
{
    tree->sprite = create_sprite(create_image("res/tree.png"), 32, 32);
    if (tree->sprite == NULL) goto cleanup_sprite;
    tree->windblow = create_animation();
    if (tree->windblow == NULL) goto cleanup_animation;
    add_frame(tree->windblow, 0, 1 * SECOND, NULL);
    add_frame(tree->windblow, 1, 1 * SECOND, NULL);
    tree->windblow->loop_from = 0;
    tree->windblow->loop_to = 1;
    return 0;

cleanup_animation:
    destroy_animation(tree->windblow);
cleanup_sprite:
    destroy_sprite(tree->sprite);
error:
    ERROR("Unable to prepare tree");
    return -1;
}
Ejemplo n.º 6
0
static void cleanup_tree(struct tree* tree)
{
    destroy_sprite(tree->sprite);
    destroy_animation(tree->windblow);
}
Ejemplo n.º 7
0
void zombie_racer(int start_x, int start_y) {
	sprite_id racetrack = generate_racetrack();
	int x = start_x;
	int y = start_y;

	int dir = 0; // Start facing North.

	bool alive = on_racetrack(x, y);
	update_view(racetrack, x, y, alive);
	int key = wait_char();

	while ((key != 'q') && (key >= 0) && alive) {
		switch (key) {
			case '1':
				dir = (dir + 7) % 8;
				break;
			case '3':
				dir = (dir + 1) % 8;
				break;
		}
		
		switch (dir) {
			case 0:
				y--;
				break;
			case 1:
				y--;
				x++;
				break;
			case 2:
				x++;
				break;
			case 3:
				x++;
				y++;
				break;
			case 4:
				y++;
				break;
			case 5:
				y++;
				x--;
				break;
			case 6:
				x--;
				break;
			case 7:
				x--;
				y--;
				break;
		}

		alive = on_racetrack(x, y);
		update_view(racetrack, x, y, alive);
		timer_pause(100);
		key = wait_char();
	}
	
	free(racetrack->bitmap);
	racetrack->bitmap = NULL;
	destroy_sprite(racetrack);
	
	timer_pause(1000);
}
Ejemplo n.º 8
0
void cleanup_ten_squares( sprite_id sprites[] ) {
	for ( int i = 0; i < SPR_COUNT; i++ ) {
		destroy_sprite( sprites[i] );
	}
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
0
/* Load the game file. */
int load_game_file(nbstate *state)
{
	FILE *fp;
	int line = 1;
	level *l, *lev = NULL;
	char buf[256], *p;
	int inlevelblock = 0;

	/* Generate the full game file name including the directory: */
	snprintf(buf, 256, "%s/%s", state->gamedir, state->gamefile);

	/* Try to open the game file: */
	if(!(fp = fopen(buf, "r"))) {
		/* It failed, so print an error message and return "failure": */
		GrError("Failed to open game file \"%s\": %s\n",
						buf, strerror(errno));
		return 1;
	}

	/* Read the file one line at a time in a loop: */
	while(fgets(buf, 256, fp)) {

		/* Look for the newline at the end of the line. */
		if(!(p = strchr(buf, '\n'))) {
			/* There wasn't one, which probably means that the
			 * line was longer than 255 characters. */
			GrError("Too long line on line %d of game file "
					"\"%s\"\n", line, state->gamefile);
			return 1;
		}
		*p = 0; /* Get rid of the newline. */

		/* Ignore comments and blank lines: */
		if(*buf == '#' || *buf == 0) {
		/* Compare the line against each of the different keywords: */
		} else if(!memcmp(buf, "TitleBackground ", 16)) {
			if(state->titlebackground) {
				redefinewarning("TitleBackground", line,
						state->gamefile);
				free(state->titlebackground);
			}
			if(!(state->titlebackground = strdup(buf + 16))) {
				oom();
				goto err;
			}
		} else if(!memcmp(buf, "TitleBackgroundTiled ", 21)) {
			/* Check whether the parameter to TitleBackgroundTiled
			 * is "Yes" (1), "No" (0), or something else (parse
			 * error): */
			if(!strcmp(buf + 21, "Yes"))
				state->backgroundtiled = 1;
			else if(!strcmp(buf + 21, "No"))
				state->backgroundtiled = 0;
			else goto parseerr;
		} else if(!memcmp(buf, "TitleSplash ", 12)) {
			if(state->titlesplash) {
				redefinewarning("TitleSplash", line,
						state->gamefile);
				free(state->titlesplash);
			}
			if(!(state->titlesplash = strdup(buf + 12))) {
				oom();
				goto err;
			}
		} else if(!memcmp(buf, "GameWonSplash ", 14)) {
			if(state->gamewonsplash) {
				redefinewarning("GameWonSplash", line,
						state->gamefile);
				free(state->gamewonsplash);
			}
			if(!(state->gamewonsplash = strdup(buf + 14))) {
				oom();
				goto err;
			}
		} else if(!memcmp(buf, "GameLostSplash ", 15)) {
			if(state->gamelostsplash) {
				redefinewarning("GameLostSplash", line,
						state->gamefile);
				free(state->gamelostsplash);
			}
			if(!(state->gamelostsplash = strdup(buf + 15))) {
				oom();
				goto err;
			}
		} else if(!memcmp(buf, "NormalPoints ", 13)) {
			/* Convert the parameter to NormalPoints into a
			 * number: */
			state->normalpoints = strtol(buf + 13, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "SmallBonusPoints ", 17)) {
			state->smallbonuspoints = strtol(buf + 17, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "MediumBonusPoints ", 18)) {
			state->mediumbonuspoints = strtol(buf + 18, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "LargeBonusPoints ", 17)) {
			state->largebonuspoints = strtol(buf + 17, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "HugeBonusPoints ", 16)) {
			state->hugebonuspoints = strtol(buf + 16, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "PowerUpPoints ", 14)) {
			state->poweruppoints = strtol(buf + 14, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "PowerDownPoints ", 16)) {
			state->powerdownpoints = strtol(buf + 16, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "StartBalls ", 11)) {
			state->startballs = strtol(buf + 11, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "NewLevelBalls ", 14)) {
			state->newlevelballs = strtol(buf + 14, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "BallImage ", 10)) {
			/* If the ball sprite has already been defined, print
			 * a warning and destroy the old sprite: */
			if(state->ball.s) {
				redefinewarning("BallImage", line,
						state->gamefile);
				destroy_sprite(state, state->ball.s);
			}
			/* Try to load the ball sprite: */
			if(!(state->ball.s = load_sprite(state, buf + 10,
								-1, -1))) {
				/* That failed so try to make an empty one: */
				if(!(state->ball.s = make_empty_sprite(state,
							buf + 10,
							DEFAULT_BALL_SIZE,
							DEFAULT_BALL_SIZE))) {
					/* That failed too so print an error
					 * message and give up: */
					GrError("Couldn't create "
							"ball sprite on line "
							"%d of game file "
							"\"%s\"\n", line,
							state->gamefile);
					goto err;
				}
				/* Fill in the dummy sprite with a white
				 * circle: */
				GrSetGCForeground(state->gc, GR_COLOR_WHITE);
				GrFillEllipse(state->ball.s->p, state->gc,
							DEFAULT_BALL_SIZE / 2,
							DEFAULT_BALL_SIZE / 2,
						(DEFAULT_BALL_SIZE / 2) - 1,
						(DEFAULT_BALL_SIZE / 2) - 1);
				GrFillEllipse(state->ball.s->a, state->gc,
							DEFAULT_BALL_SIZE / 2,
							DEFAULT_BALL_SIZE / 2,
						(DEFAULT_BALL_SIZE / 2) - 1,
						(DEFAULT_BALL_SIZE / 2) - 1);
			}
		} else if(!memcmp(buf, "SlowBallVelocity ", 17)) {
			state->ball.sv = strtol(buf + 17, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "NormalBallVelocity ", 19)) {
			state->ball.nv = strtol(buf + 19, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "FastBallVelocity ", 17)) {
			state->ball.fv = strtol(buf + 17, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "BatVelocity ", 12)) {
			state->batv = strtol(buf + 12, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "PowerVelocity ", 14)) {
			state->powerv = strtol(buf + 14, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "AnimatePeriod ", 14)) {
			state->animateperiod = strtol(buf + 14, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "BrickWidth ", 11)) {
			state->brickwidth = strtol(buf + 11, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "BrickHeight ", 12)) {
			state->brickheight = strtol(buf + 12, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "Brick ", 6)) {
			/* Parse the brick line: */
			if(parse_brick(state, inlevelblock, lev, line, buf + 6))
				goto err;
		} else if(!memcmp(buf, "Width ", 6)) {
			if(lev) {
				GrError("Error: Width must be set "
					"before the first level is defined "
					"(see line %d of game file \"%s\")\n",
					line, state->gamefile);
				goto err;
			}
			state->width = strtol(buf + 6, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "Height ", 7)) {
			if(lev) {
				GrError("Error: Height must be set "
					"before the first level is defined "
					"(see line %d of game file \"%s\")\n",
					line, state->gamefile);
				goto err;
			}
			state->height = strtol(buf + 7, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "BatHeight ", 10)) {
			state->batheight = strtol(buf + 10, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "NormalBatWidth ", 15)) {
			state->batwidths[NORMALBAT] = strtol(buf + 15, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "SmallBatWidth ", 14)) {
			state->batwidths[SMALLBAT] = strtol(buf + 14, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "LargeBatWidth ", 14)) {
			state->batwidths[LARGEBAT] = strtol(buf + 14, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "NormalBat ", 10)) {
			if(state->bats[NORMALBAT]) {
				redefinewarning("NormalBat", line,
						state->gamefile);
				destroy_sprite(state, state->bats[NORMALBAT]);
			}
			if(!(state->bats[NORMALBAT] = load_sprite(state,
					buf + 10, state->batwidths[NORMALBAT],
					state->batheight))) {
				if(!(state->bats[NORMALBAT] =
					make_empty_sprite(state, buf + 10,
						state->batwidths[NORMALBAT],
						state->batheight))) {
					GrError("Couldn't create "
							"normal bat sprite on "
							"line %d of game file "
							"\"%s\"\n", line,
							state->gamefile);
					goto err;
				}
				GrSetGCForeground(state->gc, GR_COLOR_RED);
				GrFillRect(state->bats[NORMALBAT]->p,
						state->gc, 0, 0,
						state->batwidths[NORMALBAT],
						state->batheight);
				GrSetGCForeground(state->gc, GR_COLOR_WHITE);
				GrFillRect(state->bats[NORMALBAT]->a,
						state->gc, 0, 0,
						state->batwidths[NORMALBAT],
						state->batheight);
			}
		} else if(!memcmp(buf, "SmallBat ", 9)) {
			if(state->bats[SMALLBAT]) {
				redefinewarning("SmallBat", line,
						state->gamefile);
				destroy_sprite(state, state->bats[SMALLBAT]);
			}
			if(!(state->bats[SMALLBAT] = load_sprite(state,
					buf + 9, state->batwidths[SMALLBAT],
					state->batheight))) {
				if(!(state->bats[SMALLBAT] =
					make_empty_sprite(state, buf + 9,
						state->batwidths[SMALLBAT],
						state->batheight))) {
					GrError("Couldn't create "
							"small bat sprite on "
							"line %d of game file "
							"\"%s\"\n", line,
							state->gamefile);
					goto err;
				}
				GrSetGCForeground(state->gc, GR_COLOR_RED);
				GrFillRect(state->bats[SMALLBAT]->p,
						state->gc, 0, 0,
						state->batwidths[SMALLBAT],
						state->batheight);
				GrSetGCForeground(state->gc, GR_COLOR_WHITE);
				GrFillRect(state->bats[SMALLBAT]->a,
						state->gc, 0, 0,
						state->batwidths[SMALLBAT],
						state->batheight);
			}
		} else if(!memcmp(buf, "LargeBat ", 9)) {
			if(state->bats[LARGEBAT]) {
				redefinewarning("LargeBat", line,
						state->gamefile);
				destroy_sprite(state, state->bats[LARGEBAT]);
			}
			if(!(state->bats[LARGEBAT] = load_sprite(state,
					buf + 9, state->batwidths[LARGEBAT],
					state->batheight))) {
				if(!(state->bats[LARGEBAT] =
					make_empty_sprite(state, buf + 9,
						state->batwidths[LARGEBAT],
						state->batheight))) {
					GrError("Couldn't create "
							"large bat sprite on "
							"line %d of game file "
							"\"%s\"\n", line,
							state->gamefile);
					goto err;
				}
				GrSetGCForeground(state->gc, GR_COLOR_RED);
				GrFillRect(state->bats[LARGEBAT]->p,
						state->gc, 0, 0,
						state->batwidths[LARGEBAT],
						state->batheight);
				GrSetGCForeground(state->gc, GR_COLOR_WHITE);
				GrFillRect(state->bats[LARGEBAT]->a,
						state->gc, 0, 0,
						state->batwidths[LARGEBAT],
						state->batheight);
			}
		} else if(!memcmp(buf, "PowerSprite ", 12)) {
			/* Parse the PowerSprite line: */
			if(parse_powersprite(state, buf + 12, line)) goto err;
		} else if(!memcmp(buf, "PowerUpTimeout ", 15)) {
			state->poweruptime = strtol(buf + 15, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "PowerDownTimeout ", 17)) {
			state->powerdowntime = strtol(buf + 17, &p, 10);
			if(*p) goto parseerr;
		} else if(!memcmp(buf, "FadeRate ", 9)) {
			state->faderate = strtol(buf + 9, &p, 10);
			if(*p) goto parseerr;
			if(state->faderate > 255 || state->faderate < 0) {
				GrError("Invalid fade rate on line "
					"%d of game file \"%s\"\n", line,
					state->gamefile);
				goto err;
			}
		} else if(!memcmp(buf, "SolidFloorCheat ", 16)) {
			if(state->cheats[SFCHEAT]) {
				redefinewarning("SolidFloorCheat", line,
						state->gamefile);
				free(state->cheats[SFCHEAT]);
			}
			if(!(state->cheats[SFCHEAT] = strdup(buf + 16))) {
				oom();
				goto err;
			}
			if(strlen(state->cheats[SFCHEAT]) > MAXCHEATLEN) {
				GrError("Cheat sequence too long on "
						"line %d of game file \"%s\"\n",
						line, state->gamefile);
				goto err;
			}
		} else if(!memcmp(buf, "TeleportCheat ", 14)) {
			if(state->cheats[TPCHEAT]) {
				redefinewarning("TeleportCheat", line,
						state->gamefile);
				free(state->cheats[TPCHEAT]);
			}
			if(!(state->cheats[TPCHEAT] = strdup(buf + 14))) {
				oom();
				goto err;
			}
			if(strlen(state->cheats[TPCHEAT]) > MAXCHEATLEN) {
				GrError("Cheat sequence too long on "
						"line %d of game file \"%s\"\n",
						line, state->gamefile);
				goto err;
			}
		} else if(!memcmp(buf, "NoBounceCheat ", 14)) {
			if(state->cheats[NBCHEAT]) {
				redefinewarning("NoBounceCheat", line,
						state->gamefile);
				free(state->cheats[NBCHEAT]);
			}
			if(!(state->cheats[NBCHEAT] = strdup(buf + 14))) {
				oom();
				goto err;
			}
			if(strlen(state->cheats[NBCHEAT]) > MAXCHEATLEN) {
				GrError("Cheat sequence too long on "
						"line %d of game file \"%s\"\n",
						line, state->gamefile);
				goto err;
			}

		} else if(!memcmp(buf, "NoPowerDownCheat ", 17)) {
			if(state->cheats[NPDCHEAT]) {
				redefinewarning("NoPowerDownCheat", line,
						state->gamefile);
				free(state->cheats[NPDCHEAT]);
			}
			if(!(state->cheats[NPDCHEAT] = strdup(buf + 17))) {
				oom();
				goto err;
			}
			if(strlen(state->cheats[NPDCHEAT]) > MAXCHEATLEN) {
				GrError("Cheat sequence too long on "
						"line %d of game file \"%s\"\n",
						line, state->gamefile);
				goto err;
			}

		} else if(!memcmp(buf, "NoPowerUpTimeoutCheat ", 22)) {
			if(state->cheats[NPUTOCHEAT]) {
				redefinewarning("NoPowerUpTimeoutCheat", line,
						state->gamefile);
				free(state->cheats[NPUTOCHEAT]);
			}
			if(!(state->cheats[NPUTOCHEAT] = strdup(buf + 22))) {
				oom();
				goto err;
			}
			if(strlen(state->cheats[NPUTOCHEAT]) > MAXCHEATLEN) {
				GrError("Cheat sequence too long on "
						"line %d of game file \"%s\"\n",
						line, state->gamefile);
				goto err;
			}
		} else if(!memcmp(buf, "BeginLevel", 10)) {

			/* Check to make sure we haven't got another BeginLevel
			 * line while already in a level definition block: */
			if(inlevelblock) {
				GrError("Error: BeginLevel while "
					"already in a level block on line %d "
					"of game file \"%s\"\n", line,
					state->gamefile);
				goto err;
			}
			inlevelblock = 1;

			/* Allocate a new level structure: */
			if(!(lev = malloc(sizeof(level)))) {
				oom();
				goto err;
			}
			/* Fill in the structure members with some defaults: */
			lev->bricks = NULL;
			lev->backgroundname = NULL;
			lev->backgroundtiled = DEFAULT_BACKGROUND_TILED;
			lev->numbricks = 0;
			lev->next = NULL;

			/* Allocate and initialise the level grid: */
			if(!(lev->grid = newgrid(state))) {
				oom();
				goto err;
			}

			/* Link the new level structure onto the end of the
			 * levels list: */
			if(!state->levels) state->levels = lev;
			else {
				for(l = state->levels; l->next; l = l->next);
				l->next = lev;
			}
		} else if(!memcmp(buf, "LevelBackground ", 16)) {
			if(!inlevelblock) {
				notinlevblockerr("LevelBackground", line,
						state->gamefile);
				goto err;
			}
			if(lev->backgroundname) {
				redefinewarning("LevelBackground", line,
						state->gamefile);
				free(lev->backgroundname);
			}
			if(!(lev->backgroundname = strdup(buf + 16))) {
				oom();
				goto err;
			}
		} else if(!memcmp(buf, "LevelBackgroundTiled ", 21)) {
			if(!inlevelblock) {
				notinlevblockerr("LevelBackgroundTiled", line,
						state->gamefile);
				goto err;
			}
			if(!strcmp(buf + 21, "Yes")) lev->backgroundtiled = 1;
			else if(!strcmp(buf + 21, "No"))
				lev->backgroundtiled = 0;
			else goto parseerr;
		} else if(!memcmp(buf, "BeginRows", 9)) {
			if(!inlevelblock) {
				notinlevblockerr("BeginRows", line,
						state->gamefile);
				goto err;
			}
			/* Parse the rows block: */
			if(parse_rows(state, lev, fp, &line)) goto err;
		} else if(!memcmp(buf, "EndRows", 7)) {
			/* We should never see an EndRows here in a valid
			 * level file because parse_rows() consumes it. */
			GrError("Error: EndRows without corresponding "
					"BeginRows on line %d of game file "
					"\"%s\"\n", line, state->gamefile);
			goto err;
		} else if(!memcmp(buf, "BeginPowers", 11)) {
			if(!inlevelblock) {
				notinlevblockerr("BeginPowers", line,
						state->gamefile);
				goto err;
			}
			if(parse_powers(state, lev, fp, &line)) goto err;
		} else if(!memcmp(buf, "EndPowers", 9)) {
			GrError("Error: EndPowers without "
					"corresponding BeginPowers on line %d "
					"of game file \"%s\"\n", line,
					state->gamefile);
			goto err;
		} else if(!memcmp(buf, "EndLevel", 8)) {
			if(!inlevelblock) {
				GrError("Error: EndLevel while not in "
					"in a level block on line %d of game "
					"file \"%s\"\n", line, state->gamefile);
				goto err;
			}
			inlevelblock = 0;
			state->numlevels++;
		} else {
			GrError("Unknown command \"%s\" on line %d "
					"of game file \"%s\"\n", buf,
					line, state->gamefile);
		}
		/* We keep a count of the line we're on so that errors and
		 * warnings can print out the number of the bad line: */
		line++;
	}

	/* Check if the reason fgets() failed was because of an I/O error
	 * instead of simply reaching the end of the file: */
	if(ferror(fp)) {
		GrError("Error reading from game file \"%s\" on line "
				"%d: %s\n", state->gamefile, line,
				strerror(errno));
		goto err;
	}

	/* Allocate and initialise the current game grid: */
	if(!(state->grid = newgrid(state))) {
		oom();
		goto err;
	}

	fclose(fp); /* Close the game file. */

	return 0; /* Success. */

parseerr: /* A parse error occured so print an error message: */
	GrError("Parse error on line %d of game file \"%s\"\n", line,
							state->gamefile);
err: /* Some other error occured and we've already printed the error message. */
	fclose(fp); /* Close the game file (may fail but we don't care). */
	return 1; /* Failure. */
}
Ejemplo n.º 11
0
/* Parse a PowerSprite line. */
static int parse_powersprite(nbstate *state, char *buf, int line)
{
	sprite *s;
	int power;

	/* Determine which power is being referred to: */
	switch(*buf) {
		case 'W':
			power = POWERW;
			break;
		case 'S':
			power = POWERS;
			break;
		case 'T':
			power = POWERT;
			break;
		case 'P':
			power = POWERP;
			break;
		case 'N':
			power = POWERN;
			break;
		case 'F':
			power = POWERF;
			break;
		default:
			power = NOPOWER;
	}

	/* If it wasn't a valid power identifier, print an error message and
	 * return "failure": */
	if(power == NOPOWER) {
		GrError("Invalid power \"%c\" on line %d of game file "
				"\"%s\"\n", *buf, line, state->gamefile);
		return 1;
	}

	/* If this power sprite has already been defined, print a warning and
	 * destroy the old sprite: */
	if(state->powersprites[power]) {
		redefinewarning("PowerSprite", line, state->gamefile);
		destroy_sprite(state, state->powersprites[power]);
	}

	/* Try to load the image for this power sprite: */
	if(!(s = load_sprite(state, buf + 2, -1, -1))) {
		/* If that failed, try making an empty sprite: */
		if(!(s = make_empty_sprite(state, buf + 2, DEFAULT_POWER_WIDTH,
						DEFAULT_POWER_HEIGHT))) {
			/* That failed too, so print an error message and
			 * return "failure": */
			GrError("Error: failed to create power sprite "
					"on line %d of game file \"%s\"\n",
					line, state->gamefile);
			return 1;
		}
		/* If it's a power-up, fill the power rectangle in green;
		 * if it's a power-down, fill it in red: */
		if(power == POWERW || power == POWERS || power == POWERT ||
				power == POWERP)
			GrSetGCForeground(state->gc, GR_COLOR_GREEN);
		else GrSetGCForeground(state->gc, GR_COLOR_RED);
		GrFillRect(s->p, state->gc, 0, 0, DEFAULT_POWER_WIDTH,
						DEFAULT_POWER_HEIGHT);
		GrSetGCForeground(state->gc, GR_COLOR_WHITE);
		GrFillRect(s->a, state->gc, 0, 0, DEFAULT_POWER_WIDTH,
						DEFAULT_POWER_HEIGHT);
	}

	/* Set this power sprite to the newly created sprite. */
	state->powersprites[power] = s;

	return 0; /* Success. */
}
Ejemplo n.º 12
0
void destroy_naves() {
	destroy_sprite(nave_parada);
	destroy_sprite(nave_esquerda);
	destroy_sprite(nave_direita);
}
Ejemplo n.º 13
0
ENTRYPOINT void
draw_slideshow (ModeInfo *mi)
{
  slideshow_state *ss = &sss[MI_SCREEN(mi)];
  int i;

  if (!ss->glx_context)
    return;

  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(ss->glx_context));

  if (ss->awaiting_first_image_p)
    {
      image *img = ss->images[0];
      if (!img) abort();
      if (!img->loaded_p)
        return;

      ss->awaiting_first_image_p = False;
      ss->dawn_of_time = double_time();

      /* start the very first sprite fading in */
      new_sprite (mi);
    }

  ss->now = double_time();

  /* Each sprite has three states: fading in, full, fading out.
     The in/out states overlap like this:

     iiiiiiFFFFFFFFFFFFoooooo  . . . . . . . . . . . . . . . . . 
     . . . . . . . . . iiiiiiFFFFFFFFFFFFoooooo  . . . . . . . .
     . . . . . . . . . . . . . . . . . . iiiiiiFFFFFFFFFFFFooooo

     So as soon as a sprite goes into the "out" state, we create
     a new sprite (in the "in" state.)
   */

  if (ss->nsprites > 2) abort();

  /* If a sprite is just entering the fade-out state,
     then add a new sprite in the fade-in state.
   */
  for (i = 0; i < ss->nsprites; i++)
    {
      sprite *sp = ss->sprites[i];
      if (sp->state != sp->prev_state &&
          sp->state == (fade_seconds == 0 ? DEAD : OUT))
        new_sprite (mi);
    }

  tick_sprites (mi);

  /* Now garbage collect the dead sprites.
   */
  for (i = 0; i < ss->nsprites; i++)
    {
      sprite *sp = ss->sprites[i];
      if (sp->state == DEAD)
        {
          destroy_sprite (mi, sp);
          i--;
        }
    }

  /* We can only ever end up with no sprites at all if the machine is
     being really slow and we hopped states directly from FULL to DEAD
     without passing OUT... */
  if (ss->nsprites == 0)
    new_sprite (mi);

  if (!ss->redisplay_needed_p)
    return;

  if (debug_p && ss->now - ss->prev_frame_time > 1)
    fprintf (stderr, "%s: static screen for %.1f secs\n",
             blurb(), ss->now - ss->prev_frame_time);

  draw_sprites (mi);

  if (mi->fps_p) do_fps (mi);

  glFinish();
  glXSwapBuffers (MI_DISPLAY (mi), MI_WINDOW(mi));
  ss->prev_frame_time = ss->now;
  ss->redisplay_needed_p = False;
  check_fps (mi);
}
Ejemplo n.º 14
0
/* Make the current level active. This mainly consists of destroying the old
 * background image and loading the new one, destroying the splash image,
 * possibly loading a new splash image depending on the state, copying over the
 * new level data into the current level state, then redrawing the entire game
 * area. */
void set_level_active(nbstate *state)
{
	int i;
	level *lev;
	grid *g, *gg;
	int bgchanged;
	sprite *s = NULL;
	power *p, *pnext;
	GR_PIXMAP_ID ctmp;
	char *backgroundfile;

	/* Destroy the old splash image sprite: */
	destroy_sprite(state, state->splash);

	/* If we're on the title screen: */
	if(state->state == STATE_TITLESCREEN) {
		/* Set the background file to the title background file: */
		backgroundfile = state->titlebackground;
		/* Set the tiled state appropriately: */
		state->backgroundtiled = state->titlebackgroundtiled;
		/* Try to load the title screen splash graphic (if it doesn't
		 * work nothing bad will happen- load_sprite() will print an
		 * error message and draw_splash() will not draw anything.) */
		state->splash = load_sprite(state, state->titlesplash, -1, -1);
	} else { /* Not on the title screen. */
		/* Find the level structure for the current level number: */
		for(lev = state->levels, i = 1; i < state->level;
				lev = lev->next, i++);
		/* Set the current number of bricks and background info: */
		state->numbricks = lev->numbricks;
		backgroundfile = lev->backgroundname;
		state->backgroundtiled = lev->backgroundtiled;
		/* If we're in the "game won" state, try to load the appropriate
		 * splash image: */
		if(state->state == STATE_GAMEWON) {
			state->splash = load_sprite(state, state->gamewonsplash,
									-1, -1);
		/* If we're in the "game lost" state, try to load the
		 * appropriate splash image: */
		} else if(state->state == STATE_GAMELOST) {
			state->splash = load_sprite(state,
						state->gamelostsplash, -1, -1);
		} else { /* We must be in the STATE_RUNNING state. */
			/* No splash image: */
			state->splash = NULL;
			/* Copy this levels game grid into the current game
			 * grid: */
			g = state->grid;
			gg = lev->grid;
			for(i = 0; i < state->width * state->height; i++)
				*g++ = *gg++;
		}
	}

	/* If there was a background filename specified: */
	if(backgroundfile) {
		/* If there is a current background sprite with a filename
		 * and the filename is the same as the new background
		 * filename, the background file has not changed. Otherwise,
		 * assume that it has. */
		if(state->background && state->background->fname &&
				!strcmp(backgroundfile,
					state->background->fname))
			bgchanged = 0;
		else bgchanged = 1;
	/* No background filename was specified, so assume it has changed (to
	 * a blank black frame): */
	} else bgchanged = 1;

	/* If the background image has changed, try to load the new one: */
	if(bgchanged && !(s = load_sprite(state, backgroundfile, -1, -1))) {
		/* If it fails, try to make a new empty sprite and colour it
		 * in black (the 16*16 pixels is purely arbitrary- make it too
		 * large and it uses a lot of memory, make it too small and
		 * we spend ages painting hundreds of tiny tiles onto the
		 * background. */
		if(!(s = make_empty_sprite(state, backgroundfile, 16, 16))) {
			/* If that fails too (shouldn't happen under normal
			 * circumstances), issue a warning and keep the old
			 * background image sprite: */
			s = state->background;
		} else {
			/* Fill in the new dummy background black: */
			GrSetGCForeground(state->gc, GR_COLOR_BLACK);
			GrFillRect(s->p, state->gc, 0, 0, 16, 16);
			/* Make it tiled. FIXME: it would make more sense to
			 * have a "no background image" option which simply
			 * coloured in the background black: */
			state->backgroundtiled = 1;
		}
	}

	/* If we have made a new background image sprite: */
	if(bgchanged && s != state->background) {
		/* Destroy the old one: */
		destroy_sprite(state, state->background);
		/* Set the background to the new sprite: */
		state->background = s;
	}

	/* Empty the list of power boxes: */
	for(p = state->powers; p; p = pnext) {
		pnext = p->next;
		free(p);
	}
	state->powers = NULL;

	/* If fading has been requested, we want to fade the new level in, so
	 * swap the canvasses around so the current screen is the old canvas,
	 * then draw the new screen and make the new canvas, then start the
	 * process of fading it in: */
	if(state->faderate) {
		/* Swap the canvasses around: */
		ctmp = state->oldcanvas;
		state->oldcanvas = state->canvas;
		state->canvas = ctmp;

		/* Remember the state we're fading into: */
		state->nextstate = state->state;

		/* Go into the fading state: */
		state->state= STATE_FADING;

		/* Initialise the fade level as completely opaque: */
		state->fadelevel = 256;
	}

	/* Clear the whole game area to the background image: */
	draw_background(state, 0, 0, state->canvaswidth, state->canvasheight);

	/* If we're not on the title screen or fading to the title screen: */
	if(state->state != STATE_TITLESCREEN && !(state->state == STATE_FADING
				&& state->nextstate == STATE_TITLESCREEN)) {
		/* Draw the bricks: */
		draw_bricks(state, 0, 0, state->canvaswidth,
						state->canvasheight);
		draw_scores(state); /* Draw the scores bar. */
		draw_balls(state); /* Draw the row of balls. */
		draw_bat(state); /* Draw the bat. */
		/* Draw the current ball unless the game is over: */
		if(state->state != STATE_GAMELOST &&
				state->state != STATE_GAMEWON)
			draw_ball(state);
	}

	draw_splash(state); /* Draw the splash graphic (if there is one). */

	/* If we're fading, remember the new canvas and generate the first
	 * frame of the fade: */
	if(state->state == STATE_FADING) {

		/* Swap the canvasses around: */
		ctmp = state->newcanvas;
		state->newcanvas = state->canvas;
		state->canvas = ctmp;

		/* Reduce the opacity: */
		state->fadelevel -= state->faderate;

		/* Generate the first frame: */
		GrCopyArea(state->canvas, state->gc, 0, 0, state->canvaswidth,
				state->canvasheight, state->newcanvas, 0, 0, 0);
		GrCopyArea(state->canvas, state->gc, 0, 0, state->canvaswidth,
				state->canvasheight, state->oldcanvas, 0, 0,
				GR_CONST_BLEND | state->fadelevel);
	}

	/* Copy the entire redrawn canvas to the output window: */
	draw_canvas(state, 0, 0, state->canvaswidth, state->canvasheight);
}