static void cleanup_title(struct game_title* title) { destroy_sprite(title->sprite); destroy_animation(title->bling); destroy_image(title->spot); destroy_image(title->mask); }
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); }
/* 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); } }
/* 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); }
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; }
static void cleanup_tree(struct tree* tree) { destroy_sprite(tree->sprite); destroy_animation(tree->windblow); }
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); }
void cleanup_ten_squares( sprite_id sprites[] ) { for ( int i = 0; i < SPR_COUNT; i++ ) { destroy_sprite( sprites[i] ); } }
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; }
/* 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. */ }
/* 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. */ }
void destroy_naves() { destroy_sprite(nave_parada); destroy_sprite(nave_esquerda); destroy_sprite(nave_direita); }
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); }
/* 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); }