-/* $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 {
TTF_Font *fnt;
};
+typedef struct text {
+ TTF_Font *fnt;
+ int numlines, alloclines;
+ char **lines;
+} text_t;
+
/* PRIVATE PROTOTYPES */
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 */
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;
}
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
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);
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
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);
+ }
+}