#include <stdio.h> #include <gtk/gtk.h> #include <math.h> // 游戏区域的定义 #define GAME_WIDTH 500 #define GAME_LENGTH 600 struct Ball { int x, y; // 小球的坐标(圆心) int speed_x, speed_y; // 小球的速度 int radius; // 半径 }; struct Baffle { int x, y; // 挡板的坐标(挡板左上角) int width, length; // 挡板的长和宽 }; struct Bricks { int matrix[8][12]; // 记录砖块群信息的矩阵 int width, length; // 每一块砖块的长和宽 }; // 全局变量 struct Ball ball; // 小球 struct Baffle baffle; // 挡板 struct Bricks bricks; // 砖块 GtkWidget *window = NULL; // 游戏主窗口 GktWidget *lose = NULL; // 游戏失败提示窗口 GtkWidget *win = NULL; // 游戏胜利窗口 int pause = 1; // 处理暂停的变量。0代表游戏继续,1代表游戏暂停 // 函数声明 void init(void); static gboolean expose_handler(GtkWidget * widget, GdkEventExpose * event, gpointer data); static gboolean time_handler(GtkWidget *widget); void press_handler(GtkWidget *widget, GdkEventKey *event); int main(int argc, char **argv) { init(); gtk_init(&argc,&argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(G_OBJECT(window), "expose_event", G_CALLBACK(expose_handler), NULL); g_signal_connect ( G_OBJECT ( window) , "key_press_event" , G_CALLBACK (press_handler) , NULL ) ; gtk_window_set_position ( GTK_WINDOW ( window) , GTK_WIN_POS_CENTER) ; gtk_window_set_default_size ( GTK_WINDOW ( window) , GAME_LENGTH, GAME_WIDTH ) ; gtk_widget_set_app_paintable ( window, TRUE ) ; gtk_widget_show_all(window) ; g_timeout_add(10, (GSourceFunc)time_handler, NULL); gtk_main() ; return 0; } /* * * name: init * @param * @return * * 完成初始化 */ void init() { int i,j; // 挡板的初始化 baffle.length = 100; baffle.width = 10; baffle.x = GAME_LENGTH / 2 - baffle.length / 2; baffle.y = GAME_WIDTH - baffle.width; // 小球的初始化 ball.radius = 5; ball.x = GAME_LENGTH / 2; ball.y = baffle.y - ball.radius; ball.speed_x = 1; ball.speed_y = -1; // 砖块群的初始化 bricks.length = 50; bricks.width = 20; for(i = 0; i < 8; i++) { for(j = 0; j < 12; j++) bricks.matrix[i][j] = 1; } } static gboolean expose_handler(GtkWidget * widget, GdkEventExpose * event, gpointer data) { cairo_t *cr; int i,j; cr = gdk_cairo_create(widget ->window); // 先画出挡板(矩形) cairo_set_line_width(cr, 2); cairo_set_source_rgb(cr, 0.69, 0.19, 0); cairo_rectangle(cr, baffle.x, baffle.y, baffle.length, baffle.width); cairo_stroke_preserve(cr); cairo_set_source_rgb(cr, 0.3, 0.4, 0.6); cairo_fill(cr); // 再画出小球 cairo_set_line_width(cr, 0); cairo_arc(cr, ball.x, ball.y, ball.radius, 0, 2 * M_PI); cairo_stroke_preserve(cr); cairo_set_source_rgb(cr, 1, 0, 0); cairo_fill(cr); // 画出砖块群 for(i = 0; i < 8; i++) { for(j = 0; j < 12; j++) { if(bricks.matrix[i][j] != 0) { cairo_set_line_width(cr, 1); cairo_set_source_rgb(cr, 1, 1, 0); cairo_rectangle(cr, j * bricks.length, i * bricks.width, bricks.length, bricks.width); cairo_stroke_preserve(cr); cairo_set_source_rgb(cr, 0.4, 0.8, 0.2); cairo_fill(cr); } } } cairo_destroy(cr); return FALSE; } static gboolean time_handler(GtkWidget *widget) { int top_ball, bottom_ball, right_ball, left_ball; int virtual_x, virtual_y; if(pause == 1) return TRUE; ball.x += ball.speed_x; ball.y += ball.speed_y; if(ball.x <= 0 + ball.radius || ball.x >= GAME_LENGTH - ball.radius) ball.speed_x = -ball.speed_x; if(ball.y <= 0 + ball.radius) ball.speed_y = -ball.speed_y; if(ball.y >= GAME_WIDTH - baffle.width - ball.radius) { if(ball.x >= baffle.x && ball.x <= baffle.x + baffle.length) ball.speed_y = -ball.speed_y; } // 小球落入最下方,停止游戏 if(ball.y >= GAME_WIDTH - ball.radius) return FALSE; // 检测碰撞 // 当小球向右下方移动时,小球的右方和下方可能碰到砖块 if(ball.speed_x > 0 && ball.speed_y > 0) { bottom_ball = ball.y + ball.radius; virtual_x = ball.x / bricks.length; virtual_y = bottom_ball / bricks.width; // 小球下方碰撞到砖块 if(virtual_x >= 0 && virtual_x <= 11 && virtual_y >= 0 && virtual_y <= 7) { if(bricks.matrix[virtual_y][virtual_x] != 0) // 该砖块存在 { bricks.matrix[virtual_y][virtual_x]--; ball.speed_y = -ball.speed_y; } } right_ball = ball.x + ball.radius; virtual_x = right_ball / bricks.length; virtual_y = ball.y / bricks.width; if(virtual_x >= 0 && virtual_x <= 11 && virtual_y >= 0 && virtual_y <= 7) { if(bricks.matrix[virtual_y][virtual_x] != 0) { bricks.matrix[virtual_y][virtual_x]--; ball.speed_x = -ball.speed_x; } } } // 当小球向右上方移动时 else if(ball.speed_x > 0 && ball.speed_y < 0) { top_ball = ball.y - ball.radius; virtual_x = ball.x / bricks.length; virtual_y = top_ball / bricks.width; // 小球上方碰撞到砖块 if(virtual_x >= 0 && virtual_x <= 11 && virtual_y >= 0 && virtual_y <= 7) { if(bricks.matrix[virtual_y][virtual_x] != 0) // 该砖块存在 { bricks.matrix[virtual_y][virtual_x]--; ball.speed_y = -ball.speed_y; } } right_ball = ball.x + ball.radius; virtual_x = right_ball / bricks.length; virtual_y = ball.y / bricks.width; // 小球右方碰撞到砖块 if(virtual_x >= 0 && virtual_x <= 11 && virtual_y >= 0 && virtual_y <= 7) { if(bricks.matrix[virtual_y][virtual_x] != 0) // 该砖块存在 { bricks.matrix[virtual_y][virtual_x]--; ball.speed_x = -ball.speed_x; } } } // 当小球向左下方移动时 else if(ball.speed_x < 0 && ball.speed_y > 0) { bottom_ball = ball.y + ball.radius; virtual_x = ball.x / bricks.length; virtual_y = bottom_ball / bricks.width; // 小球下方碰撞到砖块 if(virtual_x >= 0 && virtual_x <= 11 && virtual_y >= 0 && virtual_y <= 7) { if(bricks.matrix[virtual_y][virtual_x] != 0) // 该砖块存在 { bricks.matrix[virtual_y][virtual_x]--; ball.speed_y = -ball.speed_y; } } left_ball = ball.x - ball.radius; virtual_x = left_ball / bricks.length; virtual_y = ball.y / bricks.width; // 小球左方碰撞到砖块 if(virtual_x >= 0 && virtual_x <= 11 && virtual_y >= 0 && virtual_y <= 7) { if(bricks.matrix[virtual_y][virtual_x] != 0) // 该砖块存在 { bricks.matrix[virtual_y][virtual_x]--; ball.speed_x = -ball.speed_x; } } } // 当小球向左上方移动时 else { top_ball = ball.y - ball.radius; virtual_x = ball.x / bricks.length; virtual_y = top_ball / bricks.width; // 小球下方碰撞到砖块 if(virtual_x >= 0 && virtual_x <= 11 && virtual_y >= 0 && virtual_y <= 7) { if(bricks.matrix[virtual_y][virtual_x] != 0) // 该砖块存在 { bricks.matrix[virtual_y][virtual_x]--; ball.speed_y = -ball.speed_y; } } left_ball = ball.x - ball.radius; virtual_x = left_ball / bricks.length; virtual_y = ball.y / bricks.width; // 小球左方碰撞到砖块 if(virtual_x >= 0 && virtual_x <= 11 && virtual_y >= 0 && virtual_y <= 7) { if(bricks.matrix[virtual_y][virtual_x] != 0) // 该砖块存在 { bricks.matrix[virtual_y][virtual_x]--; ball.speed_x = -ball.speed_x; } } } gdk_window_invalidate_rect(window ->window, NULL, FALSE); return TRUE ; } void press_handler(GtkWidget *widget, GdkEventKey *event) { switch(event ->keyval) { case 65361: // 左键 if(baffle.x > 0) baffle.x -= 10; break; case 65363: // 右键 if(baffle.x < 600 - baffle.length) baffle.x += 10; break; case 32: // 空格(暂停) pause = 1; break; case 65293: // 回车 pause = 0; break; default: break; } }