diff --git a/backend/src/index.ts b/backend/src/index.ts
index fc2b951f4475ee2833fcf9a04a9694f78d0664bf..c73a1f1f6f8fdf0f93a8702ae36f5b752a0f6350 100644
--- a/backend/src/index.ts
+++ b/backend/src/index.ts
@@ -18,6 +18,8 @@ app.use((req, res, next) => {
   next();
 });
 
+app.use(express.json());
+
 app.get('/', (req, res) => {
   res.send('Hello, World!');
 });
@@ -123,26 +125,43 @@ app.get('/highscores', async (req, res) => {
 });
 
 // join a lobby with specific id
-app.post('/lobby/:id', async (req, res) => {
-  if (gameHandler.getLobbyById(req.params.id)) {
-    const lobby = gameHandler.getLobbyById(req.params.id);
+app.post('/lobby/create', async (req, res) => {
+  // if lobby doesn't exist, create a new lobby
+  const lobby = gameHandler.createLobby();
+  lobby.addUser(req.body.userId);
+  res.status(201).send({ lobbyId: lobby.getId() });
+});
 
-    if (!lobby) {
-      res.status(404).send('Lobby not found');
-      return;
-    }
+// Inform client if requested lobby is full or not
+app.get('/lobby/:id/status', async (req, res) => {
+  const lobby = gameHandler.getLobbyById(req.params.id);
 
-    lobby.addUser(req.body.userId);
-    gameHandler.createGame(lobby); // start game since 2 players are in lobby
-    res.status(200).send(lobby.getId());
+  if (!lobby) {
+    res.status(404).send('Lobby not found');
+    return;
+  }
+
+  if (lobby.isFull()) {
+    res.status(200).send({ isFull: true });
   } else {
-    // if lobby doesn't exist, create a new lobby
-    const lobby = gameHandler.createLobby();
-    lobby.addUser(req.body.userId);
-    res.status(201).send(lobby.getId());
+    res.status(200).send({ isFull: false });
   }
 });
 
+// join a lobby with specific id
+app.post('/lobby/:id/join', async (req, res) => {
+  const lobby = gameHandler.getLobbyById(req.params.id);
+
+  if (!lobby) {
+    res.status(404).send('Lobby not found');
+    return;
+  }
+
+  lobby.addUser(req.body.userId);
+  gameHandler.createGame(lobby); // start game since 2 players are in lobby
+  res.status(200).send({ lobbyId: lobby.getId() });
+});
+
 // leave a lobby with specific id
 app.post('/lobby/:id/leave', async (req, res) => {
   const lobby = gameHandler.getLobbyById(req.params.id);
@@ -151,7 +170,7 @@ app.post('/lobby/:id/leave', async (req, res) => {
   if (lobby?.getUsers().length === 0) {
     gameHandler.removeLobby(lobby);
   }
-  res.status(200).send(lobby?.getId());
+  res.status(200).send({ lobbyId: lobby?.getId() });
 });
 
 // Polling endpoint to check if its your turn (sends username)
diff --git a/backend/src/interfaces/ILobby.ts b/backend/src/interfaces/ILobby.ts
index 46edf40f6606d9719f81da94586b2bde9ca473ea..072b103f46334b6c72e3d1ccb5dc07946e083589 100644
--- a/backend/src/interfaces/ILobby.ts
+++ b/backend/src/interfaces/ILobby.ts
@@ -6,5 +6,6 @@ export interface ILobby {
   getUsers(): User[];
   id: string;
   getId(): string;
+  isFull(): boolean;
   // maybe add a relation to a game?
 }
diff --git a/backend/src/lobby/Lobby.ts b/backend/src/lobby/Lobby.ts
index 2c3acecff54164234e47f1a964993f18c3d3c977..34e0f12cf16e8b1390d695bd1c3d6702d8fb9149 100644
--- a/backend/src/lobby/Lobby.ts
+++ b/backend/src/lobby/Lobby.ts
@@ -44,4 +44,8 @@ export class Lobby implements ILobby {
   getUsers() {
     return this.users;
   }
+
+  isFull() {
+    return this.game != undefined;
+  }
 }
diff --git a/frontend/assets/menu-textures.atlas b/frontend/assets/menu-textures.atlas
index 046381c0b71c99f89d48c22fd37f0195871832d0..a9e0a1c361a9a9e07a8aa6a454b49e5ab93529eb 100644
--- a/frontend/assets/menu-textures.atlas
+++ b/frontend/assets/menu-textures.atlas
@@ -67,13 +67,20 @@ logo
   orig: 134, 40
   offset: 0, 0
   index: -1
-transparent-white-box
+semi-transparent-white-box
   rotate: false
   xy: 921, 1009
   size: 1, 1
   orig: 1, 1
   offset: 0, 0
   index: -1
+transparent-white-box
+  rotate: false
+  xy: 892, 973
+  size: 1, 1
+  orig: 1, 1
+  offset: 0, 0
+  index: -1
 typing-cursor
   rotate: false
   xy: 2, 2
diff --git a/frontend/assets/menu-textures.png b/frontend/assets/menu-textures.png
index 6b223eced211d505301197211b096bcdbc94a6c7..bd0676b21eceb450b41ae64eee8bc8f276ba16f6 100644
Binary files a/frontend/assets/menu-textures.png and b/frontend/assets/menu-textures.png differ
diff --git a/frontend/core/src/com/game/tankwars/HTTPRequestHandler.java b/frontend/core/src/com/game/tankwars/HTTPRequestHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..dace91d89e8b477ede77918ff814e459ff088cd2
--- /dev/null
+++ b/frontend/core/src/com/game/tankwars/HTTPRequestHandler.java
@@ -0,0 +1,74 @@
+package com.game.tankwars;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Net;
+import com.badlogic.gdx.Net.HttpResponse;
+
+/**
+ * Handles request and response from the HTTP request using
+ * a passed callback function that treats request success, failure and cancellation.
+ * Implements the retry tactic by resending the request on failure
+ * a few times with increasing backoff time between resends.
+ */
+public class HTTPRequestHandler implements Net.HttpResponseListener {
+
+    public static final String PROTOCOL = "http";
+    public static final String HOST = "localhost";
+    public static final int PORT = 3000;
+
+    private final Callback callback;
+    private final Net.HttpRequest request;
+    private int attempts = 0;
+    private final int MAX_ATTEMPTS = 3;
+    private final int BACKOFF_TIME = 300;
+
+    public HTTPRequestHandler(Callback callback, Net.HttpRequest request) {
+        this.callback = callback;
+        this.request = request;
+    }
+
+    /**
+     * Send the HTTP request
+     */
+    public void sendRequest() {
+        Gdx.net.sendHttpRequest(request, this);
+    }
+
+    /**
+     * Request was successful and response received. Passes response body
+     * to callback.
+     *
+     * @param httpResponse The {@link HttpResponse} with the HTTP response values.
+     */
+    public void handleHttpResponse(HttpResponse httpResponse) {
+        callback.onResult(httpResponse.getResultAsString());
+    }
+
+    /**
+     * Request failed. Request will be retried until the attempts
+     * have been exhausted with an increasing backoff time between each retry.
+     *
+     * @param t If the HTTP request failed because an Exception, t encapsulates it to give more information.
+     */
+    public void failed(Throwable t) {
+        if (attempts < MAX_ATTEMPTS) {
+            attempts++;
+
+            try {
+                Thread.sleep((long) attempts * BACKOFF_TIME);
+                sendRequest();
+            } catch(InterruptedException e) {
+                System.err.println(e.getMessage());
+            }
+        } else {
+            callback.onFailed(t);
+        }
+    }
+
+    /**
+     * Request was cancelled
+     */
+    public void cancelled() {
+        System.out.println("Request cancelled");
+    }
+}
\ No newline at end of file
diff --git a/frontend/core/src/com/game/tankwars/ReceiverHandler.java b/frontend/core/src/com/game/tankwars/ReceiverHandler.java
index 4f16b98b91e6479f626057606e936d81817d1629..a0adc82af98ba35ab1ba6c3a01d627cc94fdb67b 100644
--- a/frontend/core/src/com/game/tankwars/ReceiverHandler.java
+++ b/frontend/core/src/com/game/tankwars/ReceiverHandler.java
@@ -19,6 +19,10 @@ public class ReceiverHandler implements Net.HttpResponseListener {
     private final Callback callback;
     public static final int MAX_RETRIES = 5;
 
+    public static final String PROTOCOL = "http";
+    public static final String HOST = "localhost";
+    public static final int PORT = 3000;
+
     // Constructor to initialize the Callback instance
     public ReceiverHandler(Callback callback) {
         this.callback = callback;
diff --git a/frontend/core/src/com/game/tankwars/TankWarsGame.java b/frontend/core/src/com/game/tankwars/TankWarsGame.java
index 2e86cff9a98de774ec67e1f01e572798a3b07ef3..3c93ec84373938149727812059eb8324ddda054a 100644
--- a/frontend/core/src/com/game/tankwars/TankWarsGame.java
+++ b/frontend/core/src/com/game/tankwars/TankWarsGame.java
@@ -4,6 +4,7 @@
 package com.game.tankwars;
 
 import com.badlogic.gdx.Game;
+import com.game.tankwars.view.FindGameScreen;
 import com.game.tankwars.view.LoginScreen;
 
 public class TankWarsGame extends Game {
diff --git a/frontend/core/src/com/game/tankwars/controller/FindGameController.java b/frontend/core/src/com/game/tankwars/controller/FindGameController.java
index 4730e36abefc93d7700358d63f8bf5f9329b9a4d..f98492c6f7f5e7c71adf3d9edad3eff526226c62 100644
--- a/frontend/core/src/com/game/tankwars/controller/FindGameController.java
+++ b/frontend/core/src/com/game/tankwars/controller/FindGameController.java
@@ -1,71 +1,104 @@
 package com.game.tankwars.controller;
 
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Net;
+import com.badlogic.gdx.net.HttpRequestBuilder;
+import com.badlogic.gdx.scenes.scene2d.EventListener;
 import com.badlogic.gdx.scenes.scene2d.InputEvent;
 import com.badlogic.gdx.scenes.scene2d.InputListener;
 import com.badlogic.gdx.scenes.scene2d.Stage;
 import com.badlogic.gdx.scenes.scene2d.ui.Button;
+import com.badlogic.gdx.scenes.scene2d.ui.Label;
 import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
 import com.badlogic.gdx.scenes.scene2d.ui.TextField;
 import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
+import com.badlogic.gdx.utils.Json;
+import com.badlogic.gdx.utils.SerializationException;
+import com.game.tankwars.Callback;
+import com.game.tankwars.ConfigReader;
+import com.game.tankwars.HTTPRequestHandler;
 import com.game.tankwars.ResourceManager;
 import com.game.tankwars.TankWarsGame;
+import com.game.tankwars.model.CurrentUser;
+import com.game.tankwars.model.LobbyId;
+import com.game.tankwars.model.LobbyStatus;
+import com.game.tankwars.view.FindGameScreen;
 import com.game.tankwars.view.GameScreen;
 import com.game.tankwars.view.MainMenuScreen;
 
+
 public class FindGameController {
 
     private final TankWarsGame tankWarsGame;
+    private final FindGameScreen screen;
     private final Stage stage;
     private final TextField gamePinField;
-    private final TextButton joinLobbyButton, createLobbyButton;
+    private final TextButton joinLobbyButton, createLobbyButton, cancelButton;
     private final Button backButton;
+    private final Label gamePinWaitingLabel;
+
+    private EventListener backButtonInputListener, gamePinFieldInputListener,
+            gamePinFieldClickListener, joinLobbyButtonInputListener,
+            createLobbyButtonInputListener, cancelButtonInputListener;
+
+    private String lobbyId = null;
+    private final Runnable gameScreenTransition;
+
 
     /**
+     * TODO: Ensure that user is logged in -> e.g. auth method in Auth/Utils class
      * Sets the event listeners of the buttons and the text field of the FindGameScreen,
-     * and allows for transitioning to MainMenuScreen and to GameScreen.
+     * and allows for transitioning to MainMenuScreen and to GameScreen. Handles communication
+     * with server to create, join and leave a lobbies.
      */
-    public FindGameController(final TankWarsGame tankWarsGame,
+    public FindGameController(final TankWarsGame tankWarsGame, FindGameScreen screen,
                               TextField gamePinField, TextButton joinLobbyButton,
-                              TextButton createLobbyButton, Button backButton, final Stage stage) {
+                              TextButton createLobbyButton, Button backButton,
+                              TextButton cancelButton, Label gamePinWaitingLabel,
+                              final Stage stage) {
         this.tankWarsGame = tankWarsGame;
+        this.screen = screen;
+
         this.gamePinField = gamePinField;
         this.joinLobbyButton = joinLobbyButton;
         this.createLobbyButton = createLobbyButton;
         this.backButton = backButton;
+        this.cancelButton = cancelButton;
+        this.gamePinWaitingLabel = gamePinWaitingLabel;
         this.stage = stage;
 
-        setEventListeners();
+        // This Runnable will be passed to the "render" thread
+        // using Gdx.app.postRunnable() from the threads of HTTP requests
+        gameScreenTransition = new Runnable() {
+            @Override
+            public void run() {
+                ResourceManager.getInstance().clear();
+                tankWarsGame.setScreen(new GameScreen(tankWarsGame));
+            }
+        };
+
+        defineEventListeners();
+        setMainListeners();
     }
 
-    public void setEventListeners() {
+    private void defineEventListeners() {
 
         /*
-         * Transitions back to MainMenuScreen
+         * Transition back to MainMenuScreen
          */
-        backButton.addListener(new InputListener() {
+        backButtonInputListener = new InputListener() {
             @Override
             public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                 tankWarsGame.setScreen(new MainMenuScreen(tankWarsGame));
                 return true;
             }
-        });
+        };
 
         /*
-         * Filters text field input:
-         * Max 4 characters long and only digits
+         * Remove keyboard and reset camera position when "Enter" button is pressed.
+         * Enable the joinLobbyButton when gamePinField contains at least one character.
          */
-        gamePinField.setTextFieldFilter(new TextField.TextFieldFilter() {
-            @Override
-            public boolean acceptChar(TextField textField, char c) {
-                return textField.getText().length() < 4 && Character.isDigit(c);
-            }
-        });
-
-        /*
-         * Enables the joinLobbyButton when the gamePinField contains 4 digits,
-         * and disables it otherwise
-         */
-        gamePinField.addListener(new InputListener() {
+        gamePinFieldInputListener = new InputListener() {
             @Override
             public boolean keyTyped(InputEvent event, char character) {
                 super.keyTyped(event, character);
@@ -77,50 +110,236 @@ public class FindGameController {
                     stage.getViewport().apply();
                 }
 
-                joinLobbyButton.setDisabled(gamePinField.getText().length() != 4);
-
+                joinLobbyButton.setDisabled(gamePinField.getText().length() == 0);
                 return true;
             }
-        });
+        };
 
         /*
          * Move camera down when text field is clicked
          * to make the field appear above the keyboard.
          */
-        gamePinField.addListener(new ClickListener() {
+        gamePinFieldClickListener = new ClickListener() {
             @Override
             public void clicked(InputEvent event, float x, float y) {
                 super.clicked(event, x, y);
                 stage.getViewport().setScreenY((int) (2 * stage.getHeight() / 3));
                 stage.getViewport().apply();
             }
-        });
+        };
 
         /*
-         * Disables input listener when the button is disabled.
-         * TODO: Join a lobby by sending a request to the backend
+         * Send HTTP request to join lobby with game pin specified in text field.
+         * Avoid sending request if joinLobbyButton is disabled.
          */
-        joinLobbyButton.addListener(new InputListener() {
+        joinLobbyButtonInputListener = new InputListener() {
             @Override
             public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                 if (joinLobbyButton.isDisabled()) return true;
 
-                System.out.println("Game pin: " + gamePinField.getText() + " - yet to be implemented");
+                joinLobby();
                 return true;
             }
-        });
+        };
 
         /*
-         * TODO: Create a lobby by sending request to backend - Transition to waiting screen?
+         * Create new lobby and display waiting window.
+         * Poll server for lobby status to know when to transition to game screen.
          */
-        createLobbyButton.addListener(new InputListener() {
+        createLobbyButtonInputListener = new InputListener() {
             @Override
             public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
-                ResourceManager.getInstance().clear();
-                tankWarsGame.setScreen(new GameScreen(tankWarsGame));
+                createLobby();
                 return true;
             }
-        });
+        };
+
+        /*
+         * Exit from waiting window and render normal FindGameScreen
+         */
+        cancelButtonInputListener = new InputListener() {
+          @Override
+          public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
+              exitLobby();
+              return true;
+          }
+        };
+    }
+
+
+    public void setMainListeners() {
+        backButton.addListener(backButtonInputListener);
+        gamePinField.addListener(gamePinFieldInputListener);
+        gamePinField.addListener(gamePinFieldClickListener);
+        joinLobbyButton.addListener(joinLobbyButtonInputListener);
+        createLobbyButton.addListener(createLobbyButtonInputListener);
+    }
+
+    public void removeMainListeners() {
+        backButton.removeListener(backButtonInputListener);
+        gamePinField.removeListener(gamePinFieldInputListener);
+        gamePinField.removeListener(gamePinFieldClickListener);
+        joinLobbyButton.removeListener(joinLobbyButtonInputListener);
+        createLobbyButton.removeListener(createLobbyButtonInputListener);
+    }
+
+    public void setWaitingWindowListeners() {
+        cancelButton.addListener(cancelButtonInputListener);
+    }
+
+    public void removeWaitingWindowListeners() {
+        cancelButton.removeListener(cancelButtonInputListener);
     }
 
+
+    /**
+     * Send HTTP request to create a new lobby.
+     * On success, a waiting window is shown, and polling for
+     * the lobby status is initiated.
+     */
+    private void createLobby() {
+        new HTTPRequestHandler(new Callback() {
+            @Override
+            public void onResult(String result) {
+                try {
+                    LobbyId lobbyIdClass = new Json().fromJson(LobbyId.class, result);
+                    lobbyId = lobbyIdClass.getLobbyId();
+
+                    removeMainListeners();
+                    setWaitingWindowListeners();
+
+                    gamePinWaitingLabel.setText("Game pin: " + lobbyId);
+                    screen.showWaitingWindow();
+
+                    checkLobbyStatus();
+                } catch (SerializationException e) {
+                    System.err.println("Invalid HTTP response on create lobby");
+                }
+            }
+
+            @Override
+            public void onFailed(Throwable t) {
+                System.err.println("Create lobby request failed:\n" + t);
+            }
+        }, new HttpRequestBuilder()
+                .newRequest()
+                .url(String.format("%s/lobby/create", ConfigReader.getProperty("backend.url")))
+                .method(Net.HttpMethods.POST)
+                .header("Content-Type", "application/json")
+                .content(String.format("{\"userId\": \"%s\"}", CurrentUser.getCurrentUser().getUser().id))
+                .build())
+                .sendRequest();
+    }
+
+    /**
+     * Send HTTP request while waiting for lobby to fill,
+     * polling for the lobby's fill status with a set backoff period between requests.
+     * Transition to game screen when lobby is full.
+     */
+    private void checkLobbyStatus() {
+        new HTTPRequestHandler(new Callback() {
+            @Override
+            public void onResult(String result) {
+                try {
+                    LobbyStatus lobbyStatus = new Json().fromJson(LobbyStatus.class, result);
+
+                    if (lobbyStatus.isFull()) {
+                        Gdx.app.postRunnable(gameScreenTransition);
+                    } else if (lobbyId != null) {
+                        System.out.println("Awaiting opponent...");
+
+                        try {
+                            Thread.sleep(1500);
+                            if (lobbyId != null) checkLobbyStatus();
+                        } catch (InterruptedException e) {
+                            System.out.println(e.getMessage());
+                            exitLobby();
+                        }
+                    }
+                } catch (SerializationException e) {
+                    System.err.println("Invalid HTTP response on check lobby status");
+                    exitLobby();
+                }
+            }
+
+            @Override
+            public void onFailed(Throwable t) {
+                System.err.println("Check lobby status request failed:\n" + t);
+                exitLobby();
+            }
+        }, new HttpRequestBuilder()
+                .newRequest()
+                .url(String.format("%s/lobby/%s/status",
+                        ConfigReader.getProperty("backend.url"), lobbyId))
+                .method(Net.HttpMethods.GET)
+                .build())
+                .sendRequest();
+    }
+
+    /**
+     * Send HTTP request to exit the joined lobby while the lobby
+     * is not yet full. Hide the waiting window.
+     */
+    private void exitLobby() {
+        new HTTPRequestHandler(new Callback() {
+            @Override
+            public void onResult(String result) {
+                removeWaitingWindowListeners();
+                setMainListeners();
+
+                lobbyId = null;
+                screen.hideWaitingWindow();
+            }
+
+            @Override
+            public void onFailed(Throwable t) {
+                System.err.println("Exit lobby request failed:\n" + t);
+                removeWaitingWindowListeners();
+                setMainListeners();
+
+                lobbyId = null;
+                screen.hideWaitingWindow();
+            }
+        }, new HttpRequestBuilder()
+                .newRequest()
+                .url(String.format("%s/lobby/%s/leave",
+                        ConfigReader.getProperty("backend.url"), lobbyId))
+                .method(Net.HttpMethods.POST)
+                .header("Content-Type", "application/json")
+                .content(String.format("{\"userId\": \"%s\"}", CurrentUser.getCurrentUser().getUser().id))
+                .build())
+                .sendRequest();
+    }
+
+    /**
+     * Send HTTP request to join a lobby using the game pin in the text field.
+     * On success, transition to game screen.
+     */
+    private void joinLobby() {
+        new HTTPRequestHandler(new Callback() {
+            @Override
+            public void onResult(String result) {
+                try {
+                    new Json().fromJson(LobbyId.class, result);
+
+                    Gdx.app.postRunnable(gameScreenTransition);
+                } catch (SerializationException e) {
+                    System.out.println(result);
+                }
+            }
+
+            @Override
+            public void onFailed(Throwable t) {
+                System.err.println("Join lobby request failed:\n" + t);
+            }
+        }, new HttpRequestBuilder()
+                .newRequest()
+                .url(String.format("%s/lobby/%s/join",
+                        ConfigReader.getProperty("backend.url"), gamePinField.getText()))
+                .method(Net.HttpMethods.POST)
+                .header("Content-Type", "application/json")
+                .content(String.format("{\"userId\": \"%s\"}", CurrentUser.getCurrentUser().getUser().id))
+                .build())
+                .sendRequest();
+    }
 }
diff --git a/frontend/core/src/com/game/tankwars/model/LobbyId.java b/frontend/core/src/com/game/tankwars/model/LobbyId.java
new file mode 100644
index 0000000000000000000000000000000000000000..a2cb3750e1a5fdfc4e40eebb724e0aa8324ae9a8
--- /dev/null
+++ b/frontend/core/src/com/game/tankwars/model/LobbyId.java
@@ -0,0 +1,14 @@
+package com.game.tankwars.model;
+
+public class LobbyId {
+
+    private String lobbyId;
+
+    public String getLobbyId() {
+        return lobbyId;
+    }
+
+    public void setLobbyId(String lobbyId) {
+        this.lobbyId = lobbyId;
+    }
+}
diff --git a/frontend/core/src/com/game/tankwars/model/LobbyStatus.java b/frontend/core/src/com/game/tankwars/model/LobbyStatus.java
new file mode 100644
index 0000000000000000000000000000000000000000..2c0bc324af9d7050e8ceb36727f0eb61b93bd010
--- /dev/null
+++ b/frontend/core/src/com/game/tankwars/model/LobbyStatus.java
@@ -0,0 +1,13 @@
+package com.game.tankwars.model;
+
+public class LobbyStatus {
+    private boolean isFull;
+
+    public boolean isFull() {
+        return isFull;
+    }
+
+    public void setFull(boolean full) {
+        isFull = full;
+    }
+}
diff --git a/frontend/core/src/com/game/tankwars/view/FindGameScreen.java b/frontend/core/src/com/game/tankwars/view/FindGameScreen.java
index 3c4f4885e950c37fe2f3687069b30765da3052ce..bf5f2c5ba2174e5aa080463523d8ce01a9d6537e 100644
--- a/frontend/core/src/com/game/tankwars/view/FindGameScreen.java
+++ b/frontend/core/src/com/game/tankwars/view/FindGameScreen.java
@@ -28,6 +28,8 @@ public class FindGameScreen implements Screen {
 
     private final TankWarsGame tankWarsGame;
     private Stage stage;
+    private Group layoutGroup;
+    private Table windowTable;
 
     public FindGameScreen(final TankWarsGame tankWarsGame) {
         this.tankWarsGame = tankWarsGame;
@@ -65,7 +67,7 @@ public class FindGameScreen implements Screen {
         float rw = stage.getWidth() - lw;
 
         Table rootTable = new Table();
-        rootTable.setFillParent(true);
+        rootTable.setBounds(0, 0, stage.getWidth(), stage.getHeight());
 
         Group leftGroup = new Group();
         leftGroup.setSize(lw, stage.getHeight());
@@ -96,9 +98,42 @@ public class FindGameScreen implements Screen {
 
         rootTable.add(leftGroup).width(lw).height(stage.getHeight());
         rootTable.add(rightTable).expandX().height(stage.getHeight());
-        stage.addActor(rootTable);
 
-        new FindGameController(tankWarsGame, gamePinField, joinLobbyButton, createLobbyButton, backButton, stage);
+        //--- Awaiting opponent window
+        windowTable = new Table();
+        float ww = 3 * stage.getWidth() / 5f;
+        float wh = 3 * stage.getHeight() / 5f;
+
+        windowTable.setBounds(stage.getWidth() / 2f - ww / 2f, stage.getHeight() / 2f - wh / 2f, ww, wh);
+
+        Drawable windowBackground = skin.getDrawable("semi-transparent-white-box");
+        Label waitingLabel = new Label("Awaiting opponent...", skin.get("default", Label.LabelStyle.class));
+        Label gamePinWaitingLabel = new Label("Game pin: ---", skin.get("default", Label.LabelStyle.class));
+        TextButton cancelButton = new TextButton("Cancel", skin.get("default", TextButton.TextButtonStyle.class));
+
+        windowTable.background(windowBackground);
+        windowTable.row().expand();
+        windowTable.add(waitingLabel);
+        windowTable.row().expand();
+        windowTable.add(gamePinWaitingLabel);
+        windowTable.row().expand();
+        windowTable.add(cancelButton).width(2 * ww / 3f).height(30);
+
+
+        layoutGroup = new Group();
+        layoutGroup.addActor(rootTable);
+
+        stage.addActor(layoutGroup);
+
+        new FindGameController(tankWarsGame, this, gamePinField,
+                joinLobbyButton, createLobbyButton,
+                backButton, cancelButton, gamePinWaitingLabel, stage);
+    }
+
+    public void showWaitingWindow() { layoutGroup.addActor(windowTable); }
+
+    public void hideWaitingWindow() {
+        layoutGroup.removeActor(windowTable);
     }
 
     @Override