animate.c
来自「开发linux应用-用gtk+和gdk开发linux图形用户界面应用--的实例」· C语言 代码 · 共 436 行
C
436 行
/* * Auth: Eric Harlow * Linux application development * * Demo of sprites. */#include <gtk/gtk.h>#include <time.h>#include "man.h"#include "woman.h"#include "ball.h"#include "driver.h"#include "police.h"#include "bike.h"#define LINE_LEN 20#define GAP_LEN 15/* * Our sprite data structure */typedef struct { char **xpm_data; GdkPixmap *pixmap; GdkBitmap *mask;} typSprite;/* * Here's the actor. Actor consists of one or more * sprites. */typedef struct { int seq; int x; int y; int height; int width; int nSequences; typSprite *sprites;} typActor;/* * Man walking */typSprite walk[] = { { xpm_standright, NULL, NULL }, { xpm_walkright1, NULL, NULL }, { xpm_standright, NULL, NULL }, { xpm_walkright2, NULL, NULL }, { NULL, NULL, NULL }};/* * Man on a bike */typSprite sprite_bike[] = { { xpm_bike1, NULL, NULL }, { xpm_bike2, NULL, NULL }, { xpm_bike3, NULL, NULL }, { NULL, NULL, NULL }};/* * Woman walking */typSprite sprite_woman[] = { { xpm_womanr, NULL, NULL }, { xpm_womanwalkr1, NULL, NULL }, { xpm_womanr, NULL, NULL }, { xpm_womanwalkr2, NULL, NULL }, { NULL, NULL, NULL }};/* * Police car */typSprite sprite_police[] = { { xpm_police1, NULL, NULL }, { xpm_police2, NULL, NULL }, { NULL, NULL, NULL }};/* * Partially transparent ball. */typSprite sprite_ball[] = { { xpm_ball1, NULL, NULL }, { NULL, NULL, NULL }};/* * Car */typSprite sprite_car[] = { { xpm_car1, NULL, NULL }, { xpm_car1, NULL, NULL }, { NULL, NULL, NULL }};/* * Here are the stars of the production */typActor man;typActor bike;typActor woman;typActor police;typActor ball1;typActor car1;/* --- Backing pixmap for drawing area --- */static GdkPixmap *pixmap = NULL;/* --- Flag to use mask --- */static int bUseMask = TRUE;/* * Prototypes. */void GetWidthHeight (gchar **xpm, int *width, int *height);/* * LoadPixmaps * * Load the actor's pixmaps, get the sprite information * from the xpm data and initialize the actor animation * information. */void LoadPixmaps (GtkWidget *widget, typActor *actor, typSprite *sprites){ int i = 0; /* --- Get every sequence --- */ while (sprites[i].xpm_data) { /* --- Convert xpm data to pixmap & mask --- */ sprites[i].pixmap = gdk_pixmap_create_from_xpm_d ( widget->window, &sprites[i].mask, NULL, sprites[i].xpm_data); i++; } /* --- Get sprite height and width --- */ GetWidthHeight (sprites[0].xpm_data, &actor->width, &actor->height); /* --- Initialize sprite information --- */ actor->seq = 0; actor->nSequences = i; actor->sprites = sprites;}/* * SequenceSprite * * Move to the next sprite in the sequence and * draw it with the mask */SequenceSprite (GtkWidget *drawing_area, typActor *actor, int nDist){ GdkGC *gc; actor->x += nDist; if (actor->x > drawing_area->allocation.width) { actor->x = 0; } /* --- Use the next image for the actor --- */ actor->seq++; /* --- Use 0 if at the end --- */ if (actor->seq >= actor->nSequences) { actor->seq = 0; } /* --- Get foreground color --- */ gc = drawing_area->style->fg_gc[GTK_STATE_NORMAL]; if (bUseMask) { /* --- Set the clipping of the sprites --- */ gdk_gc_set_clip_mask (gc, actor->sprites[actor->seq].mask); /* --- Set the origin of the clipping --- */ gdk_gc_set_clip_origin (gc, actor->x, actor->y); } /* --- Copy pixmap to the window, properly clipped --- */ gdk_draw_pixmap (pixmap, drawing_area->style->fg_gc[GTK_STATE_NORMAL], actor->sprites[actor->seq].pixmap, 0, 0, actor->x, actor->y, actor->width, actor->height); if (bUseMask) { /* --- Clear the clipping mask --- */ gdk_gc_set_clip_mask (gc, NULL); }}/* * Repaint * * data - widget to repaint */gint Repaint (gpointer data){ GtkWidget* drawing_area = (GtkWidget *) data; GdkRectangle update_rect; static offset = 0; int nTop; /* --- clear pixmap (background image) --- */ gdk_draw_rectangle (pixmap, drawing_area->style->black_gc, TRUE, 0, 0, drawing_area->allocation.width, drawing_area->allocation.height); /* --- Draw road --- */ gdk_draw_rectangle (pixmap, drawing_area->style->white_gc, TRUE, 50, 0, 100, drawing_area->allocation.height); /* * Draw lines on the road */ /* --- Figure out where first line should be. --- */ offset++; if ((offset - GAP_LEN) >= 0) { offset -= (LINE_LEN + GAP_LEN); } /* --- Draw the lines all the way down the road --- */ nTop = offset; do { gdk_draw_rectangle (pixmap, drawing_area->style->black_gc, TRUE, 100, nTop, 5, LINE_LEN); nTop += LINE_LEN + GAP_LEN; } while (nTop < drawing_area->allocation.height); /* --- Draw each of these images --- */ SequenceSprite (drawing_area, &bike, 3); SequenceSprite (drawing_area, &man, 2); SequenceSprite (drawing_area, &woman, 2); SequenceSprite (drawing_area, &police, 0); SequenceSprite (drawing_area, &ball1, 2); SequenceSprite (drawing_area, &car1, 3); /* --- The whole screen needs to be updated --- */ update_rect.x = 0; update_rect.y = 0; update_rect.width = drawing_area->allocation.width; update_rect.height = drawing_area->allocation.height; /* --- So update it --- */ gtk_widget_draw (drawing_area, &update_rect);}/* * configure_event * * Create a new backing pixmap of the appropriate size * Of course, this is called whenever the window is * resized. We have to free up things we allocated. */static gint configure_event (GtkWidget *widget, GdkEventConfigure *event){ /* --- Free background if we created it --- */ if (pixmap) { gdk_pixmap_unref (pixmap); } /* --- Create a new pixmap with new size --- */ pixmap = gdk_pixmap_new (widget->window, widget->allocation.width, widget->allocation.height, -1); return TRUE;}/* * expose_event * * When the window is exposed to the viewer or * the gdk_widget_draw routine is called, this * routine is called. Copies the background pixmap * to the window. */gint expose_event (GtkWidget *widget, GdkEventExpose *event){ /* --- Copy pixmap to the window --- */ gdk_draw_pixmap (widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], pixmap, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); return FALSE;}/* * quit * * Get out of the application */void quit (){ gtk_exit (0);}/* * GetWidgthHeight * * Get the widget and height for the xpm data * */void GetWidthHeight (gchar **xpm, int *width, int *height){ sscanf (xpm [0], "%d %d", width, height);}/* * main * * Program begins here. */ int main (int argc, char *argv[]){ GtkWidget *window; GtkWidget *drawing_area; GtkWidget *vbox; /* --- Initialize GTK --- */ gtk_init (&argc, &argv); if (argc > 1) { bUseMask = FALSE; } /* --- Create the top level window --- */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); vbox = gtk_hbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (window), vbox); gtk_widget_show (vbox); gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (quit), NULL); /* --- Create the drawing area --- */ drawing_area = gtk_drawing_area_new (); gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 300); gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0); gtk_widget_show (drawing_area); /* --- Signals used to handle backing pixmap --- */ gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event", (GtkSignalFunc) expose_event, NULL); gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event", (GtkSignalFunc) configure_event, NULL); /* --- Show the window --- */ gtk_widget_show (window); /* --- Repaint every so often --- */ gtk_timeout_add (100, Repaint, drawing_area); /* --- Load all these sprites --- */ LoadPixmaps (window, &man, walk); LoadPixmaps (window, &bike, sprite_bike); LoadPixmaps (window, &woman, sprite_woman); LoadPixmaps (window, &police, sprite_police); LoadPixmaps (window, &ball1, sprite_ball); LoadPixmaps (window, &car1, sprite_car); /* --- Position them --- */ bike.x = 30; bike.y = 60; man.x = 50; man.y = 60; man.x = 60; man.y = 60; police.x = 60; police.y = 90; ball1.x = 0; ball1.y = 90; car1.x = 0; car1.y = 120; /* --- Call gtk-main loop --- */ gtk_main (); return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?