Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Snake game issue !!! java - swing - Jframe

I am a high school student who is currently working on a snake game (eating the food version) on java swing (JFrame); in NetBeans IDE 8.0.2. So far I was able to move the snake and randomly generate the food; the snake is eating the food though and is stopping when colliding to the borders/boundaries around the board. But to be honest, I really don't know how to grow the snake from onwards. People suggested me to use an ArrayList so that I can add pieces of the same block(Jpanel). To say the truth, I am not too familiar to ArrayList. So would you guys help me around on how do I make that ArrayList and use that to grow the snake. Also, when the snake is moving forward(at any direction), how do I stop the snake from moving backwards(the opposite of the forward button), shouldn't it be only able to move left, right and forward. I hope you guys get what I mean. Finally, since my food gets randomly generated, it overlaps the snake sometimes and how do I stop the food from getting overlapped on the snakes body.

This link will show you what my game looks like (the red block is my snake): https://i.sstatic.net/xko2n.jpg

In the above link, the red block is my snake, the yellow blocks are my food and the extra piece there is the block that I wanna add to the snake and grow it. The Blue lines there are my borders/boundaries.

Here is my code so far:

package culminating;

import java.util.Random;
import javax.swing.JLabel;
import javax.swing.Timer;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Rectangle;
import javax.swing.JOptionPane;

public class Visual extends javax.swing.JFrame {
 JLabel[] food = new JLabel[10];
 JLabel[] border = new JLabel[4];
 Timer s_timer;
 boolean[] keys = new boolean[525];
 boolean up = false, down = false;
 int count;
 static int X,Y, lcount;
  public Visual() {
    initComponents();
}


@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

    jPanel1 = new javax.swing.JPanel();
    snake = new javax.swing.JLabel();
    jLabel8 = new javax.swing.JLabel();
    jLabel2 = new javax.swing.JLabel();
    jLabel10 = new javax.swing.JLabel();
    jLabel7 = new javax.swing.JLabel();
    jLabel4 = new javax.swing.JLabel();
    jLabel5 = new javax.swing.JLabel();
    jLabel9 = new javax.swing.JLabel();
    jLabel3 = new javax.swing.JLabel();
    jLabel6 = new javax.swing.JLabel();
    jLabel1 = new javax.swing.JLabel();
    jLabel11 = new javax.swing.JLabel();
    jLabel12 = new javax.swing.JLabel();
    jLabel13 = new javax.swing.JLabel();
    jLabel14 = new javax.swing.JLabel();
    jLabel15 = new javax.swing.JLabel();
    jLabel18 = new javax.swing.JLabel();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    addComponentListener(new java.awt.event.ComponentAdapter() {
        public void componentShown(java.awt.event.ComponentEvent evt) {
            formComponentShown(evt);
        }
    });
    addKeyListener(new java.awt.event.KeyAdapter() {
        public void keyPressed(java.awt.event.KeyEvent evt) {
            formKeyPressed(evt);
        }
    });

    jPanel1.setBackground(new java.awt.Color(0, 0, 0));
    jPanel1.addKeyListener(new java.awt.event.KeyAdapter() {
        public void keyPressed(java.awt.event.KeyEvent evt) {
            jPanel1KeyPressed(evt);
        }
    });
    jPanel1.setLayout(null);

    snake.setBackground(new java.awt.Color(255, 51, 0));
    snake.setOpaque(true);
    jPanel1.add(snake);
    snake.setBounds(230, 230, 20, 20);

    jLabel8.setBackground(new java.awt.Color(255, 255, 0));
    jLabel8.setOpaque(true);
    jPanel1.add(jLabel8);
    jLabel8.setBounds(100, 184, 10, 10);

    jLabel2.setBackground(new java.awt.Color(255, 255, 0));
    jLabel2.setOpaque(true);
    jPanel1.add(jLabel2);
    jLabel2.setBounds(225, 137, 10, 10);

    jLabel10.setBackground(new java.awt.Color(255, 255, 0));
    jLabel10.setOpaque(true);
    jPanel1.add(jLabel10);
    jLabel10.setBounds(419, 305, 10, 10);

    jLabel7.setBackground(new java.awt.Color(255, 255, 0));
    jLabel7.setOpaque(true);
    jPanel1.add(jLabel7);
    jLabel7.setBounds(301, 137, 10, 10);

    jLabel4.setBackground(new java.awt.Color(255, 255, 0));
    jLabel4.setOpaque(true);
    jPanel1.add(jLabel4);
    jLabel4.setBounds(158, 325, 10, 10);

    jLabel5.setBackground(new java.awt.Color(255, 255, 0));
    jLabel5.setForeground(new java.awt.Color(51, 0, 51));
    jLabel5.setOpaque(true);
    jPanel1.add(jLabel5);
    jLabel5.setBounds(412, 381, 10, 10);

    jLabel9.setBackground(new java.awt.Color(255, 255, 0));
    jLabel9.setOpaque(true);
    jPanel1.add(jLabel9);
    jLabel9.setBounds(503, 325, 10, 10);

    jLabel3.setBackground(new java.awt.Color(255, 255, 0));
    jLabel3.setOpaque(true);
    jPanel1.add(jLabel3);
    jLabel3.setBounds(410, 220, 10, 10);

    jLabel6.setBackground(new java.awt.Color(255, 255, 0));
    jLabel6.setOpaque(true);
    jPanel1.add(jLabel6);
    jLabel6.setBounds(432, 99, 10, 10);

    jLabel1.setBackground(new java.awt.Color(255, 255, 0));
    jLabel1.setOpaque(true);
    jPanel1.add(jLabel1);
    jLabel1.setBounds(510, 400, 10, 10);

    jLabel11.setBackground(new java.awt.Color(51, 51, 255));
    jLabel11.setOpaque(true);
    jPanel1.add(jLabel11);
    jLabel11.setBounds(0, 0, 20, 460);

    jLabel12.setBackground(new java.awt.Color(51, 51, 255));
    jLabel12.setOpaque(true);
    jPanel1.add(jLabel12);
    jLabel12.setBounds(0, 450, 560, 0);

    jLabel13.setBackground(new java.awt.Color(51, 51, 255));
    jLabel13.setOpaque(true);
    jPanel1.add(jLabel13);
    jLabel13.setBounds(0, 0, 560, 20);

    jLabel14.setBackground(new java.awt.Color(51, 51, 255));
    jLabel14.setOpaque(true);
    jPanel1.add(jLabel14);
    jLabel14.setBounds(540, 0, 20, 460);

    jLabel15.setBackground(new java.awt.Color(51, 51, 255));
    jLabel15.setOpaque(true);
    jPanel1.add(jLabel15);
    jLabel15.setBounds(0, 450, 560, 14);

    jLabel18.setIcon(new   javax.swing.ImageIcon(getClass().getResource("/culminating/snake body.jpg"))); // NOI18N
    jLabel18.setText("jLabel17");
    jPanel1.add(jLabel18);
    jLabel18.setBounds(150, 350, 20, 20);

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 556, Short.MAX_VALUE)
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 463, Short.MAX_VALUE)
    );

    pack();
}// </editor-fold>                        

private void formComponentShown(java.awt.event.ComponentEvent evt) {                                    
  this.requestFocusInWindow();
    food[0]=jLabel1;
    food[1]=jLabel2;
    food[2]=jLabel3;
    food[3]=jLabel4;
    food[4]=jLabel5;
    food[5]=jLabel6;
    food[6]=jLabel7;
    food[7]=jLabel8;
    food[8]=jLabel9;
    food[9]=jLabel10;

    Random h = new Random();
    Random v = new Random();

    border[0]=jLabel11;
    border[1]=jLabel13;
    border[2]=jLabel14;
    border[3]=jLabel15;

    System.out.println(jLabel1.getX());
    System.out.println(jLabel1.getY());
    this.setBounds(0, 0, 570, 500);

    food[0].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);
    food[1].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);
    food[2].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);
    food[3].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);
    food[4].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);
    food[5].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);
    food[6].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);
    food[7].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);
    food[8].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);
    food[9].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);

   s_timer = new Timer(50, new SnakeAction());
   s_timer.start();
   X=snake.getX();
   Y=snake.getY();

}                                   

private void jPanel1KeyPressed(java.awt.event.KeyEvent evt) {                                   

}                                  

private void formKeyPressed(java.awt.event.KeyEvent evt) {                                
    System.out.println(evt.getKeyCode());
      switch( evt.getKeyCode()){
    case 37:
    case 39:
    case 32:
    case 38:
    case 40:
    if (keys[evt.getKeyCode()]==false){
         keys[37]=false;
         keys[39]=false;
         keys[32]=false;
         keys[38]=false;
         keys[40]=false;
        keys[evt.getKeyCode()] = true;
    }
    break;
}           
}                               




 class SnakeAction implements ActionListener {
    public void actionPerformed(ActionEvent e) {
    String infoMessage, titleBar;
    if(keys[37]){       //left arrow
    up =false;
    down = false;
    checkCollision();
        if(!borderCollision(snake.getX()-10,snake.getY(),snake.getWidth(),snake.getHeight())){
    X-=10;
    snake.setLocation(X, Y);
    }

    }

    if(keys[39]){       //right arrow
    up = false;
    down = false;
    checkCollision();
    if(!borderCollision(snake.getX()+10,snake.getY(),snake.getWidth(),snake.getHeight())){
    X+=10;
    snake.setLocation(X, Y);
    }
    }

    if(keys[38]){       // up
    up=true;
    checkCollision();
    if(!borderCollision(snake.getX(),snake.getY()-7,snake.getWidth(),snake.getHeight())){
    Y-=10;
    snake.setLocation(X, Y);
    }
    }

    if(keys[40]){       //down
    down=true;
    checkCollision();
    if(!borderCollision(snake.getX(),snake.getY()+7,snake.getWidth(),snake.getHeight())){
    Y+=10;
    snake.setLocation(X, Y);
    }

  }

    }
  }
public void checkCollision(){
boolean collision=false;
Rectangle c1,c2=snake.getBounds();
for(int i=0;i<=9;i++){
c1=food[i].getBounds();
if(c1.intersects(c2))food[i].setVisible(false);
}

}
public boolean borderCollision(int x, int y, int w, int h){
boolean collide = false;
Rectangle r1,r2=snake.getBounds();
r2.x=x;
r2.y=y;
r2.width=w;
r2.height=h;
for(int c=0; c<=3;c++){
r1=border[c].getBounds();
if(r1.intersects(r2)){
collide=true;
}
}
return collide;
}
public static void main(String args[]) {

    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new Visual().setVisible(true);
        }
    });
}

// Variables declaration - do not modify                     
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel10;
private javax.swing.JLabel jLabel11;
private javax.swing.JLabel jLabel12;
private javax.swing.JLabel jLabel13;
private javax.swing.JLabel jLabel14;
private javax.swing.JLabel jLabel15;
private javax.swing.JLabel jLabel18;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel5;
private javax.swing.JLabel jLabel6;
private javax.swing.JLabel jLabel7;
private javax.swing.JLabel jLabel8;
private javax.swing.JLabel jLabel9;
private javax.swing.JPanel jPanel1;
private javax.swing.JLabel snake;
// End of variables declaration                   

}

Explanation of code: I made two arrays for my food and border/boundaries. Each food is randomly generated at different locations. From Jlabel 1 to 10 is my food and Jlabel 11, 13, 14 and 15 is my border/boundaries. I have a timer for my snakes movement. I have used up[key 38], down[key 40], left[key 37] and right[key 39] arrows for movement. The food gets randomly generated at different location. When the snake the collides with a food, I have used setvisible function to hide the food and when the snake collides with the borders/boundaries, it stops moving.

like image 584
Qwerty6501 Avatar asked Sep 20 '26 17:09

Qwerty6501


2 Answers

Well your code is quite... interesting.

As to how to use ArrayList you should try something like this :

JLabel snakeBody = new JLabel();

snakeBody.setBackground(new java.awt.Color(255, 255, 0));
snakeBody.setOpaque(true);
snakeBody.setBounds(510, 400, 10, 10);

ArrayList<JLabel> snake = new ArrayList<>();
snake.add(snakeBody);

And each time the snake eats you add a body element (in the correct location):

snake.add(snakeBody);

To display the snake a foreach loop should do the trick

for(JLabel body : snake){
    jPanel.add(body);
}

To prevent the snake from going back you should just delete the key up and key down Listeners and use a loop to make it go forward (on its own perspective). Otherwise just disable the listener depending on which direction the snake is going on. You can create a method to determine the direction the snake is at.

class SnakeAction implements ActionListener{
    public void actionPerformed(ActionEvent e) {
        if(key[37] && snakeDirection()!="right"){
            //some code
        }
    }
}

To prevent the food from overlaping the snake you should check each time you generate your random number if these numbers are not matching the snake (and its body) location. If it does generate another number.

like image 100
YounesM Avatar answered Sep 23 '26 05:09

YounesM


About to grow the snake, I will suggest that use below code instead of ArrayList, because you don't have to use that.

First, setVisible is not work in this game. You hide it, but it still there. That mean you will keep eating the hided food while you pass it. But you can use setBounds to move it out.

public void checkCollision()
{
    boolean collision=false;
    Rectangle c1,c2=snake.getBounds();
    for(int i=0;i<=9;i++)
    {
        c1=food[i].getBounds();
        if(c1.intersects(c2))
        {   // it cause the problem
            food[i].setVisible(false);
            // add 
            food[i].setBounds(0,0,0,0);
        }
    }
}

And in same way, to grow snake

//A variable to save direction
String direction = "";
//A variable to save how long you will grow
int grow = 5;

Switch(direction)
{
     case N:

     snake.setBounds(X, Y,(int)snake.getSize().getWidth() ,(int)snake.getSize().getHeight()+grow);
     break;

     case E:

     snake.setBounds(X, Y,(int)snake.getSize().getWidth()+grow ,(int)snake.getSize().getHeight());
     break;

     case W:

     snake.setBounds(X, Y,(int)snake.getSize().getWidth()+grow ,(int)snake.getSize().getHeight());
     break;

     case S:

     snake.setBounds(X, Y,(int)snake.getSize().getWidth() ,(int)snake.getSize().getHeight()+grow);
     break;
}

In detail, notice that if you want a better effect, control the growing part and snake's position in the code will be help.

And as @Younes Mgharfaoui said, you can't let snake going back. So make direction in a variable. If you going left side, you cannot go right immediately as a snake.

like image 35
TomN Avatar answered Sep 23 '26 07:09

TomN



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!