From 20860a4723336805598595fe916ab2709490bc61 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tobias=20Gl=C3=A4=C3=9Fer?= Date: Wed, 31 Dec 2003 02:47:08 +0000 Subject: [PATCH] applied leveleditor and multiline-drawtext patches from Ricardo Cruz and reorganized level-code / NOTE: this is still work in progress SVN-Revision: 85 --- src/gameloop.c | 449 +++++++++++++++++++++++------------------------------- src/level.c | 120 +++++++++++++++ src/level.h | 29 ++++ src/leveleditor.c | 241 ++++++++++++----------------- src/menu.c | 38 ++++- src/menu.h | 2 +- src/screen.c | 16 +- 7 files changed, 479 insertions(+), 416 deletions(-) create mode 100644 src/level.c create mode 100644 src/level.h diff --git a/src/gameloop.c b/src/gameloop.c index 413d9eab2..9c6f3acdb 100644 --- a/src/gameloop.c +++ b/src/gameloop.c @@ -34,6 +34,7 @@ #include "badguy.h" #include "world.h" #include "player.h" +#include "level.h" /* extern variables */ @@ -45,9 +46,8 @@ int score, highscore, distros, level, lives, scroll_x, next_level, game_pause, done, quit, tux_dir, tux_size, tux_duck, tux_x, tux_xm, tux_y, tux_ym, tux_dying, tux_safe, jumping, jump_counter, frame, score_multiplier, tux_frame_main, tux_frame, tux_got_coffee, tux_skidding, -super_bkgd_time, time_left, tux_invincible_time, endpos, +super_bkgd_time, tux_invincible_time, endpos, counting_distros, distro_counter; -int bkgd_red, bkgd_green, bkgd_blue, level_width; int left, right, up, down, fire, old_fire; SDL_Surface * img_brick[2], * img_solid[4], * img_distro[4], * img_waves[3], * img_water, * img_pole, * img_poletop, * img_flag[2]; @@ -79,7 +79,6 @@ SDL_Surface * tux_life, SDL_Event event; SDL_Rect src, dest; SDLKey key; -unsigned char * tiles[15]; bouncy_distro_type bouncy_distros[NUM_BOUNCY_DISTROS]; broken_brick_type broken_bricks[NUM_BROKEN_BRICKS]; bouncy_brick_type bouncy_bricks[NUM_BOUNCY_BRICKS]; @@ -87,16 +86,16 @@ bad_guy_type bad_guys[NUM_BAD_GUYS]; floating_score_type floating_scores[NUM_FLOATING_SCORES]; upgrade_type upgrades[NUM_UPGRADES]; bullet_type bullets[NUM_BULLETS]; -char song_title[60]; -char levelname[60]; -char leveltheme[60]; +st_level current_level; +char level_subset[100]; char str[60]; /* Local function prototypes: */ +void levelintro(void); +void set_default(void); void initgame(void); -void loadlevel(void); void loadlevelgfx(void); void loadlevelsong(void); void unloadlevelgfx(void); @@ -123,10 +122,118 @@ void add_score(int x, int y, int s); void trybumpbadguy(int x, int y, int sx); void add_upgrade(int x, int y, int kind); void killtux(int mode); +void remove_powerups(void); void add_bullet(int x, int y, int dir, int xm); void drawendscreen(void); void drawresultscreen(void); +void levelintro(void) +{ + /* Level Intro: */ + + clearscreen(0, 0, 0); + + sprintf(str, "LEVEL %d", level); + drawcenteredtext(str, 200, letters_red, NO_UPDATE, 1); + + sprintf(str, "%s", current_level.name); + drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1); + + sprintf(str, "TUX x %d", lives); + drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1); + + SDL_Flip(screen); + + SDL_Delay(1000); +} + +void set_defaults(void) +{ + int i; + + /* Reset arrays: */ + + for (i = 0; i < NUM_BOUNCY_DISTROS; i++) + bouncy_distros[i].alive = NO; + + for (i = 0; i < NUM_BROKEN_BRICKS; i++) + broken_bricks[i].alive = NO; + + for (i = 0; i < NUM_BOUNCY_BRICKS; i++) + bouncy_bricks[i].alive = NO; + + for (i = 0; i < NUM_BAD_GUYS; i++) + bad_guys[i].alive = NO; + + for (i = 0; i < NUM_FLOATING_SCORES; i++) + floating_scores[i].alive = NO; + + for (i = 0; i < NUM_UPGRADES; i++) + upgrades[i].alive = NO; + + for (i = 0; i < NUM_BULLETS; i++) + bullets[i].alive = NO; + + + /* Set defaults: */ + + tux_x = 0; + tux_xm = 0; + tux_y = 240; + tux_ym = 0; + tux_dir = RIGHT; + tux_invincible_time = 0; + tux_duck = NO; + + tux_dying = NO; + tux_safe = TUX_SAFE_TIME; + + jumping = NO; + jump_counter = 0; + + tux_skidding = 0; + + scroll_x = 0; + + right = UP; + left = UP; + up = UP; + down = UP; + fire = UP; + old_fire = UP; + + score_multiplier = 1; + super_bkgd_time = 0; + + counting_distros = NO; + distro_counter = 0; + + endpos = 0; + + /* set current song/music */ + current_music = LEVEL_MUSIC; +} + +void activate_bad_guys(void) +{ +int x,y; + + /* Activate bad guys: */ + + for (y = 0; y < 15; y++) + { + for (x = 0; x < current_level.width; x++) + { + if (current_level.tiles[y][x] >= '0' && current_level.tiles[y][x] <= '9') + { + add_bad_guy(x * 32, y * 32, current_level.tiles[y][x] - '0'); + current_level.tiles[y][x] = '.'; + } + } + } + +} + /* --- GAME EVENT! --- */ void game_event(void) @@ -515,7 +622,8 @@ int game_action(void) /* He died :^( */ - lives--; + --lives; + remove_powerups(); /* No more lives!? */ @@ -535,11 +643,14 @@ int game_action(void) /* Either way, (re-)load the (next) level... */ - loadlevel(); + set_defaults(); + loadlevel(¤t_level,"default",level); + activate_bad_guys(); unloadlevelgfx(); loadlevelgfx(); unloadlevelsong(); loadlevelsong(); + levelintro(); } /* Move tux: */ @@ -560,15 +671,15 @@ int game_action(void) scroll_x = 0; } - else if (tux_x > 320 && scroll_x < ((level_width * 32) - 640)) + else if (tux_x > 320 && scroll_x < ((current_level.width * 32) - 640)) { /* Scroll the screen in past center: */ scroll_x = scroll_x + (tux_x - 320); tux_x = 320; - if (scroll_x > ((level_width * 32) - 640)) - scroll_x = ((level_width * 32) - 640); + if (scroll_x > ((current_level.width * 32) - 640)) + scroll_x = ((current_level.width * 32) - 640); } else if (tux_x > 608) { @@ -1093,7 +1204,7 @@ int game_action(void) if (!playing_music()) { - if (time_left <= TIME_WARNING) + if (current_level.time_left <= TIME_WARNING) play_music( level_song_fast, 1 ); else play_music( level_song, 1 ); @@ -1639,7 +1750,7 @@ void game_draw() else { if (super_bkgd_time == 0) - clearscreen(bkgd_red, bkgd_green, bkgd_blue); + clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); else drawimage(img_super_bkgd, 0, 0, NO_UPDATE); } @@ -1652,7 +1763,7 @@ void game_draw() for (x = 0; x < 21; x++) { drawshape(x * 32 - (scroll_x % 32), y * 32, - tiles[y][x + (scroll_x / 32)]); + current_level.tiles[y][x + (scroll_x / 32)]); } } @@ -1672,9 +1783,9 @@ void game_draw() dest.h = 32; SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, - bkgd_red, - bkgd_green, - bkgd_blue)); + current_level.bkgd_red, + current_level.bkgd_green, + current_level.bkgd_blue)); drawshape(bouncy_bricks[i].x - scroll_x, bouncy_bricks[i].y + bouncy_bricks[i].offset, @@ -2218,9 +2329,9 @@ void game_draw() drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE, 1); drawtext(str, 96, 20, letters_gold, NO_UPDATE, 1); - if (time_left >= TIME_WARNING || (frame % 10) < 5) + if (current_level.time_left >= TIME_WARNING || (frame % 10) < 5) { - sprintf(str, "%d", time_left); + sprintf(str, "%d", current_level.time_left); drawtext("TIME", 224, 0, letters_blue, NO_UPDATE, 1); drawtext(str, 304, 0, letters_gold, NO_UPDATE, 1); } @@ -2272,12 +2383,15 @@ int gameloop(void) tux_size = SMALL; tux_got_coffee = NO; - loadlevel(); + set_defaults(); + loadlevel(¤t_level,"default",level); loadlevelgfx(); + activate_bad_guys(); loadlevelsong(); highscore = load_hs(); - + levelintro(); + /* --- MAIN GAME LOOP!!! --- */ done = 0; @@ -2325,7 +2439,7 @@ int gameloop(void) switch (current_music) { case LEVEL_MUSIC: - if (time_left <= TIME_WARNING) + if (current_level.time_left <= TIME_WARNING) play_music(level_song_fast, 1); else play_music(level_song, 1); @@ -2355,15 +2469,15 @@ int gameloop(void) /* Handle time: */ - if ((frame % 10) == 0 && time_left > 0) + if ((frame % 10) == 0 && current_level.time_left > 0) { - time_left--; + current_level.time_left--; /* Stop the music; it will start again, faster! */ - if (time_left == TIME_WARNING) + if (current_level.time_left == TIME_WARNING) halt_music(); - if (time_left <= 0) + if (current_level.time_left <= 0) killtux(KILL); } } @@ -2390,230 +2504,28 @@ void initgame(void) lives = 3; } +/* Load graphics: */ - -/* Load data for this level: */ - -void loadlevel(void) -{ - int i, x, y; - FILE * fi; - char * filename; - char str[80]; - char * line; - - - /* Reset arrays: */ - - for (i = 0; i < NUM_BOUNCY_DISTROS; i++) - bouncy_distros[i].alive = NO; - - for (i = 0; i < NUM_BROKEN_BRICKS; i++) - broken_bricks[i].alive = NO; - - for (i = 0; i < NUM_BOUNCY_BRICKS; i++) - bouncy_bricks[i].alive = NO; - - for (i = 0; i < NUM_BAD_GUYS; i++) - bad_guys[i].alive = NO; - - for (i = 0; i < NUM_FLOATING_SCORES; i++) - floating_scores[i].alive = NO; - - for (i = 0; i < NUM_UPGRADES; i++) - upgrades[i].alive = NO; - - for (i = 0; i < NUM_BULLETS; i++) - bullets[i].alive = NO; - - - /* Load data file: */ - - filename = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + 20)); - sprintf(filename, "%s/levels/level%d.dat", DATA_PREFIX, level); - fi = fopen(filename, "r"); - if (fi == NULL) - { - perror(filename); - st_shutdown(); - free(filename); - exit(-1); - } - free(filename); - - - /* Load header info: */ - - - /* (Level title) */ - fgets(str, 20, fi); - strcpy(levelname, str); - levelname[strlen(levelname)-1] = '\0'; - - /* (Level theme) */ - fgets(str, 20, fi); - strcpy(leveltheme, str); - leveltheme[strlen(leveltheme)-1] = '\0'; - - - - /* (Time to beat level) */ - fgets(str, 10, fi); - time_left = atoi(str); - - /* (Song file for this level) */ - fgets(str, sizeof(song_title), fi); - strcpy(song_title, str); - song_title[strlen(song_title)-1] = '\0'; - - - - /* (Level background color) */ - fgets(str, 10, fi); - bkgd_red = atoi(str); - fgets(str, 10, fi); - bkgd_green= atoi(str); - fgets(str, 10, fi); - bkgd_blue = atoi(str); - - /* (Level width) */ - fgets(str, 10, fi); - level_width = atoi(str); - - - /* Allocate some space for the line-reading! */ - - line = (char *) malloc(sizeof(char) * (level_width + 5)); - if (line == NULL) - { - fprintf(stderr, "Couldn't allocate space to load level data!"); - exit(1); - } - - - /* Load the level lines: */ - - for (y = 0; y < 15; y++) - { - if(fgets(line, level_width + 5, fi) == NULL) - { - fprintf(stderr, "Level %s isn't complete!\n",levelname); - exit(1); - } - line[strlen(line) - 1] = '\0'; - tiles[y] = strdup(line); - } - - fclose(fi); - - - /* Activate bad guys: */ - - for (y = 0; y < 15; y++) - { - for (x = 0; x < level_width; x++) - { - if (tiles[y][x] >= '0' && tiles[y][x] <= '9') - { - add_bad_guy(x * 32, y * 32, tiles[y][x] - '0'); - tiles[y][x] = '.'; - } - } - } - - - /* Set defaults: */ - - tux_x = 0; - tux_xm = 0; - tux_y = 240; - tux_ym = 0; - tux_dir = RIGHT; - tux_invincible_time = 0; - tux_duck = NO; - - tux_dying = NO; - tux_safe = TUX_SAFE_TIME; - - jumping = NO; - jump_counter = 0; - - tux_skidding = 0; - - scroll_x = 0; - - right = UP; - left = UP; - up = UP; - down = UP; - fire = UP; - old_fire = UP; - - score_multiplier = 1; - super_bkgd_time = 0; - - counting_distros = NO; - distro_counter = 0; - - endpos = 0; - - /* set current song/music */ - current_music = LEVEL_MUSIC; - - /* Level Intro: */ - - clearscreen(0, 0, 0); - - sprintf(str, "LEVEL %d", level); - drawcenteredtext(str, 200, letters_red, NO_UPDATE, 1); - - sprintf(str, "%s", levelname); - drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1); - - sprintf(str, "TUX x %d", lives); - drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1); - - SDL_Flip(screen); - - SDL_Delay(1000); - - -} - - -/* Load a level-specific graphic... */ - -SDL_Surface * load_level_image(char * file, int use_alpha) +void loadlevelgfx(void) { - char fname[1024]; - - snprintf(fname, 1024, "%s/images/themes/%s/%s", DATA_PREFIX, leveltheme, file); - return(load_image(fname, use_alpha)); -} + img_brick[0] = load_level_image(current_level.theme,"brick0.png", IGNORE_ALPHA); + img_brick[1] = load_level_image(current_level.theme,"brick1.png", IGNORE_ALPHA); + img_solid[0] = load_level_image(current_level.theme,"solid0.png", USE_ALPHA); + img_solid[1] = load_level_image(current_level.theme,"solid1.png", USE_ALPHA); + img_solid[2] = load_level_image(current_level.theme,"solid2.png", USE_ALPHA); + img_solid[3] = load_level_image(current_level.theme,"solid3.png", USE_ALPHA); -/* Load graphics: */ + img_bkgd[0][0] = load_level_image(current_level.theme,"bkgd-00.png", USE_ALPHA); + img_bkgd[0][1] = load_level_image(current_level.theme,"bkgd-01.png", USE_ALPHA); + img_bkgd[0][2] = load_level_image(current_level.theme,"bkgd-02.png", USE_ALPHA); + img_bkgd[0][3] = load_level_image(current_level.theme,"bkgd-03.png", USE_ALPHA); -void loadlevelgfx(void) -{ - img_brick[0] = load_level_image("brick0.png", IGNORE_ALPHA); - img_brick[1] = load_level_image("brick1.png", IGNORE_ALPHA); - - img_solid[0] = load_level_image("solid0.png", USE_ALPHA); - img_solid[1] = load_level_image("solid1.png", USE_ALPHA); - img_solid[2] = load_level_image("solid2.png", USE_ALPHA); - img_solid[3] = load_level_image("solid3.png", USE_ALPHA); - - img_bkgd[0][0] = load_level_image("bkgd-00.png", USE_ALPHA); - img_bkgd[0][1] = load_level_image("bkgd-01.png", USE_ALPHA); - img_bkgd[0][2] = load_level_image("bkgd-02.png", USE_ALPHA); - img_bkgd[0][3] = load_level_image("bkgd-03.png", USE_ALPHA); - - img_bkgd[1][0] = load_level_image("bkgd-10.png", USE_ALPHA); - img_bkgd[1][1] = load_level_image("bkgd-11.png", USE_ALPHA); - img_bkgd[1][2] = load_level_image("bkgd-12.png", USE_ALPHA); - img_bkgd[1][3] = load_level_image("bkgd-13.png", USE_ALPHA); + img_bkgd[1][0] = load_level_image(current_level.theme,"bkgd-10.png", USE_ALPHA); + img_bkgd[1][1] = load_level_image(current_level.theme,"bkgd-11.png", USE_ALPHA); + img_bkgd[1][2] = load_level_image(current_level.theme,"bkgd-12.png", USE_ALPHA); + img_bkgd[1][3] = load_level_image(current_level.theme,"bkgd-13.png", USE_ALPHA); } @@ -2626,17 +2538,17 @@ void loadlevelsong(void) char * song_subtitle; song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + - strlen(song_title) + 8)); - sprintf(song_path, "%s/music/%s", DATA_PREFIX, song_title); + strlen(current_level.song_title) + 8)); + sprintf(song_path, "%s/music/%s", DATA_PREFIX, current_level.song_title); level_song = load_song(song_path); free(song_path); song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + - strlen(song_title) + 8 + 5)); - song_subtitle = strdup(song_title); + strlen(current_level.song_title) + 8 + 5)); + song_subtitle = strdup(current_level.song_title); strcpy(strstr(song_subtitle, "."), "\0"); - sprintf(song_path, "%s/music/%s-fast%s", DATA_PREFIX, song_subtitle, strstr(song_title, ".")); + sprintf(song_path, "%s/music/%s-fast%s", DATA_PREFIX, song_subtitle, strstr(current_level.song_title, ".")); level_song_fast = load_song(song_path); free(song_subtitle); free(song_path); @@ -3264,17 +3176,19 @@ void drawshape(int x, int y, unsigned char c) unsigned char shape(int x, int y, int sx) { + int xx, yy; unsigned char c; - + yy = (y / 32); xx = ((x + sx) / 32); + - if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width) - c = tiles[yy][xx]; + if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width) + c = current_level.tiles[yy][xx]; else c = '.'; - + return(c); } @@ -3378,8 +3292,8 @@ void change(int x, int y, int sx, unsigned char c) yy = (y / 32); xx = ((x + sx) / 32); - if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width) - tiles[yy][xx] = c; + if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width) + current_level.tiles[yy][xx] = c; } @@ -3739,6 +3653,13 @@ void add_upgrade(int x, int y, int kind) } } +/* Remove Tux's power ups */ +void remove_powerups(void) +{ + tux_got_coffee = NO; + tux_size = SMALL; +} + /* Kill tux! */ @@ -3839,8 +3760,7 @@ void drawresultscreen(void) drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1); SDL_Flip(screen); - /*SDL_Delay(2000);*/ - sleep(2); + SDL_Delay(2000); } void savegame(void) @@ -3870,6 +3790,7 @@ void savegame(void) fwrite(&tux_x,4,1,fi); fwrite(&tux_y,4,1,fi); fwrite(&scroll_x,4,1,fi); + fwrite(¤t_level.time_left,4,1,fi); } fclose(fi); @@ -3895,13 +3816,23 @@ void loadgame(char* filename) } else - { + { + set_defaults(); + loadlevel(¤t_level,"default",level); + activate_bad_guys(); + unloadlevelgfx(); + loadlevelgfx(); + unloadlevelsong(); + loadlevelsong(); + levelintro(); + fread(&level,4,1,fi); fread(&score,4,1,fi); fread(&distros,4,1,fi); fread(&tux_x,4,1,fi); fread(&tux_y,4,1,fi); fread(&scroll_x,4,1,fi); + fread(¤t_level.time_left,4,1,fi); fclose(fi); } diff --git a/src/level.c b/src/level.c new file mode 100644 index 000000000..6df811d24 --- /dev/null +++ b/src/level.c @@ -0,0 +1,120 @@ +// +// C Implementation: level +// +// Description: +// +// +// Author: Tobias Glaesser , (C) 2003 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include +#include +#include +#include "setup.h" +#include "screen.h" +#include "level.h" + +/* Load data for this level: */ + +void loadlevel(st_level* plevel, char *subset, int level) +{ + int y; + FILE * fi; + char str[80]; + char * filename; + char * line; + + /* Load data file: */ + + filename = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + 20) + strlen(subset)); + sprintf(filename, "%s/levels/%s/level%d.dat", DATA_PREFIX, subset, level); + fi = fopen(filename, "r"); + if (fi == NULL) + { + perror(filename); + st_shutdown(); + free(filename); + exit(-1); + } + free(filename); + + + /* Load header info: */ + + + /* (Level title) */ + fgets(str, 20, fi); + strcpy(plevel->name, str); + plevel->name[strlen(plevel->name)-1] = '\0'; + + /* (Level theme) */ + fgets(str, 20, fi); + strcpy(plevel->theme, str); + plevel->theme[strlen(plevel->theme)-1] = '\0'; + + + + /* (Time to beat level) */ + fgets(str, 10, fi); + plevel->time_left = atoi(str); + + /* (Song file for this level) */ + fgets(str, sizeof(plevel->song_title), fi); + strcpy(plevel->song_title, str); + plevel->song_title[strlen(plevel->song_title)-1] = '\0'; + + + + /* (Level background color) */ + fgets(str, 10, fi); + plevel->bkgd_red = atoi(str); + fgets(str, 10, fi); + plevel->bkgd_green= atoi(str); + fgets(str, 10, fi); + plevel->bkgd_blue = atoi(str); + + /* (Level width) */ + fgets(str, 10, fi); + plevel->width = atoi(str); + + + /* Allocate some space for the line-reading! */ + + line = (char *) malloc(sizeof(char) * (plevel->width + 5)); + if (line == NULL) + { + fprintf(stderr, "Couldn't allocate space to load level data!"); + exit(1); + } + + + /* Load the level lines: */ + + for (y = 0; y < 15; y++) + { + if(fgets(line, plevel->width + 5, fi) == NULL) + { + fprintf(stderr, "Level %s isn't complete!\n",plevel->name); + exit(1); + } + line[strlen(line) - 1] = '\0'; + plevel->tiles[y] = strdup(line); + } + + fclose(fi); + +} + +/* Load a level-specific graphic... */ + +SDL_Surface * load_level_image(char* theme, char * file, int use_alpha) +{ + char fname[2024]; + + snprintf(fname, 21024, "%simages/themes/%s/%s", DATA_PREFIX, theme, file); + + return(load_image(fname, use_alpha)); +} diff --git a/src/level.h b/src/level.h new file mode 100644 index 000000000..4d9f14b42 --- /dev/null +++ b/src/level.h @@ -0,0 +1,29 @@ +// +// C Interface: level +// +// Description: +// +// +// Author: Tobias Glaesser , (C) 2003 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +typedef struct st_level /*It is easier to read the sources IMHO, if we don't write something like int a,b,c; */ + { + char name[100]; + char theme[100]; + char song_title[100]; + unsigned char* tiles[15]; + int time_left; + int bkgd_red; + int bkgd_green; + int bkgd_blue; + int width; + } st_level; + +void loadlevel(st_level* plevel, char * subset, int level); +SDL_Surface * load_level_image(char* theme, char * file, int use_alpha); + + diff --git a/src/leveleditor.c b/src/leveleditor.c index 7c4be0fee..5c15090bf 100644 --- a/src/leveleditor.c +++ b/src/leveleditor.c @@ -28,22 +28,9 @@ #include "globals.h" #include "setup.h" #include "menu.h" - +#include "level.h" #include "badguy.h" -char levelname[60]; -char leveltheme[60]; -bad_guy_type bad_guys[NUM_BAD_GUYS]; -SDL_Surface *img_bsod_left[4], *img_laptop_left[3], *img_money_left[2]; -char song_title[60]; -char levelfilename[100]; - -int time_left; -unsigned char* tiles[15]; -int bkgd_red, bkgd_green, bkgd_blue, level_width; - -SDL_Surface *selection; - /* definitions to aid development */ #define DONE_LEVELEDITOR 1 #define DONE_QUIT 2 @@ -59,6 +46,32 @@ SDL_Surface *selection; #define MOUSE_RIGHT_MARGIN 608 #define MOUSE_POS_SPEED 32 + /* Level Intro: */ +/* + clearscreen(0, 0, 0); + + sprintf(str, "Editing Level %s", levelfilename); + drawcenteredtext(str, 200, letters_red, NO_UPDATE, 1); + + sprintf(str, "%s", levelname); + drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1); + + SDL_Flip(screen); + + SDL_Delay(1000); +*/ + +/* global variables (based on the gameloop ones) */ + +bad_guy_type bad_guys[NUM_BAD_GUYS]; +SDL_Surface *img_bsod_left[4], *img_laptop_left[3], *img_money_left[2]; +int level; +st_level current_level; +char level_subset[100]; + +int frame; +SDL_Surface *selection; + /* gameloop funcs declerations */ void loadlevelgfx(void); @@ -74,6 +87,31 @@ void savelevel(); void le_loadlevel(void); void le_change(int x, int y, int sx, unsigned char c); void showhelp(); +void le_set_defaults(void); +void le_activate_bad_guys(void); + +void le_activate_bad_guys(void) +{ +int x,y; + + /* Activate bad guys: */ + + /* as oposed to the gameloop.c func, this one doesn't remove + the badguys from tiles */ + + for (y = 0; y < 15; ++y) + for (x = 0; x < current_level.width; ++x) + if (current_level.tiles[y][x] >= '0' && current_level.tiles[y][x] <= '9') + add_bad_guy(x * 32, y * 32, current_level.tiles[y][x] - '0'); +} + +void le_set_defaults() +{ + /* Set defaults: */ + + if(current_level.time_left == 0) + current_level.time_left = 255; +} /* FIXME: Needs to be implemented. It should ask the user for the level(file)name and then let him create a new level based on this. */ void newlevel() @@ -94,18 +132,25 @@ int leveleditor() SDL_Event event; SDLKey key; SDLMod keymod; + + strcpy(level_subset,"default"); - - strcpy(levelfilename,"level1"); + level = 1; initmenu(); menumenu = MENU_LEVELEDITOR; show_menu = YES; + int last_time, now_time; + frame = 0; /* support for frames in some tiles, like waves and bad guys */ + loadshared(); - le_loadlevel(); + loadlevel(¤t_level,"default",level); loadlevelgfx(); + le_activate_bad_guys(); + le_set_defaults(); + selection = load_image(DATA_PREFIX "/images/leveleditor/select.png", USE_ALPHA); done = 0; @@ -119,8 +164,11 @@ int leveleditor() while(1) { - SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, bkgd_red, bkgd_green, bkgd_blue)); + SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue)); + last_time = SDL_GetTicks(); + frame++; + keymod = SDL_GetModState(); while(SDL_PollEvent(&event)) @@ -152,8 +200,8 @@ int leveleditor() else cursor_x += KEY_CURSOR_FASTSPEED; - if(cursor_x > (level_width*32) - 1) - cursor_x = (level_width*32) - 1; + if(cursor_x > (current_level.width*32) - 1) + cursor_x = (current_level.width*32) - 1; break; case SDLK_UP: if(fire == DOWN) @@ -183,7 +231,7 @@ int leveleditor() cursor_x = 0; break; case SDLK_END: - cursor_x = (level_width * 32) - 32; + cursor_x = (current_level.width * 32) - 32; break; case SDLK_PERIOD: le_change(cursor_x, cursor_y, 0, '.'); @@ -401,14 +449,14 @@ int leveleditor() if(pos_x < 0) pos_x = 0; - if(pos_x > (level_width * 32) - 640) - pos_x = (level_width * 32) - 640; + if(pos_x > (current_level.width * 32) - 640) + pos_x = (current_level.width * 32) - 640; old_cursor_x = cursor_x; for (y = 0; y < 15; ++y) for (x = 0; x < 21; ++x) - drawshape(x * 32, y * 32, tiles[y][x + (pos_x / 32)]); + drawshape(x * 32, y * 32, current_level.tiles[y][x + (pos_x / 32)]); /* Draw the Bad guys: */ for (i = 0; i < NUM_BAD_GUYS; ++i) @@ -418,21 +466,21 @@ int leveleditor() continue; /* to support frames: img_bsod_left[(frame / 5) % 4] */ if(bad_guys[i].kind == BAD_BSOD) - drawimage(img_bsod_left[0], ((int)(bad_guys[i].x - pos_x)/32)*32, bad_guys[i].y, NO_UPDATE); + drawimage(img_bsod_left[(frame / 5) % 4], ((int)(bad_guys[i].x - pos_x)/32)*32, bad_guys[i].y, NO_UPDATE); else if(bad_guys[i].kind == BAD_LAPTOP) - drawimage(img_laptop_left[0], ((int)(bad_guys[i].x - pos_x)/32)*32, bad_guys[i].y, NO_UPDATE); + drawimage(img_laptop_left[(frame / 5) % 3], ((int)(bad_guys[i].x - pos_x)/32)*32, bad_guys[i].y, NO_UPDATE); else if (bad_guys[i].kind == BAD_MONEY) - drawimage(img_money_left[0], ((int)(bad_guys[i].x - pos_x)/32)*32, bad_guys[i].y, NO_UPDATE); + drawimage(img_money_left[(frame / 5) % 2], ((int)(bad_guys[i].x - pos_x)/32)*32, bad_guys[i].y, NO_UPDATE); } drawimage(selection, ((int)(cursor_x - pos_x)/32)*32, cursor_y, NO_UPDATE); - sprintf(str, "%d", time_left); + sprintf(str, "%d", current_level.time_left); drawtext("TIME", 324, 0, letters_blue, NO_UPDATE, 1); drawtext(str, 404, 0, letters_gold, NO_UPDATE, 1); - sprintf(str, "%s", levelname); + sprintf(str, "%s", current_level.name); drawtext("NAME", 0, 0, letters_blue, NO_UPDATE, 1); drawtext(str, 80, 0, letters_gold, NO_UPDATE, 1); @@ -448,6 +496,10 @@ int leveleditor() return 1; SDL_Delay(50); + now_time = SDL_GetTicks(); + if (now_time < last_time + FPS) + SDL_Delay(last_time + FPS - now_time); /* delay some time */ + SDL_Flip(screen); } @@ -456,12 +508,6 @@ int leveleditor() SDL_FreeSurface(selection); - /*if(done == DONE_SAVE)*/ /* let's save the changes */ - /* savelevel();*/ - /* - if(done == DONE_CHANGELEVEL) change level - return leveleditor(level); - */ return done; } @@ -480,8 +526,8 @@ void le_change(int x, int y, int sx, unsigned char c) bad_guys[i].alive = NO; - if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width) - tiles[yy][xx] = c; + if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width) + current_level.tiles[yy][xx] = c; } /* Save data for this level: */ @@ -494,8 +540,8 @@ void savelevel(void) /* Save data file: */ - filename = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + 20)); - sprintf(filename, "%s/levels/%s.dat", DATA_PREFIX, levelfilename); + filename = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + 20) + strlen(level_subset)); + sprintf(filename, "%s/levels/%s/level%d.dat", DATA_PREFIX, level_subset, level); fi = fopen(filename, "w"); if (fi == NULL) { @@ -509,25 +555,25 @@ void savelevel(void) /* sptrinf("# Level created by SuperTux built-in editor", fi); */ - fputs(levelname, fi); + fputs(current_level.name, fi); fputs("\n", fi); - fputs(leveltheme, fi); + fputs(current_level.theme, fi); fputs("\n", fi); - sprintf(str, "%d\n", time_left); /* time */ + sprintf(str, "%d\n", current_level.time_left); /* time */ fputs(str, fi); - fputs(song_title, fi); /* song filename */ - sprintf(str, "%d\n", bkgd_red); /* red background color */ + fputs(current_level.song_title, fi); /* song filename */ + sprintf(str, "\n%d\n", current_level.bkgd_red); /* red background color */ fputs(str, fi); - sprintf(str, "%d\n", bkgd_green); /* green background color */ + sprintf(str, "%d\n", current_level.bkgd_green); /* green background color */ fputs(str, fi); - sprintf(str, "%d\n", bkgd_blue); /* blue background color */ + sprintf(str, "%d\n", current_level.bkgd_blue); /* blue background color */ fputs(str, fi); - sprintf(str, "%d\n", level_width); /* level width */ + sprintf(str, "%d\n", current_level.width); /* level width */ fputs(str, fi); for(y = 0; y < 15; ++y) { - fputs(tiles[y], fi); + fputs(current_level.tiles[y], fi); fputs("\n", fi); } @@ -538,105 +584,6 @@ void savelevel(void) SDL_Delay(1000); } - -/* I had to copy loadlevel, because loadlevel changes the tiles. - For intance, badguys are removed from the tiles and we have to - keep them there. */ - -/* Load data for this level: */ - -void le_loadlevel(void) -{ - FILE * fi; - char * filename; - int x, y; - char str[80]; - char* line = malloc(sizeof(char)*10);/*[LEVEL_WIDTH + 5];*/ - - /* Load data file: */ - - filename = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + 20)); - sprintf(filename, "%s/levels/%s.dat", DATA_PREFIX, levelfilename); - fi = fopen(filename, "r"); - if (fi == NULL) - { - perror(filename); - st_shutdown(); - free(filename); - exit(-1); - } - free(filename); - - /* (Level title) */ - fgets(str, 20, fi); - strcpy(levelname, str); - levelname[strlen(levelname)-1] = '\0'; - - /* (Level theme) */ - fgets(str, 20, fi); - strcpy(leveltheme, str); - leveltheme[strlen(leveltheme)-1] = '\0'; - - fgets(line, 10, fi); - time_left = atoi(line); - fgets(str, 60, fi); - song_title[0]='\0'; - strcpy(song_title,str); - fgets(line, 10, fi); - bkgd_red = atoi(line); - fgets(line, 10, fi); - bkgd_green= atoi(line); - fgets(line, 10, fi); - bkgd_blue = atoi(line); - fgets(line, 10, fi); - level_width = atoi(line); - - free(line); - line = malloc(level_width*sizeof(char)+5); - - for (y = 0; y < 15; ++y) - { - fgets(line, level_width + 5, fi); - line[strlen(line) - 1] = '\0'; - free(tiles[y]); - tiles[y] = malloc((strlen(line)+5)*sizeof(char)); - strcpy(tiles[y], line); - } - - fclose(fi); - - /* Activate bad guys: */ - - /* as oposed to the gameloop.c func, this one doesn't remove - the badguys from tiles */ - - for (y = 0; y < 15; ++y) - for (x = 0; x < level_width; ++x) - if (tiles[y][x] >= '0' && tiles[y][x] <= '9') - add_bad_guy(x * 32, y * 32, tiles[y][x] - '0'); - - - /* Set defaults: */ - - if(time_left == 0) - time_left = 255; - - - /* Level Intro: */ - - clearscreen(0, 0, 0); - - sprintf(str, "Editing Level %s", levelfilename); - drawcenteredtext(str, 200, letters_red, NO_UPDATE, 1); - - sprintf(str, "%s", levelname); - drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1); - - SDL_Flip(screen); - - SDL_Delay(1000); -} - void showhelp() { SDL_Event event; diff --git a/src/menu.c b/src/menu.c index 09e242a81..2ac0fe370 100644 --- a/src/menu.c +++ b/src/menu.c @@ -23,6 +23,7 @@ #include "setup.h" #include "sound.h" #include "leveleditor.h" +#include "gameloop.h" /* Set defaults */ void initmenu(void) @@ -236,10 +237,35 @@ int menu_game(void) } else drawcenteredtext("Return To Game", 192, letters_blue, NO_UPDATE, 2); - + if(menuitem == 1) { - drawcenteredtext("Options", 224, letters_red, NO_UPDATE, 2); + drawcenteredtext("Save Game", 224, letters_red, NO_UPDATE, 2); + if(menuaction == MN_HIT) /* Don't show the menu anymore, if this item got hit */ + { + show_menu = 0; + savegame(); + } + } + else + drawcenteredtext("Save Game", 224, letters_blue, NO_UPDATE, 2); + + if(menuitem == 2) + { + drawcenteredtext("Load Game", 256, letters_red, NO_UPDATE, 2); + if(menuaction == MN_HIT) /* Don't show the menu anymore, if this item got hit */ + { + show_menu = 0; + char *x = NULL; + loadgame(x); + } + } + else + drawcenteredtext("Load Game", 256, letters_blue, NO_UPDATE, 2); + + if(menuitem == 3) + { + drawcenteredtext("Options", 288, letters_red, NO_UPDATE, 2); if(menuaction == MN_HIT) /* Switch to the 'Options' menu */ { menumenu = MENU_OPTIONS; @@ -247,17 +273,17 @@ int menu_game(void) } } else - drawcenteredtext("Options", 224, letters_blue, NO_UPDATE, 2); + drawcenteredtext("Options", 288, letters_blue, NO_UPDATE, 2); - if(menuitem == 2) + if(menuitem == 4) { - drawcenteredtext("Quit Game", 256, letters_red, NO_UPDATE, 2); + drawcenteredtext("Quit Game", 320, letters_red, NO_UPDATE, 2); if(menuaction == MN_HIT) /* Quit a running game */ return 1; } else { - drawcenteredtext("Quit Game", 256, letters_blue, NO_UPDATE, 2); + drawcenteredtext("Quit Game", 320, letters_blue, NO_UPDATE, 2); } return 0; diff --git a/src/menu.h b/src/menu.h index 0d9dc41ea..233481eb4 100644 --- a/src/menu.h +++ b/src/menu.h @@ -23,7 +23,7 @@ int show_menu; int menu_change; #define MENU_MAIN_ITEM_MAX 3 -#define MENU_GAME_ITEM_MAX 2 +#define MENU_GAME_ITEM_MAX 4 #define MENU_OPTIONS_ITEM_MAX 3 #define MENU_LEVELEDITOR_ITEM_MAX 4 diff --git a/src/screen.c b/src/screen.c index aa20abdf6..aebb7aaa7 100644 --- a/src/screen.c +++ b/src/screen.c @@ -62,17 +62,19 @@ void updatescreen(void) SDL_Surface * load_image(char * file, int use_alpha) { + SDL_Surface * temp, * surf; temp = IMG_Load(file); + if (temp == NULL) st_abort("Can't load", file); - + surf = SDL_DisplayFormatAlpha(temp); if (surf == NULL) st_abort("Can't covert to display format", file); - + if (use_alpha == IGNORE_ALPHA) SDL_SetAlpha(surf, 0, 0); @@ -126,7 +128,9 @@ void drawpart(SDL_Surface * surf, int x, int y, int w, int h, int update) void drawtext(char * text, int x, int y, SDL_Surface * surf, int update, int shadowsize) { - int i; + /* i - helps to keep tracking of the all string length + j - helps to keep track of the length of the current line */ + int i, j; char c; SDL_Rect src, dest; @@ -166,6 +170,12 @@ void drawtext(char * text, int x, int y, SDL_Surface * surf, int update, int sha src.x = 400; src.y = 24; } + else if (c == '\n') /* support for multi-lines */ + { + j = i + 1; + y += 18; + continue; + } else src.x = -1; -- 2.11.0