From 42e354b1bd588a142838e1b2c8b00a620c254a34 Mon Sep 17 00:00:00 2001 From: Midgar Date: Fri, 30 May 2014 15:01:29 -0400 Subject: [PATCH] Enabled Multiplayer Feature This enables the multiplayer feature. When the game is started, the user is asked if he/she wants to play single player or multiplayer. For multiplayer: Player One uses arrow keys, Player Two uses WASD. The issue is that when one player eats food and then the other player eats food, the food disappears. (It is still there but it turns white) Also, changing the colors of the two players may be a good idea. --- src/KeyboardListener.java | 60 +++++++--- src/Main.java | 4 +- src/ThreadsController.java | 2 +- src/ThreadsControllerPlayerTwo.java | 169 ++++++++++++++++++++++++++++ src/Window.java | 48 +++++++- 5 files changed, 258 insertions(+), 25 deletions(-) create mode 100644 src/ThreadsControllerPlayerTwo.java diff --git a/src/KeyboardListener.java b/src/KeyboardListener.java index 0271729..d003dc5 100644 --- a/src/KeyboardListener.java +++ b/src/KeyboardListener.java @@ -5,25 +5,51 @@ public class KeyboardListener extends KeyAdapter{ public void keyPressed(KeyEvent e){ switch(e.getKeyCode()){ - case 39: // -> Right - //if it's not the opposite direction - if(ThreadsController.directionSnake!=2) - ThreadsController.directionSnake=1; - break; - case 38: // -> Top - if(ThreadsController.directionSnake!=4) - ThreadsController.directionSnake=3; - break; + + //Player One Controls + case 39: // -> Right + //if it's not the opposite direction + if(ThreadsController.directionSnake!=2) + ThreadsController.directionSnake=1; + break; + case 38: // -> Top + if(ThreadsController.directionSnake!=4) + ThreadsController.directionSnake=3; + break; - case 37: // -> Left - if(ThreadsController.directionSnake!=1) - ThreadsController.directionSnake=2; - break; + case 37: // -> Left + if(ThreadsController.directionSnake!=1) + ThreadsController.directionSnake=2; + break; - case 40: // -> Bottom - if(ThreadsController.directionSnake!=3) - ThreadsController.directionSnake=4; - break; + case 40: // -> Bottom + if(ThreadsController.directionSnake!=3) + ThreadsController.directionSnake=4; + break; + + //Player Two Controls + + case KeyEvent.VK_D: // -> Player 2 Right + if(ThreadsControllerPlayerTwo.directionSnake != 2) + ThreadsControllerPlayerTwo.directionSnake = 1; + break; + + + case KeyEvent.VK_W: // -> Player 2 Top + if(ThreadsControllerPlayerTwo.directionSnake != 4) + ThreadsControllerPlayerTwo.directionSnake = 3; + break; + + case KeyEvent.VK_A: // -> Player 2 Left + if(ThreadsControllerPlayerTwo.directionSnake != 1) + ThreadsControllerPlayerTwo.directionSnake = 2; + break; + + + case KeyEvent.VK_S: // -> Player 2 Bottom + if(ThreadsControllerPlayerTwo.directionSnake != 3) + ThreadsControllerPlayerTwo.directionSnake = 4; + break; default: break; } diff --git a/src/Main.java b/src/Main.java index e2da510..8a6ed60 100644 --- a/src/Main.java +++ b/src/Main.java @@ -4,8 +4,8 @@ public class Main { public static void main(String[] args) { - //Creating the window with all its awesome snaky features - Window f1= new Window(); + //Creating the window with all its awesome snakey features + Window f1 = new Window(); //Setting up the window settings f1.setTitle("Snake"); diff --git a/src/ThreadsController.java b/src/ThreadsController.java index 3df2d3d..82ac83d 100644 --- a/src/ThreadsController.java +++ b/src/ThreadsController.java @@ -71,7 +71,7 @@ private void checkCollision() { //Stops The Game private void stopTheGame(){ - System.out.println("COLISION! \n"); + System.out.println("COLLISION! \n"); while(true){ pauser(); } diff --git a/src/ThreadsControllerPlayerTwo.java b/src/ThreadsControllerPlayerTwo.java new file mode 100644 index 0000000..20df098 --- /dev/null +++ b/src/ThreadsControllerPlayerTwo.java @@ -0,0 +1,169 @@ +import java.util.ArrayList; + + +//Controls all the game logic .. most important class in this project. +public class ThreadsControllerPlayerTwo extends Thread { + ArrayList> Squares= new ArrayList>(); + Tuple headSnakePos; + int sizeSnake=3; + long speed = 50; + public static int directionSnake ; + + ArrayList positions = new ArrayList(); + Tuple foodPosition; + + //Constructor of ControlleurThread + ThreadsControllerPlayerTwo(Tuple positionDepart){ + //Get all the threads + Squares=Window.Grid; + + headSnakePos=new Tuple(positionDepart.x,positionDepart.y); + directionSnake = 1; + + //!!! Pointer !!!! + Tuple headPos = new Tuple(headSnakePos.getX(),headSnakePos.getY()); + positions.add(headPos); + + foodPosition= new Tuple(Window.height-1,Window.width-1); + spawnFood(foodPosition); + + } + + //Important part : + public void run() { + while(true){ + moveInterne(directionSnake); + checkCollision(); + moveExterne(); + deleteTail(); + pauser(); + } + } + + //delay between each move of the snake + private void pauser(){ + try { + sleep(speed); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + //Checking if the snake bites itself or is eating + private void checkCollision() { + Tuple posCritique = positions.get(positions.size()-1); + for(int i = 0;i<=positions.size()-2;i++){ + boolean biteItself = posCritique.getX()==positions.get(i).getX() && posCritique.getY()==positions.get(i).getY(); + if(biteItself){ + stopTheGame(); + } + } + + boolean eatingFood = posCritique.getX()==foodPosition.y && posCritique.getY()==foodPosition.x; + if(eatingFood){ + System.out.println("Yummy!"); + sizeSnake=sizeSnake+1; + foodPosition = getValAleaNotInSnake(); + + spawnFood(foodPosition); + } + } + + //Stops The Game + private void stopTheGame(){ + System.out.println("COLLISION! \n"); + while(true){ + pauser(); + } + } + + //Put food in a position and displays it + private void spawnFood(Tuple foodPositionIn){ + Squares.get(foodPositionIn.x).get(foodPositionIn.y).lightMeUp(1); + } + + //return a position not occupied by the snake + private Tuple getValAleaNotInSnake(){ + Tuple p ; + int ranX= 0 + (int)(Math.random()*19); + int ranY= 0 + (int)(Math.random()*19); + p=new Tuple(ranX,ranY); + for(int i = 0;i<=positions.size()-1;i++){ + if(p.getY()==positions.get(i).getX() && p.getX()==positions.get(i).getY()){ + ranX= 0 + (int)(Math.random()*19); + ranY= 0 + (int)(Math.random()*19); + p=new Tuple(ranX,ranY); + i=0; + } + } + return p; + } + + //Moves the head of the snake and refreshes the positions in the arraylist + //1:right 2:left 3:top 4:bottom 0:nothing + private void moveInterne(int dir){ + switch(dir){ + case 4: + headSnakePos.ChangeData(headSnakePos.x,(headSnakePos.y+1)%20); + positions.add(new Tuple(headSnakePos.x,headSnakePos.y)); + break; + case 3: + if(headSnakePos.y-1<0){ + headSnakePos.ChangeData(headSnakePos.x,19); + } + else{ + headSnakePos.ChangeData(headSnakePos.x,Math.abs(headSnakePos.y-1)%20); + } + positions.add(new Tuple(headSnakePos.x,headSnakePos.y)); + break; + case 2: + if(headSnakePos.x-1<0){ + headSnakePos.ChangeData(19,headSnakePos.y); + } + else{ + headSnakePos.ChangeData(Math.abs(headSnakePos.x-1)%20,headSnakePos.y); + } + positions.add(new Tuple(headSnakePos.x,headSnakePos.y)); + + break; + case 1: + headSnakePos.ChangeData(Math.abs(headSnakePos.x+1)%20,headSnakePos.y); + positions.add(new Tuple(headSnakePos.x,headSnakePos.y)); + break; + } + } + + //Refresh the squares that needs to be + private void moveExterne(){ + for(Tuple t : positions){ + int y = t.getX(); + int x = t.getY(); + Squares.get(x).get(y).lightMeUp(0); + + } + } + + //Refreshes the tail of the snake, by removing the superfluous data in positions arraylist + //and refreshing the display of the things that is removed + private void deleteTail(){ + int cmpt = sizeSnake; + for(int i = positions.size()-1;i>=0;i--){ + if(cmpt==0){ + Tuple t = positions.get(i); + Squares.get(t.y).get(t.x).lightMeUp(2); + } + else{ + cmpt--; + } + } + cmpt = sizeSnake; + for(int i = positions.size()-1;i>=0;i--){ + if(cmpt==0){ + positions.remove(i); + } + else{ + cmpt--; + } + } + } +} diff --git a/src/Window.java b/src/Window.java index 518fa9e..b476858 100644 --- a/src/Window.java +++ b/src/Window.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import javax.swing.JFrame; +import javax.swing.JOptionPane; class Window extends JFrame{ @@ -37,6 +38,33 @@ public Window(){ } } + + + /* + * The below code makes a JOptionPane ask the user if he/she wants to play with + * one player or two player, and sets up the game accordingly. + */ + + String[] options = {"One player" , "Two Players"}; + int playersSelected = JOptionPane.showOptionDialog(null, "Would you like to play single player or multiplayer?", + "A Silly Question", + JOptionPane.YES_NO_CANCEL_OPTION, + JOptionPane.QUESTION_MESSAGE, + null, + options, + options[1]); + + //If user selects "Two Player" + if(playersSelected == 1){ + //Set up Player Two Controller + Tuple position2 = new Tuple(13,13); + ThreadsControllerPlayerTwo c2 = new ThreadsControllerPlayerTwo(position2); + c2.start(); + } + + //If User selects "One Player" or exits out of JOptionPane, game starts with only one player + + // initial position of the snake Tuple position = new Tuple(10,10); // passing this value to the controller @@ -46,12 +74,22 @@ public Window(){ // Links the window to the keyboardlistenner. this.addKeyListener((KeyListener) new KeyboardListener()); - - //To do : handle multiplayers .. The above works, test it and see what happens - //Tuple position2 = new Tuple(13,13); - //ControlleurThreads c2 = new ControlleurThreads(position2); - //c2.start(); + + /*TODO: + * Problems With Multiplayer: + * -When one player eats food, and then the other player eats food, the food completely disappears. + * -The two players can freely go through each other (no collision happens between two players). + * This does not necessarily need to be fixed, but it would be interesting to allow + * players to make other players collide in order to win (like original snake of light cycle games). + * This feature would also give more motivation to get the food (the more food you get, + * the longer you are, the more of a chance you have of trapping opponent). + * + * If this feature is not implemented, an alternative would be to show a "scoreboard" on the + * right of the screen, and set a time limit to see which player can get most food + * (without colliding into itself). + */ + } }