diff --git a/android/build.gradle b/android/build.gradle
index 7194380062b187012ed5c9c35dca81f7dfa008c5..0d921dcf3cc2e7a44c9a58180b0c42decc13e124 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -15,7 +15,9 @@ android {
 
     }
     packagingOptions {
-        exclude 'META-INF/robovm/ios/robovm.xml'
+        resources {
+            excludes += ['META-INF/robovm/ios/robovm.xml']
+        }
     }
     defaultConfig {
         applicationId "com.wordbattle.game"
diff --git a/core/src/com/wordbattle/game/controller/JoinGameController.java b/core/src/com/wordbattle/game/controller/JoinGameController.java
index 764568ce64f9fb557302bda8f86f09ec48266181..8551b367b3b57fac341efdd8b1b8b7ef3baa5a4e 100644
--- a/core/src/com/wordbattle/game/controller/JoinGameController.java
+++ b/core/src/com/wordbattle/game/controller/JoinGameController.java
@@ -1,5 +1,83 @@
 package com.wordbattle.game.controller;
 
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.graphics.g2d.SpriteBatch;
+import com.badlogic.gdx.math.Rectangle;
+import com.badlogic.gdx.math.Vector3;
+import com.wordbattle.game.states.CreateGameState;
+import com.wordbattle.game.states.JoinGameState;
+import com.wordbattle.game.states.MainMenuState;
+import com.wordbattle.game.view.JoinGameView;
+import com.wordbattle.game.view.MainMenuView;
+
 public class JoinGameController {
 
+    private JoinGameState state;
+    private JoinGameView joinGameView;
+
+    private String pin; //just for testing since we dont have database yet
+
+
+    public JoinGameController(JoinGameState state) {
+        this.state = state;
+        this.joinGameView = new JoinGameView(state.getCam());
+        pin="1234";//testing
+    }
+
+    public void handleInput() {
+
+        if (Gdx.input.justTouched()) {
+            Vector3 touchPos = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
+            state.getCam().unproject(touchPos);
+            Rectangle joinGameButtonBounds = joinGameView.getJoinGameButtonBounds();
+            if (joinGameButtonBounds.contains(touchPos.x, touchPos.y)) {
+                System.out.println("Join Game Button Pressed");
+                if (confirmNickname() && confirmPin()){
+                    state.getStateManager().setState(new CreateGameState(state.getStateManager()));//needs to be changed to lobbyState when it is ready
+
+
+                }
+
+
+            }
+        }
+    }
+
+
+
+
+
+    public void update(float dt) {
+        handleInput();
+    }
+
+
+    public void render(SpriteBatch sb){
+        joinGameView.render(sb);
+    }
+
+    public boolean confirmPin(){
+        if (joinGameView.getPin().equals(pin)){
+            return true;
+        }
+        else{
+            joinGameView.setPinMessage("Wrong PIN");
+            return false;
+        }
+    }
+
+    public boolean confirmNickname(){
+        String Nickname = joinGameView.getNickname();
+        if (Nickname.trim().isEmpty()) { //does not allow empty string or only whitespace
+            joinGameView.setNicknameMessage("Nickname must be filled out");
+            return false;
+        }
+        else{
+            return true;
+        }
+    }
+
+    public void dispose() {
+        joinGameView.dispose();
+    }
 }
diff --git a/core/src/com/wordbattle/game/controller/MainMenuController.java b/core/src/com/wordbattle/game/controller/MainMenuController.java
index 509c62418ad66f9bcc7c56aa1d161f82874020bd..dc2a54b5956c5b1f22810cc3a3a4001df05ab9bc 100644
--- a/core/src/com/wordbattle/game/controller/MainMenuController.java
+++ b/core/src/com/wordbattle/game/controller/MainMenuController.java
@@ -7,6 +7,7 @@ import com.badlogic.gdx.math.Rectangle;
 import com.badlogic.gdx.math.Vector3;
 import com.badlogic.gdx.utils.Null;
 import com.wordbattle.game.states.CreateGameState;
+import com.wordbattle.game.states.JoinGameState;
 import com.wordbattle.game.states.MainMenuState;
 import com.wordbattle.game.states.StateManager;
 import com.wordbattle.game.view.MainMenuView;
@@ -43,7 +44,7 @@ public class MainMenuController {
             // Button checks
             if (joinGameButtonBounds.contains(touchPos.x, touchPos.y)) {
                 System.out.println("Join Game Button Pressed");
-                state.getStateManager().setState(new CreateGameState(state.getStateManager()));
+                state.getStateManager().setState(new JoinGameState(state.getStateManager()));
 
             }
             if (newGameButtonBounds.contains(touchPos.x, touchPos.y)) {
diff --git a/core/src/com/wordbattle/game/states/JoinGameState.java b/core/src/com/wordbattle/game/states/JoinGameState.java
index 3853b4a6dacb0ee014874d26e34a998fc9d71f29..197b5fcab6d28cd70ed2970e0c97a4cbdab04f77 100644
--- a/core/src/com/wordbattle/game/states/JoinGameState.java
+++ b/core/src/com/wordbattle/game/states/JoinGameState.java
@@ -1,5 +1,55 @@
 package com.wordbattle.game.states;
 
-public class JoinGameState {
+import com.badlogic.gdx.graphics.g2d.SpriteBatch;
+import com.wordbattle.game.WordBattle;
+import com.wordbattle.game.controller.JoinGameController;
+import com.wordbattle.game.controller.MainMenuController;
 
+public class JoinGameState extends BaseState {
+
+    private JoinGameController controller;
+
+    public JoinGameState(StateManager gsm) {
+        super(gsm);
+        this.controller = new JoinGameController(this); // 'this' provides context
+        cam.setToOrtho(false, WordBattle.WIDTH, WordBattle.HEIGHT);
+
+    }
+
+
+    @Override
+    public void handleInput() {
+
+    }
+
+    @Override
+    public void update(float dt) {
+        controller.update(dt);
+        cam.update();
+
+    }
+
+    @Override
+    public void render(SpriteBatch sb) {
+        controller.render(sb);
+    }
+
+    @Override
+    public void enter() {
+
+    }
+
+    public StateManager getStateManager() {
+        return gsm;
+    }
+
+    @Override
+    public void exit() {
+
+    }
+
+    @Override
+    public void dispose() {
+
+    }
 }
diff --git a/core/src/com/wordbattle/game/view/JoinGameView.java b/core/src/com/wordbattle/game/view/JoinGameView.java
index e3c6580614cf3d640e917206f74b1ab9ed9cc411..b194b2b3793a913d07350dd977e65ef2490b7d59 100644
--- a/core/src/com/wordbattle/game/view/JoinGameView.java
+++ b/core/src/com/wordbattle/game/view/JoinGameView.java
@@ -1,10 +1,16 @@
 package com.wordbattle.game.view;
 
 import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.graphics.Color;
 import com.badlogic.gdx.graphics.GL20;
 import com.badlogic.gdx.graphics.OrthographicCamera;
 import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.BitmapFont;
+import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
 import com.badlogic.gdx.math.Rectangle;
+import com.badlogic.gdx.scenes.scene2d.Stage;
+import com.badlogic.gdx.scenes.scene2d.ui.TextField;
+import com.badlogic.gdx.utils.viewport.ScreenViewport;
 import com.wordbattle.game.WordBattle;
 import com.badlogic.gdx.graphics.g2d.SpriteBatch;
 
@@ -12,42 +18,163 @@ public class JoinGameView {
 
     private Texture backgroundTexture;
     private Texture joinGameButton;
+
+    private Texture nicknameTexture;
+
+    private Texture pinTexture;
     private Rectangle joinGameButtonBounds;
+
+    private Rectangle pinButtonBounds;
+
+    private Rectangle nicknameBounds;
     private OrthographicCamera cam;
+    private Stage stage;
+
+    private BitmapFont font;
+
+    private TextField nicknameField;
+
+    private TextField pinField;
+
+    private String pinMessage;
+
+    private String nicknameMessage;
+
+
 
     public JoinGameView(OrthographicCamera cam){
         this.cam = cam;
-        this.backgroundTexture = new Texture("bg2.png");
-        this.joinGameButton = new Texture("join_game.png");
+        stage = new Stage(new ScreenViewport(cam));
+        Gdx.input.setInputProcessor(stage);
+
+
+
+        backgroundTexture = new Texture("bg2.png");
+        nicknameTexture = new Texture("pink_long-01.png");
+        pinTexture = new Texture("pink_long-01.png");
+        joinGameButton = new Texture("join_game.png");
+
+
 
         joinGameButtonBounds = new Rectangle(
                 (WordBattle.WIDTH - joinGameButton.getWidth()) / 2,
-                (WordBattle.HEIGHT / 2 - joinGameButton.getHeight() / 2) - 50,
+                (WordBattle.HEIGHT / 2 - joinGameButton.getHeight() / 2) -160,
                 joinGameButton.getWidth(),
-                joinGameButton.getHeight()
+                joinGameButton.getHeight()-40 //rectangle is larger than button for some reason
+        );
+
+        pinButtonBounds= new Rectangle(
+                (WordBattle.WIDTH - pinTexture.getWidth()) / 2,
+                (WordBattle.HEIGHT / 2 - pinTexture.getHeight() / 2) +0,
+                pinTexture.getWidth(),
+                pinTexture.getHeight()-40
         );
 
+        nicknameBounds = new Rectangle(
+                (WordBattle.WIDTH - nicknameTexture.getWidth()) / 2,
+                (WordBattle.HEIGHT / 2 - nicknameTexture.getHeight() / 2)+160,
+                nicknameTexture.getWidth(),
+                nicknameTexture.getHeight()-40
+        );
+
+
+
+        // Load and set up font
+        FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("Knewave-Regular.ttf"));
+        FreeTypeFontGenerator.FreeTypeFontParameter parameter = new FreeTypeFontGenerator.FreeTypeFontParameter();
+        parameter.size = 36;
+        font = generator.generateFont(parameter);
+        generator.dispose();
+
+        TextField.TextFieldStyle textFieldStyle = new TextField.TextFieldStyle();
+        textFieldStyle.font = font;
+        textFieldStyle.fontColor = Color.WHITE;
+
+        nicknameField = new TextField("", textFieldStyle);
+        nicknameField.setMessageText("Enter Nickname");
+        nicknameField.setAlignment(1); // 1 = Center
+        nicknameField.setMaxLength(15); // Max chars set to 15
+
+        pinField = new TextField("", textFieldStyle);
+        pinField.setMessageText("Enter Pin");
+        pinField.setAlignment(1); // 1 = Center
+        pinField.setMaxLength(4); // Max chars set to 4
+
+
+
+        // Set the position and size of the nicknameField
+        nicknameField.setPosition(nicknameBounds.x, nicknameBounds.y + 5);
+        nicknameField.setSize(nicknameBounds.width, nicknameBounds.height);
+        stage.addActor(nicknameField);
+
+        // Set the position and size of the nicknameField
+        pinField.setPosition(pinButtonBounds.x, pinButtonBounds.y + 5);
+        pinField.setSize(pinButtonBounds.width, pinButtonBounds.height);
+        stage.addActor(pinField);
+
+        nicknameMessage="";
+        pinMessage="";
+
+
+
     }
 
     public void render(SpriteBatch spriteBatch){
         Gdx.gl.glClearColor(0, 0, 0, 1);
         Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
         cam.update();
-        spriteBatch.setProjectionMatrix(cam.combined);
         spriteBatch.begin();
+
+        spriteBatch.setProjectionMatrix(cam.combined);
         spriteBatch.draw(backgroundTexture, 0, 0, WordBattle.WIDTH, WordBattle.HEIGHT);
+
         spriteBatch.draw(joinGameButton, joinGameButtonBounds.x, joinGameButtonBounds.y);
+        spriteBatch.draw(pinTexture,pinButtonBounds.x, pinButtonBounds.y);
+        spriteBatch.draw(nicknameTexture, nicknameBounds.x, nicknameBounds.y);
+
+        font.draw(spriteBatch,pinMessage,pinButtonBounds.x + pinButtonBounds.width/4, pinButtonBounds.y+32);
+        font.draw(spriteBatch,nicknameMessage,nicknameBounds.x-12,nicknameBounds.y+32);
+
+
+
+        //rectangle y coordinate is from top instead of bottom. -150 is to adjust for offset.
         spriteBatch.end();
+        stage.act(Gdx.graphics.getDeltaTime()); // Update logic
+        stage.draw(); // Draw the UI for the inputfield, which is needed separate
     }
 
     public Rectangle getJoinGameButtonBounds() {
         return joinGameButtonBounds;
     }
 
+    public String getPin(){
+        return pinField.getText();
+    }
+
+    public String getNickname(){
+        return nicknameField.getText();
+    }
+
+    public void setBackgroundTexture(Texture backgroundTexture) {
+        this.backgroundTexture = backgroundTexture;
+    }
+
+    public void setPinMessage(String pinMessage) {
+        this.pinMessage = pinMessage;
+    }
+
+    public void setNicknameMessage(String nicknameMessage) {
+        this.nicknameMessage = nicknameMessage;
+    }
+
     public void dispose() {
         backgroundTexture.dispose();
         joinGameButton.dispose();
     }
 
 
+
+
+
+
 }