[Tux4kids-commits] r513 - tuxmath/trunk/src
cheezmeister-guest at alioth.debian.org
cheezmeister-guest at alioth.debian.org
Thu Jun 12 00:07:51 UTC 2008
Author: cheezmeister-guest
Date: 2008-06-12 00:07:50 +0000 (Thu, 12 Jun 2008)
New Revision: 513
Modified:
tuxmath/trunk/src/SDL_extras.c
tuxmath/trunk/src/SDL_extras.h
tuxmath/trunk/src/game.c
tuxmath/trunk/src/highscore.c
tuxmath/trunk/src/setup.c
tuxmath/trunk/src/titlescreen.c
tuxmath/trunk/src/titlescreen.h
tuxmath/trunk/src/tuxmath.h
Log:
Added title screen and in-game support for extended fullscreen
tmdprintf(): works like printf(); only outputs when TUXMATH_DEBUG is
defined
game_draw() separated into four functions for background, comets,
igloos, and miscellaneous items like the score
Easter egg: when Tux's beak is clicked on the title screen, he eats
the cursor and temporarily turns it into an egg.
Modified: tuxmath/trunk/src/SDL_extras.c
===================================================================
--- tuxmath/trunk/src/SDL_extras.c 2008-06-11 21:26:58 UTC (rev 512)
+++ tuxmath/trunk/src/SDL_extras.c 2008-06-12 00:07:50 UTC (rev 513)
@@ -12,6 +12,7 @@
#include "SDL_extras.h"
#include "tuxmath.h"
+#include "pixels.h"
#ifdef SDL_Pango
#include "SDL_Pango.h"
@@ -29,7 +30,7 @@
SDL_Surface* tmp_surf = SDL_CreateRGBSurface(SDL_SWSURFACE|SDL_SRCALPHA,
target_rect->w,
target_rect->h,
- 32,
+ 32,
rmask, gmask, bmask, amask);
Uint32 color = SDL_MapRGBA(tmp_surf->format, r, g, b, a);
SDL_FillRect(tmp_surf, NULL, color);
@@ -48,7 +49,7 @@
Uint32* p = NULL;
Uint32 alpha_mask;
int bytes_per_pix;
-
+
if (!s)
return;
if (SDL_LockSurface(s) == -1)
@@ -69,8 +70,8 @@
/* Now round off corners: */
/* upper left: */
- for (y = 0; y < radius; y++)
- {
+ for (y = 0; y < radius; y++)
+ {
p = (Uint32*)(s->pixels + (y * s->pitch));
x_dist = radius;
y_dist = radius - y;
@@ -85,8 +86,8 @@
}
/* upper right: */
- for (y = 0; y < radius; y++)
- {
+ for (y = 0; y < radius; y++)
+ {
/* start at end of top row: */
p = (Uint32*)(s->pixels + ((y + 1) * s->pitch) - bytes_per_pix);
@@ -103,8 +104,8 @@
}
/* bottom left: */
- for (y = (s->h - 1); y > (s->h - radius); y--)
- {
+ for (y = (s->h - 1); y > (s->h - radius); y--)
+ {
/* start at beginning of bottom row */
p = (Uint32*)(s->pixels + (y * s->pitch));
x_dist = radius;
@@ -120,8 +121,8 @@
}
/* bottom right: */
- for (y = (s->h - 1); y > (s->h - radius); y--)
- {
+ for (y = (s->h - 1); y > (s->h - radius); y--)
+ {
/* start at end of bottom row */
p = (Uint32*)(s->pixels + ((y + 1) * s->pitch) - bytes_per_pix);
x_dist = radius;
@@ -136,7 +137,7 @@
}
}
SDL_UnlockSurface(s);
-}
+}
/**********************
@@ -144,8 +145,8 @@
input: a SDL_Surface, x, y
output: a copy of the SDL_Surface flipped via rules:
- if x is a positive value, then flip horizontally
- if y is a positive value, then flip vertically
+ if x is a nonzero value, then flip horizontally
+ if y is a nonzero value, then flip vertically
note: you can have it flip both
**********************/
@@ -323,8 +324,8 @@
void init_SDLPango_Context()
{
context = SDLPango_CreateContext_GivenFontDesc(DEFAULT_FONT_NAME);
-}
-void free_SDLPango_Context()
+}
+void free_SDLPango_Context()
{
if(context != NULL)
SDLPango_FreeContext(context);
@@ -441,19 +442,17 @@
void DarkenScreen(Uint8 bits)
{
#if PIXEL_BITS == 32
- Uint32 rm = screen->format->Rmask;
- Uint32 gm = screen->format->Gmask;
- Uint32 bm = screen->format->Bmask;
- Uint32* p;
+ Uint32* p;
#elif PIXEL_BITS == 16
- Uint16 rm = screen->format->Rmask;
- Uint16 gm = screen->format->Gmask;
- Uint16 bm = screen->format->Bmask;
- Uint16* p;
+ Uint16* p;
#else
return;
#endif
+ Uint32 rm = screen->format->Rmask;
+ Uint32 gm = screen->format->Gmask;
+ Uint32 bm = screen->format->Bmask;
+
int x, y;
/* (realistically, 1 and 2 are the only useful values) */
@@ -463,7 +462,7 @@
p = screen->pixels;
for (y = 0; y < RES_Y; y++)
- {
+ {
for (x = 0; x < RES_X; x++)
{
*p = (((*p&rm)>>bits)&rm)
@@ -477,63 +476,430 @@
void SwitchScreenMode(void)
{
- SDL_Surface *tmp;
- SDL_Rect src, dst;
+ int window = (screen->flags & SDL_FULLSCREEN);
+ SDL_Surface* oldscreen = screen;
- int window = 0;
-
- src.x = 0;
- src.y = 0;
- src.w = RES_X;
- src.h = RES_Y;
- dst.x = 0;
- dst.y = 0;
-
- tmp = SDL_CreateRGBSurface(
- SDL_SWSURFACE,
- RES_X,
- RES_Y,
- PIXEL_BITS,
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
- 0xff000000,
- 0x00ff0000,
- 0x0000ff00,
- 0x000000ff
-#else
- 0x000000ff,
- 0x0000ff00,
- 0x00ff0000,
- 0xff000000
-#endif
- );
-
- if (screen->flags & SDL_FULLSCREEN)
+ if (!window)
{
- window = 1;
+ screen = SDL_SetVideoMode(fs_res_x,
+ fs_res_y,
+ PIXEL_BITS,
+ SDL_SWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN);
}
-
- SDL_BlitSurface(screen,&src,tmp,&dst);
- SDL_UpdateRect(tmp, 0, 0, RES_X, RES_Y);
- SDL_FreeSurface(screen);
- screen = NULL;
-
- if (window)
+ else
{
screen = SDL_SetVideoMode(RES_X,
RES_Y,
PIXEL_BITS,
SDL_SWSURFACE|SDL_HWPALETTE);
+
}
+
+ if (screen == NULL)
+ {
+ fprintf(stderr,
+ "\nError: I could not switch to %s mode.\n"
+ "The Simple DirectMedia error that occured was:\n"
+ "%s\n\n",
+ window ? "windowed" : "fullscreen",
+ SDL_GetError());
+ screen = oldscreen;
+ }
else
{
- screen = SDL_SetVideoMode(RES_X,
- RES_Y,
- PIXEL_BITS,
- SDL_SWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN);
+ SDL_FreeSurface(oldscreen);
+ oldscreen = NULL;
+ SDL_UpdateRect(screen, 0, 0, 0, 0);
}
- SDL_BlitSurface(tmp,&src,screen,&dst);
- SDL_UpdateRect(tmp,0,0,RES_X,RES_Y);
- SDL_FreeSurface(tmp);
}
+//#if 0
+
+/* Swiped shamelessly from TuxPaint
+ Based on code from: http://www.codeproject.com/cs/media/imageprocessing4.asp
+ copyright 2002 Christian Graus */
+
+SDL_Surface *zoom(SDL_Surface * src, int new_w, int new_h)
+{
+ SDL_Surface * s;
+ void (*putpixel) (SDL_Surface *, int, int, Uint32);
+ Uint32(*getpixel) (SDL_Surface *, int, int) =
+ getpixels[src->format->BytesPerPixel];
+ float xscale, yscale;
+ int x, y;
+ float floor_x, ceil_x, floor_y, ceil_y, fraction_x, fraction_y,
+ one_minus_x, one_minus_y;
+ float n1, n2;
+ float r1, g1, b1, a1;
+ float r2, g2, b2, a2;
+ float r3, g3, b3, a3;
+ float r4, g4, b4, a4;
+ Uint8 r, g, b, a;
+
+
+ /* Create surface for zoom: */
+
+ s = SDL_CreateRGBSurface(src->flags, /* SDL_SWSURFACE, */
+ new_w, new_h, src->format->BitsPerPixel,
+ src->format->Rmask,
+ src->format->Gmask,
+ src->format->Bmask,
+ src->format->Amask);
+
+
+ if (s == NULL)
+ {
+ fprintf(stderr, "\nError: Can't build zoom surface\n"
+ "The Simple DirectMedia Layer error that occurred was:\n"
+ "%s\n\n", SDL_GetError());
+
+ cleanup();
+ exit(1);
+ }
+
+ putpixel = putpixels[s->format->BytesPerPixel];
+
+
+ SDL_LockSurface(src);
+ SDL_LockSurface(s);
+
+ xscale = (float) src->w / (float) new_w;
+ yscale = (float) src->h / (float) new_h;
+
+ for (x = 0; x < new_w; x++)
+ {
+ for (y = 0; y < new_h; y++)
+ {
+ floor_x = floor((float) x * xscale);
+ ceil_x = floor_x + 1;
+ if (ceil_x >= src->w)
+ ceil_x = floor_x;
+
+ floor_y = floor((float) y * yscale);
+ ceil_y = floor_y + 1;
+ if (ceil_y >= src->h)
+ ceil_y = floor_y;
+
+ fraction_x = x * xscale - floor_x;
+ fraction_y = y * yscale - floor_y;
+
+ one_minus_x = 1.0 - fraction_x;
+ one_minus_y = 1.0 - fraction_y;
+
+ SDL_GetRGBA(getpixel(src, floor_x, floor_y), src->format,
+ &r1, &g1, &b1, &a1);
+ SDL_GetRGBA(getpixel(src, ceil_x, floor_y), src->format,
+ &r2, &g2, &b2, &a2);
+ SDL_GetRGBA(getpixel(src, floor_x, ceil_y), src->format,
+ &r3, &g3, &b3, &a3);
+ SDL_GetRGBA(getpixel(src, ceil_x, ceil_y), src->format,
+ &r4, &g4, &b4, &a4);
+
+ n1 = (one_minus_x * r1 + fraction_x * r2);
+ n2 = (one_minus_x * r3 + fraction_x * r4);
+ r = (one_minus_y * n1 + fraction_y * n2);
+
+ n1 = (one_minus_x * g1 + fraction_x * g2);
+ n2 = (one_minus_x * g3 + fraction_x * g4);
+ g = (one_minus_y * n1 + fraction_y * n2);
+
+ n1 = (one_minus_x * b1 + fraction_x * b2);
+ n2 = (one_minus_x * b3 + fraction_x * b4);
+ b = (one_minus_y * n1 + fraction_y * n2);
+
+ n1 = (one_minus_x * a1 + fraction_x * a2);
+ n2 = (one_minus_x * a3 + fraction_x * a4);
+ a = (one_minus_y * n1 + fraction_y * n2);
+
+ putpixel(s, x, y, SDL_MapRGBA(s->format, r, g, b, a));
+ }
+ }
+
+ SDL_UnlockSurface(s);
+ SDL_UnlockSurface(src);
+
+ return s;
+
+}
+
+//FIXME: everything below is slightly modified code from pixels.c and would do
+// better to be included as such.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+ pixels.c
+
+ For Tux Paint
+ Pixel read/write functions
+
+ Copyright (c) 2002-2006 by Bill Kendrick and others
+ bill at newbreedsoftware.com
+ http://www.newbreedsoftware.com/tuxpaint/
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ (See COPYING.txt)
+
+ June 14, 2002 - February 17, 2006
+ $Id: pixels.c,v 1.3 2006/08/27 21:00:55 wkendrick Exp $
+*/
+
+#include "pixels.h"
+//#include "compiler.h"
+//#include "debug.h"
+
+/* Draw a single pixel into the surface: */
+void putpixel8(SDL_Surface * surface, int x, int y, Uint32 pixel)
+{
+ Uint8 *p;
+
+ /* Assuming the X/Y values are within the bounds of this surface... */
+ if (
+ (((unsigned) x < (unsigned) surface->w)
+ && ((unsigned) y < (unsigned) surface->h)))
+ {
+ // Set a pointer to the exact location in memory of the pixel
+ p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
+ (y * surface->pitch) + /* Go down Y lines */
+ x); /* Go in X pixels */
+
+
+ /* Set the (correctly-sized) piece of data in the surface's RAM
+ * to the pixel value sent in: */
+
+ *p = pixel;
+ }
+}
+
+/* Draw a single pixel into the surface: */
+void putpixel16(SDL_Surface * surface, int x, int y, Uint32 pixel)
+{
+ Uint8 *p;
+
+ /* Assuming the X/Y values are within the bounds of this surface... */
+ if (
+ (((unsigned) x < (unsigned) surface->w)
+ && ((unsigned) y < (unsigned) surface->h)))
+ {
+ // Set a pointer to the exact location in memory of the pixel
+ p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
+ (y * surface->pitch) + /* Go down Y lines */
+ (x * 2)); /* Go in X pixels */
+
+
+ /* Set the (correctly-sized) piece of data in the surface's RAM
+ * to the pixel value sent in: */
+
+ *(Uint16 *) p = pixel;
+ }
+}
+
+/* Draw a single pixel into the surface: */
+void putpixel24(SDL_Surface * surface, int x, int y, Uint32 pixel)
+{
+ Uint8 *p;
+
+ /* Assuming the X/Y values are within the bounds of this surface... */
+ if (
+ (((unsigned) x < (unsigned) surface->w)
+ && ((unsigned) y < (unsigned) surface->h)))
+ {
+ // Set a pointer to the exact location in memory of the pixel
+ p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
+ (y * surface->pitch) + /* Go down Y lines */
+ (x * 3)); /* Go in X pixels */
+
+
+ /* Set the (correctly-sized) piece of data in the surface's RAM
+ * to the pixel value sent in: */
+
+ if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
+ {
+ p[0] = (pixel >> 16) & 0xff;
+ p[1] = (pixel >> 8) & 0xff;
+ p[2] = pixel & 0xff;
+ }
+ else
+ {
+ p[0] = pixel & 0xff;
+ p[1] = (pixel >> 8) & 0xff;
+ p[2] = (pixel >> 16) & 0xff;
+ }
+
+ }
+}
+
+/* Draw a single pixel into the surface: */
+void putpixel32(SDL_Surface * surface, int x, int y, Uint32 pixel)
+{
+ Uint8 *p;
+
+ /* Assuming the X/Y values are within the bounds of this surface... */
+ if (
+ (((unsigned) x < (unsigned) surface->w)
+ && ((unsigned) y < (unsigned) surface->h)))
+ {
+ // Set a pointer to the exact location in memory of the pixel
+ p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
+ (y * surface->pitch) + /* Go down Y lines */
+ (x * 4)); /* Go in X pixels */
+
+
+ /* Set the (correctly-sized) piece of data in the surface's RAM
+ * to the pixel value sent in: */
+
+ *(Uint32 *) p = pixel; // 32-bit display
+ }
+}
+
+/* Get a pixel: */
+Uint32 getpixel8(SDL_Surface * surface, int x, int y)
+{
+ Uint8 *p;
+
+ /* get the X/Y values within the bounds of this surface */
+ if ((unsigned) x < (unsigned) surface->w)
+ x = (x < 0) ? 0 : surface->w - 1;
+ if ((unsigned) y < (unsigned) surface->h)
+ y = (y < 0) ? 0 : surface->h - 1;
+
+ /* Set a pointer to the exact location in memory of the pixel
+ in question: */
+
+ p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start at top of RAM */
+ (y * surface->pitch) + /* Go down Y lines */
+ x); /* Go in X pixels */
+
+
+ /* Return the correctly-sized piece of data containing the
+ * pixel's value (an 8-bit palette value, or a 16-, 24- or 32-bit
+ * RGB value) */
+
+ return (*p);
+}
+
+/* Get a pixel: */
+Uint32 getpixel16(SDL_Surface * surface, int x, int y)
+{
+ Uint8 *p;
+
+ /* get the X/Y values within the bounds of this surface */
+ if ((unsigned) x < (unsigned) surface->w)
+ x = (x < 0) ? 0 : surface->w - 1;
+ if ((unsigned) y < (unsigned) surface->h)
+ y = (y < 0) ? 0 : surface->h - 1;
+
+ /* Set a pointer to the exact location in memory of the pixel
+ in question: */
+
+ p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start at top of RAM */
+ (y * surface->pitch) + /* Go down Y lines */
+ (x * 2)); /* Go in X pixels */
+
+
+ /* Return the correctly-sized piece of data containing the
+ * pixel's value (an 8-bit palette value, or a 16-, 24- or 32-bit
+ * RGB value) */
+
+ return (*(Uint16 *) p);
+}
+
+/* Get a pixel: */
+Uint32 getpixel24(SDL_Surface * surface, int x, int y)
+{
+ Uint8 *p;
+ Uint32 pixel;
+
+ /* get the X/Y values within the bounds of this surface */
+ if ((unsigned) x < (unsigned) surface->w)
+ x = (x < 0) ? 0 : surface->w - 1;
+ if ((unsigned) y < (unsigned) surface->h)
+ y = (y < 0) ? 0 : surface->h - 1;
+
+ /* Set a pointer to the exact location in memory of the pixel
+ in question: */
+
+ p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start at top of RAM */
+ (y * surface->pitch) + /* Go down Y lines */
+ (x * 3)); /* Go in X pixels */
+
+
+ /* Return the correctly-sized piece of data containing the
+ * pixel's value (an 8-bit palette value, or a 16-, 24- or 32-bit
+ * RGB value) */
+
+ /* Depending on the byte-order, it could be stored RGB or BGR! */
+
+ if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
+ pixel = p[0] << 16 | p[1] << 8 | p[2];
+ else
+ pixel = p[0] | p[1] << 8 | p[2] << 16;
+
+ return pixel;
+}
+
+/* Get a pixel: */
+Uint32 getpixel32(SDL_Surface * surface, int x, int y)
+{
+ Uint8 *p;
+
+ /* get the X/Y values within the bounds of this surface */
+ if ((unsigned) x < (unsigned) surface->w)
+ x = (x < 0) ? 0 : surface->w - 1;
+ if ((unsigned) y < (unsigned) surface->h)
+ y = (y < 0) ? 0 : surface->h - 1;
+
+ /* Set a pointer to the exact location in memory of the pixel
+ in question: */
+
+ p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start at top of RAM */
+ (y * surface->pitch) + /* Go down Y lines */
+ (x * 4)); /* Go in X pixels */
+
+
+ /* Return the correctly-sized piece of data containing the
+ * pixel's value (an 8-bit palette value, or a 16-, 24- or 32-bit
+ * RGB value) */
+
+ return *(Uint32 *) p; // 32-bit display
+}
+
+void (*putpixels[]) (SDL_Surface *, int, int, Uint32) =
+{
+putpixel8, putpixel8, putpixel16, putpixel24, putpixel32};
+
+
+Uint32(*getpixels[])(SDL_Surface *, int, int) =
+{
+getpixel8, getpixel8, getpixel16, getpixel24, getpixel32};
+
+//#endif
Modified: tuxmath/trunk/src/SDL_extras.h
===================================================================
--- tuxmath/trunk/src/SDL_extras.h 2008-06-11 21:26:58 UTC (rev 512)
+++ tuxmath/trunk/src/SDL_extras.h 2008-06-12 00:07:50 UTC (rev 513)
@@ -36,5 +36,7 @@
void DarkenScreen(Uint8 bits);
void SwitchScreenMode(void);
SDL_Surface* Blend(SDL_Surface *S1, SDL_Surface *S2,float gamma);
+SDL_Surface *zoom(SDL_Surface * src, int new_w, int new_h);
+
#endif
Modified: tuxmath/trunk/src/game.c
===================================================================
--- tuxmath/trunk/src/game.c 2008-06-11 21:26:58 UTC (rev 512)
+++ tuxmath/trunk/src/game.c 2008-06-12 00:07:50 UTC (rev 513)
@@ -11,7 +11,7 @@
Part of "Tux4Kids" Project
http://www.tux4kids.org/
-
+
August 26, 2001 - February 18, 2004
Revised by David Bruce, Tim Holy and others
@@ -36,7 +36,7 @@
#include "setup.h"
#include "mathcards.h"
#include "titlescreen.h"
-#include "options.h"
+#include "options.h"
#include "SDL_extras.h"
#define FPS 15 /* 15 frames per second */
@@ -152,6 +152,11 @@
static void game_handle_steam(void);
static void game_handle_extra_life(void);
static void game_draw(void);
+static void game_draw_background(void);
+static void game_draw_comets(void);
+static void game_draw_cities(void);
+static void game_draw_misc(void);
+
static int check_extra_life(void);
static int check_exit_conditions(void);
@@ -179,6 +184,8 @@
static void help_add_comet(int a,int oper,int b,int c);
static int help_renderframe_exit(void);
+static void game_recalc_positions(void);
+
#ifdef TUXMATH_DEBUG
static void print_exit_conditions(void);
static void print_status(void);
@@ -195,6 +202,13 @@
fprintf(stderr, "Entering game():\n");
#endif
+ //see if the option matches the actual screen
+ if (Opts_Fullscreen() == !(screen->flags & SDL_FULLSCREEN) )
+ {
+ SwitchScreenMode();
+ }
+
+
/* most code moved into smaller functions (game_*()): */
if (!game_initialize())
{
@@ -203,7 +217,7 @@
/* player simply has all operations deselected */
free_on_exit();
return 0;
- }
+ }
if (Opts_HelpMode()) {
game_handle_help();
@@ -211,7 +225,9 @@
return 0;
}
- /* --- MAIN GAME LOOP: --- */
+
+
+ /* --- MAIN GAME LOOP: --- */
do
{
/* reset or increment various things with each loop: */
@@ -223,11 +239,11 @@
if (laser.alive > 0)
{
laser.alive--;
- }
+ }
/* Most code now in smaller functions: */
game_handle_user_events();
- game_handle_demo();
+ game_handle_demo();
game_handle_answer();
game_countdown();
game_handle_tux();
@@ -238,28 +254,28 @@
game_handle_extra_life();
game_draw();
/* figure out if we should leave loop: */
- game_status = check_exit_conditions();
+ game_status = check_exit_conditions();
-
+
/* If we're in "PAUSE" mode, pause! */
if (paused)
{
pause_game();
paused = 0;
}
-
+
/* Keep playing music: */
-
+
#ifndef NOSOUND
if (Opts_UsingSound())
{
if (!Mix_PlayingMusic())
{
Mix_PlayMusic(musics[MUS_GAME + (rand() % 3)], 0);
- }
+ }
}
#endif
-
+
/* Pause (keep frame-rate event) */
now_time = SDL_GetTicks();
if (now_time < last_time + MS_PER_FRAME)
@@ -313,7 +329,7 @@
|| event.type == SDL_MOUSEBUTTONDOWN)
{
looping = 0;
- }
+ }
}
if (bkgd)
@@ -352,7 +368,7 @@
SDL_BlitSurface(images[tux_img], NULL, screen, &dest_tux);
/* draw_console_image(tux_img);*/
-
+
SDL_Flip(screen);
now_time = SDL_GetTicks();
@@ -370,7 +386,7 @@
printf("\ngame() exiting with error");
#endif
}
- case GAME_OVER_LOST:
+ case GAME_OVER_LOST:
case GAME_OVER_OTHER:
{
int looping = 1;
@@ -393,7 +409,7 @@
|| event.type == SDL_MOUSEBUTTONDOWN)
{
looping = 0;
- }
+ }
}
SDL_BlitSurface(images[IMG_GAMEOVER], NULL, screen, &dest_message);
@@ -402,7 +418,7 @@
now_time = SDL_GetTicks();
if (now_time < last_time + MS_PER_FRAME)
- SDL_Delay(last_time + MS_PER_FRAME - now_time);
+ SDL_Delay(last_time + MS_PER_FRAME - now_time);
}
while (looping);
@@ -419,7 +435,7 @@
break;
}
- }
+ }
game_cleanup();
@@ -427,13 +443,13 @@
if (Opts_SaveSummary())
{
write_postgame_summary();
- }
+ }
/* Save score in case needed for high score table: */
Opts_SetLastScore(score);
/* Return the chosen command: */
- if (GAME_OVER_WINDOW_CLOSE == game_status)
+ if (GAME_OVER_WINDOW_CLOSE == game_status)
{
/* program exits: */
cleanup();
@@ -452,11 +468,11 @@
{
int i,img;
/* Clear window: */
-
+
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
SDL_Flip(screen);
- game_status = GAME_IN_PROGRESS;
+ game_status = GAME_IN_PROGRESS;
gameover_counter = -1;
SDL_quit_received = 0;
escape_received = 0;
@@ -499,8 +515,8 @@
#endif
fprintf(stderr, "\nMC_StartGame() failed!");
return 0;
- }
-
+ }
+
/* Write pre-game info to game summary file: */
if (Opts_SaveSummary())
{
@@ -514,7 +530,7 @@
comet_feedback_number = 0;
comet_feedback_height = 0;
danger_level = Opts_DangerLevel();
-
+
wave = 1;
num_attackers = 2;
prev_wave_comets = Opts_StartingComets();
@@ -524,9 +540,9 @@
demo_countdown = 2000;
level_start_wait = LEVEL_START_WAIT_START;
neg_answer_picked = 0;
-
+
/* (Create and position cities) */
-
+
if (Opts_UseIgloos())
img = IMG_IGLOO_INTACT;
else
@@ -538,7 +554,7 @@
cities[i].counter = 0;
cities[i].threatened = 0;
cities[i].layer = 0;
-
+
/* Left vs. Right - makes room for Tux and the console */
if (i < NUM_CITIES / 2)
{
@@ -581,13 +597,13 @@
/* (Clear laser) */
laser.alive = 0;
-
+
/* Reset remaining stuff: */
-
+
bkgd = NULL;
last_bkgd = -1;
reset_level();
- reset_comets();
+ reset_comets();
frame = 0;
paused = 0;
@@ -668,10 +684,10 @@
if (!Mix_PlayingMusic())
{
Mix_PlayMusic(musics[MUS_GAME], 0);
- }
+ }
}
#endif
-
+
// Wait 2 seconds while rendering frames
while (frame < 2*FPS && !(quit_help = help_renderframe_exit()));
if (quit_help)
@@ -717,7 +733,7 @@
help_controls.laser_enabled = 0;
frame_start = frame;
while (frame-frame_start < 3*FPS && !(quit_help = help_renderframe_exit())); // wait 3 secs
-
+
speed = 2;
game_set_message(&s1,_("If an igloo gets hit by a comet,"),left_edge,100);
game_set_message(&s2,_("it melts. But don't worry: the"),left_edge,135);
@@ -730,7 +746,7 @@
if (quit_help)
return;
game_clear_message(&s5);
-
+
help_add_comet(3,MC_OPER_MULT,3,9);
comets[0].y = 2*(screen->h)/3; // start it low down
while (!(comets[0].expl) && !(quit_help = help_renderframe_exit())); // wait 3 secs
@@ -765,7 +781,7 @@
while ((frame-frame_start < 3*FPS) && !(quit_help = help_renderframe_exit()));
if (quit_help)
return;
-
+
help_controls.laser_enabled = 1;
game_set_message(&s1,_("You can fix the igloos"),left_edge,100);
game_set_message(&s2,_("by stopping bonus comets."),left_edge,135);
@@ -979,7 +995,7 @@
answer_digit = 2;
}
}
-
+
/* Add a digit: */
if (picked_comet != -1 && (frame % 5) == 0 && (rand() % 10) < 8)
{
@@ -1002,7 +1018,7 @@
{
digits[2] = (demo_answer % 10);
}
-
+
answer_digit++;
}
else
@@ -1040,8 +1056,8 @@
if (neg_answer_picked)
{
num = -num;
- }
-
+ }
+
/* Pick the lowest comet which has the right answer: */
/* FIXME: do we want it to prefer bonus comets to regular comets? */
lowest_y = 0;
@@ -1050,7 +1066,7 @@
for (i = 0; i < MAX_COMETS; i++)
{
if (comets[i].alive &&
- comets[i].expl < COMET_EXPL_END &&
+ comets[i].expl < COMET_EXPL_END &&
comets[i].answer == num &&
comets[i].y > lowest_y)
{
@@ -1058,7 +1074,7 @@
lowest_y = comets[i].y;
}
}
-
+
/* If there was an comet with this answer, destroy it! */
if (lowest != -1) /* -1 means no comet had this answer */
{
@@ -1070,8 +1086,8 @@
if (ctime > comets[lowest].time_started) {
MC_AddTimeToList((float)(ctime - comets[lowest].time_started)/1000);
}
-
+
/* Destroy comet: */
comets[lowest].expl = COMET_EXPL_START;
comets[lowest].zapped = 1;
@@ -1095,7 +1111,7 @@
#endif
}
-
+
/* FIXME maybe should move this into game_handle_tux() */
/* 50% of the time.. */
if ((rand() % 10) < 5)
@@ -1126,13 +1142,13 @@
laser.y2 = 0;
playsound(SND_LASER);
playsound(SND_BUZZ);
-
+
if ((rand() % 10) < 5)
tux_img = IMG_TUX_DRAT;
else
tux_img = IMG_TUX_YIPE;
}
-
+
/* Clear digits: */
digits[0] = 0;
digits[1] = 0;
@@ -1152,7 +1168,7 @@
tux_img = IMG_TUX_RELAX2;
else
tux_img = IMG_TUX_SIT;
-
+
if (level_start_wait == LEVEL_START_WAIT_START / 4)
{
playsound(SND_ALARM);
@@ -1174,7 +1190,7 @@
playsound(SND_CLICK);
}
-
+
/* If Tux is being animated, show the animation: */
if (tux_anim != -1)
{
@@ -1198,6 +1214,8 @@
tux_same_counter = 0;
}
+//FIXME might be simpler to store vertical position (and speed) in terms of time
+//rather than absolute position, and determine the latter in game_draw_comets()
void game_handle_comets(void)
{
/* Handle comets. Since the comets also are the things that trigger
@@ -1223,11 +1241,13 @@
/* Make bonus comet move faster at chosen ratio: */
if (comets[i].bonus)
{
- comets[i].y += speed * Opts_BonusSpeedRatio();
+ comets[i].y += speed * Opts_BonusSpeedRatio() *
+ city_expl_height / (RES_Y - images[IMG_CITY_BLUE]->h);
}
else /* Regular comet: */
{
- comets[i].y += speed;
+ comets[i].y += speed *
+ city_expl_height / (RES_Y - images[IMG_CITY_BLUE]->h);
}
/* Does it threaten a city? */
@@ -1260,7 +1280,7 @@
1.0 + Opts_CityExplHandicap());
#endif
}
-
+
/* Disable shields/destroy city/create steam cloud: */
if (cities[this_city].hits_left)
{
@@ -1282,8 +1302,8 @@
}
}
cities[this_city].hits_left--;
- }
-
+ }
+
/* If this was a bonus comet, restart the counter */
if (comets[i].bonus)
bonus_comet_counter = Opts_BonusCometInterval()+1;
@@ -1433,7 +1453,7 @@
/* Change image to appropriate color: */
cities[i].img = cities[i].img + ((wave % MAX_CITY_COLORS) *
(IMG_CITY_GREEN - IMG_CITY_BLUE));
-
+
}
}
}
@@ -1681,116 +1701,211 @@
/* FIXME consider splitting this into smaller functions e.g. draw_comets(), etc. */
void game_draw(void)
{
- int i,j, img, current_layer, max_layer,offset;
- SDL_Rect src, dest;
- SDL_Surface *this_image;
- char str[64];
- char* comet_str;
+ SDL_Rect dest;
/* Clear screen: */
- if (bkgd == NULL)
+ game_draw_background();
+
+ /* Draw miscellaneous informational items */
+ game_draw_misc();
+
+ /* Draw cities/igloos and (if applicable) penguins: */
+ game_draw_cities();
+
+ /* Draw normal comets first, then bonus comets */
+ game_draw_comets();
+
+
+ /* Draw laser: */
+ if (laser.alive)
{
+ draw_line(laser.x1, laser.y1, laser.x2, laser.y2,
+ 255 / ((LASER_START + 1) - laser.alive),
+ 192 / ((LASER_START + 1) - laser.alive),
+ 64);
+ }
+
+ /* Draw numeric keypad: */
+ if (Opts_UseKeypad())
+ {
+ /* pick image to draw: */
+ int keypad_image;
+ if (MC_AllowNegatives())
+ {
+ /* draw regular keypad */
+ keypad_image = IMG_KEYPAD;
+ }
+ else
+ {
+ /* draw keypad with with grayed-out '+' and '-' */
+ keypad_image = IMG_KEYPAD_NO_NEG;
+ }
+
+ /* now draw it: */
+ dest.x = (screen->w - images[keypad_image]->w) / 2;
+ dest.y = (screen->h - images[keypad_image]->h) / 2;
+ dest.w = images[keypad_image]->w;
+ dest.h = images[keypad_image]->h;
+ SDL_BlitSurface(images[keypad_image], NULL, screen, &dest);
+ }
+
+ /* Draw console, LED numbers, & tux: */
+ draw_led_console();
+ draw_console_image(tux_img);
+
+ /* Draw any messages on the screen (used for the help mode) */
+ game_write_messages();
+
+ /* Swap buffers: */
+ SDL_Flip(screen);
+}
+
+void game_draw_background(void)
+{
+ static int old_wave = 0; //update wave immediately
+ static Uint32 bgcolor, fgcolor = 0;
+ SDL_Rect dest;
+
+ if (fgcolor == 0)
+ fgcolor = SDL_MapRGB(screen->format, 64, 96, 64);
+ if (old_wave != wave)
+ {
+ tmdprintf("Wave %d\n", wave);
+ old_wave = wave;
+ bgcolor = SDL_MapRGB(screen->format,
+ 64,
+ 64 + ((wave * 32) % 192),
+ 128 - ((wave * 16) % 128) );
+ tmdprintf("Filling screen with color %d\n", bgcolor);
+ }
+
+ if (bkgd == NULL || screen->flags & SDL_FULLSCREEN)
+ {
dest.x = 0;
dest.y = 0;
dest.w = screen->w;
dest.h = ((screen->h) / 4) * 3;
- SDL_FillRect(screen, &dest,
- SDL_MapRGB(screen->format,
- 64,
- 64 + ((wave * 32) % 192),
- 128 - ((wave * 16) % 128)));
+ SDL_FillRect(screen, &dest, bgcolor);
- dest.x = 0;
+
dest.y = ((screen->h) / 4) * 3;
- dest.w = screen->w;
dest.h = (screen->h) / 4;
- SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 64, 96, 64));
+ SDL_FillRect(screen, &dest, fgcolor);
}
- else
+
+ if (bkgd)
{
- SDL_BlitSurface(bkgd, NULL, screen, NULL);
+ dest.x = (screen->w - bkgd->w) / 2;
+ dest.y = (screen->h - bkgd->h) / 2;
+ SDL_BlitSurface(bkgd, NULL, screen, &dest);
}
+}
- /* Draw "Demo" */
- if (Opts_DemoMode())
+/* Draw comets: */
+/* NOTE bonus comets split into separate pass to make them */
+/* draw last (i.e. in front), as they can overlap */
+void game_draw_comets(void)
+{
+
+ int i,j, img, max_layer,offset;
+ SDL_Rect dest;
+ char* comet_str;
+
+ /* First draw regular comets: */
+ for (i = 0; i < MAX_COMETS; i++)
{
- dest.x = (screen->w - images[IMG_DEMO]->w) / 2;
- dest.y = (screen->h - images[IMG_DEMO]->h) / 2;
- dest.w = images[IMG_DEMO]->w;
- dest.h = images[IMG_DEMO]->h;
+ if (comets[i].alive && !comets[i].bonus)
+ {
+ if (comets[i].expl < COMET_EXPL_END)
+ {
+ /* Decide which image to display: */
+ img = IMG_COMET1 + ((frame + i) % 3);
+ /* Display the formula (flashing, in the bottom half
+ of the screen) */
+ if (comets[i].y < screen->h / 2 || frame % 8 < 6)
+ {
+ comet_str = comets[i].flashcard.formula_string;
+ }
+ else
+ {
+ comet_str = NULL;
+ }
+ }
+ else
+ {
+ img = comets[i].expl;
+ comet_str = comets[i].flashcard.answer_string;
+ }
- SDL_BlitSurface(images[IMG_DEMO], NULL, screen, &dest);
+ /* Draw it! */
+ dest.x = comets[i].x - (images[img]->w / 2);
+ dest.y = comets[i].y - images[img]->h;
+ dest.w = images[img]->w;
+ dest.h = images[img]->h;
+
+ SDL_BlitSurface(images[img], NULL, screen, &dest);
+ if (comet_str != NULL)
+ {
+ draw_nums(comet_str, comets[i].x, comets[i].y);
+ }
+ }
}
- /* If we are playing through a defined list of questions */
- /* without "recycling", display number of remaining questions: */
- if (MC_PlayThroughList())
+ /* Now draw any bonus comets: */
+ for (i = 0; i < MAX_COMETS; i++)
{
- draw_question_counter();
- }
+ if (comets[i].alive && comets[i].bonus)
+ {
+ if (comets[i].expl < COMET_EXPL_END)
+ {
+ /* Decide which image to display: */
+ img = IMG_COMET1 + ((frame + i) % 3);
+ /* Display the formula (flashing, in the bottom half
+ of the screen) */
+ if (comets[i].y < screen->h / 2 || frame % 8 < 6)
+ {
+ comet_str = comets[i].flashcard.formula_string;
+ }
+ else
+ {
+ comet_str = NULL;
+ }
+ }
+ else
+ {
+ img = comets[i].expl;
+ comet_str = comets[i].flashcard.answer_string;
+ }
- if (extra_life_earned) {
- /* Draw extra life earned icon */
- dest.x = 0;
- dest.y = 0;
- dest.w = images[IMG_EXTRA_LIFE]->w;
- dest.h = images[IMG_EXTRA_LIFE]->h;
- SDL_BlitSurface(images[IMG_EXTRA_LIFE], NULL, screen, &dest);
- } else if (bonus_comet_counter) {
- /* Draw extra life progress bar */
- dest.x = 0;
- dest.y = images[IMG_EXTRA_LIFE]->h/4;
- dest.h = images[IMG_EXTRA_LIFE]->h/2;
- dest.w = ((Opts_BonusCometInterval() + 1 - bonus_comet_counter)
- * images[IMG_EXTRA_LIFE]->w) / Opts_BonusCometInterval();
- SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 0, 255, 0));
- }
+ /* Move images[] index to bonus range: */
+ img += IMG_BONUS_COMET1 - IMG_COMET1;
- /* Draw wave: */
- if (Opts_BonusCometInterval())
- offset = images[IMG_EXTRA_LIFE]->w + 5;
- else
- offset = 0;
+ /* Draw it! */
+ dest.x = comets[i].x - (images[img]->w / 2);
+ dest.y = comets[i].y - images[img]->h;
+ dest.w = images[img]->w;
+ dest.h = images[img]->h;
- dest.x = offset;
- dest.y = 0;
- dest.w = images[IMG_WAVE]->w;
- dest.h = images[IMG_WAVE]->h;
+ SDL_BlitSurface(images[img], NULL, screen, &dest);
+ if (comet_str != NULL)
+ {
+ draw_nums(comet_str, comets[i].x, comets[i].y);
+ }
+ }
+ }
- SDL_BlitSurface(images[IMG_WAVE], NULL, screen, &dest);
- sprintf(str, "%d", wave);
- draw_numbers(str, offset+images[IMG_WAVE]->w + (images[IMG_NUMBERS]->w / 10), 0);
- /* Draw "score" label: */
- dest.x = (screen->w - ((images[IMG_NUMBERS]->w / 10) * 7) -
- images[IMG_SCORE]->w -
- images[IMG_STOP]->w - 5);
- dest.y = 0;
- dest.w = images[IMG_SCORE]->w;
- dest.h = images[IMG_SCORE]->h;
+}
- SDL_BlitSurface(images[IMG_SCORE], NULL, screen, &dest);
-
- /* Draw score numbers: */
- sprintf(str, "%.6d", score);
- draw_numbers(str,
- screen->w - ((images[IMG_NUMBERS]->w / 10) * 6) - images[IMG_STOP]->w - 5,
- 0);
+void game_draw_cities(void)
+{
+ int i, j, current_layer, max_layer;
+ SDL_Rect src, dest;
+ SDL_Surface* this_image;
- /* Draw stop button: */
- if (!help_controls.x_is_blinking || (frame % 10 < 5)) {
- dest.x = (screen->w - images[IMG_STOP]->w);
- dest.y = 0;
- dest.w = images[IMG_STOP]->w;
- dest.h = images[IMG_STOP]->h;
-
- SDL_BlitSurface(images[IMG_STOP], NULL, screen, &dest);
- }
-
- /* Draw cities/igloos and (if applicable) penguins: */
if (Opts_UseIgloos()) {
/* We have to draw respecting layering */
current_layer = 0;
@@ -1859,7 +1974,7 @@
dest.w = (this_image->w);
dest.h = (this_image->h);
SDL_BlitSurface(this_image, NULL, screen, &dest);
- }
+ }
}
current_layer++;
} while (current_layer <= max_layer);
@@ -1915,138 +2030,89 @@
}
- /* Draw comets: */
- /* NOTE bonus comets split into separate pass to make them */
- /* draw last (i.e. in front), as they can overlap */
+}
+void game_draw_misc(void)
+{
+ int offset;
+ SDL_Rect dest;
+ char str[64];
- /* First draw regular comets: */
- for (i = 0; i < MAX_COMETS; i++)
+ /* Draw "Demo" */
+ if (Opts_DemoMode())
{
- if (comets[i].alive && !comets[i].bonus)
- {
- if (comets[i].expl < COMET_EXPL_END)
- {
- /* Decide which image to display: */
- img = IMG_COMET1 + ((frame + i) % 3);
- /* Display the formula (flashing, in the bottom half
- of the screen) */
- if (comets[i].y < screen->h / 2 || frame % 8 < 6)
- {
- comet_str = comets[i].flashcard.formula_string;
- }
- else
- {
- comet_str = NULL;
- }
- }
- else
- {
- img = comets[i].expl;
- comet_str = comets[i].flashcard.answer_string;
- }
+ dest.x = (screen->w - images[IMG_DEMO]->w) / 2;
+ dest.y = (screen->h - images[IMG_DEMO]->h) / 2;
+ dest.w = images[IMG_DEMO]->w;
+ dest.h = images[IMG_DEMO]->h;
- /* Draw it! */
- dest.x = comets[i].x - (images[img]->w / 2);
- dest.y = comets[i].y - images[img]->h;
- dest.w = images[img]->w;
- dest.h = images[img]->h;
-
- SDL_BlitSurface(images[img], NULL, screen, &dest);
- if (comet_str != NULL)
- {
- draw_nums(comet_str, comets[i].x, comets[i].y);
- }
- }
+ SDL_BlitSurface(images[IMG_DEMO], NULL, screen, &dest);
}
- /* Now draw any bonus comets: */
- for (i = 0; i < MAX_COMETS; i++)
+ /* If we are playing through a defined list of questions */
+ /* without "recycling", display number of remaining questions: */
+ if (MC_PlayThroughList())
{
- if (comets[i].alive && comets[i].bonus)
- {
- if (comets[i].expl < COMET_EXPL_END)
- {
- /* Decide which image to display: */
- img = IMG_COMET1 + ((frame + i) % 3);
- /* Display the formula (flashing, in the bottom half
- of the screen) */
- if (comets[i].y < screen->h / 2 || frame % 8 < 6)
- {
- comet_str = comets[i].flashcard.formula_string;
- }
- else
- {
- comet_str = NULL;
- }
- }
- else
- {
- img = comets[i].expl;
- comet_str = comets[i].flashcard.answer_string;
- }
+ draw_question_counter();
+ }
- /* Move images[] index to bonus range: */
- img += IMG_BONUS_COMET1 - IMG_COMET1;
-
- /* Draw it! */
- dest.x = comets[i].x - (images[img]->w / 2);
- dest.y = comets[i].y - images[img]->h;
- dest.w = images[img]->w;
- dest.h = images[img]->h;
-
- SDL_BlitSurface(images[img], NULL, screen, &dest);
- if (comet_str != NULL)
- {
- draw_nums(comet_str, comets[i].x, comets[i].y);
- }
- }
+ if (extra_life_earned) {
+ /* Draw extra life earned icon */
+ dest.x = 0;
+ dest.y = 0;
+ dest.w = images[IMG_EXTRA_LIFE]->w;
+ dest.h = images[IMG_EXTRA_LIFE]->h;
+ SDL_BlitSurface(images[IMG_EXTRA_LIFE], NULL, screen, &dest);
+ } else if (bonus_comet_counter) {
+ /* Draw extra life progress bar */
+ dest.x = 0;
+ dest.y = images[IMG_EXTRA_LIFE]->h/4;
+ dest.h = images[IMG_EXTRA_LIFE]->h/2;
+ dest.w = ((Opts_BonusCometInterval() + 1 - bonus_comet_counter)
+ * images[IMG_EXTRA_LIFE]->w) / Opts_BonusCometInterval();
+ SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 0, 255, 0));
}
+ /* Draw wave: */
+ if (Opts_BonusCometInterval())
+ offset = images[IMG_EXTRA_LIFE]->w + 5;
+ else
+ offset = 0;
+ dest.x = offset;
+ dest.y = 0;
+ dest.w = images[IMG_WAVE]->w;
+ dest.h = images[IMG_WAVE]->h;
+ SDL_BlitSurface(images[IMG_WAVE], NULL, screen, &dest);
- /* Draw laser: */
- if (laser.alive)
- {
- draw_line(laser.x1, laser.y1, laser.x2, laser.y2,
- 255 / ((LASER_START + 1) - laser.alive),
- 192 / ((LASER_START + 1) - laser.alive),
- 64);
- }
+ sprintf(str, "%d", wave);
+ draw_numbers(str, offset+images[IMG_WAVE]->w + (images[IMG_NUMBERS]->w / 10), 0);
- /* Draw numeric keypad: */
- if (Opts_UseKeypad())
- {
- /* pick image to draw: */
- int keypad_image;
- if (MC_AllowNegatives())
- {
- /* draw regular keypad */
- keypad_image = IMG_KEYPAD;
- }
- else
- {
- /* draw keypad with with grayed-out '+' and '-' */
- keypad_image = IMG_KEYPAD_NO_NEG;
- }
+ /* Draw "score" label: */
+ dest.x = (screen->w - ((images[IMG_NUMBERS]->w / 10) * 7) -
+ images[IMG_SCORE]->w -
+ images[IMG_STOP]->w - 5);
+ dest.y = 0;
+ dest.w = images[IMG_SCORE]->w;
+ dest.h = images[IMG_SCORE]->h;
- /* now draw it: */
- dest.x = (screen->w - images[keypad_image]->w) / 2;
- dest.y = (screen->h - images[keypad_image]->h) / 2;
- dest.w = images[keypad_image]->w;
- dest.h = images[keypad_image]->h;
- SDL_BlitSurface(images[keypad_image], NULL, screen, &dest);
- }
+ SDL_BlitSurface(images[IMG_SCORE], NULL, screen, &dest);
- /* Draw console, LED numbers, & tux: */
- draw_led_console();
- draw_console_image(tux_img);
+ /* Draw score numbers: */
+ sprintf(str, "%.6d", score);
+ draw_numbers(str,
+ screen->w - ((images[IMG_NUMBERS]->w / 10) * 6) - images[IMG_STOP]->w - 5,
+ 0);
- /* Draw any messages on the screen (used for the help mode) */
- game_write_messages();
-
- /* Swap buffers: */
- SDL_Flip(screen);
+ /* Draw stop button: */
+ if (!help_controls.x_is_blinking || (frame % 10 < 5)) {
+ dest.x = (screen->w - images[IMG_STOP]->w);
+ dest.y = 0;
+ dest.w = images[IMG_STOP]->w;
+ dest.h = images[IMG_STOP]->h;
+
+ SDL_BlitSurface(images[IMG_STOP], NULL, screen, &dest);
+ }
}
int check_exit_conditions(void)
@@ -2070,7 +2136,7 @@
if (gameover_counter == 0)
return GAME_OVER_LOST;
}
-
+
/* determine if game won (i.e. all questions in mission answered correctly): */
if (MC_MissionAccomplished())
{
@@ -2092,11 +2158,11 @@
#ifdef TUXMATH_DEBUG
printf("\nListQuestionsLeft() = %d", MC_ListQuestionsLeft());
printf("\nnum_comets_alive = %d", num_comets_alive);
- #endif
+ #endif
return GAME_OVER_ERROR;
}
-
- /* If using demo mode, see if counter has run out: */
+
+ /* If using demo mode, see if counter has run out: */
if (Opts_DemoMode())
{
if (demo_countdown <= 0 )
@@ -2163,14 +2229,14 @@
void reset_level(void)
{
char fname[1024];
- int i;
+ int i;
int next_wave_comets;
int use_feedback;
float comet_avg_height,height_differential;
-
-
+
+
/* Clear all comets: */
-
+
for (i = 0; i < MAX_COMETS; i++)
{
comets[i].alive = 0;
@@ -2178,7 +2244,7 @@
num_comets_alive = 0;
/* Clear LED digits: */
-
+
digits[0] = 0;
digits[1] = 0;
digits[2] = 0;
@@ -2186,13 +2252,14 @@
- /* Load random background image: */
- do
- {
- /* Don't pick the same one as last time... */
- i = rand() % NUM_BKGDS;
- }
- while (i == last_bkgd);
+ /* Load random background image, but ensure it's different from this one: */
+ for (i = last_bkgd; i == last_bkgd; i = rand() % NUM_BKGDS);
+// do
+// {
+// /* Don't pick the same one as last time... */
+// i = rand() % NUM_BKGDS;
+// }
+// while (i == last_bkgd);
last_bkgd = i;
@@ -2245,17 +2312,17 @@
{
next_wave_comets = Opts_MaxComets();
}
-
+
use_feedback = Opts_UseFeedback();
- if (use_feedback)
+ if (use_feedback)
{
#ifdef FEEDBACK_DEBUG
printf("Evaluating feedback...\n old danger level = %g,",danger_level);
#endif
-
+
/* Update our danger level, i.e., the target height */
- danger_level = 1 - (1-danger_level) /
+ danger_level = 1 - (1-danger_level) /
Opts_DangerLevelSpeedup();
if (danger_level > Opts_DangerLevelMax())
danger_level = Opts_DangerLevelMax();
@@ -2273,7 +2340,7 @@
printf("No feedback data available, aborting.\n\n");
#endif
}
- else
+ else
{
/* Compute the average height of comet destruction. */
comet_avg_height = comet_feedback_height/comet_feedback_number;
@@ -2285,7 +2352,7 @@
/* height. That makes the changes a bit more conservative. */
#ifdef FEEDBACK_DEBUG
- printf(" comet average height = %g, height differential = %g.\n",
+ printf(" comet average height = %g, height differential = %g.\n",
comet_avg_height, height_differential);
printf(" old speed = %g,",speed);
#endif
@@ -2354,19 +2421,19 @@
found = i;
}
}
-
+
if (-1 == found)
{
/* free comet slot not found - no comet added: */
return 0;
}
-
+
/* Get math question for new comet - the following function fills in */
/* the flashcard struct that is part of the comet struct: */
if (!MC_NextQuestion(&(comets[found].flashcard)))
{
- /* no more questions available - cannot create comet. */
+ /* no more questions available - cannot create comet. */
return 0;
}
@@ -2399,20 +2466,20 @@
comets[found].alive = 1;
- num_comets_alive++;
+ num_comets_alive++;
/* Pick a city to attack that was not attacked last time */
/* (so formulas are less likely to overlap). */
- do
+ do
{
i = rand() % NUM_CITIES;
}
while (i == prev_city);
prev_city = i;
-
+
/* Set in to attack that city: */
- comets[found].city = i;
+ comets[found].city = i;
/* Start at the top, above the city in question: */
comets[found].x = cities[i].x;
comets[found].y = 0;
@@ -2455,7 +2522,7 @@
str_length = strlen(str);
/* IMG_NUMS now consists of 10 digit graphics, NUM_OPERS (i.e. 4) */
/* operation symbols, and the '=' and '?' symbols, all side by side. */
- /* char_width is the width of a single symbol. */
+ /* char_width is the width of a single symbol. */
char_width = (images[IMG_NUMS]->w / (16));
/* Calculate image_length, taking into account that the string will */
/* usually have four empty spaces that are only half as wide: */
@@ -2473,20 +2540,20 @@
/* Draw each character: */
-
+
for (i = 0; i < str_length; i++)
{
c = -1;
/* Determine which character to display: */
-
+
if (str[i] >= '0' && str[i] <= '9')
{
c = str[i] - '0';
}
else if ('=' == str[i])
- {
+ {
c = 14; /* determined by layout of nums.png image */
}
else if ('?' == str[i])
@@ -2503,7 +2570,7 @@
}
}
}
-
+
/* Display this character! */
if (c != -1)
{
@@ -2511,12 +2578,12 @@
src.y = 0;
src.w = char_width;
src.h = images[IMG_NUMS]->h;
-
+
dest.x = cur_x;
dest.y = y - images[IMG_NUMS]->h;
dest.w = src.w;
dest.h = src.h;
-
+
SDL_BlitSurface(images[IMG_NUMS], &src,
screen, &dest);
/* Move the 'cursor' one character width: */
@@ -2543,32 +2610,32 @@
/* Draw each character: */
-
+
for (i = 0; i < strlen(str); i++)
{
c = -1;
/* Determine which character to display: */
-
+
if (str[i] >= '0' && str[i] <= '9')
c = str[i] - '0';
-
+
/* Display this character! */
-
+
if (c != -1)
{
src.x = c * (images[IMG_NUMBERS]->w / 10);
src.y = 0;
src.w = (images[IMG_NUMBERS]->w / 10);
src.h = images[IMG_NUMBERS]->h;
-
+
dest.x = cur_x;
dest.y = y;
dest.w = src.w;
dest.h = src.h;
-
+
SDL_BlitSurface(images[IMG_NUMBERS], &src,
screen, &dest);
@@ -2597,7 +2664,7 @@
fprintf(stderr, "Pause requested but not allowed by Opts!\n");
return 0;
}
-
+
pause_done = 0;
pause_quit = 0;
@@ -2615,8 +2682,8 @@
if (Opts_UsingSound())
Mix_PauseMusic();
#endif
-
-
+
+
do
{
while (SDL_PollEvent(&event))
@@ -2641,7 +2708,7 @@
#endif
return (pause_quit);
-}
+}
@@ -2653,14 +2720,14 @@
float m, b;
Uint32 pixel;
SDL_Rect dest;
-
+
pixel = SDL_MapRGB(screen->format, red, grn, blu);
dx = x2 - x1;
dy = y2 - y1;
putpixel(screen, x1, y1, pixel);
-
+
if (dx != 0)
{
m = ((float) dy) / ((float) dx);
@@ -2675,7 +2742,7 @@
{
x1 = x1 + dx;
y1 = m * x1 + b;
-
+
putpixel(screen, x1, y1, pixel);
}
}
@@ -2687,7 +2754,7 @@
y1 = y2;
y2 = tmp;
}
-
+
dest.x = x1;
dest.y = y1;
dest.w = 3;
@@ -2705,27 +2772,27 @@
#ifdef PUTPIXEL_RAW
int bpp;
Uint8* p;
-
+
/* Determine bytes-per-pixel for the surface in question: */
-
+
bpp = surface->format->BytesPerPixel;
-
-
+
+
/* Set a pointer to the exact location in memory of the pixel
in question: */
-
+
p = (Uint8 *) (surface->pixels + /* Start at beginning of RAM */
(y * surface->pitch) + /* Go down Y lines */
(x * bpp)); /* Go in X pixels */
-
-
+
+
/* Assuming the X/Y values are within the bounds of this surface... */
-
+
if (x >= 0 && y >= 0 && x < surface->w && y < surface->h)
{
/* Set the (correctly-sized) piece of data in the surface's RAM
to the pixel value sent in: */
-
+
if (bpp == 1)
*p = pixel;
else if (bpp == 2)
@@ -2787,7 +2854,7 @@
int comet_x;
char str[64];
- SDL_Rect dest;
+ SDL_Rect dest;
/* Calculate placement based on image widths: */
nums_width = (images[IMG_NUMBERS]->w / 10) * 4; /* displaying 4 digits */
@@ -2803,7 +2870,7 @@
dest.y = 0;
dest.w = comet_width;
dest.h = images[comet_img]->h;
-
+
SDL_BlitSurface(images[comet_img], NULL, screen, &dest);
/* draw number of remaining questions: */
@@ -2824,7 +2891,7 @@
/* set y to draw LED numbers into Tux's "monitor": */
y = (screen->h
- images[IMG_CONSOLE_LED]->h
- + 4); /* "monitor" has 4 pixel margin */
+ + 4); /* "monitor" has 4 pixel margin */
/* begin drawing so as to center display depending on whether minus */
/* sign needed (4 digit slots) or not (3 digit slots) DSB */
@@ -2835,7 +2902,7 @@
for (i = -1; i < 3; i++) /* -1 is special case to allow minus sign */
/* with minimal modification of existing code DSB */
- {
+ {
if (-1 == i)
{
if (MC_AllowNegatives())
@@ -2848,11 +2915,11 @@
src.y = 0;
src.w = (images[IMG_LED_NEG_SIGN]->w) / 2;
src.h = images[IMG_LED_NEG_SIGN]->h;
-
+
dest.y = y;
dest.w = src.w;
dest.h = src.h;
-
+
SDL_BlitSurface(images[IMG_LED_NEG_SIGN], &src, screen, &dest);
/* move "cursor" */
dest.x += src.w;
@@ -2864,12 +2931,12 @@
src.y = 0;
src.w = (images[IMG_LEDNUMS]->w) / 10;
src.h = images[IMG_LEDNUMS]->h;
-
+
/* dest.x already set */
dest.y = y;
dest.w = src.w;
dest.h = src.h;
-
+
SDL_BlitSurface(images[IMG_LEDNUMS], &src, screen, &dest);
/* move "cursor" */
dest.x += src.w;
@@ -2895,10 +2962,10 @@
key = SDLK_ESCAPE;
game_key_event(key);
return;
- }
+ }
/* get out unless we really are using keypad */
- if ( level_start_wait
+ if ( level_start_wait
|| Opts_DemoMode()
|| !Opts_UseKeypad())
{
@@ -2929,7 +2996,7 @@
keypad_h = images[IMG_KEYPAD]->h;
}
}
-
+
if (!keypad_w || !keypad_h)
{
return;
@@ -2941,7 +3008,7 @@
(screen->w / 2) - (keypad_w / 2) &&
event.button.x <=
(screen->w / 2) + (keypad_w / 2) &&
- event.button.y >=
+ event.button.y >=
(screen->h / 2) - (keypad_h / 2) &&
event.button.y <=
(screen->h / 2) + (keypad_h / 2))))
@@ -2949,12 +3016,12 @@
{
return;
}
-
- else /* click was within keypad */
+
+ else /* click was within keypad */
{
x = (event.button.x - ((screen->w / 2) - (keypad_w / 2)));
y = (event.button.y - ((screen->h / 2) - (keypad_h / 2)));
-
+
/* Now determine what onscreen key was pressed */
/* */
/* The on-screen keypad has a 4 x 4 layout: */
@@ -3006,7 +3073,7 @@
key = SDLK_9;
if (3 == column)
key = SDLK_MINUS;
- }
+ }
if (1 == row)
{
if (0 == column)
@@ -3017,7 +3084,7 @@
key = SDLK_6;
if (3 == column)
key = SDLK_PLUS;
- }
+ }
if (2 == row)
{
if (0 == column)
@@ -3028,7 +3095,7 @@
key = SDLK_3;
if (3 == column)
key = SDLK_PLUS;
- }
+ }
if (3 == row)
{
if (0 == column)
@@ -3039,7 +3106,7 @@
key = SDLK_RETURN;
if (3 == column)
key = SDLK_RETURN;
- }
+ }
if (key == SDLK_UNKNOWN)
{
@@ -3095,7 +3162,9 @@
/* Toggle screen mode: */
else if (key == SDLK_F10)
{
+ Opts_SetFullscreen(!Opts_Fullscreen() );
SwitchScreenMode();
+ game_recalc_positions();
}
/* Toggle music: */
@@ -3107,7 +3176,7 @@
if (Mix_PlayingMusic())
{
Mix_HaltMusic();
- }
+ }
else
{
Mix_PlayMusic(musics[MUS_GAME + (rand() % 3)], 0);
@@ -3116,7 +3185,7 @@
}
#endif
-
+
if (level_start_wait > 0 || Opts_DemoMode() || !help_controls.laser_enabled)
{
/* Eat other keys until level start wait has passed,
@@ -3126,7 +3195,7 @@
/* The rest of the keys control the numeric answer console: */
-
+
if (key >= SDLK_0 && key <= SDLK_9)
{
/* [0]-[9]: Add a new digit: */
@@ -3197,8 +3266,8 @@
comets[i].x = 0;
comets[i].y = 0;
comets[i].answer = 0;
- strncpy(comets[i].flashcard.formula_string, " ", MC_FORMULA_LEN);
- strncpy(comets[i].flashcard.answer_string, " ", MC_ANSWER_LEN);
+ strncpy(comets[i].flashcard.formula_string, " ", MC_FORMULA_LEN);
+ strncpy(comets[i].flashcard.answer_string, " ", MC_ANSWER_LEN);
comets[i].bonus = 0;
}
}
@@ -3233,3 +3302,55 @@
free(penguins);
free(steam);
}
+
+/* Recalculate on-screen city & comet locations when screen dimensions change */
+void game_recalc_positions(void)
+{
+ int i, img;
+ int old_city_expl_height = city_expl_height;
+
+ tmdprintf("Recalculating positions\n");
+
+ if (Opts_UseIgloos())
+ img = IMG_IGLOO_INTACT;
+ else
+ img = IMG_CITY_BLUE;
+
+ for (i = 0; i < NUM_CITIES; ++i)
+ {
+ /* Left vs. Right - makes room for Tux and the console */
+ if (i < NUM_CITIES / 2)
+ {
+ cities[i].x = (((screen->w / (NUM_CITIES + 1)) * i) +
+ ((images[img] -> w) / 2));
+ tmdprintf("%d,", cities[i].x);
+ }
+ else
+ {
+ cities[i].x = screen->w -
+ (screen->w / (NUM_CITIES + 1) *
+ (i - NUM_CITIES / 2) +
+ images[img]->w / 2);
+ tmdprintf("%d,", cities[i].x);
+ }
+
+ penguins[i].x = cities[i].x;
+ }
+
+ city_expl_height = screen->h - images[IMG_CITY_BLUE]->h;
+ //move comets to a location 'equivalent' to where they were
+ //i.e. with the same amount of time left before impact
+ for (i = 0; i < MAX_COMETS; ++i)
+ {
+ if (!comets[i].alive)
+ continue;
+
+ comets[i].x = cities[comets[i].city].x;
+ //if (Opts_Fullscreen() )
+ comets[i].y = comets[i].y * city_expl_height / old_city_expl_height;
+ //else
+ // comets[i].y = comets[i].y * RES_Y / screen->h;
+ }
+
+
+}
Modified: tuxmath/trunk/src/highscore.c
===================================================================
--- tuxmath/trunk/src/highscore.c 2008-06-11 21:26:58 UTC (rev 512)
+++ tuxmath/trunk/src/highscore.c 2008-06-12 00:07:50 UTC (rev 513)
@@ -426,7 +426,7 @@
default_font, &white);
if (s)
{
- loc.x = 320 - (s->w/2);
+ loc.x = (screen->w/2) - (s->w/2);
loc.y = 110;
SDL_BlitSurface(s, NULL, screen, &loc);
SDL_FreeSurface(s);
@@ -436,7 +436,7 @@
default_font, &white);
if (s)
{
- loc.x = 320 - (s->w/2);
+ loc.x = (screen->w/2) - (s->w/2);
loc.y = 140;
SDL_BlitSurface(s, NULL, screen, &loc);
SDL_FreeSurface(s);
@@ -537,7 +537,7 @@
if (s)
{
/* set up loc and blit: */
- loc.x = 320 - (s->w/2);
+ loc.x = (screen->w/2) - (s->w/2);
loc.y = 200;
SDL_BlitSurface(s, NULL, screen, &loc);
Modified: tuxmath/trunk/src/setup.c
===================================================================
--- tuxmath/trunk/src/setup.c 2008-06-11 21:26:58 UTC (rev 512)
+++ tuxmath/trunk/src/setup.c 2008-06-12 00:07:50 UTC (rev 513)
@@ -18,7 +18,7 @@
Subversion repository:
https://svn.debian.alioth.org/tux4kids/tuxmath/
-
+
August 26, 2001 - Sept 18, 2007.
*/
@@ -51,6 +51,11 @@
/* Global data used in setup.c: */
/* (These are now 'extern'd in "tuxmath.h") */
+
+int fs_res_x = RES_X;
+int fs_res_y = RES_Y;
+
+
SDL_Surface* screen;
SDL_Surface* images[NUM_IMAGES];
/* Need special handling to generate flipped versions of images. This
@@ -70,6 +75,7 @@
IMG_PENGUIN_WALK_OFF3
};
+
#ifndef NOSOUND
Mix_Chunk* sounds[NUM_SOUNDS];
Mix_Music* musics[NUM_MUSICS];
@@ -152,7 +158,7 @@
/* from titlescreen, to allow for user-login to occur. */
void initialize_options_user(void)
{
- /* Read in user-specific settings, if desired. By */
+ /* Read in user-specific settings, if desired. By */
/* default, this restores settings from the player's last */
/* game: */
if (Opts_PerUserConfig())
@@ -184,7 +190,7 @@
}
#ifdef TUXMATH_DEBUG
- print_high_scores(stdout);
+ print_high_scores(stdout);
#endif
}
@@ -249,7 +255,7 @@
);
printf("\n");
-
+
cleanup_on_error();
exit(0);
}
@@ -274,7 +280,7 @@
strcmp(argv[i], "-u") == 0)
{
/* Display (happy) usage: */
-
+
usage(0, argv[0]);
}
else if (0 == strcmp(argv[i], "--homedir"))
@@ -305,7 +311,7 @@
}
else /* try to read file named in following arg: */
{
- if (!read_named_config_file(argv[i + 1]))
+ if (!read_named_config_file(argv[i + 1]))
{
fprintf(stderr, "Could not read config file: %s\n", argv[i + 1]);
}
@@ -456,7 +462,7 @@
/* Init SDL Audio: */
Opts_SetSoundHWAvailable(0); // By default no sound HW
if (Opts_UseSound())
- {
+ {
if (SDL_Init(SDL_INIT_AUDIO) < 0)
{
fprintf(stderr,
@@ -466,18 +472,21 @@
}
else {
//if (Mix_OpenAudio(44100, AUDIO_S16SYS, 2, 2048) < 0)
- if (Mix_OpenAudio(22050, AUDIO_S16SYS, 2, 2048) < 0)
+ if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, AUDIO_S16SYS, 2, 2048) < 0)
{
fprintf(stderr,
"\nWarning: I could not set up audio for 44100 Hz "
"16-bit stereo.\n"
"The Simple DirectMedia error that occured was:\n"
"%s\n\n", SDL_GetError());
+
}
}
n_timesopened = Mix_QuerySpec(&frequency,&format,&channels);
if (n_timesopened > 0)
Opts_SetSoundHWAvailable(1);
+ else
+ frequency = format = channels = 0; //more helpful than garbage
#ifdef TUXMATH_DEBUG
fprintf(stderr, "Sound mixer: frequency = %d, "
"format = %x, "
@@ -486,7 +495,7 @@
frequency,format,channels,n_timesopened);
#endif
}
-
+
#endif
{
SDL_VideoInfo *videoInfo;
@@ -495,21 +504,32 @@
if (videoInfo->hw_available)
{
surfaceMode = SDL_HWSURFACE;
-#ifdef TUXMATH_DEBUG
+#ifdef TUXMATH_DEBUG
printf("HW mode\n");
#endif
}
else
{
surfaceMode = SDL_SWSURFACE;
-#ifdef TUXMATH_DEBUG
+#ifdef TUXMATH_DEBUG
printf("SW mode\n");
#endif
}
+ //determine the best fullscreen resolution
+ int i;
+ SDL_Rect** modes = SDL_ListModes(videoInfo->vfmt, SDL_FULLSCREEN | surfaceMode);
+ if (modes != 0 && modes != -1) //if there _is_ a "best" resolution
+ {
+ fs_res_x = modes[0]->w;
+ fs_res_y = modes[0]->h;
+ tmdprintf("Optimal resolution is %dx%d\n", RES_X, RES_Y);
+ }
+
+
if (Opts_Fullscreen())
{
- screen = SDL_SetVideoMode(RES_X, RES_Y, PIXEL_BITS, SDL_FULLSCREEN | surfaceMode);
+ screen = SDL_SetVideoMode(fs_res_x, fs_res_y, PIXEL_BITS, SDL_FULLSCREEN | surfaceMode);
if (screen == NULL)
{
fprintf(stderr,
@@ -583,7 +603,6 @@
}
}
-
/* Created images that are blends of two other images to smooth out
the transitions. */
void generate_blended_images(void)
@@ -712,7 +731,7 @@
Mix_CloseAudio();
n_timesopened--;
}
-
+
#ifdef SDL_Pango
free_SDLPango_Context();
#endif
@@ -736,8 +755,8 @@
int masklen;
Uint8* mask;
SDL_Surface* icon;
-
-
+
+
/* Load icon into a surface: */
icon = IMG_Load(DATA_PREFIX "/images/icons/icon.png");
if (icon == NULL)
@@ -748,23 +767,23 @@
"%s\n\n", DATA_PREFIX "/images/icons/icon.png", SDL_GetError());
return;
}
-
-
+
+
/* Create mask: */
masklen = (((icon -> w) + 7) / 8) * (icon -> h);
mask = malloc(masklen * sizeof(Uint8));
memset(mask, 0xFF, masklen);
-
-
+
+
/* Set icon: */
SDL_WM_SetIcon(icon, mask);
-
-
+
+
/* Free icon surface & mask: */
free(mask);
SDL_FreeSurface(icon);
-
-
+
+
/* Seed random-number generator: */
srand(SDL_GetTicks());
}
Modified: tuxmath/trunk/src/titlescreen.c
===================================================================
--- tuxmath/trunk/src/titlescreen.c 2008-06-11 21:26:58 UTC (rev 512)
+++ tuxmath/trunk/src/titlescreen.c 2008-06-12 00:07:50 UTC (rev 513)
@@ -1,6 +1,6 @@
/***************************************************************************
- file: titlescreen.c
- - description: splash, title and menu screen functionality
+ - description: splash, title and menu screen functionality
------------------
begin : Thur May 4 2000
copyright : (C) 2000 by Sam Hart
@@ -103,7 +103,7 @@
"trophy",
"credits"
};
-
+
sprite **sprite_list = NULL;
/* reg and sel are used to create the translucent button backgrounds. */
@@ -118,8 +118,16 @@
Tuxdest,
Titledest,
stopRect,
+ Backrect, //location of the background
+ Tuxback, //the portion of the background actually covered by Tux
+ Titleback,//and that covered by the title
cursor;
+/* The background image scaled to fullscreen dimensions */
+SDL_Surface* scaled_bkgd = NULL;
+/* Set to scaled_bkgd if scaling fullscreen, images[IMG_MENU_BKG] otherwise */
+SDL_Surface* current_bkg = NULL; //DON'T SDL_Free()!
+
/* Local function prototypes: */
void TitleScreen_load_menu(void);
void TitleScreen_unload_menu(void);
@@ -131,7 +139,12 @@
void AddRect(SDL_Rect* src, SDL_Rect* dst);
void InitEngine(void);
void ShowMessage(char* str1, char* str2, char* str3, char* str4);
-void set_buttons_max_width(SDL_Rect *,int);
+void RecalcTitlePositions();
+void RecalcMenuPositions(int*, int, menu_options*, void (*)(menu_options*),
+ SDL_Rect**, SDL_Rect**, SDL_Rect**,
+ SDL_Rect**, SDL_Rect**, SDL_Rect**,
+ SDL_Rect*, SDL_Rect*);
+void set_buttons_max_width(SDL_Rect *, SDL_Rect *, int);
int run_main_menu(void);
int run_arcade_menu(void);
int run_custom_menu(void);
@@ -140,7 +153,6 @@
-
/***********************************************************/
/* */
/* "Public functions" (callable throughout program) */
@@ -160,7 +172,7 @@
Uint32 start = 0;
- int i;
+ int i;
int n_subdirs;
char **subdir_names;
@@ -178,10 +190,10 @@
/* --- setup colors we use --- */
black.r = 0x00; black.g = 0x00; black.b = 0x00;
gray.r = 0x80; gray.g = 0x80; gray.b = 0x80;
- dark_blue.r = 0x00; dark_blue.g = 0x00; dark_blue.b = 0x60;
+ dark_blue.r = 0x00; dark_blue.g = 0x00; dark_blue.b = 0x60;
red.r = 0xff; red.g = 0x00; red.b = 0x00;
white.r = 0xff; white.g = 0xff; white.b = 0xff;
- yellow.r = 0xff; yellow.g = 0xff; yellow.b = 0x00;
+ yellow.r = 0xff; yellow.g = 0xff; yellow.b = 0x00;
start = SDL_GetTicks();
@@ -189,7 +201,7 @@
/* StandbyScreen: Display the Standby screen: */
if (images[IMG_STANDBY])
- {
+ {
// Center horizontally
dest.x = ((screen->w) / 2) - (images[IMG_STANDBY]->w) / 2;
// Center vertically
@@ -201,8 +213,8 @@
SDL_BlitSurface(images[IMG_STANDBY], NULL, screen, &dest);
SDL_UpdateRect(screen, 0, 0, 0, 0);
}
-
+
/* --- wait --- */
while ((SDL_GetTicks() - start) < 2000)
@@ -213,7 +225,7 @@
&& event.key.keysym.sym == SDLK_ESCAPE)
{
return;
- }
+ }
SDL_Delay(50);
}
@@ -236,15 +248,23 @@
return;
}
+// if (screen->flags & SDL_FULLSCREEN)
+// current_bkg = scaled_bkgd;
+// else
+ current_bkg = images[IMG_MENU_BKG];
/* Draw background, if it loaded OK: */
- if (images[IMG_MENU_BKG])
+ if (current_bkg)
{
+ Backrect.x = (screen->w - current_bkg->w) / 2;
+ Backrect.y = (screen->h - current_bkg->h) / 2;
+ Backrect.w = current_bkg->w;
+ Backrect.h = current_bkg->h;
/* FIXME not sure TransWipe() works in Windows: */
- TransWipe(images[IMG_MENU_BKG], RANDOM_WIPE, 10, 20);
+ TransWipe(current_bkg, RANDOM_WIPE, 10, 20);
/* Make sure background gets drawn (since TransWipe() doesn't */
/* seem to work reliably as of yet): */
- SDL_BlitSurface(images[IMG_MENU_BKG], NULL, screen, NULL);
-
+ SDL_BlitSurface(current_bkg, NULL, screen, &Backrect);
+
}
/* Red "Stop" circle in upper right corner to go back to main menu: */
if (images[IMG_STOP])
@@ -260,41 +280,68 @@
/* --- Pull tux & logo onscreen --- */
/* NOTE we wind up with Tuxdest.y == (screen->h) - (Tux->frame[0]->h), */
/* and Titledest.x == 0. */
- if (images[IMG_MENU_BKG]
+ if (current_bkg
&& images[IMG_MENU_TITLE]
&& images[IMG_STOP]
&& Tux && Tux->frame[0])
{
+
Tuxdest.x = 0;
Tuxdest.y = screen->h;
- Tuxdest.w = Tux->frame[0]->w;
- Tuxdest.h = Tux->frame[0]->h;
+ Tuxback.x = Tuxdest.x - Backrect.x;
+ Tuxback.y = Tuxdest.y - Backrect.y;
+ Tuxdest.w = Tuxback.w = Tux->frame[0]->w;
+ Tuxdest.h = Tuxback.h = Tux->frame[0]->h;
+
Titledest.x = screen->w;
Titledest.y = 10;
- Titledest.w = images[IMG_MENU_TITLE]->w;
- Titledest.h = images[IMG_MENU_TITLE]->h;
+ Titleback.x = Titledest.x - Backrect.x;
+ Titleback.y = Titledest.y - Backrect.y;
+ Titledest.w = Titleback.w = images[IMG_MENU_TITLE]->w;
+ Titledest.h = Titleback.h = images[IMG_MENU_TITLE]->h;
for (i = 0; i < (PRE_ANIM_FRAMES * PRE_FRAME_MULT); i++)
{
start = SDL_GetTicks();
- SDL_BlitSurface(images[IMG_MENU_BKG], &Tuxdest, screen, &Tuxdest);
- SDL_BlitSurface(images[IMG_MENU_BKG], &Titledest, screen, &Titledest);
+ /*
+ if (inRect(Backrect, Tuxdest.x, Tuxdest.y) &&
+ inRect(Backrect, Tuxdest.x + Tuxdest.w, Tuxdest.y) &&
+ inRect(Backrect, Tuxdest.x, Tuxdest.y + Tuxdest.h) &&
+ inRect(Backrect, Tuxdest.x + Tuxdest.w, Tuxdest.y + Tuxdest.h) )
+ SDL_BlitSurface(images[IMG_MENU_BKG], &Tuxback, screen, &Tuxdest);
+ else
+ SDL_FillRect(screen, &Tuxdest, 0);
+ if (inRect(Backrect, Titledest.x, Titledest.y) &&
+ inRect(Backrect, Titledest.x + Titledest.w, Titledest.y) &&
+ inRect(Backrect, Titledest.x, Titledest.y + Titledest.h) &&
+ inRect(Backrect, Titledest.x + Titledest.w, Titledest.y + Titledest.h) )
+ SDL_BlitSurface(images[IMG_MENU_BKG], &Titleback, screen, &Titledest);
+ else
+ SDL_FillRect(screen, &Titledest, 0);
+ */
+
+ //just draw to the whole screen. Less error prone than the above at the cost of efficiency
+ SDL_FillRect(screen, &screen->clip_rect, 0);
+ SDL_BlitSurface(current_bkg, NULL, screen, &Backrect);
+
Tuxdest.y -= Tux->frame[0]->h / (PRE_ANIM_FRAMES * PRE_FRAME_MULT);
+ Tuxback.y -= Tux->frame[0]->h / (PRE_ANIM_FRAMES * PRE_FRAME_MULT);
Titledest.x -= (screen->w) / (PRE_ANIM_FRAMES * PRE_FRAME_MULT);
+ Titleback.y -= (screen->w) / (PRE_ANIM_FRAMES * PRE_FRAME_MULT);
SDL_BlitSurface(Tux->frame[0], NULL, screen, &Tuxdest);
SDL_BlitSurface(images[IMG_MENU_TITLE], NULL, screen, &Titledest);
SDL_BlitSurface(images[IMG_STOP], NULL, screen, &stopRect);
-
+
SDL_UpdateRect(screen, Tuxdest.x, Tuxdest.y, Tuxdest.w, Tuxdest.h);
SDL_UpdateRect(screen, Titledest.x, Titledest.y, Titledest.w + 40,
Titledest.h);
SDL_UpdateRect(screen, stopRect.x, stopRect.y, stopRect.w, stopRect.h);
- while ((SDL_GetTicks() - start) < 33)
+ while ((SDL_GetTicks() - start) < 33)
{
SDL_Delay(2);
}
@@ -367,12 +414,13 @@
sprite_list = (sprite**) malloc(N_SPRITES*sizeof(sprite*));
if (sprite_list == NULL)
return 0;
-
+
for (i = 0; i < N_SPRITES; i++) {
/* --- load animated icon for menu item --- */
sprintf(fn, "sprites/%s", menu_sprite_files[i]);
sprite_list[i] = LoadSprite(fn, IMG_ALPHA);
}
+ scaled_bkgd = zoom(images[IMG_MENU_BKG], fs_res_x, fs_res_y);
return 1;
}
@@ -396,6 +444,7 @@
FreeSprite(Tux);
Tux = NULL;
TitleScreen_unload_menu();
+ SDL_FreeSurface(scaled_bkgd);
}
@@ -452,7 +501,7 @@
// TTF_CloseFont(english_font);
// useEnglish = 0;
// }
-// else
+// else
// {
// s4 = black_outline( "tuxmath-devel at lists.sourceforge.net", default_font, &white);
// }
@@ -463,7 +512,7 @@
/* Redraw background: */
if (images[IMG_MENU_BKG])
- SDL_BlitSurface( images[IMG_MENU_BKG], NULL, screen, NULL );
+ SDL_BlitSurface( current_bkg, NULL, screen, &Backrect );
/* Red "Stop" circle in upper right corner to go back to main menu: */
if (images[IMG_STOP])
@@ -483,24 +532,24 @@
/* Draw lines of text (do after drawing Tux so text is in front): */
if (s1)
{
- loc.x = 320 - (s1->w/2); loc.y = 10;
+ loc.x = (screen->w / 2) - (s1->w/2); loc.y = 10;
SDL_BlitSurface( s1, NULL, screen, &loc);
}
if (s2)
{
- loc.x = 320 - (s2->w/2); loc.y = 60;
+ loc.x = (screen->w / 2) - (s2->w/2); loc.y = 60;
SDL_BlitSurface( s2, NULL, screen, &loc);
}
if (s3)
{
//loc.x = 320 - (s3->w/2); loc.y = 300;
- loc.x = 320 - (s3->w/2); loc.y = 110;
+ loc.x = (screen->w / 2) - (s3->w/2); loc.y = 110;
SDL_BlitSurface( s3, NULL, screen, &loc);
}
if (s4)
{
//loc.x = 320 - (s4->w/2); loc.y = 340;
- loc.x = 320 - (s4->w/2); loc.y = 200;
+ loc.x = (screen->w / 2) - (s4->w/2); loc.y = 200;
SDL_BlitSurface( s4, NULL, screen, &loc);
}
@@ -511,7 +560,7 @@
{
start = SDL_GetTicks();
- while (SDL_PollEvent(&event))
+ while (SDL_PollEvent(&event))
{
switch (event.type)
{
@@ -522,7 +571,7 @@
case SDL_MOUSEBUTTONDOWN:
/* "Stop" button - go to main menu: */
- {
+ {
if (inRect(stopRect, event.button.x, event.button.y ))
{
finished = 1;
@@ -544,7 +593,7 @@
case 0: tux_frame = 1; break;
case TUX1: tux_frame = 2; break;
case TUX2: tux_frame = 3; break;
- case TUX3: tux_frame = 4; break;
+ case TUX3: tux_frame = 4; break;
case TUX4: tux_frame = 3; break;
case TUX5: tux_frame = 2; break;
default: tux_frame = 0;
@@ -572,6 +621,10 @@
}
+void main_scmo(menu_options* mo) //set custum menu opts for main
+{
+ mo->ygap = 15;
+}
int run_main_menu(void)
{
const unsigned char* menu_text[6] =
@@ -594,14 +647,15 @@
sprites[4] = sprite_list[SPRITE_OPTIONS];
sprites[5] = sprite_list[SPRITE_QUIT];
- set_default_menu_options(&menu_opts);
- menu_opts.ytop = 100;
- menu_opts.ygap = 15;
+ //set_default_menu_options(&menu_opts);
+ //menu_opts.ytop = 100;
+ //menu_opts.ygap = 15;
+
//This function takes care of all the drawing and receives
//user input:
- choice = choose_menu_item(menu_text,sprites,6,menu_opts);
-
+ choice = choose_menu_item(menu_text,sprites,6,NULL,main_scmo);
+
while (choice >= 0) {
switch (choice) {
case 0: {
@@ -642,7 +696,7 @@
}
}
menu_opts.starting_entry = choice;
- choice = choose_menu_item(menu_text,sprites,6,menu_opts);
+ choice = choose_menu_item(menu_text,sprites,6,NULL,main_scmo);
}
return 0;
}
@@ -673,12 +727,12 @@
sprites[4] = sprite_list[SPRITE_TROPHY];
sprites[5] = sprite_list[SPRITE_MAIN];
- set_default_menu_options(&menu_opts);
- menu_opts.ytop = 100;
+// set_default_menu_options(&menu_opts);
+// menu_opts.ytop = 100;
//This function takes care of all the drawing and receives
//user input:
- choice = choose_menu_item(menu_text,sprites,6,menu_opts);
+ choice = choose_menu_item(menu_text,sprites,6,NULL,NULL);
while (choice >= 0) {
if (choice < 4) {
@@ -687,6 +741,7 @@
{
audioMusicUnload();
game();
+ RecalcTitlePositions();
if (Opts_MenuMusic()) {
audioMusicLoad( "tuxi.ogg", -1 );
}
@@ -694,9 +749,9 @@
read_high_scores(); /* Update, in case other users have added to it */
hs_table = arcade_high_score_tables[choice];
if (check_score_place(hs_table, Opts_LastScore()) < HIGH_SCORES_SAVED){
-
+
unsigned char player_name[HIGH_SCORE_NAME_LENGTH * 3];
-
+
/* Get name from player: */
HighScoreNameEntry(&player_name[0]);
insert_score(player_name, hs_table, Opts_LastScore());
@@ -707,10 +762,10 @@
/* save to disk: */
/* See "On File Locking" in fileops.c */
append_high_score(choice,Opts_LastScore(),&player_name[0]);
-
+
#ifdef TUXMATH_DEBUG
print_high_scores(stderr);
-#endif
+#endif
}
} else {
fprintf(stderr, "\nCould not find %s config file\n",arcade_config_files[choice]);
@@ -724,9 +779,9 @@
// Return to main menu
return 0;
}
-
+ set_default_menu_options(&menu_opts);
menu_opts.starting_entry = choice;
- choice = choose_menu_item(menu_text,sprites,6,menu_opts);
+ choice = choose_menu_item(menu_text,sprites,6,NULL, NULL);
}
return 0;
@@ -786,12 +841,12 @@
sprites[2] = sprite_list[SPRITE_CREDITS];
sprites[3] = sprite_list[SPRITE_MAIN];
- set_default_menu_options(&menu_opts);
- menu_opts.ytop = 100;
+ //set_default_menu_options(&menu_opts);
+ //menu_opts.ytop = 100;
//This function takes care of all the drawing and receives
//user input:
- choice = choose_menu_item(menu_text,sprites,n_menu_entries,menu_opts);
+ choice = choose_menu_item(menu_text,sprites,n_menu_entries,NULL,NULL);
while (choice >= 0) {
switch (choice) {
@@ -838,14 +893,19 @@
}
}
+ set_default_menu_options(&menu_opts);
menu_opts.starting_entry = choice;
- choice = choose_menu_item(menu_text,sprites,n_menu_entries,menu_opts);
+ choice = choose_menu_item(menu_text,sprites,n_menu_entries,NULL,NULL);
}
return 0;
}
+void lessons_scmo(menu_options* mo)
+{
+mo->ytop = 30;
+}
/* Display a list of tuxmath config files in the missions directory */
/* and allow the player to pick one (AKA "Lessons"). */
@@ -871,28 +931,30 @@
star_sprites[i] = sprite_list[SPRITE_NO_GOLDSTAR];
}
}
- set_default_menu_options(&menu_opts);
+// set_default_menu_options(&menu_opts);
+// ytop = 30;
//This function takes care of all the drawing and receives
//user input:
- chosen_lesson = choose_menu_item((const unsigned char**)lesson_list_titles, star_sprites, num_lessons, menu_opts);
+ chosen_lesson = choose_menu_item((const unsigned char**)lesson_list_titles, star_sprites, num_lessons, NULL, &lessons_scmo);
- while (chosen_lesson >= 0)
+ while (chosen_lesson >= 0)
{
if (Opts_MenuSound())
playsound(SND_POP);
-
+
/* Re-read global settings first in case any settings were */
/* clobbered by other lesson or arcade games this session: */
read_global_config_file();
-
- /* Now read the selected file and play the "mission": */
+ /* Now read the selected file and play the "mission": */
if (read_named_config_file(lesson_list_filenames[chosen_lesson]))
{
if (Opts_MenuMusic()) //Turn menu music off for game
{audioMusicUnload();}
+
game();
+ RecalcTitlePositions();
/* If successful, display Gold Star for this lesson! */
if (MC_MissionAccomplished())
@@ -913,8 +975,9 @@
}
// Let the user choose another lesson; start with the screen and
// selection that we ended with
+ set_default_menu_options(&menu_opts);
menu_opts.starting_entry = chosen_lesson;
- chosen_lesson = choose_menu_item((const unsigned char**)lesson_list_titles, star_sprites, num_lessons, menu_opts);
+ chosen_lesson = choose_menu_item((const unsigned char**)lesson_list_titles, star_sprites, num_lessons, &menu_opts, &lessons_scmo);
}
if (star_sprites)
{
@@ -951,7 +1014,7 @@
// Check for & read user_menu_entries file
n_users = read_user_menu_entries(&user_names);
-
+
if (n_users == 0)
return 0; // a quick exit, there's only one user
@@ -967,7 +1030,7 @@
while (n_users) {
// Get the user choice
- chosen_login = choose_menu_item(user_names, NULL, n_users, menu_opts);
+ chosen_login = choose_menu_item(user_names, NULL, n_users, &menu_opts, NULL);
// Determine whether there were any modifier (CTRL) keys pressed
mod = SDL_GetModState();
if (chosen_login == -1 || chosen_login == n_users) {
@@ -1037,7 +1100,7 @@
/* (the function returns the index for the selected menu item) */
/* -1 indicates that the user pressed escape */
/****************************************************************/
-int choose_menu_item(const unsigned char **menu_text, sprite **menu_sprites, int n_menu_entries, menu_options menu_opts)
+int choose_menu_item(const unsigned char **menu_text, sprite **menu_sprites, int n_menu_entries, menu_options* custom_mo, void (*set_custom_menu_opts)(menu_options*) )
{
// Pixel renderings of menu text choices
SDL_Surface **menu_item_unselected = NULL;
@@ -1049,10 +1112,17 @@
// Menu sprite locations
SDL_Rect *menu_sprite_rect = NULL;
+ // The section of the background that the menu rects actually cover
+ SDL_Rect *back_text_rect = NULL,
+ *back_button_rect = NULL,
+ *back_sprite_rect = NULL;
SDL_Rect left_arrow_rect, right_arrow_rect;
+ SDL_Rect temp_rect; //temporary copy of a dest rect that may be written to by SDL_BlitSurface
+ menu_options menu_opts;
+
Uint32 frame_counter = 0;
- Uint32 frame_start = 0; //For keeping frame rate constant
+ Uint32 frame_start = 0; //For keeping frame rate constant
Uint32 frame_now = 0;
int stop = 0;
int loc = 0; //The currently selected menu item
@@ -1081,6 +1151,14 @@
fprintf(stderr,"%s\n",menu_text[i]);
#endif
+ if (custom_mo == NULL)
+ set_default_menu_options(&menu_opts);
+ else
+ menu_opts = *custom_mo;
+ if (set_custom_menu_opts != NULL)
+ set_custom_menu_opts(&menu_opts);
+
+ tmdprintf("Allocating memory\n");
/**** Memory allocation for menu text ****/
title_offset = 0;
if (menu_opts.title != NULL)
@@ -1115,6 +1193,8 @@
// the total entries including the title & trailer
n_menu_entries += title_offset+have_trailer;
+// recalcMenuPositions();
+
/**** Calculate the menu item heights and the number of ****/
/**** entries per screen ****/
if (menu_opts.buttonheight <= 0) {
@@ -1139,15 +1219,22 @@
/**** Memory allocation for current screen rects ****/
menu_text_rect = (SDL_Rect*) malloc(n_entries_per_screen * sizeof(SDL_Rect));
menu_button_rect = (SDL_Rect*) malloc(n_entries_per_screen * sizeof(SDL_Rect));
- if (menu_text_rect == NULL || menu_button_rect == NULL) {
+ back_text_rect = (SDL_Rect*) malloc(n_entries_per_screen * sizeof(SDL_Rect));
+ back_button_rect = (SDL_Rect*) malloc(n_entries_per_screen * sizeof(SDL_Rect));
+ if (menu_text_rect == NULL || menu_button_rect == NULL ||
+ back_text_rect == NULL || back_button_rect == NULL) {
free(menu_text_rect);
free(menu_button_rect);
+ free(back_text_rect);
+ free(back_button_rect);
return -2;
}
if (menu_sprites != NULL) {
menu_sprite_rect = (SDL_Rect*) malloc(n_entries_per_screen * sizeof(SDL_Rect));
- if (menu_sprite_rect == NULL) {
+ back_sprite_rect = (SDL_Rect*) malloc(n_entries_per_screen * sizeof(SDL_Rect));
+ if (menu_sprite_rect == NULL || back_sprite_rect == NULL) {
free(menu_sprite_rect);
+ free(back_sprite_rect);
return -2;
}
}
@@ -1188,7 +1275,7 @@
loc_screen_start = 0; // in case starting_entry was -1 (or wasn't set)
imod = loc-loc_screen_start;
for (i = 0; i < n_entries_per_screen; i++)
- {
+ {
menu_button_rect[i].x = menu_opts.xleft;
menu_text_rect[i].x = menu_opts.xleft + 15; // 15 is left gap
if (menu_sprites != NULL)
@@ -1212,12 +1299,28 @@
menu_sprite_rect[i].h = 50;
}
}
+
if (menu_opts.button_same_width)
- set_buttons_max_width(menu_button_rect,n_entries_per_screen);
+ set_buttons_max_width(menu_button_rect,back_button_rect,n_entries_per_screen);
+ for (i = 0; i < n_entries_per_screen; ++i)
+ {
+ back_button_rect[i] = menu_button_rect[i];
+ back_button_rect[i].x -= Backrect.x;
+ back_button_rect[i].y -= Backrect.y;
+
+ back_text_rect[i] = menu_text_rect[i];
+ back_text_rect[i].x -= Backrect.x;
+ back_text_rect[i].y -= Backrect.y;
+
+ back_sprite_rect[i] = menu_sprite_rect[i];
+ back_sprite_rect[i].x -= Backrect.x;
+ back_sprite_rect[i].y -= Backrect.y;
+ }
+
/**** Draw background, title, and Tux: ****/
- if (images[IMG_MENU_BKG])
- SDL_BlitSurface(images[IMG_MENU_BKG], NULL, screen, NULL);
+ if (current_bkg)
+ SDL_BlitSurface(current_bkg, NULL, screen, &Backrect);
if (images[IMG_MENU_TITLE])
SDL_BlitSurface(images[IMG_MENU_TITLE], NULL, screen, &Titledest);
if (Tux && Tux->frame[0])
@@ -1249,7 +1352,7 @@
//exit(0);
break;
}
-
+
case SDL_MOUSEMOTION:
{
loc = -1; // By default, don't be in any entry
@@ -1258,7 +1361,7 @@
if (inRect(menu_button_rect[i], event.motion.x, event.motion.y))
{
// Play sound if loc is being changed:
- if (Opts_MenuSound() && (old_loc != loc_screen_start + i))
+ if (Opts_MenuSound() && (old_loc != loc_screen_start + i))
{
playsound(SND_TOCK);
}
@@ -1319,7 +1422,7 @@
break;
}
}
-
+
/* "Left" button - go to previous page: */
if (inRect(left_arrow_rect, event.button.x, event.button.y))
{
@@ -1368,7 +1471,7 @@
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
- {
+ {
stop = 2;
break;
}
@@ -1410,7 +1513,7 @@
loc = -1;
}
// {loc = (loc_screen_start + n_entries_per_screen);}
- break;
+ break;
}
/* Go up one entry, if present: */
@@ -1446,14 +1549,29 @@
loc = loc_screen_start;
if (loc != old_loc)
warp_mouse = 1;
- break;
+ break;
}
/* Toggle screen mode: */
- case SDLK_F10:
+ case SDLK_F10:
{
SwitchScreenMode();
+ RecalcTitlePositions();
+ RecalcMenuPositions(&n_entries_per_screen,
+ n_menu_entries,
+ &menu_opts,
+ set_custom_menu_opts,
+ &menu_button_rect,
+ &menu_sprite_rect,
+ &menu_text_rect,
+ &back_button_rect,
+ &back_sprite_rect,
+ &back_text_rect,
+ &left_arrow_rect,
+ &right_arrow_rect);
+ //we're unsure how the entries might shuffle, so return to start
+ loc_screen_start = 0;
redraw = 1;
break;
}
@@ -1493,21 +1611,23 @@
/* Redraw screen: */
if (loc >= 0)
loc_screen_start = loc - (loc % n_entries_per_screen);
- if (old_loc_screen_start != loc_screen_start)
+ if (old_loc_screen_start != loc_screen_start)
redraw = 1;
if (redraw)
{
+ tmdprintf("Updating entire screen\n");
/* This is a full-screen redraw */
/* Redraw background, title, stop button, and Tux: */
- if (images[IMG_MENU_BKG])
- SDL_BlitSurface(images[IMG_MENU_BKG], NULL, screen, NULL);
+ if (!current_bkg || Opts_Fullscreen() )
+ SDL_FillRect(screen, &screen->clip_rect, 0); //clear to black
+ if (current_bkg)
+ SDL_BlitSurface(current_bkg, NULL, screen, &Backrect);
if (images[IMG_MENU_TITLE])
SDL_BlitSurface(images[IMG_MENU_TITLE], NULL, screen, &Titledest);
if (images[IMG_STOP])
SDL_BlitSurface(images[IMG_STOP], NULL, screen, &stopRect);
if (Tux->frame[0])
SDL_BlitSurface(Tux->frame[0], NULL, screen, &Tuxdest);
-
/* Redraw the menu entries */
for (imod = 0; imod < n_entries_per_screen; imod++)
menu_button_rect[imod].w = 0; // so undrawn buttons don't affect width
@@ -1521,11 +1641,10 @@
}
if (menu_opts.button_same_width)
- set_buttons_max_width(menu_button_rect,n_entries_per_screen);
+ set_buttons_max_width(menu_button_rect,back_button_rect,n_entries_per_screen);
// Make sure the menu title mouse button didn't get turned on
if (loc_screen_start == 0 && title_offset)
menu_button_rect[0].w = 0;
-
for (i = loc_screen_start, imod = 0; i < loc_screen_start+n_entries_per_screen && i < n_menu_entries; i++, imod++) {
if (i == loc) { //Draw text in yellow
DrawButton(&menu_button_rect[imod], 10, SEL_RGBA);
@@ -1560,36 +1679,44 @@
SDL_BlitSurface(images[IMG_RIGHT_GRAY], NULL, screen, &right_arrow_rect);
}
}
- SDL_UpdateRect(screen, 0, 0, 0 ,0);
+ SDL_Flip(screen);//SDL_UpdateRect(screen, 0, 0, 0 ,0);
} else if (old_loc != loc) {
// This is not a full redraw, but the selected entry did change.
// By just redrawing the old and new selections, we avoid flickering.
if (old_loc >= 0) {
imod = old_loc-loc_screen_start;
use_sprite = (menu_sprites != NULL && old_loc >= title_offset && menu_sprites[old_loc-title_offset] != NULL);
- SDL_BlitSurface(images[IMG_MENU_BKG], &menu_button_rect[imod], screen, &menu_button_rect[imod]); // redraw background
+ temp_rect = menu_button_rect[imod];
+ SDL_FillRect(screen, &temp_rect, 0);
+ SDL_BlitSurface(current_bkg, &back_button_rect[imod], screen, &temp_rect); // redraw background
if (use_sprite) {
// Some of the sprites extend beyond the menu button, so we
// have to make sure we redraw in the sprite rects, too
- SDL_BlitSurface(images[IMG_MENU_BKG], &menu_sprite_rect[imod], screen, &menu_sprite_rect[imod]);
+ SDL_BlitSurface(current_bkg, &back_sprite_rect[imod], screen, &temp_rect);
}
DrawButton(&menu_button_rect[imod], 10, REG_RGBA); // draw button
+ //temp_rect = menu_text_rect[imod];
SDL_BlitSurface(menu_item_unselected[old_loc], NULL, screen, &menu_text_rect[imod]); // draw text
if (use_sprite) {
- SDL_BlitSurface(menu_sprites[old_loc-title_offset]->default_img, NULL, screen, &menu_sprite_rect[imod]);
+ temp_rect = menu_sprite_rect[imod];
+ tmdprintf("Sprite %d at (%d %d)\n", imod, temp_rect.x, temp_rect.y);
+ SDL_BlitSurface(menu_sprites[old_loc-title_offset]->default_img, NULL, screen, &temp_rect);
// Also update the sprite rect (in some cases the sprite
// extends beyond the menu button)
SDL_UpdateRect(screen, menu_sprite_rect[imod].x, menu_sprite_rect[imod].y, menu_sprite_rect[imod].w, menu_sprite_rect[imod].h);
}
SDL_UpdateRect(screen, menu_button_rect[imod].x, menu_button_rect[imod].y, menu_button_rect[imod].w, menu_button_rect[imod].h);
}
-
if (loc >= 0) {
imod = loc-loc_screen_start;
use_sprite = (menu_sprites != NULL && loc >= title_offset && menu_sprites[loc] != NULL);
- SDL_BlitSurface(images[IMG_MENU_BKG], &menu_button_rect[imod], screen, &menu_button_rect[imod]);
+ temp_rect = menu_button_rect[imod];
+ SDL_BlitSurface(current_bkg, &back_button_rect[imod], screen, &temp_rect);
if (use_sprite)
- SDL_BlitSurface(images[IMG_MENU_BKG], &menu_sprite_rect[imod], screen, &menu_sprite_rect[imod]);
+ {
+ temp_rect = menu_sprite_rect[imod];
+ SDL_BlitSurface(current_bkg, &back_sprite_rect[imod], screen, &temp_rect);
+ }
DrawButton(&menu_button_rect[imod], 10, SEL_RGBA);
SDL_BlitSurface(menu_item_selected[loc], NULL, screen, &menu_text_rect[imod]);
if (use_sprite) {
@@ -1599,14 +1726,16 @@
next_frame(menu_sprites[loc-title_offset]);
}
SDL_UpdateRect(screen, menu_button_rect[imod].x, menu_button_rect[imod].y, menu_button_rect[imod].w, menu_button_rect[imod].h);
+ tmdprintf("Updating rect: %d %d %d %d\n", menu_button_rect[imod].x, menu_button_rect[imod].y, menu_button_rect[imod].w, menu_button_rect[imod].h);
}
} else if (frame_counter % 5 == 0 && loc >= 0) {
// No user input changed anything, but check to see if we need to
// animate the sprite
if (menu_sprites != NULL && loc >= title_offset && menu_sprites[loc-title_offset] != NULL) {
imod = loc-loc_screen_start;
- //SDL_BlitSurface(images[IMG_MENU_BKG], &menu_button_rect[imod], screen, &menu_button_rect[imod]);
- SDL_BlitSurface(images[IMG_MENU_BKG], &menu_sprite_rect[imod], screen, &menu_sprite_rect[imod]);
+ //SDL_BlitSurface(current_bkg, &menu_button_rect[imod], screen, &menu_button_rect[imod]);
+ temp_rect = menu_sprite_rect[imod];
+ SDL_BlitSurface(current_bkg, &back_sprite_rect[imod], screen, &temp_rect);
DrawButton(&menu_button_rect[imod], 10, SEL_RGBA);
//SDL_BlitSurface(menu_item_selected[loc], NULL, screen, &menu_text_rect[imod]);
// Note: even though the whole button was redrawn, we don't
@@ -1634,13 +1763,15 @@
old_loc = loc;
old_loc_screen_start = loc_screen_start;
+
+
/* --- make Tux blink --- */
switch (frame_counter % TUX6)
{
case 0: tux_frame = 1; break;
case TUX1: tux_frame = 2; break;
case TUX2: tux_frame = 3; break;
- case TUX3: tux_frame = 4; break;
+ case TUX3: tux_frame = 4; break;
case TUX4: tux_frame = 3; break;
case TUX5: tux_frame = 2; break;
default: tux_frame = 0;
@@ -1649,7 +1780,7 @@
if (Tux && tux_frame)
{
/* Redraw background to keep edges anti-aliased properly: */
- SDL_BlitSurface(images[IMG_MENU_BKG],&Tuxdest, screen, &Tuxdest);
+ SDL_BlitSurface(current_bkg,&Tuxdest, screen, &Tuxdest);
SDL_BlitSurface(Tux->frame[tux_frame - 1], NULL, screen, &Tuxdest);
SDL_UpdateRect(screen, Tuxdest.x, Tuxdest.y, Tuxdest.w, Tuxdest.h);
//SDL_UpdateRect(screen, 0, 0, 0, 0);
@@ -1668,7 +1799,7 @@
/***** User made a choice, clean up and return the choice. ******/
- /* --- clear graphics before leaving function --- */
+ /* --- clear graphics before leaving function --- */
for (i = 0; i < n_menu_entries; i++)
{
SDL_FreeSurface(menu_item_unselected[i]);
@@ -1689,7 +1820,8 @@
-void set_buttons_max_width(SDL_Rect *menu_button_rect,int n)
+void set_buttons_max_width(SDL_Rect *menu_button_rect,
+ SDL_Rect *back_button_rect, int n)
{
int i,max;
@@ -1699,7 +1831,9 @@
max = menu_button_rect[i].w;
for (i = 0; i < n; i++)
- menu_button_rect[i].w = max;
+ menu_button_rect[i].w = back_button_rect[i].w = max;
+
+ tmdprintf("All buttons at width %d\n", max);
}
// Was in playgame.c in tuxtype:
@@ -1752,10 +1886,10 @@
var2 is how many frames animation should take */
if( var1 < 1 ) var1 = 1;
if( var2 < 1 ) var2 = 1;
- step1 = screen->w / var1;
+ step1 = screen->w / var1;
step2 = step1 / var2;
- for(i = 0; i <= var2; i++)
+ for(i = 0; i <= var2; i++)
{
for(j = 0; j <= var1; j++)
{
@@ -1904,20 +2038,20 @@
/* -- First erase everything we need to -- */
for (i = 0; i < numupdates; i++)
- if (blits[i].type == 'E')
+ if (blits[i].type == 'E')
SDL_LowerBlit(blits[i].src, blits[i].srcrect, screen, blits[i].dstrect);
// SNOW_erase();
- /* -- then draw -- */
+ /* -- then draw -- */
for (i = 0; i < numupdates; i++)
- if (blits[i].type == 'D')
+ if (blits[i].type == 'D')
SDL_BlitSurface(blits[i].src, blits[i].srcrect, screen, blits[i].dstrect);
// SNOW_draw();
/* -- update the screen only where we need to! -- */
-// if (SNOW_on)
+// if (SNOW_on)
// SDL_UpdateRects(screen, SNOW_add( (SDL_Rect*)&dstupdate, numupdates ), SNOW_rects);
-// else
+// else
SDL_UpdateRects(screen, numupdates, dstupdate);
numupdates = 0;
@@ -1937,7 +2071,7 @@
if (!src || !dst)
{
-#ifdef TUXMATH_DEBUG
+#ifdef TUXMATH_DEBUG
fprintf(stderr, "AddRect(): src or dst invalid!\n");
#endif
return;
@@ -1963,7 +2097,7 @@
int i;
/* --- Set up the update rectangle pointers --- */
-
+
for (i = 0; i < MAX_UPDATES; ++i) {
blits[i].srcrect = &srcupdate[i];
blits[i].dstrect = &dstupdate[i];
@@ -1974,8 +2108,8 @@
void set_default_menu_options(menu_options *menu_opts)
{
menu_opts->starting_entry = 0;
- menu_opts->xleft = 240;
- menu_opts->ytop = 30;
+ menu_opts->xleft = screen->w / 2 - 60;
+ menu_opts->ytop = (screen->h - current_bkg->h) / 2 + 100;
// Leave room for arrows at the bottom:
menu_opts->ybottom = screen->h - images[IMG_LEFT]->h - 20;
menu_opts->buttonheight = -1;
@@ -1984,3 +2118,148 @@
menu_opts->title = NULL;
menu_opts->trailer = NULL;
}
+
+/* Recalculate on-screen locations for title screen elements */
+void RecalcTitlePositions()
+{
+// if (screen->flags & SDL_FULLSCREEN)
+// current_bkg = scaled_bkgd;
+// else
+ current_bkg = images[IMG_MENU_BKG];
+ Backrect = current_bkg->clip_rect;
+ Backrect.x = (screen->w - Backrect.w) / 2;
+ Backrect.y = (screen->h - Backrect.h) / 2;
+ Titledest.x = 0;
+ Titledest.y = 0;
+ Tuxdest.x = 0;
+ Tuxdest.y = screen->h - Tuxdest.h;
+ stopRect.x = screen->w - stopRect.w;
+ stopRect.y = 0;
+}
+
+/* Recalculate on-screen locations for menus when screen dimensions change */
+/* Perhaps consider generalizing this for use in initial menu calculations? */
+void RecalcMenuPositions(int* numentries,
+ int totalentries,
+ menu_options* mo,
+ void (*set_custom_menu_opts)(menu_options*),
+ SDL_Rect** menu_button_rect,
+ SDL_Rect** menu_sprite_rect,
+ SDL_Rect** menu_text_rect,
+ SDL_Rect** back_button_rect,
+ SDL_Rect** back_sprite_rect,
+ SDL_Rect** back_text_rect,
+ SDL_Rect* left_arrow_rect,
+ SDL_Rect* right_arrow_rect)
+{
+ int i, imod;
+ SDL_Rect* old_mbr = *menu_button_rect;
+ SDL_Rect* old_msr = *menu_sprite_rect;
+ SDL_Rect* old_mtr = *menu_text_rect;
+ SDL_Rect* old_bbr = *back_button_rect;
+ SDL_Rect* old_bsr = *back_sprite_rect;
+ SDL_Rect* old_btr = *back_text_rect;
+
+ int old_ne = *numentries;
+ int buttonheight = old_mbr->h; //height shouldn't change
+ int textwidth = old_mtr->w; //neither should width =P
+
+ right_arrow_rect->x = screen->w - images[IMG_RIGHT]->w - 20;
+ right_arrow_rect->y = screen->h - images[IMG_RIGHT]->h - 20;
+ left_arrow_rect->x = right_arrow_rect->x - 10 - images[IMG_LEFT]->w;
+ left_arrow_rect->y = screen->h - images[IMG_LEFT]->h - 20;
+
+ set_default_menu_options(mo);
+ if (set_custom_menu_opts != NULL)
+ set_custom_menu_opts(mo);
+
+ *numentries = (int)(screen->h - mo->ytop+mo->ygap)/(buttonheight + mo->ygap);
+ if (*numentries < totalentries)
+ *numentries = (int)(mo->ybottom - mo->ytop+mo->ygap)/(buttonheight + mo->ygap);
+ if (*numentries > totalentries)
+ *numentries = totalentries;
+
+
+
+
+ /**** Memory allocation for new screen rects ****/
+ *menu_text_rect = (SDL_Rect*) malloc(*numentries * sizeof(SDL_Rect));
+ *menu_button_rect = (SDL_Rect*) malloc(*numentries * sizeof(SDL_Rect));
+ *menu_sprite_rect = (SDL_Rect*) malloc(*numentries * sizeof(SDL_Rect));
+ *back_text_rect = (SDL_Rect*) malloc(*numentries * sizeof(SDL_Rect));
+ *back_button_rect = (SDL_Rect*) malloc(*numentries * sizeof(SDL_Rect));
+ *back_sprite_rect = (SDL_Rect*) malloc(*numentries * sizeof(SDL_Rect));
+ if (*menu_text_rect == NULL ||
+ *back_text_rect == NULL ||
+ *menu_button_rect == NULL ||
+ *back_button_rect == NULL ||
+ *menu_sprite_rect == NULL ||
+ *back_sprite_rect == NULL) {
+ free(*menu_text_rect);
+ free(*menu_button_rect);
+ free(*menu_sprite_rect);
+ free(*back_text_rect);
+ free(*back_button_rect);
+ free(*back_sprite_rect);
+ *menu_text_rect = old_mtr;
+ *menu_button_rect = old_mbr;
+ *menu_sprite_rect = old_msr;
+ *numentries = old_ne;
+ return;
+ }
+ else {
+ free(old_mtr);
+ free(old_mbr);
+ free(old_msr);
+ free(old_btr);
+ free(old_bbr);
+ free(old_bsr);
+ }
+
+
+ //note: the [0] notation is merely to avoid typing out (*menu_xxx_rect)[i]
+ for (i = 0; i < *numentries; i++)
+ {
+ menu_button_rect[0][i].x = mo->xleft;
+ menu_text_rect[0][i].x = mo->xleft + 15; // 15 is left gap
+ menu_text_rect[0][i].x += 60; // for now, assume we have a sprite
+ if (i > 0)
+ menu_text_rect[0][i].y = menu_text_rect[0][i - 1].y + buttonheight + mo->ygap;
+ else
+ menu_text_rect[0][i].y = mo->ytop;
+
+ menu_button_rect[0][i].y = menu_text_rect[0][i].y - 5;
+ menu_text_rect[0][i].h = buttonheight - 10;
+ menu_button_rect[0][i].h = buttonheight;
+
+ menu_text_rect[0][i].w = textwidth;
+ menu_button_rect[0][i].w = menu_text_rect[0][i].w + 30;
+
+ if (menu_sprite_rect != NULL) {
+ menu_sprite_rect[0][i].x = menu_button_rect[0][i].x + 3;
+ menu_sprite_rect[0][i].y = menu_button_rect[0][i].y + 3;
+ menu_sprite_rect[0][i].w = 40;
+ menu_sprite_rect[0][i].h = 50;
+ }
+ tmdprintf("***Rects[%d]****\n", i);
+ tmdprintf("%3d %3d %3d %3d\n", menu_button_rect[0][i].x, menu_button_rect[0][i].y, menu_button_rect[0][i].w, menu_button_rect[0][i].h);
+ tmdprintf("%3d %3d %3d %3d\n", menu_text_rect[0][i].x, menu_text_rect[0][i].y, menu_text_rect[0][i].w, menu_text_rect[0][i].h);
+ tmdprintf("%3d %3d %3d %3d\n", menu_sprite_rect[0][i].x, menu_sprite_rect[0][i].y, menu_sprite_rect[0][i].w, menu_sprite_rect[0][i].h);
+ tmdprintf("***************\n");
+ }
+ for (i = 0; i < *numentries; ++i)
+ {
+ back_button_rect[0][i] = menu_button_rect[0][i];
+ back_button_rect[0][i].x -= Backrect.x;
+ back_button_rect[0][i].y -= Backrect.y;
+
+ back_text_rect[0][i] = menu_text_rect[0][i];
+ back_text_rect[0][i].x -= Backrect.x;
+ back_text_rect[0][i].y -= Backrect.y;
+
+ back_sprite_rect[0][i] = menu_sprite_rect[0][i];
+ back_sprite_rect[0][i].x -= Backrect.x;
+ back_sprite_rect[0][i].y -= Backrect.y;
+ }
+
+}
Modified: tuxmath/trunk/src/titlescreen.h
===================================================================
--- tuxmath/trunk/src/titlescreen.h 2008-06-11 21:26:58 UTC (rev 512)
+++ tuxmath/trunk/src/titlescreen.h 2008-06-12 00:07:50 UTC (rev 513)
@@ -76,7 +76,7 @@
#define menu_font "AndikaDesRevA.ttf" /* "GenAI102.ttf" */
#define menu_font_size 18
-#define ttf_font "AndikaDesRevA.ttf" /* "GenAI102.ttf" */
+#define ttf_font "AndikaDesRevA.ttf" /* "GenAI102.ttf" */
#define ttf_font_size 18
#define MAX_LESSONS 100
@@ -109,11 +109,10 @@
-extern SDL_Surface *screen;
+//extern SDL_Surface *screen;
//extern TTF_Font *font;
extern SDL_Event event;
-
extern SDL_Surface *bkg;
#define MUSIC_FADE_OUT_MS 80
@@ -157,7 +156,7 @@
/*In titlescreen.c */
void TitleScreen(void);
int ChooseMission(void); //FIXME really should be in fileops.c
-int choose_menu_item(const unsigned char**, sprite**, int, menu_options);
+int choose_menu_item(const unsigned char**, sprite**, int, menu_options* menu_opts, void (*)(menu_options*) );
void set_default_menu_options(menu_options *);
Modified: tuxmath/trunk/src/tuxmath.h
===================================================================
--- tuxmath/trunk/src/tuxmath.h 2008-06-11 21:26:58 UTC (rev 512)
+++ tuxmath/trunk/src/tuxmath.h 2008-06-12 00:07:50 UTC (rev 513)
@@ -45,6 +45,12 @@
//#define TUXMATH_DEBUG
/* for Tim's feedback speed control code */
//#define FEEDBACK_DEBUG
++/* nice inline debugging macro */
+#ifdef TUXMATH_DEBUG
+#define tmdprintf(...) printf(__VA_ARGS__)
+#else
+#define tmdprintf(...) 0
+#endif
/* Maximum length of file path: */
#define PATH_MAX 4096
@@ -125,6 +131,9 @@
/* Global data gets 'externed' here: */
+extern int fs_res_x;
+extern int fs_res_y;
+
extern SDL_Color black;
extern SDL_Color gray;
extern SDL_Color dark_blue;
More information about the Tux4kids-commits
mailing list