📄 loader.c
字号:
if(b->flags & BRICK_FLAG_LARGE_BONUS) i++; if(b->flags & BRICK_FLAG_HUGE_BONUS) i++; /* If there was more than one of the above flags set, print a warning * and cancel all of them: */ if(i > 1) { fprintf(stderr, "Warning: brick flags S, M, L, and H are " "mutually exclusive (see brick \"%c\" on line " "%d of game file \"%s\")\n", b->identifier, line, state->gamefile); b->flags &= ~(BRICK_FLAG_SMALL_BONUS | BRICK_FLAG_LARGE_BONUS | BRICK_FLAG_MEDIUM_BONUS | BRICK_FLAG_HUGE_BONUS); } /* Try to load the sprite for this brick: */ if(!(b->s = load_sprite(state, buf, state->brickwidth, state->brickheight))) { /* It failed, so try to make an empty sprite: */ if(!(b->s = make_empty_sprite(state, buf, state->brickwidth, state->brickheight))) { /* That failed too, so print an error message and * return "failure": */ fprintf(stderr, "Error: failed to create brick " "sprite on line %d of game file \"%s\"\n", line, state->gamefile); free(b); return 1; } /* Fill in the dummy sprite with a solid colour: */ GrSetGCForeground(state->gc, GR_COLOR_BLUE); GrFillRect(b->s->p, state->gc, 0, 0, state->brickwidth, state->brickheight); GrSetGCForeground(state->gc, GR_COLOR_WHITE); GrFillRect(b->s->a, state->gc, 0, 0, state->brickwidth, state->brickheight); } /* If we're in a level definition, link the new brick into the level * specific brick list: */ if(inlevel) { b->next = lev->bricks; lev->bricks = b; } else { /* Otherwise link it into the global brick list: */ b->next = state->bricks; state->bricks = b; } return 0; /* Success. */}/* Create and initialise a new level grid with default parameters. */static grid *newgrid(nbstate *state){ int x, xx, y, yy; grid *g, *gg; /* Allocate the new grid: */ if(!(gg = g = malloc(state->width * state->height * sizeof(grid)))) return NULL; /* Initialise the Y coordinate to the start of the brick area within the * canvas area: */ yy = state->scores.h + state->ball.s->h + (BALLS_BORDER * 2); /* For each row of bricks: */ for(y = 0; y < state->height; y++, yy += state->brickheight) { /* For each brick in the row: */ for(x = 0, xx = 0; x < state->width; x++, xx += state->brickwidth) { /* Initialise the parameters for this grid location: */ g->b = NULL; g->x = xx; g->y = yy; g->hits = 0; g->power = -1; g++; /* Increment to the next grid location. */ } } return gg; /* Return the newly allocated grid. */}/* 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) { fprintf(stderr, "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": */ fprintf(stderr, "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. */}/* 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": */ fprintf(stderr, "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. */ fprintf(stderr, "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: */ fprintf(stderr, "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) { fprintf(stderr, "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) { fprintf(stderr, "Error: Height must be set "
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -