*** empty log message ***
authorMatthew Mondor <mmondor@pulsar-zone.net>
Tue, 9 Jan 2007 01:49:10 +0000 (01:49 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Tue, 9 Jan 2007 01:49:10 +0000 (01:49 +0000)
mmsoftware/paradise_adventure/src/main.c

index 9a90954..312c4be 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.9 2007/01/08 11:46:57 mmondor Exp $ */
+/* $Id: main.c,v 1.10 2007/01/09 01:49:10 mmondor Exp $ */
 
 /*
  * Copyright (c) 2006, Matthew Mondor
 
 #define FADEOUT_DELAY  1000
 
+#define TEXT_WIDTH     185
+#define TEXT_LINE_SIZE 256
+
 struct scene {
        const char      *img, *mus;
        int             vol;
+       const char      *text;
 };
 
 struct font {
@@ -41,6 +45,12 @@ struct font {
        TTF_Font        *fnt;
 };
 
+typedef struct text {
+       TTF_Font        *fnt;
+       int             numlines, alloclines;
+       char            **lines;
+} text_t;
+
 
 
 /* PRIVATE PROTOTYPES */
@@ -48,12 +58,16 @@ struct font {
 int                    main(int, char **);
 
 static void            screen_draw(void);
-static void            scene_switch(const char *, const char *, int);
+static void            scene_switch(const char *, const char *, int,
+                           const char *);
 static void            scene_next(void);
 
 static void            fonts_load(void);
 static TTF_Font                *font_next(void);
 
+static text_t          *text_create(TTF_Font *, const char *);
+static void            text_free(text_t *);
+
 
 
 /* PUBLIC GLOBALS */
@@ -72,12 +86,23 @@ static Mix_Music    *music = NULL;
 static char            *painting_file = NULL, *music_file = NULL;
 
 static const struct scene scenes[] = {
-       { "gardens_smallbridge",        "adventure1",   128 },
-       { "forest_entry",               "forest",       128 },
-       { "dungeon_deadend",            "cavern",       128 },
-       { "gardens_house",              "castle",       128 },
-       { "mountains_landscape",        "aria_prima",   85  },
-       { NULL, NULL }
+       { "gardens_smallbridge",        "adventure1",   128,
+               "The water is calm.  Far ahead can be seen a bridge at the "
+               "right."
+       },
+       { "forest_entry",               "forest",       128,
+               "You are at the entrance of a deep forest."
+       },
+       { "dungeon_deadend",            "cavern",       128,
+               "You reached a deadly dungeon dead-end!"
+       },
+       { "gardens_house",              "castle",       128,
+               "Here can be seen a quiet asian-style castle."
+       },
+       { "mountains_landscape",        "aria_prima",   85,
+               "What a great mountain landscape!"
+       },
+       { NULL, NULL, 0, NULL }
 };
 static int             curscene = 0;
 
@@ -209,14 +234,15 @@ screen_draw(void)
 }
 
 static void
-scene_switch(const char *img, const char *mus, int vol)
+scene_switch(const char *img, const char *mus, int vol, const char *text)
 {
        SDL_Surface     *s = NULL;
        Mix_Music       *m = NULL;
        char            path[1024], *str = NULL;
        int             music_new = 0;
+       text_t          *txt;
 
-       ASSERT(img != NULL && mus != NULL);
+       ASSERT(img != NULL && mus != NULL && text != NULL);
 
        /*
         * Because redrawing a lot while the music is just starting appears
@@ -255,9 +281,33 @@ scene_switch(const char *img, const char *mus, int vol)
 
                r = (SDL_Rect){ 16, 16, 0, 0 };
                (void) SDL_BlitSurface(img_painting, NULL, screen_surface, &r);
-               (void) SDL_Flip(screen_surface);
        }
 
+       /* Draw text */
+       if ((txt = text_create(font_next(), text)) != NULL) {
+               SDL_Rect        r;
+               SDL_Surface     *s;
+               int             i, y, h;
+
+               r = (SDL_Rect){ 798, 16, 0, 0 };
+               (void) SDL_BlitSurface(img_textarea, NULL, screen_surface, &r);
+
+               h = TTF_FontHeight(txt->fnt);
+               y = 32;
+               for (i = 0; i < txt->numlines; i++, y += h) {
+                       if ((s = TTF_RenderText_Blended(txt->fnt,
+                           txt->lines[i], fontcol)) != NULL) {
+                               r = (SDL_Rect){ 815, y, 0, 0 };
+                               (void) SDL_BlitSurface(s, NULL, screen_surface,
+                                   &r);
+                               SDL_FreeSurface(s);
+                       }
+               }
+               text_free(txt);
+       }
+
+       (void) SDL_Flip(screen_surface);
+
        /* Load new music track if necessary and start it */
        if (music_new) {
                (void) snprintf(path, 1023, "mus/%s.ogg", mus);
@@ -286,25 +336,13 @@ scene_switch(const char *img, const char *mus, int vol)
 static void
 scene_next(void)
 {
-       SDL_Surface     *s;
 
        if (scenes[curscene].img == NULL)
                curscene = 0;
 
        scene_switch(scenes[curscene].img, scenes[curscene].mus,
-           scenes[curscene].vol);
+           scenes[curscene].vol, scenes[curscene].text);
        curscene++;
-
-       if ((s = TTF_RenderText_Blended(font_next(), "A Paradise Adventure!",
-           fontcol)) != NULL) {
-               SDL_Rect        r;
-
-               r = (SDL_Rect){ 798, 16, 0, 0 };
-               (void) SDL_BlitSurface(img_textarea, NULL, screen_surface, &r);
-               r = (SDL_Rect){ 832, 32, 0, 0 };
-               (void) SDL_BlitSurface(s, NULL, screen_surface, &r);
-               SDL_FreeSurface(s);
-       }
 }
 
 static void
@@ -338,3 +376,95 @@ font_next(void)
 
        return fonts[curfont++].fnt;
 }
+
+static text_t *
+text_create(TTF_Font *font, const char *string)
+{
+       text_t  *text;
+       char    *str, *ptr, *olptr, *lptr;
+
+       /*
+        * Since not performance-critical, and that we could be supplied
+        * a read-only string, let's duplicate the supplied string.
+        */
+       if ((str = strdup(string)) == NULL)
+               return NULL;
+
+       if ((text = malloc(sizeof(text_t))) == NULL)
+               goto err;
+       text->numlines = 0;
+       if ((text->lines = malloc(sizeof(char *) * 16)) == NULL)
+               goto err;
+       text->alloclines = 16;
+       text->fnt = font;
+
+       /* Allocate an initial line */
+       if ((olptr = malloc(sizeof(char) * TEXT_LINE_SIZE)) == NULL)
+               goto err;
+       lptr = text->lines[text->numlines++] = olptr;
+
+       /*
+        * Populate line with words until it exceeds the allowed width,
+        * in which case we delete the last word from it and create a new
+        * line, adding it to it.
+        */
+       for (ptr = strtok(str, " \t"); ptr != NULL;
+           ptr = strtok(NULL, " \t")) {
+               int     l, w;
+
+               l = strlen(ptr);
+again:
+               (void) memcpy(lptr, ptr, l);
+               lptr[l] = ' ';
+               lptr[l + 1] = '\0';
+               if (TTF_SizeText(font, olptr, &w, NULL) == -1)
+                       goto err;
+               if (w < TEXT_WIDTH) {
+                       lptr += l + 1;
+                       continue;
+               }
+
+               /*
+                * We need to allocate a new line and reiterate.
+                * First discard last word we appended to current line.
+                */
+               *lptr = '\0';
+               if (text->numlines == text->alloclines) {
+                       /* Grow strings array buffer */
+                       char **a;
+
+                       if ((a = malloc(sizeof(char *) *
+                           (text->alloclines * 2))) == NULL)
+                               goto err;
+                       text->lines = a;
+               }
+               if ((olptr = malloc(sizeof(char) * TEXT_LINE_SIZE)) == NULL)
+                       goto err;
+               lptr = text->lines[text->numlines++] = olptr;
+               goto again;
+       }
+
+       free(str);
+       return text;
+
+err:
+       if (str != NULL)
+               free(str);
+       text_free(text);
+       return NULL;
+}
+
+static void
+text_free(text_t *text)
+{
+       int     i;
+
+       if (text != NULL) {
+               if (text->lines != NULL) {
+                       for (i = 0; i < text->numlines; i++)
+                               free(text->lines[i]);
+                       free(text->lines);
+               }
+               free(text);
+       }
+}