Waiting for user input so game logic can continue

Hi all,

I am creating a little battleship game, where at the beginning the player should enter the coordinates of his ships via a display running with LVGL. I am using Arduino as IDE

As each player has lets say 2 ships. So I though I run a for loop to get all the coordinates of the ships. In the loop I am waiting for the user input from the display:

Code

for (int j = 0; j < NUM_SHIPS; ++j) {
Ship& ship = players[1].ships[j]

        while  (startPointX && startPointY == Null){

       // wait for user input
        }
       ship.startX = startPointX
       ship.startY = startPointY

    }

In the event of the text area I am filling the startPointX & startPointY.

But in this way the display does not react, as it is not running in the usual loop() with the lv_task_handler() function.

How can I best wait for a user input in such a case, so that the game logic can continue?

This is how I did it:

while  (startPointX != Null && startPointY != Null){

lv_task_handler(); 
    lv_tick_inc(5);
    delay(5); 
}
 ship.startX = startPointX
       ship.startY = startPointY

I have a game simulation program written in two parts; I wrote the actual functionality first, and then the GUI to display sign language alphabet it all. I figured … When my Text Box says "Press 1 to Continue or 2 to exit the game " I then want to wait for the user input to handle it correctly. I can 't use the … As far as I can tell, the Main Loop is still not going to block waiting* for an event. So my node(s) will not get any CPU, but the main loop will …

The issue is that your code is blocking the main loop, which prevents lv_task_handler() from being called — and that’s why your display stops responding. In LVGL (and generally in event-driven systems), you can’t use while loops to “wait” for user input, because it halts everything else.

Instead, you should structure your game logic as a state machine or use callbacks/events. For example:

  1. Keep a variable like currentShipIndex and a flag that indicates whether you’re waiting for input.
  2. When the player finishes entering coordinates (handled in your LVGL event), store the values and then increment currentShipIndex.
  3. Once all ships are placed, move to the next game state (e.g., start the battle).

Something like this (simplified):

int currentShipIndex = 0;
bool waitingForInput = true;

void loop() {
    lv_task_handler();

    if (!waitingForInput && currentShipIndex < NUM_SHIPS) {
        players[1].ships[currentShipIndex].startX = startPointX;
        players[1].ships[currentShipIndex].startY = startPointY;
        currentShipIndex++;
        waitingForInput = true;
    }
}

void onUserInputReceived(int x, int y) {
    startPointX = x;
    startPointY = y;
    waitingForInput = false;
}

This way, the GUI stays responsive, and your logic progresses step by step as the player interacts.

In short — avoid blocking loops and let LVGL handle user input asynchronously.