diff --git a/overcooked_simulator/game_content/layouts/godot_test_layout.layout b/overcooked_simulator/game_content/layouts/godot_test_layout.layout
new file mode 100644
index 0000000000000000000000000000000000000000..06db451a2f644732cc693835a9a5aaee6a38d612
--- /dev/null
+++ b/overcooked_simulator/game_content/layouts/godot_test_layout.layout
@@ -0,0 +1,9 @@
+##########
+#________#
+#________#
+#________#
+#________#
+#________#
+#________#
+#________#
+#########P
diff --git a/overcooked_simulator/game_content/layouts/split.layout b/overcooked_simulator/game_content/layouts/split.layout
new file mode 100644
index 0000000000000000000000000000000000000000..39bace3e0a94b0594d8ef9f294daeb40aae4492f
--- /dev/null
+++ b/overcooked_simulator/game_content/layouts/split.layout
@@ -0,0 +1,9 @@
+#QU#T###NLB#
+#__________M
+#____A_____#
+W__________#
+############
+C__________#
+C_____A____#
+#__________X
+#P#S+####S+#
\ No newline at end of file
diff --git a/overcooked_simulator/game_server.py b/overcooked_simulator/game_server.py
new file mode 100644
index 0000000000000000000000000000000000000000..3832221d9561f61b43eae2773010d4ef2072e7d4
--- /dev/null
+++ b/overcooked_simulator/game_server.py
@@ -0,0 +1,98 @@
+import asyncio
+import json
+import logging
+import os
+import sys
+import threading
+from datetime import datetime
+
+import numpy as np
+from websockets.server import serve
+
+from overcooked_simulator import ROOT_DIR
+from overcooked_simulator.overcooked_environment import Action
+from overcooked_simulator.simulation_runner import Simulator
+
+log = logging.getLogger(__name__)
+
+
+PORT = 8765
+
+
+class Connector:
+    def __init__(self, simulator: Simulator):
+        self.simulator: Simulator = simulator
+
+        super().__init__()
+
+    async def process_message(self, websocket):
+        async for message in websocket:
+            if message.replace('"', "") != "get_state":
+                message_dict = json.loads(message)
+                if message_dict["act_type"] == "movement":
+                    value = np.array(message_dict["value"])
+                else:
+                    value = None
+                action = Action(
+                    message_dict["player_name"], message_dict["act_type"], value
+                )
+                self.simulator.enter_action(action)
+
+            json_answer = self.simulator.get_state_simple_json()
+
+            # print("json:", json_answer, type(json_answer))
+            await websocket.send(json_answer)
+
+    async def connection_server(self):
+        async with serve(self.process_message, "localhost", PORT):
+            await asyncio.Future()  # run forever
+
+    def set_sim(self, simulation_runner: Simulator):
+        self.simulator = simulation_runner
+
+    def start_connector(self):
+        asyncio.run(self.connection_server())
+
+
+def setup_logging():
+    path_logs = ROOT_DIR.parent / "logs"
+    os.makedirs(path_logs, exist_ok=True)
+    logging.basicConfig(
+        level=logging.DEBUG,
+        format="%(asctime)s %(levelname)-8s %(name)-50s %(message)s",
+        handlers=[
+            logging.FileHandler(
+                path_logs / f"{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}_debug.log",
+                encoding="utf-8",
+            ),
+            logging.StreamHandler(sys.stdout),
+        ],
+    )
+
+
+def main():
+    simulator = Simulator(
+        ROOT_DIR / "game_content" / "environment_config.yaml",
+        ROOT_DIR / "game_content" / "layouts" / "basic.layout",
+        600,
+    )
+    number_player = 2
+    for i in range(number_player):
+        player_name = f"p{i}"
+        simulator.register_player(player_name)
+
+    connector = Connector(simulator)
+    connector.start_connector()
+
+
+if __name__ == "__main__":
+    setup_logging()
+    try:
+        main()
+    except Exception as e:
+        log.exception(e)
+        for thread in threading.enumerate():
+            if isinstance(thread, Simulator):
+                thread.stop()
+                thread.join()
+        sys.exit(1)
diff --git a/overcooked_simulator/gui_2d_vis/overcooked_gui.py b/overcooked_simulator/gui_2d_vis/overcooked_gui.py
index 7c910c07f9b6fadfd571a64eaf6d4f606fee333f..7d7e8aea4d86494b9bf9134be0208b3d516d6354 100644
--- a/overcooked_simulator/gui_2d_vis/overcooked_gui.py
+++ b/overcooked_simulator/gui_2d_vis/overcooked_gui.py
@@ -1,4 +1,5 @@
 import colorsys
+import json
 import logging
 import math
 import sys
@@ -11,6 +12,7 @@ import pygame
 import pygame_gui
 import yaml
 from scipy.spatial import KDTree
+from websockets.sync.client import connect
 
 from overcooked_simulator import ROOT_DIR
 from overcooked_simulator.counters import Counter
@@ -26,9 +28,9 @@ from overcooked_simulator.gui_2d_vis.game_colors import colors, Color
 from overcooked_simulator.overcooked_environment import Action
 from overcooked_simulator.simulation_runner import Simulator
 
-USE_PLAYER_COOK_SPRITES = True
+USE_PLAYER_COOK_SPRITES = False
 SHOW_INTERACTION_RANGE = False
-SHOW_COUNTER_CENTERS = False
+SHOW_COUNTER_CENTERS = True
 
 
 class MenuStates(Enum):
@@ -90,13 +92,11 @@ class PyGameGUI:
 
     def __init__(
         self,
-        simulator: Simulator,
         player_names: list[str],
         player_keys: list[pygame.key],
     ):
         self.game_screen = None
         self.FPS = 60
-        self.simulator: Simulator = simulator
         self.running = True
 
         self.player_names = player_names
@@ -109,6 +109,8 @@ class PyGameGUI:
             )
         ]
 
+        self.websocket_url = "ws://localhost:8765"
+
         # TODO cache loaded images?
         with open(ROOT_DIR / "gui_2d_vis" / "visualization.yaml", "r") as file:
             self.visualization_config = yaml.safe_load(file)
@@ -134,22 +136,35 @@ class PyGameGUI:
         self.manager: pygame_gui.UIManager
 
     def init_window_sizes(self):
-        if self.visualization_config["GameWindow"]["WhatIsFixed"] == "window_width":
-            game_width = self.visualization_config["GameWindow"]["size"]
-            kitchen_aspect_ratio = (
-                self.simulator.env.kitchen_height / self.simulator.env.kitchen_width
-            )
-            game_height = int(game_width * kitchen_aspect_ratio)
-            grid_size = int(game_width / self.simulator.env.kitchen_width)
-        elif self.visualization_config["GameWindow"]["WhatIsFixed"] == "grid":
-            grid_size = self.visualization_config["GameWindow"]["size"]
-            game_width, game_height = (
-                self.simulator.env.kitchen_width * grid_size,
-                self.simulator.env.kitchen_height * grid_size,
-            )
-        else:
-            game_width, game_height = 0, 0
-            grid_size = 0
+        state = self.request_state()
+        print("THIS:", state["counters"])
+        counter_positions = np.array([c["pos"] for c in state["counters"]])
+        print(counter_positions)
+        kitchen_width = np.max(counter_positions[:, 0]) + 0.5
+        kitchen_height = np.max(counter_positions[:, 1]) + 0.5
+
+        print(kitchen_width, kitchen_height)
+
+        # if self.visualization_config["GameWindow"]["WhatIsFixed"] == "window_width":
+        #     game_width = self.visualization_config["GameWindow"]["size"]
+        #     kitchen_aspect_ratio = (
+        #         self.simulator.env.kitchen_height / self.simulator.env.kitchen_width
+        #     )
+        #     game_height = int(game_width * kitchen_aspect_ratio)
+        #     grid_size = int(game_width / self.simulator.env.kitchen_width)
+        # elif self.visualization_config["GameWindow"]["WhatIsFixed"] == "grid":
+        #     grid_size = self.visualization_config["GameWindow"]["size"]
+        #     game_width, game_height = (
+        #         self.simulator.env.kitchen_width * grid_size,
+        #         self.simulator.env.kitchen_height * grid_size,
+        #     )
+        # else:
+        #     game_width, game_height = 0, 0
+        #     grid_size = 0
+
+        grid_size = 40
+        game_width = kitchen_width * grid_size
+        game_height = kitchen_height * grid_size
 
         window_width, window_height = (
             game_width + (2 * self.screen_margin),
@@ -159,7 +174,7 @@ class PyGameGUI:
         return window_width, window_height, game_width, game_height, grid_size
 
     def create_player_colors(self) -> list[Color]:
-        number_player = len(self.simulator.env.players)
+        number_player = len(self.player_keys)
         hue_values = np.linspace(0, 1, number_player + 1)
 
         colors_vec = np.array([col for col in colors.values()])
@@ -177,14 +192,6 @@ class PyGameGUI:
 
         return player_colors
 
-    def send_action(self, action: Action):
-        """Sends an action to the game environment.
-
-        Args:
-            action: The action to be sent. Contains the player, action type and move direction if action is a movement.
-        """
-        self.simulator.enter_action(action)
-
     def handle_keys(self):
         """Handles keyboard inputs. Sends action for the respective players. When a key is held down, every frame
         an action is sent in this function.
@@ -230,8 +237,8 @@ class PyGameGUI:
         self.game_screen.fill(
             colors[self.visualization_config["Kitchen"]["ground_tiles_color"]]
         )
-        for x in range(0, self.window_width, block_size):
-            for y in range(0, self.window_height, block_size):
+        for x in range(0, int(self.window_width), block_size):
+            for y in range(0, int(self.window_height), block_size):
                 rect = pygame.Rect(x, y, block_size, block_size)
                 pygame.draw.rect(
                     self.game_screen,
@@ -257,7 +264,7 @@ class PyGameGUI:
         rect.center = pos
         self.game_screen.blit(image, rect)
 
-    def draw_players(self, state):
+    def draw_players(self, state, state_dict):
         """Visualizes the players as circles with a triangle for the facing direction.
         If the player holds something in their hands, it is displayed
 
@@ -265,11 +272,14 @@ class PyGameGUI:
             state: The game state returned by the environment.
         """
         for p_idx, player in enumerate(state["players"].values()):
-            pos = player.pos * self.grid_size
+            # pos = player.pos * self.grid_size
+            pos = np.array(state_dict["players"][p_idx]["pos"]) * self.grid_size
+
+            facing = np.array(state_dict["players"][p_idx]["facing"])
 
             if USE_PLAYER_COOK_SPRITES:
                 img_path = self.visualization_config["Cook"]["parts"][0]["path"]
-                rel_x, rel_y = player.facing_direction
+                rel_x, rel_y = pos = facing
                 angle = -np.rad2deg(math.atan2(rel_y, rel_x)) + 90
                 size = (
                     self.visualization_config["Cook"]["parts"][0]["size"]
@@ -286,7 +296,7 @@ class PyGameGUI:
                 pygame.draw.circle(self.game_screen, BLUE, pos, size, width=1)
                 pygame.draw.circle(self.game_screen, colors[color1], pos, size // 2)
 
-                facing = player.facing_direction
+                facing = facing
                 pygame.draw.polygon(
                     self.game_screen,
                     BLUE,
@@ -475,9 +485,11 @@ class PyGameGUI:
         for counter in state["counters"]:
             self.draw_counter(counter)
             if SHOW_COUNTER_CENTERS:
-                pygame.draw.circle(self.game_screen, colors["green1"], counter.pos, 3)
+                pygame.draw.circle(
+                    self.game_screen, colors["green1"], counter.pos * self.grid_size, 3
+                )
 
-    def draw(self, state):
+    def draw(self, state, state_dict):
         """Main visualization function.
 
         Args:
@@ -487,7 +499,7 @@ class PyGameGUI:
         self.draw_background()
 
         self.draw_counters(state)
-        self.draw_players(state)
+        self.draw_players(state, state_dict)
         self.manager.draw_ui(self.game_screen)
 
     def init_ui_elements(self):
@@ -654,6 +666,8 @@ class PyGameGUI:
         self.init_ui_elements()
         log.debug("Pressed start button")
 
+        # self.api.set_sim(self.simulator)
+
     def back_button_press(self):
         self.simulator.stop()
         self.menu_state = MenuStates.Start
@@ -669,6 +683,35 @@ class PyGameGUI:
         self.menu_state = MenuStates.End
         log.debug("Pressed finished button")
 
+    def send_action(self, action: Action):
+        """Sends an action to the game environment.
+
+        Args:
+            action: The action to be sent. Contains the player, action type and move direction if action is a movement.
+        """
+        if isinstance(action.action, np.ndarray):
+            value = [float(action.action[0]), float(action.action[1])]
+        else:
+            value = action.action
+        message_dict = {
+            "player_name": action.player,
+            "act_type": action.act_type,
+            "value": value,
+        }
+        _ = self.websocket_communicate(message_dict)
+
+    def websocket_communicate(self, message_dict: dict | str):
+        with connect(self.websocket_url) as websocket:
+            print(message_dict)
+            websocket.send(json.dumps(message_dict))
+            answer = websocket.recv()
+            print(answer)
+        return json.loads(answer)
+
+    def request_state(self):
+        state_dict = self.websocket_communicate("get_state")
+        return state_dict
+
     def start_pygame(self):
         """Starts pygame and the gui loop. Each frame the game state is visualized and keyboard inputs are read."""
         log.debug(f"Starting pygame gui at {self.FPS} fps")
@@ -727,8 +770,9 @@ class PyGameGUI:
 
                         self.handle_keys()
 
+                        state_dict = self.request_state()
                         state = self.simulator.get_state()
-                        self.draw(state)
+                        self.draw(state, state_dict)
 
                         game_screen_rect = self.game_screen.get_rect()
                         game_screen_rect.center = [
@@ -753,3 +797,20 @@ class PyGameGUI:
         self.simulator.stop()
         pygame.quit()
         sys.exit()
+
+
+if __name__ == "__main__":
+    # TODO maybe read the player names and keyboard keys from config file?
+    keys1 = [
+        pygame.K_LEFT,
+        pygame.K_RIGHT,
+        pygame.K_UP,
+        pygame.K_DOWN,
+        pygame.K_SPACE,
+        pygame.K_i,
+    ]
+    keys2 = [pygame.K_a, pygame.K_d, pygame.K_w, pygame.K_s, pygame.K_f, pygame.K_e]
+
+    number_players = 2
+    gui = PyGameGUI([f"p{i}" for i in range(number_players)], [keys1, keys2])
+    gui.start_pygame()
diff --git a/overcooked_simulator/main.py b/overcooked_simulator/main.py
index 86caba35763a863735582b4f0e0fb32c3402bae7..81a5d8f029c82707cb5720a6a8d08c8b16309d8c 100644
--- a/overcooked_simulator/main.py
+++ b/overcooked_simulator/main.py
@@ -51,10 +51,14 @@ def main():
     ]
     keys2 = [pygame.K_a, pygame.K_d, pygame.K_w, pygame.K_s, pygame.K_f, pygame.K_e]
 
-    gui = PyGameGUI(simulator, [f"p{i}" for i in range(number_player)], [keys1, keys2])
+    gui = PyGameGUI(
+        simulator, None, [f"p{i}" for i in range(number_player)], [keys1, keys2]
+    )
     gui.start_pygame()
     sys.exit()
 
+    print("HERE?")
+
 
 if __name__ == "__main__":
     setup_logging()
diff --git a/overcooked_simulator/overcooked_environment.py b/overcooked_simulator/overcooked_environment.py
index 8f5adf962fed07d207ac034821c4978edb3a3d47..c3bf550256bc7f40abbd14bf6362a05c3865cc33 100644
--- a/overcooked_simulator/overcooked_environment.py
+++ b/overcooked_simulator/overcooked_environment.py
@@ -1,5 +1,6 @@
 from __future__ import annotations
 
+import json
 import logging
 import random
 from datetime import timedelta
@@ -177,6 +178,7 @@ class Environment:
             for character in line:
                 character = character.capitalize()
                 pos = np.array([current_x, current_y])
+                print(pos)
                 counter_class = self.SYMBOL_TO_CHARACTER_MAP[character]
                 if not isinstance(counter_class, str):
                     counter = counter_class(pos)
@@ -450,13 +452,31 @@ class Environment:
         """
         return {"players": self.players, "counters": self.counters, "score": self.score}
 
-    def get_state_json(self):
+    def get_state_simple_json(self):
         """Get the current state of the game environment as a json-like nested dictionary.
 
         Returns: Json-like string of the current game state.
 
         """
-        pass
+        players = [
+            {
+                "pos": [float(p.pos[0]), float(p.pos[1])],
+                "facing": [float(p.facing_direction[0]), float(p.facing_direction[1])],
+            }
+            for p in self.players.values()
+        ]
+
+        counters = [
+            {"type": str(c.__class__), "pos": [float(c.pos[0]), float(c.pos[1])]}
+            for c in self.counters
+        ]
+
+        gamestate_dict = {
+            "players": players,
+            "counters": counters,
+        }
+        answer = json.dumps(gamestate_dict)
+        return answer
 
     def init_counters(self):
         plate_dispenser = self.get_counter_of_type(PlateDispenser)
diff --git a/overcooked_simulator/simulation_runner.py b/overcooked_simulator/simulation_runner.py
index 8ad41e28ae7bb2834297cadeaa2d06f915e1c87a..f004ecdd68d52be1e5d596c0bef5434948aa610b 100644
--- a/overcooked_simulator/simulation_runner.py
+++ b/overcooked_simulator/simulation_runner.py
@@ -66,14 +66,14 @@ class Simulator(Thread):
 
         return self.env.get_state()
 
-    def get_state_json(self):
+    def get_state_simple_json(self):
         """Get the current game state in json-like dict.
 
         Returns:
             The gamest ate encoded in a json style nested dict.
         """
 
-        return self.env.get_state_json()
+        return self.env.get_state_simple_json()
 
     def register_player(self, player_name: str, pos=None):
         """Adds a player to the environment.
diff --git a/overcooked_simulator/websocket_connector.py b/overcooked_simulator/websocket_connector.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/setup.py b/setup.py
index b3ceeba705d5d329be64f2dc239e4de19dbc5056..f03249639eb04f12e8b9bbd12d70ac9d792a9e19 100644
--- a/setup.py
+++ b/setup.py
@@ -10,7 +10,15 @@ with open("README.md") as readme_file:
 with open("CHANGELOG.md") as history_file:
     history = history_file.read()
 
-requirements = ["numpy", "pygame", "scipy", "pytest>=3", "pyyaml", "pygame-gui"]
+requirements = [
+    "numpy",
+    "pygame",
+    "scipy",
+    "pytest>=3",
+    "pyyaml",
+    "pygame-gui",
+    "websockets",
+]
 
 test_requirements = [
     "pytest>=3",