Search code examples
cuser-interfacegtkgtk3

How can I "pause" app for user to press a button? GTK


I am making an card game in C using GTK 3.0. I have two functions for two windows, openMenu() to open the menu and newGame() to create a new window with a card table. The player is playing against two bots which will choose their cards randomly. I need the player to start the game with choosing one card. Open Menu:

static void openMenu(int argc, char *argv[]){
    GtkBuilder *builder;
    GtkWidget *window;
    GObject *button;
    GError *error = NULL;

    gtk_init(&argc, &argv);
    builder = gtk_builder_new_from_file("menu_window_glade.glade");
    window = GTK_WIDGET(gtk_builder_get_object(builder, "menu_window"));
    gtk_builder_connect_signals(builder, NULL);
    gtk_widget_show(window);

    gtk_main();
}

New Game:

void newGame(){
    GtkBuilder *builder;
    GtkWidget *window;
    GtkImage *image;
    widgetsPtrs *widgets = malloc(sizeof(widgetsPtrs));
    char imageStr[] = "image00";
    char aImgstr[] = "A0";
    char dImgstr[] = "D0";
    builder = gtk_builder_new_from_file("game_glade.glade");
    window = GTK_WIDGET(gtk_builder_get_object(builder, "game_glade_window"));
    gtk_builder_connect_signals(builder, NULL);
    gtk_widget_show(window);

    shuffleTheDeck();
    printAll(Deck);

    card *player = malloc(sizeof(card));
    card *leftBot = malloc(sizeof(card));
    card *rightBot = malloc(sizeof(card));

    deal(player, 0);
    deal(leftBot, 0);
    deal(rightBot, 0);

    /***************Puts images into buttons***********/
    tmpCard = player;
    for (size_t i = 0; i < 6; i++)
    {
        tmpCard = tmpCard->next;
        imgPath[20] = zero + tmpCard->rank; 
        imgPath[21] = zero + tmpCard->suit;
        gtk_image_set_from_file(GTK_IMAGE(widgets->w_playersHandPtr[i]), imgPath);   
    }

    int a = firstTurnCheck();
    playersTurn(player, leftBot, rightBot);
}

The problem comes from here: I've come with an idea of a loop, which can be broken only if the global bool is changed, which is changed in a function serving on click events. However, the window with a game table doesn't show, therefore I am never able to click a button, so the app freezes.

void playersTurn(card *player, card *leftBot, card *rightBot){
    bool DEFENDERTOOKTHECARDS = false;
    bool RBHASMORE = true;
    PLAYERCHOOSING = true;
    int attackCounter = 0;
    int *appearedRanks = calloc(9, sizeof(int));
    card *cardsOnTheTable = malloc(sizeof(card)); //cardsOnTheTable[0] is a pointer to the table
    char answer;

    puts("Player's Turn");
    puts("Choose a card.");
    /*****************The spot where the mistake might be****************/
    while(PLAYERCHOOSING);//PLAYERCHOOSING is a global bool.
    puts("You've chosen a card.");
}

On_card_click function:

void on_card_clicked(GtkButton *button, gpointer *data){ 
    gtk_widget_hide(GTK_WIDGET(data));
    PLAYERCHOOSING = false;
}

Solution

  • Thanks a lot @ryyker for the advice he's given. The solution is based on threading. As I said, I've never worked with them before, but it took me like 15 mins to figure out everything I needed, so there is nothing to be afraid of :) There is my solution:

    1. '#include < pthread.h >',
    2. declare pthread_t thread in newGame(),
    3. add pthread_create(&thread, NULL, playersTurn, NULL); into newGame()
    4. you can leave 'while(PLAYERCHOOSING)' loop as it is.
    5. compile with -lpthread flag.

    Voila, you are amazing.