Logo Search packages:      
Sourcecode: mathwar version File versions  Download package

draw.c

/*-------------------------------------------------------------------------
 * Copyright (c) 2002 Kenneth W. Sodemann (stufflehead@bigfoot.com)
 *-------------------------------------------------------------------------
 * draw
 *
 * Synopsis:
 *   routines used to draw the game board
 *
 * $Id: draw.c,v 1.5 2002/05/25 16:44:49 stuffle Exp $
 *
 * 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
 * Free Software Foundation, Inc.
 * 59 Temple Place, Suite 330 
 * Boston, MA  02111-1307  USA
 *
 *-------------------------------------------------------------------------
 */
#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <gnome.h>

#include "cards.h"
#include "draw.h"
#include "ini_defs.h"
#include "mainwin.h"
#include "support.h"

/*
 * The score area height is set in the init_draw_objects() function
 * after we load the font that we are going to use.  I supposed this 
 * could change mid run if we ever let the user set the font.  The value
 * set here is just an estimate.
 */
#define TEXT_Y_PADDING   5
#define TEXT_X_PADDING   5
#define TEXT_INDENT      30
static gint score_area_height = 50;

/*
 * Define how the cards and opers line up in that area
 */
#define LINE_WIDTH       5
#define SIGN_SQR        20
#define CARD_X_PAD      30
#define CARD_Y_PAD      20
#define CARD_AREA_Y     (score_area_height)
#define CARD_Y          (CARD_AREA_Y) + (CARD_Y_PAD) 
#define CARD_ONE_X      (CARD_X_PAD)
#define CARD_TWO_X      ((CARD_ONE_X) + (CARD_WIDTH) + (CARD_X_PAD) + \
                         (SIGN_SQR) + (CARD_X_PAD))
#define OPER_X          ((CARD_ONE_X) + (CARD_WIDTH) + (CARD_X_PAD))
#define EQUAL_X         ((CARD_TWO_X) + (CARD_WIDTH) + (CARD_X_PAD))
#define OPER_Y          ((CARD_Y) + ((CARD_HEIGHT) / 2) - ((SIGN_SQR) / 2))
#define CARD_AREA_HEIGHT  ((CARD_Y_PAD) + (CARD_HEIGHT) + (CARD_Y_PAD))

#define FEEDBACK_AREA_Y ((CARD_AREA_Y) + (CARD_AREA_HEIGHT))
static gint feedback_area_height = 50;   
/*
 * Module variables
 */
static GdkPixmap     *main_area_pix = NULL;
static GdkGC         *main_gc = NULL;
static GdkGC         *shadow_gc = NULL;
static GdkGC         *oper_gc = NULL;

static void
draw_plus_sign (GdkPixmap *pix, gint x, gint y)
{
   gdk_draw_line (pix, oper_gc,
                  x + (SIGN_SQR / 2), y,
                  x + (SIGN_SQR / 2), y + SIGN_SQR);
   gdk_draw_line (pix, oper_gc,
                  x, y + (SIGN_SQR / 2),
                  x + SIGN_SQR, y + (SIGN_SQR / 2));
}


static void
draw_mult_sign (GdkPixmap *pix, gint x, gint y)
{
   gdk_draw_line (pix, oper_gc,
                  x, y,
                  x + SIGN_SQR, y + SIGN_SQR);
   gdk_draw_line (pix, oper_gc,
                  x, y + SIGN_SQR,
                  x + SIGN_SQR, y);
}


static void
draw_minus_sign (GdkPixmap *pix, gint x, gint y)
{
   gdk_draw_line (pix, oper_gc,
                  x, y + (SIGN_SQR / 2),
                  x + SIGN_SQR, y + (SIGN_SQR / 2));
}


static void
draw_equal_sign (GdkPixmap *pix, gint x, gint y)
{
   gdk_draw_line (pix, oper_gc,
                  x, y + (SIGN_SQR / 4),
                  x + (SIGN_SQR), y + (SIGN_SQR / 4));
   gdk_draw_line (pix, oper_gc,
                  x, y + (SIGN_SQR * 3 / 4),
                  x + (SIGN_SQR), y + (SIGN_SQR * 3 / 4));
}


static void
draw_scoreboard (const player_object *p1, const player_object *p2)
{
   GString *str;
   gint     width1;
   gint     width2;
   gint     height;
   gint     y;
   gint     player1_y;
   GdkFont *display_font;
   gchar   *fstr;

   g_assert (score_area_height > 0);

   fstr = ini_get_string (PACKAGE, FONTS, TEXT_FONT, DEF_TEXT_FONT);
   display_font = gdk_font_load (fstr);
   g_free (fstr);

   gdk_draw_rectangle (main_area_pix, main_gc, TRUE,
                       0, 0, board_width(), score_area_height);

   str = g_string_new (_("Scores"));
   height = gdk_text_height (display_font, str->str, str->len);
   y = TEXT_Y_PADDING + height;
   gdk_draw_text (main_area_pix, display_font, oper_gc,
                  TEXT_X_PADDING, y, str->str, str->len);

   str = g_string_assign (str, get_player_name (p1));
   width1 = gdk_text_width (display_font, str->str, str->len);
   y += TEXT_Y_PADDING + height;
   player1_y = y;
   gdk_draw_text (main_area_pix, display_font, oper_gc,
                  3 * TEXT_X_PADDING, y, str->str, str->len);

   str = g_string_assign (str, get_player_name (p2));
   width2 = gdk_text_width (display_font, str->str, str->len);
   y += TEXT_Y_PADDING + height;
   gdk_draw_text (main_area_pix, display_font, oper_gc,
                  3 * TEXT_X_PADDING, y, str->str, str->len);

   width1 = (width1 > width2) ? width1 : width2;
   width1 += 6 * TEXT_X_PADDING;

   g_string_sprintf (str, "%d",  get_player_score (p1));
   gdk_draw_text (main_area_pix, display_font, oper_gc,
                  width1, player1_y, str->str, str->len);
   g_string_sprintf (str, "%d", get_player_score (p2));
   gdk_draw_text (main_area_pix, display_font, oper_gc,
                  width1, y, str->str, str->len);

   gdk_font_unref (display_font);
   g_string_free (str, TRUE);
}

gint
board_height (void)
{
   return (score_area_height + CARD_AREA_HEIGHT + feedback_area_height);
}

gint
board_width (void)
{
   /*
    * The position of the equal sign + the width of the equal sign,
    * plus some padding.
    */
   return (EQUAL_X + SIGN_SQR + CARD_X_PAD);
}


void
draw_cards_up (gint card_one_val, gint card_two_val, operator_type operator)
{
   gdk_draw_rectangle (main_area_pix, main_gc, TRUE,
                       0, CARD_AREA_Y, board_width(), CARD_AREA_HEIGHT);

   draw_card (main_area_pix, main_gc, shadow_gc,
              card_one_val, CARD_ONE_X, CARD_Y);
   draw_card (main_area_pix, main_gc, shadow_gc,
              card_two_val, CARD_TWO_X, CARD_Y);

   switch (operator)
      {
      case SUBTRACTION:
         draw_minus_sign (main_area_pix, OPER_X, OPER_Y);
         break;

      case ADDITION:
         draw_plus_sign (main_area_pix, OPER_X, OPER_Y);
         break;

      case MULTIPLICATION:
         draw_mult_sign (main_area_pix, OPER_X, OPER_Y);
         break;

      default:
         g_assert_not_reached ();
         break;
      }

   draw_equal_sign (main_area_pix, EQUAL_X, OPER_Y);
}


void
draw_cards_down (void)
{
   /*
    * Just draw the cards "UP" using the back...
    */
   draw_cards_up (CARD_BACK_ONE, CARD_BACK_TWO, ADDITION);
}


void
clear_message_area (void)
{
   gdk_draw_rectangle (main_area_pix, main_gc, TRUE,
                       0, FEEDBACK_AREA_Y,
                       board_width(), feedback_area_height);
}


void
draw_message (const gchar *str1, const gchar *str2, gboolean center)
{
   gint       x = TEXT_X_PADDING;
   gint       y;
   gint       len;
   gint       width;
   gint       height;
   GdkFont   *display_font;
   gchar     *fstr;
   GtkWidget *draw_area = GTK_WIDGET (get_main_drawing_area());

   g_assert (str1 != NULL);
   
   clear_message_area();

   fstr = ini_get_string (PACKAGE, FONTS, TEXT_FONT, DEF_TEXT_FONT);
   display_font = gdk_font_load (fstr);
   g_free (fstr);

   len = strlen (str1);
   if (center)
      {
      width = gdk_text_width (display_font, str1, len);
      x = (board_width() - width) / 2;
      x = (x < TEXT_X_PADDING) ? TEXT_X_PADDING : x;
      }
   height = gdk_text_height (display_font, str1, len);
   y = FEEDBACK_AREA_Y + TEXT_Y_PADDING + height;
   gdk_draw_text (main_area_pix, display_font, oper_gc, x, y, str1, len);

   if (str2 != NULL)
      {
      len = strlen (str2);
      if (center)
         {
         width = gdk_text_width (display_font, str2, len);
         x = (board_width() - width) / 2;
         x = (x < TEXT_X_PADDING) ? TEXT_X_PADDING : x;
         }
      height = gdk_text_height (display_font, str2, len);
      y += (TEXT_Y_PADDING + height);
      gdk_draw_text (main_area_pix, display_font, oper_gc, x, y, str2, len);
      }

   gdk_window_set_back_pixmap (draw_area->window, main_area_pix, 0);
   gdk_window_clear (draw_area->window);
   gdk_font_unref (display_font);
}


void
refresh_board (const player_object *player1, const player_object *player2)
{
   GtkWidget *draw_area = GTK_WIDGET (get_main_drawing_area());

   draw_scoreboard (player1, player2);
   gdk_window_set_back_pixmap (draw_area->window, main_area_pix, 0);
   gdk_window_clear (draw_area->window);
}


void
setup_text_gc (void)
{
   GdkColormap *cmap = gdk_colormap_get_system();
   GtkWidget   *draw_area = GTK_WIDGET (get_main_drawing_area());
   GdkColor     color;

   if (oper_gc != NULL)
      {
      gdk_gc_unref (oper_gc);
      }

   color.red = ini_get_int (PACKAGE, FONTS, FONT_COLOR_R, DEF_RED);
   color.blue = ini_get_int (PACKAGE, FONTS, FONT_COLOR_B, DEF_BLUE);
   color.green = ini_get_int (PACKAGE, FONTS, FONT_COLOR_G, DEF_GREEN);
   if (!gdk_colormap_alloc_color (cmap, &color, FALSE, TRUE))
      {
      g_error ("Cound not allocate operator color");
      }
   oper_gc = gdk_gc_new (draw_area->window);
   gdk_gc_set_foreground (oper_gc, &color);
   gdk_gc_set_line_attributes (oper_gc, LINE_WIDTH, GDK_LINE_SOLID,
                               GDK_CAP_ROUND, GDK_JOIN_BEVEL);
}


void
init_draw_objects (void)
{
   GdkPixmap   *bg;
   GtkWidget   *draw_area = GTK_WIDGET (get_main_drawing_area());
   GdkColormap *cmap = gdk_colormap_get_system();
   GdkColor     color;
   GdkFont     *display_font;
   gchar       *fstr;

   g_return_if_fail (main_area_pix == NULL);
   g_return_if_fail (main_gc == NULL);
   g_return_if_fail (shadow_gc == NULL);
   g_return_if_fail (oper_gc == NULL);

   /*
    * Check the size of the normal display font.
    *
    * I use "A4gp" to estimate the height that will be used as it 
    * should provide a maximal height since it has an upper case
    * letter, a number, and two lower case numbers that dip
    * below the baseline.
    */
   fstr = ini_get_string (PACKAGE, FONTS, TEXT_FONT, DEF_TEXT_FONT);
   display_font = gdk_font_load (fstr);
   g_free (fstr);
   score_area_height = (4 * TEXT_Y_PADDING) +
      (3 * gdk_text_height (display_font, "A4gp", 4));
   feedback_area_height = (3 * TEXT_Y_PADDING) + 
      (2 * gdk_text_height (display_font, "A4gp", 4));
   gdk_font_unref (display_font);

   /*
    * Setup the main GC that is used when drawing in the drawing area.
    */
   main_gc = gdk_gc_new (draw_area->window);
   bg = load_pixmap ("bg.png");
   gdk_gc_set_tile (main_gc, bg);
   gdk_gc_set_fill (main_gc, GDK_TILED);
   gdk_pixmap_unref (bg);

   /*
    * Setup the GC used to draw the operators
    */
   setup_text_gc ();

   /*
    * Setup the GC used to draw the shadow of the cards
    */
   color.red = 0x0000;
   color.blue = 0x0000;
   color.green = 0x0000;
   if (!gdk_colormap_alloc_color (cmap, &color, FALSE, TRUE))
      {
      g_error ("Cound not allocate shadow color");
      }
   shadow_gc = gdk_gc_new (draw_area->window);
   gdk_gc_set_foreground (shadow_gc, &color);

   main_area_pix = gdk_pixmap_new (GTK_WIDGET (draw_area)->window,
                                   board_width(), board_height(),
                                   gdk_window_get_visual
                                      (GTK_WIDGET (draw_area)->window)->depth);
   gdk_draw_rectangle (main_area_pix, main_gc, TRUE, 0, 0, -1, -1);
}

void
destroy_draw_objects (void)
{
   gdk_pixmap_unref (main_area_pix);
   gdk_gc_unref (main_gc);
   gdk_gc_unref (shadow_gc);
   gdk_gc_unref (oper_gc);
}


void
draw_pause (void)
{
   gint       t_half_h;
   gint       t_half_w;
   gint       x, y;
   GdkFont   *big_font;
   gchar     *fstr;
   GString   *str;
   GdkPixmap *pause_pix;
   GtkWidget *draw_area = GTK_WIDGET (get_main_drawing_area());

   pause_pix = gdk_pixmap_new (GTK_WIDGET (draw_area)->window,
                               board_width(), board_height(),
                               gdk_window_get_visual
                                  (GTK_WIDGET (draw_area)->window)->depth);

   gdk_draw_rectangle (pause_pix, main_gc, TRUE,
                       0, 0, board_width(), board_height());

   str = g_string_new (_("Pause"));
   fstr = ini_get_string (PACKAGE, FONTS, TITLE_FONT, DEF_TITLE_FONT);
   big_font = gdk_font_load (fstr);
   g_free (fstr);
   
   /*
    * Center the text...
    */
   t_half_h = gdk_text_height (big_font, str->str, str->len) / 2; 
   t_half_w = gdk_text_width (big_font, str->str, str->len) / 2; 
   x = board_width() / 2 - t_half_w;
   y = board_height() / 2 - t_half_h;

   gdk_draw_text (pause_pix, big_font, oper_gc, x, y,
                  str->str, str->len);
   gdk_window_set_back_pixmap (draw_area->window, pause_pix, 0);
   gdk_window_clear (draw_area->window);

   gdk_font_unref (big_font);
   gdk_pixmap_unref (pause_pix);
   g_string_free (str, TRUE);
}


void
draw_game_over (const game_engine *game)
{
   gint       t_half_w;
   gint       x, y;
   gint       h;
   gint       statx = 0;
   GString   *pts_str = g_string_new (_("Total Points:"));
   GString   *guess_str = g_string_new (_("Guesses:"));
   GString   *correct_guess_str = g_string_new (_("Correct Guesses:"));
   GString   *str;
   GdkFont   *big_font;
   GdkFont   *display_font;
   gchar     *fstr;
   GdkPixmap *bgpix;
   GtkWidget *draw_area = GTK_WIDGET (get_main_drawing_area());

   fstr = ini_get_string (PACKAGE, FONTS, TEXT_FONT, DEF_TEXT_FONT);
   display_font = gdk_font_load (fstr);
   g_free (fstr);

   fstr = ini_get_string (PACKAGE, FONTS, TITLE_FONT, DEF_TITLE_FONT);
   big_font = gdk_font_load (fstr);
   g_free (fstr);
   
   /* 
    * The score text will be lined up after the longest of the 
    * "prompt" strings.  Determine which one is longest, and how
    * long it is.
    */
   statx = gdk_text_width (display_font, pts_str->str, pts_str->len);
   x = gdk_text_width (display_font, guess_str->str, guess_str->len);
   statx = (x > statx) ? x : statx;
   x = gdk_text_width (display_font, correct_guess_str->str, 
                       correct_guess_str->len);
   statx = (x > statx) ? x : statx;
   statx += (TEXT_INDENT + TEXT_X_PADDING);

   bgpix = gdk_pixmap_new (GTK_WIDGET (draw_area)->window,
                           board_width(), board_height(),
                           gdk_window_get_visual
                              (GTK_WIDGET (draw_area)->window)->depth);

   gdk_draw_rectangle (bgpix, main_gc, TRUE,
                       0, 0, board_width(), board_height());

   /*
    * Game Over text...
    */
   str = g_string_new (_("Game Over!!"));
   t_half_w = gdk_text_width (big_font, str->str, str->len) / 2; 
   x = board_width() / 2 - t_half_w;
   y = 2 * gdk_text_height (big_font, str->str, str->len);
   gdk_draw_text (bgpix, big_font, oper_gc, x, y,
                  str->str, str->len);

   /*
    * Statisticts
    */
   str = g_string_assign (str, _("Scores:"));
   t_half_w = gdk_text_width (big_font, str->str, str->len) / 2;
   x = board_width() / 2 - t_half_w;
   h = gdk_text_height (big_font, str->str, str->len);
   y = y + (3 * h);
   gdk_draw_text (bgpix, big_font, oper_gc, x, y,
                  str->str, str->len);
   
   /*
    * Player 1
    */
   str = g_string_assign (str, get_player_name (game->player1));
   str = g_string_append (str, ":");
   y += (gdk_text_height (display_font, str->str, str->len) * 2);
   gdk_draw_text (bgpix, display_font, oper_gc, TEXT_X_PADDING, y,
                  str->str, str->len);
   y += gdk_text_height (display_font, pts_str->str, pts_str->len) +
       TEXT_Y_PADDING;
   gdk_draw_text (bgpix, display_font, oper_gc, TEXT_INDENT, y,
                  pts_str->str, pts_str->len);
   g_string_sprintf (str, "%d", get_player_score (game->player1));
   gdk_draw_text (bgpix, display_font, oper_gc, statx, y,
                  str->str, str->len);
   y += gdk_text_height (display_font, guess_str->str, guess_str->len) +
       TEXT_Y_PADDING;
   gdk_draw_text (bgpix, display_font, oper_gc, TEXT_INDENT, y,
                  guess_str->str, guess_str->len);
   g_string_sprintf (str, "%d", get_player_guesses (game->player1));
   gdk_draw_text (bgpix, display_font, oper_gc, statx, y,
                  str->str, str->len);
   y += gdk_text_height (display_font, correct_guess_str->str,
                         correct_guess_str->len) + TEXT_Y_PADDING;
   gdk_draw_text (bgpix, display_font, oper_gc, TEXT_INDENT, y,
                  correct_guess_str->str, correct_guess_str->len);
   g_string_sprintf (str, "%d", get_player_correct_guesses (game->player1));
   gdk_draw_text (bgpix, display_font, oper_gc, statx, y,
                  str->str, str->len);

   /*
    * Player 1
    */
   str = g_string_assign (str, get_player_name (game->player2));
   str = g_string_append (str, ":");
   y += (gdk_text_height (display_font, str->str, str->len) * 2);
   gdk_draw_text (bgpix, display_font, oper_gc, TEXT_X_PADDING, y,
                  str->str, str->len);
   y += gdk_text_height (display_font, pts_str->str, pts_str->len) +
       TEXT_Y_PADDING;
   gdk_draw_text (bgpix, display_font, oper_gc, TEXT_INDENT, y,
                  pts_str->str, pts_str->len);
   g_string_sprintf (str, "%d", get_player_score (game->player2));
   gdk_draw_text (bgpix, display_font, oper_gc, statx, y,
                  str->str, str->len);
   y += gdk_text_height (display_font, guess_str->str, guess_str->len) +
       TEXT_Y_PADDING;
   gdk_draw_text (bgpix, display_font, oper_gc, TEXT_INDENT, y,
                  guess_str->str, guess_str->len);
   g_string_sprintf (str, "%d", get_player_guesses (game->player2));
   gdk_draw_text (bgpix, display_font, oper_gc, statx, y,
                  str->str, str->len);
   y += gdk_text_height (display_font, correct_guess_str->str,
                         correct_guess_str->len) + TEXT_Y_PADDING;
   gdk_draw_text (bgpix, display_font, oper_gc, TEXT_INDENT, y,
                  correct_guess_str->str, correct_guess_str->len);
   g_string_sprintf (str, "%d", get_player_correct_guesses (game->player2));
   gdk_draw_text (bgpix, display_font, oper_gc, statx, y,
                  str->str, str->len);

   gdk_window_set_back_pixmap (draw_area->window, bgpix, 0);
   gdk_window_clear (draw_area->window);

   gdk_font_unref (big_font);
   gdk_font_unref (display_font);
   gdk_pixmap_unref (bgpix);
   g_string_free (str, TRUE);
   g_string_free (pts_str, TRUE);
   g_string_free (guess_str, TRUE);
   g_string_free (correct_guess_str, TRUE);
}

Generated by  Doxygen 1.6.0   Back to index